@spinnaker/cloudrun 0.0.0-2025.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE.txt +203 -0
  3. package/dist/cloudrun.module.d.ts +4 -0
  4. package/dist/cloudrun.settings.d.ts +7 -0
  5. package/dist/common/cloudrunHealth.d.ts +3 -0
  6. package/dist/common/componentUrlDetails.component.d.ts +1 -0
  7. package/dist/common/conditionalDescriptionListItem.component.d.ts +1 -0
  8. package/dist/common/domain/ICloudrunInstance.d.ts +20 -0
  9. package/dist/common/domain/ICloudrunLoadBalancer.d.ts +18 -0
  10. package/dist/common/domain/index.d.ts +2 -0
  11. package/dist/common/loadBalancerMessage.component.d.ts +1 -0
  12. package/dist/help/cloudrun.help.d.ts +1 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.js +2598 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/instance/details/details.controller.d.ts +1 -0
  17. package/dist/interfaces/index.d.ts +1 -0
  18. package/dist/interfaces/infrastructure.types.d.ts +18 -0
  19. package/dist/loadBalancer/configure/wizard/allocationConfigurationRow.component.d.ts +1 -0
  20. package/dist/loadBalancer/configure/wizard/basicSettings.component.d.ts +1 -0
  21. package/dist/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.d.ts +1 -0
  22. package/dist/loadBalancer/configure/wizard/wizard.controller.d.ts +2 -0
  23. package/dist/loadBalancer/details/details.controller.d.ts +1 -0
  24. package/dist/loadBalancer/index.d.ts +3 -0
  25. package/dist/loadBalancer/loadBalancerTransformer.d.ts +38 -0
  26. package/dist/manifest/ManifestSource.d.ts +4 -0
  27. package/dist/manifest/index.d.ts +2 -0
  28. package/dist/manifest/manifest.service.d.ts +25 -0
  29. package/dist/manifest/manifestCommandBuilder.service.d.ts +30 -0
  30. package/dist/manifest/wizard/BasicSettings.d.ts +17 -0
  31. package/dist/pipeline/pipeline.module.d.ts +1 -0
  32. package/dist/pipeline/stages/deployManifest/DeployStageConfig.d.ts +15 -0
  33. package/dist/pipeline/stages/deployManifest/DeployStageForm.d.ts +23 -0
  34. package/dist/pipeline/stages/deployManifest/ManifestBindArtifactsSelector.d.ts +17 -0
  35. package/dist/pipeline/stages/deployManifest/deploy.validator.d.ts +2 -0
  36. package/dist/pipeline/stages/deployManifest/deployStage.d.ts +1 -0
  37. package/dist/pipeline/stages/deployManifest/manifestStatus/DeployStatus.d.ts +22 -0
  38. package/dist/pipeline/stages/deployManifest/manifestStatus/DeployStatusPills.d.ts +8 -0
  39. package/dist/pipeline/stages/deployManifest/manifestStatus/ManifestDetailsLink.d.ts +20 -0
  40. package/dist/pipeline/stages/deployManifest/manifestStatus/ManifestEvents.d.ts +9 -0
  41. package/dist/pipeline/stages/deployManifest/manifestStatus/ManifestStatus.d.ts +8 -0
  42. package/dist/pipeline/stages/deployManifest/serverGroupNamePreview.d.ts +9 -0
  43. package/dist/pipeline/stages/editLoadBalancer/cloudrunEditLoadBalancerStage.d.ts +1 -0
  44. package/dist/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.d.ts +1 -0
  45. package/dist/rolloutStrategy/redblack.strategy.d.ts +2 -0
  46. package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +74 -0
  47. package/dist/serverGroup/configure/wizard/BasicSettings.d.ts +29 -0
  48. package/dist/serverGroup/configure/wizard/ConfigFiles.d.ts +15 -0
  49. package/dist/serverGroup/configure/wizard/serverGroupWizard.d.ts +25 -0
  50. package/dist/serverGroup/details/details.controller.d.ts +1 -0
  51. package/dist/serverGroup/index.d.ts +3 -0
  52. package/dist/serverGroup/serverGroupTransformer.service.d.ts +31 -0
  53. package/package.json +58 -0
  54. package/src/cloudrun.module.ts +73 -0
  55. package/src/cloudrun.settings.ts +14 -0
  56. package/src/common/cloudrunHealth.ts +3 -0
  57. package/src/common/componentUrlDetails.component.ts +22 -0
  58. package/src/common/conditionalDescriptionListItem.component.ts +37 -0
  59. package/src/common/domain/ICloudrunInstance.ts +21 -0
  60. package/src/common/domain/ICloudrunLoadBalancer.ts +18 -0
  61. package/src/common/domain/index.ts +2 -0
  62. package/src/common/loadBalancerMessage.component.html +11 -0
  63. package/src/common/loadBalancerMessage.component.ts +13 -0
  64. package/src/help/cloudrun.help.ts +99 -0
  65. package/src/index.ts +3 -0
  66. package/src/instance/details/details.controller.ts +84 -0
  67. package/src/instance/details/details.html +68 -0
  68. package/src/interfaces/index.ts +1 -0
  69. package/src/interfaces/infrastructure.types.ts +23 -0
  70. package/src/loadBalancer/configure/wizard/allocationConfigurationRow.component.ts +70 -0
  71. package/src/loadBalancer/configure/wizard/basicSettings.component.html +44 -0
  72. package/src/loadBalancer/configure/wizard/basicSettings.component.ts +86 -0
  73. package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html +45 -0
  74. package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.ts +84 -0
  75. package/src/loadBalancer/configure/wizard/wizard.controller.ts +157 -0
  76. package/src/loadBalancer/configure/wizard/wizard.html +39 -0
  77. package/src/loadBalancer/configure/wizard/wizard.less +9 -0
  78. package/src/loadBalancer/details/details.controller.ts +140 -0
  79. package/src/loadBalancer/details/details.html +89 -0
  80. package/src/loadBalancer/index.ts +3 -0
  81. package/src/loadBalancer/loadBalancerTransformer.ts +168 -0
  82. package/src/logo/cloudrun.icon.svg +27 -0
  83. package/src/logo/cloudrun.logo.less +6 -0
  84. package/src/logo/cloudrun.logo.png +0 -0
  85. package/src/manifest/ManifestSource.ts +4 -0
  86. package/src/manifest/index.ts +2 -0
  87. package/src/manifest/manifest.service.ts +89 -0
  88. package/src/manifest/manifestCommandBuilder.service.ts +116 -0
  89. package/src/manifest/wizard/BasicSettings.tsx +57 -0
  90. package/src/pipeline/pipeline.module.ts +6 -0
  91. package/src/pipeline/stages/deployManifest/DeployStageConfig.tsx +73 -0
  92. package/src/pipeline/stages/deployManifest/DeployStageForm.tsx +185 -0
  93. package/src/pipeline/stages/deployManifest/ManifestBindArtifactsSelector.tsx +69 -0
  94. package/src/pipeline/stages/deployManifest/deploy.validator.ts +38 -0
  95. package/src/pipeline/stages/deployManifest/deployStage.ts +28 -0
  96. package/src/pipeline/stages/deployManifest/manifestStatus/DeployStatus.tsx +108 -0
  97. package/src/pipeline/stages/deployManifest/manifestStatus/DeployStatusPills.tsx +47 -0
  98. package/src/pipeline/stages/deployManifest/manifestStatus/ManifestDetailsLink.tsx +92 -0
  99. package/src/pipeline/stages/deployManifest/manifestStatus/ManifestEvents.tsx +87 -0
  100. package/src/pipeline/stages/deployManifest/manifestStatus/ManifestStatus.less +24 -0
  101. package/src/pipeline/stages/deployManifest/manifestStatus/ManifestStatus.tsx +46 -0
  102. package/src/pipeline/stages/deployManifest/serverGroupNamePreview.tsx +28 -0
  103. package/src/pipeline/stages/editLoadBalancer/cloudrunEditLoadBalancerStage.ts +74 -0
  104. package/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html +33 -0
  105. package/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html +51 -0
  106. package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.ts +65 -0
  107. package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html +53 -0
  108. package/src/rolloutStrategy/redblack.strategy.ts +7 -0
  109. package/src/serverGroup/configure/serverGroupCommandBuilder.service.ts +254 -0
  110. package/src/serverGroup/configure/wizard/BasicSettings.tsx +160 -0
  111. package/src/serverGroup/configure/wizard/ConfigFiles.tsx +75 -0
  112. package/src/serverGroup/configure/wizard/serverGroupWizard.tsx +150 -0
  113. package/src/serverGroup/details/details.controller.ts +134 -0
  114. package/src/serverGroup/details/details.html +94 -0
  115. package/src/serverGroup/index.ts +3 -0
  116. package/src/serverGroup/serverGroupTransformer.service.ts +61 -0
@@ -0,0 +1,53 @@
1
+ <div modal-page>
2
+ <modal-close dismiss="$dismiss()"></modal-close>
3
+ <div class="modal-header">
4
+ <h4 class="modal-title">Select Load Balancer</h4>
5
+ </div>
6
+ <div class="modal-body" ng-if="ctrl.state.loading" style="height: 200px" class="horizontal center middle">
7
+ <loading-spinner size="'small'"></loading-spinner>
8
+ </div>
9
+ <div class="modal-body" ng-if="!ctrl.state.loading">
10
+ <div class="alert alert-warning" ng-if="ctrl.loadBalancers.length === 0">
11
+ <p>
12
+ Spinnaker cannot create a load balancer for Cloud Run. A Spinnaker load balancer maps to a Cloud Run service
13
+ which along with a Revision are created from Create Server Group page using a
14
+ </p>
15
+ <p><code>yaml file</code> <help-field key="cloudrun.serverGroup.file"></help-field></p>
16
+ <p>
17
+ If a service does not exist when a Revision is deployed, it will be created. It will then be editable as a load
18
+ balancer within Spinnaker.
19
+ </p>
20
+ </div>
21
+ <form
22
+ role="form"
23
+ name="form"
24
+ class="form-horizontal"
25
+ ng-submit="ctrl.submit()"
26
+ ng-if="ctrl.loadBalancers.length > 0"
27
+ >
28
+ <div class="form-group">
29
+ <div class="col-md-3 sm-label-right">
30
+ <b>Load Balancer</b>
31
+ </div>
32
+ <div class="col-md-7">
33
+ <ui-select class="form-control input-sm" ng-model="ctrl.selectedLoadBalancer">
34
+ <ui-select-match>
35
+ <account-tag account="$select.selected.account"></account-tag>
36
+ <span style="margin-left: 5px">{{$select.selected.name}}</span>
37
+ </ui-select-match>
38
+ <ui-select-choices repeat="loadBalancer in ctrl.loadBalancers | filter: $select.search">
39
+ <account-tag account="loadBalancer.account"></account-tag>
40
+ <span style="margin-left: 5px" ng-bind-html="loadBalancer.name"></span>
41
+ </ui-select-choices>
42
+ </ui-select>
43
+ </div>
44
+ </div>
45
+ </form>
46
+ </div>
47
+ <div class="modal-footer">
48
+ <button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>
49
+ <button class="btn btn-primary" ng-if="ctrl.loadBalancers.length > 0" ng-click="ctrl.submit()">
50
+ <span class="far fa-check-circle"></span> Edit
51
+ </button>
52
+ </div>
53
+ </div>
@@ -0,0 +1,7 @@
1
+ import type { IDeploymentStrategy } from '@spinnaker/core';
2
+
3
+ export const strategyRedBlack: IDeploymentStrategy = {
4
+ label: 'Red/Black',
5
+ description: 'Disables <i>all</i> previous ReplicaSets in the cluster as soon as the new ReplicaSet is ready',
6
+ key: 'redblack',
7
+ };
@@ -0,0 +1,254 @@
1
+ import { module } from 'angular';
2
+ import { cloneDeep } from 'lodash';
3
+ import { $q } from 'ngimport';
4
+
5
+ import type {
6
+ Application,
7
+ IAccountDetails,
8
+ IExpectedArtifact,
9
+ IMoniker,
10
+ IPipeline,
11
+ IServerGroupCommand,
12
+ IServerGroupCommandViewState,
13
+ IStage,
14
+ } from '@spinnaker/core';
15
+ import { AccountService } from '@spinnaker/core';
16
+
17
+ import { CloudrunProviderSettings } from '../../cloudrun.settings';
18
+ import type { CloudrunDeployDescription } from '../serverGroupTransformer.service';
19
+
20
+ export enum ServerGroupSource {
21
+ TEXT = 'text',
22
+ ARTIFACT = 'artifact',
23
+ }
24
+
25
+ export interface ICloudrunServerGroupCommandData {
26
+ command: ICloudrunServerGroupCommand;
27
+ metadata: ICloudrunServerGroupCommandMetadata;
28
+ stack: string;
29
+ freeFormDetails: string;
30
+ configFiles: string[];
31
+ }
32
+
33
+ export interface ICloudrunServerGroupCommand extends Omit<IServerGroupCommand, 'source' | 'application'> {
34
+ application?: string;
35
+ stack?: string;
36
+ detail?: string;
37
+ account: string;
38
+ configFiles: string[];
39
+ freeFormDetails: string;
40
+ region: string;
41
+ regions: [];
42
+ isNew?: boolean;
43
+ cloudProvider: string;
44
+ provider: string;
45
+ selectedProvider: string;
46
+ manifest: any; // deprecated
47
+ manifests: any[];
48
+ relationships: ICloudrunServerGroupSpinnakerRelationships;
49
+ moniker: IMoniker;
50
+ manifestArtifactId?: string;
51
+ manifestArtifactAccount?: string;
52
+ source: ServerGroupSource;
53
+ versioned?: boolean;
54
+ gitCredentialType?: string;
55
+ viewState: IServerGroupCommandViewState;
56
+ mode: string;
57
+ credentials: string;
58
+ sourceType: string;
59
+ configArtifacts: any[];
60
+ interestingHealthProviderNames: [];
61
+ fromArtifact: boolean;
62
+ }
63
+
64
+ export interface IViewState {
65
+ mode: string;
66
+ submitButtonLabel: string;
67
+ disableStrategySelection: boolean;
68
+ stage?: IStage;
69
+ pipeline?: IPipeline;
70
+ }
71
+
72
+ export interface ICloudrunServerGroupCommandMetadata {
73
+ backingData: any;
74
+ }
75
+
76
+ export interface ICloudrunServerGroupSpinnakerRelationships {
77
+ loadBalancers?: string[];
78
+ securityGroups?: string[];
79
+ }
80
+
81
+ const getSubmitButtonLabel = (mode: string): string => {
82
+ switch (mode) {
83
+ case 'createPipeline':
84
+ return 'Add';
85
+ case 'editPipeline':
86
+ return 'Done';
87
+ default:
88
+ return 'Create';
89
+ }
90
+ };
91
+
92
+ export class CloudrunV2ServerGroupCommandBuilder {
93
+ // new add servergroup
94
+ public buildNewServerGroupCommand(app: Application): PromiseLike<ICloudrunServerGroupCommandData> {
95
+ return CloudrunServerGroupCommandBuilder.buildNewServerGroupCommand(app, 'cloudrun', 'create');
96
+ }
97
+
98
+ // add servergroup from deploy stage of pipeline
99
+ public buildNewServerGroupCommandForPipeline(_stage: IStage, pipeline: IPipeline) {
100
+ return CloudrunServerGroupCommandBuilder.buildNewServerGroupCommandForPipeline(_stage, pipeline);
101
+ }
102
+
103
+ // edit servergroup from deploy stage of pipeline
104
+ // add servergroup from deploy stage of pipeline
105
+ public buildServerGroupCommandFromPipeline(
106
+ app: Application,
107
+ cluster: CloudrunDeployDescription,
108
+ _stage: IStage,
109
+ pipeline: IPipeline,
110
+ ) {
111
+ return CloudrunServerGroupCommandBuilder.buildServerGroupCommandFromPipeline(app, cluster, _stage, pipeline);
112
+ }
113
+ }
114
+
115
+ export class CloudrunServerGroupCommandBuilder {
116
+ public static $inject = ['$q'];
117
+ public static ServerGroupCommandIsValid(command: ICloudrunServerGroupCommand): boolean {
118
+ if (!command.moniker) {
119
+ return false;
120
+ }
121
+
122
+ if (!command.moniker.app) {
123
+ return false;
124
+ }
125
+
126
+ return true;
127
+ }
128
+
129
+ public static copyAndCleanCommand(input: ICloudrunServerGroupCommand): ICloudrunServerGroupCommand {
130
+ const command = cloneDeep(input);
131
+ return command;
132
+ }
133
+
134
+ // deploy stage : construct servergroup command
135
+ public static buildNewServerGroupCommandForPipeline(stage: IStage, pipeline: IPipeline): any {
136
+ const command: any = this.buildNewServerGroupCommand(
137
+ { name: pipeline.application } as Application,
138
+ 'cloudrun',
139
+ 'createPipeline',
140
+ );
141
+ command.viewState = {
142
+ ...command.viewState,
143
+ pipeline,
144
+ requiresTemplateSelection: true,
145
+ stage,
146
+ };
147
+ return command;
148
+ }
149
+
150
+ private static getExpectedArtifacts(pipeline: IPipeline): IExpectedArtifact[] {
151
+ return pipeline.expectedArtifacts || [];
152
+ }
153
+
154
+ public static buildServerGroupCommandFromPipeline(
155
+ app: Application,
156
+ cluster: CloudrunDeployDescription,
157
+ _stage: IStage,
158
+ pipeline: IPipeline,
159
+ ): PromiseLike<ICloudrunServerGroupCommandData> {
160
+ return CloudrunServerGroupCommandBuilder.buildNewServerGroupCommand(app, 'cloudrun', 'editPipeline').then(
161
+ (command: ICloudrunServerGroupCommandData) => {
162
+ command = {
163
+ ...command,
164
+ ...cluster,
165
+
166
+ backingData: {
167
+ ...command.metadata.backingData.backingData,
168
+
169
+ expectedArtifacts: CloudrunServerGroupCommandBuilder.getExpectedArtifacts(pipeline),
170
+ },
171
+ credentials: cluster.account || command.metadata.backingData.credentials,
172
+ viewState: {
173
+ ...command.metadata.backingData.viewState,
174
+ stage: _stage,
175
+ pipeline,
176
+ },
177
+ } as ICloudrunServerGroupCommandData;
178
+ return command;
179
+ },
180
+ );
181
+ }
182
+
183
+ public static getCredentials(accounts: IAccountDetails[]): string {
184
+ const accountNames: string[] = (accounts || []).map((account) => account.name);
185
+ const defaultCredentials: string = CloudrunProviderSettings.defaults.account;
186
+
187
+ return accountNames.includes(defaultCredentials) ? defaultCredentials : accountNames[0];
188
+ }
189
+
190
+ public static getRegion(accounts: any[], credentials: string): string {
191
+ const account = accounts.find((_account) => _account.name === credentials);
192
+ return account ? account.region : null;
193
+ }
194
+
195
+ // new servergroup command
196
+ public static buildNewServerGroupCommand(
197
+ app: Application,
198
+ sourceAccount: string,
199
+ mode: string,
200
+ ): PromiseLike<ICloudrunServerGroupCommandData> {
201
+ const dataToFetch = {
202
+ accounts: AccountService.getAllAccountDetailsForProvider('cloudrun'),
203
+ artifactAccounts: AccountService.getArtifactAccounts(),
204
+ };
205
+
206
+ return $q.all(dataToFetch).then((backingData: { accounts: IAccountDetails[] }) => {
207
+ const { accounts } = backingData;
208
+
209
+ const account = accounts.some((a) => a.name === sourceAccount)
210
+ ? accounts.find((a) => a.name === sourceAccount).name
211
+ : accounts.length
212
+ ? accounts[0].name
213
+ : null;
214
+ const viewState: IViewState = {
215
+ mode,
216
+ submitButtonLabel: getSubmitButtonLabel(mode),
217
+ disableStrategySelection: mode === 'create',
218
+ };
219
+ const credentials = account ? account : this.getCredentials(accounts);
220
+ const region = this.getRegion(backingData.accounts, credentials);
221
+ const cloudProvider = 'cloudrun';
222
+
223
+ return {
224
+ command: {
225
+ application: app.name,
226
+ configFiles: [''],
227
+ cloudProvider,
228
+ selectedProvider: cloudProvider,
229
+ provider: cloudProvider,
230
+ region,
231
+ credentials,
232
+ gitCredentialType: 'NONE',
233
+ manifest: null,
234
+ sourceType: 'git',
235
+ configArtifacts: [],
236
+ interestingHealthProviderNames: [],
237
+ fromArtifact: false,
238
+ account,
239
+ viewState,
240
+ },
241
+ metadata: {
242
+ backingData,
243
+ },
244
+ } as ICloudrunServerGroupCommandData;
245
+ });
246
+ }
247
+ }
248
+
249
+ export const CLOUDRUN_SERVER_GROUP_COMMAND_BUILDER = 'spinnaker.cloudrun.serverGroup.commandBuilder.service';
250
+
251
+ module(CLOUDRUN_SERVER_GROUP_COMMAND_BUILDER, []).service(
252
+ 'cloudrunV2ServerGroupCommandBuilder',
253
+ CloudrunV2ServerGroupCommandBuilder,
254
+ );
@@ -0,0 +1,160 @@
1
+ import type { FormikProps } from 'formik';
2
+ import React from 'react';
3
+
4
+ import type { Application, IAccount, IServerGroup } from '@spinnaker/core';
5
+ import { AccountSelectInput, HelpField, NameUtils, ReactInjector, ServerGroupNamePreview } from '@spinnaker/core';
6
+
7
+ import type { ICloudrunServerGroupCommandData } from '../serverGroupCommandBuilder.service';
8
+
9
+ export interface IServerGroupBasicSettingsProps {
10
+ accounts: IAccount[];
11
+ onAccountSelect: (account: string) => void;
12
+ selectedAccount: string;
13
+ formik: IWizardServerGroupBasicSettingsProps['formik'];
14
+ onEnterStack: (stack: string) => void;
15
+ detailsChanged: (detail: string) => void;
16
+ app: Application;
17
+ }
18
+
19
+ export interface IServerGroupBasicSettingsState {
20
+ namePreview: string;
21
+ createsNewCluster: boolean;
22
+ latestServerGroup: IServerGroup;
23
+ }
24
+
25
+ export function ServerGroupBasicSettings({
26
+ accounts,
27
+ onAccountSelect,
28
+ selectedAccount,
29
+ formik,
30
+ onEnterStack,
31
+ detailsChanged,
32
+ app,
33
+ }: IServerGroupBasicSettingsProps) {
34
+ const { values } = formik;
35
+ const { stack = '', freeFormDetails } = values;
36
+
37
+ const namePreview = NameUtils.getClusterName(app.name, stack, freeFormDetails);
38
+ const createsNewCluster = !app.clusters.find((c) => c.name === namePreview);
39
+ const inCluster = (app.serverGroups.data as IServerGroup[])
40
+ .filter((serverGroup) => {
41
+ return (
42
+ serverGroup.cluster === namePreview &&
43
+ serverGroup.account === values.command.credentials &&
44
+ serverGroup.region === values.command.region
45
+ );
46
+ })
47
+ .sort((a, b) => a.createdTime - b.createdTime);
48
+ const latestServerGroup = inCluster.length ? inCluster.pop() : null;
49
+
50
+ const navigateToLatestServerGroup = () => {
51
+ const { values } = formik;
52
+ const params = {
53
+ provider: values.command.selectedProvider,
54
+ accountId: latestServerGroup.account,
55
+ region: latestServerGroup.region,
56
+ serverGroup: latestServerGroup.name,
57
+ };
58
+
59
+ const { $state } = ReactInjector;
60
+ if ($state.is('home.applications.application.insight.clusters')) {
61
+ $state.go('.serverGroup', params);
62
+ } else {
63
+ $state.go('^.serverGroup', params);
64
+ }
65
+ };
66
+
67
+ return (
68
+ <div className="form-horizontal">
69
+ <div className="form-group">
70
+ <div className="col-md-3 sm-label-right">Account</div>
71
+ <div className="col-md-7">
72
+ <AccountSelectInput
73
+ value={selectedAccount}
74
+ onChange={(evt: any) => onAccountSelect(evt.target.value)}
75
+ readOnly={false}
76
+ accounts={accounts}
77
+ provider="cloudrun"
78
+ />
79
+ </div>
80
+ </div>
81
+
82
+ <div className="form-group">
83
+ <div className="col-md-3 sm-label-right">
84
+ Stack <HelpField id="cloudrun.serverGroup.stack" />
85
+ </div>
86
+ <div className="col-md-7">
87
+ <input
88
+ type="text"
89
+ className="form-control input-sm no-spel"
90
+ value={stack}
91
+ onChange={(e) => onEnterStack(e.target.value)}
92
+ />
93
+ </div>
94
+ </div>
95
+
96
+ <div className="form-group">
97
+ <div className="col-md-3 sm-label-right">
98
+ Detail <HelpField id="cloudrun.serverGroup.detail" />
99
+ </div>
100
+ <div className="col-md-7">
101
+ <input
102
+ type="text"
103
+ className="form-control input-sm no-spel"
104
+ value={freeFormDetails}
105
+ onChange={(e) => detailsChanged(e.target.value)}
106
+ />
107
+ </div>
108
+ </div>
109
+ {!values.command.viewState.hideClusterNamePreview && (
110
+ <ServerGroupNamePreview
111
+ createsNewCluster={createsNewCluster}
112
+ latestServerGroupName={latestServerGroup?.name}
113
+ mode={values.command.viewState.mode}
114
+ namePreview={namePreview}
115
+ navigateToLatestServerGroup={navigateToLatestServerGroup}
116
+ />
117
+ )}
118
+ </div>
119
+ );
120
+ }
121
+
122
+ export interface IWizardServerGroupBasicSettingsProps {
123
+ formik: FormikProps<ICloudrunServerGroupCommandData>;
124
+ app: Application;
125
+ }
126
+
127
+ export class WizardServerGroupBasicSettings extends React.Component<IWizardServerGroupBasicSettingsProps> {
128
+ private accountUpdated = (account: string): void => {
129
+ const { formik } = this.props;
130
+ formik.values.command.account = account;
131
+ formik.setFieldValue('account', account);
132
+ };
133
+
134
+ private stackChanged = (stack: string): void => {
135
+ const { setFieldValue, values } = this.props.formik;
136
+ values.command.stack = stack;
137
+ setFieldValue('stack', stack);
138
+ };
139
+
140
+ private freeFormDetailsChanged = (freeFormDetails: string) => {
141
+ const { setFieldValue, values } = this.props.formik;
142
+ values.command.freeFormDetails = freeFormDetails;
143
+ setFieldValue('freeFormDetails', freeFormDetails);
144
+ };
145
+
146
+ public render() {
147
+ const { formik, app } = this.props;
148
+ return (
149
+ <ServerGroupBasicSettings
150
+ accounts={formik.values.metadata?.backingData?.accounts || []}
151
+ onAccountSelect={this.accountUpdated}
152
+ selectedAccount={formik.values.command?.account || ''}
153
+ onEnterStack={this.stackChanged}
154
+ formik={formik}
155
+ detailsChanged={this.freeFormDetailsChanged}
156
+ app={app}
157
+ />
158
+ );
159
+ }
160
+ }
@@ -0,0 +1,75 @@
1
+ import type { FormikProps } from 'formik';
2
+ import React, { useState } from 'react';
3
+
4
+ import { HelpField, TextAreaInput } from '@spinnaker/core';
5
+ import type { ICloudrunServerGroupCommandData } from '../serverGroupCommandBuilder.service';
6
+
7
+ export interface IServerGroupConfigFilesSettingsProps {
8
+ configFiles: string[];
9
+ onEnterConfig: (file: string[]) => void;
10
+ }
11
+ type configFiles = IServerGroupConfigFilesSettingsProps['configFiles'];
12
+
13
+ export function ServerGroupConfigFilesSettings({ configFiles, onEnterConfig }: IServerGroupConfigFilesSettingsProps) {
14
+ const [configValues, setConfigValues] = useState<configFiles>(configFiles);
15
+
16
+ function mapTabToSpaces(event: any, i: number) {
17
+ if (event.which === 9) {
18
+ event.preventDefault();
19
+ const cursorPosition = event.target.selectionStart;
20
+ const inputValue = event.target.value;
21
+ event.target.value = `${inputValue.substring(0, cursorPosition)} ${inputValue.substring(cursorPosition)}`;
22
+ event.target.selectionStart += 2;
23
+ }
24
+ const newConfigValues = [...configValues];
25
+ newConfigValues[i] = event.target.value;
26
+ setConfigValues(newConfigValues);
27
+ onEnterConfig(newConfigValues);
28
+ }
29
+
30
+ return (
31
+ <div className="form-horizontal">
32
+ <div className="form-group">
33
+ {configValues.map((configFile, index) => (
34
+ <>
35
+ <div className="col-md-3 sm-label-right">
36
+ Service Yaml
37
+ <HelpField id="cloudrun.serverGroup.configFiles" />{' '}
38
+ </div>
39
+ <div className="col-md-8" key={index}>
40
+ <TextAreaInput
41
+ name={'text' + index}
42
+ value={configFile}
43
+ rows={10}
44
+ onChange={(e) => mapTabToSpaces(e, index)}
45
+ />
46
+ </div>
47
+ </>
48
+ ))}
49
+ </div>
50
+ </div>
51
+ );
52
+ }
53
+
54
+ export interface IWizardServerGroupConfigFilesSettingsProps {
55
+ formik: FormikProps<ICloudrunServerGroupCommandData>;
56
+ }
57
+
58
+ export class WizardServerGroupConfigFilesSettings extends React.Component<IWizardServerGroupConfigFilesSettingsProps> {
59
+ private configUpdated = (configFiles: string[]): void => {
60
+ const { formik } = this.props;
61
+ formik.values.command.configFiles = configFiles;
62
+ formik.setFieldValue('configFiles', configFiles);
63
+ };
64
+
65
+ // yaml config files input from server group wizard
66
+ public render() {
67
+ const { formik } = this.props;
68
+ return (
69
+ <ServerGroupConfigFilesSettings
70
+ configFiles={formik.values.configFiles || formik.values.command.configFiles}
71
+ onEnterConfig={this.configUpdated}
72
+ />
73
+ );
74
+ }
75
+ }
@@ -0,0 +1,150 @@
1
+ import React from 'react';
2
+ import type { Application, IModalComponentProps, IStage } from '@spinnaker/core';
3
+ //import type { IModalInstanceService } from 'angular-ui-bootstrap';
4
+ import { noop, ReactInjector, ReactModal, TaskMonitor, WizardModal, WizardPage } from '@spinnaker/core';
5
+ import { WizardServerGroupBasicSettings } from './BasicSettings';
6
+ import { WizardServerGroupConfigFilesSettings } from './ConfigFiles';
7
+ import type { ICloudrunServerGroupCommandData } from '../serverGroupCommandBuilder.service';
8
+ import { CloudrunServerGroupCommandBuilder } from '../serverGroupCommandBuilder.service';
9
+
10
+ export interface ICloudrunServerGroupModalProps extends IModalComponentProps {
11
+ title: string;
12
+ application: Application;
13
+ command: ICloudrunServerGroupCommandData;
14
+ isNew?: boolean;
15
+ }
16
+
17
+ export interface ICloudrunServerGroupModalState {
18
+ command: ICloudrunServerGroupCommandData;
19
+ loaded: boolean;
20
+ taskMonitor: TaskMonitor;
21
+ }
22
+
23
+ export class ServerGroupWizard extends React.Component<ICloudrunServerGroupModalProps, ICloudrunServerGroupModalState> {
24
+ public static defaultProps: Partial<ICloudrunServerGroupModalProps> = {
25
+ closeModal: noop,
26
+ dismissModal: noop,
27
+ };
28
+
29
+ private _isUnmounted = false;
30
+
31
+ /* private serverGroupWriter: ServerGroupWriter; */
32
+ public static show(props: ICloudrunServerGroupModalProps): Promise<ICloudrunServerGroupCommandData> {
33
+ const modalProps = { dialogClassName: 'wizard-modal modal-lg' };
34
+ return ReactModal.show(ServerGroupWizard, props, modalProps);
35
+ }
36
+
37
+ constructor(props: ICloudrunServerGroupModalProps) {
38
+ super(props);
39
+ if (!props.command) {
40
+ CloudrunServerGroupCommandBuilder.buildNewServerGroupCommand(props.application, 'cloudrun', 'create').then(
41
+ (command) => {
42
+ Object.assign(this.state.command, command);
43
+ this.setState({ loaded: true });
44
+ },
45
+ );
46
+ }
47
+
48
+ this.state = {
49
+ loaded: !!props.command,
50
+ command: props.command || ({} as ICloudrunServerGroupCommandData),
51
+ taskMonitor: new TaskMonitor({
52
+ application: props.application,
53
+ title: `${
54
+ props.command.command.viewState.submitButtonLabel === 'Create' ? 'Creating' : 'Updating'
55
+ } your Server Group`,
56
+ modalInstance: TaskMonitor.modalInstanceEmulation(() => this.props.dismissModal()),
57
+ onTaskComplete: this.onTaskComplete,
58
+ }),
59
+ };
60
+ }
61
+
62
+ private onTaskComplete = () => {
63
+ this.props.application.serverGroups.refresh();
64
+ this.props.application.serverGroups.onNextRefresh(null, this.onApplicationRefresh);
65
+ };
66
+
67
+ protected onApplicationRefresh = (): void => {
68
+ if (this._isUnmounted) {
69
+ return;
70
+ }
71
+
72
+ const { command } = this.props;
73
+ const { taskMonitor } = this.state;
74
+ const cloneStage = taskMonitor.task.execution.stages.find((stage: IStage) => stage.type === 'cloneServerGroup');
75
+ if (cloneStage && cloneStage.context['deploy.server.groups']) {
76
+ const newServerGroupName = cloneStage.context['deploy.server.groups'][command.command.region];
77
+ if (newServerGroupName) {
78
+ const newStateParams = {
79
+ serverGroup: newServerGroupName,
80
+ accountId: command.command.credentials,
81
+ region: command.command.region,
82
+ provider: 'cloudrun',
83
+ };
84
+ let transitionTo = '^.^.^.clusters.serverGroup';
85
+ if (ReactInjector.$state.includes('**.clusters.serverGroup')) {
86
+ // clone via details, all view
87
+ transitionTo = '^.serverGroup';
88
+ }
89
+ if (ReactInjector.$state.includes('**.clusters.cluster.serverGroup')) {
90
+ // clone or create with details open
91
+ transitionTo = '^.^.serverGroup';
92
+ }
93
+ if (ReactInjector.$state.includes('**.clusters')) {
94
+ // create new, no details open
95
+ transitionTo = '.serverGroup';
96
+ }
97
+ ReactInjector.$state.go(transitionTo, newStateParams);
98
+ }
99
+ }
100
+ };
101
+
102
+ private submit = (c: ICloudrunServerGroupCommandData): void => {
103
+ const command: any = CloudrunServerGroupCommandBuilder.copyAndCleanCommand(c.command);
104
+ const forPipelineConfig = command.viewState.mode === 'editPipeline' || command.viewState.mode === 'createPipeline';
105
+ if (forPipelineConfig) {
106
+ this.props.closeModal && this.props.closeModal(command);
107
+ } else {
108
+ //command.viewState.mode = 'create';
109
+ const submitMethod = () => ReactInjector.serverGroupWriter.cloneServerGroup(command, this.props.application);
110
+ this.state.taskMonitor.submit(submitMethod);
111
+ return null;
112
+ }
113
+ };
114
+ public render() {
115
+ const { dismissModal, application } = this.props;
116
+ const { loaded, taskMonitor, command } = this.state;
117
+ const labelButton = this.state.command.command.viewState.submitButtonLabel;
118
+
119
+ return (
120
+ <WizardModal<ICloudrunServerGroupCommandData>
121
+ heading={`${labelButton === 'Add' || labelButton === 'Create' ? 'Create New' : 'Update'} Server Group`}
122
+ initialValues={command}
123
+ loading={!loaded}
124
+ taskMonitor={taskMonitor}
125
+ dismissModal={dismissModal}
126
+ closeModal={this.submit}
127
+ submitButtonLabel={labelButton}
128
+ render={({ formik, nextIdx, wizard }) => (
129
+ <>
130
+ <WizardPage
131
+ label="Basic Settings"
132
+ wizard={wizard}
133
+ order={nextIdx()}
134
+ render={({ innerRef }) => (
135
+ <WizardServerGroupBasicSettings ref={innerRef} formik={formik} app={application} />
136
+ )}
137
+ />
138
+
139
+ <WizardPage
140
+ label="Service Yaml"
141
+ wizard={wizard}
142
+ order={nextIdx()}
143
+ render={({ innerRef }) => <WizardServerGroupConfigFilesSettings ref={innerRef} formik={formik} />}
144
+ />
145
+ </>
146
+ )}
147
+ />
148
+ );
149
+ }
150
+ }