@spinnaker/appengine 0.0.0-main-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/CHANGELOG.md +981 -0
  2. package/LICENSE.txt +203 -0
  3. package/dist/appengine.logoc2c312af6aa99037.png +0 -0
  4. package/dist/appengine.module.d.ts +5 -0
  5. package/dist/appengine.settings.d.ts +7 -0
  6. package/dist/common/FormikAccountRegionSelector.d.ts +26 -0
  7. package/dist/common/appengineHealth.d.ts +3 -0
  8. package/dist/common/componentUrlDetails.component.d.ts +1 -0
  9. package/dist/common/conditionalDescriptionListItem.component.d.ts +1 -0
  10. package/dist/common/loadBalancerMessage.component.d.ts +1 -0
  11. package/dist/domain/IAppengineAccount.d.ts +6 -0
  12. package/dist/domain/IAppengineInstance.d.ts +20 -0
  13. package/dist/domain/IAppengineLoadBalancer.d.ts +19 -0
  14. package/dist/domain/IAppengineServerGroup.d.ts +11 -0
  15. package/dist/domain/IAppengineStageScope.d.ts +18 -0
  16. package/dist/domain/IAppengineTriggers.d.ts +11 -0
  17. package/dist/domain/index.d.ts +6 -0
  18. package/dist/helpContents/appengineHelpContents.d.ts +1 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +4084 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/instance/details/details.controller.d.ts +1 -0
  23. package/dist/loadBalancer/configure/wizard/advancedSettings.component.d.ts +1 -0
  24. package/dist/loadBalancer/configure/wizard/allocationConfigurationRow.component.d.ts +1 -0
  25. package/dist/loadBalancer/configure/wizard/basicSettings.component.d.ts +1 -0
  26. package/dist/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.d.ts +1 -0
  27. package/dist/loadBalancer/configure/wizard/wizard.controller.d.ts +2 -0
  28. package/dist/loadBalancer/details/details.controller.d.ts +1 -0
  29. package/dist/loadBalancer/loadBalancer.module.d.ts +1 -0
  30. package/dist/loadBalancer/transformer.d.ts +40 -0
  31. package/dist/pipeline/pipeline.module.d.ts +1 -0
  32. package/dist/pipeline/stages/appengineStage.controller.d.ts +12 -0
  33. package/dist/pipeline/stages/deployAppengineConfig/DeployAppengineConfigForm.d.ts +16 -0
  34. package/dist/pipeline/stages/deployAppengineConfig/DeployAppengineConfigurationConfig.d.ts +5 -0
  35. package/dist/pipeline/stages/deployAppengineConfig/deployAppengineConfigStage.d.ts +1 -0
  36. package/dist/pipeline/stages/destroyAsg/appengineDestroyAsgStage.d.ts +1 -0
  37. package/dist/pipeline/stages/disableAsg/appengineDisableAsgStage.d.ts +1 -0
  38. package/dist/pipeline/stages/editLoadBalancer/appengineEditLoadBalancerStage.d.ts +1 -0
  39. package/dist/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.d.ts +1 -0
  40. package/dist/pipeline/stages/enableAsg/appengineEnableAsgStage.d.ts +1 -0
  41. package/dist/pipeline/stages/shrinkCluster/appengineShrinkClusterStage.d.ts +1 -0
  42. package/dist/pipeline/stages/startServerGroup/appengineStartServerGroupStage.d.ts +1 -0
  43. package/dist/pipeline/stages/stopServerGroup/appengineStopServerGroupStage.d.ts +1 -0
  44. package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +74 -0
  45. package/dist/serverGroup/configure/wizard/ConfigFileArtifactList.d.ts +10 -0
  46. package/dist/serverGroup/configure/wizard/basicSettings.controller.d.ts +1 -0
  47. package/dist/serverGroup/configure/wizard/cloneServerGroup.controller.d.ts +2 -0
  48. package/dist/serverGroup/configure/wizard/configFileArtifactList.module.d.ts +1 -0
  49. package/dist/serverGroup/configure/wizard/configFiles.component.d.ts +20 -0
  50. package/dist/serverGroup/configure/wizard/dynamicBranchLabel.component.d.ts +1 -0
  51. package/dist/serverGroup/details/details.controller.d.ts +1 -0
  52. package/dist/serverGroup/transformer.d.ts +45 -0
  53. package/dist/serverGroup/writer/serverGroup.write.service.d.ts +8 -0
  54. package/dist/validation/ApplicationNameValidator.d.ts +1 -0
  55. package/package.json +46 -0
  56. package/src/appengine.module.ts +70 -0
  57. package/src/appengine.settings.ts +14 -0
  58. package/src/common/FormikAccountRegionSelector.tsx +107 -0
  59. package/src/common/appengineHealth.ts +3 -0
  60. package/src/common/componentUrlDetails.component.ts +29 -0
  61. package/src/common/conditionalDescriptionListItem.component.ts +37 -0
  62. package/src/common/loadBalancerMessage.component.html +33 -0
  63. package/src/common/loadBalancerMessage.component.ts +13 -0
  64. package/src/domain/IAppengineAccount.ts +8 -0
  65. package/src/domain/IAppengineInstance.ts +21 -0
  66. package/src/domain/IAppengineLoadBalancer.ts +21 -0
  67. package/src/domain/IAppengineServerGroup.ts +13 -0
  68. package/src/domain/IAppengineStageScope.ts +22 -0
  69. package/src/domain/IAppengineTriggers.ts +12 -0
  70. package/src/domain/index.ts +6 -0
  71. package/src/helpContents/appengineHelpContents.ts +141 -0
  72. package/src/index.ts +1 -0
  73. package/src/instance/details/details.controller.ts +116 -0
  74. package/src/instance/details/details.html +99 -0
  75. package/src/loadBalancer/configure/wizard/advancedSettings.component.ts +56 -0
  76. package/src/loadBalancer/configure/wizard/allocationConfigurationRow.component.ts +70 -0
  77. package/src/loadBalancer/configure/wizard/basicSettings.component.html +65 -0
  78. package/src/loadBalancer/configure/wizard/basicSettings.component.ts +98 -0
  79. package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html +117 -0
  80. package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.ts +108 -0
  81. package/src/loadBalancer/configure/wizard/wizard.controller.ts +163 -0
  82. package/src/loadBalancer/configure/wizard/wizard.html +44 -0
  83. package/src/loadBalancer/configure/wizard/wizard.less +17 -0
  84. package/src/loadBalancer/details/details.controller.ts +151 -0
  85. package/src/loadBalancer/details/details.html +102 -0
  86. package/src/loadBalancer/loadBalancer.module.ts +21 -0
  87. package/src/loadBalancer/transformer.ts +170 -0
  88. package/src/logo/appengine.icon.svg +37 -0
  89. package/src/logo/appengine.logo.less +6 -0
  90. package/src/logo/appengine.logo.png +0 -0
  91. package/src/pipeline/pipeline.module.ts +20 -0
  92. package/src/pipeline/stages/appengineStage.controller.ts +45 -0
  93. package/src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigForm.tsx +203 -0
  94. package/src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigurationConfig.tsx +34 -0
  95. package/src/pipeline/stages/deployAppengineConfig/deployAppengineConfigStage.ts +19 -0
  96. package/src/pipeline/stages/destroyAsg/appengineDestroyAsgStage.ts +45 -0
  97. package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +16 -0
  98. package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +1 -0
  99. package/src/pipeline/stages/disableAsg/appengineDisableAsgStage.ts +54 -0
  100. package/src/pipeline/stages/disableAsg/disableAsgStage.html +18 -0
  101. package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +1 -0
  102. package/src/pipeline/stages/editLoadBalancer/appengineEditLoadBalancerStage.ts +74 -0
  103. package/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html +33 -0
  104. package/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html +51 -0
  105. package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.ts +65 -0
  106. package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html +45 -0
  107. package/src/pipeline/stages/enableAsg/appengineEnableAsgStage.ts +49 -0
  108. package/src/pipeline/stages/enableAsg/enableAsgStage.html +18 -0
  109. package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +1 -0
  110. package/src/pipeline/stages/shrinkCluster/appengineShrinkClusterStage.ts +62 -0
  111. package/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html +41 -0
  112. package/src/pipeline/stages/startServerGroup/appengineStartServerGroupStage.ts +54 -0
  113. package/src/pipeline/stages/startServerGroup/startServerGroupExecutionDetails.html +26 -0
  114. package/src/pipeline/stages/startServerGroup/startServerGroupStage.html +18 -0
  115. package/src/pipeline/stages/startServerGroup/startServerGroupStepLabel.html +1 -0
  116. package/src/pipeline/stages/stopServerGroup/appengineStopServerGroupStage.ts +54 -0
  117. package/src/pipeline/stages/stopServerGroup/stopServerGroupExecutionDetails.html +26 -0
  118. package/src/pipeline/stages/stopServerGroup/stopServerGroupStage.html +18 -0
  119. package/src/pipeline/stages/stopServerGroup/stopServerGroupStepLabel.html +1 -0
  120. package/src/serverGroup/configure/serverGroupCommandBuilder.service.ts +235 -0
  121. package/src/serverGroup/configure/wizard/ConfigFileArtifactList.tsx +81 -0
  122. package/src/serverGroup/configure/wizard/advancedSettings.html +33 -0
  123. package/src/serverGroup/configure/wizard/basicSettings.controller.ts +151 -0
  124. package/src/serverGroup/configure/wizard/basicSettings.html +287 -0
  125. package/src/serverGroup/configure/wizard/cloneServerGroup.controller.ts +103 -0
  126. package/src/serverGroup/configure/wizard/configFileArtifactList.module.ts +18 -0
  127. package/src/serverGroup/configure/wizard/configFileArtifactList.spec.tsx +78 -0
  128. package/src/serverGroup/configure/wizard/configFiles.component.html +81 -0
  129. package/src/serverGroup/configure/wizard/configFiles.component.ts +121 -0
  130. package/src/serverGroup/configure/wizard/dynamicBranchLabel.component.ts +19 -0
  131. package/src/serverGroup/configure/wizard/serverGroupWizard.html +39 -0
  132. package/src/serverGroup/configure/wizard/serverGroupWizard.less +28 -0
  133. package/src/serverGroup/details/details.controller.ts +463 -0
  134. package/src/serverGroup/details/details.html +229 -0
  135. package/src/serverGroup/transformer.ts +92 -0
  136. package/src/serverGroup/transformet.spec.ts +40 -0
  137. package/src/serverGroup/writer/serverGroup.write.service.ts +57 -0
  138. package/src/validation/ApplicationNameValidator.ts +40 -0
@@ -0,0 +1,21 @@
1
+ import type { ILoadBalancer } from '@spinnaker/core';
2
+
3
+ export interface IAppengineLoadBalancer extends ILoadBalancer {
4
+ credentials?: string;
5
+ split?: IAppengineTrafficSplit;
6
+ migrateTraffic: boolean;
7
+ dispatchRules?: IAppengineDispatchRule[];
8
+ }
9
+
10
+ export interface IAppengineTrafficSplit {
11
+ shardBy: ShardBy;
12
+ allocations: { [serverGroupName: string]: number };
13
+ }
14
+
15
+ export interface IAppengineDispatchRule {
16
+ domain: string;
17
+ path: string;
18
+ service: string;
19
+ }
20
+
21
+ export type ShardBy = 'UNSPECIFIED' | 'IP' | 'COOKIE';
@@ -0,0 +1,13 @@
1
+ import type { IServerGroup } from '@spinnaker/core';
2
+
3
+ export interface IAppengineServerGroup extends IServerGroup {
4
+ disabled: boolean;
5
+ env: 'FLEXIBLE' | 'STANDARD';
6
+ scalingPolicy: IAppengineScalingPolicy;
7
+ servingStatus: 'SERVING' | 'STOPPED';
8
+ allowsGradualTrafficMigration: boolean;
9
+ }
10
+
11
+ export interface IAppengineScalingPolicy {
12
+ type: 'AUTOMATIC' | 'MANUAL' | 'BASIC';
13
+ }
@@ -0,0 +1,22 @@
1
+ import type { IScope } from 'angular';
2
+
3
+ import type { Application, IStageConstant } from '@spinnaker/core';
4
+
5
+ import type { IAppengineAccount } from './IAppengineAccount';
6
+
7
+ export interface IAppengineStage {
8
+ credentials: string;
9
+ region: string;
10
+ target?: string;
11
+ cloudProvider: string;
12
+ isNew?: boolean;
13
+ interestingHealthProviderNames: string[];
14
+ }
15
+
16
+ export interface IAppengineStageScope extends IScope {
17
+ accounts: IAppengineAccount[];
18
+ targets: IStageConstant[];
19
+ stage: IAppengineStage;
20
+ application: Application;
21
+ platformHealth: string;
22
+ }
@@ -0,0 +1,12 @@
1
+ export interface IAppengineGitTrigger {
2
+ source: string;
3
+ project: string;
4
+ slug: string;
5
+ branch: string;
6
+ }
7
+
8
+ export interface IAppengineJenkinsTrigger {
9
+ master: string;
10
+ job: string;
11
+ matchBranchOnRegex?: string;
12
+ }
@@ -0,0 +1,6 @@
1
+ export * from './IAppengineAccount';
2
+ export * from './IAppengineInstance';
3
+ export * from './IAppengineLoadBalancer';
4
+ export * from './IAppengineServerGroup';
5
+ export * from './IAppengineStageScope';
6
+ export * from './IAppengineTriggers';
@@ -0,0 +1,141 @@
1
+ import { HelpContentsRegistry } from '@spinnaker/core';
2
+
3
+ const helpContents = [
4
+ {
5
+ key: 'appengine.serverGroup.gcs.repositoryUrl',
6
+ value: `The full URL to the GCS bucket or TAR file containing the source files for this deployment,
7
+ including 'gs://'. For example, <b>gs://my-bucket/my-app</b> or <b>gs://my-bucket/app.tar</b>.`,
8
+ },
9
+ {
10
+ key: 'appengine.serverGroup.git.repositoryUrl',
11
+ value: `The full URL to the git repository containing the source files for this deployment,
12
+ including protocol. For example, <b>https://github.com/spinnaker/deck.git</b>`,
13
+ },
14
+ {
15
+ key: 'appengine.serverGroup.gitCredentialType',
16
+ value: `The credential type that will be used to access the git repository for this deployment.
17
+ You can configure these credentials alongside your App Engine credentials.`,
18
+ },
19
+ {
20
+ key: 'appengine.serverGroup.branch',
21
+ value: 'The name of the branch in the above git repository to be used for this deployment.',
22
+ },
23
+ {
24
+ key: 'appengine.serverGroup.applicationDirectoryRoot',
25
+ value: `(Optional) Path to the directory root of the application to be deployed,
26
+ starting from the root of the git repository. This is the directory from which
27
+ <code>gcloud app deploy</code> will be run.`,
28
+ },
29
+ {
30
+ key: 'appengine.serverGroup.configFilepaths',
31
+ value: `Paths to App Engine application configuration files, starting from the application directory root,
32
+ specified above. In most cases, this will be <code>app.yaml</code> or <code>cron.yaml</code>,
33
+ but could be <code>path/to/app.yaml</code> or <code>path/to/cron.yaml</code>.`,
34
+ },
35
+ {
36
+ key: 'appengine.serverGroup.configFiles',
37
+ value: `<p>(Optional) The contents of an App Engine config file (e.g., an <code>app.yaml</code> or
38
+ <code>cron.yaml</code> file). These files should not conflict with the config filepaths above:
39
+ if you include, for example, the contents of an <code>app.yaml</code>
40
+ file here, you should <b>not</b> specify the file path to an <code>app.yaml</code> above.<br></p>
41
+ <p>If this is a pipeline stage, you can use Spinnaker Pipeline Expressions here.</p>`,
42
+ },
43
+ {
44
+ key: 'appengine.serverGroup.configFilesRequired',
45
+ value: `<p>The contents of an App Engine config file (e.g., an <code>app.yaml</code> or
46
+ <code>cron.yaml</code> file).</p>
47
+ <p>An <code>app.yaml</code> file is required and must have <code>runtime: custom</code> in
48
+ order to deploy successfully.</p>
49
+ <p>If this is a pipeline stage, you can use Spinnaker Pipeline Expressions here.</p>`,
50
+ },
51
+ {
52
+ key: 'appengine.serverGroup.matchBranchOnRegex',
53
+ value: `(Optional) A Jenkins trigger may produce details from multiple repositories and branches.
54
+ Spinnaker will use the regex specified here to help resolve a branch for the deployment.
55
+ If Spinnaker cannot resolve exactly one branch from the trigger, this pipeline will fail.`,
56
+ },
57
+ {
58
+ key: 'appengine.serverGroup.promote',
59
+ value: 'If selected, the newly deployed server group will receive all traffic.',
60
+ },
61
+ {
62
+ key: 'appengine.serverGroup.stopPreviousVersion',
63
+ value: `If selected, the previously running server group in this server group's <b>service</b>
64
+ (Spinnaker load balancer) will be stopped. This option will be respected only if this server group will
65
+ be receiving all traffic and the previous server group is using manual scaling.`,
66
+ },
67
+ {
68
+ key: 'appengine.serverGroup.containerImageUrl',
69
+ value: `The full URL to the container image to use for deployment. The URL must be one of the valid GCR hostnames,
70
+ for example <b>gcr.io/my-project/image:tag</b>`,
71
+ },
72
+ {
73
+ key: 'appengine.serverGroup.suppress-version-string',
74
+ value: `Spinnaker automatically versions your server groups. This means deployments through Spinnaker receive a
75
+ short version string at the end of their name, like "v001". In most cases you will want to keep this
76
+ version as part of the name. Preventing this string from being added to your server group will stop
77
+ it from being considered when rolling back, promoting new versions or executing deployment strategies.
78
+ If you are certain that you do not want the version string applied to this server group then check
79
+ this box.`,
80
+ },
81
+ {
82
+ key: 'appengine.loadBalancer.shardBy.cookie',
83
+ value:
84
+ 'Diversion based on a specially named cookie, "GOOGAPPUID." The cookie must be set by the application itself or no diversion will occur.',
85
+ },
86
+ {
87
+ key: 'appengine.loadBalancer.shardBy.ip',
88
+ value: 'Diversion based on applying the modulus operation to a fingerprint of the IP address.',
89
+ },
90
+ {
91
+ key: 'appengine.loadBalancer.migrateTraffic',
92
+ value: `If selected, traffic will be gradually shifted to a single version. For gradual traffic migration,
93
+ the target version must be located within instances that are configured for
94
+ both warmup requests and automatic scaling.
95
+ Gradual traffic migration is not supported in the App Engine flexible environment.`,
96
+ },
97
+ {
98
+ key: 'appengine.loadBalancer.allocations',
99
+ value: 'An allocation is the percent of traffic directed to a server group.',
100
+ },
101
+ {
102
+ key: 'appengine.loadBalancer.textLocator',
103
+ value: `Either the name of a server group, or a Spinnaker Pipeline Expression
104
+ that resolves to the name of a server group.`,
105
+ },
106
+ {
107
+ key: 'appengine.instance.availability',
108
+ value: `
109
+ An instance's <b>availability</b> is determined by its version (Spinnaker server group).
110
+ <ul>
111
+ <li>Manual scaling versions use resident instances</li>
112
+ <li>Basic scaling versions use dynamic instances</li>
113
+ <li>Auto scaling versions use dynamic instances - but if you specify a number, N,
114
+ of minimum idle instances, the first N instances will be resident,
115
+ and additional dynamic instances will be created as necessary.
116
+ </li>
117
+ </ul>`,
118
+ },
119
+ {
120
+ key: 'appengine.instance.averageLatency',
121
+ value: 'Average latency over the last minute in milliseconds.',
122
+ },
123
+ {
124
+ key: 'appengine.instance.vmStatus',
125
+ value: 'Status of the virtual machine where this instance lives.',
126
+ },
127
+ {
128
+ key: 'appengine.instance.qps',
129
+ value: 'Average queries per second over the last minute.',
130
+ },
131
+ {
132
+ key: 'appengine.instance.errors',
133
+ value: 'Number of errors since this instance was started.',
134
+ },
135
+ {
136
+ key: 'appengine.instance.requests',
137
+ value: 'Number of requests since this instance was started.',
138
+ },
139
+ ];
140
+
141
+ helpContents.forEach((entry) => HelpContentsRegistry.register(entry.key, entry.value));
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { APPENGINE_MODULE } from './appengine.module';
@@ -0,0 +1,116 @@
1
+ import type { IController, IQService } from 'angular';
2
+ import { module } from 'angular';
3
+ import { cloneDeep, flattenDeep } from 'lodash';
4
+
5
+ import type { Application, ILoadBalancer } from '@spinnaker/core';
6
+ import { ConfirmationModalService, InstanceReader, InstanceWriter, RecentHistoryService } from '@spinnaker/core';
7
+ import type { IAppengineInstance } from '../../domain';
8
+
9
+ interface InstanceFromStateParams {
10
+ instanceId: string;
11
+ }
12
+
13
+ interface InstanceManager {
14
+ account: string;
15
+ region: string;
16
+ category: string; // e.g., serverGroup, loadBalancer.
17
+ name: string; // Parent resource name, not instance name.
18
+ instances: IAppengineInstance[];
19
+ }
20
+
21
+ class AppengineInstanceDetailsController implements IController {
22
+ public state = { loading: true };
23
+ public instance: IAppengineInstance;
24
+ public instanceIdNotFound: string;
25
+ public upToolTip = "An App Engine instance is 'Up' if a load balancer is directing traffic to its server group.";
26
+ public outOfServiceToolTip = `
27
+ An App Engine instance is 'Out Of Service' if no load balancers are directing traffic to its server group.`;
28
+
29
+ public static $inject = ['$q', 'app', 'instance'];
30
+
31
+ constructor(private $q: IQService, private app: Application, instance: InstanceFromStateParams) {
32
+ this.app
33
+ .ready()
34
+ .then(() => this.retrieveInstance(instance))
35
+ .then((instanceDetails) => {
36
+ this.instance = instanceDetails;
37
+ this.state.loading = false;
38
+ })
39
+ .catch(() => {
40
+ this.instanceIdNotFound = instance.instanceId;
41
+ this.state.loading = false;
42
+ });
43
+ }
44
+
45
+ public terminateInstance(): void {
46
+ const instance = cloneDeep(this.instance) as any;
47
+ const shortName = `${this.instance.name.substring(0, 10)}...`;
48
+ instance.placement = {};
49
+ instance.instanceId = instance.name;
50
+
51
+ const taskMonitor = {
52
+ application: this.app,
53
+ title: 'Terminating ' + shortName,
54
+ onTaskComplete() {
55
+ if (this.$state.includes('**.instanceDetails', { instanceId: instance.name })) {
56
+ this.$state.go('^');
57
+ }
58
+ },
59
+ };
60
+
61
+ const submitMethod = () => {
62
+ return InstanceWriter.terminateInstance(instance, this.app, { cloudProvider: 'appengine' });
63
+ };
64
+
65
+ ConfirmationModalService.confirm({
66
+ header: 'Really terminate ' + shortName + '?',
67
+ buttonText: 'Terminate ' + shortName,
68
+ account: instance.account,
69
+ taskMonitorConfig: taskMonitor,
70
+ submitMethod,
71
+ });
72
+ }
73
+
74
+ private retrieveInstance(instance: InstanceFromStateParams): PromiseLike<IAppengineInstance> {
75
+ const instanceLocatorPredicate = (dataSource: InstanceManager) => {
76
+ return dataSource.instances.some((possibleMatch) => possibleMatch.id === instance.instanceId);
77
+ };
78
+
79
+ const dataSources: InstanceManager[] = flattenDeep([
80
+ this.app.getDataSource('serverGroups').data,
81
+ this.app.getDataSource('loadBalancers').data,
82
+ this.app.getDataSource('loadBalancers').data.map((loadBalancer: ILoadBalancer) => loadBalancer.serverGroups),
83
+ ]);
84
+
85
+ const instanceManager = dataSources.find(instanceLocatorPredicate);
86
+
87
+ if (instanceManager) {
88
+ const recentHistoryExtraData: { [key: string]: string } = {
89
+ region: instanceManager.region,
90
+ account: instanceManager.account,
91
+ };
92
+ if (instanceManager.category === 'serverGroup') {
93
+ recentHistoryExtraData.serverGroup = instanceManager.name;
94
+ }
95
+ RecentHistoryService.addExtraDataToLatest('instances', recentHistoryExtraData);
96
+
97
+ return InstanceReader.getInstanceDetails(
98
+ instanceManager.account,
99
+ instanceManager.region,
100
+ instance.instanceId,
101
+ ).then((instanceDetails: IAppengineInstance) => {
102
+ instanceDetails.account = instanceManager.account;
103
+ instanceDetails.region = instanceManager.region;
104
+ return instanceDetails;
105
+ });
106
+ } else {
107
+ return this.$q.reject();
108
+ }
109
+ }
110
+ }
111
+
112
+ export const APPENGINE_INSTANCE_DETAILS_CTRL = 'spinnaker.appengine.instanceDetails.controller';
113
+ module(APPENGINE_INSTANCE_DETAILS_CTRL, []).controller(
114
+ 'appengineInstanceDetailsCtrl',
115
+ AppengineInstanceDetailsController,
116
+ );
@@ -0,0 +1,99 @@
1
+ <div class="details-panel">
2
+ <div class="header">
3
+ <instance-details-header
4
+ health-state="ctrl.instance.healthState"
5
+ instance-id="ctrl.instance ? ctrl.instance.name : ctrl.instanceIdNotFound"
6
+ loading="ctrl.state.loading"
7
+ standalone="false"
8
+ ></instance-details-header>
9
+ <div ng-if="!ctrl.state.loading">
10
+ <div class="actions">
11
+ <div class="dropdown" uib-dropdown dropdown-append-to-body>
12
+ <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>
13
+ Instance Actions <span class="caret"></span>
14
+ </button>
15
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu">
16
+ <li><a href ng-click="ctrl.terminateInstance()">Terminate</a></li>
17
+ </ul>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <div class="content" ng-if="!ctrl.state.loading && ctrl.instance">
23
+ <collapsible-section heading="Instance Information" expanded="true">
24
+ <dl class="dl-horizontal dl-narrow">
25
+ <dt>Launched</dt>
26
+ <dd ng-if="ctrl.instance.launchTime">{{ctrl.instance.launchTime | timestamp}}</dd>
27
+ <dt>In</dt>
28
+ <dd><account-tag account="ctrl.instance.account" pad="right"></account-tag>{{}}</dd>
29
+ <dt ng-if="ctrl.instance.serverGroup">Server Group</dt>
30
+ <dd ng-if="ctrl.instance.serverGroup">
31
+ <a
32
+ ui-sref="^.serverGroup({region: ctrl.instance.region,
33
+ accountId: ctrl.instance.account,
34
+ serverGroup: ctrl.instance.serverGroup,
35
+ provider: 'appengine'})"
36
+ >{{ctrl.instance.serverGroup}}</a
37
+ >
38
+ </dd>
39
+ <dt>Region</dt>
40
+ <dd>{{ctrl.instance.region}}</dd>
41
+ <appengine-conditional-dt-dd
42
+ component="ctrl.instance"
43
+ key="vmZoneName"
44
+ label="Zone"
45
+ ></appengine-conditional-dt-dd>
46
+ </dl>
47
+ </collapsible-section>
48
+ <collapsible-section heading="Status" expanded="true">
49
+ <dl>
50
+ <dt>Load Balancer</dt>
51
+ <dd>
52
+ <span
53
+ class="pull-left"
54
+ uib-tooltip="{{ctrl.instance.healthState === 'Up' ? ctrl.upToolTip : ctrl.outOfServiceToolTip}}"
55
+ tooltip-placement="right"
56
+ >
57
+ <span class="glyphicon glyphicon-{{ctrl.instance.healthState}}-triangle"></span>
58
+ {{ctrl.instance.loadBalancers[0]}}
59
+ </span>
60
+ </dd>
61
+ </dl>
62
+ </collapsible-section>
63
+ <collapsible-section heading="Metrics" expanded="true">
64
+ <dl>
65
+ <appengine-conditional-dt-dd component="ctrl.instance" key="instanceStatus" label="Availability">
66
+ <key-label><help-field key="appengine.instance.availability"></help-field></key-label>
67
+ </appengine-conditional-dt-dd>
68
+ <appengine-conditional-dt-dd component="ctrl.instance" key="averageLatency">
69
+ <key-label><help-field key="appengine.instance.averageLatency"></help-field></key-label>
70
+ <value-label>ms</value-label>
71
+ </appengine-conditional-dt-dd>
72
+ <appengine-conditional-dt-dd component="ctrl.instance" key="errors">
73
+ <key-label><help-field key="appengine.instance.errors"></help-field></key-label>
74
+ </appengine-conditional-dt-dd>
75
+ <appengine-conditional-dt-dd component="ctrl.instance" key="qps" label="QPS">
76
+ <key-label><help-field key="appengine.instance.qps"></help-field></key-label>
77
+ </appengine-conditional-dt-dd>
78
+ <appengine-conditional-dt-dd component="ctrl.instance" key="requests">
79
+ <key-label><help-field key="appengine.instance.requests"></help-field></key-label>
80
+ </appengine-conditional-dt-dd>
81
+ <appengine-conditional-dt-dd component="ctrl.instance" key="vmStatus" label="VM Status">
82
+ <key-label><help-field key="appengine.instance.vmStatus"></help-field></key-label>
83
+ </appengine-conditional-dt-dd>
84
+ <appengine-conditional-dt-dd
85
+ component="ctrl.instance"
86
+ key="vmDebugEnabled"
87
+ label="Debug Enabled"
88
+ ></appengine-conditional-dt-dd>
89
+ </dl>
90
+ </collapsible-section>
91
+ </div>
92
+ <div class="content" ng-if="!ctrl.state.loading && !ctrl.instance">
93
+ <div class="content-section">
94
+ <div class="content-body text-center">
95
+ <h3>Instance not found.</h3>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </div>
@@ -0,0 +1,56 @@
1
+ import type { IComponentOptions, IController } from 'angular';
2
+ import { module } from 'angular';
3
+
4
+ import type { AppengineLoadBalancerUpsertDescription } from '../../transformer';
5
+
6
+ class AppengineLoadBalancerAdvancedSettingsCtrl implements IController {
7
+ public state = { error: false };
8
+ public loadBalancer: AppengineLoadBalancerUpsertDescription;
9
+
10
+ public disableMigrateTraffic(): boolean {
11
+ if (this.loadBalancer.splitDescription.allocationDescriptions.length !== 1) {
12
+ return true;
13
+ } else {
14
+ const targetServerGroupName = this.loadBalancer.splitDescription.allocationDescriptions[0].serverGroupName;
15
+ const targetServerGroup = this.loadBalancer.serverGroups.find(
16
+ (candidate) => candidate.name === targetServerGroupName,
17
+ );
18
+
19
+ if (targetServerGroup) {
20
+ return !targetServerGroup.allowsGradualTrafficMigration;
21
+ } else {
22
+ // If the target server group name is not in the load balancer's server groups, then hopefully we are in
23
+ // a pipeline stage - we'll leave it up to the user to make smart decisions.
24
+ return false;
25
+ }
26
+ }
27
+ }
28
+ }
29
+
30
+ const appengineLoadBalancerAdvancedSettingsComponent: IComponentOptions = {
31
+ bindings: { loadBalancer: '=', application: '<' },
32
+ template: `
33
+ <ng-form name="advancedSettingsForm">
34
+ <div class="row">
35
+ <div class="form-group">
36
+ <div class="col-md-3 sm-label-right">
37
+ Migrate Traffic <help-field key="appengine.loadBalancer.migrateTraffic"></help-field>
38
+ </div>
39
+ <div class="col-md-9">
40
+ <div class="checkbox">
41
+ <input type="checkbox" ng-disabled="$ctrl.disableMigrateTraffic() && !($ctrl.loadBalancer.migrateTraffic = false)" ng-model="$ctrl.loadBalancer.migrateTraffic">
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </ng-form>
47
+ `,
48
+ controller: AppengineLoadBalancerAdvancedSettingsCtrl,
49
+ };
50
+
51
+ export const APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS = 'spinnaker.appengine.loadBalancer.advancedSettings.component';
52
+
53
+ module(APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS, []).component(
54
+ 'appengineLoadBalancerAdvancedSettings',
55
+ appengineLoadBalancerAdvancedSettingsComponent,
56
+ );
@@ -0,0 +1,70 @@
1
+ import type { IComponentOptions, IController } from 'angular';
2
+ import { module } from 'angular';
3
+ import { uniq } from 'lodash';
4
+
5
+ import type { IAppengineAllocationDescription } from '../../transformer';
6
+
7
+ class AppengineAllocationConfigurationRowCtrl implements IController {
8
+ public allocationDescription: IAppengineAllocationDescription;
9
+ public serverGroupOptions: string[];
10
+
11
+ public getServerGroupOptions(): string[] {
12
+ if (this.allocationDescription.serverGroupName) {
13
+ return uniq(this.serverGroupOptions.concat(this.allocationDescription.serverGroupName));
14
+ } else {
15
+ return this.serverGroupOptions;
16
+ }
17
+ }
18
+ }
19
+
20
+ const appengineAllocationConfigurationRowComponent: IComponentOptions = {
21
+ bindings: {
22
+ allocationDescription: '<',
23
+ removeAllocation: '&',
24
+ serverGroupOptions: '<',
25
+ onAllocationChange: '&',
26
+ },
27
+ template: `
28
+ <div class="form-group">
29
+ <div class="row">
30
+ <div class="col-md-7">
31
+ <ui-select ng-model="$ctrl.allocationDescription.serverGroupName"
32
+ on-select="$ctrl.onAllocationChange()"
33
+ class="form-control input-sm">
34
+ <ui-select-match placeholder="Select...">
35
+ {{$select.selected}}
36
+ </ui-select-match>
37
+ <ui-select-choices repeat="serverGroup as serverGroup in $ctrl.getServerGroupOptions() | filter: $select.search">
38
+ <div ng-bind-html="serverGroup | highlight: $select.search"></div>
39
+ </ui-select-choices>
40
+ </ui-select>
41
+ </div>
42
+ <div class="col-md-3">
43
+ <div class="input-group input-group-sm">
44
+ <input type="number"
45
+ ng-model="$ctrl.allocationDescription.allocation"
46
+ required
47
+ class="form-control input-sm"
48
+ min="0"
49
+ ng-change="$ctrl.onAllocationChange()"
50
+ max="100"/>
51
+ <span class="input-group-addon">%</span>
52
+ </div>
53
+ </div>
54
+ <div class="col-md-2">
55
+ <a class="btn btn-link sm-label" ng-click="$ctrl.removeAllocation()">
56
+ <span class="glyphicon glyphicon-trash"></span>
57
+ </a>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ `,
62
+ controller: AppengineAllocationConfigurationRowCtrl,
63
+ };
64
+
65
+ export const APPENGINE_ALLOCATION_CONFIGURATION_ROW = 'spinnaker.appengine.allocationConfigurationRow.component';
66
+
67
+ module(APPENGINE_ALLOCATION_CONFIGURATION_ROW, []).component(
68
+ 'appengineAllocationConfigurationRow',
69
+ appengineAllocationConfigurationRowComponent,
70
+ );
@@ -0,0 +1,65 @@
1
+ <ng-form name="basicSettingsForm">
2
+ <div class="row">
3
+ <div class="form-group">
4
+ <div class="col-md-3 sm-label-right">
5
+ Allocations
6
+ <help-field key="appengine.loadBalancer.allocations"></help-field>
7
+ </div>
8
+ <div class="col-md-9">
9
+ <div ng-if="!$ctrl.forPipelineConfig">
10
+ <appengine-allocation-configuration-row
11
+ ng-repeat="description in $ctrl.loadBalancer.splitDescription.allocationDescriptions"
12
+ allocation-description="description"
13
+ server-group-options="$ctrl.serverGroupOptions"
14
+ on-allocation-change="$ctrl.updateServerGroupOptions()"
15
+ remove-allocation="$ctrl.removeAllocation($index)"
16
+ >
17
+ </appengine-allocation-configuration-row>
18
+ </div>
19
+ <div ng-if="$ctrl.forPipelineConfig">
20
+ <appengine-stage-allocation-configuration-row
21
+ ng-repeat="description in $ctrl.loadBalancer.splitDescription.allocationDescriptions"
22
+ allocation-description="description"
23
+ application="$ctrl.application"
24
+ region="{{ $ctrl.loadBalancer.region }}"
25
+ account="{{ $ctrl.loadBalancer.account || $ctrl.loadBalancer.credentials }}"
26
+ server-group-options="$ctrl.serverGroupOptions"
27
+ on-allocation-change="$ctrl.updateServerGroupOptions()"
28
+ remove-allocation="$ctrl.removeAllocation($index)"
29
+ >
30
+ </appengine-stage-allocation-configuration-row>
31
+ </div>
32
+ <button class="add-new col-md-11" ng-if="$ctrl.showAddButton()" ng-click="$ctrl.addAllocation()">
33
+ <span class="glyphicon glyphicon-plus-sign"></span> Add allocation
34
+ </button>
35
+ </div>
36
+ </div>
37
+ <div class="form-group" ng-if="$ctrl.allocationIsInvalid()">
38
+ <div class="col-md-12 text-center">
39
+ <p class="alert alert-warning">Allocations must sum to 100%.</p>
40
+ </div>
41
+ </div>
42
+ </div>
43
+
44
+ <div class="row" ng-if="$ctrl.showShardByOptions()">
45
+ <div class="form-group">
46
+ <div class="col-md-3 sm-label-right">Shard By</div>
47
+ <div class="col-md-9">
48
+ <form class="form-inline">
49
+ <div class="form-group">
50
+ <label class="radio-inline">
51
+ <input type="radio" ng-model="$ctrl.loadBalancer.splitDescription.shardBy" value="IP" />
52
+ IP
53
+ <help-field key="appengine.loadBalancer.shardBy.ip"></help-field>
54
+ </label>
55
+ <label class="radio-inline">
56
+ <input type="radio" ng-model="$ctrl.loadBalancer.splitDescription.shardBy" value="COOKIE" />
57
+ Cookie
58
+ <help-field key="appengine.loadBalancer.shardBy.cookie"></help-field>
59
+ </label>
60
+ </div>
61
+ </form>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ </ng-form>