@spinnaker/cloudrun 2025.3.0 → 2025.4.0-rc1
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/dist/index.js +1 -2597
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
package/dist/index.js
CHANGED
|
@@ -1,2598 +1,2 @@
|
|
|
1
|
-
import { module } from 'angular';
|
|
2
|
-
import { HelpContentsRegistry, RecentHistoryService, InstanceReader, StageConstants, LoadBalancerWriter, TaskMonitor, ConfirmationModalService, CloudProviderRegistry, Registry, StageArtifactSelector, ArtifactTypePatterns, HelpField, AccountSelectInput, yamlDocumentsToString, StageConfigField, RadioButtonInput, YamlEditor, StageArtifactSelectorDelegate, CheckboxInput, AccountService, FormikStageConfig, ReactInjector, relativeTime, JobManifestPodLogs, JobEventBasedPodNameProvider, CopyToClipboard, ManifestYaml, ManifestReader, ExecutionDetailsSection, StageFailureMessage, ExecutionDetailsTasks, ExecutionArtifactTab, ExpectedArtifactService, ArtifactReferenceService, SETTINGS, NameUtils, ServerGroupNamePreview as ServerGroupNamePreview$1, TextAreaInput, ReactModal, WizardModal, WizardPage, noop, SERVER_GROUP_WRITER, ServerGroupReader, DeploymentStrategyRegistry } from '@spinnaker/core';
|
|
3
|
-
import { flattenDeep, uniq, difference, reduce, filter, chain, cloneDeep, has, camelCase, get, map, capitalize, isEmpty, trim } from 'lodash';
|
|
4
|
-
import React, { useState } from 'react';
|
|
5
|
-
import { Subject, from } from 'rxjs';
|
|
6
|
-
import { takeUntil } from 'rxjs/operators';
|
|
7
|
-
import { dump } from 'js-yaml';
|
|
8
|
-
import { DateTime } from 'luxon';
|
|
9
|
-
import { $q } from 'ngimport';
|
|
10
|
-
|
|
11
|
-
const cloudrunComponentUrlDetailsComponent = {
|
|
12
|
-
bindings: { component: "<" },
|
|
13
|
-
template: `
|
|
14
|
-
<dt>HTTPS</dt>
|
|
15
|
-
<dl class="small">
|
|
16
|
-
<a href="{{$ctrl.component.url}}" target="_blank">{{$ctrl.component.url}}</a>
|
|
17
|
-
<copy-to-clipboard class="copy-to-clipboard copy-to-clipboard-sm"
|
|
18
|
-
tool-tip="'Copy URL to clipboard'"
|
|
19
|
-
text="$ctrl.component.httpsUrl"></copy-to-clipboard>
|
|
20
|
-
</dl>
|
|
21
|
-
`
|
|
22
|
-
};
|
|
23
|
-
const CLOUDRUN_COMPONENT_URL_DETAILS = "spinnaker.cloudrun.componentUrlDetails.component";
|
|
24
|
-
module(CLOUDRUN_COMPONENT_URL_DETAILS, []).component("cloudrunComponentUrlDetails", cloudrunComponentUrlDetailsComponent);
|
|
25
|
-
|
|
26
|
-
const cloudRunLoadBalancerMessageComponent = {
|
|
27
|
-
bindings: { showCreateMessage: "<", columnOffset: "@", columns: "@" },
|
|
28
|
-
templateUrl: "cloudrun/src/common/loadBalancerMessage.component.html"
|
|
29
|
-
};
|
|
30
|
-
const CLOUDRUN_LOAD_BALANCER_CREATE_MESSAGE = "spinnaker.cloudrun.loadBalancer.createMessage.component";
|
|
31
|
-
module(CLOUDRUN_LOAD_BALANCER_CREATE_MESSAGE, []).component("cloudrunLoadBalancerMessage", cloudRunLoadBalancerMessageComponent);
|
|
32
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
33
|
-
templateCache.put("cloudrun/src/common/loadBalancerMessage.component.html", `<div class="row">
|
|
34
|
-
<div class="col-md-offset-{{ $ctrl.columnOffset || 0 }} col-md-{{ $ctrl.columns || 12 }}">
|
|
35
|
-
<div class="well">
|
|
36
|
-
<p>
|
|
37
|
-
<span ng-if="$ctrl.showCreateMessage">Spinnaker cannot create a load balancer for Cloud Run.</span>
|
|
38
|
-
A Spinnaker load balancer maps to an Cloud Run Service, which will be created automatically alongside a
|
|
39
|
-
Revision. Once created, the Service can be edited as a Load Balancer.
|
|
40
|
-
</p>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
44
|
-
`);
|
|
45
|
-
}]);
|
|
46
|
-
|
|
47
|
-
const helpContents = [
|
|
48
|
-
{
|
|
49
|
-
key: "cloudrun.serverGroup.stack",
|
|
50
|
-
value: "(Optional) <b>Stack</b> is one of the core naming components of a cluster, used to create vertical stacks of dependent services for integration testing."
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
key: "cloudrun.serverGroup.file",
|
|
54
|
-
value: `<pre>
|
|
55
|
-
apiVersion: serving.knative.dev/v1
|
|
56
|
-
kind: Service
|
|
57
|
-
metadata:
|
|
58
|
-
name: spinappcloud1
|
|
59
|
-
namespace: '135005621049'
|
|
60
|
-
labels:
|
|
61
|
-
cloud.googleapis.com/location: us-central1
|
|
62
|
-
annotations:
|
|
63
|
-
run.googleapis.com/client-name: cloud-console
|
|
64
|
-
serving.knative.dev/creator: kiran@opsmx.io
|
|
65
|
-
serving.knative.dev/lastModifier: kiran@opsmx.io
|
|
66
|
-
client.knative.dev/user-image: us-docker.pkg.dev/cloudrun/container/hello
|
|
67
|
-
run.googleapis.com/ingress-status: all
|
|
68
|
-
spec:
|
|
69
|
-
template:
|
|
70
|
-
metagoogleapis.com/ingress: all
|
|
71
|
-
run.data:
|
|
72
|
-
name: spinappcloud1
|
|
73
|
-
annotations:
|
|
74
|
-
run.googleapis.com/client-name: cloud-console
|
|
75
|
-
autoscaling.knative.dev/minScale: '1'
|
|
76
|
-
autoscaling.knative.dev/maxScale: '3'
|
|
77
|
-
spec:
|
|
78
|
-
containerConcurrency: 80
|
|
79
|
-
timeoutSeconds: 200
|
|
80
|
-
serviceAccountName:spinnaker-cloudrun-account@my-orbit-project-71824.iam.gserviceaccount.com
|
|
81
|
-
containers:
|
|
82
|
-
- image:us-docker.pkg.dev/cloudrun/container/hello
|
|
83
|
-
ports:
|
|
84
|
-
- name: http1
|
|
85
|
-
containerPort: 8080
|
|
86
|
-
resources:
|
|
87
|
-
limits:
|
|
88
|
-
cpu: 1000m
|
|
89
|
-
memory: 256Mi
|
|
90
|
-
</pre>
|
|
91
|
-
`
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
key: "cloudrun.serverGroup.detail",
|
|
95
|
-
value: " (Optional) <b>Detail</b> is a string of free-form alphanumeric characters and hyphens to describe any other variables."
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
key: "cloudrun.serverGroup.configFiles",
|
|
99
|
-
value: `<p> The contents of a Cloud Run Service yaml </p>`
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
key: "cloudrun.loadBalancer.allocations",
|
|
103
|
-
value: "An allocation is the percent of traffic directed to a server group."
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
key: "cloudrun.manifest.source",
|
|
107
|
-
value: `
|
|
108
|
-
<p>Where the manifest file content is read from.</p>
|
|
109
|
-
<p>
|
|
110
|
-
<b>text:</b> The manifest is supplied statically to the pipeline from the below text-box.
|
|
111
|
-
</p>
|
|
112
|
-
<p>
|
|
113
|
-
<b>artifact:</b> The manifest is read from an artifact supplied/created upstream. The expected artifact must be referenced here, and will be bound at runtime.
|
|
114
|
-
</p>`
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
key: "cloudrun.manifest.expectedArtifact",
|
|
118
|
-
value: "The artifact that is to be applied to the Cloud Run account for this stage. The artifact should represent a valid Cloud Run manifest."
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
key: "cloudrun.manifest.skipExpressionEvaluation",
|
|
122
|
-
value: '<p>Skip SpEL expression evaluation of the manifest artifact in this stage. Can be paired with the "Evaluate SpEL expressions in overrides at bake time" option in the Bake Manifest stage when baking a third-party manifest artifact with expressions not meant for Spinnaker to evaluate as SpEL.</p>'
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
key: "cloudrun.manifest.requiredArtifactsToBind",
|
|
126
|
-
value: 'These artifacts must be present in the context for this stage to successfully complete. Artifacts specified will be <a href="https://www.spinnaker.io/reference/artifacts/in-cloudrun-v2/#binding-artifacts-in-manifests" target="_blank">bound to the deployed manifest.</a>'
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
key: "cloudrun.manifest.account",
|
|
130
|
-
value: `
|
|
131
|
-
<p>A Spinnaker account corresponds to a physical Cloud Run cluster. If you are unsure which account to use, talk to your Spinnaker admin.</p>
|
|
132
|
-
`
|
|
133
|
-
}
|
|
134
|
-
];
|
|
135
|
-
helpContents.forEach((entry) => HelpContentsRegistry.register(entry.key, entry.value));
|
|
136
|
-
|
|
137
|
-
class CloudrunInstanceDetailsController {
|
|
138
|
-
constructor($q, app, instance) {
|
|
139
|
-
this.$q = $q;
|
|
140
|
-
this.app = app;
|
|
141
|
-
this.state = { loading: true };
|
|
142
|
-
this.upToolTip = "A Cloud Run instance is 'Up' if a load balancer is directing traffic to its server group.";
|
|
143
|
-
this.outOfServiceToolTip = `
|
|
144
|
-
A Cloud Run instance is 'Out Of Service' if no load balancers are directing traffic to its server group.`;
|
|
145
|
-
this.app.ready().then(() => this.retrieveInstance(instance)).then((instanceDetails) => {
|
|
146
|
-
this.instance = instanceDetails;
|
|
147
|
-
this.state.loading = false;
|
|
148
|
-
}).catch(() => {
|
|
149
|
-
this.instanceIdNotFound = instance.instanceId;
|
|
150
|
-
this.state.loading = false;
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
retrieveInstance(instance) {
|
|
154
|
-
const instanceLocatorPredicate = (dataSource) => {
|
|
155
|
-
return dataSource.instances.some((possibleMatch) => possibleMatch.id === instance.instanceId);
|
|
156
|
-
};
|
|
157
|
-
const dataSources = flattenDeep([
|
|
158
|
-
this.app.getDataSource("serverGroups").data,
|
|
159
|
-
this.app.getDataSource("loadBalancers").data,
|
|
160
|
-
this.app.getDataSource("loadBalancers").data.map((loadBalancer) => loadBalancer.serverGroups)
|
|
161
|
-
]);
|
|
162
|
-
const instanceManager = dataSources.find(instanceLocatorPredicate);
|
|
163
|
-
if (instanceManager) {
|
|
164
|
-
const recentHistoryExtraData = {
|
|
165
|
-
region: instanceManager.region,
|
|
166
|
-
account: instanceManager.account
|
|
167
|
-
};
|
|
168
|
-
if (instanceManager.category === "serverGroup") {
|
|
169
|
-
recentHistoryExtraData.serverGroup = instanceManager.name;
|
|
170
|
-
}
|
|
171
|
-
RecentHistoryService.addExtraDataToLatest("instances", recentHistoryExtraData);
|
|
172
|
-
return InstanceReader.getInstanceDetails(instanceManager.account, instanceManager.region, instance.instanceId).then((instanceDetails) => {
|
|
173
|
-
instanceDetails.account = instanceManager.account;
|
|
174
|
-
instanceDetails.region = instanceManager.region;
|
|
175
|
-
return instanceDetails;
|
|
176
|
-
});
|
|
177
|
-
} else {
|
|
178
|
-
return this.$q.reject();
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
CloudrunInstanceDetailsController.$inject = ["$q", "app", "instance"];
|
|
183
|
-
const CLOUDRUN_INSTANCE_DETAILS_CTRL = "spinnaker.cloudrun.instanceDetails.controller";
|
|
184
|
-
module(CLOUDRUN_INSTANCE_DETAILS_CTRL, []).controller("cloudrunInstanceDetailsCtrl", CloudrunInstanceDetailsController);
|
|
185
|
-
|
|
186
|
-
class CloudrunAllocationConfigurationRowCtrl {
|
|
187
|
-
getServerGroupOptions() {
|
|
188
|
-
if (this.allocationDescription.revisionName) {
|
|
189
|
-
return uniq(this.serverGroupOptions.concat(this.allocationDescription.revisionName));
|
|
190
|
-
} else {
|
|
191
|
-
return this.serverGroupOptions;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
const cloudrunAllocationConfigurationRowComponent = {
|
|
196
|
-
bindings: {
|
|
197
|
-
allocationDescription: "<",
|
|
198
|
-
removeAllocation: "&",
|
|
199
|
-
serverGroupOptions: "<",
|
|
200
|
-
onAllocationChange: "&"
|
|
201
|
-
},
|
|
202
|
-
template: `
|
|
203
|
-
<div class="form-group">
|
|
204
|
-
<div class="row">
|
|
205
|
-
<div class="col-md-7">
|
|
206
|
-
<ui-select ng-model="$ctrl.allocationDescription.revisionName"
|
|
207
|
-
on-select="$ctrl.onAllocationChange()"
|
|
208
|
-
class="form-control input-sm">
|
|
209
|
-
<ui-select-match placeholder="Select...">
|
|
210
|
-
{{$select.selected}}
|
|
211
|
-
</ui-select-match>
|
|
212
|
-
<ui-select-choices repeat="serverGroup as serverGroup in $ctrl.getServerGroupOptions() | filter: $select.search">
|
|
213
|
-
<div ng-bind-html="serverGroup | highlight: $select.search"></div>
|
|
214
|
-
</ui-select-choices>
|
|
215
|
-
</ui-select>
|
|
216
|
-
</div>
|
|
217
|
-
<div class="col-md-3">
|
|
218
|
-
<div class="input-group input-group-sm">
|
|
219
|
-
<input type="number"
|
|
220
|
-
ng-model="$ctrl.allocationDescription.percent"
|
|
221
|
-
required
|
|
222
|
-
class="form-control input-sm"
|
|
223
|
-
min="0"
|
|
224
|
-
ng-change="$ctrl.onAllocationChange()"
|
|
225
|
-
max="100"/>
|
|
226
|
-
<span class="input-group-addon">%</span>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
<div class="col-md-2">
|
|
230
|
-
<a class="btn btn-link sm-label" ng-click="$ctrl.removeAllocation()">
|
|
231
|
-
<span class="glyphicon glyphicon-trash"></span>
|
|
232
|
-
</a>
|
|
233
|
-
</div>
|
|
234
|
-
</div>
|
|
235
|
-
</div>
|
|
236
|
-
`,
|
|
237
|
-
controller: CloudrunAllocationConfigurationRowCtrl
|
|
238
|
-
};
|
|
239
|
-
const CLOUDRUN_ALLOCATION_CONFIGURATION_ROW = "spinnaker.cloudrun.allocationConfigurationRow.component";
|
|
240
|
-
module(CLOUDRUN_ALLOCATION_CONFIGURATION_ROW, []).component("cloudrunAllocationConfigurationRow", cloudrunAllocationConfigurationRowComponent);
|
|
241
|
-
|
|
242
|
-
class CloudrunLoadBalancerSettingsController {
|
|
243
|
-
$onInit() {
|
|
244
|
-
this.updateServerGroupOptions();
|
|
245
|
-
}
|
|
246
|
-
addAllocation() {
|
|
247
|
-
const remainingServerGroups = this.serverGroupsWithoutAllocation();
|
|
248
|
-
if (remainingServerGroups.length) {
|
|
249
|
-
this.loadBalancer.splitDescription.allocationDescriptions.push({
|
|
250
|
-
revisionName: remainingServerGroups[0],
|
|
251
|
-
percent: 0
|
|
252
|
-
});
|
|
253
|
-
this.updateServerGroupOptions();
|
|
254
|
-
} else if (this.forPipelineConfig) {
|
|
255
|
-
this.loadBalancer.splitDescription.allocationDescriptions.push({
|
|
256
|
-
percent: 0,
|
|
257
|
-
revisionName: ""
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
removeAllocation(index) {
|
|
262
|
-
this.loadBalancer.splitDescription.allocationDescriptions.splice(index, 1);
|
|
263
|
-
this.updateServerGroupOptions();
|
|
264
|
-
}
|
|
265
|
-
allocationIsInvalid() {
|
|
266
|
-
return this.loadBalancer.splitDescription.allocationDescriptions.reduce((sum, allocationDescription) => sum + allocationDescription.percent, 0) !== 100;
|
|
267
|
-
}
|
|
268
|
-
updateServerGroupOptions() {
|
|
269
|
-
this.serverGroupOptions = this.serverGroupsWithoutAllocation();
|
|
270
|
-
}
|
|
271
|
-
showAddButton() {
|
|
272
|
-
if (this.forPipelineConfig) {
|
|
273
|
-
return true;
|
|
274
|
-
} else {
|
|
275
|
-
return this.serverGroupsWithoutAllocation().length > 0;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
initializeAsTextInput(serverGroupName) {
|
|
279
|
-
if (this.forPipelineConfig) {
|
|
280
|
-
return !this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name).includes(serverGroupName);
|
|
281
|
-
} else {
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
serverGroupsWithoutAllocation() {
|
|
286
|
-
const serverGroupsWithAllocation = this.loadBalancer.splitDescription.allocationDescriptions.map((description) => description.revisionName);
|
|
287
|
-
const allServerGroups = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);
|
|
288
|
-
return difference(allServerGroups, serverGroupsWithAllocation);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
const cloudrunLoadBalancerSettingsComponent = {
|
|
292
|
-
bindings: { loadBalancer: "=", forPipelineConfig: "<", application: "<" },
|
|
293
|
-
controller: CloudrunLoadBalancerSettingsController,
|
|
294
|
-
templateUrl: "cloudrun/src/loadBalancer/configure/wizard/basicSettings.component.html"
|
|
295
|
-
};
|
|
296
|
-
const CLOUDRUN_LOAD_BALANCER_BASIC_SETTINGS = "spinnaker.cloudrun.loadBalancerSettings.component";
|
|
297
|
-
module(CLOUDRUN_LOAD_BALANCER_BASIC_SETTINGS, []).component("cloudrunLoadBalancerBasicSettings", cloudrunLoadBalancerSettingsComponent);
|
|
298
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
299
|
-
templateCache.put("cloudrun/src/loadBalancer/configure/wizard/basicSettings.component.html", `<ng-form name="basicSettingsForm">
|
|
300
|
-
<div class="row">
|
|
301
|
-
<div class="form-group">
|
|
302
|
-
<div class="col-md-3 sm-label-right">
|
|
303
|
-
Allocations
|
|
304
|
-
<help-field key="cloudrun.loadBalancer.allocations"></help-field>
|
|
305
|
-
</div>
|
|
306
|
-
<div class="col-md-9">
|
|
307
|
-
<div ng-if="!$ctrl.forPipelineConfig">
|
|
308
|
-
<cloudrun-allocation-configuration-row
|
|
309
|
-
ng-repeat="description in $ctrl.loadBalancer.splitDescription.allocationDescriptions"
|
|
310
|
-
allocation-description="description"
|
|
311
|
-
server-group-options="$ctrl.serverGroupOptions"
|
|
312
|
-
on-allocation-change="$ctrl.updateServerGroupOptions()"
|
|
313
|
-
remove-allocation="$ctrl.removeAllocation($index)"
|
|
314
|
-
>
|
|
315
|
-
</cloudrun-allocation-configuration-row>
|
|
316
|
-
</div>
|
|
317
|
-
<div ng-if="$ctrl.forPipelineConfig">
|
|
318
|
-
<cloudrun-stage-allocation-configuration-row
|
|
319
|
-
ng-repeat="description in $ctrl.loadBalancer.splitDescription.allocationDescriptions"
|
|
320
|
-
allocation-description="description"
|
|
321
|
-
application="$ctrl.application"
|
|
322
|
-
region="{{ $ctrl.loadBalancer.region }}"
|
|
323
|
-
account="{{ $ctrl.loadBalancer.account || $ctrl.loadBalancer.credentials }}"
|
|
324
|
-
name="{{ $ctrl.loadBalancer.name }}"
|
|
325
|
-
server-group-options="$ctrl.serverGroupOptions"
|
|
326
|
-
on-allocation-change="$ctrl.updateServerGroupOptions()"
|
|
327
|
-
remove-allocation="$ctrl.removeAllocation($index)"
|
|
328
|
-
>
|
|
329
|
-
</cloudrun-stage-allocation-configuration-row>
|
|
330
|
-
</div>
|
|
331
|
-
<button class="add-new col-md-11" ng-if="$ctrl.showAddButton()" ng-click="$ctrl.addAllocation()">
|
|
332
|
-
<span class="glyphicon glyphicon-plus-sign"></span> Add allocation
|
|
333
|
-
</button>
|
|
334
|
-
</div>
|
|
335
|
-
</div>
|
|
336
|
-
<div class="form-group" ng-if="$ctrl.allocationIsInvalid()">
|
|
337
|
-
<div class="col-md-12 text-center">
|
|
338
|
-
<p class="alert alert-warning">Allocations must sum to 100%.</p>
|
|
339
|
-
</div>
|
|
340
|
-
</div>
|
|
341
|
-
</div>
|
|
342
|
-
</ng-form>
|
|
343
|
-
`);
|
|
344
|
-
}]);
|
|
345
|
-
|
|
346
|
-
class CloudrunStageAllocationLabelCtrl {
|
|
347
|
-
static mapTargetCoordinateToLabel(targetCoordinate) {
|
|
348
|
-
const target = StageConstants.TARGET_LIST.find((t) => t.val === targetCoordinate);
|
|
349
|
-
if (target) {
|
|
350
|
-
return target.label;
|
|
351
|
-
} else {
|
|
352
|
-
return null;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
$doCheck() {
|
|
356
|
-
this.setInputViewValue();
|
|
357
|
-
}
|
|
358
|
-
setInputViewValue() {
|
|
359
|
-
if (this.allocationDescription.cluster && this.allocationDescription.target) {
|
|
360
|
-
const targetLabel = CloudrunStageAllocationLabelCtrl.mapTargetCoordinateToLabel(this.allocationDescription.target);
|
|
361
|
-
this.inputViewValue = `${targetLabel} (${this.allocationDescription.cluster})`;
|
|
362
|
-
} else {
|
|
363
|
-
this.inputViewValue = null;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
const cloudrunStageAllocationLabel = {
|
|
368
|
-
bindings: { allocationDescription: "<" },
|
|
369
|
-
controller: CloudrunStageAllocationLabelCtrl,
|
|
370
|
-
template: `<input ng-model="$ctrl.inputViewValue" type="text" class="form-control input-sm" readonly/>`
|
|
371
|
-
};
|
|
372
|
-
class CloudrunStageAllocationConfigurationRowCtrl {
|
|
373
|
-
constructor() {
|
|
374
|
-
this.targets = StageConstants.TARGET_LIST;
|
|
375
|
-
}
|
|
376
|
-
$onInit() {
|
|
377
|
-
this.allocationDescription.cluster = this.name;
|
|
378
|
-
}
|
|
379
|
-
getServerGroupOptions() {
|
|
380
|
-
if (this.allocationDescription.revisionName) {
|
|
381
|
-
return uniq(this.serverGroupOptions.concat(this.allocationDescription.revisionName));
|
|
382
|
-
} else {
|
|
383
|
-
return this.serverGroupOptions;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
const cloudrunStageAllocationConfigurationRow = {
|
|
388
|
-
bindings: {
|
|
389
|
-
application: "<",
|
|
390
|
-
region: "@",
|
|
391
|
-
account: "@",
|
|
392
|
-
name: "@",
|
|
393
|
-
allocationDescription: "<",
|
|
394
|
-
removeAllocation: "&",
|
|
395
|
-
serverGroupOptions: "<",
|
|
396
|
-
onAllocationChange: "&"
|
|
397
|
-
},
|
|
398
|
-
controller: CloudrunStageAllocationConfigurationRowCtrl,
|
|
399
|
-
templateUrl: "cloudrun/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html"
|
|
400
|
-
};
|
|
401
|
-
const CLOUDRUN_STAGE_ALLOCATION_CONFIGURATION_ROW = "spinnaker.cloudrun.stageAllocationConfigurationRow.component";
|
|
402
|
-
module(CLOUDRUN_STAGE_ALLOCATION_CONFIGURATION_ROW, []).component("cloudrunStageAllocationConfigurationRow", cloudrunStageAllocationConfigurationRow).component("cloudrunStageAllocationLabel", cloudrunStageAllocationLabel);
|
|
403
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
404
|
-
templateCache.put("cloudrun/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html", `<div class="form-group">
|
|
405
|
-
<div class="row">
|
|
406
|
-
<div class="col-md-7">
|
|
407
|
-
<cloudrun-stage-allocation-label allocation-description="$ctrl.allocationDescription">
|
|
408
|
-
</cloudrun-stage-allocation-label>
|
|
409
|
-
</div>
|
|
410
|
-
<div class="col-md-3">
|
|
411
|
-
<div class="input-group input-group-sm">
|
|
412
|
-
<input
|
|
413
|
-
type="number"
|
|
414
|
-
ng-model="$ctrl.allocationDescription.percent"
|
|
415
|
-
required
|
|
416
|
-
class="form-control input-sm"
|
|
417
|
-
min="0"
|
|
418
|
-
ng-change="$ctrl.onAllocationChange()"
|
|
419
|
-
max="100"
|
|
420
|
-
/>
|
|
421
|
-
<span class="input-group-addon">%</span>
|
|
422
|
-
</div>
|
|
423
|
-
</div>
|
|
424
|
-
<div class="col-md-2">
|
|
425
|
-
<a class="btn btn-link sm-label" ng-click="$ctrl.removeAllocation()">
|
|
426
|
-
<span class="glyphicon glyphicon-trash"></span>
|
|
427
|
-
</a>
|
|
428
|
-
</div>
|
|
429
|
-
</div>
|
|
430
|
-
</div>
|
|
431
|
-
<div class="form-group">
|
|
432
|
-
<div class="well col-md-11" style="padding-top: 5px; padding-bottom: 10px">
|
|
433
|
-
<div class="row">
|
|
434
|
-
<div class="form-group">
|
|
435
|
-
<div>
|
|
436
|
-
<div class="col-md-3 sm-label-right">Cluster</div>
|
|
437
|
-
<div class="col-md-7" style="margin-bottom: 10px">
|
|
438
|
-
<input ng-model="$ctrl.allocationDescription.cluster" type="text" class="form-control input-sm" readonly />
|
|
439
|
-
</div>
|
|
440
|
-
<div class="col-md-3 sm-label-right">Target</div>
|
|
441
|
-
<div class="col-md-7">
|
|
442
|
-
<target-select model="$ctrl.allocationDescription" options="$ctrl.targets"></target-select>
|
|
443
|
-
</div>
|
|
444
|
-
</div>
|
|
445
|
-
</div>
|
|
446
|
-
</div>
|
|
447
|
-
</div>
|
|
448
|
-
</div>
|
|
449
|
-
`);
|
|
450
|
-
}]);
|
|
451
|
-
|
|
452
|
-
class CloudrunLoadBalancerUpsertDescription {
|
|
453
|
-
static convertTrafficSplitToTrafficSplitDescription(split) {
|
|
454
|
-
const allocationDescriptions = reduce(split.trafficTargets, (acc, trafficTarget) => {
|
|
455
|
-
const { revisionName, percent } = trafficTarget;
|
|
456
|
-
return acc.concat({ percent, revisionName });
|
|
457
|
-
}, []);
|
|
458
|
-
return { allocationDescriptions };
|
|
459
|
-
}
|
|
460
|
-
constructor(loadBalancer) {
|
|
461
|
-
this.credentials = loadBalancer.account || loadBalancer.credentials;
|
|
462
|
-
this.account = this.credentials;
|
|
463
|
-
this.cloudProvider = loadBalancer.cloudProvider;
|
|
464
|
-
this.loadBalancerName = loadBalancer.name;
|
|
465
|
-
this.name = loadBalancer.name;
|
|
466
|
-
this.region = loadBalancer.region;
|
|
467
|
-
this.migrateTraffic = loadBalancer.migrateTraffic || false;
|
|
468
|
-
this.serverGroups = loadBalancer.serverGroups;
|
|
469
|
-
}
|
|
470
|
-
mapAllocationsToDecimals() {
|
|
471
|
-
this.splitDescription.allocationDescriptions.forEach((description) => {
|
|
472
|
-
description.percent = description.percent / 100;
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
mapAllocationsToPercentages() {
|
|
476
|
-
this.splitDescription.allocationDescriptions.forEach((description) => {
|
|
477
|
-
description.percent = Math.round(description.percent);
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
class CloudrunLoadBalancerTransformer {
|
|
482
|
-
constructor($q) {
|
|
483
|
-
this.$q = $q;
|
|
484
|
-
}
|
|
485
|
-
normalizeLoadBalancer(loadBalancer) {
|
|
486
|
-
loadBalancer.provider = loadBalancer.type;
|
|
487
|
-
loadBalancer.instanceCounts = this.buildInstanceCounts(loadBalancer.serverGroups);
|
|
488
|
-
loadBalancer.instances = [];
|
|
489
|
-
loadBalancer.serverGroups.forEach((serverGroup) => {
|
|
490
|
-
serverGroup.account = loadBalancer.account;
|
|
491
|
-
serverGroup.region = loadBalancer.region;
|
|
492
|
-
if (serverGroup.detachedInstances) {
|
|
493
|
-
serverGroup.detachedInstances = serverGroup.detachedInstances.map((id) => ({ id }));
|
|
494
|
-
}
|
|
495
|
-
serverGroup.instances = serverGroup.instances.concat(serverGroup.detachedInstances || []).map((instance) => this.transformInstance(instance, loadBalancer));
|
|
496
|
-
});
|
|
497
|
-
const activeServerGroups = filter(loadBalancer.serverGroups, { isDisabled: false });
|
|
498
|
-
loadBalancer.instances = chain(activeServerGroups).map("instances").flatten().value();
|
|
499
|
-
return this.$q.resolve(loadBalancer);
|
|
500
|
-
}
|
|
501
|
-
convertLoadBalancerForEditing(loadBalancer, application) {
|
|
502
|
-
return application.getDataSource("loadBalancers").ready().then(() => {
|
|
503
|
-
const upToDateLoadBalancer = application.getDataSource("loadBalancers").data.find((candidate) => {
|
|
504
|
-
return candidate.name === loadBalancer.name && (candidate.account === loadBalancer.account || candidate.account === loadBalancer.credentials);
|
|
505
|
-
});
|
|
506
|
-
if (upToDateLoadBalancer) {
|
|
507
|
-
loadBalancer.serverGroups = cloneDeep(upToDateLoadBalancer.serverGroups);
|
|
508
|
-
}
|
|
509
|
-
return loadBalancer;
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
convertLoadBalancerToUpsertDescription(loadBalancer) {
|
|
513
|
-
return new CloudrunLoadBalancerUpsertDescription(loadBalancer);
|
|
514
|
-
}
|
|
515
|
-
buildInstanceCounts(serverGroups) {
|
|
516
|
-
const instanceCounts = chain(serverGroups).map("instances").flatten().reduce((acc, instance) => {
|
|
517
|
-
if (has(instance, "health.state")) {
|
|
518
|
-
acc[camelCase(instance.health.state)]++;
|
|
519
|
-
}
|
|
520
|
-
return acc;
|
|
521
|
-
}, { up: 0, down: 0, outOfService: 0, succeeded: 0, failed: 0, starting: 0, unknown: 0 }).value();
|
|
522
|
-
instanceCounts.outOfService += chain(serverGroups).map("detachedInstances").flatten().value().length;
|
|
523
|
-
return instanceCounts;
|
|
524
|
-
}
|
|
525
|
-
transformInstance(instance, loadBalancer) {
|
|
526
|
-
instance.provider = loadBalancer.type;
|
|
527
|
-
instance.account = loadBalancer.account;
|
|
528
|
-
instance.region = loadBalancer.region;
|
|
529
|
-
instance.loadBalancers = [loadBalancer.name];
|
|
530
|
-
const health = instance.health || {};
|
|
531
|
-
instance.healthState = get(instance, "health.state") || "OutOfService";
|
|
532
|
-
instance.health = [health];
|
|
533
|
-
return instance;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
CloudrunLoadBalancerTransformer.$inject = ["$q"];
|
|
537
|
-
const CLOUDRUN_LOAD_BALANCER_TRANSFORMER = "spinnaker.cloudrun.loadBalancer.transformer.service";
|
|
538
|
-
module(CLOUDRUN_LOAD_BALANCER_TRANSFORMER, []).service("cloudrunLoadBalancerTransformer", CloudrunLoadBalancerTransformer);
|
|
539
|
-
|
|
540
|
-
function styleInject(css, ref) {
|
|
541
|
-
if ( ref === void 0 ) ref = {};
|
|
542
|
-
var insertAt = ref.insertAt;
|
|
543
|
-
|
|
544
|
-
if (!css || typeof document === 'undefined') { return; }
|
|
545
|
-
|
|
546
|
-
var head = document.head || document.getElementsByTagName('head')[0];
|
|
547
|
-
var style = document.createElement('style');
|
|
548
|
-
style.type = 'text/css';
|
|
549
|
-
|
|
550
|
-
if (insertAt === 'top') {
|
|
551
|
-
if (head.firstChild) {
|
|
552
|
-
head.insertBefore(style, head.firstChild);
|
|
553
|
-
} else {
|
|
554
|
-
head.appendChild(style);
|
|
555
|
-
}
|
|
556
|
-
} else {
|
|
557
|
-
head.appendChild(style);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
if (style.styleSheet) {
|
|
561
|
-
style.styleSheet.cssText = css;
|
|
562
|
-
} else {
|
|
563
|
-
style.appendChild(document.createTextNode(css));
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
var css_248z$2 = "cloudrun-load-balancer-basic-settings a.btn.btn-link {\n padding: 0;\n}\ncloudrun-load-balancer-basic-settings .form-group {\n margin-top: 0.4rem;\n}\n";
|
|
568
|
-
styleInject(css_248z$2);
|
|
569
|
-
|
|
570
|
-
class CloudrunLoadBalancerWizardController {
|
|
571
|
-
constructor($scope, $state, $uibModalInstance, application, loadBalancer, isNew, forPipelineConfig, cloudrunLoadBalancerTransformer, wizardSubFormValidation) {
|
|
572
|
-
this.$scope = $scope;
|
|
573
|
-
this.$state = $state;
|
|
574
|
-
this.$uibModalInstance = $uibModalInstance;
|
|
575
|
-
this.application = application;
|
|
576
|
-
this.isNew = isNew;
|
|
577
|
-
this.forPipelineConfig = forPipelineConfig;
|
|
578
|
-
this.cloudrunLoadBalancerTransformer = cloudrunLoadBalancerTransformer;
|
|
579
|
-
this.wizardSubFormValidation = wizardSubFormValidation;
|
|
580
|
-
this.state = { loading: true };
|
|
581
|
-
this.submitButtonLabel = this.forPipelineConfig ? "Done" : "Update";
|
|
582
|
-
if (this.isNew) {
|
|
583
|
-
this.heading = "Create New Load Balancer";
|
|
584
|
-
} else {
|
|
585
|
-
this.heading = `Edit ${[
|
|
586
|
-
loadBalancer.name,
|
|
587
|
-
loadBalancer.region,
|
|
588
|
-
loadBalancer.account || loadBalancer.credentials
|
|
589
|
-
].join(":")}`;
|
|
590
|
-
this.cloudrunLoadBalancerTransformer.convertLoadBalancerForEditing(loadBalancer, application).then((convertedLoadBalancer) => {
|
|
591
|
-
this.loadBalancer = this.cloudrunLoadBalancerTransformer.convertLoadBalancerToUpsertDescription(convertedLoadBalancer);
|
|
592
|
-
if (loadBalancer.split && !this.loadBalancer.splitDescription) {
|
|
593
|
-
this.loadBalancer.splitDescription = CloudrunLoadBalancerUpsertDescription.convertTrafficSplitToTrafficSplitDescription(loadBalancer.split);
|
|
594
|
-
} else {
|
|
595
|
-
this.loadBalancer.splitDescription = loadBalancer.splitDescription;
|
|
596
|
-
}
|
|
597
|
-
this.loadBalancer.mapAllocationsToPercentages();
|
|
598
|
-
this.setTaskMonitor();
|
|
599
|
-
this.initializeFormValidation();
|
|
600
|
-
this.state.loading = false;
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
submit() {
|
|
605
|
-
const description = cloneDeep(this.loadBalancer);
|
|
606
|
-
description.mapAllocationsToPercentages();
|
|
607
|
-
delete description.serverGroups;
|
|
608
|
-
if (this.forPipelineConfig) {
|
|
609
|
-
return this.$uibModalInstance.close(description);
|
|
610
|
-
} else {
|
|
611
|
-
return this.taskMonitor.submit(() => {
|
|
612
|
-
return LoadBalancerWriter.upsertLoadBalancer(description, this.application, "Update");
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
cancel() {
|
|
617
|
-
this.$uibModalInstance.dismiss();
|
|
618
|
-
}
|
|
619
|
-
showSubmitButton() {
|
|
620
|
-
return this.wizardSubFormValidation.subFormsAreValid();
|
|
621
|
-
}
|
|
622
|
-
setTaskMonitor() {
|
|
623
|
-
this.taskMonitor = new TaskMonitor({
|
|
624
|
-
application: this.application,
|
|
625
|
-
title: "Updating your load balancer",
|
|
626
|
-
modalInstance: this.$uibModalInstance,
|
|
627
|
-
onTaskComplete: () => this.onTaskComplete()
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
initializeFormValidation() {
|
|
631
|
-
this.wizardSubFormValidation.config({ form: "form", scope: this.$scope }).register({
|
|
632
|
-
page: "basic-settings",
|
|
633
|
-
subForm: "basicSettingsForm",
|
|
634
|
-
validators: [
|
|
635
|
-
{
|
|
636
|
-
watchString: "ctrl.loadBalancer.splitDescription",
|
|
637
|
-
validator: (splitDescription) => {
|
|
638
|
-
return splitDescription.allocationDescriptions.reduce((sum, description) => sum + description.percent, 0) === 100;
|
|
639
|
-
},
|
|
640
|
-
watchDeep: true
|
|
641
|
-
}
|
|
642
|
-
]
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
onTaskComplete() {
|
|
646
|
-
this.application.getDataSource("loadBalancers").refresh();
|
|
647
|
-
this.application.getDataSource("loadBalancers").onNextRefresh(this.$scope, () => this.onApplicationRefresh());
|
|
648
|
-
}
|
|
649
|
-
onApplicationRefresh() {
|
|
650
|
-
if (this.$scope.$$destroyed) {
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
this.$uibModalInstance.dismiss();
|
|
654
|
-
const newStateParams = {
|
|
655
|
-
name: this.loadBalancer.name,
|
|
656
|
-
accountId: this.loadBalancer.credentials,
|
|
657
|
-
region: this.loadBalancer.region,
|
|
658
|
-
provider: "cloudrun"
|
|
659
|
-
};
|
|
660
|
-
if (!this.$state.includes("**.loadBalancerDetails")) {
|
|
661
|
-
this.$state.go(".loadBalancerDetails", newStateParams);
|
|
662
|
-
} else {
|
|
663
|
-
this.$state.go("^.loadBalancerDetails", newStateParams);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
CloudrunLoadBalancerWizardController.$inject = [
|
|
668
|
-
"$scope",
|
|
669
|
-
"$state",
|
|
670
|
-
"$uibModalInstance",
|
|
671
|
-
"application",
|
|
672
|
-
"loadBalancer",
|
|
673
|
-
"isNew",
|
|
674
|
-
"forPipelineConfig",
|
|
675
|
-
"cloudrunLoadBalancerTransformer",
|
|
676
|
-
"wizardSubFormValidation"
|
|
677
|
-
];
|
|
678
|
-
const CLOUDRUN_LOAD_BALANCER_WIZARD_CTRL = "spinnaker.cloudrun.loadBalancer.wizard.controller";
|
|
679
|
-
module(CLOUDRUN_LOAD_BALANCER_WIZARD_CTRL, []).controller("cloudrunLoadBalancerWizardCtrl", CloudrunLoadBalancerWizardController);
|
|
680
|
-
|
|
681
|
-
class CloudrunLoadBalancerDetailsController {
|
|
682
|
-
constructor($uibModal, $state, $scope, loadBalancer, app) {
|
|
683
|
-
this.$uibModal = $uibModal;
|
|
684
|
-
this.$state = $state;
|
|
685
|
-
this.$scope = $scope;
|
|
686
|
-
this.app = app;
|
|
687
|
-
this.state = { loading: true };
|
|
688
|
-
this.loadBalancerFromParams = loadBalancer;
|
|
689
|
-
this.app.getDataSource("loadBalancers").ready().then(() => this.extractLoadBalancer());
|
|
690
|
-
}
|
|
691
|
-
editLoadBalancer() {
|
|
692
|
-
this.$uibModal.open({
|
|
693
|
-
templateUrl: "cloudrun/src/loadBalancer/configure/wizard/wizard.html",
|
|
694
|
-
controller: "cloudrunLoadBalancerWizardCtrl as ctrl",
|
|
695
|
-
size: "lg",
|
|
696
|
-
resolve: {
|
|
697
|
-
application: () => this.app,
|
|
698
|
-
loadBalancer: () => cloneDeep(this.loadBalancer),
|
|
699
|
-
isNew: () => false,
|
|
700
|
-
forPipelineConfig: () => false
|
|
701
|
-
}
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
extractLoadBalancer() {
|
|
705
|
-
this.loadBalancer = this.app.getDataSource("loadBalancers").data.find((test) => {
|
|
706
|
-
return test.name === this.loadBalancerFromParams.name && test.account === this.loadBalancerFromParams.accountId;
|
|
707
|
-
});
|
|
708
|
-
if (this.loadBalancer) {
|
|
709
|
-
this.state.loading = false;
|
|
710
|
-
this.app.getDataSource("loadBalancers").onRefresh(this.$scope, () => this.extractLoadBalancer());
|
|
711
|
-
} else {
|
|
712
|
-
this.autoClose();
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
deleteLoadBalancer() {
|
|
716
|
-
const taskMonitor = {
|
|
717
|
-
application: this.app,
|
|
718
|
-
title: "Deleting " + this.loadBalancer.name
|
|
719
|
-
};
|
|
720
|
-
const submitMethod = () => {
|
|
721
|
-
const loadBalancer = {
|
|
722
|
-
cloudProvider: this.loadBalancer.cloudProvider,
|
|
723
|
-
loadBalancerName: this.loadBalancer.name,
|
|
724
|
-
credentials: this.loadBalancer.account
|
|
725
|
-
};
|
|
726
|
-
return LoadBalancerWriter.deleteLoadBalancer(loadBalancer, this.app);
|
|
727
|
-
};
|
|
728
|
-
ConfirmationModalService.confirm({
|
|
729
|
-
header: "Really delete " + this.loadBalancer.name + "?",
|
|
730
|
-
buttonText: "Delete " + this.loadBalancer.name,
|
|
731
|
-
body: this.getConfirmationModalBodyHtml(),
|
|
732
|
-
account: this.loadBalancer.account,
|
|
733
|
-
taskMonitorConfig: taskMonitor,
|
|
734
|
-
submitMethod
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
canDeleteLoadBalancer() {
|
|
738
|
-
return this.loadBalancer.name !== "default";
|
|
739
|
-
}
|
|
740
|
-
getConfirmationModalBodyHtml() {
|
|
741
|
-
const serverGroupNames = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);
|
|
742
|
-
const hasAny = serverGroupNames ? serverGroupNames.length > 0 : false;
|
|
743
|
-
const hasMoreThanOne = serverGroupNames ? serverGroupNames.length > 1 : false;
|
|
744
|
-
if (hasAny) {
|
|
745
|
-
if (hasMoreThanOne) {
|
|
746
|
-
const listOfServerGroupNames = serverGroupNames.map((name) => `<li>${name}</li>`).join("");
|
|
747
|
-
return `<div class="alert alert-warning">
|
|
748
|
-
<p>
|
|
749
|
-
Deleting <b>${this.loadBalancer.name}</b> will destroy the following server groups:
|
|
750
|
-
<ul>
|
|
751
|
-
${listOfServerGroupNames}
|
|
752
|
-
</ul>
|
|
753
|
-
</p>
|
|
754
|
-
</div>
|
|
755
|
-
`;
|
|
756
|
-
} else {
|
|
757
|
-
return `<div class="alert alert-warning">
|
|
758
|
-
<p>
|
|
759
|
-
Deleting <b>${this.loadBalancer.name}</b> will destroy <b>${serverGroupNames[0]}</b>.
|
|
760
|
-
</p>
|
|
761
|
-
</div>
|
|
762
|
-
`;
|
|
763
|
-
}
|
|
764
|
-
} else {
|
|
765
|
-
return null;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
autoClose() {
|
|
769
|
-
if (this.$scope.$$destroyed) {
|
|
770
|
-
return;
|
|
771
|
-
} else {
|
|
772
|
-
this.$state.params.allowModalToStayOpen = true;
|
|
773
|
-
this.$state.go("^", null, { location: "replace" });
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
CloudrunLoadBalancerDetailsController.$inject = ["$uibModal", "$state", "$scope", "loadBalancer", "app"];
|
|
778
|
-
const CLOUDRUN_LOAD_BALANCER_DETAILS_CTRL = "spinnaker.cloudrun.loadBalancerDetails.controller";
|
|
779
|
-
module(CLOUDRUN_LOAD_BALANCER_DETAILS_CTRL, []).controller("cloudrunLoadBalancerDetailsCtrl", CloudrunLoadBalancerDetailsController);
|
|
780
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
781
|
-
templateCache.put("cloudrun/src/loadBalancer/configure/wizard/wizard.html", `<form name="form">
|
|
782
|
-
<div ng-if="ctrl.state.loading && !ctrl.isNew" style="height: 200px" class="horizontal center middle">
|
|
783
|
-
<loading-spinner size="'small'"></loading-spinner>
|
|
784
|
-
</div>
|
|
785
|
-
<v2-modal-wizard
|
|
786
|
-
heading="{{::ctrl.heading}}"
|
|
787
|
-
task-monitor="ctrl.taskMonitor"
|
|
788
|
-
dismiss="$dismiss()"
|
|
789
|
-
ng-if="!ctrl.state.loading || ctrl.isNew"
|
|
790
|
-
>
|
|
791
|
-
<div ng-if="!ctrl.isNew">
|
|
792
|
-
<v2-wizard-page key="basic-settings" label="Basic Settings" mark-complete-on-view="false">
|
|
793
|
-
<cloudrun-load-balancer-basic-settings
|
|
794
|
-
load-balancer="ctrl.loadBalancer"
|
|
795
|
-
application="ctrl.application"
|
|
796
|
-
for-pipeline-config="ctrl.forPipelineConfig"
|
|
797
|
-
></cloudrun-load-balancer-basic-settings>
|
|
798
|
-
</v2-wizard-page>
|
|
799
|
-
</div>
|
|
800
|
-
</v2-modal-wizard>
|
|
801
|
-
<cloudrun-load-balancer-message
|
|
802
|
-
ng-if="ctrl.isNew"
|
|
803
|
-
column-offset="1"
|
|
804
|
-
columns="10"
|
|
805
|
-
show-create-message="true"
|
|
806
|
-
></cloudrun-load-balancer-message>
|
|
807
|
-
<div class="modal-footer">
|
|
808
|
-
<button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>
|
|
809
|
-
<submit-button
|
|
810
|
-
ng-if="!ctrl.isNew && ctrl.showSubmitButton()"
|
|
811
|
-
label="ctrl.submitButtonLabel"
|
|
812
|
-
is-disabled="cloudrunLoadBalancerForm.$invalid || ctrl.taskMonitor.submitting || ctrl.state.loading"
|
|
813
|
-
submitting="ctrl.taskMonitor.submitting"
|
|
814
|
-
on-click="ctrl.submit()"
|
|
815
|
-
is-new="ctrl.isNew"
|
|
816
|
-
>
|
|
817
|
-
</submit-button>
|
|
818
|
-
</div>
|
|
819
|
-
</form>
|
|
820
|
-
`);
|
|
821
|
-
}]);
|
|
822
|
-
|
|
823
|
-
var logo = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAFAUlEQVRYR82YfUwcRRjGn5m7veO4rZI2aKuk1kRNjQ012rRANB53YNpYtFHS1Aj9ktaPtGINpPWgKQ0sVNvUNGirgYBJSTSA1H6ltpTrVYtUS2u1aRS/LSRFEmqBPcC7vR2zixwc7N4tJ02c5P64zMwzv332fd+ZWYL/USNGWFL3MpvVJy4xMlZzTJA/7y0hw9HmR4VxlokVIGQzwOzRxCL0D4DgA4+bL4ykERHGKfiqAJb3HyAmTCXVniL7Bj09XRhXqZjBKJqnD2REicjIbNnOn9bS1YVxlvuOgrHl0w0DQo553PYswzAuQcxhwMFpB/lXkAC5LUV83UT9Sc44SpjZxPnaGLDoFsK0BwP2VG8JkcavMQnGWSYWgGD3rQIJ6TIUeor5PbowjrcGk6gktwFI0oKZk0Bw/SYLdSXNpOi6IcfK3SWbaap3a3zXqECYM85ycTcYCvTUX3JZ0NMn41D7iLt5Dgv6hhgavgrEBkSwZ3ztCcE4ynyLKGGKK2Y95ZT7TBBWxuHzH4LY2TSMBUkU+1bbcOn3IPZ95o/FJUlmJNVbbG9X0350YacgKtmTE+kRORNQs9GGO2+nyKsawrVeGe+vt+HyH0E88yiHmrP+WFyq8xTxuSEYV2n/ckbpUSNeFzxlxbKFZuxv9uPUFQkrUzgkz6U4/o2E7MUcbvgY3j01NZeILGe1bL/tmOpMernYTBgyjMBkLjBj29NWfNEhofKkH/MSKXatikPO/kEwBmQv4bA02YyD5wKGXWIEp8+4+UziFPrzAFplBEQZM4snqH8tHjcHGTZWD6nTKtfYUHvWr8aO0u6fTbHpSSt+6ZFR5THqkryBOAXfEYBplmc9wPfW2jD/Loqi+mH81C1jzeMWzEvU3lnmJFDUtfpx+GJYfdOSPkHSBbGHAIlGnRlN6efTOPU1KL+HkkzY8aw1okTLVQk1Xj+6+8bq1MQJJL1MrCYEL04FpjrPhnvvGHNm3RMWNai1mlIkFeBzHRL8QWBgSAeGkAbiKhWXMooTRmFmzSCo3xweMwfW29RYmthOfiepIP3jAAJBhP0PVV8Zy1QFpyDWAlhrBEhJ31cyLKFsevBuip3PxYVN7eyV8XFbABd+HQnoiU2Sgb7BMIc+9BTx61QYhyA+TAGl+oaragjtfSEOC+8xqXXG+72E3Mc4ZD3ChUYeuRRAw/kA/o4Sr0EZakYCGJaBVG8Rf3msApcPVoDJ26K50+K2QxF6tXYIf/mYuh0oG+hvPTLqWgO40qnthq5DQ2SXxx3/ptI/tjeViLMpp7ozTw8o7QETSrOVvUlSq2zyXBOKV1jRdCGgvpapNkrR+WcvW+wt4bvDYNTYKRNfB8E7eqJK5f365yC+vTby9EoWffmjhI7rsR0jgjLb2rSFfzsUxBMXdgnKKY+laAFZzQAfF/V2Y8ggAlysz7eHnSYnKbuEgVUM5CM9xekCCshs9adb+LBztuZjOgXfIYCt0AXiAN4au0MM9Hhjvm3SzUNT0VE64KCUnInkdxwH2GME8vtZ5uHCyXcn/XuT4DsAsJenG4gBNY35ds3tRxfGUd4/nzKqpHpCJCCbhSDeYihmAbB+2cTSPtk046rWjMh37dKBElCyI9pSRoEYUNGYb3fr6UWNQqcKRAuifYWItxDYdBwihIgyY5WRQCYVPT1io99nZvKc5jnCxKytDW+QkWNhhBbVmWgC09n/Dw0j4+SJOXQTAAAAAElFTkSuQmCC";
|
|
824
|
-
|
|
825
|
-
class CloudrunLoadBalancerChoiceModalCtrl {
|
|
826
|
-
constructor($uibModal, $uibModalInstance, application) {
|
|
827
|
-
this.$uibModal = $uibModal;
|
|
828
|
-
this.$uibModalInstance = $uibModalInstance;
|
|
829
|
-
this.application = application;
|
|
830
|
-
this.state = { loading: true };
|
|
831
|
-
this.initialize();
|
|
832
|
-
}
|
|
833
|
-
submit() {
|
|
834
|
-
const config = CloudProviderRegistry.getValue("cloudrun", "loadBalancer");
|
|
835
|
-
const updatedLoadBalancerPromise = this.$uibModal.open({
|
|
836
|
-
templateUrl: config.createLoadBalancerTemplateUrl,
|
|
837
|
-
controller: `${config.createLoadBalancerController} as ctrl`,
|
|
838
|
-
size: "lg",
|
|
839
|
-
resolve: {
|
|
840
|
-
application: () => this.application,
|
|
841
|
-
loadBalancer: () => cloneDeep(this.selectedLoadBalancer),
|
|
842
|
-
isNew: () => false,
|
|
843
|
-
forPipelineConfig: () => true
|
|
844
|
-
}
|
|
845
|
-
}).result;
|
|
846
|
-
this.$uibModalInstance.close(updatedLoadBalancerPromise);
|
|
847
|
-
}
|
|
848
|
-
cancel() {
|
|
849
|
-
this.$uibModalInstance.dismiss();
|
|
850
|
-
}
|
|
851
|
-
initialize() {
|
|
852
|
-
this.application.getDataSource("loadBalancers").ready().then(() => {
|
|
853
|
-
this.loadBalancers = this.application.loadBalancers.data.filter((candidate) => candidate.cloudProvider === "cloudrun");
|
|
854
|
-
if (this.loadBalancers.length) {
|
|
855
|
-
this.selectedLoadBalancer = this.loadBalancers[0];
|
|
856
|
-
}
|
|
857
|
-
this.state.loading = false;
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
CloudrunLoadBalancerChoiceModalCtrl.$inject = ["$uibModal", "$uibModalInstance", "application"];
|
|
862
|
-
const CLOUDRUN_LOAD_BALANCER_CHOICE_MODAL_CTRL = "spinnaker.Cloudrun.loadBalancerChoiceModal.controller";
|
|
863
|
-
module(CLOUDRUN_LOAD_BALANCER_CHOICE_MODAL_CTRL, []).controller("cloudrunLoadBalancerChoiceModelCtrl", CloudrunLoadBalancerChoiceModalCtrl);
|
|
864
|
-
|
|
865
|
-
class CloudrunEditLoadBalancerStageCtrl {
|
|
866
|
-
constructor($scope, $uibModal) {
|
|
867
|
-
this.$scope = $scope;
|
|
868
|
-
this.$uibModal = $uibModal;
|
|
869
|
-
$scope.stage.loadBalancers = $scope.stage.loadBalancers || [];
|
|
870
|
-
$scope.stage.cloudProvider = "cloudrun";
|
|
871
|
-
}
|
|
872
|
-
addLoadBalancer() {
|
|
873
|
-
this.$uibModal.open({
|
|
874
|
-
templateUrl: "cloudrun/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html",
|
|
875
|
-
controller: `cloudrunLoadBalancerChoiceModelCtrl as ctrl`,
|
|
876
|
-
resolve: {
|
|
877
|
-
application: () => this.$scope.application
|
|
878
|
-
}
|
|
879
|
-
}).result.then((newLoadBalancer) => {
|
|
880
|
-
this.$scope.stage.loadBalancers.push(newLoadBalancer);
|
|
881
|
-
}).catch(() => {
|
|
882
|
-
});
|
|
883
|
-
}
|
|
884
|
-
editLoadBalancer(index) {
|
|
885
|
-
const config = CloudProviderRegistry.getValue("cloudrun", "loadBalancer");
|
|
886
|
-
this.$uibModal.open({
|
|
887
|
-
templateUrl: config.createLoadBalancerTemplateUrl,
|
|
888
|
-
controller: `${config.createLoadBalancerController} as ctrl`,
|
|
889
|
-
size: "lg",
|
|
890
|
-
resolve: {
|
|
891
|
-
application: () => this.$scope.application,
|
|
892
|
-
loadBalancer: () => cloneDeep(this.$scope.stage.loadBalancers[index]),
|
|
893
|
-
isNew: () => false,
|
|
894
|
-
forPipelineConfig: () => true
|
|
895
|
-
}
|
|
896
|
-
}).result.then((updatedLoadBalancer) => {
|
|
897
|
-
this.$scope.stage.loadBalancers[index] = updatedLoadBalancer;
|
|
898
|
-
}).catch(() => {
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
|
-
removeLoadBalancer(index) {
|
|
902
|
-
this.$scope.stage.loadBalancers.splice(index, 1);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
CloudrunEditLoadBalancerStageCtrl.$inject = ["$scope", "$uibModal"];
|
|
906
|
-
const CLOUDRUN_EDIT_LOAD_BALANCER_STAGE = "spinnaker.cloudrun.pipeline.stage.editLoadBalancerStage";
|
|
907
|
-
module(CLOUDRUN_EDIT_LOAD_BALANCER_STAGE, [CLOUDRUN_LOAD_BALANCER_CHOICE_MODAL_CTRL]).config(() => {
|
|
908
|
-
Registry.pipeline.registerStage({
|
|
909
|
-
label: "Edit Load Balancer (Cloud Run)",
|
|
910
|
-
description: "Edits a load balancer",
|
|
911
|
-
key: "upsertCloudrunLoadBalancers",
|
|
912
|
-
cloudProvider: "cloudrun",
|
|
913
|
-
templateUrl: "cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html",
|
|
914
|
-
executionDetailsUrl: "cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html",
|
|
915
|
-
executionConfigSections: ["editLoadBalancerConfig", "taskStatus"],
|
|
916
|
-
controller: "cloudrunEditLoadBalancerStageCtrl",
|
|
917
|
-
controllerAs: "editLoadBalancerStageCtrl",
|
|
918
|
-
validators: []
|
|
919
|
-
});
|
|
920
|
-
}).controller("cloudrunEditLoadBalancerStageCtrl", CloudrunEditLoadBalancerStageCtrl);
|
|
921
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
922
|
-
templateCache.put("cloudrun/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html", `<div modal-page>
|
|
923
|
-
<modal-close dismiss="$dismiss()"></modal-close>
|
|
924
|
-
<div class="modal-header">
|
|
925
|
-
<h4 class="modal-title">Select Load Balancer</h4>
|
|
926
|
-
</div>
|
|
927
|
-
<div class="modal-body" ng-if="ctrl.state.loading" style="height: 200px" class="horizontal center middle">
|
|
928
|
-
<loading-spinner size="'small'"></loading-spinner>
|
|
929
|
-
</div>
|
|
930
|
-
<div class="modal-body" ng-if="!ctrl.state.loading">
|
|
931
|
-
<div class="alert alert-warning" ng-if="ctrl.loadBalancers.length === 0">
|
|
932
|
-
<p>
|
|
933
|
-
Spinnaker cannot create a load balancer for Cloud Run. A Spinnaker load balancer maps to a Cloud Run service
|
|
934
|
-
which along with a Revision are created from Create Server Group page using a
|
|
935
|
-
</p>
|
|
936
|
-
<p><code>yaml file</code> <help-field key="cloudrun.serverGroup.file"></help-field></p>
|
|
937
|
-
<p>
|
|
938
|
-
If a service does not exist when a Revision is deployed, it will be created. It will then be editable as a load
|
|
939
|
-
balancer within Spinnaker.
|
|
940
|
-
</p>
|
|
941
|
-
</div>
|
|
942
|
-
<form
|
|
943
|
-
role="form"
|
|
944
|
-
name="form"
|
|
945
|
-
class="form-horizontal"
|
|
946
|
-
ng-submit="ctrl.submit()"
|
|
947
|
-
ng-if="ctrl.loadBalancers.length > 0"
|
|
948
|
-
>
|
|
949
|
-
<div class="form-group">
|
|
950
|
-
<div class="col-md-3 sm-label-right">
|
|
951
|
-
<b>Load Balancer</b>
|
|
952
|
-
</div>
|
|
953
|
-
<div class="col-md-7">
|
|
954
|
-
<ui-select class="form-control input-sm" ng-model="ctrl.selectedLoadBalancer">
|
|
955
|
-
<ui-select-match>
|
|
956
|
-
<account-tag account="$select.selected.account"></account-tag>
|
|
957
|
-
<span style="margin-left: 5px">{{$select.selected.name}}</span>
|
|
958
|
-
</ui-select-match>
|
|
959
|
-
<ui-select-choices repeat="loadBalancer in ctrl.loadBalancers | filter: $select.search">
|
|
960
|
-
<account-tag account="loadBalancer.account"></account-tag>
|
|
961
|
-
<span style="margin-left: 5px" ng-bind-html="loadBalancer.name"></span>
|
|
962
|
-
</ui-select-choices>
|
|
963
|
-
</ui-select>
|
|
964
|
-
</div>
|
|
965
|
-
</div>
|
|
966
|
-
</form>
|
|
967
|
-
</div>
|
|
968
|
-
<div class="modal-footer">
|
|
969
|
-
<button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>
|
|
970
|
-
<button class="btn btn-primary" ng-if="ctrl.loadBalancers.length > 0" ng-click="ctrl.submit()">
|
|
971
|
-
<span class="far fa-check-circle"></span> Edit
|
|
972
|
-
</button>
|
|
973
|
-
</div>
|
|
974
|
-
</div>
|
|
975
|
-
`);
|
|
976
|
-
}]);
|
|
977
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
978
|
-
templateCache.put("cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html", `<div class="well well-sm clearfix" ng-if="!pipeline.strategy">
|
|
979
|
-
<div class="row">
|
|
980
|
-
<div class="col-md-12">
|
|
981
|
-
<h4 class="text-left">Load Balancers</h4>
|
|
982
|
-
</div>
|
|
983
|
-
</div>
|
|
984
|
-
<div class="row">
|
|
985
|
-
<div class="col-md-12">
|
|
986
|
-
<table class="table table-condensed">
|
|
987
|
-
<thead>
|
|
988
|
-
<tr>
|
|
989
|
-
<th>Account</th>
|
|
990
|
-
<th>Name</th>
|
|
991
|
-
<th>Region</th>
|
|
992
|
-
<th>Actions</th>
|
|
993
|
-
</tr>
|
|
994
|
-
</thead>
|
|
995
|
-
<tbody>
|
|
996
|
-
<tr ng-repeat="loadBalancer in stage.loadBalancers">
|
|
997
|
-
<td>
|
|
998
|
-
<account-tag account="loadBalancer.credentials"></account-tag>
|
|
999
|
-
</td>
|
|
1000
|
-
<td>{{ loadBalancer.name }}</td>
|
|
1001
|
-
<td>{{ loadBalancer.region }}</td>
|
|
1002
|
-
<td class="condensed-actions">
|
|
1003
|
-
<a class="btn btn-sm btn-link" href ng-click="editLoadBalancerStageCtrl.editLoadBalancer($index)">
|
|
1004
|
-
<span class="glyphicon glyphicon-edit" uib-tooltip="Edit"></span
|
|
1005
|
-
></a>
|
|
1006
|
-
<a
|
|
1007
|
-
class="btn btn-sm btn-link pad-left"
|
|
1008
|
-
href
|
|
1009
|
-
ng-click="editLoadBalancerStageCtrl.removeLoadBalancer($index)"
|
|
1010
|
-
>
|
|
1011
|
-
<span class="glyphicon glyphicon-trash" uib-tooltip="Remove"></span>
|
|
1012
|
-
</a>
|
|
1013
|
-
</td>
|
|
1014
|
-
</tr>
|
|
1015
|
-
</tbody>
|
|
1016
|
-
<tfoot>
|
|
1017
|
-
<tr>
|
|
1018
|
-
<td colspan="8">
|
|
1019
|
-
<button class="btn btn-block btn-sm add-new" ng-click="editLoadBalancerStageCtrl.addLoadBalancer()">
|
|
1020
|
-
<span class="glyphicon glyphicon-plus-sign"></span> Add load balancer
|
|
1021
|
-
</button>
|
|
1022
|
-
</td>
|
|
1023
|
-
</tr>
|
|
1024
|
-
</tfoot>
|
|
1025
|
-
</table>
|
|
1026
|
-
</div>
|
|
1027
|
-
</div>
|
|
1028
|
-
</div>
|
|
1029
|
-
`);
|
|
1030
|
-
}]);
|
|
1031
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
1032
|
-
templateCache.put("cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html", `<div ng-controller="BaseExecutionDetailsCtrl">
|
|
1033
|
-
<execution-details-section-nav sections="configSections"></execution-details-section-nav>
|
|
1034
|
-
<div class="step-section-details" ng-if="detailsSection === 'editLoadBalancerConfig'">
|
|
1035
|
-
<div class="row">
|
|
1036
|
-
<div class="col-md-12">
|
|
1037
|
-
<table class="table table-condensed">
|
|
1038
|
-
<thead>
|
|
1039
|
-
<tr>
|
|
1040
|
-
<th>Account</th>
|
|
1041
|
-
<th>Name</th>
|
|
1042
|
-
<th>Region</th>
|
|
1043
|
-
</tr>
|
|
1044
|
-
</thead>
|
|
1045
|
-
<tbody>
|
|
1046
|
-
<tr ng-repeat="loadBalancer in stage.context.loadBalancers">
|
|
1047
|
-
<td>
|
|
1048
|
-
<account-tag account="loadBalancer.credentials"></account-tag>
|
|
1049
|
-
</td>
|
|
1050
|
-
<td>{{ loadBalancer.name }}</td>
|
|
1051
|
-
<td>{{ loadBalancer.region }}</td>
|
|
1052
|
-
</tr>
|
|
1053
|
-
</tbody>
|
|
1054
|
-
</table>
|
|
1055
|
-
</div>
|
|
1056
|
-
</div>
|
|
1057
|
-
<stage-failure-message stage="stage" message="stage.failureMessage"></stage-failure-message>
|
|
1058
|
-
</div>
|
|
1059
|
-
<div class="step-section-details" ng-if="detailsSection === 'taskStatus'">
|
|
1060
|
-
<div class="row">
|
|
1061
|
-
<execution-step-details item="stage"></execution-step-details>
|
|
1062
|
-
</div>
|
|
1063
|
-
</div>
|
|
1064
|
-
</div>
|
|
1065
|
-
`);
|
|
1066
|
-
}]);
|
|
1067
|
-
|
|
1068
|
-
const CLOUDRUN_PIPELINE_MODULE = "spinnaker.cloudrun.pipeline.module";
|
|
1069
|
-
module(CLOUDRUN_PIPELINE_MODULE, [CLOUDRUN_EDIT_LOAD_BALANCER_STAGE]);
|
|
1070
|
-
|
|
1071
|
-
class ManifestBindArtifactsSelector extends React.Component {
|
|
1072
|
-
constructor() {
|
|
1073
|
-
super(...arguments);
|
|
1074
|
-
this.onChangeBinding = (index, binding) => {
|
|
1075
|
-
const bindings = (this.props.bindings || []).slice(0);
|
|
1076
|
-
bindings[index] = binding;
|
|
1077
|
-
this.props.onChangeBindings(bindings);
|
|
1078
|
-
};
|
|
1079
|
-
this.onRemoveBinding = (index) => {
|
|
1080
|
-
const bindings = (this.props.bindings || []).slice(0);
|
|
1081
|
-
bindings.splice(index, 1);
|
|
1082
|
-
this.props.onChangeBindings(bindings);
|
|
1083
|
-
};
|
|
1084
|
-
}
|
|
1085
|
-
render() {
|
|
1086
|
-
const { stage, pipeline, bindings } = this.props;
|
|
1087
|
-
const renderSelect = (i, binding) => {
|
|
1088
|
-
const key = !binding && "new" || binding.expectedArtifactId || binding.artifact && binding.artifact.id;
|
|
1089
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
1090
|
-
className: "row",
|
|
1091
|
-
key
|
|
1092
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1093
|
-
className: "col-md-10"
|
|
1094
|
-
}, /* @__PURE__ */ React.createElement(StageArtifactSelector, {
|
|
1095
|
-
pipeline,
|
|
1096
|
-
stage,
|
|
1097
|
-
expectedArtifactId: binding && binding.expectedArtifactId,
|
|
1098
|
-
artifact: !!binding && binding.artifact,
|
|
1099
|
-
onArtifactEdited: (artifact) => this.onChangeBinding(i, { artifact }),
|
|
1100
|
-
onExpectedArtifactSelected: (expectedArtifact) => this.onChangeBinding(i, { expectedArtifactId: expectedArtifact.id }),
|
|
1101
|
-
excludedArtifactIds: bindings.map((b) => b.expectedArtifactId),
|
|
1102
|
-
excludedArtifactTypePatterns: [ArtifactTypePatterns.FRONT50_PIPELINE_TEMPLATE]
|
|
1103
|
-
})), binding && /* @__PURE__ */ React.createElement("div", {
|
|
1104
|
-
className: "col-md-2"
|
|
1105
|
-
}, /* @__PURE__ */ React.createElement("a", {
|
|
1106
|
-
className: "glyphicon glyphicon-trash",
|
|
1107
|
-
onClick: () => this.onRemoveBinding(i)
|
|
1108
|
-
})));
|
|
1109
|
-
};
|
|
1110
|
-
const renderSelectEditable = (binding, i) => renderSelect(i, binding);
|
|
1111
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, bindings.map(renderSelectEditable), renderSelect(bindings.length));
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
var ManifestSource;
|
|
1116
|
-
(function(ManifestSource2) {
|
|
1117
|
-
ManifestSource2["TEXT"] = "text";
|
|
1118
|
-
ManifestSource2["ARTIFACT"] = "artifact";
|
|
1119
|
-
})(ManifestSource || (ManifestSource = {}));
|
|
1120
|
-
|
|
1121
|
-
function ManifestBasicSettings({ accounts, onAccountSelect, selectedAccount }) {
|
|
1122
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
1123
|
-
className: "form-horizontal"
|
|
1124
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1125
|
-
className: "form-group"
|
|
1126
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1127
|
-
className: "col-md-3 sm-label-right"
|
|
1128
|
-
}, "Account ", /* @__PURE__ */ React.createElement(HelpField, {
|
|
1129
|
-
id: "cloudrun.manifest.account"
|
|
1130
|
-
})), /* @__PURE__ */ React.createElement("div", {
|
|
1131
|
-
className: "col-md-8"
|
|
1132
|
-
}, /* @__PURE__ */ React.createElement(AccountSelectInput, {
|
|
1133
|
-
value: selectedAccount,
|
|
1134
|
-
onChange: (evt) => onAccountSelect(evt.target.value),
|
|
1135
|
-
readOnly: false,
|
|
1136
|
-
accounts,
|
|
1137
|
-
provider: "cloudrun"
|
|
1138
|
-
}))));
|
|
1139
|
-
}
|
|
1140
|
-
class WizardManifestBasicSettings extends React.Component {
|
|
1141
|
-
constructor() {
|
|
1142
|
-
super(...arguments);
|
|
1143
|
-
this.accountUpdated = (account) => {
|
|
1144
|
-
const { formik } = this.props;
|
|
1145
|
-
formik.values.command.account = account;
|
|
1146
|
-
formik.setFieldValue("account", account);
|
|
1147
|
-
};
|
|
1148
|
-
}
|
|
1149
|
-
render() {
|
|
1150
|
-
const { formik } = this.props;
|
|
1151
|
-
return /* @__PURE__ */ React.createElement(ManifestBasicSettings, {
|
|
1152
|
-
accounts: formik.values.metadata.backingData.accounts,
|
|
1153
|
-
onAccountSelect: this.accountUpdated,
|
|
1154
|
-
selectedAccount: formik.values.command.account
|
|
1155
|
-
});
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
class ServerGroupNamePreview extends React.Component {
|
|
1160
|
-
render() {
|
|
1161
|
-
const application = this.props.application ? this.props.application : "";
|
|
1162
|
-
const stack = this.props.stack ? `-${this.props.stack}` : "";
|
|
1163
|
-
const details = this.props.details ? `-${this.props.details}` : "";
|
|
1164
|
-
return /* @__PURE__ */ React.createElement("pre", {
|
|
1165
|
-
style: { textAlign: "center" }
|
|
1166
|
-
}, /* @__PURE__ */ React.createElement("p", null, " Your server group will be in the cluster:"), /* @__PURE__ */ React.createElement("p", null, /* @__PURE__ */ React.createElement("b", null, application, stack, details)));
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
class DeployStageForm extends React.Component {
|
|
1171
|
-
constructor(props) {
|
|
1172
|
-
super(props);
|
|
1173
|
-
this.excludedManifestArtifactTypes = [
|
|
1174
|
-
ArtifactTypePatterns.FRONT50_PIPELINE_TEMPLATE,
|
|
1175
|
-
ArtifactTypePatterns.MAVEN_FILE
|
|
1176
|
-
];
|
|
1177
|
-
this.getSourceOptions = () => {
|
|
1178
|
-
return map([ManifestSource.TEXT, ManifestSource.ARTIFACT], (option) => ({
|
|
1179
|
-
label: capitalize(option),
|
|
1180
|
-
value: option
|
|
1181
|
-
}));
|
|
1182
|
-
};
|
|
1183
|
-
this.handleRawManifestChange = (rawManifest, manifests) => {
|
|
1184
|
-
this.setState({
|
|
1185
|
-
rawManifest
|
|
1186
|
-
});
|
|
1187
|
-
this.props.formik.setFieldValue("manifests", manifests);
|
|
1188
|
-
};
|
|
1189
|
-
this.onManifestArtifactSelected = (expectedArtifactId) => {
|
|
1190
|
-
this.props.formik.setFieldValue("manifestArtifactId", expectedArtifactId);
|
|
1191
|
-
this.props.formik.setFieldValue("manifestArtifact", null);
|
|
1192
|
-
};
|
|
1193
|
-
this.onManifestArtifactEdited = (artifact) => {
|
|
1194
|
-
this.props.formik.setFieldValue("manifestArtifactId", null);
|
|
1195
|
-
this.props.formik.setFieldValue("manifestArtifact", artifact);
|
|
1196
|
-
};
|
|
1197
|
-
this.getRequiredArtifacts = () => {
|
|
1198
|
-
const { requiredArtifactIds, requiredArtifacts } = this.props.formik.values;
|
|
1199
|
-
return (requiredArtifactIds || []).map((id) => ({ expectedArtifactId: id })).concat(requiredArtifacts || []);
|
|
1200
|
-
};
|
|
1201
|
-
this.onRequiredArtifactsChanged = (bindings) => {
|
|
1202
|
-
this.props.formik.setFieldValue("requiredArtifactIds", bindings.filter((b) => b.expectedArtifactId).map((b) => b.expectedArtifactId));
|
|
1203
|
-
this.props.formik.setFieldValue("requiredArtifacts", bindings.filter((b) => b.artifact));
|
|
1204
|
-
};
|
|
1205
|
-
const stage = this.props.formik.values;
|
|
1206
|
-
const manifests = get(props.formik.values, "manifests");
|
|
1207
|
-
const isTextManifest = get(props.formik.values, "source") === ManifestSource.TEXT;
|
|
1208
|
-
this.state = {
|
|
1209
|
-
rawManifest: !isEmpty(manifests) && isTextManifest ? yamlDocumentsToString(manifests) : "",
|
|
1210
|
-
application: this.props.application.name,
|
|
1211
|
-
stack: get(stage, "stack"),
|
|
1212
|
-
details: get(stage, "details")
|
|
1213
|
-
};
|
|
1214
|
-
}
|
|
1215
|
-
render() {
|
|
1216
|
-
const stage = this.props.formik.values;
|
|
1217
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
1218
|
-
className: "form-horizontal"
|
|
1219
|
-
}, /* @__PURE__ */ React.createElement("h4", null, "Basic Settings"), /* @__PURE__ */ React.createElement(ManifestBasicSettings, {
|
|
1220
|
-
accounts: this.props.accounts,
|
|
1221
|
-
onAccountSelect: (accountName) => this.props.formik.setFieldValue("account", accountName),
|
|
1222
|
-
selectedAccount: stage.account
|
|
1223
|
-
}), /* @__PURE__ */ React.createElement(StageConfigField, {
|
|
1224
|
-
label: "Application"
|
|
1225
|
-
}, /* @__PURE__ */ React.createElement("input", {
|
|
1226
|
-
className: "form-control input-sm",
|
|
1227
|
-
type: "text",
|
|
1228
|
-
value: this.props.application.name,
|
|
1229
|
-
onChange: (event) => this.props.formik.setFieldValue("application", event.target.value),
|
|
1230
|
-
disabled: true
|
|
1231
|
-
})), /* @__PURE__ */ React.createElement(StageConfigField, {
|
|
1232
|
-
label: "Stack"
|
|
1233
|
-
}, /* @__PURE__ */ React.createElement("input", {
|
|
1234
|
-
className: "form-control input-sm",
|
|
1235
|
-
type: "text",
|
|
1236
|
-
value: stage.stack,
|
|
1237
|
-
onChange: (event) => this.props.formik.setFieldValue("stack", event.target.value)
|
|
1238
|
-
})), /* @__PURE__ */ React.createElement(StageConfigField, {
|
|
1239
|
-
label: "Details"
|
|
1240
|
-
}, /* @__PURE__ */ React.createElement("input", {
|
|
1241
|
-
className: "form-control input-sm",
|
|
1242
|
-
type: "text",
|
|
1243
|
-
value: stage.details,
|
|
1244
|
-
onChange: (event) => this.props.formik.setFieldValue("details", event.target.value)
|
|
1245
|
-
})), /* @__PURE__ */ React.createElement(ServerGroupNamePreview, {
|
|
1246
|
-
application: this.props.application.name,
|
|
1247
|
-
stack: stage.stack,
|
|
1248
|
-
details: stage.details
|
|
1249
|
-
}), /* @__PURE__ */ React.createElement("hr", null), /* @__PURE__ */ React.createElement("h4", null, "Manifest Configuration"), /* @__PURE__ */ React.createElement(StageConfigField, {
|
|
1250
|
-
label: "Manifest Source",
|
|
1251
|
-
helpKey: "cloudrun.manifest.source"
|
|
1252
|
-
}, /* @__PURE__ */ React.createElement(RadioButtonInput, {
|
|
1253
|
-
options: this.getSourceOptions(),
|
|
1254
|
-
onChange: (e) => this.props.formik.setFieldValue("source", e.target.value),
|
|
1255
|
-
value: stage.source
|
|
1256
|
-
})), stage.source === ManifestSource.TEXT && /* @__PURE__ */ React.createElement(StageConfigField, {
|
|
1257
|
-
label: "Manifest"
|
|
1258
|
-
}, /* @__PURE__ */ React.createElement(YamlEditor, {
|
|
1259
|
-
onChange: this.handleRawManifestChange,
|
|
1260
|
-
value: this.state.rawManifest
|
|
1261
|
-
})), stage.source === ManifestSource.ARTIFACT && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StageArtifactSelectorDelegate, {
|
|
1262
|
-
artifact: stage.manifestArtifact,
|
|
1263
|
-
excludedArtifactTypePatterns: this.excludedManifestArtifactTypes,
|
|
1264
|
-
expectedArtifactId: stage.manifestArtifactId,
|
|
1265
|
-
helpKey: "cloudrun.manifest.expectedArtifact",
|
|
1266
|
-
label: "Manifest Artifact",
|
|
1267
|
-
onArtifactEdited: this.onManifestArtifactEdited,
|
|
1268
|
-
onExpectedArtifactSelected: (artifact) => this.onManifestArtifactSelected(artifact.id),
|
|
1269
|
-
pipeline: this.props.pipeline,
|
|
1270
|
-
stage
|
|
1271
|
-
}), /* @__PURE__ */ React.createElement(StageConfigField, {
|
|
1272
|
-
label: "Expression Evaluation",
|
|
1273
|
-
helpKey: "cloudrun.manifest.skipExpressionEvaluation"
|
|
1274
|
-
}, /* @__PURE__ */ React.createElement(CheckboxInput, {
|
|
1275
|
-
checked: stage.skipExpressionEvaluation === true,
|
|
1276
|
-
onChange: (e) => this.props.formik.setFieldValue("skipExpressionEvaluation", e.target.checked),
|
|
1277
|
-
text: "Skip SpEL expression evaluation"
|
|
1278
|
-
}))), /* @__PURE__ */ React.createElement(StageConfigField, {
|
|
1279
|
-
label: "Required Artifacts to Bind",
|
|
1280
|
-
helpKey: "cloudrun.manifest.requiredArtifactsToBind"
|
|
1281
|
-
}, /* @__PURE__ */ React.createElement(ManifestBindArtifactsSelector, {
|
|
1282
|
-
bindings: this.getRequiredArtifacts(),
|
|
1283
|
-
onChangeBindings: this.onRequiredArtifactsChanged,
|
|
1284
|
-
pipeline: this.props.pipeline,
|
|
1285
|
-
stage
|
|
1286
|
-
})));
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
class DeployStageConfig extends React.Component {
|
|
1291
|
-
constructor(props) {
|
|
1292
|
-
super(props);
|
|
1293
|
-
this.destroy$ = new Subject();
|
|
1294
|
-
this.fetchAccounts = () => {
|
|
1295
|
-
from(AccountService.getAllAccountDetailsForProvider("cloudrun")).pipe(takeUntil(this.destroy$)).subscribe((accounts) => {
|
|
1296
|
-
this.setState({ accounts });
|
|
1297
|
-
});
|
|
1298
|
-
};
|
|
1299
|
-
this.state = {
|
|
1300
|
-
accounts: []
|
|
1301
|
-
};
|
|
1302
|
-
const { stage: initialStageConfig } = props;
|
|
1303
|
-
const stage = cloneDeep(initialStageConfig);
|
|
1304
|
-
if (!stage.source) {
|
|
1305
|
-
stage.source = ManifestSource.TEXT;
|
|
1306
|
-
}
|
|
1307
|
-
if (!stage.skipExpressionEvaluation) {
|
|
1308
|
-
stage.skipExpressionEvaluation = false;
|
|
1309
|
-
}
|
|
1310
|
-
if (!stage.cloudProvider) {
|
|
1311
|
-
stage.cloudProvider = "cloudrun";
|
|
1312
|
-
}
|
|
1313
|
-
if (!stage.moniker) {
|
|
1314
|
-
stage.moniker = {};
|
|
1315
|
-
}
|
|
1316
|
-
if (!stage.moniker.app) {
|
|
1317
|
-
stage.moniker.app = props.application.name;
|
|
1318
|
-
}
|
|
1319
|
-
this.stage = stage;
|
|
1320
|
-
}
|
|
1321
|
-
componentDidMount() {
|
|
1322
|
-
this.fetchAccounts();
|
|
1323
|
-
}
|
|
1324
|
-
componentWillUnmount() {
|
|
1325
|
-
this.destroy$.next();
|
|
1326
|
-
}
|
|
1327
|
-
render() {
|
|
1328
|
-
return /* @__PURE__ */ React.createElement(FormikStageConfig, {
|
|
1329
|
-
...this.props,
|
|
1330
|
-
stage: this.stage,
|
|
1331
|
-
onChange: this.props.updateStage,
|
|
1332
|
-
render: (props) => /* @__PURE__ */ React.createElement(DeployStageForm, {
|
|
1333
|
-
...props,
|
|
1334
|
-
accounts: this.state.accounts
|
|
1335
|
-
})
|
|
1336
|
-
});
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
const strategyRedBlack = {
|
|
1341
|
-
label: "Red/Black",
|
|
1342
|
-
description: "Disables <i>all</i> previous ReplicaSets in the cluster as soon as the new ReplicaSet is ready",
|
|
1343
|
-
key: "redblack"
|
|
1344
|
-
};
|
|
1345
|
-
|
|
1346
|
-
const MAX_VERSION_HISTORY_ANNOTATION = "strategy.spinnaker.io/max-version-history";
|
|
1347
|
-
const deployValidators = () => {
|
|
1348
|
-
return [
|
|
1349
|
-
{ type: "requiredField", fieldName: "account", fieldLabel: "Account" },
|
|
1350
|
-
{ type: "requiredField", fieldName: "source", fieldLabel: "Source" },
|
|
1351
|
-
{
|
|
1352
|
-
type: "custom",
|
|
1353
|
-
validate: (_pipeline, stage) => {
|
|
1354
|
-
const enabled = get(stage, "trafficManagement.enabled", false);
|
|
1355
|
-
const services = get(stage, "trafficManagement.options.services", []);
|
|
1356
|
-
if (enabled && isEmpty(services)) {
|
|
1357
|
-
return `Select at least one <strong>Service</strong> to enable Spinnaker-managed rollout strategy options.`;
|
|
1358
|
-
}
|
|
1359
|
-
if (enabled && stage.source === ManifestSource.TEXT) {
|
|
1360
|
-
const manifests = get(stage, "manifests", []);
|
|
1361
|
-
const replicaSetManifests = manifests.filter((m) => m.kind === "ReplicaSet");
|
|
1362
|
-
const strategy = get(stage, "trafficManagement.options.strategy");
|
|
1363
|
-
const maxVersionHistory = parseInt(get(replicaSetManifests, [0, "metadata", "annotations", MAX_VERSION_HISTORY_ANNOTATION]), 10);
|
|
1364
|
-
if (strategy === strategyRedBlack.key && maxVersionHistory < 2) {
|
|
1365
|
-
return `The max version history specified in your manifest conflicts with the behavior of the Red/Black rollout strategy. Please update your <strong>${MAX_VERSION_HISTORY_ANNOTATION}</strong> annotation to a value greater than or equal to 2.`;
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
return null;
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
];
|
|
1372
|
-
};
|
|
1373
|
-
|
|
1374
|
-
const STATUS_PILLS = {
|
|
1375
|
-
available: "success",
|
|
1376
|
-
stable: "success",
|
|
1377
|
-
paused: "warn",
|
|
1378
|
-
failed: "danger"
|
|
1379
|
-
};
|
|
1380
|
-
class DeployManifestStatusPills extends React.Component {
|
|
1381
|
-
render() {
|
|
1382
|
-
const { manifest } = this.props;
|
|
1383
|
-
if (manifest == null || manifest.status == null) {
|
|
1384
|
-
return null;
|
|
1385
|
-
}
|
|
1386
|
-
return Object.keys(manifest.status).map((statusKey, i) => {
|
|
1387
|
-
const statusDescription = manifest.status[statusKey];
|
|
1388
|
-
const statusClass = STATUS_PILLS[statusKey] || "";
|
|
1389
|
-
const isStable = statusDescription.state;
|
|
1390
|
-
const isUnstableWithMessage = !isStable && statusDescription.message;
|
|
1391
|
-
return /* @__PURE__ */ React.createElement("span", {
|
|
1392
|
-
key: i
|
|
1393
|
-
}, isStable && /* @__PURE__ */ React.createElement("span", {
|
|
1394
|
-
title: statusDescription.message,
|
|
1395
|
-
className: `pill ${statusClass}`
|
|
1396
|
-
}, statusKey), isUnstableWithMessage && /* @__PURE__ */ React.createElement("span", {
|
|
1397
|
-
title: statusDescription.message,
|
|
1398
|
-
className: "pill warn"
|
|
1399
|
-
}, statusKey), /* @__PURE__ */ React.createElement("span", null, "\xA0"));
|
|
1400
|
-
});
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
const UNMAPPED_K8S_RESOURCE_STATE_KEY = "cloudrunResource";
|
|
1405
|
-
class ManifestDetailsLink extends React.Component {
|
|
1406
|
-
constructor(props) {
|
|
1407
|
-
super(props);
|
|
1408
|
-
this.spinnakerKindStateMap = {
|
|
1409
|
-
serverGroupManagers: "serverGroupManager",
|
|
1410
|
-
serverGroups: "serverGroup"
|
|
1411
|
-
};
|
|
1412
|
-
this.state = {
|
|
1413
|
-
url: ""
|
|
1414
|
-
};
|
|
1415
|
-
this.loadUrl();
|
|
1416
|
-
}
|
|
1417
|
-
canOpen() {
|
|
1418
|
-
return !!this.props.manifest.manifest && !!this.state.url;
|
|
1419
|
-
}
|
|
1420
|
-
spinnakerKindFromCloudrunKind(kind, kindMap) {
|
|
1421
|
-
const foundKind = Object.keys(kindMap).find((k) => k.toLowerCase() === kind.toLowerCase());
|
|
1422
|
-
return kindMap[foundKind];
|
|
1423
|
-
}
|
|
1424
|
-
resourceRegion() {
|
|
1425
|
-
return trim(get(this.props, ["manifest", "manifest", "metadata", "annotations", "artifact.spinnaker.io/location"], ""));
|
|
1426
|
-
}
|
|
1427
|
-
getStateParams(stateKey) {
|
|
1428
|
-
const kind = this.props.manifest.manifest.kind.toLowerCase();
|
|
1429
|
-
const name = this.props.manifest.manifest.metadata.name;
|
|
1430
|
-
const region = this.resourceRegion();
|
|
1431
|
-
const params = {
|
|
1432
|
-
accountId: this.props.accountId,
|
|
1433
|
-
provider: "cloudrun",
|
|
1434
|
-
region,
|
|
1435
|
-
reg: region,
|
|
1436
|
-
[stateKey]: `${kind} ${name}`
|
|
1437
|
-
};
|
|
1438
|
-
if (!params.region && kind === "namespace" && stateKey === UNMAPPED_K8S_RESOURCE_STATE_KEY) {
|
|
1439
|
-
params.region = name;
|
|
1440
|
-
}
|
|
1441
|
-
if (!params.region || params.region === "") {
|
|
1442
|
-
params.region = "_";
|
|
1443
|
-
}
|
|
1444
|
-
return params;
|
|
1445
|
-
}
|
|
1446
|
-
loadUrl() {
|
|
1447
|
-
const kind = get(this.props, ["manifest", "manifest", "kind"], "");
|
|
1448
|
-
const { accountId } = this.props;
|
|
1449
|
-
AccountService.getAccountDetails(accountId).then((account) => {
|
|
1450
|
-
const spinnakerKind = this.spinnakerKindFromCloudrunKind(kind, account.spinnakerKindMap);
|
|
1451
|
-
const stateKey = this.spinnakerKindStateMap[spinnakerKind] || UNMAPPED_K8S_RESOURCE_STATE_KEY;
|
|
1452
|
-
const params = this.getStateParams(stateKey);
|
|
1453
|
-
const url = ReactInjector.$state.href(`home.applications.application.insight.clusters.${stateKey}`, params);
|
|
1454
|
-
this.setState({ url });
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
|
-
render() {
|
|
1458
|
-
if (this.canOpen()) {
|
|
1459
|
-
return /* @__PURE__ */ React.createElement("a", {
|
|
1460
|
-
href: this.state.url,
|
|
1461
|
-
className: "clickable"
|
|
1462
|
-
}, this.props.linkName);
|
|
1463
|
-
} else {
|
|
1464
|
-
return null;
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
|
|
1469
|
-
class ManifestEvents extends React.Component {
|
|
1470
|
-
pillStyle(e) {
|
|
1471
|
-
if (e.type === "Warning") {
|
|
1472
|
-
return "alert";
|
|
1473
|
-
} else if (e.type === "Normal") {
|
|
1474
|
-
return "success";
|
|
1475
|
-
} else {
|
|
1476
|
-
return "";
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
render() {
|
|
1480
|
-
if (!this.props.manifest) {
|
|
1481
|
-
return null;
|
|
1482
|
-
}
|
|
1483
|
-
if (this.props.manifest && (!this.props.manifest.events || this.props.manifest.events.length === 0)) {
|
|
1484
|
-
return /* @__PURE__ */ React.createElement("div", null, "No recent events found - Cloud Run does not store events for long.");
|
|
1485
|
-
}
|
|
1486
|
-
const { events } = this.props.manifest;
|
|
1487
|
-
const namespace = trim(get(this.props.manifest, ["manifest", "metadata", "annotations", "artifact.spinnaker.io/location"], ""));
|
|
1488
|
-
return events.map((e, i) => {
|
|
1489
|
-
const firstTimestamp = get(e, "firstTimestamp", "");
|
|
1490
|
-
const lastTimestamp = get(e, "lastTimestamp", "");
|
|
1491
|
-
let firstEpochMilliseconds = 0;
|
|
1492
|
-
let lastEpochMilliseconds = 0;
|
|
1493
|
-
if (firstTimestamp) {
|
|
1494
|
-
firstEpochMilliseconds = DateTime.fromISO(firstTimestamp).toMillis();
|
|
1495
|
-
}
|
|
1496
|
-
if (lastTimestamp) {
|
|
1497
|
-
lastEpochMilliseconds = DateTime.fromISO(lastTimestamp).toMillis();
|
|
1498
|
-
}
|
|
1499
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
1500
|
-
key: get(e, ["metadata", "uid"], String(i)),
|
|
1501
|
-
className: "info"
|
|
1502
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1503
|
-
className: "horizontal"
|
|
1504
|
-
}, e.count && /* @__PURE__ */ React.createElement("div", {
|
|
1505
|
-
className: `pill ${this.pillStyle(e)}`
|
|
1506
|
-
}, e.count, " \xD7 ", /* @__PURE__ */ React.createElement("b", null, e.reason))), (e.firstTimestamp || e.lastTimestamp) && /* @__PURE__ */ React.createElement("div", null, e.firstTimestamp === e.lastTimestamp && /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("i", null, relativeTime(firstEpochMilliseconds))), e.firstTimestamp !== e.lastTimestamp && /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", null, "First Occurrence: ", /* @__PURE__ */ React.createElement("i", null, relativeTime(firstEpochMilliseconds))), /* @__PURE__ */ React.createElement("div", null, "Last Occurrence: ", /* @__PURE__ */ React.createElement("i", null, relativeTime(lastEpochMilliseconds))))), /* @__PURE__ */ React.createElement("div", null, e.message), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(JobManifestPodLogs, {
|
|
1507
|
-
account: this.props.manifest.account,
|
|
1508
|
-
location: namespace,
|
|
1509
|
-
podNamesProviders: [new JobEventBasedPodNameProvider(this.props.manifest, e)],
|
|
1510
|
-
linkName: "Console Output (Raw)"
|
|
1511
|
-
})), i !== events.length - 1 && /* @__PURE__ */ React.createElement("br", null));
|
|
1512
|
-
});
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
var css_248z$1 = "dl.manifest-status {\n display: block;\n margin: 0;\n}\ndl.manifest-status dt,\ndl.manifest-status dd {\n display: inline-block;\n}\ndl.manifest-status dt {\n margin-right: 4px;\n}\n.manifest-support-links {\n margin: 0 0 1em;\n}\n.manifest-support-links a {\n margin-right: 2em;\n}\n.manifest-events {\n margin: 0 0 2em;\n}\n";
|
|
1517
|
-
styleInject(css_248z$1);
|
|
1518
|
-
|
|
1519
|
-
function ManifestStatus({ account, manifest }) {
|
|
1520
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("dl", {
|
|
1521
|
-
className: "manifest-status",
|
|
1522
|
-
key: "manifest-status"
|
|
1523
|
-
}, /* @__PURE__ */ React.createElement("dt", null, manifest.manifest.kind), /* @__PURE__ */ React.createElement("dd", null, /* @__PURE__ */ React.createElement(CopyToClipboard, {
|
|
1524
|
-
displayText: true,
|
|
1525
|
-
text: manifest.manifest.metadata.name,
|
|
1526
|
-
toolTip: `Copy ${manifest.manifest.metadata.name}`
|
|
1527
|
-
}), "\xA0", /* @__PURE__ */ React.createElement(DeployManifestStatusPills, {
|
|
1528
|
-
manifest
|
|
1529
|
-
}))), /* @__PURE__ */ React.createElement("div", {
|
|
1530
|
-
className: "manifest-support-links",
|
|
1531
|
-
key: "manifest-support-links"
|
|
1532
|
-
}, /* @__PURE__ */ React.createElement(ManifestYaml, {
|
|
1533
|
-
linkName: "YAML",
|
|
1534
|
-
manifestText: dump(manifest.manifest),
|
|
1535
|
-
modalTitle: manifest.manifest.metadata.name
|
|
1536
|
-
}), /* @__PURE__ */ React.createElement(ManifestDetailsLink, {
|
|
1537
|
-
linkName: "Details",
|
|
1538
|
-
manifest,
|
|
1539
|
-
accountId: account
|
|
1540
|
-
})), /* @__PURE__ */ React.createElement("div", {
|
|
1541
|
-
className: "manifest-events pad-left",
|
|
1542
|
-
key: "manifest-events"
|
|
1543
|
-
}, /* @__PURE__ */ React.createElement(ManifestEvents, {
|
|
1544
|
-
manifest
|
|
1545
|
-
})));
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
const _CloudrunManifestService = class {
|
|
1549
|
-
static subscribe(app, params, fn) {
|
|
1550
|
-
_CloudrunManifestService.updateManifest(params, fn);
|
|
1551
|
-
return app.onRefresh(null, () => _CloudrunManifestService.updateManifest(params, fn));
|
|
1552
|
-
}
|
|
1553
|
-
static updateManifest(params, fn) {
|
|
1554
|
-
ManifestReader.getManifest(params.account, params.location, params.name).then((manifest) => fn(manifest));
|
|
1555
|
-
}
|
|
1556
|
-
static manifestIdentifier(manifest) {
|
|
1557
|
-
const kind = manifest.kind.toLowerCase();
|
|
1558
|
-
const namespace = (manifest.metadata.namespace || "_").toLowerCase();
|
|
1559
|
-
const name = manifest.metadata.name.toLowerCase();
|
|
1560
|
-
const apiVersion = (manifest.apiVersion || "_").toLowerCase();
|
|
1561
|
-
return `${namespace} ${kind} ${apiVersion} ${name}`;
|
|
1562
|
-
}
|
|
1563
|
-
static stageManifestToManifestParams(manifest, account) {
|
|
1564
|
-
return {
|
|
1565
|
-
account,
|
|
1566
|
-
name: _CloudrunManifestService.scopedKind(manifest) + " " + manifest.metadata.name,
|
|
1567
|
-
location: manifest.metadata.namespace == null ? "_" : manifest.metadata.namespace
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
|
-
static apiGroup(manifest) {
|
|
1571
|
-
const parts = (manifest.apiVersion || "_").split("/");
|
|
1572
|
-
if (parts.length < 2) {
|
|
1573
|
-
return "";
|
|
1574
|
-
}
|
|
1575
|
-
return parts[0];
|
|
1576
|
-
}
|
|
1577
|
-
static isCRDGroup(manifest) {
|
|
1578
|
-
return !_CloudrunManifestService.BUILT_IN_GROUPS.includes(_CloudrunManifestService.apiGroup(manifest));
|
|
1579
|
-
}
|
|
1580
|
-
static scopedKind(manifest) {
|
|
1581
|
-
if (_CloudrunManifestService.isCRDGroup(manifest)) {
|
|
1582
|
-
return manifest.kind + "." + _CloudrunManifestService.apiGroup(manifest);
|
|
1583
|
-
}
|
|
1584
|
-
return manifest.kind;
|
|
1585
|
-
}
|
|
1586
|
-
};
|
|
1587
|
-
let CloudrunManifestService = _CloudrunManifestService;
|
|
1588
|
-
CloudrunManifestService.BUILT_IN_GROUPS = [
|
|
1589
|
-
"",
|
|
1590
|
-
"core",
|
|
1591
|
-
"batch",
|
|
1592
|
-
"apps",
|
|
1593
|
-
"extensions",
|
|
1594
|
-
"storage.k8s.io",
|
|
1595
|
-
"apiextensions.k8s.io",
|
|
1596
|
-
"apiregistration.k8s.io",
|
|
1597
|
-
"policy",
|
|
1598
|
-
"scheduling.k8s.io",
|
|
1599
|
-
"settings.k8s.io",
|
|
1600
|
-
"authorization.k8s.io",
|
|
1601
|
-
"authentication.k8s.io",
|
|
1602
|
-
"rbac.authorization.k8s.io",
|
|
1603
|
-
"certifcates.k8s.io",
|
|
1604
|
-
"networking.k8s.io"
|
|
1605
|
-
];
|
|
1606
|
-
|
|
1607
|
-
class DeployStatus extends React.Component {
|
|
1608
|
-
constructor(props) {
|
|
1609
|
-
super(props);
|
|
1610
|
-
this.state = { subscriptions: [], manifestIds: [] };
|
|
1611
|
-
}
|
|
1612
|
-
componentDidMount() {
|
|
1613
|
-
this.componentDidUpdate(this.props, this.state);
|
|
1614
|
-
}
|
|
1615
|
-
componentWillUnmount() {
|
|
1616
|
-
this.unsubscribeAll();
|
|
1617
|
-
}
|
|
1618
|
-
componentDidUpdate(_prevProps, prevState) {
|
|
1619
|
-
const manifests = get(this.props.stage, ["context", "outputs.manifests"], []).filter((m) => !!m);
|
|
1620
|
-
const manifestIds = manifests.map((m) => CloudrunManifestService.manifestIdentifier(m)).sort();
|
|
1621
|
-
if (prevState.manifestIds.join("") !== manifestIds.join("")) {
|
|
1622
|
-
this.unsubscribeAll();
|
|
1623
|
-
const subscriptions = manifests.map((manifest) => {
|
|
1624
|
-
const id = CloudrunManifestService.manifestIdentifier(manifest);
|
|
1625
|
-
return {
|
|
1626
|
-
id,
|
|
1627
|
-
unsubscribe: this.subscribeToManifestUpdates(id, manifest),
|
|
1628
|
-
manifest: this.stageManifestToIManifest(manifest, this.props.stage.context.account)
|
|
1629
|
-
};
|
|
1630
|
-
});
|
|
1631
|
-
this.setState({ subscriptions, manifestIds });
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
|
-
subscribeToManifestUpdates(id, manifest) {
|
|
1635
|
-
const params = CloudrunManifestService.stageManifestToManifestParams(manifest, this.props.stage.context.account);
|
|
1636
|
-
return CloudrunManifestService.subscribe(this.props.application, params, (updated) => {
|
|
1637
|
-
const idx = this.state.subscriptions.findIndex((sub) => sub.id === id);
|
|
1638
|
-
if (idx !== -1) {
|
|
1639
|
-
const subscription = { ...this.state.subscriptions[idx], manifest: updated };
|
|
1640
|
-
const subscriptions = [...this.state.subscriptions];
|
|
1641
|
-
subscriptions[idx] = subscription;
|
|
1642
|
-
this.setState({ subscriptions });
|
|
1643
|
-
}
|
|
1644
|
-
});
|
|
1645
|
-
}
|
|
1646
|
-
unsubscribeAll() {
|
|
1647
|
-
this.state.subscriptions.forEach(({ unsubscribe }) => unsubscribe());
|
|
1648
|
-
}
|
|
1649
|
-
stageManifestToIManifest(manifest, account) {
|
|
1650
|
-
return {
|
|
1651
|
-
name: get(manifest, "metadata.name", ""),
|
|
1652
|
-
moniker: null,
|
|
1653
|
-
account,
|
|
1654
|
-
cloudProvider: "cloudrun",
|
|
1655
|
-
location: get(manifest, "metadata.namespace", ""),
|
|
1656
|
-
manifest,
|
|
1657
|
-
status: {},
|
|
1658
|
-
artifacts: [],
|
|
1659
|
-
events: []
|
|
1660
|
-
};
|
|
1661
|
-
}
|
|
1662
|
-
render() {
|
|
1663
|
-
const { name: sectionName, current: currentSection, stage } = this.props;
|
|
1664
|
-
const manifests = this.state.subscriptions.filter((sub) => !!sub.manifest).map((sub) => sub.manifest);
|
|
1665
|
-
return /* @__PURE__ */ React.createElement(ExecutionDetailsSection, {
|
|
1666
|
-
name: sectionName,
|
|
1667
|
-
current: currentSection
|
|
1668
|
-
}, /* @__PURE__ */ React.createElement(StageFailureMessage, {
|
|
1669
|
-
stage,
|
|
1670
|
-
message: stage.failureMessage
|
|
1671
|
-
}), manifests && /* @__PURE__ */ React.createElement("div", {
|
|
1672
|
-
className: "row"
|
|
1673
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1674
|
-
className: "col-md-12"
|
|
1675
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1676
|
-
className: "well alert alert-info"
|
|
1677
|
-
}, manifests.map((manifest) => {
|
|
1678
|
-
const uid = manifest.manifest.metadata.uid || CloudrunManifestService.manifestIdentifier(manifest.manifest);
|
|
1679
|
-
return /* @__PURE__ */ React.createElement(ManifestStatus, {
|
|
1680
|
-
key: uid,
|
|
1681
|
-
manifest,
|
|
1682
|
-
account: stage.context.account
|
|
1683
|
-
});
|
|
1684
|
-
})))));
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
DeployStatus.title = "deployStatus";
|
|
1688
|
-
|
|
1689
|
-
Registry.pipeline.registerStage({
|
|
1690
|
-
label: "Deploy (Cloud Run)",
|
|
1691
|
-
description: "Deploy a Cloud Run manifest yaml/json file.",
|
|
1692
|
-
key: "deployCloudrunManifest",
|
|
1693
|
-
cloudProvider: "cloudrun",
|
|
1694
|
-
component: DeployStageConfig,
|
|
1695
|
-
executionDetailsSections: [DeployStatus, ExecutionDetailsTasks, ExecutionArtifactTab],
|
|
1696
|
-
producesArtifacts: true,
|
|
1697
|
-
supportsCustomTimeout: true,
|
|
1698
|
-
validators: deployValidators(),
|
|
1699
|
-
accountExtractor: (stage) => stage.account ? [stage.account] : [],
|
|
1700
|
-
configAccountExtractor: (stage) => stage.account ? [stage.account] : [],
|
|
1701
|
-
artifactExtractor: ExpectedArtifactService.accumulateArtifacts(["manifestArtifactId", "requiredArtifactIds"]),
|
|
1702
|
-
artifactRemover: ArtifactReferenceService.removeArtifactFromFields(["manifestArtifactId", "requiredArtifactIds"])
|
|
1703
|
-
});
|
|
1704
|
-
|
|
1705
|
-
const CloudrunProviderSettings = SETTINGS.providers.cloudrun || { defaults: {} };
|
|
1706
|
-
if (CloudrunProviderSettings) {
|
|
1707
|
-
CloudrunProviderSettings.resetToOriginal = SETTINGS.resetProvider("cloudrun");
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
var ServerGroupSource;
|
|
1711
|
-
(function(ServerGroupSource2) {
|
|
1712
|
-
ServerGroupSource2["TEXT"] = "text";
|
|
1713
|
-
ServerGroupSource2["ARTIFACT"] = "artifact";
|
|
1714
|
-
})(ServerGroupSource || (ServerGroupSource = {}));
|
|
1715
|
-
const getSubmitButtonLabel = (mode) => {
|
|
1716
|
-
switch (mode) {
|
|
1717
|
-
case "createPipeline":
|
|
1718
|
-
return "Add";
|
|
1719
|
-
case "editPipeline":
|
|
1720
|
-
return "Done";
|
|
1721
|
-
default:
|
|
1722
|
-
return "Create";
|
|
1723
|
-
}
|
|
1724
|
-
};
|
|
1725
|
-
class CloudrunV2ServerGroupCommandBuilder {
|
|
1726
|
-
buildNewServerGroupCommand(app) {
|
|
1727
|
-
return CloudrunServerGroupCommandBuilder.buildNewServerGroupCommand(app, "cloudrun", "create");
|
|
1728
|
-
}
|
|
1729
|
-
buildNewServerGroupCommandForPipeline(_stage, pipeline) {
|
|
1730
|
-
return CloudrunServerGroupCommandBuilder.buildNewServerGroupCommandForPipeline(_stage, pipeline);
|
|
1731
|
-
}
|
|
1732
|
-
buildServerGroupCommandFromPipeline(app, cluster, _stage, pipeline) {
|
|
1733
|
-
return CloudrunServerGroupCommandBuilder.buildServerGroupCommandFromPipeline(app, cluster, _stage, pipeline);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
const _CloudrunServerGroupCommandBuilder = class {
|
|
1737
|
-
static ServerGroupCommandIsValid(command) {
|
|
1738
|
-
if (!command.moniker) {
|
|
1739
|
-
return false;
|
|
1740
|
-
}
|
|
1741
|
-
if (!command.moniker.app) {
|
|
1742
|
-
return false;
|
|
1743
|
-
}
|
|
1744
|
-
return true;
|
|
1745
|
-
}
|
|
1746
|
-
static copyAndCleanCommand(input) {
|
|
1747
|
-
const command = cloneDeep(input);
|
|
1748
|
-
return command;
|
|
1749
|
-
}
|
|
1750
|
-
static buildNewServerGroupCommandForPipeline(stage, pipeline) {
|
|
1751
|
-
const command = this.buildNewServerGroupCommand({ name: pipeline.application }, "cloudrun", "createPipeline");
|
|
1752
|
-
command.viewState = {
|
|
1753
|
-
...command.viewState,
|
|
1754
|
-
pipeline,
|
|
1755
|
-
requiresTemplateSelection: true,
|
|
1756
|
-
stage
|
|
1757
|
-
};
|
|
1758
|
-
return command;
|
|
1759
|
-
}
|
|
1760
|
-
static getExpectedArtifacts(pipeline) {
|
|
1761
|
-
return pipeline.expectedArtifacts || [];
|
|
1762
|
-
}
|
|
1763
|
-
static buildServerGroupCommandFromPipeline(app, cluster, _stage, pipeline) {
|
|
1764
|
-
return _CloudrunServerGroupCommandBuilder.buildNewServerGroupCommand(app, "cloudrun", "editPipeline").then((command) => {
|
|
1765
|
-
command = {
|
|
1766
|
-
...command,
|
|
1767
|
-
...cluster,
|
|
1768
|
-
backingData: {
|
|
1769
|
-
...command.metadata.backingData.backingData,
|
|
1770
|
-
expectedArtifacts: _CloudrunServerGroupCommandBuilder.getExpectedArtifacts(pipeline)
|
|
1771
|
-
},
|
|
1772
|
-
credentials: cluster.account || command.metadata.backingData.credentials,
|
|
1773
|
-
viewState: {
|
|
1774
|
-
...command.metadata.backingData.viewState,
|
|
1775
|
-
stage: _stage,
|
|
1776
|
-
pipeline
|
|
1777
|
-
}
|
|
1778
|
-
};
|
|
1779
|
-
return command;
|
|
1780
|
-
});
|
|
1781
|
-
}
|
|
1782
|
-
static getCredentials(accounts) {
|
|
1783
|
-
const accountNames = (accounts || []).map((account) => account.name);
|
|
1784
|
-
const defaultCredentials = CloudrunProviderSettings.defaults.account;
|
|
1785
|
-
return accountNames.includes(defaultCredentials) ? defaultCredentials : accountNames[0];
|
|
1786
|
-
}
|
|
1787
|
-
static getRegion(accounts, credentials) {
|
|
1788
|
-
const account = accounts.find((_account) => _account.name === credentials);
|
|
1789
|
-
return account ? account.region : null;
|
|
1790
|
-
}
|
|
1791
|
-
static buildNewServerGroupCommand(app, sourceAccount, mode) {
|
|
1792
|
-
const dataToFetch = {
|
|
1793
|
-
accounts: AccountService.getAllAccountDetailsForProvider("cloudrun"),
|
|
1794
|
-
artifactAccounts: AccountService.getArtifactAccounts()
|
|
1795
|
-
};
|
|
1796
|
-
return $q.all(dataToFetch).then((backingData) => {
|
|
1797
|
-
const { accounts } = backingData;
|
|
1798
|
-
const account = accounts.some((a) => a.name === sourceAccount) ? accounts.find((a) => a.name === sourceAccount).name : accounts.length ? accounts[0].name : null;
|
|
1799
|
-
const viewState = {
|
|
1800
|
-
mode,
|
|
1801
|
-
submitButtonLabel: getSubmitButtonLabel(mode),
|
|
1802
|
-
disableStrategySelection: mode === "create"
|
|
1803
|
-
};
|
|
1804
|
-
const credentials = account ? account : this.getCredentials(accounts);
|
|
1805
|
-
const region = this.getRegion(backingData.accounts, credentials);
|
|
1806
|
-
const cloudProvider = "cloudrun";
|
|
1807
|
-
return {
|
|
1808
|
-
command: {
|
|
1809
|
-
application: app.name,
|
|
1810
|
-
configFiles: [""],
|
|
1811
|
-
cloudProvider,
|
|
1812
|
-
selectedProvider: cloudProvider,
|
|
1813
|
-
provider: cloudProvider,
|
|
1814
|
-
region,
|
|
1815
|
-
credentials,
|
|
1816
|
-
gitCredentialType: "NONE",
|
|
1817
|
-
manifest: null,
|
|
1818
|
-
sourceType: "git",
|
|
1819
|
-
configArtifacts: [],
|
|
1820
|
-
interestingHealthProviderNames: [],
|
|
1821
|
-
fromArtifact: false,
|
|
1822
|
-
account,
|
|
1823
|
-
viewState
|
|
1824
|
-
},
|
|
1825
|
-
metadata: {
|
|
1826
|
-
backingData
|
|
1827
|
-
}
|
|
1828
|
-
};
|
|
1829
|
-
});
|
|
1830
|
-
}
|
|
1831
|
-
};
|
|
1832
|
-
let CloudrunServerGroupCommandBuilder = _CloudrunServerGroupCommandBuilder;
|
|
1833
|
-
CloudrunServerGroupCommandBuilder.$inject = ["$q"];
|
|
1834
|
-
const CLOUDRUN_SERVER_GROUP_COMMAND_BUILDER = "spinnaker.cloudrun.serverGroup.commandBuilder.service";
|
|
1835
|
-
module(CLOUDRUN_SERVER_GROUP_COMMAND_BUILDER, []).service("cloudrunV2ServerGroupCommandBuilder", CloudrunV2ServerGroupCommandBuilder);
|
|
1836
|
-
|
|
1837
|
-
function ServerGroupBasicSettings({
|
|
1838
|
-
accounts,
|
|
1839
|
-
onAccountSelect,
|
|
1840
|
-
selectedAccount,
|
|
1841
|
-
formik,
|
|
1842
|
-
onEnterStack,
|
|
1843
|
-
detailsChanged,
|
|
1844
|
-
app
|
|
1845
|
-
}) {
|
|
1846
|
-
const { values } = formik;
|
|
1847
|
-
const { stack = "", freeFormDetails } = values;
|
|
1848
|
-
const namePreview = NameUtils.getClusterName(app.name, stack, freeFormDetails);
|
|
1849
|
-
const createsNewCluster = !app.clusters.find((c) => c.name === namePreview);
|
|
1850
|
-
const inCluster = app.serverGroups.data.filter((serverGroup) => {
|
|
1851
|
-
return serverGroup.cluster === namePreview && serverGroup.account === values.command.credentials && serverGroup.region === values.command.region;
|
|
1852
|
-
}).sort((a, b) => a.createdTime - b.createdTime);
|
|
1853
|
-
const latestServerGroup = inCluster.length ? inCluster.pop() : null;
|
|
1854
|
-
const navigateToLatestServerGroup = () => {
|
|
1855
|
-
const { values: values2 } = formik;
|
|
1856
|
-
const params = {
|
|
1857
|
-
provider: values2.command.selectedProvider,
|
|
1858
|
-
accountId: latestServerGroup.account,
|
|
1859
|
-
region: latestServerGroup.region,
|
|
1860
|
-
serverGroup: latestServerGroup.name
|
|
1861
|
-
};
|
|
1862
|
-
const { $state } = ReactInjector;
|
|
1863
|
-
if ($state.is("home.applications.application.insight.clusters")) {
|
|
1864
|
-
$state.go(".serverGroup", params);
|
|
1865
|
-
} else {
|
|
1866
|
-
$state.go("^.serverGroup", params);
|
|
1867
|
-
}
|
|
1868
|
-
};
|
|
1869
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
1870
|
-
className: "form-horizontal"
|
|
1871
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1872
|
-
className: "form-group"
|
|
1873
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1874
|
-
className: "col-md-3 sm-label-right"
|
|
1875
|
-
}, "Account"), /* @__PURE__ */ React.createElement("div", {
|
|
1876
|
-
className: "col-md-7"
|
|
1877
|
-
}, /* @__PURE__ */ React.createElement(AccountSelectInput, {
|
|
1878
|
-
value: selectedAccount,
|
|
1879
|
-
onChange: (evt) => onAccountSelect(evt.target.value),
|
|
1880
|
-
readOnly: false,
|
|
1881
|
-
accounts,
|
|
1882
|
-
provider: "cloudrun"
|
|
1883
|
-
}))), /* @__PURE__ */ React.createElement("div", {
|
|
1884
|
-
className: "form-group"
|
|
1885
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1886
|
-
className: "col-md-3 sm-label-right"
|
|
1887
|
-
}, "Stack ", /* @__PURE__ */ React.createElement(HelpField, {
|
|
1888
|
-
id: "cloudrun.serverGroup.stack"
|
|
1889
|
-
})), /* @__PURE__ */ React.createElement("div", {
|
|
1890
|
-
className: "col-md-7"
|
|
1891
|
-
}, /* @__PURE__ */ React.createElement("input", {
|
|
1892
|
-
type: "text",
|
|
1893
|
-
className: "form-control input-sm no-spel",
|
|
1894
|
-
value: stack,
|
|
1895
|
-
onChange: (e) => onEnterStack(e.target.value)
|
|
1896
|
-
}))), /* @__PURE__ */ React.createElement("div", {
|
|
1897
|
-
className: "form-group"
|
|
1898
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1899
|
-
className: "col-md-3 sm-label-right"
|
|
1900
|
-
}, "Detail ", /* @__PURE__ */ React.createElement(HelpField, {
|
|
1901
|
-
id: "cloudrun.serverGroup.detail"
|
|
1902
|
-
})), /* @__PURE__ */ React.createElement("div", {
|
|
1903
|
-
className: "col-md-7"
|
|
1904
|
-
}, /* @__PURE__ */ React.createElement("input", {
|
|
1905
|
-
type: "text",
|
|
1906
|
-
className: "form-control input-sm no-spel",
|
|
1907
|
-
value: freeFormDetails,
|
|
1908
|
-
onChange: (e) => detailsChanged(e.target.value)
|
|
1909
|
-
}))), !values.command.viewState.hideClusterNamePreview && /* @__PURE__ */ React.createElement(ServerGroupNamePreview$1, {
|
|
1910
|
-
createsNewCluster,
|
|
1911
|
-
latestServerGroupName: latestServerGroup == null ? void 0 : latestServerGroup.name,
|
|
1912
|
-
mode: values.command.viewState.mode,
|
|
1913
|
-
namePreview,
|
|
1914
|
-
navigateToLatestServerGroup
|
|
1915
|
-
}));
|
|
1916
|
-
}
|
|
1917
|
-
class WizardServerGroupBasicSettings extends React.Component {
|
|
1918
|
-
constructor() {
|
|
1919
|
-
super(...arguments);
|
|
1920
|
-
this.accountUpdated = (account) => {
|
|
1921
|
-
const { formik } = this.props;
|
|
1922
|
-
formik.values.command.account = account;
|
|
1923
|
-
formik.setFieldValue("account", account);
|
|
1924
|
-
};
|
|
1925
|
-
this.stackChanged = (stack) => {
|
|
1926
|
-
const { setFieldValue, values } = this.props.formik;
|
|
1927
|
-
values.command.stack = stack;
|
|
1928
|
-
setFieldValue("stack", stack);
|
|
1929
|
-
};
|
|
1930
|
-
this.freeFormDetailsChanged = (freeFormDetails) => {
|
|
1931
|
-
const { setFieldValue, values } = this.props.formik;
|
|
1932
|
-
values.command.freeFormDetails = freeFormDetails;
|
|
1933
|
-
setFieldValue("freeFormDetails", freeFormDetails);
|
|
1934
|
-
};
|
|
1935
|
-
}
|
|
1936
|
-
render() {
|
|
1937
|
-
var _a, _b, _c;
|
|
1938
|
-
const { formik, app } = this.props;
|
|
1939
|
-
return /* @__PURE__ */ React.createElement(ServerGroupBasicSettings, {
|
|
1940
|
-
accounts: ((_b = (_a = formik.values.metadata) == null ? void 0 : _a.backingData) == null ? void 0 : _b.accounts) || [],
|
|
1941
|
-
onAccountSelect: this.accountUpdated,
|
|
1942
|
-
selectedAccount: ((_c = formik.values.command) == null ? void 0 : _c.account) || "",
|
|
1943
|
-
onEnterStack: this.stackChanged,
|
|
1944
|
-
formik,
|
|
1945
|
-
detailsChanged: this.freeFormDetailsChanged,
|
|
1946
|
-
app
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1949
|
-
}
|
|
1950
|
-
|
|
1951
|
-
function ServerGroupConfigFilesSettings({ configFiles, onEnterConfig }) {
|
|
1952
|
-
const [configValues, setConfigValues] = useState(configFiles);
|
|
1953
|
-
function mapTabToSpaces(event, i) {
|
|
1954
|
-
if (event.which === 9) {
|
|
1955
|
-
event.preventDefault();
|
|
1956
|
-
const cursorPosition = event.target.selectionStart;
|
|
1957
|
-
const inputValue = event.target.value;
|
|
1958
|
-
event.target.value = `${inputValue.substring(0, cursorPosition)} ${inputValue.substring(cursorPosition)}`;
|
|
1959
|
-
event.target.selectionStart += 2;
|
|
1960
|
-
}
|
|
1961
|
-
const newConfigValues = [...configValues];
|
|
1962
|
-
newConfigValues[i] = event.target.value;
|
|
1963
|
-
setConfigValues(newConfigValues);
|
|
1964
|
-
onEnterConfig(newConfigValues);
|
|
1965
|
-
}
|
|
1966
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
1967
|
-
className: "form-horizontal"
|
|
1968
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
1969
|
-
className: "form-group"
|
|
1970
|
-
}, configValues.map((configFile, index) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
|
1971
|
-
className: "col-md-3 sm-label-right"
|
|
1972
|
-
}, "Service Yaml", /* @__PURE__ */ React.createElement(HelpField, {
|
|
1973
|
-
id: "cloudrun.serverGroup.configFiles"
|
|
1974
|
-
}), " "), /* @__PURE__ */ React.createElement("div", {
|
|
1975
|
-
className: "col-md-8",
|
|
1976
|
-
key: index
|
|
1977
|
-
}, /* @__PURE__ */ React.createElement(TextAreaInput, {
|
|
1978
|
-
name: "text" + index,
|
|
1979
|
-
value: configFile,
|
|
1980
|
-
rows: 10,
|
|
1981
|
-
onChange: (e) => mapTabToSpaces(e, index)
|
|
1982
|
-
}))))));
|
|
1983
|
-
}
|
|
1984
|
-
class WizardServerGroupConfigFilesSettings extends React.Component {
|
|
1985
|
-
constructor() {
|
|
1986
|
-
super(...arguments);
|
|
1987
|
-
this.configUpdated = (configFiles) => {
|
|
1988
|
-
const { formik } = this.props;
|
|
1989
|
-
formik.values.command.configFiles = configFiles;
|
|
1990
|
-
formik.setFieldValue("configFiles", configFiles);
|
|
1991
|
-
};
|
|
1992
|
-
}
|
|
1993
|
-
render() {
|
|
1994
|
-
const { formik } = this.props;
|
|
1995
|
-
return /* @__PURE__ */ React.createElement(ServerGroupConfigFilesSettings, {
|
|
1996
|
-
configFiles: formik.values.configFiles || formik.values.command.configFiles,
|
|
1997
|
-
onEnterConfig: this.configUpdated
|
|
1998
|
-
});
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
const _ServerGroupWizard = class extends React.Component {
|
|
2003
|
-
constructor(props) {
|
|
2004
|
-
super(props);
|
|
2005
|
-
this._isUnmounted = false;
|
|
2006
|
-
this.onTaskComplete = () => {
|
|
2007
|
-
this.props.application.serverGroups.refresh();
|
|
2008
|
-
this.props.application.serverGroups.onNextRefresh(null, this.onApplicationRefresh);
|
|
2009
|
-
};
|
|
2010
|
-
this.onApplicationRefresh = () => {
|
|
2011
|
-
if (this._isUnmounted) {
|
|
2012
|
-
return;
|
|
2013
|
-
}
|
|
2014
|
-
const { command } = this.props;
|
|
2015
|
-
const { taskMonitor } = this.state;
|
|
2016
|
-
const cloneStage = taskMonitor.task.execution.stages.find((stage) => stage.type === "cloneServerGroup");
|
|
2017
|
-
if (cloneStage && cloneStage.context["deploy.server.groups"]) {
|
|
2018
|
-
const newServerGroupName = cloneStage.context["deploy.server.groups"][command.command.region];
|
|
2019
|
-
if (newServerGroupName) {
|
|
2020
|
-
const newStateParams = {
|
|
2021
|
-
serverGroup: newServerGroupName,
|
|
2022
|
-
accountId: command.command.credentials,
|
|
2023
|
-
region: command.command.region,
|
|
2024
|
-
provider: "cloudrun"
|
|
2025
|
-
};
|
|
2026
|
-
let transitionTo = "^.^.^.clusters.serverGroup";
|
|
2027
|
-
if (ReactInjector.$state.includes("**.clusters.serverGroup")) {
|
|
2028
|
-
transitionTo = "^.serverGroup";
|
|
2029
|
-
}
|
|
2030
|
-
if (ReactInjector.$state.includes("**.clusters.cluster.serverGroup")) {
|
|
2031
|
-
transitionTo = "^.^.serverGroup";
|
|
2032
|
-
}
|
|
2033
|
-
if (ReactInjector.$state.includes("**.clusters")) {
|
|
2034
|
-
transitionTo = ".serverGroup";
|
|
2035
|
-
}
|
|
2036
|
-
ReactInjector.$state.go(transitionTo, newStateParams);
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
};
|
|
2040
|
-
this.submit = (c) => {
|
|
2041
|
-
const command = CloudrunServerGroupCommandBuilder.copyAndCleanCommand(c.command);
|
|
2042
|
-
const forPipelineConfig = command.viewState.mode === "editPipeline" || command.viewState.mode === "createPipeline";
|
|
2043
|
-
if (forPipelineConfig) {
|
|
2044
|
-
this.props.closeModal && this.props.closeModal(command);
|
|
2045
|
-
} else {
|
|
2046
|
-
const submitMethod = () => ReactInjector.serverGroupWriter.cloneServerGroup(command, this.props.application);
|
|
2047
|
-
this.state.taskMonitor.submit(submitMethod);
|
|
2048
|
-
return null;
|
|
2049
|
-
}
|
|
2050
|
-
};
|
|
2051
|
-
if (!props.command) {
|
|
2052
|
-
CloudrunServerGroupCommandBuilder.buildNewServerGroupCommand(props.application, "cloudrun", "create").then((command) => {
|
|
2053
|
-
Object.assign(this.state.command, command);
|
|
2054
|
-
this.setState({ loaded: true });
|
|
2055
|
-
});
|
|
2056
|
-
}
|
|
2057
|
-
this.state = {
|
|
2058
|
-
loaded: !!props.command,
|
|
2059
|
-
command: props.command || {},
|
|
2060
|
-
taskMonitor: new TaskMonitor({
|
|
2061
|
-
application: props.application,
|
|
2062
|
-
title: `${props.command.command.viewState.submitButtonLabel === "Create" ? "Creating" : "Updating"} your Server Group`,
|
|
2063
|
-
modalInstance: TaskMonitor.modalInstanceEmulation(() => this.props.dismissModal()),
|
|
2064
|
-
onTaskComplete: this.onTaskComplete
|
|
2065
|
-
})
|
|
2066
|
-
};
|
|
2067
|
-
}
|
|
2068
|
-
static show(props) {
|
|
2069
|
-
const modalProps = { dialogClassName: "wizard-modal modal-lg" };
|
|
2070
|
-
return ReactModal.show(_ServerGroupWizard, props, modalProps);
|
|
2071
|
-
}
|
|
2072
|
-
render() {
|
|
2073
|
-
const { dismissModal, application } = this.props;
|
|
2074
|
-
const { loaded, taskMonitor, command } = this.state;
|
|
2075
|
-
const labelButton = this.state.command.command.viewState.submitButtonLabel;
|
|
2076
|
-
return /* @__PURE__ */ React.createElement(WizardModal, {
|
|
2077
|
-
heading: `${labelButton === "Add" || labelButton === "Create" ? "Create New" : "Update"} Server Group`,
|
|
2078
|
-
initialValues: command,
|
|
2079
|
-
loading: !loaded,
|
|
2080
|
-
taskMonitor,
|
|
2081
|
-
dismissModal,
|
|
2082
|
-
closeModal: this.submit,
|
|
2083
|
-
submitButtonLabel: labelButton,
|
|
2084
|
-
render: ({ formik, nextIdx, wizard }) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(WizardPage, {
|
|
2085
|
-
label: "Basic Settings",
|
|
2086
|
-
wizard,
|
|
2087
|
-
order: nextIdx(),
|
|
2088
|
-
render: ({ innerRef }) => /* @__PURE__ */ React.createElement(WizardServerGroupBasicSettings, {
|
|
2089
|
-
ref: innerRef,
|
|
2090
|
-
formik,
|
|
2091
|
-
app: application
|
|
2092
|
-
})
|
|
2093
|
-
}), /* @__PURE__ */ React.createElement(WizardPage, {
|
|
2094
|
-
label: "Service Yaml",
|
|
2095
|
-
wizard,
|
|
2096
|
-
order: nextIdx(),
|
|
2097
|
-
render: ({ innerRef }) => /* @__PURE__ */ React.createElement(WizardServerGroupConfigFilesSettings, {
|
|
2098
|
-
ref: innerRef,
|
|
2099
|
-
formik
|
|
2100
|
-
})
|
|
2101
|
-
}))
|
|
2102
|
-
});
|
|
2103
|
-
}
|
|
2104
|
-
};
|
|
2105
|
-
let ServerGroupWizard = _ServerGroupWizard;
|
|
2106
|
-
ServerGroupWizard.defaultProps = {
|
|
2107
|
-
closeModal: noop,
|
|
2108
|
-
dismissModal: noop
|
|
2109
|
-
};
|
|
2110
|
-
|
|
2111
|
-
class CloudrunHealth {
|
|
2112
|
-
}
|
|
2113
|
-
CloudrunHealth.PLATFORM = "Cloud Run Service";
|
|
2114
|
-
|
|
2115
|
-
class CloudrunServerGroupDetailsController {
|
|
2116
|
-
constructor($state, $scope, serverGroup, app, serverGroupWriter) {
|
|
2117
|
-
this.$state = $state;
|
|
2118
|
-
this.$scope = $scope;
|
|
2119
|
-
this.app = app;
|
|
2120
|
-
this.serverGroupWriter = serverGroupWriter;
|
|
2121
|
-
this.state = { loading: true };
|
|
2122
|
-
this.extractServerGroup(serverGroup).then(() => {
|
|
2123
|
-
if (!this.$scope.$$destroyed) {
|
|
2124
|
-
this.app.getDataSource("serverGroups").onRefresh(this.$scope, () => this.extractServerGroup(serverGroup));
|
|
2125
|
-
}
|
|
2126
|
-
}).catch(() => this.autoClose());
|
|
2127
|
-
}
|
|
2128
|
-
canDestroyServerGroup() {
|
|
2129
|
-
if (this.serverGroup) {
|
|
2130
|
-
const isCurrentRevision = this.serverGroup.tags.isLatest;
|
|
2131
|
-
if (isCurrentRevision) {
|
|
2132
|
-
return false;
|
|
2133
|
-
} else if (this.serverGroup.disabled) {
|
|
2134
|
-
return true;
|
|
2135
|
-
} else {
|
|
2136
|
-
return false;
|
|
2137
|
-
}
|
|
2138
|
-
} else {
|
|
2139
|
-
return false;
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
destroyServerGroup() {
|
|
2143
|
-
const stateParams = {
|
|
2144
|
-
name: this.serverGroup.name,
|
|
2145
|
-
accountId: this.serverGroup.account,
|
|
2146
|
-
region: this.serverGroup.region
|
|
2147
|
-
};
|
|
2148
|
-
const taskMonitor = {
|
|
2149
|
-
application: this.app,
|
|
2150
|
-
title: "Destroying " + this.serverGroup.name,
|
|
2151
|
-
onTaskComplete: () => {
|
|
2152
|
-
if (this.$state.includes("**.serverGroup", stateParams)) {
|
|
2153
|
-
this.$state.go("^");
|
|
2154
|
-
}
|
|
2155
|
-
}
|
|
2156
|
-
};
|
|
2157
|
-
const submitMethod = (params) => this.serverGroupWriter.destroyServerGroup(this.serverGroup, this.app, params);
|
|
2158
|
-
const confirmationModalParams = {
|
|
2159
|
-
header: "Really destroy " + this.serverGroup.name + "?",
|
|
2160
|
-
buttonText: "Destroy " + this.serverGroup.name,
|
|
2161
|
-
account: this.serverGroup.account,
|
|
2162
|
-
taskMonitorConfig: taskMonitor,
|
|
2163
|
-
submitMethod,
|
|
2164
|
-
askForReason: true,
|
|
2165
|
-
platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,
|
|
2166
|
-
platformHealthType: CloudrunHealth.PLATFORM,
|
|
2167
|
-
interestingHealthProviderNames: []
|
|
2168
|
-
};
|
|
2169
|
-
if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {
|
|
2170
|
-
confirmationModalParams.interestingHealthProviderNames = [CloudrunHealth.PLATFORM];
|
|
2171
|
-
}
|
|
2172
|
-
ConfirmationModalService.confirm(confirmationModalParams);
|
|
2173
|
-
}
|
|
2174
|
-
autoClose() {
|
|
2175
|
-
if (this.$scope.$$destroyed) {
|
|
2176
|
-
return;
|
|
2177
|
-
} else {
|
|
2178
|
-
this.$state.params.allowModalToStayOpen = true;
|
|
2179
|
-
this.$state.go("^", null, { location: "replace" });
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
extractServerGroup({ name, accountId, region }) {
|
|
2183
|
-
return ServerGroupReader.getServerGroup(this.app.name, accountId, region, name).then((serverGroupDetails) => {
|
|
2184
|
-
let fromApp = this.app.getDataSource("serverGroups").data.find((toCheck) => {
|
|
2185
|
-
return toCheck.name === name && toCheck.account === accountId && toCheck.region === region;
|
|
2186
|
-
});
|
|
2187
|
-
if (!fromApp) {
|
|
2188
|
-
this.app.getDataSource("loadBalancers").data.some((loadBalancer) => {
|
|
2189
|
-
if (loadBalancer.account === accountId) {
|
|
2190
|
-
return loadBalancer.serverGroups.some((toCheck) => {
|
|
2191
|
-
let result = false;
|
|
2192
|
-
if (toCheck.name === name) {
|
|
2193
|
-
fromApp = toCheck;
|
|
2194
|
-
result = true;
|
|
2195
|
-
}
|
|
2196
|
-
return result;
|
|
2197
|
-
});
|
|
2198
|
-
} else {
|
|
2199
|
-
return false;
|
|
2200
|
-
}
|
|
2201
|
-
});
|
|
2202
|
-
}
|
|
2203
|
-
this.serverGroup = { ...serverGroupDetails, ...fromApp };
|
|
2204
|
-
this.state.loading = false;
|
|
2205
|
-
});
|
|
2206
|
-
}
|
|
2207
|
-
}
|
|
2208
|
-
CloudrunServerGroupDetailsController.$inject = ["$state", "$scope", "serverGroup", "app", "serverGroupWriter"];
|
|
2209
|
-
const CLOUDRUN_SERVER_GROUP_DETAILS_CTRL = "spinnaker.cloudrun.serverGroup.details.controller";
|
|
2210
|
-
module(CLOUDRUN_SERVER_GROUP_DETAILS_CTRL, [SERVER_GROUP_WRITER]).controller("cloudrunV2ServerGroupDetailsCtrl", CloudrunServerGroupDetailsController);
|
|
2211
|
-
|
|
2212
|
-
class CloudrunV2ServerGroupTransformer {
|
|
2213
|
-
constructor($q) {
|
|
2214
|
-
this.$q = $q;
|
|
2215
|
-
}
|
|
2216
|
-
normalizeServerGroup(serverGroup) {
|
|
2217
|
-
return this.$q.resolve(serverGroup);
|
|
2218
|
-
}
|
|
2219
|
-
convertServerGroupCommandToDeployConfiguration(command) {
|
|
2220
|
-
return new CloudrunDeployDescription(command);
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
|
-
CloudrunV2ServerGroupTransformer.$inject = ["$q"];
|
|
2224
|
-
class CloudrunDeployDescription {
|
|
2225
|
-
constructor(command) {
|
|
2226
|
-
this.cloudProvider = "cloudrun";
|
|
2227
|
-
this.provider = "cloudrun";
|
|
2228
|
-
this.credentials = command.credentials;
|
|
2229
|
-
this.account = command.credentials;
|
|
2230
|
-
this.application = command.application;
|
|
2231
|
-
this.stack = command.stack;
|
|
2232
|
-
this.freeFormDetails = command.freeFormDetails;
|
|
2233
|
-
this.region = command.region;
|
|
2234
|
-
this.strategy = command.strategy;
|
|
2235
|
-
this.type = command.type;
|
|
2236
|
-
this.fromArtifact = command.fromArtifact;
|
|
2237
|
-
this.gitCredentialType = command.gitCredentialType;
|
|
2238
|
-
this.configFiles = command.configFiles;
|
|
2239
|
-
this.sourceType = command.sourceType;
|
|
2240
|
-
this.interestingHealthProviderNames = command.interestingHealthProviderNames || [];
|
|
2241
|
-
this.configArtifacts = [];
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2244
|
-
const CLOUDRUN_SERVER_GROUP_TRANSFORMER = "spinnaker.cloudrun.serverGroup.transformer.service";
|
|
2245
|
-
module(CLOUDRUN_SERVER_GROUP_TRANSFORMER, []).service("cloudrunV2ServerGroupTransformer", CloudrunV2ServerGroupTransformer);
|
|
2246
|
-
|
|
2247
|
-
var css_248z = ".cloud-provider-logo .icon-cloudrun {\n -webkit-mask-image: url(\"data:image/svg+xml,%3Csvg width%3D%2224px%22 height%3D%2224px%22 viewBox%3D%220 0 24 24%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cdefs%3E %3Cstyle%3E .cls-1 %7B fill%3A %23aecbfa%3B %7D .cls-1%2C .cls-2 %7B fill-rule%3A evenodd%3B %7D .cls-2 %7B fill%3A %234285f4%3B %7D %3C%2Fstyle%3E %3C%2Fdefs%3E %3Ctitle%3EIcon_24px_CloudRun_Color%3C%2Ftitle%3E %3Cg data-name%3D%22Product Icons%22%3E %3Cg%3E %3Cpolygon class%3D%22cls-1%22 points%3D%228.9 2.63 12.02 12 21.38 12 8.9 2.63%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%2221.38 12 12.02 12 8.9 21.38 21.38 12%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%223.44 21.38 6.57 19.81 8.9 12 5.78 12 3.44 21.38%22 %2F%3E %3Cpolygon class%3D%22cls-1%22 points%3D%223.44 2.63 5.78 12 8.9 12 6.57 4.19 3.44 2.63%22 %2F%3E %3C%2Fg%3E %3C%2Fg%3E%3C%2Fsvg%3E\");\n mask-image: url(\"data:image/svg+xml,%3Csvg width%3D%2224px%22 height%3D%2224px%22 viewBox%3D%220 0 24 24%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cdefs%3E %3Cstyle%3E .cls-1 %7B fill%3A %23aecbfa%3B %7D .cls-1%2C .cls-2 %7B fill-rule%3A evenodd%3B %7D .cls-2 %7B fill%3A %234285f4%3B %7D %3C%2Fstyle%3E %3C%2Fdefs%3E %3Ctitle%3EIcon_24px_CloudRun_Color%3C%2Ftitle%3E %3Cg data-name%3D%22Product Icons%22%3E %3Cg%3E %3Cpolygon class%3D%22cls-1%22 points%3D%228.9 2.63 12.02 12 21.38 12 8.9 2.63%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%2221.38 12 12.02 12 8.9 21.38 21.38 12%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%223.44 21.38 6.57 19.81 8.9 12 5.78 12 3.44 21.38%22 %2F%3E %3Cpolygon class%3D%22cls-1%22 points%3D%223.44 2.63 5.78 12 8.9 12 6.57 4.19 3.44 2.63%22 %2F%3E %3C%2Fg%3E %3C%2Fg%3E%3C%2Fsvg%3E\");\n background-color: #4285f4;\n}\n";
|
|
2248
|
-
styleInject(css_248z);
|
|
2249
|
-
|
|
2250
|
-
const CLOUDRUN_MODULE = "spinnaker.cloudrun";
|
|
2251
|
-
const requires = [
|
|
2252
|
-
CLOUDRUN_COMPONENT_URL_DETAILS,
|
|
2253
|
-
CLOUDRUN_SERVER_GROUP_COMMAND_BUILDER,
|
|
2254
|
-
CLOUDRUN_SERVER_GROUP_DETAILS_CTRL,
|
|
2255
|
-
CLOUDRUN_SERVER_GROUP_TRANSFORMER,
|
|
2256
|
-
CLOUDRUN_LOAD_BALANCER_TRANSFORMER,
|
|
2257
|
-
CLOUDRUN_LOAD_BALANCER_DETAILS_CTRL,
|
|
2258
|
-
CLOUDRUN_LOAD_BALANCER_WIZARD_CTRL,
|
|
2259
|
-
CLOUDRUN_LOAD_BALANCER_CREATE_MESSAGE,
|
|
2260
|
-
CLOUDRUN_ALLOCATION_CONFIGURATION_ROW,
|
|
2261
|
-
CLOUDRUN_LOAD_BALANCER_BASIC_SETTINGS,
|
|
2262
|
-
CLOUDRUN_STAGE_ALLOCATION_CONFIGURATION_ROW,
|
|
2263
|
-
CLOUDRUN_PIPELINE_MODULE,
|
|
2264
|
-
CLOUDRUN_INSTANCE_DETAILS_CTRL
|
|
2265
|
-
];
|
|
2266
|
-
module(CLOUDRUN_MODULE, requires).config(() => {
|
|
2267
|
-
CloudProviderRegistry.registerProvider("cloudrun", {
|
|
2268
|
-
name: "cloudrun",
|
|
2269
|
-
logo: {
|
|
2270
|
-
path: logo
|
|
2271
|
-
},
|
|
2272
|
-
instance: {
|
|
2273
|
-
detailsTemplateUrl: "cloudrun/src/instance/details/details.html",
|
|
2274
|
-
detailsController: "cloudrunInstanceDetailsCtrl"
|
|
2275
|
-
},
|
|
2276
|
-
serverGroup: {
|
|
2277
|
-
CloneServerGroupModal: ServerGroupWizard,
|
|
2278
|
-
commandBuilder: "cloudrunV2ServerGroupCommandBuilder",
|
|
2279
|
-
detailsController: "cloudrunV2ServerGroupDetailsCtrl",
|
|
2280
|
-
detailsTemplateUrl: "cloudrun/src/serverGroup/details/details.html",
|
|
2281
|
-
transformer: "cloudrunV2ServerGroupTransformer",
|
|
2282
|
-
skipUpstreamStageCheck: true
|
|
2283
|
-
},
|
|
2284
|
-
loadBalancer: {
|
|
2285
|
-
transformer: "cloudrunLoadBalancerTransformer",
|
|
2286
|
-
createLoadBalancerTemplateUrl: "cloudrun/src/loadBalancer/configure/wizard/wizard.html",
|
|
2287
|
-
createLoadBalancerController: "cloudrunLoadBalancerWizardCtrl",
|
|
2288
|
-
detailsTemplateUrl: "cloudrun/src/loadBalancer/details/details.html",
|
|
2289
|
-
detailsController: "cloudrunLoadBalancerDetailsCtrl"
|
|
2290
|
-
}
|
|
2291
|
-
});
|
|
2292
|
-
});
|
|
2293
|
-
DeploymentStrategyRegistry.registerProvider("cloudrun", ["custom", "redblack", "rollingpush", "rollingredblack"]);
|
|
2294
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
2295
|
-
templateCache.put("cloudrun/src/instance/details/details.html", `<div class="details-panel">
|
|
2296
|
-
<div class="header">
|
|
2297
|
-
<instance-details-header
|
|
2298
|
-
health-state="ctrl.instance.healthState"
|
|
2299
|
-
instance-id="ctrl.instance ? ctrl.instance.name : ctrl.instanceIdNotFound"
|
|
2300
|
-
loading="ctrl.state.loading"
|
|
2301
|
-
standalone="false"
|
|
2302
|
-
></instance-details-header>
|
|
2303
|
-
<div ng-if="!ctrl.state.loading">
|
|
2304
|
-
<div class="actions">
|
|
2305
|
-
<div class="dropdown" uib-dropdown dropdown-append-to-body>
|
|
2306
|
-
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>
|
|
2307
|
-
Instance Actions <span class="caret"></span>
|
|
2308
|
-
</button>
|
|
2309
|
-
</div>
|
|
2310
|
-
</div>
|
|
2311
|
-
</div>
|
|
2312
|
-
</div>
|
|
2313
|
-
<div class="content" ng-if="!ctrl.state.loading && ctrl.instance">
|
|
2314
|
-
<collapsible-section heading="Instance Information" expanded="true">
|
|
2315
|
-
<dl class="dl-horizontal dl-narrow">
|
|
2316
|
-
<dt>Launched</dt>
|
|
2317
|
-
<dd ng-if="ctrl.instance.launchTime">{{ctrl.instance.launchTime | timestamp}}</dd>
|
|
2318
|
-
<dt>In</dt>
|
|
2319
|
-
<dd><account-tag account="ctrl.instance.account" pad="right"></account-tag>{{}}</dd>
|
|
2320
|
-
<dt ng-if="ctrl.instance.serverGroup">Server Group</dt>
|
|
2321
|
-
<dd ng-if="ctrl.instance.serverGroup">
|
|
2322
|
-
<a
|
|
2323
|
-
ui-sref="^.serverGroup({region: ctrl.instance.region,
|
|
2324
|
-
accountId: ctrl.instance.account,
|
|
2325
|
-
serverGroup: ctrl.instance.serverGroup,
|
|
2326
|
-
provider: 'cloudrun'})"
|
|
2327
|
-
>{{ctrl.instance.serverGroup}}</a
|
|
2328
|
-
>
|
|
2329
|
-
</dd>
|
|
2330
|
-
<dt>Region</dt>
|
|
2331
|
-
<dd>{{ctrl.instance.region}}</dd>
|
|
2332
|
-
<cloudrun-conditional-dt-dd
|
|
2333
|
-
component="ctrl.instance"
|
|
2334
|
-
key="vmZoneName"
|
|
2335
|
-
label="Zone"
|
|
2336
|
-
></cloudrun-conditional-dt-dd>
|
|
2337
|
-
</dl>
|
|
2338
|
-
</collapsible-section>
|
|
2339
|
-
<collapsible-section heading="Status" expanded="true">
|
|
2340
|
-
<dl>
|
|
2341
|
-
<dt>Load Balancer</dt>
|
|
2342
|
-
<dd>
|
|
2343
|
-
<span
|
|
2344
|
-
class="pull-left"
|
|
2345
|
-
uib-tooltip="{{ctrl.instance.healthState === 'Up' ? ctrl.upToolTip : ctrl.outOfServiceToolTip}}"
|
|
2346
|
-
tooltip-placement="right"
|
|
2347
|
-
>
|
|
2348
|
-
<span class="glyphicon glyphicon-{{ctrl.instance.healthState}}-triangle"></span>
|
|
2349
|
-
{{ctrl.instance.loadBalancers[0]}}
|
|
2350
|
-
</span>
|
|
2351
|
-
</dd>
|
|
2352
|
-
</dl>
|
|
2353
|
-
</collapsible-section>
|
|
2354
|
-
</div>
|
|
2355
|
-
<div class="content" ng-if="!ctrl.state.loading && !ctrl.instance">
|
|
2356
|
-
<div class="content-section">
|
|
2357
|
-
<div class="content-body text-center">
|
|
2358
|
-
<h3>Instance not found.</h3>
|
|
2359
|
-
</div>
|
|
2360
|
-
</div>
|
|
2361
|
-
</div>
|
|
2362
|
-
</div>
|
|
2363
|
-
`);
|
|
2364
|
-
}]);
|
|
2365
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
2366
|
-
templateCache.put("cloudrun/src/serverGroup/details/details.html", `<div class="details-panel" ng-class="{disabled: ctrl.serverGroup.isDisabled || ctrl.serverGroup.disabled}">
|
|
2367
|
-
<div class="header" ng-if="ctrl.state.loading">
|
|
2368
|
-
<div class="close-button">
|
|
2369
|
-
<a class="btn btn-link" ui-sref="^">
|
|
2370
|
-
<span class="glyphicon glyphicon-remove"></span>
|
|
2371
|
-
</a>
|
|
2372
|
-
</div>
|
|
2373
|
-
<h4 class="text-center">
|
|
2374
|
-
<span us-spinner="{radius:20, width:6, length: 12}"></span>
|
|
2375
|
-
</h4>
|
|
2376
|
-
</div>
|
|
2377
|
-
|
|
2378
|
-
<div class="header" ng-if="!ctrl.state.loading">
|
|
2379
|
-
<div class="close-button">
|
|
2380
|
-
<a class="btn btn-link" ui-sref="^">
|
|
2381
|
-
<span class="glyphicon glyphicon-remove"></span>
|
|
2382
|
-
</a>
|
|
2383
|
-
</div>
|
|
2384
|
-
<div class="header-text horizontal middle">
|
|
2385
|
-
<cloud-provider-logo provider="ctrl.serverGroup.type" height="'36px'" width="'36px'"></cloud-provider-logo>
|
|
2386
|
-
<h3 class="horizontal middle space-between flex-1" select-on-dbl-click>{{ctrl.serverGroup.name}}</h3>
|
|
2387
|
-
</div>
|
|
2388
|
-
<div class="actions">
|
|
2389
|
-
<div class="dropdown" uib-dropdown dropdown-append-to-body>
|
|
2390
|
-
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>
|
|
2391
|
-
Server Group Actions <span class="caret"></span>
|
|
2392
|
-
</button>
|
|
2393
|
-
<ul class="dropdown-menu" uib-dropdown-menu role="menu">
|
|
2394
|
-
<li
|
|
2395
|
-
ng-if="ctrl.serverGroup.tags.isLatest"
|
|
2396
|
-
uib-tooltip="You cannot destroy the latest server group (revision) .
|
|
2397
|
-
You may be able to delete this server group's load balancer."
|
|
2398
|
-
class="disabled"
|
|
2399
|
-
>
|
|
2400
|
-
<a href>Destroy</a>
|
|
2401
|
-
</li>
|
|
2402
|
-
<li ng-if="ctrl.canDestroyServerGroup() && !ctrl.serverGroup.tags.isLatest">
|
|
2403
|
-
<a href ng-click="ctrl.destroyServerGroup()">Destroy</a>
|
|
2404
|
-
</li>
|
|
2405
|
-
<li
|
|
2406
|
-
ng-if="(!ctrl.canDestroyServerGroup() && !ctrl.serverGroup.tags.isLatest)"
|
|
2407
|
-
uib-tooltip="You cannot destroy this server group while it is receiving traffic.
|
|
2408
|
-
You may be able to delete this server group's load balancer."
|
|
2409
|
-
class="disabled"
|
|
2410
|
-
>
|
|
2411
|
-
<a href>Destroy</a>
|
|
2412
|
-
</li>
|
|
2413
|
-
</ul>
|
|
2414
|
-
</div>
|
|
2415
|
-
</div>
|
|
2416
|
-
</div>
|
|
2417
|
-
<div class="content" ng-if="!ctrl.state.loading">
|
|
2418
|
-
<div class="band band-info" ng-if="ctrl.serverGroup.isDisabled || ctrl.serverGroup.disabled">Disabled</div>
|
|
2419
|
-
<server-group-running-tasks-details
|
|
2420
|
-
server-group="ctrl.serverGroup"
|
|
2421
|
-
application="ctrl.app"
|
|
2422
|
-
></server-group-running-tasks-details>
|
|
2423
|
-
<collapsible-section heading="Server Group Information" expanded="true">
|
|
2424
|
-
<dl class="dl-horizontal dl-narrow">
|
|
2425
|
-
<dt>Created</dt>
|
|
2426
|
-
<dd>{{ctrl.serverGroup.createdTime | timestamp}}</dd>
|
|
2427
|
-
<dt>In</dt>
|
|
2428
|
-
<dd><account-tag account="ctrl.serverGroup.account"></account-tag></dd>
|
|
2429
|
-
<dt>Region</dt>
|
|
2430
|
-
<dd>{{ctrl.serverGroup.region}}</dd>
|
|
2431
|
-
</dl>
|
|
2432
|
-
</collapsible-section>
|
|
2433
|
-
|
|
2434
|
-
<collapsible-section heading="Size" expanded="true">
|
|
2435
|
-
<dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup.capacity.min === ctrl.serverGroup.capacity.max">
|
|
2436
|
-
<dt>Min/Max</dt>
|
|
2437
|
-
<dd>{{ctrl.serverGroup.capacity.min}}</dd>
|
|
2438
|
-
<dt>Current</dt>
|
|
2439
|
-
<dd>{{ctrl.serverGroup.instances.length}}</dd>
|
|
2440
|
-
</dl>
|
|
2441
|
-
<dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup.capacity.min !== ctrl.serverGroup.capacity.max">
|
|
2442
|
-
<dt>Min</dt>
|
|
2443
|
-
<dd>{{ctrl.serverGroup.capacity.min}}</dd>
|
|
2444
|
-
<dt>Max</dt>
|
|
2445
|
-
<dd>{{ctrl.serverGroup.capacity.max}}</dd>
|
|
2446
|
-
<dt>Current</dt>
|
|
2447
|
-
<dd>{{ctrl.serverGroup.instances.length}}</dd>
|
|
2448
|
-
</dl>
|
|
2449
|
-
</collapsible-section>
|
|
2450
|
-
<collapsible-section heading="Health" expanded="true">
|
|
2451
|
-
<dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup">
|
|
2452
|
-
<dt>Instances</dt>
|
|
2453
|
-
<dd>
|
|
2454
|
-
<health-counts container="ctrl.serverGroup.instanceCounts" class="pull-left"></health-counts>
|
|
2455
|
-
</dd>
|
|
2456
|
-
</dl>
|
|
2457
|
-
</collapsible-section>
|
|
2458
|
-
</div>
|
|
2459
|
-
</div>
|
|
2460
|
-
`);
|
|
2461
|
-
}]);
|
|
2462
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
2463
|
-
templateCache.put("cloudrun/src/loadBalancer/configure/wizard/wizard.html", `<form name="form">
|
|
2464
|
-
<div ng-if="ctrl.state.loading && !ctrl.isNew" style="height: 200px" class="horizontal center middle">
|
|
2465
|
-
<loading-spinner size="'small'"></loading-spinner>
|
|
2466
|
-
</div>
|
|
2467
|
-
<v2-modal-wizard
|
|
2468
|
-
heading="{{::ctrl.heading}}"
|
|
2469
|
-
task-monitor="ctrl.taskMonitor"
|
|
2470
|
-
dismiss="$dismiss()"
|
|
2471
|
-
ng-if="!ctrl.state.loading || ctrl.isNew"
|
|
2472
|
-
>
|
|
2473
|
-
<div ng-if="!ctrl.isNew">
|
|
2474
|
-
<v2-wizard-page key="basic-settings" label="Basic Settings" mark-complete-on-view="false">
|
|
2475
|
-
<cloudrun-load-balancer-basic-settings
|
|
2476
|
-
load-balancer="ctrl.loadBalancer"
|
|
2477
|
-
application="ctrl.application"
|
|
2478
|
-
for-pipeline-config="ctrl.forPipelineConfig"
|
|
2479
|
-
></cloudrun-load-balancer-basic-settings>
|
|
2480
|
-
</v2-wizard-page>
|
|
2481
|
-
</div>
|
|
2482
|
-
</v2-modal-wizard>
|
|
2483
|
-
<cloudrun-load-balancer-message
|
|
2484
|
-
ng-if="ctrl.isNew"
|
|
2485
|
-
column-offset="1"
|
|
2486
|
-
columns="10"
|
|
2487
|
-
show-create-message="true"
|
|
2488
|
-
></cloudrun-load-balancer-message>
|
|
2489
|
-
<div class="modal-footer">
|
|
2490
|
-
<button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>
|
|
2491
|
-
<submit-button
|
|
2492
|
-
ng-if="!ctrl.isNew && ctrl.showSubmitButton()"
|
|
2493
|
-
label="ctrl.submitButtonLabel"
|
|
2494
|
-
is-disabled="cloudrunLoadBalancerForm.$invalid || ctrl.taskMonitor.submitting || ctrl.state.loading"
|
|
2495
|
-
submitting="ctrl.taskMonitor.submitting"
|
|
2496
|
-
on-click="ctrl.submit()"
|
|
2497
|
-
is-new="ctrl.isNew"
|
|
2498
|
-
>
|
|
2499
|
-
</submit-button>
|
|
2500
|
-
</div>
|
|
2501
|
-
</form>
|
|
2502
|
-
`);
|
|
2503
|
-
}]);
|
|
2504
|
-
window.angular.module("ng").run(["$templateCache", function(templateCache) {
|
|
2505
|
-
templateCache.put("cloudrun/src/loadBalancer/details/details.html", `<div class="details-panel">
|
|
2506
|
-
<div ng-if="ctrl.state.loading" class="header">
|
|
2507
|
-
<div class="close-button">
|
|
2508
|
-
<a class="btn btn-link" ui-sref="^">
|
|
2509
|
-
<span class="glyphicon glyphicon-remove"></span>
|
|
2510
|
-
</a>
|
|
2511
|
-
</div>
|
|
2512
|
-
<div class="horizontal center middle">
|
|
2513
|
-
<loading-spinner size="'small'"></loading-spinner>
|
|
2514
|
-
</div>
|
|
2515
|
-
</div>
|
|
2516
|
-
|
|
2517
|
-
<div ng-if="!ctrl.state.loading" class="header">
|
|
2518
|
-
<div class="close-button">
|
|
2519
|
-
<a class="btn btn-link" ui-sref="^">
|
|
2520
|
-
<span class="glyphicon glyphicon-remove"></span>
|
|
2521
|
-
</a>
|
|
2522
|
-
</div>
|
|
2523
|
-
<div class="header-text horizontal middle">
|
|
2524
|
-
<i class="fa icon-sitemap"></i>
|
|
2525
|
-
<h3 class="horizontal middle space-between flex-1" select-on-dbl-click>{{ctrl.loadBalancer.name}}</h3>
|
|
2526
|
-
</div>
|
|
2527
|
-
<div>
|
|
2528
|
-
<div class="actions">
|
|
2529
|
-
<div class="dropdown" uib-dropdown dropdown-append-to-body>
|
|
2530
|
-
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>
|
|
2531
|
-
Load Balancer Actions <span class="caret"></span>
|
|
2532
|
-
</button>
|
|
2533
|
-
<ul class="dropdown-menu" uib-dropdown-menu role="menu">
|
|
2534
|
-
<li><a href ng-click="ctrl.editLoadBalancer()">Edit Load Balancer</a></li>
|
|
2535
|
-
<li ng-if="ctrl.canDeleteLoadBalancer()">
|
|
2536
|
-
<a href ng-click="ctrl.deleteLoadBalancer()">Delete Load Balancer</a>
|
|
2537
|
-
</li>
|
|
2538
|
-
<li
|
|
2539
|
-
ng-if="!ctrl.canDeleteLoadBalancer()"
|
|
2540
|
-
uib-tooltip="You cannot delete a default service."
|
|
2541
|
-
class="disabled"
|
|
2542
|
-
>
|
|
2543
|
-
<a href>Delete Load Balancer</a>
|
|
2544
|
-
</li>
|
|
2545
|
-
</ul>
|
|
2546
|
-
</div>
|
|
2547
|
-
</div>
|
|
2548
|
-
</div>
|
|
2549
|
-
</div>
|
|
2550
|
-
|
|
2551
|
-
<div ng-if="!ctrl.state.loading" class="content">
|
|
2552
|
-
<collapsible-section heading="Load Balancer Details" expanded="true">
|
|
2553
|
-
<dl class="dl-horizontal dl-narrow">
|
|
2554
|
-
<dt>In</dt>
|
|
2555
|
-
<dd><account-tag account="ctrl.loadBalancer.account" pad="right"></account-tag></dd>
|
|
2556
|
-
<dt>Region</dt>
|
|
2557
|
-
<dd>{{ctrl.loadBalancer.region}}</dd>
|
|
2558
|
-
<dt ng-if="ctrl.loadBalancer.serverGroups.length">Server Groups</dt>
|
|
2559
|
-
<dd ng-if="ctrl.loadBalancer.serverGroups.length">
|
|
2560
|
-
<ul>
|
|
2561
|
-
<li ng-repeat="serverGroup in ctrl.loadBalancer.serverGroups | orderBy: ['isDisabled', '-name']">
|
|
2562
|
-
<a
|
|
2563
|
-
ui-sref="^.serverGroup({region: serverGroup.region,
|
|
2564
|
-
accountId: serverGroup.account,
|
|
2565
|
-
serverGroup: serverGroup.name,
|
|
2566
|
-
provider: 'cloudrun'})"
|
|
2567
|
-
>
|
|
2568
|
-
{{serverGroup.name}}
|
|
2569
|
-
</a>
|
|
2570
|
-
</li>
|
|
2571
|
-
</ul>
|
|
2572
|
-
</dd>
|
|
2573
|
-
</dl>
|
|
2574
|
-
</collapsible-section>
|
|
2575
|
-
<collapsible-section heading="Status" expanded="true">
|
|
2576
|
-
<health-counts class="pull-left" container="ctrl.loadBalancer.instanceCounts"></health-counts>
|
|
2577
|
-
</collapsible-section>
|
|
2578
|
-
<collapsible-section heading="Traffic Split" expanded="true">
|
|
2579
|
-
<dl class="dl-horizontal dl-narrow">
|
|
2580
|
-
<ul>
|
|
2581
|
-
<li ng-repeat="trafficTarget in ctrl.loadBalancer.split.trafficTargets">
|
|
2582
|
-
{{trafficTarget.revisionName}}:<span class="pull-right">{{trafficTarget.percent}}</span>
|
|
2583
|
-
</li>
|
|
2584
|
-
</ul>
|
|
2585
|
-
</dl>
|
|
2586
|
-
</collapsible-section>
|
|
2587
|
-
<collapsible-section heading="DNS" expanded="true">
|
|
2588
|
-
<dl class="dl-narrow">
|
|
2589
|
-
<cloudrun-component-url-details component="ctrl.loadBalancer"></cloudrun-component-url-details>
|
|
2590
|
-
</dl>
|
|
2591
|
-
</collapsible-section>
|
|
2592
|
-
</div>
|
|
2593
|
-
</div>
|
|
2594
|
-
`);
|
|
2595
|
-
}]);
|
|
2596
|
-
|
|
2597
|
-
export { CLOUDRUN_LOAD_BALANCER_DETAILS_CTRL, CLOUDRUN_LOAD_BALANCER_TRANSFORMER, CLOUDRUN_LOAD_BALANCER_WIZARD_CTRL, CLOUDRUN_MODULE, CLOUDRUN_SERVER_GROUP_COMMAND_BUILDER, CLOUDRUN_SERVER_GROUP_DETAILS_CTRL, CLOUDRUN_SERVER_GROUP_TRANSFORMER, CloudrunDeployDescription, CloudrunLoadBalancerTransformer, CloudrunLoadBalancerUpsertDescription, CloudrunServerGroupCommandBuilder, CloudrunV2ServerGroupCommandBuilder, CloudrunV2ServerGroupTransformer, ServerGroupSource };
|
|
1
|
+
import{module as e}from"angular";import{HelpContentsRegistry as t,RecentHistoryService as n,InstanceReader as a,StageConstants as i,LoadBalancerWriter as r,TaskMonitor as s,ConfirmationModalService as o,CloudProviderRegistry as l,Registry as c,StageArtifactSelector as d,ArtifactTypePatterns as u,HelpField as p,AccountSelectInput as m,yamlDocumentsToString as h,StageConfigField as g,RadioButtonInput as f,YamlEditor as v,StageArtifactSelectorDelegate as b,CheckboxInput as B,AccountService as k,FormikStageConfig as C,ReactInjector as w,relativeTime as y,JobManifestPodLogs as S,JobEventBasedPodNameProvider as E,CopyToClipboard as A,ManifestYaml as G,ManifestReader as x,ExecutionDetailsSection as D,StageFailureMessage as T,ExecutionDetailsTasks as $,ExecutionArtifactTab as N,ExpectedArtifactService as L,ArtifactReferenceService as M,SETTINGS as I,NameUtils as F,ServerGroupNamePreview as R,TextAreaInput as P,ReactModal as z,WizardModal as O,WizardPage as U,noop as V,SERVER_GROUP_WRITER as Y,ServerGroupReader as j,DeploymentStrategyRegistry as K}from"@spinnaker/core";import{flattenDeep as q,uniq as W,difference as H,reduce as X,filter as Q,chain as _,cloneDeep as Z,has as J,camelCase as ee,get as te,map as ne,capitalize as ae,isEmpty as ie,trim as re}from"lodash";import se,{useState as oe}from"react";import{Subject as le,from as ce}from"rxjs";import{takeUntil as de}from"rxjs/operators";import{dump as ue}from"js-yaml";import{DateTime as pe}from"luxon";import{$q as me}from"ngimport";const he={bindings:{component:"<"},template:'\n <dt>HTTPS</dt>\n <dl class="small">\n <a href="{{$ctrl.component.url}}" target="_blank">{{$ctrl.component.url}}</a>\n <copy-to-clipboard class="copy-to-clipboard copy-to-clipboard-sm"\n tool-tip="\'Copy URL to clipboard\'"\n text="$ctrl.component.httpsUrl"></copy-to-clipboard>\n </dl>\n '},ge="spinnaker.cloudrun.componentUrlDetails.component";e(ge,[]).component("cloudrunComponentUrlDetails",he);const fe="spinnaker.cloudrun.loadBalancer.createMessage.component";e(fe,[]).component("cloudrunLoadBalancerMessage",{bindings:{showCreateMessage:"<",columnOffset:"@",columns:"@"},templateUrl:"cloudrun/src/common/loadBalancerMessage.component.html"}),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/common/loadBalancerMessage.component.html",'<div class="row">\n <div class="col-md-offset-{{ $ctrl.columnOffset || 0 }} col-md-{{ $ctrl.columns || 12 }}">\n <div class="well">\n <p>\n <span ng-if="$ctrl.showCreateMessage">Spinnaker cannot create a load balancer for Cloud Run.</span>\n A Spinnaker load balancer maps to an Cloud Run Service, which will be created automatically alongside a\n Revision. Once created, the Service can be edited as a Load Balancer.\n </p>\n </div>\n </div>\n</div>\n')}]);[{key:"cloudrun.serverGroup.stack",value:"(Optional) <b>Stack</b> is one of the core naming components of a cluster, used to create vertical stacks of dependent services for integration testing."},{key:"cloudrun.serverGroup.file",value:"<pre>\n apiVersion: serving.knative.dev/v1\n kind: Service\n metadata:\n name: spinappcloud1\n namespace: '135005621049'\n labels:\n cloud.googleapis.com/location: us-central1\n annotations:\n run.googleapis.com/client-name: cloud-console\n serving.knative.dev/creator: kiran@opsmx.io\n serving.knative.dev/lastModifier: kiran@opsmx.io\n client.knative.dev/user-image: us-docker.pkg.dev/cloudrun/container/hello\n run.googleapis.com/ingress-status: all\n spec:\n template:\n metagoogleapis.com/ingress: all\n run.data:\n name: spinappcloud1\n annotations:\n run.googleapis.com/client-name: cloud-console\n autoscaling.knative.dev/minScale: '1'\n autoscaling.knative.dev/maxScale: '3'\n spec:\n containerConcurrency: 80\n timeoutSeconds: 200\n serviceAccountName:spinnaker-cloudrun-account@my-orbit-project-71824.iam.gserviceaccount.com\n containers:\n - image:us-docker.pkg.dev/cloudrun/container/hello\n ports:\n - name: http1\n containerPort: 8080\n resources:\n limits:\n cpu: 1000m\n memory: 256Mi \n</pre>\n "},{key:"cloudrun.serverGroup.detail",value:" (Optional) <b>Detail</b> is a string of free-form alphanumeric characters and hyphens to describe any other variables."},{key:"cloudrun.serverGroup.configFiles",value:"<p> The contents of a Cloud Run Service yaml </p>"},{key:"cloudrun.loadBalancer.allocations",value:"An allocation is the percent of traffic directed to a server group."},{key:"cloudrun.manifest.source",value:"\n <p>Where the manifest file content is read from.</p>\n <p>\n <b>text:</b> The manifest is supplied statically to the pipeline from the below text-box.\n </p>\n <p>\n <b>artifact:</b> The manifest is read from an artifact supplied/created upstream. The expected artifact must be referenced here, and will be bound at runtime.\n </p>"},{key:"cloudrun.manifest.expectedArtifact",value:"The artifact that is to be applied to the Cloud Run account for this stage. The artifact should represent a valid Cloud Run manifest."},{key:"cloudrun.manifest.skipExpressionEvaluation",value:'<p>Skip SpEL expression evaluation of the manifest artifact in this stage. Can be paired with the "Evaluate SpEL expressions in overrides at bake time" option in the Bake Manifest stage when baking a third-party manifest artifact with expressions not meant for Spinnaker to evaluate as SpEL.</p>'},{key:"cloudrun.manifest.requiredArtifactsToBind",value:'These artifacts must be present in the context for this stage to successfully complete. Artifacts specified will be <a href="https://www.spinnaker.io/reference/artifacts/in-cloudrun-v2/#binding-artifacts-in-manifests" target="_blank">bound to the deployed manifest.</a>'},{key:"cloudrun.manifest.account",value:"\n <p>A Spinnaker account corresponds to a physical Cloud Run cluster. If you are unsure which account to use, talk to your Spinnaker admin.</p>\n "}].forEach((e=>t.register(e.key,e.value)));class ve{constructor(e,t,n){this.$q=e,this.app=t,this.state={loading:!0},this.upToolTip="A Cloud Run instance is 'Up' if a load balancer is directing traffic to its server group.",this.outOfServiceToolTip="\n A Cloud Run instance is 'Out Of Service' if no load balancers are directing traffic to its server group.",this.app.ready().then((()=>this.retrieveInstance(n))).then((e=>{this.instance=e,this.state.loading=!1})).catch((()=>{this.instanceIdNotFound=n.instanceId,this.state.loading=!1}))}retrieveInstance(e){const t=q([this.app.getDataSource("serverGroups").data,this.app.getDataSource("loadBalancers").data,this.app.getDataSource("loadBalancers").data.map((e=>e.serverGroups))]).find((t=>t.instances.some((t=>t.id===e.instanceId))));if(t){const i={region:t.region,account:t.account};return"serverGroup"===t.category&&(i.serverGroup=t.name),n.addExtraDataToLatest("instances",i),a.getInstanceDetails(t.account,t.region,e.instanceId).then((e=>(e.account=t.account,e.region=t.region,e)))}return this.$q.reject()}}ve.$inject=["$q","app","instance"];const be="spinnaker.cloudrun.instanceDetails.controller";e(be,[]).controller("cloudrunInstanceDetailsCtrl",ve);const Be={bindings:{allocationDescription:"<",removeAllocation:"&",serverGroupOptions:"<",onAllocationChange:"&"},template:'\n <div class="form-group">\n <div class="row">\n <div class="col-md-7">\n <ui-select ng-model="$ctrl.allocationDescription.revisionName"\n on-select="$ctrl.onAllocationChange()"\n class="form-control input-sm">\n <ui-select-match placeholder="Select...">\n {{$select.selected}}\n </ui-select-match>\n <ui-select-choices repeat="serverGroup as serverGroup in $ctrl.getServerGroupOptions() | filter: $select.search">\n <div ng-bind-html="serverGroup | highlight: $select.search"></div>\n </ui-select-choices>\n </ui-select>\n </div>\n <div class="col-md-3">\n <div class="input-group input-group-sm">\n <input type="number"\n ng-model="$ctrl.allocationDescription.percent"\n required\n class="form-control input-sm"\n min="0"\n ng-change="$ctrl.onAllocationChange()"\n max="100"/>\n <span class="input-group-addon">%</span>\n </div>\n </div>\n <div class="col-md-2">\n <a class="btn btn-link sm-label" ng-click="$ctrl.removeAllocation()">\n <span class="glyphicon glyphicon-trash"></span>\n </a>\n </div>\n </div>\n </div>\n ',controller:class{getServerGroupOptions(){return this.allocationDescription.revisionName?W(this.serverGroupOptions.concat(this.allocationDescription.revisionName)):this.serverGroupOptions}}},ke="spinnaker.cloudrun.allocationConfigurationRow.component";e(ke,[]).component("cloudrunAllocationConfigurationRow",Be);const Ce={bindings:{loadBalancer:"=",forPipelineConfig:"<",application:"<"},controller:class{$onInit(){this.updateServerGroupOptions()}addAllocation(){const e=this.serverGroupsWithoutAllocation();e.length?(this.loadBalancer.splitDescription.allocationDescriptions.push({revisionName:e[0],percent:0}),this.updateServerGroupOptions()):this.forPipelineConfig&&this.loadBalancer.splitDescription.allocationDescriptions.push({percent:0,revisionName:""})}removeAllocation(e){this.loadBalancer.splitDescription.allocationDescriptions.splice(e,1),this.updateServerGroupOptions()}allocationIsInvalid(){return 100!==this.loadBalancer.splitDescription.allocationDescriptions.reduce(((e,t)=>e+t.percent),0)}updateServerGroupOptions(){this.serverGroupOptions=this.serverGroupsWithoutAllocation()}showAddButton(){return!!this.forPipelineConfig||this.serverGroupsWithoutAllocation().length>0}initializeAsTextInput(e){return!!this.forPipelineConfig&&!this.loadBalancer.serverGroups.map((e=>e.name)).includes(e)}serverGroupsWithoutAllocation(){const e=this.loadBalancer.splitDescription.allocationDescriptions.map((e=>e.revisionName)),t=this.loadBalancer.serverGroups.map((e=>e.name));return H(t,e)}},templateUrl:"cloudrun/src/loadBalancer/configure/wizard/basicSettings.component.html"},we="spinnaker.cloudrun.loadBalancerSettings.component";e(we,[]).component("cloudrunLoadBalancerBasicSettings",Ce),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/loadBalancer/configure/wizard/basicSettings.component.html",'<ng-form name="basicSettingsForm">\n <div class="row">\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n Allocations\n <help-field key="cloudrun.loadBalancer.allocations"></help-field>\n </div>\n <div class="col-md-9">\n <div ng-if="!$ctrl.forPipelineConfig">\n <cloudrun-allocation-configuration-row\n ng-repeat="description in $ctrl.loadBalancer.splitDescription.allocationDescriptions"\n allocation-description="description"\n server-group-options="$ctrl.serverGroupOptions"\n on-allocation-change="$ctrl.updateServerGroupOptions()"\n remove-allocation="$ctrl.removeAllocation($index)"\n >\n </cloudrun-allocation-configuration-row>\n </div>\n <div ng-if="$ctrl.forPipelineConfig">\n <cloudrun-stage-allocation-configuration-row\n ng-repeat="description in $ctrl.loadBalancer.splitDescription.allocationDescriptions"\n allocation-description="description"\n application="$ctrl.application"\n region="{{ $ctrl.loadBalancer.region }}"\n account="{{ $ctrl.loadBalancer.account || $ctrl.loadBalancer.credentials }}"\n name="{{ $ctrl.loadBalancer.name }}"\n server-group-options="$ctrl.serverGroupOptions"\n on-allocation-change="$ctrl.updateServerGroupOptions()"\n remove-allocation="$ctrl.removeAllocation($index)"\n >\n </cloudrun-stage-allocation-configuration-row>\n </div>\n <button class="add-new col-md-11" ng-if="$ctrl.showAddButton()" ng-click="$ctrl.addAllocation()">\n <span class="glyphicon glyphicon-plus-sign"></span> Add allocation\n </button>\n </div>\n </div>\n <div class="form-group" ng-if="$ctrl.allocationIsInvalid()">\n <div class="col-md-12 text-center">\n <p class="alert alert-warning">Allocations must sum to 100%.</p>\n </div>\n </div>\n </div>\n</ng-form>\n')}]);class ye{static mapTargetCoordinateToLabel(e){const t=i.TARGET_LIST.find((t=>t.val===e));return t?t.label:null}$doCheck(){this.setInputViewValue()}setInputViewValue(){if(this.allocationDescription.cluster&&this.allocationDescription.target){const e=ye.mapTargetCoordinateToLabel(this.allocationDescription.target);this.inputViewValue=`${e} (${this.allocationDescription.cluster})`}else this.inputViewValue=null}}const Se={bindings:{allocationDescription:"<"},controller:ye,template:'<input ng-model="$ctrl.inputViewValue" type="text" class="form-control input-sm" readonly/>'};const Ee={bindings:{application:"<",region:"@",account:"@",name:"@",allocationDescription:"<",removeAllocation:"&",serverGroupOptions:"<",onAllocationChange:"&"},controller:class{constructor(){this.targets=i.TARGET_LIST}$onInit(){this.allocationDescription.cluster=this.name}getServerGroupOptions(){return this.allocationDescription.revisionName?W(this.serverGroupOptions.concat(this.allocationDescription.revisionName)):this.serverGroupOptions}},templateUrl:"cloudrun/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html"},Ae="spinnaker.cloudrun.stageAllocationConfigurationRow.component";e(Ae,[]).component("cloudrunStageAllocationConfigurationRow",Ee).component("cloudrunStageAllocationLabel",Se),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html",'<div class="form-group">\n <div class="row">\n <div class="col-md-7">\n <cloudrun-stage-allocation-label allocation-description="$ctrl.allocationDescription">\n </cloudrun-stage-allocation-label>\n </div>\n <div class="col-md-3">\n <div class="input-group input-group-sm">\n <input\n type="number"\n ng-model="$ctrl.allocationDescription.percent"\n required\n class="form-control input-sm"\n min="0"\n ng-change="$ctrl.onAllocationChange()"\n max="100"\n />\n <span class="input-group-addon">%</span>\n </div>\n </div>\n <div class="col-md-2">\n <a class="btn btn-link sm-label" ng-click="$ctrl.removeAllocation()">\n <span class="glyphicon glyphicon-trash"></span>\n </a>\n </div>\n </div>\n</div>\n<div class="form-group">\n <div class="well col-md-11" style="padding-top: 5px; padding-bottom: 10px">\n <div class="row">\n <div class="form-group">\n <div>\n <div class="col-md-3 sm-label-right">Cluster</div>\n <div class="col-md-7" style="margin-bottom: 10px">\n <input ng-model="$ctrl.allocationDescription.cluster" type="text" class="form-control input-sm" readonly />\n </div>\n <div class="col-md-3 sm-label-right">Target</div>\n <div class="col-md-7">\n <target-select model="$ctrl.allocationDescription" options="$ctrl.targets"></target-select>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n')}]);class Ge{static convertTrafficSplitToTrafficSplitDescription(e){return{allocationDescriptions:X(e.trafficTargets,((e,t)=>{const{revisionName:n,percent:a}=t;return e.concat({percent:a,revisionName:n})}),[])}}constructor(e){this.credentials=e.account||e.credentials,this.account=this.credentials,this.cloudProvider=e.cloudProvider,this.loadBalancerName=e.name,this.name=e.name,this.region=e.region,this.migrateTraffic=e.migrateTraffic||!1,this.serverGroups=e.serverGroups}mapAllocationsToDecimals(){this.splitDescription.allocationDescriptions.forEach((e=>{e.percent=e.percent/100}))}mapAllocationsToPercentages(){this.splitDescription.allocationDescriptions.forEach((e=>{e.percent=Math.round(e.percent)}))}}class xe{constructor(e){this.$q=e}normalizeLoadBalancer(e){e.provider=e.type,e.instanceCounts=this.buildInstanceCounts(e.serverGroups),e.instances=[],e.serverGroups.forEach((t=>{t.account=e.account,t.region=e.region,t.detachedInstances&&(t.detachedInstances=t.detachedInstances.map((e=>({id:e})))),t.instances=t.instances.concat(t.detachedInstances||[]).map((t=>this.transformInstance(t,e)))}));const t=Q(e.serverGroups,{isDisabled:!1});return e.instances=_(t).map("instances").flatten().value(),this.$q.resolve(e)}convertLoadBalancerForEditing(e,t){return t.getDataSource("loadBalancers").ready().then((()=>{const n=t.getDataSource("loadBalancers").data.find((t=>t.name===e.name&&(t.account===e.account||t.account===e.credentials)));return n&&(e.serverGroups=Z(n.serverGroups)),e}))}convertLoadBalancerToUpsertDescription(e){return new Ge(e)}buildInstanceCounts(e){const t=_(e).map("instances").flatten().reduce(((e,t)=>(J(t,"health.state")&&e[ee(t.health.state)]++,e)),{up:0,down:0,outOfService:0,succeeded:0,failed:0,starting:0,unknown:0}).value();return t.outOfService+=_(e).map("detachedInstances").flatten().value().length,t}transformInstance(e,t){e.provider=t.type,e.account=t.account,e.region=t.region,e.loadBalancers=[t.name];const n=e.health||{};return e.healthState=te(e,"health.state")||"OutOfService",e.health=[n],e}}xe.$inject=["$q"];const De="spinnaker.cloudrun.loadBalancer.transformer.service";function Te(e,t){void 0===t&&(t={});var n=t.insertAt;if(e&&"undefined"!=typeof document){var a=document.head||document.getElementsByTagName("head")[0],i=document.createElement("style");i.type="text/css","top"===n&&a.firstChild?a.insertBefore(i,a.firstChild):a.appendChild(i),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(document.createTextNode(e))}}e(De,[]).service("cloudrunLoadBalancerTransformer",xe);Te("cloudrun-load-balancer-basic-settings a.btn.btn-link {\n padding: 0;\n}\ncloudrun-load-balancer-basic-settings .form-group {\n margin-top: 0.4rem;\n}\n");class $e{constructor(e,t,n,a,i,r,s,o,l){this.$scope=e,this.$state=t,this.$uibModalInstance=n,this.application=a,this.isNew=r,this.forPipelineConfig=s,this.cloudrunLoadBalancerTransformer=o,this.wizardSubFormValidation=l,this.state={loading:!0},this.submitButtonLabel=this.forPipelineConfig?"Done":"Update",this.isNew?this.heading="Create New Load Balancer":(this.heading=`Edit ${[i.name,i.region,i.account||i.credentials].join(":")}`,this.cloudrunLoadBalancerTransformer.convertLoadBalancerForEditing(i,a).then((e=>{this.loadBalancer=this.cloudrunLoadBalancerTransformer.convertLoadBalancerToUpsertDescription(e),i.split&&!this.loadBalancer.splitDescription?this.loadBalancer.splitDescription=Ge.convertTrafficSplitToTrafficSplitDescription(i.split):this.loadBalancer.splitDescription=i.splitDescription,this.loadBalancer.mapAllocationsToPercentages(),this.setTaskMonitor(),this.initializeFormValidation(),this.state.loading=!1})))}submit(){const e=Z(this.loadBalancer);return e.mapAllocationsToPercentages(),delete e.serverGroups,this.forPipelineConfig?this.$uibModalInstance.close(e):this.taskMonitor.submit((()=>r.upsertLoadBalancer(e,this.application,"Update")))}cancel(){this.$uibModalInstance.dismiss()}showSubmitButton(){return this.wizardSubFormValidation.subFormsAreValid()}setTaskMonitor(){this.taskMonitor=new s({application:this.application,title:"Updating your load balancer",modalInstance:this.$uibModalInstance,onTaskComplete:()=>this.onTaskComplete()})}initializeFormValidation(){this.wizardSubFormValidation.config({form:"form",scope:this.$scope}).register({page:"basic-settings",subForm:"basicSettingsForm",validators:[{watchString:"ctrl.loadBalancer.splitDescription",validator:e=>100===e.allocationDescriptions.reduce(((e,t)=>e+t.percent),0),watchDeep:!0}]})}onTaskComplete(){this.application.getDataSource("loadBalancers").refresh(),this.application.getDataSource("loadBalancers").onNextRefresh(this.$scope,(()=>this.onApplicationRefresh()))}onApplicationRefresh(){if(this.$scope.$$destroyed)return;this.$uibModalInstance.dismiss();const e={name:this.loadBalancer.name,accountId:this.loadBalancer.credentials,region:this.loadBalancer.region,provider:"cloudrun"};this.$state.includes("**.loadBalancerDetails")?this.$state.go("^.loadBalancerDetails",e):this.$state.go(".loadBalancerDetails",e)}}$e.$inject=["$scope","$state","$uibModalInstance","application","loadBalancer","isNew","forPipelineConfig","cloudrunLoadBalancerTransformer","wizardSubFormValidation"];const Ne="spinnaker.cloudrun.loadBalancer.wizard.controller";e(Ne,[]).controller("cloudrunLoadBalancerWizardCtrl",$e);class Le{constructor(e,t,n,a,i){this.$uibModal=e,this.$state=t,this.$scope=n,this.app=i,this.state={loading:!0},this.loadBalancerFromParams=a,this.app.getDataSource("loadBalancers").ready().then((()=>this.extractLoadBalancer()))}editLoadBalancer(){this.$uibModal.open({templateUrl:"cloudrun/src/loadBalancer/configure/wizard/wizard.html",controller:"cloudrunLoadBalancerWizardCtrl as ctrl",size:"lg",resolve:{application:()=>this.app,loadBalancer:()=>Z(this.loadBalancer),isNew:()=>!1,forPipelineConfig:()=>!1}})}extractLoadBalancer(){this.loadBalancer=this.app.getDataSource("loadBalancers").data.find((e=>e.name===this.loadBalancerFromParams.name&&e.account===this.loadBalancerFromParams.accountId)),this.loadBalancer?(this.state.loading=!1,this.app.getDataSource("loadBalancers").onRefresh(this.$scope,(()=>this.extractLoadBalancer()))):this.autoClose()}deleteLoadBalancer(){const e={application:this.app,title:"Deleting "+this.loadBalancer.name};o.confirm({header:"Really delete "+this.loadBalancer.name+"?",buttonText:"Delete "+this.loadBalancer.name,body:this.getConfirmationModalBodyHtml(),account:this.loadBalancer.account,taskMonitorConfig:e,submitMethod:()=>{const e={cloudProvider:this.loadBalancer.cloudProvider,loadBalancerName:this.loadBalancer.name,credentials:this.loadBalancer.account};return r.deleteLoadBalancer(e,this.app)}})}canDeleteLoadBalancer(){return"default"!==this.loadBalancer.name}getConfirmationModalBodyHtml(){const e=this.loadBalancer.serverGroups.map((e=>e.name)),t=!!e&&e.length>0,n=!!e&&e.length>1;if(t){if(n){const t=e.map((e=>`<li>${e}</li>`)).join("");return`<div class="alert alert-warning">\n <p>\n Deleting <b>${this.loadBalancer.name}</b> will destroy the following server groups:\n <ul>\n ${t}\n </ul>\n </p>\n </div>\n `}return`<div class="alert alert-warning">\n <p>\n Deleting <b>${this.loadBalancer.name}</b> will destroy <b>${e[0]}</b>.\n </p>\n </div>\n `}return null}autoClose(){this.$scope.$$destroyed||(this.$state.params.allowModalToStayOpen=!0,this.$state.go("^",null,{location:"replace"}))}}Le.$inject=["$uibModal","$state","$scope","loadBalancer","app"];const Me="spinnaker.cloudrun.loadBalancerDetails.controller";e(Me,[]).controller("cloudrunLoadBalancerDetailsCtrl",Le),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/loadBalancer/configure/wizard/wizard.html",'<form name="form">\n <div ng-if="ctrl.state.loading && !ctrl.isNew" style="height: 200px" class="horizontal center middle">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n <v2-modal-wizard\n heading="{{::ctrl.heading}}"\n task-monitor="ctrl.taskMonitor"\n dismiss="$dismiss()"\n ng-if="!ctrl.state.loading || ctrl.isNew"\n >\n <div ng-if="!ctrl.isNew">\n <v2-wizard-page key="basic-settings" label="Basic Settings" mark-complete-on-view="false">\n <cloudrun-load-balancer-basic-settings\n load-balancer="ctrl.loadBalancer"\n application="ctrl.application"\n for-pipeline-config="ctrl.forPipelineConfig"\n ></cloudrun-load-balancer-basic-settings>\n </v2-wizard-page>\n </div>\n </v2-modal-wizard>\n <cloudrun-load-balancer-message\n ng-if="ctrl.isNew"\n column-offset="1"\n columns="10"\n show-create-message="true"\n ></cloudrun-load-balancer-message>\n <div class="modal-footer">\n <button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>\n <submit-button\n ng-if="!ctrl.isNew && ctrl.showSubmitButton()"\n label="ctrl.submitButtonLabel"\n is-disabled="cloudrunLoadBalancerForm.$invalid || ctrl.taskMonitor.submitting || ctrl.state.loading"\n submitting="ctrl.taskMonitor.submitting"\n on-click="ctrl.submit()"\n is-new="ctrl.isNew"\n >\n </submit-button>\n </div>\n</form>\n')}]);class Ie{constructor(e,t,n){this.$uibModal=e,this.$uibModalInstance=t,this.application=n,this.state={loading:!0},this.initialize()}submit(){const e=l.getValue("cloudrun","loadBalancer"),t=this.$uibModal.open({templateUrl:e.createLoadBalancerTemplateUrl,controller:`${e.createLoadBalancerController} as ctrl`,size:"lg",resolve:{application:()=>this.application,loadBalancer:()=>Z(this.selectedLoadBalancer),isNew:()=>!1,forPipelineConfig:()=>!0}}).result;this.$uibModalInstance.close(t)}cancel(){this.$uibModalInstance.dismiss()}initialize(){this.application.getDataSource("loadBalancers").ready().then((()=>{this.loadBalancers=this.application.loadBalancers.data.filter((e=>"cloudrun"===e.cloudProvider)),this.loadBalancers.length&&(this.selectedLoadBalancer=this.loadBalancers[0]),this.state.loading=!1}))}}Ie.$inject=["$uibModal","$uibModalInstance","application"];const Fe="spinnaker.Cloudrun.loadBalancerChoiceModal.controller";e(Fe,[]).controller("cloudrunLoadBalancerChoiceModelCtrl",Ie);class Re{constructor(e,t){this.$scope=e,this.$uibModal=t,e.stage.loadBalancers=e.stage.loadBalancers||[],e.stage.cloudProvider="cloudrun"}addLoadBalancer(){this.$uibModal.open({templateUrl:"cloudrun/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html",controller:"cloudrunLoadBalancerChoiceModelCtrl as ctrl",resolve:{application:()=>this.$scope.application}}).result.then((e=>{this.$scope.stage.loadBalancers.push(e)})).catch((()=>{}))}editLoadBalancer(e){const t=l.getValue("cloudrun","loadBalancer");this.$uibModal.open({templateUrl:t.createLoadBalancerTemplateUrl,controller:`${t.createLoadBalancerController} as ctrl`,size:"lg",resolve:{application:()=>this.$scope.application,loadBalancer:()=>Z(this.$scope.stage.loadBalancers[e]),isNew:()=>!1,forPipelineConfig:()=>!0}}).result.then((t=>{this.$scope.stage.loadBalancers[e]=t})).catch((()=>{}))}removeLoadBalancer(e){this.$scope.stage.loadBalancers.splice(e,1)}}Re.$inject=["$scope","$uibModal"];const Pe="spinnaker.cloudrun.pipeline.stage.editLoadBalancerStage";e(Pe,[Fe]).config((()=>{c.pipeline.registerStage({label:"Edit Load Balancer (Cloud Run)",description:"Edits a load balancer",key:"upsertCloudrunLoadBalancers",cloudProvider:"cloudrun",templateUrl:"cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html",executionDetailsUrl:"cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html",executionConfigSections:["editLoadBalancerConfig","taskStatus"],controller:"cloudrunEditLoadBalancerStageCtrl",controllerAs:"editLoadBalancerStageCtrl",validators:[]})})).controller("cloudrunEditLoadBalancerStageCtrl",Re),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html",'<div modal-page>\n <modal-close dismiss="$dismiss()"></modal-close>\n <div class="modal-header">\n <h4 class="modal-title">Select Load Balancer</h4>\n </div>\n <div class="modal-body" ng-if="ctrl.state.loading" style="height: 200px" class="horizontal center middle">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n <div class="modal-body" ng-if="!ctrl.state.loading">\n <div class="alert alert-warning" ng-if="ctrl.loadBalancers.length === 0">\n <p>\n Spinnaker cannot create a load balancer for Cloud Run. A Spinnaker load balancer maps to a Cloud Run service\n which along with a Revision are created from Create Server Group page using a\n </p>\n <p><code>yaml file</code> <help-field key="cloudrun.serverGroup.file"></help-field></p>\n <p>\n If a service does not exist when a Revision is deployed, it will be created. It will then be editable as a load\n balancer within Spinnaker.\n </p>\n </div>\n <form\n role="form"\n name="form"\n class="form-horizontal"\n ng-submit="ctrl.submit()"\n ng-if="ctrl.loadBalancers.length > 0"\n >\n <div class="form-group">\n <div class="col-md-3 sm-label-right">\n <b>Load Balancer</b>\n </div>\n <div class="col-md-7">\n <ui-select class="form-control input-sm" ng-model="ctrl.selectedLoadBalancer">\n <ui-select-match>\n <account-tag account="$select.selected.account"></account-tag>\n <span style="margin-left: 5px">{{$select.selected.name}}</span>\n </ui-select-match>\n <ui-select-choices repeat="loadBalancer in ctrl.loadBalancers | filter: $select.search">\n <account-tag account="loadBalancer.account"></account-tag>\n <span style="margin-left: 5px" ng-bind-html="loadBalancer.name"></span>\n </ui-select-choices>\n </ui-select>\n </div>\n </div>\n </form>\n </div>\n <div class="modal-footer">\n <button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>\n <button class="btn btn-primary" ng-if="ctrl.loadBalancers.length > 0" ng-click="ctrl.submit()">\n <span class="far fa-check-circle"></span> Edit\n </button>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html",'<div class="well well-sm clearfix" ng-if="!pipeline.strategy">\n <div class="row">\n <div class="col-md-12">\n <h4 class="text-left">Load Balancers</h4>\n </div>\n </div>\n <div class="row">\n <div class="col-md-12">\n <table class="table table-condensed">\n <thead>\n <tr>\n <th>Account</th>\n <th>Name</th>\n <th>Region</th>\n <th>Actions</th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="loadBalancer in stage.loadBalancers">\n <td>\n <account-tag account="loadBalancer.credentials"></account-tag>\n </td>\n <td>{{ loadBalancer.name }}</td>\n <td>{{ loadBalancer.region }}</td>\n <td class="condensed-actions">\n <a class="btn btn-sm btn-link" href ng-click="editLoadBalancerStageCtrl.editLoadBalancer($index)">\n <span class="glyphicon glyphicon-edit" uib-tooltip="Edit"></span\n ></a>\n <a\n class="btn btn-sm btn-link pad-left"\n href\n ng-click="editLoadBalancerStageCtrl.removeLoadBalancer($index)"\n >\n <span class="glyphicon glyphicon-trash" uib-tooltip="Remove"></span>\n </a>\n </td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td colspan="8">\n <button class="btn btn-block btn-sm add-new" ng-click="editLoadBalancerStageCtrl.addLoadBalancer()">\n <span class="glyphicon glyphicon-plus-sign"></span> Add load balancer\n </button>\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html",'<div ng-controller="BaseExecutionDetailsCtrl">\n <execution-details-section-nav sections="configSections"></execution-details-section-nav>\n <div class="step-section-details" ng-if="detailsSection === \'editLoadBalancerConfig\'">\n <div class="row">\n <div class="col-md-12">\n <table class="table table-condensed">\n <thead>\n <tr>\n <th>Account</th>\n <th>Name</th>\n <th>Region</th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="loadBalancer in stage.context.loadBalancers">\n <td>\n <account-tag account="loadBalancer.credentials"></account-tag>\n </td>\n <td>{{ loadBalancer.name }}</td>\n <td>{{ loadBalancer.region }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n <stage-failure-message stage="stage" message="stage.failureMessage"></stage-failure-message>\n </div>\n <div class="step-section-details" ng-if="detailsSection === \'taskStatus\'">\n <div class="row">\n <execution-step-details item="stage"></execution-step-details>\n </div>\n </div>\n</div>\n')}]);const ze="spinnaker.cloudrun.pipeline.module";e(ze,[Pe]);class Oe extends se.Component{constructor(){super(...arguments),this.onChangeBinding=(e,t)=>{const n=(this.props.bindings||[]).slice(0);n[e]=t,this.props.onChangeBindings(n)},this.onRemoveBinding=e=>{const t=(this.props.bindings||[]).slice(0);t.splice(e,1),this.props.onChangeBindings(t)}}render(){const{stage:e,pipeline:t,bindings:n}=this.props,a=(a,i)=>{const r=(i?i.expectedArtifactId:"new")||i.artifact&&i.artifact.id;return se.createElement("div",{className:"row",key:r},se.createElement("div",{className:"col-md-10"},se.createElement(d,{pipeline:t,stage:e,expectedArtifactId:i&&i.expectedArtifactId,artifact:!!i&&i.artifact,onArtifactEdited:e=>this.onChangeBinding(a,{artifact:e}),onExpectedArtifactSelected:e=>this.onChangeBinding(a,{expectedArtifactId:e.id}),excludedArtifactIds:n.map((e=>e.expectedArtifactId)),excludedArtifactTypePatterns:[u.FRONT50_PIPELINE_TEMPLATE]})),i&&se.createElement("div",{className:"col-md-2"},se.createElement("a",{className:"glyphicon glyphicon-trash",onClick:()=>this.onRemoveBinding(a)})))};return se.createElement(se.Fragment,null,n.map(((e,t)=>a(t,e))),a(n.length))}}var Ue,Ve;function Ye({accounts:e,onAccountSelect:t,selectedAccount:n}){return se.createElement("div",{className:"form-horizontal"},se.createElement("div",{className:"form-group"},se.createElement("div",{className:"col-md-3 sm-label-right"},"Account ",se.createElement(p,{id:"cloudrun.manifest.account"})),se.createElement("div",{className:"col-md-8"},se.createElement(m,{value:n,onChange:e=>t(e.target.value),readOnly:!1,accounts:e,provider:"cloudrun"}))))}(Ve=Ue||(Ue={})).TEXT="text",Ve.ARTIFACT="artifact";se.Component;class je extends se.Component{render(){const e=this.props.application?this.props.application:"",t=this.props.stack?`-${this.props.stack}`:"",n=this.props.details?`-${this.props.details}`:"";return se.createElement("pre",{style:{textAlign:"center"}},se.createElement("p",null," Your server group will be in the cluster:"),se.createElement("p",null,se.createElement("b",null,e,t,n)))}}class Ke extends se.Component{constructor(e){super(e),this.excludedManifestArtifactTypes=[u.FRONT50_PIPELINE_TEMPLATE,u.MAVEN_FILE],this.getSourceOptions=()=>ne([Ue.TEXT,Ue.ARTIFACT],(e=>({label:ae(e),value:e}))),this.handleRawManifestChange=(e,t)=>{this.setState({rawManifest:e}),this.props.formik.setFieldValue("manifests",t)},this.onManifestArtifactSelected=e=>{this.props.formik.setFieldValue("manifestArtifactId",e),this.props.formik.setFieldValue("manifestArtifact",null)},this.onManifestArtifactEdited=e=>{this.props.formik.setFieldValue("manifestArtifactId",null),this.props.formik.setFieldValue("manifestArtifact",e)},this.getRequiredArtifacts=()=>{const{requiredArtifactIds:e,requiredArtifacts:t}=this.props.formik.values;return(e||[]).map((e=>({expectedArtifactId:e}))).concat(t||[])},this.onRequiredArtifactsChanged=e=>{this.props.formik.setFieldValue("requiredArtifactIds",e.filter((e=>e.expectedArtifactId)).map((e=>e.expectedArtifactId))),this.props.formik.setFieldValue("requiredArtifacts",e.filter((e=>e.artifact)))};const t=this.props.formik.values,n=te(e.formik.values,"manifests"),a=te(e.formik.values,"source")===Ue.TEXT;this.state={rawManifest:!ie(n)&&a?h(n):"",application:this.props.application.name,stack:te(t,"stack"),details:te(t,"details")}}render(){const e=this.props.formik.values;return se.createElement("div",{className:"form-horizontal"},se.createElement("h4",null,"Basic Settings"),se.createElement(Ye,{accounts:this.props.accounts,onAccountSelect:e=>this.props.formik.setFieldValue("account",e),selectedAccount:e.account}),se.createElement(g,{label:"Application"},se.createElement("input",{className:"form-control input-sm",type:"text",value:this.props.application.name,onChange:e=>this.props.formik.setFieldValue("application",e.target.value),disabled:!0})),se.createElement(g,{label:"Stack"},se.createElement("input",{className:"form-control input-sm",type:"text",value:e.stack,onChange:e=>this.props.formik.setFieldValue("stack",e.target.value)})),se.createElement(g,{label:"Details"},se.createElement("input",{className:"form-control input-sm",type:"text",value:e.details,onChange:e=>this.props.formik.setFieldValue("details",e.target.value)})),se.createElement(je,{application:this.props.application.name,stack:e.stack,details:e.details}),se.createElement("hr",null),se.createElement("h4",null,"Manifest Configuration"),se.createElement(g,{label:"Manifest Source",helpKey:"cloudrun.manifest.source"},se.createElement(f,{options:this.getSourceOptions(),onChange:e=>this.props.formik.setFieldValue("source",e.target.value),value:e.source})),e.source===Ue.TEXT&&se.createElement(g,{label:"Manifest"},se.createElement(v,{onChange:this.handleRawManifestChange,value:this.state.rawManifest})),e.source===Ue.ARTIFACT&&se.createElement(se.Fragment,null,se.createElement(b,{artifact:e.manifestArtifact,excludedArtifactTypePatterns:this.excludedManifestArtifactTypes,expectedArtifactId:e.manifestArtifactId,helpKey:"cloudrun.manifest.expectedArtifact",label:"Manifest Artifact",onArtifactEdited:this.onManifestArtifactEdited,onExpectedArtifactSelected:e=>this.onManifestArtifactSelected(e.id),pipeline:this.props.pipeline,stage:e}),se.createElement(g,{label:"Expression Evaluation",helpKey:"cloudrun.manifest.skipExpressionEvaluation"},se.createElement(B,{checked:!0===e.skipExpressionEvaluation,onChange:e=>this.props.formik.setFieldValue("skipExpressionEvaluation",e.target.checked),text:"Skip SpEL expression evaluation"}))),se.createElement(g,{label:"Required Artifacts to Bind",helpKey:"cloudrun.manifest.requiredArtifactsToBind"},se.createElement(Oe,{bindings:this.getRequiredArtifacts(),onChangeBindings:this.onRequiredArtifactsChanged,pipeline:this.props.pipeline,stage:e})))}}class qe extends se.Component{constructor(e){super(e),this.destroy$=new le,this.fetchAccounts=()=>{ce(k.getAllAccountDetailsForProvider("cloudrun")).pipe(de(this.destroy$)).subscribe((e=>{this.setState({accounts:e})}))},this.state={accounts:[]};const{stage:t}=e,n=Z(t);n.source||(n.source=Ue.TEXT),n.skipExpressionEvaluation||(n.skipExpressionEvaluation=!1),n.cloudProvider||(n.cloudProvider="cloudrun"),n.moniker||(n.moniker={}),n.moniker.app||(n.moniker.app=e.application.name),this.stage=n}componentDidMount(){this.fetchAccounts()}componentWillUnmount(){this.destroy$.next()}render(){return se.createElement(C,{...this.props,stage:this.stage,onChange:this.props.updateStage,render:e=>se.createElement(Ke,{...e,accounts:this.state.accounts})})}}const We="redblack",He="strategy.spinnaker.io/max-version-history",Xe={available:"success",stable:"success",paused:"warn",failed:"danger"};class Qe extends se.Component{render(){const{manifest:e}=this.props;return null==e||null==e.status?null:Object.keys(e.status).map(((t,n)=>{const a=e.status[t],i=Xe[t]||"",r=a.state,s=!r&&a.message;return se.createElement("span",{key:n},r&&se.createElement("span",{title:a.message,className:`pill ${i}`},t),s&&se.createElement("span",{title:a.message,className:"pill warn"},t),se.createElement("span",null," "))}))}}const _e="cloudrunResource";class Ze extends se.Component{constructor(e){super(e),this.spinnakerKindStateMap={serverGroupManagers:"serverGroupManager",serverGroups:"serverGroup"},this.state={url:""},this.loadUrl()}canOpen(){return!!this.props.manifest.manifest&&!!this.state.url}spinnakerKindFromCloudrunKind(e,t){return t[Object.keys(t).find((t=>t.toLowerCase()===e.toLowerCase()))]}resourceRegion(){return re(te(this.props,["manifest","manifest","metadata","annotations","artifact.spinnaker.io/location"],""))}getStateParams(e){const t=this.props.manifest.manifest.kind.toLowerCase(),n=this.props.manifest.manifest.metadata.name,a=this.resourceRegion(),i={accountId:this.props.accountId,provider:"cloudrun",region:a,reg:a,[e]:`${t} ${n}`};return i.region||"namespace"!==t||e!==_e||(i.region=n),i.region&&""!==i.region||(i.region="_"),i}loadUrl(){const e=te(this.props,["manifest","manifest","kind"],""),{accountId:t}=this.props;k.getAccountDetails(t).then((t=>{const n=this.spinnakerKindFromCloudrunKind(e,t.spinnakerKindMap),a=this.spinnakerKindStateMap[n]||_e,i=this.getStateParams(a),r=w.$state.href(`home.applications.application.insight.clusters.${a}`,i);this.setState({url:r})}))}render(){return this.canOpen()?se.createElement("a",{href:this.state.url,className:"clickable"},this.props.linkName):null}}class Je extends se.Component{pillStyle(e){return"Warning"===e.type?"alert":"Normal"===e.type?"success":""}render(){if(!this.props.manifest)return null;if(this.props.manifest&&(!this.props.manifest.events||0===this.props.manifest.events.length))return se.createElement("div",null,"No recent events found - Cloud Run does not store events for long.");const{events:e}=this.props.manifest,t=re(te(this.props.manifest,["manifest","metadata","annotations","artifact.spinnaker.io/location"],""));return e.map(((n,a)=>{const i=te(n,"firstTimestamp",""),r=te(n,"lastTimestamp","");let s=0,o=0;return i&&(s=pe.fromISO(i).toMillis()),r&&(o=pe.fromISO(r).toMillis()),se.createElement("div",{key:te(n,["metadata","uid"],String(a)),className:"info"},se.createElement("div",{className:"horizontal"},n.count&&se.createElement("div",{className:`pill ${this.pillStyle(n)}`},n.count," × ",se.createElement("b",null,n.reason))),(n.firstTimestamp||n.lastTimestamp)&&se.createElement("div",null,n.firstTimestamp===n.lastTimestamp&&se.createElement("div",null,se.createElement("i",null,y(s))),n.firstTimestamp!==n.lastTimestamp&&se.createElement("div",null,se.createElement("div",null,"First Occurrence: ",se.createElement("i",null,y(s))),se.createElement("div",null,"Last Occurrence: ",se.createElement("i",null,y(o))))),se.createElement("div",null,n.message),se.createElement("div",null,se.createElement(S,{account:this.props.manifest.account,location:t,podNamesProviders:[new E(this.props.manifest,n)],linkName:"Console Output (Raw)"})),a!==e.length-1&&se.createElement("br",null))}))}}function et({account:e,manifest:t}){return se.createElement(se.Fragment,null,se.createElement("dl",{className:"manifest-status",key:"manifest-status"},se.createElement("dt",null,t.manifest.kind),se.createElement("dd",null,se.createElement(A,{displayText:!0,text:t.manifest.metadata.name,toolTip:`Copy ${t.manifest.metadata.name}`})," ",se.createElement(Qe,{manifest:t}))),se.createElement("div",{className:"manifest-support-links",key:"manifest-support-links"},se.createElement(G,{linkName:"YAML",manifestText:ue(t.manifest),modalTitle:t.manifest.metadata.name}),se.createElement(Ze,{linkName:"Details",manifest:t,accountId:e})),se.createElement("div",{className:"manifest-events pad-left",key:"manifest-events"},se.createElement(Je,{manifest:t})))}Te("dl.manifest-status {\n display: block;\n margin: 0;\n}\ndl.manifest-status dt,\ndl.manifest-status dd {\n display: inline-block;\n}\ndl.manifest-status dt {\n margin-right: 4px;\n}\n.manifest-support-links {\n margin: 0 0 1em;\n}\n.manifest-support-links a {\n margin-right: 2em;\n}\n.manifest-events {\n margin: 0 0 2em;\n}\n");const tt=class{static subscribe(e,t,n){return tt.updateManifest(t,n),e.onRefresh(null,(()=>tt.updateManifest(t,n)))}static updateManifest(e,t){x.getManifest(e.account,e.location,e.name).then((e=>t(e)))}static manifestIdentifier(e){const t=e.kind.toLowerCase(),n=(e.metadata.namespace||"_").toLowerCase(),a=e.metadata.name.toLowerCase();return`${n} ${t} ${(e.apiVersion||"_").toLowerCase()} ${a}`}static stageManifestToManifestParams(e,t){return{account:t,name:tt.scopedKind(e)+" "+e.metadata.name,location:null==e.metadata.namespace?"_":e.metadata.namespace}}static apiGroup(e){const t=(e.apiVersion||"_").split("/");return t.length<2?"":t[0]}static isCRDGroup(e){return!tt.BUILT_IN_GROUPS.includes(tt.apiGroup(e))}static scopedKind(e){return tt.isCRDGroup(e)?e.kind+"."+tt.apiGroup(e):e.kind}};let nt=tt;nt.BUILT_IN_GROUPS=["","core","batch","apps","extensions","storage.k8s.io","apiextensions.k8s.io","apiregistration.k8s.io","policy","scheduling.k8s.io","settings.k8s.io","authorization.k8s.io","authentication.k8s.io","rbac.authorization.k8s.io","certifcates.k8s.io","networking.k8s.io"];class at extends se.Component{constructor(e){super(e),this.state={subscriptions:[],manifestIds:[]}}componentDidMount(){this.componentDidUpdate(this.props,this.state)}componentWillUnmount(){this.unsubscribeAll()}componentDidUpdate(e,t){const n=te(this.props.stage,["context","outputs.manifests"],[]).filter((e=>!!e)),a=n.map((e=>nt.manifestIdentifier(e))).sort();if(t.manifestIds.join("")!==a.join("")){this.unsubscribeAll();const e=n.map((e=>{const t=nt.manifestIdentifier(e);return{id:t,unsubscribe:this.subscribeToManifestUpdates(t,e),manifest:this.stageManifestToIManifest(e,this.props.stage.context.account)}}));this.setState({subscriptions:e,manifestIds:a})}}subscribeToManifestUpdates(e,t){const n=nt.stageManifestToManifestParams(t,this.props.stage.context.account);return nt.subscribe(this.props.application,n,(t=>{const n=this.state.subscriptions.findIndex((t=>t.id===e));if(-1!==n){const e={...this.state.subscriptions[n],manifest:t},a=[...this.state.subscriptions];a[n]=e,this.setState({subscriptions:a})}}))}unsubscribeAll(){this.state.subscriptions.forEach((({unsubscribe:e})=>e()))}stageManifestToIManifest(e,t){return{name:te(e,"metadata.name",""),moniker:null,account:t,cloudProvider:"cloudrun",location:te(e,"metadata.namespace",""),manifest:e,status:{},artifacts:[],events:[]}}render(){const{name:e,current:t,stage:n}=this.props,a=this.state.subscriptions.filter((e=>!!e.manifest)).map((e=>e.manifest));return se.createElement(D,{name:e,current:t},se.createElement(T,{stage:n,message:n.failureMessage}),a&&se.createElement("div",{className:"row"},se.createElement("div",{className:"col-md-12"},se.createElement("div",{className:"well alert alert-info"},a.map((e=>{const t=e.manifest.metadata.uid||nt.manifestIdentifier(e.manifest);return se.createElement(et,{key:t,manifest:e,account:n.context.account})}))))))}}at.title="deployStatus",c.pipeline.registerStage({label:"Deploy (Cloud Run)",description:"Deploy a Cloud Run manifest yaml/json file.",key:"deployCloudrunManifest",cloudProvider:"cloudrun",component:qe,executionDetailsSections:[at,$,N],producesArtifacts:!0,supportsCustomTimeout:!0,validators:[{type:"requiredField",fieldName:"account",fieldLabel:"Account"},{type:"requiredField",fieldName:"source",fieldLabel:"Source"},{type:"custom",validate:(e,t)=>{const n=te(t,"trafficManagement.enabled",!1),a=te(t,"trafficManagement.options.services",[]);if(n&&ie(a))return"Select at least one <strong>Service</strong> to enable Spinnaker-managed rollout strategy options.";if(n&&t.source===Ue.TEXT){const e=te(t,"manifests",[]).filter((e=>"ReplicaSet"===e.kind)),n=te(t,"trafficManagement.options.strategy"),a=parseInt(te(e,[0,"metadata","annotations",He]),10);if(n===We&&a<2)return`The max version history specified in your manifest conflicts with the behavior of the Red/Black rollout strategy. Please update your <strong>${He}</strong> annotation to a value greater than or equal to 2.`}return null}}],accountExtractor:e=>e.account?[e.account]:[],configAccountExtractor:e=>e.account?[e.account]:[],artifactExtractor:L.accumulateArtifacts(["manifestArtifactId","requiredArtifactIds"]),artifactRemover:M.removeArtifactFromFields(["manifestArtifactId","requiredArtifactIds"])});const it=I.providers.cloudrun||{defaults:{}};var rt,st;it&&(it.resetToOriginal=I.resetProvider("cloudrun")),(st=rt||(rt={})).TEXT="text",st.ARTIFACT="artifact";const ot=e=>{switch(e){case"createPipeline":return"Add";case"editPipeline":return"Done";default:return"Create"}};class lt{buildNewServerGroupCommand(e){return dt.buildNewServerGroupCommand(e,"cloudrun","create")}buildNewServerGroupCommandForPipeline(e,t){return dt.buildNewServerGroupCommandForPipeline(e,t)}buildServerGroupCommandFromPipeline(e,t,n,a){return dt.buildServerGroupCommandFromPipeline(e,t,n,a)}}const ct=class{static ServerGroupCommandIsValid(e){return!!e.moniker&&!!e.moniker.app}static copyAndCleanCommand(e){return Z(e)}static buildNewServerGroupCommandForPipeline(e,t){const n=this.buildNewServerGroupCommand({name:t.application},"cloudrun","createPipeline");return n.viewState={...n.viewState,pipeline:t,requiresTemplateSelection:!0,stage:e},n}static getExpectedArtifacts(e){return e.expectedArtifacts||[]}static buildServerGroupCommandFromPipeline(e,t,n,a){return ct.buildNewServerGroupCommand(e,"cloudrun","editPipeline").then((e=>e={...e,...t,backingData:{...e.metadata.backingData.backingData,expectedArtifacts:ct.getExpectedArtifacts(a)},credentials:t.account||e.metadata.backingData.credentials,viewState:{...e.metadata.backingData.viewState,stage:n,pipeline:a}}))}static getCredentials(e){const t=(e||[]).map((e=>e.name)),n=it.defaults.account;return t.includes(n)?n:t[0]}static getRegion(e,t){const n=e.find((e=>e.name===t));return n?n.region:null}static buildNewServerGroupCommand(e,t,n){const a={accounts:k.getAllAccountDetailsForProvider("cloudrun"),artifactAccounts:k.getArtifactAccounts()};return me.all(a).then((a=>{const{accounts:i}=a,r=i.some((e=>e.name===t))?i.find((e=>e.name===t)).name:i.length?i[0].name:null,s={mode:n,submitButtonLabel:ot(n),disableStrategySelection:"create"===n},o=r||this.getCredentials(i),l=this.getRegion(a.accounts,o),c="cloudrun";return{command:{application:e.name,configFiles:[""],cloudProvider:c,selectedProvider:c,provider:c,region:l,credentials:o,gitCredentialType:"NONE",manifest:null,sourceType:"git",configArtifacts:[],interestingHealthProviderNames:[],fromArtifact:!1,account:r,viewState:s},metadata:{backingData:a}}}))}};let dt=ct;dt.$inject=["$q"];const ut="spinnaker.cloudrun.serverGroup.commandBuilder.service";function pt({accounts:e,onAccountSelect:t,selectedAccount:n,formik:a,onEnterStack:i,detailsChanged:r,app:s}){const{values:o}=a,{stack:l="",freeFormDetails:c}=o,d=F.getClusterName(s.name,l,c),u=!s.clusters.find((e=>e.name===d)),h=s.serverGroups.data.filter((e=>e.cluster===d&&e.account===o.command.credentials&&e.region===o.command.region)).sort(((e,t)=>e.createdTime-t.createdTime)),g=h.length?h.pop():null;return se.createElement("div",{className:"form-horizontal"},se.createElement("div",{className:"form-group"},se.createElement("div",{className:"col-md-3 sm-label-right"},"Account"),se.createElement("div",{className:"col-md-7"},se.createElement(m,{value:n,onChange:e=>t(e.target.value),readOnly:!1,accounts:e,provider:"cloudrun"}))),se.createElement("div",{className:"form-group"},se.createElement("div",{className:"col-md-3 sm-label-right"},"Stack ",se.createElement(p,{id:"cloudrun.serverGroup.stack"})),se.createElement("div",{className:"col-md-7"},se.createElement("input",{type:"text",className:"form-control input-sm no-spel",value:l,onChange:e=>i(e.target.value)}))),se.createElement("div",{className:"form-group"},se.createElement("div",{className:"col-md-3 sm-label-right"},"Detail ",se.createElement(p,{id:"cloudrun.serverGroup.detail"})),se.createElement("div",{className:"col-md-7"},se.createElement("input",{type:"text",className:"form-control input-sm no-spel",value:c,onChange:e=>r(e.target.value)}))),!o.command.viewState.hideClusterNamePreview&&se.createElement(R,{createsNewCluster:u,latestServerGroupName:null==g?void 0:g.name,mode:o.command.viewState.mode,namePreview:d,navigateToLatestServerGroup:()=>{const{values:e}=a,t={provider:e.command.selectedProvider,accountId:g.account,region:g.region,serverGroup:g.name},{$state:n}=w;n.is("home.applications.application.insight.clusters")?n.go(".serverGroup",t):n.go("^.serverGroup",t)}}))}e(ut,[]).service("cloudrunV2ServerGroupCommandBuilder",lt);class mt extends se.Component{constructor(){super(...arguments),this.accountUpdated=e=>{const{formik:t}=this.props;t.values.command.account=e,t.setFieldValue("account",e)},this.stackChanged=e=>{const{setFieldValue:t,values:n}=this.props.formik;n.command.stack=e,t("stack",e)},this.freeFormDetailsChanged=e=>{const{setFieldValue:t,values:n}=this.props.formik;n.command.freeFormDetails=e,t("freeFormDetails",e)}}render(){var e,t,n;const{formik:a,app:i}=this.props;return se.createElement(pt,{accounts:(null==(t=null==(e=a.values.metadata)?void 0:e.backingData)?void 0:t.accounts)||[],onAccountSelect:this.accountUpdated,selectedAccount:(null==(n=a.values.command)?void 0:n.account)||"",onEnterStack:this.stackChanged,formik:a,detailsChanged:this.freeFormDetailsChanged,app:i})}}function ht({configFiles:e,onEnterConfig:t}){const[n,a]=oe(e);return se.createElement("div",{className:"form-horizontal"},se.createElement("div",{className:"form-group"},n.map(((e,i)=>se.createElement(se.Fragment,null,se.createElement("div",{className:"col-md-3 sm-label-right"},"Service Yaml",se.createElement(p,{id:"cloudrun.serverGroup.configFiles"})," "),se.createElement("div",{className:"col-md-8",key:i},se.createElement(P,{name:"text"+i,value:e,rows:10,onChange:e=>function(e,i){if(9===e.which){e.preventDefault();const t=e.target.selectionStart,n=e.target.value;e.target.value=`${n.substring(0,t)} ${n.substring(t)}`,e.target.selectionStart+=2}const r=[...n];r[i]=e.target.value,a(r),t(r)}(e,i)})))))))}class gt extends se.Component{constructor(){super(...arguments),this.configUpdated=e=>{const{formik:t}=this.props;t.values.command.configFiles=e,t.setFieldValue("configFiles",e)}}render(){const{formik:e}=this.props;return se.createElement(ht,{configFiles:e.values.configFiles||e.values.command.configFiles,onEnterConfig:this.configUpdated})}}const ft=class extends se.Component{constructor(e){super(e),this._isUnmounted=!1,this.onTaskComplete=()=>{this.props.application.serverGroups.refresh(),this.props.application.serverGroups.onNextRefresh(null,this.onApplicationRefresh)},this.onApplicationRefresh=()=>{if(this._isUnmounted)return;const{command:e}=this.props,{taskMonitor:t}=this.state,n=t.task.execution.stages.find((e=>"cloneServerGroup"===e.type));if(n&&n.context["deploy.server.groups"]){const t=n.context["deploy.server.groups"][e.command.region];if(t){const n={serverGroup:t,accountId:e.command.credentials,region:e.command.region,provider:"cloudrun"};let a="^.^.^.clusters.serverGroup";w.$state.includes("**.clusters.serverGroup")&&(a="^.serverGroup"),w.$state.includes("**.clusters.cluster.serverGroup")&&(a="^.^.serverGroup"),w.$state.includes("**.clusters")&&(a=".serverGroup"),w.$state.go(a,n)}}},this.submit=e=>{const t=dt.copyAndCleanCommand(e.command);if(!("editPipeline"===t.viewState.mode||"createPipeline"===t.viewState.mode)){const e=()=>w.serverGroupWriter.cloneServerGroup(t,this.props.application);return this.state.taskMonitor.submit(e),null}this.props.closeModal&&this.props.closeModal(t)},e.command||dt.buildNewServerGroupCommand(e.application,"cloudrun","create").then((e=>{Object.assign(this.state.command,e),this.setState({loaded:!0})})),this.state={loaded:!!e.command,command:e.command||{},taskMonitor:new s({application:e.application,title:("Create"===e.command.command.viewState.submitButtonLabel?"Creating":"Updating")+" your Server Group",modalInstance:s.modalInstanceEmulation((()=>this.props.dismissModal())),onTaskComplete:this.onTaskComplete})}}static show(e){return z.show(ft,e,{dialogClassName:"wizard-modal modal-lg"})}render(){const{dismissModal:e,application:t}=this.props,{loaded:n,taskMonitor:a,command:i}=this.state,r=this.state.command.command.viewState.submitButtonLabel;return se.createElement(O,{heading:("Add"===r||"Create"===r?"Create New":"Update")+" Server Group",initialValues:i,loading:!n,taskMonitor:a,dismissModal:e,closeModal:this.submit,submitButtonLabel:r,render:({formik:e,nextIdx:n,wizard:a})=>se.createElement(se.Fragment,null,se.createElement(U,{label:"Basic Settings",wizard:a,order:n(),render:({innerRef:n})=>se.createElement(mt,{ref:n,formik:e,app:t})}),se.createElement(U,{label:"Service Yaml",wizard:a,order:n(),render:({innerRef:t})=>se.createElement(gt,{ref:t,formik:e})}))})}};let vt=ft;vt.defaultProps={closeModal:V,dismissModal:V};class bt{}bt.PLATFORM="Cloud Run Service";class Bt{constructor(e,t,n,a,i){this.$state=e,this.$scope=t,this.app=a,this.serverGroupWriter=i,this.state={loading:!0},this.extractServerGroup(n).then((()=>{this.$scope.$$destroyed||this.app.getDataSource("serverGroups").onRefresh(this.$scope,(()=>this.extractServerGroup(n)))})).catch((()=>this.autoClose()))}canDestroyServerGroup(){if(this.serverGroup){return!this.serverGroup.tags.isLatest&&!!this.serverGroup.disabled}return!1}destroyServerGroup(){const e={name:this.serverGroup.name,accountId:this.serverGroup.account,region:this.serverGroup.region},t={application:this.app,title:"Destroying "+this.serverGroup.name,onTaskComplete:()=>{this.$state.includes("**.serverGroup",e)&&this.$state.go("^")}},n={header:"Really destroy "+this.serverGroup.name+"?",buttonText:"Destroy "+this.serverGroup.name,account:this.serverGroup.account,taskMonitorConfig:t,submitMethod:e=>this.serverGroupWriter.destroyServerGroup(this.serverGroup,this.app,e),askForReason:!0,platformHealthOnlyShowOverride:this.app.attributes.platformHealthOnlyShowOverride,platformHealthType:bt.PLATFORM,interestingHealthProviderNames:[]};this.app.attributes.platformHealthOnlyShowOverride&&this.app.attributes.platformHealthOnly&&(n.interestingHealthProviderNames=[bt.PLATFORM]),o.confirm(n)}autoClose(){this.$scope.$$destroyed||(this.$state.params.allowModalToStayOpen=!0,this.$state.go("^",null,{location:"replace"}))}extractServerGroup({name:e,accountId:t,region:n}){return j.getServerGroup(this.app.name,t,n,e).then((a=>{let i=this.app.getDataSource("serverGroups").data.find((a=>a.name===e&&a.account===t&&a.region===n));i||this.app.getDataSource("loadBalancers").data.some((n=>n.account===t&&n.serverGroups.some((t=>{let n=!1;return t.name===e&&(i=t,n=!0),n})))),this.serverGroup={...a,...i},this.state.loading=!1}))}}Bt.$inject=["$state","$scope","serverGroup","app","serverGroupWriter"];const kt="spinnaker.cloudrun.serverGroup.details.controller";e(kt,[Y]).controller("cloudrunV2ServerGroupDetailsCtrl",Bt);class Ct{constructor(e){this.$q=e}normalizeServerGroup(e){return this.$q.resolve(e)}convertServerGroupCommandToDeployConfiguration(e){return new wt(e)}}Ct.$inject=["$q"];class wt{constructor(e){this.cloudProvider="cloudrun",this.provider="cloudrun",this.credentials=e.credentials,this.account=e.credentials,this.application=e.application,this.stack=e.stack,this.freeFormDetails=e.freeFormDetails,this.region=e.region,this.strategy=e.strategy,this.type=e.type,this.fromArtifact=e.fromArtifact,this.gitCredentialType=e.gitCredentialType,this.configFiles=e.configFiles,this.sourceType=e.sourceType,this.interestingHealthProviderNames=e.interestingHealthProviderNames||[],this.configArtifacts=[]}}const yt="spinnaker.cloudrun.serverGroup.transformer.service";e(yt,[]).service("cloudrunV2ServerGroupTransformer",Ct);Te('.cloud-provider-logo .icon-cloudrun {\n -webkit-mask-image: url("data:image/svg+xml,%3Csvg width%3D%2224px%22 height%3D%2224px%22 viewBox%3D%220 0 24 24%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cdefs%3E %3Cstyle%3E .cls-1 %7B fill%3A %23aecbfa%3B %7D .cls-1%2C .cls-2 %7B fill-rule%3A evenodd%3B %7D .cls-2 %7B fill%3A %234285f4%3B %7D %3C%2Fstyle%3E %3C%2Fdefs%3E %3Ctitle%3EIcon_24px_CloudRun_Color%3C%2Ftitle%3E %3Cg data-name%3D%22Product Icons%22%3E %3Cg%3E %3Cpolygon class%3D%22cls-1%22 points%3D%228.9 2.63 12.02 12 21.38 12 8.9 2.63%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%2221.38 12 12.02 12 8.9 21.38 21.38 12%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%223.44 21.38 6.57 19.81 8.9 12 5.78 12 3.44 21.38%22 %2F%3E %3Cpolygon class%3D%22cls-1%22 points%3D%223.44 2.63 5.78 12 8.9 12 6.57 4.19 3.44 2.63%22 %2F%3E %3C%2Fg%3E %3C%2Fg%3E%3C%2Fsvg%3E");\n mask-image: url("data:image/svg+xml,%3Csvg width%3D%2224px%22 height%3D%2224px%22 viewBox%3D%220 0 24 24%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cdefs%3E %3Cstyle%3E .cls-1 %7B fill%3A %23aecbfa%3B %7D .cls-1%2C .cls-2 %7B fill-rule%3A evenodd%3B %7D .cls-2 %7B fill%3A %234285f4%3B %7D %3C%2Fstyle%3E %3C%2Fdefs%3E %3Ctitle%3EIcon_24px_CloudRun_Color%3C%2Ftitle%3E %3Cg data-name%3D%22Product Icons%22%3E %3Cg%3E %3Cpolygon class%3D%22cls-1%22 points%3D%228.9 2.63 12.02 12 21.38 12 8.9 2.63%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%2221.38 12 12.02 12 8.9 21.38 21.38 12%22 %2F%3E %3Cpolygon class%3D%22cls-2%22 points%3D%223.44 21.38 6.57 19.81 8.9 12 5.78 12 3.44 21.38%22 %2F%3E %3Cpolygon class%3D%22cls-1%22 points%3D%223.44 2.63 5.78 12 8.9 12 6.57 4.19 3.44 2.63%22 %2F%3E %3C%2Fg%3E %3C%2Fg%3E%3C%2Fsvg%3E");\n background-color: #4285f4;\n}\n');const St="spinnaker.cloudrun";e(St,[ge,ut,kt,yt,De,Me,Ne,fe,ke,we,Ae,ze,be]).config((()=>{l.registerProvider("cloudrun",{name:"cloudrun",logo:{path:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAFAUlEQVRYR82YfUwcRRjGn5m7veO4rZI2aKuk1kRNjQ012rRANB53YNpYtFHS1Aj9ktaPtGINpPWgKQ0sVNvUNGirgYBJSTSA1H6ltpTrVYtUS2u1aRS/LSRFEmqBPcC7vR2zixwc7N4tJ02c5P64zMwzv332fd+ZWYL/USNGWFL3MpvVJy4xMlZzTJA/7y0hw9HmR4VxlokVIGQzwOzRxCL0D4DgA4+bL4ykERHGKfiqAJb3HyAmTCXVniL7Bj09XRhXqZjBKJqnD2REicjIbNnOn9bS1YVxlvuOgrHl0w0DQo553PYswzAuQcxhwMFpB/lXkAC5LUV83UT9Sc44SpjZxPnaGLDoFsK0BwP2VG8JkcavMQnGWSYWgGD3rQIJ6TIUeor5PbowjrcGk6gktwFI0oKZk0Bw/SYLdSXNpOi6IcfK3SWbaap3a3zXqECYM85ycTcYCvTUX3JZ0NMn41D7iLt5Dgv6hhgavgrEBkSwZ3ztCcE4ynyLKGGKK2Y95ZT7TBBWxuHzH4LY2TSMBUkU+1bbcOn3IPZ95o/FJUlmJNVbbG9X0350YacgKtmTE+kRORNQs9GGO2+nyKsawrVeGe+vt+HyH0E88yiHmrP+WFyq8xTxuSEYV2n/ckbpUSNeFzxlxbKFZuxv9uPUFQkrUzgkz6U4/o2E7MUcbvgY3j01NZeILGe1bL/tmOpMernYTBgyjMBkLjBj29NWfNEhofKkH/MSKXatikPO/kEwBmQv4bA02YyD5wKGXWIEp8+4+UziFPrzAFplBEQZM4snqH8tHjcHGTZWD6nTKtfYUHvWr8aO0u6fTbHpSSt+6ZFR5THqkryBOAXfEYBplmc9wPfW2jD/Loqi+mH81C1jzeMWzEvU3lnmJFDUtfpx+GJYfdOSPkHSBbGHAIlGnRlN6efTOPU1KL+HkkzY8aw1okTLVQk1Xj+6+8bq1MQJJL1MrCYEL04FpjrPhnvvGHNm3RMWNai1mlIkFeBzHRL8QWBgSAeGkAbiKhWXMooTRmFmzSCo3xweMwfW29RYmthOfiepIP3jAAJBhP0PVV8Zy1QFpyDWAlhrBEhJ31cyLKFsevBuip3PxYVN7eyV8XFbABd+HQnoiU2Sgb7BMIc+9BTx61QYhyA+TAGl+oaragjtfSEOC+8xqXXG+72E3Mc4ZD3ChUYeuRRAw/kA/o4Sr0EZakYCGJaBVG8Rf3msApcPVoDJ26K50+K2QxF6tXYIf/mYuh0oG+hvPTLqWgO40qnthq5DQ2SXxx3/ptI/tjeViLMpp7ozTw8o7QETSrOVvUlSq2zyXBOKV1jRdCGgvpapNkrR+WcvW+wt4bvDYNTYKRNfB8E7eqJK5f365yC+vTby9EoWffmjhI7rsR0jgjLb2rSFfzsUxBMXdgnKKY+laAFZzQAfF/V2Y8ggAlysz7eHnSYnKbuEgVUM5CM9xekCCshs9adb+LBztuZjOgXfIYCt0AXiAN4au0MM9Hhjvm3SzUNT0VE64KCUnInkdxwH2GME8vtZ5uHCyXcn/XuT4DsAsJenG4gBNY35ds3tRxfGUd4/nzKqpHpCJCCbhSDeYihmAbB+2cTSPtk046rWjMh37dKBElCyI9pSRoEYUNGYb3fr6UWNQqcKRAuifYWItxDYdBwihIgyY5WRQCYVPT1io99nZvKc5jnCxKytDW+QkWNhhBbVmWgC09n/Dw0j4+SJOXQTAAAAAElFTkSuQmCC"},instance:{detailsTemplateUrl:"cloudrun/src/instance/details/details.html",detailsController:"cloudrunInstanceDetailsCtrl"},serverGroup:{CloneServerGroupModal:vt,commandBuilder:"cloudrunV2ServerGroupCommandBuilder",detailsController:"cloudrunV2ServerGroupDetailsCtrl",detailsTemplateUrl:"cloudrun/src/serverGroup/details/details.html",transformer:"cloudrunV2ServerGroupTransformer",skipUpstreamStageCheck:!0},loadBalancer:{transformer:"cloudrunLoadBalancerTransformer",createLoadBalancerTemplateUrl:"cloudrun/src/loadBalancer/configure/wizard/wizard.html",createLoadBalancerController:"cloudrunLoadBalancerWizardCtrl",detailsTemplateUrl:"cloudrun/src/loadBalancer/details/details.html",detailsController:"cloudrunLoadBalancerDetailsCtrl"}})})),K.registerProvider("cloudrun",["custom","redblack","rollingpush","rollingredblack"]),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/instance/details/details.html",'<div class="details-panel">\n <div class="header">\n <instance-details-header\n health-state="ctrl.instance.healthState"\n instance-id="ctrl.instance ? ctrl.instance.name : ctrl.instanceIdNotFound"\n loading="ctrl.state.loading"\n standalone="false"\n ></instance-details-header>\n <div ng-if="!ctrl.state.loading">\n <div class="actions">\n <div class="dropdown" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>\n Instance Actions <span class="caret"></span>\n </button>\n </div>\n </div>\n </div>\n </div>\n <div class="content" ng-if="!ctrl.state.loading && ctrl.instance">\n <collapsible-section heading="Instance Information" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <dt>Launched</dt>\n <dd ng-if="ctrl.instance.launchTime">{{ctrl.instance.launchTime | timestamp}}</dd>\n <dt>In</dt>\n <dd><account-tag account="ctrl.instance.account" pad="right"></account-tag>{{}}</dd>\n <dt ng-if="ctrl.instance.serverGroup">Server Group</dt>\n <dd ng-if="ctrl.instance.serverGroup">\n <a\n ui-sref="^.serverGroup({region: ctrl.instance.region,\n accountId: ctrl.instance.account,\n serverGroup: ctrl.instance.serverGroup,\n provider: \'cloudrun\'})"\n >{{ctrl.instance.serverGroup}}</a\n >\n </dd>\n <dt>Region</dt>\n <dd>{{ctrl.instance.region}}</dd>\n <cloudrun-conditional-dt-dd\n component="ctrl.instance"\n key="vmZoneName"\n label="Zone"\n ></cloudrun-conditional-dt-dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Status" expanded="true">\n <dl>\n <dt>Load Balancer</dt>\n <dd>\n <span\n class="pull-left"\n uib-tooltip="{{ctrl.instance.healthState === \'Up\' ? ctrl.upToolTip : ctrl.outOfServiceToolTip}}"\n tooltip-placement="right"\n >\n <span class="glyphicon glyphicon-{{ctrl.instance.healthState}}-triangle"></span>\n {{ctrl.instance.loadBalancers[0]}}\n </span>\n </dd>\n </dl>\n </collapsible-section>\n </div>\n <div class="content" ng-if="!ctrl.state.loading && !ctrl.instance">\n <div class="content-section">\n <div class="content-body text-center">\n <h3>Instance not found.</h3>\n </div>\n </div>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/serverGroup/details/details.html",'<div class="details-panel" ng-class="{disabled: ctrl.serverGroup.isDisabled || ctrl.serverGroup.disabled}">\n <div class="header" ng-if="ctrl.state.loading">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <h4 class="text-center">\n <span us-spinner="{radius:20, width:6, length: 12}"></span>\n </h4>\n </div>\n\n <div class="header" ng-if="!ctrl.state.loading">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <div class="header-text horizontal middle">\n <cloud-provider-logo provider="ctrl.serverGroup.type" height="\'36px\'" width="\'36px\'"></cloud-provider-logo>\n <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>{{ctrl.serverGroup.name}}</h3>\n </div>\n <div class="actions">\n <div class="dropdown" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>\n Server Group Actions <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li\n ng-if="ctrl.serverGroup.tags.isLatest"\n uib-tooltip="You cannot destroy the latest server group (revision) . \n You may be able to delete this server group\'s load balancer."\n class="disabled"\n >\n <a href>Destroy</a>\n </li>\n <li ng-if="ctrl.canDestroyServerGroup() && !ctrl.serverGroup.tags.isLatest">\n <a href ng-click="ctrl.destroyServerGroup()">Destroy</a>\n </li>\n <li\n ng-if="(!ctrl.canDestroyServerGroup() && !ctrl.serverGroup.tags.isLatest)"\n uib-tooltip="You cannot destroy this server group while it is receiving traffic. \n You may be able to delete this server group\'s load balancer."\n class="disabled"\n >\n <a href>Destroy</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n <div class="content" ng-if="!ctrl.state.loading">\n <div class="band band-info" ng-if="ctrl.serverGroup.isDisabled || ctrl.serverGroup.disabled">Disabled</div>\n <server-group-running-tasks-details\n server-group="ctrl.serverGroup"\n application="ctrl.app"\n ></server-group-running-tasks-details>\n <collapsible-section heading="Server Group Information" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <dt>Created</dt>\n <dd>{{ctrl.serverGroup.createdTime | timestamp}}</dd>\n <dt>In</dt>\n <dd><account-tag account="ctrl.serverGroup.account"></account-tag></dd>\n <dt>Region</dt>\n <dd>{{ctrl.serverGroup.region}}</dd>\n </dl>\n </collapsible-section>\n\n <collapsible-section heading="Size" expanded="true">\n <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup.capacity.min === ctrl.serverGroup.capacity.max">\n <dt>Min/Max</dt>\n <dd>{{ctrl.serverGroup.capacity.min}}</dd>\n <dt>Current</dt>\n <dd>{{ctrl.serverGroup.instances.length}}</dd>\n </dl>\n <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup.capacity.min !== ctrl.serverGroup.capacity.max">\n <dt>Min</dt>\n <dd>{{ctrl.serverGroup.capacity.min}}</dd>\n <dt>Max</dt>\n <dd>{{ctrl.serverGroup.capacity.max}}</dd>\n <dt>Current</dt>\n <dd>{{ctrl.serverGroup.instances.length}}</dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Health" expanded="true">\n <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup">\n <dt>Instances</dt>\n <dd>\n <health-counts container="ctrl.serverGroup.instanceCounts" class="pull-left"></health-counts>\n </dd>\n </dl>\n </collapsible-section>\n </div>\n</div>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/loadBalancer/configure/wizard/wizard.html",'<form name="form">\n <div ng-if="ctrl.state.loading && !ctrl.isNew" style="height: 200px" class="horizontal center middle">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n <v2-modal-wizard\n heading="{{::ctrl.heading}}"\n task-monitor="ctrl.taskMonitor"\n dismiss="$dismiss()"\n ng-if="!ctrl.state.loading || ctrl.isNew"\n >\n <div ng-if="!ctrl.isNew">\n <v2-wizard-page key="basic-settings" label="Basic Settings" mark-complete-on-view="false">\n <cloudrun-load-balancer-basic-settings\n load-balancer="ctrl.loadBalancer"\n application="ctrl.application"\n for-pipeline-config="ctrl.forPipelineConfig"\n ></cloudrun-load-balancer-basic-settings>\n </v2-wizard-page>\n </div>\n </v2-modal-wizard>\n <cloudrun-load-balancer-message\n ng-if="ctrl.isNew"\n column-offset="1"\n columns="10"\n show-create-message="true"\n ></cloudrun-load-balancer-message>\n <div class="modal-footer">\n <button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>\n <submit-button\n ng-if="!ctrl.isNew && ctrl.showSubmitButton()"\n label="ctrl.submitButtonLabel"\n is-disabled="cloudrunLoadBalancerForm.$invalid || ctrl.taskMonitor.submitting || ctrl.state.loading"\n submitting="ctrl.taskMonitor.submitting"\n on-click="ctrl.submit()"\n is-new="ctrl.isNew"\n >\n </submit-button>\n </div>\n</form>\n')}]),window.angular.module("ng").run(["$templateCache",function(e){e.put("cloudrun/src/loadBalancer/details/details.html",'<div class="details-panel">\n <div ng-if="ctrl.state.loading" class="header">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <div class="horizontal center middle">\n <loading-spinner size="\'small\'"></loading-spinner>\n </div>\n </div>\n\n <div ng-if="!ctrl.state.loading" class="header">\n <div class="close-button">\n <a class="btn btn-link" ui-sref="^">\n <span class="glyphicon glyphicon-remove"></span>\n </a>\n </div>\n <div class="header-text horizontal middle">\n <i class="fa icon-sitemap"></i>\n <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>{{ctrl.loadBalancer.name}}</h3>\n </div>\n <div>\n <div class="actions">\n <div class="dropdown" uib-dropdown dropdown-append-to-body>\n <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>\n Load Balancer Actions <span class="caret"></span>\n </button>\n <ul class="dropdown-menu" uib-dropdown-menu role="menu">\n <li><a href ng-click="ctrl.editLoadBalancer()">Edit Load Balancer</a></li>\n <li ng-if="ctrl.canDeleteLoadBalancer()">\n <a href ng-click="ctrl.deleteLoadBalancer()">Delete Load Balancer</a>\n </li>\n <li\n ng-if="!ctrl.canDeleteLoadBalancer()"\n uib-tooltip="You cannot delete a default service."\n class="disabled"\n >\n <a href>Delete Load Balancer</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n </div>\n\n <div ng-if="!ctrl.state.loading" class="content">\n <collapsible-section heading="Load Balancer Details" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <dt>In</dt>\n <dd><account-tag account="ctrl.loadBalancer.account" pad="right"></account-tag></dd>\n <dt>Region</dt>\n <dd>{{ctrl.loadBalancer.region}}</dd>\n <dt ng-if="ctrl.loadBalancer.serverGroups.length">Server Groups</dt>\n <dd ng-if="ctrl.loadBalancer.serverGroups.length">\n <ul>\n <li ng-repeat="serverGroup in ctrl.loadBalancer.serverGroups | orderBy: [\'isDisabled\', \'-name\']">\n <a\n ui-sref="^.serverGroup({region: serverGroup.region,\n accountId: serverGroup.account,\n serverGroup: serverGroup.name,\n provider: \'cloudrun\'})"\n >\n {{serverGroup.name}}\n </a>\n </li>\n </ul>\n </dd>\n </dl>\n </collapsible-section>\n <collapsible-section heading="Status" expanded="true">\n <health-counts class="pull-left" container="ctrl.loadBalancer.instanceCounts"></health-counts>\n </collapsible-section>\n <collapsible-section heading="Traffic Split" expanded="true">\n <dl class="dl-horizontal dl-narrow">\n <ul>\n <li ng-repeat="trafficTarget in ctrl.loadBalancer.split.trafficTargets">\n {{trafficTarget.revisionName}}:<span class="pull-right">{{trafficTarget.percent}}</span>\n </li>\n </ul>\n </dl>\n </collapsible-section>\n <collapsible-section heading="DNS" expanded="true">\n <dl class="dl-narrow">\n <cloudrun-component-url-details component="ctrl.loadBalancer"></cloudrun-component-url-details>\n </dl>\n </collapsible-section>\n </div>\n</div>\n')}]);export{Me as CLOUDRUN_LOAD_BALANCER_DETAILS_CTRL,De as CLOUDRUN_LOAD_BALANCER_TRANSFORMER,Ne as CLOUDRUN_LOAD_BALANCER_WIZARD_CTRL,St as CLOUDRUN_MODULE,ut as CLOUDRUN_SERVER_GROUP_COMMAND_BUILDER,kt as CLOUDRUN_SERVER_GROUP_DETAILS_CTRL,yt as CLOUDRUN_SERVER_GROUP_TRANSFORMER,wt as CloudrunDeployDescription,xe as CloudrunLoadBalancerTransformer,Ge as CloudrunLoadBalancerUpsertDescription,dt as CloudrunServerGroupCommandBuilder,lt as CloudrunV2ServerGroupCommandBuilder,Ct as CloudrunV2ServerGroupTransformer,rt as ServerGroupSource};
|
|
2598
2
|
//# sourceMappingURL=index.js.map
|