@spinnaker/appengine 2026.0.2 → 2026.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/common/componentUrlDetails.component.ts","../src/common/conditionalDescriptionListItem.component.ts","../src/common/loadBalancerMessage.component.ts","../src/helpContents/appengineHelpContents.ts","../src/instance/details/details.controller.ts","../src/loadBalancer/configure/wizard/advancedSettings.component.ts","../src/loadBalancer/configure/wizard/allocationConfigurationRow.component.ts","../src/loadBalancer/configure/wizard/basicSettings.component.ts","../src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.ts","../src/loadBalancer/transformer.ts","../../../node_modules/style-inject/dist/style-inject.es.js","../src/loadBalancer/configure/wizard/wizard.controller.ts","../src/loadBalancer/details/details.controller.ts","../src/loadBalancer/loadBalancer.module.ts","../src/common/appengineHealth.ts","../src/pipeline/stages/appengineStage.controller.ts","../src/pipeline/stages/destroyAsg/appengineDestroyAsgStage.ts","../src/pipeline/stages/disableAsg/appengineDisableAsgStage.ts","../src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.ts","../src/pipeline/stages/editLoadBalancer/appengineEditLoadBalancerStage.ts","../src/pipeline/stages/enableAsg/appengineEnableAsgStage.ts","../src/pipeline/stages/shrinkCluster/appengineShrinkClusterStage.ts","../src/pipeline/stages/startServerGroup/appengineStartServerGroupStage.ts","../src/pipeline/stages/stopServerGroup/appengineStopServerGroupStage.ts","../src/pipeline/pipeline.module.ts","../src/common/FormikAccountRegionSelector.tsx","../src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigForm.tsx","../src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigurationConfig.tsx","../src/pipeline/stages/deployAppengineConfig/deployAppengineConfigStage.ts","../src/appengine.settings.ts","../src/serverGroup/configure/serverGroupCommandBuilder.service.ts","../src/serverGroup/configure/wizard/basicSettings.controller.ts","../src/serverGroup/configure/wizard/configFiles.component.ts","../src/serverGroup/configure/wizard/dynamicBranchLabel.component.ts","../src/serverGroup/configure/wizard/cloneServerGroup.controller.ts","../src/serverGroup/configure/wizard/ConfigFileArtifactList.tsx","../src/serverGroup/configure/wizard/configFileArtifactList.module.ts","../src/serverGroup/writer/serverGroup.write.service.ts","../src/serverGroup/details/details.controller.ts","../src/serverGroup/transformer.ts","../src/validation/ApplicationNameValidator.ts","../src/appengine.module.ts","../src/logo/appengine.logo.png"],"sourcesContent":["import type { IComponentOptions } from 'angular';\nimport { module } from 'angular';\n\nconst appengineComponentUrlDetailsComponent: IComponentOptions = {\n bindings: { component: '<' },\n template: `\n <dt>HTTPS</dt>\n <dl class=\"small\">\n <a href=\"{{$ctrl.component.httpsUrl}}\" target=\"_blank\">{{$ctrl.component.httpsUrl}}</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 <dt>HTTP</dt>\n <dl class=\"small\">\n <a href=\"{{$ctrl.component.httpUrl}}\" target=\"_blank\">{{$ctrl.component.httpUrl}}</a>\n <copy-to-clipboard class=\"copy-to-clipboard copy-to-clipboard-sm\"\n tool-tip=\"'Copy URL to clipboard'\"\n text=\"$ctrl.component.httpUrl\"></copy-to-clipboard>\n </dl>\n `,\n};\n\nexport const APPENGINE_COMPONENT_URL_DETAILS = 'spinnaker.appengine.componentUrlDetails.component';\n\nmodule(APPENGINE_COMPONENT_URL_DETAILS, []).component(\n 'appengineComponentUrlDetails',\n appengineComponentUrlDetailsComponent,\n);\n","import type { IComponentOptions, IController, IFilterService } from 'angular';\nimport { module } from 'angular';\n\nclass AppengineConditionalDescriptionListItemCtrl implements IController {\n public label: string;\n public key: string;\n public component: any;\n\n public static $inject = ['$filter'];\n constructor(private $filter: IFilterService) {}\n\n public $onInit(): void {\n if (!this.label) {\n this.label = this.$filter<Function>('robotToHuman')(this.key);\n }\n }\n}\n\nconst appengineConditionalDescriptionListItem: IComponentOptions = {\n bindings: { label: '@', key: '@', component: '<' },\n transclude: {\n keyLabel: '?keyText',\n valueLabel: '?valueLabel',\n },\n template: `\n <dt ng-if=\"$ctrl.component[$ctrl.key]\">{{$ctrl.label}}<span ng-transclude=\"keyLabel\"></span></dt>\n <dd ng-if=\"$ctrl.component[$ctrl.key]\">{{$ctrl.component[$ctrl.key]}}<span ng-transclude=\"valueLabel\"></span></dd>\n `,\n controller: AppengineConditionalDescriptionListItemCtrl,\n};\n\nexport const APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM = 'spinnaker.appengine.conditionalDescriptionListItem';\n\nmodule(APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM, []).component(\n 'appengineConditionalDtDd',\n appengineConditionalDescriptionListItem,\n);\n","import { module } from 'angular';\n\nconst appengineLoadBalancerMessageComponent: ng.IComponentOptions = {\n bindings: { showCreateMessage: '<', columnOffset: '@', columns: '@' },\n templateUrl: require('./loadBalancerMessage.component.html'),\n};\n\nexport const APPENGINE_LOAD_BALANCER_CREATE_MESSAGE = 'spinnaker.appengine.loadBalancer.createMessage.component';\n\nmodule(APPENGINE_LOAD_BALANCER_CREATE_MESSAGE, []).component(\n 'appengineLoadBalancerMessage',\n appengineLoadBalancerMessageComponent,\n);\n","import { HelpContentsRegistry } from '@spinnaker/core';\n\nconst helpContents = [\n {\n key: 'appengine.serverGroup.gcs.repositoryUrl',\n value: `The full URL to the GCS bucket or TAR file containing the source files for this deployment,\n including 'gs://'. For example, <b>gs://my-bucket/my-app</b> or <b>gs://my-bucket/app.tar</b>.`,\n },\n {\n key: 'appengine.serverGroup.git.repositoryUrl',\n value: `The full URL to the git repository containing the source files for this deployment,\n including protocol. For example, <b>https://github.com/spinnaker/deck.git</b>`,\n },\n {\n key: 'appengine.serverGroup.gitCredentialType',\n value: `The credential type that will be used to access the git repository for this deployment.\n You can configure these credentials alongside your App Engine credentials.`,\n },\n {\n key: 'appengine.serverGroup.branch',\n value: 'The name of the branch in the above git repository to be used for this deployment.',\n },\n {\n key: 'appengine.serverGroup.applicationDirectoryRoot',\n value: `(Optional) Path to the directory root of the application to be deployed,\n starting from the root of the git repository. This is the directory from which\n <code>gcloud app deploy</code> will be run.`,\n },\n {\n key: 'appengine.serverGroup.configFilepaths',\n value: `Paths to App Engine application configuration files, starting from the application directory root,\n specified above. In most cases, this will be <code>app.yaml</code> or <code>cron.yaml</code>,\n but could be <code>path/to/app.yaml</code> or <code>path/to/cron.yaml</code>.`,\n },\n {\n key: 'appengine.serverGroup.configFiles',\n value: `<p>(Optional) The contents of an App Engine config file (e.g., an <code>app.yaml</code> or\n <code>cron.yaml</code> file). These files should not conflict with the config filepaths above:\n if you include, for example, the contents of an <code>app.yaml</code>\n file here, you should <b>not</b> specify the file path to an <code>app.yaml</code> above.<br></p>\n <p>If this is a pipeline stage, you can use Spinnaker Pipeline Expressions here.</p>`,\n },\n {\n key: 'appengine.serverGroup.configFilesRequired',\n value: `<p>The contents of an App Engine config file (e.g., an <code>app.yaml</code> or\n <code>cron.yaml</code> file).</p>\n <p>An <code>app.yaml</code> file is required and must have <code>runtime: custom</code> in\n order to deploy successfully.</p>\n <p>If this is a pipeline stage, you can use Spinnaker Pipeline Expressions here.</p>`,\n },\n {\n key: 'appengine.serverGroup.matchBranchOnRegex',\n value: `(Optional) A Jenkins trigger may produce details from multiple repositories and branches.\n Spinnaker will use the regex specified here to help resolve a branch for the deployment.\n If Spinnaker cannot resolve exactly one branch from the trigger, this pipeline will fail.`,\n },\n {\n key: 'appengine.serverGroup.promote',\n value: 'If selected, the newly deployed server group will receive all traffic.',\n },\n {\n key: 'appengine.serverGroup.stopPreviousVersion',\n value: `If selected, the previously running server group in this server group's <b>service</b>\n (Spinnaker load balancer) will be stopped. This option will be respected only if this server group will\n be receiving all traffic and the previous server group is using manual scaling.`,\n },\n {\n key: 'appengine.serverGroup.containerImageUrl',\n value: `The full URL to the container image to use for deployment. The URL must be one of the valid GCR hostnames,\n for example <b>gcr.io/my-project/image:tag</b>`,\n },\n {\n key: 'appengine.serverGroup.suppress-version-string',\n value: `Spinnaker automatically versions your server groups. This means deployments through Spinnaker receive a\n short version string at the end of their name, like \"v001\". In most cases you will want to keep this\n version as part of the name. Preventing this string from being added to your server group will stop\n it from being considered when rolling back, promoting new versions or executing deployment strategies.\n If you are certain that you do not want the version string applied to this server group then check\n this box.`,\n },\n {\n key: 'appengine.loadBalancer.shardBy.cookie',\n value:\n 'Diversion based on a specially named cookie, \"GOOGAPPUID.\" The cookie must be set by the application itself or no diversion will occur.',\n },\n {\n key: 'appengine.loadBalancer.shardBy.ip',\n value: 'Diversion based on applying the modulus operation to a fingerprint of the IP address.',\n },\n {\n key: 'appengine.loadBalancer.migrateTraffic',\n value: `If selected, traffic will be gradually shifted to a single version. For gradual traffic migration,\n the target version must be located within instances that are configured for\n both warmup requests and automatic scaling.\n Gradual traffic migration is not supported in the App Engine flexible environment.`,\n },\n {\n key: 'appengine.loadBalancer.allocations',\n value: 'An allocation is the percent of traffic directed to a server group.',\n },\n {\n key: 'appengine.loadBalancer.textLocator',\n value: `Either the name of a server group, or a Spinnaker Pipeline Expression\n that resolves to the name of a server group.`,\n },\n {\n key: 'appengine.instance.availability',\n value: `\n An instance's <b>availability</b> is determined by its version (Spinnaker server group).\n <ul>\n <li>Manual scaling versions use resident instances</li>\n <li>Basic scaling versions use dynamic instances</li>\n <li>Auto scaling versions use dynamic instances - but if you specify a number, N,\n of minimum idle instances, the first N instances will be resident,\n and additional dynamic instances will be created as necessary.\n </li>\n </ul>`,\n },\n {\n key: 'appengine.instance.averageLatency',\n value: 'Average latency over the last minute in milliseconds.',\n },\n {\n key: 'appengine.instance.vmStatus',\n value: 'Status of the virtual machine where this instance lives.',\n },\n {\n key: 'appengine.instance.qps',\n value: 'Average queries per second over the last minute.',\n },\n {\n key: 'appengine.instance.errors',\n value: 'Number of errors since this instance was started.',\n },\n {\n key: 'appengine.instance.requests',\n value: 'Number of requests since this instance was started.',\n },\n];\n\nhelpContents.forEach((entry) => HelpContentsRegistry.register(entry.key, entry.value));\n","import type { IController, IQService } from 'angular';\nimport { module } from 'angular';\nimport { cloneDeep, flattenDeep } from 'lodash';\n\nimport type { Application, ILoadBalancer } from '@spinnaker/core';\nimport { ConfirmationModalService, InstanceReader, InstanceWriter, RecentHistoryService } from '@spinnaker/core';\nimport type { IAppengineInstance } from '../../domain';\n\ninterface InstanceFromStateParams {\n instanceId: string;\n}\n\ninterface InstanceManager {\n account: string;\n region: string;\n category: string; // e.g., serverGroup, loadBalancer.\n name: string; // Parent resource name, not instance name.\n instances: IAppengineInstance[];\n}\n\nclass AppengineInstanceDetailsController implements IController {\n public state = { loading: true };\n public instance: IAppengineInstance;\n public instanceIdNotFound: string;\n public upToolTip = \"An App Engine instance is 'Up' if a load balancer is directing traffic to its server group.\";\n public outOfServiceToolTip = `\n An App Engine instance is 'Out Of Service' if no load balancers are directing traffic to its server group.`;\n\n public static $inject = ['$q', 'app', 'instance'];\n\n constructor(private $q: IQService, private app: Application, instance: InstanceFromStateParams) {\n this.app\n .ready()\n .then(() => this.retrieveInstance(instance))\n .then((instanceDetails) => {\n this.instance = instanceDetails;\n this.state.loading = false;\n })\n .catch(() => {\n this.instanceIdNotFound = instance.instanceId;\n this.state.loading = false;\n });\n }\n\n public terminateInstance(): void {\n const instance = cloneDeep(this.instance) as any;\n const shortName = `${this.instance.name.substring(0, 10)}...`;\n instance.placement = {};\n instance.instanceId = instance.name;\n\n const taskMonitor = {\n application: this.app,\n title: 'Terminating ' + shortName,\n onTaskComplete() {\n if (this.$state.includes('**.instanceDetails', { instanceId: instance.name })) {\n this.$state.go('^');\n }\n },\n };\n\n const submitMethod = () => {\n return InstanceWriter.terminateInstance(instance, this.app, { cloudProvider: 'appengine' });\n };\n\n ConfirmationModalService.confirm({\n header: 'Really terminate ' + shortName + '?',\n buttonText: 'Terminate ' + shortName,\n account: instance.account,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n });\n }\n\n private retrieveInstance(instance: InstanceFromStateParams): PromiseLike<IAppengineInstance> {\n const instanceLocatorPredicate = (dataSource: InstanceManager) => {\n return dataSource.instances.some((possibleMatch) => possibleMatch.id === instance.instanceId);\n };\n\n const dataSources: InstanceManager[] = flattenDeep([\n this.app.getDataSource('serverGroups').data,\n this.app.getDataSource('loadBalancers').data,\n this.app.getDataSource('loadBalancers').data.map((loadBalancer: ILoadBalancer) => loadBalancer.serverGroups),\n ]);\n\n const instanceManager = dataSources.find(instanceLocatorPredicate);\n\n if (instanceManager) {\n const recentHistoryExtraData: { [key: string]: string } = {\n region: instanceManager.region,\n account: instanceManager.account,\n };\n if (instanceManager.category === 'serverGroup') {\n recentHistoryExtraData.serverGroup = instanceManager.name;\n }\n RecentHistoryService.addExtraDataToLatest('instances', recentHistoryExtraData);\n\n return InstanceReader.getInstanceDetails(\n instanceManager.account,\n instanceManager.region,\n instance.instanceId,\n ).then((instanceDetails: IAppengineInstance) => {\n instanceDetails.account = instanceManager.account;\n instanceDetails.region = instanceManager.region;\n return instanceDetails;\n });\n } else {\n return this.$q.reject();\n }\n }\n}\n\nexport const APPENGINE_INSTANCE_DETAILS_CTRL = 'spinnaker.appengine.instanceDetails.controller';\nmodule(APPENGINE_INSTANCE_DETAILS_CTRL, []).controller(\n 'appengineInstanceDetailsCtrl',\n AppengineInstanceDetailsController,\n);\n","import type { IComponentOptions, IController } from 'angular';\nimport { module } from 'angular';\n\nimport type { AppengineLoadBalancerUpsertDescription } from '../../transformer';\n\nclass AppengineLoadBalancerAdvancedSettingsCtrl implements IController {\n public state = { error: false };\n public loadBalancer: AppengineLoadBalancerUpsertDescription;\n\n public disableMigrateTraffic(): boolean {\n if (this.loadBalancer.splitDescription.allocationDescriptions.length !== 1) {\n return true;\n } else {\n const targetServerGroupName = this.loadBalancer.splitDescription.allocationDescriptions[0].serverGroupName;\n const targetServerGroup = this.loadBalancer.serverGroups.find(\n (candidate) => candidate.name === targetServerGroupName,\n );\n\n if (targetServerGroup) {\n return !targetServerGroup.allowsGradualTrafficMigration;\n } else {\n // If the target server group name is not in the load balancer's server groups, then hopefully we are in\n // a pipeline stage - we'll leave it up to the user to make smart decisions.\n return false;\n }\n }\n }\n}\n\nconst appengineLoadBalancerAdvancedSettingsComponent: IComponentOptions = {\n bindings: { loadBalancer: '=', application: '<' },\n template: `\n <ng-form name=\"advancedSettingsForm\">\n <div class=\"row\">\n <div class=\"form-group\">\n <div class=\"col-md-3 sm-label-right\">\n Migrate Traffic <help-field key=\"appengine.loadBalancer.migrateTraffic\"></help-field>\n </div>\n <div class=\"col-md-9\">\n <div class=\"checkbox\">\n <input type=\"checkbox\" ng-disabled=\"$ctrl.disableMigrateTraffic() && !($ctrl.loadBalancer.migrateTraffic = false)\" ng-model=\"$ctrl.loadBalancer.migrateTraffic\">\n </div>\n </div>\n </div>\n </div>\n </ng-form>\n `,\n controller: AppengineLoadBalancerAdvancedSettingsCtrl,\n};\n\nexport const APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS = 'spinnaker.appengine.loadBalancer.advancedSettings.component';\n\nmodule(APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS, []).component(\n 'appengineLoadBalancerAdvancedSettings',\n appengineLoadBalancerAdvancedSettingsComponent,\n);\n","import type { IComponentOptions, IController } from 'angular';\nimport { module } from 'angular';\nimport { uniq } from 'lodash';\n\nimport type { IAppengineAllocationDescription } from '../../transformer';\n\nclass AppengineAllocationConfigurationRowCtrl implements IController {\n public allocationDescription: IAppengineAllocationDescription;\n public serverGroupOptions: string[];\n\n public getServerGroupOptions(): string[] {\n if (this.allocationDescription.serverGroupName) {\n return uniq(this.serverGroupOptions.concat(this.allocationDescription.serverGroupName));\n } else {\n return this.serverGroupOptions;\n }\n }\n}\n\nconst appengineAllocationConfigurationRowComponent: IComponentOptions = {\n bindings: {\n allocationDescription: '<',\n removeAllocation: '&',\n serverGroupOptions: '<',\n onAllocationChange: '&',\n },\n template: `\n <div class=\"form-group\">\n <div class=\"row\">\n <div class=\"col-md-7\">\n <ui-select ng-model=\"$ctrl.allocationDescription.serverGroupName\"\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.allocation\"\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 `,\n controller: AppengineAllocationConfigurationRowCtrl,\n};\n\nexport const APPENGINE_ALLOCATION_CONFIGURATION_ROW = 'spinnaker.appengine.allocationConfigurationRow.component';\n\nmodule(APPENGINE_ALLOCATION_CONFIGURATION_ROW, []).component(\n 'appengineAllocationConfigurationRow',\n appengineAllocationConfigurationRowComponent,\n);\n","import type { IController } from 'angular';\nimport { module } from 'angular';\nimport { difference } from 'lodash';\n\nimport type { AppengineLoadBalancerUpsertDescription } from '../../transformer';\n\nclass AppengineLoadBalancerSettingsController implements IController {\n public loadBalancer: AppengineLoadBalancerUpsertDescription;\n public serverGroupOptions: string[];\n public forPipelineConfig: boolean;\n\n public $onInit(): void {\n this.updateServerGroupOptions();\n }\n\n public addAllocation(): void {\n const remainingServerGroups = this.serverGroupsWithoutAllocation();\n if (remainingServerGroups.length) {\n this.loadBalancer.splitDescription.allocationDescriptions.push({\n serverGroupName: remainingServerGroups[0],\n allocation: 0,\n locatorType: 'fromExisting',\n });\n if (\n this.loadBalancer.splitDescription.allocationDescriptions.length > 1 &&\n !this.loadBalancer.splitDescription.shardBy\n ) {\n this.loadBalancer.splitDescription.shardBy = 'IP';\n }\n this.updateServerGroupOptions();\n } else if (this.forPipelineConfig) {\n this.loadBalancer.splitDescription.allocationDescriptions.push({\n allocation: 0,\n locatorType: 'text',\n serverGroupName: '',\n });\n }\n }\n\n public removeAllocation(index: number): void {\n this.loadBalancer.splitDescription.allocationDescriptions.splice(index, 1);\n this.updateServerGroupOptions();\n }\n\n public allocationIsInvalid(): boolean {\n return (\n this.loadBalancer.splitDescription.allocationDescriptions.reduce(\n (sum, allocationDescription) => sum + allocationDescription.allocation,\n 0,\n ) !== 100\n );\n }\n\n public updateServerGroupOptions(): void {\n this.serverGroupOptions = this.serverGroupsWithoutAllocation();\n }\n\n public showAddButton(): boolean {\n if (this.forPipelineConfig) {\n return true;\n } else {\n return this.serverGroupsWithoutAllocation().length > 0;\n }\n }\n\n public showShardByOptions(): boolean {\n return this.loadBalancer.splitDescription.allocationDescriptions.length > 1 || this.loadBalancer.migrateTraffic;\n }\n\n public initializeAsTextInput(serverGroupName: string): boolean {\n if (this.forPipelineConfig) {\n return !this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name).includes(serverGroupName);\n } else {\n return false;\n }\n }\n\n private serverGroupsWithoutAllocation(): string[] {\n const serverGroupsWithAllocation = this.loadBalancer.splitDescription.allocationDescriptions.map(\n (description) => description.serverGroupName,\n );\n const allServerGroups = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);\n return difference(allServerGroups, serverGroupsWithAllocation);\n }\n}\n\nconst appengineLoadBalancerSettingsComponent: ng.IComponentOptions = {\n bindings: { loadBalancer: '=', forPipelineConfig: '<', application: '<' },\n controller: AppengineLoadBalancerSettingsController,\n templateUrl: require('./basicSettings.component.html'),\n};\n\nexport const APPENGINE_LOAD_BALANCER_BASIC_SETTINGS = 'spinnaker.appengine.loadBalancerSettings.component';\n\nmodule(APPENGINE_LOAD_BALANCER_BASIC_SETTINGS, []).component(\n 'appengineLoadBalancerBasicSettings',\n appengineLoadBalancerSettingsComponent,\n);\n","import type { IComponentOptions, IController } from 'angular';\nimport { module } from 'angular';\nimport { uniq } from 'lodash';\n\nimport type { Application } from '@spinnaker/core';\nimport { AppListExtractor, StageConstants } from '@spinnaker/core';\n\nimport type { IAppengineAllocationDescription } from '../../transformer';\n\nclass AppengineStageAllocationLabelCtrl implements IController {\n public inputViewValue: string;\n private allocationDescription: IAppengineAllocationDescription;\n\n private static mapTargetCoordinateToLabel(targetCoordinate: string): string {\n const target = StageConstants.TARGET_LIST.find((t) => t.val === targetCoordinate);\n if (target) {\n return target.label;\n } else {\n return null;\n }\n }\n\n public $doCheck(): void {\n this.setInputViewValue();\n }\n\n private setInputViewValue(): void {\n switch (this.allocationDescription.locatorType) {\n case 'text':\n this.inputViewValue = this.allocationDescription.serverGroupName;\n break;\n case 'fromExisting':\n this.inputViewValue = this.allocationDescription.serverGroupName;\n break;\n case 'targetCoordinate':\n if (this.allocationDescription.cluster && this.allocationDescription.target) {\n const targetLabel = AppengineStageAllocationLabelCtrl.mapTargetCoordinateToLabel(\n this.allocationDescription.target,\n );\n this.inputViewValue = `${targetLabel} (${this.allocationDescription.cluster})`;\n } else {\n this.inputViewValue = null;\n }\n break;\n default:\n this.inputViewValue = null;\n break;\n }\n }\n}\n\nconst appengineStageAllocationLabel: IComponentOptions = {\n bindings: { allocationDescription: '<' },\n controller: AppengineStageAllocationLabelCtrl,\n template: `<input ng-model=\"$ctrl.inputViewValue\" type=\"text\" class=\"form-control input-sm\" readonly/>`,\n};\n\nclass AppengineStageAllocationConfigurationRowCtrl implements IController {\n public allocationDescription: IAppengineAllocationDescription;\n public serverGroupOptions: string[];\n public targets = StageConstants.TARGET_LIST;\n public clusterList: string[];\n public onAllocationChange: Function;\n private application: Application;\n private region: string;\n private account: string;\n\n public $onInit() {\n const clusterFilter = AppListExtractor.clusterFilterForCredentialsAndRegion(this.account, this.region);\n this.clusterList = AppListExtractor.getClusters([this.application], clusterFilter);\n }\n\n public getServerGroupOptions(): string[] {\n if (this.allocationDescription.serverGroupName) {\n return uniq(this.serverGroupOptions.concat(this.allocationDescription.serverGroupName));\n } else {\n return this.serverGroupOptions;\n }\n }\n\n public onLocatorTypeChange(): void {\n // Prevents pipeline expressions (or non-existent server groups) from entering the dropdown.\n if (!this.serverGroupOptions.includes(this.allocationDescription.serverGroupName)) {\n delete this.allocationDescription.serverGroupName;\n }\n this.onAllocationChange();\n }\n}\n\nconst appengineStageAllocationConfigurationRow: IComponentOptions = {\n bindings: {\n application: '<',\n region: '@',\n account: '@',\n allocationDescription: '<',\n removeAllocation: '&',\n serverGroupOptions: '<',\n onAllocationChange: '&',\n },\n controller: AppengineStageAllocationConfigurationRowCtrl,\n templateUrl: require('./stageAllocationConfigurationRow.component.html'),\n};\n\nexport const APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW =\n 'spinnaker.appengine.stageAllocationConfigurationRow.component';\nmodule(APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW, [])\n .component('appengineStageAllocationConfigurationRow', appengineStageAllocationConfigurationRow)\n .component('appengineStageAllocationLabel', appengineStageAllocationLabel);\n","import { module } from 'angular';\nimport { camelCase, chain, cloneDeep, filter, get, has, reduce } from 'lodash';\n\nimport type {\n Application,\n IInstance,\n IInstanceCounts,\n ILoadBalancer,\n ILoadBalancerUpsertCommand,\n IServerGroup,\n} from '@spinnaker/core';\nimport type { IAppengineLoadBalancer, IAppengineTrafficSplit, ShardBy } from '../domain/index';\n\nexport interface IAppengineAllocationDescription {\n serverGroupName?: string;\n target?: string;\n cluster?: string;\n allocation: number;\n locatorType: 'fromExisting' | 'targetCoordinate' | 'text';\n}\n\nexport interface IAppengineTrafficSplitDescription {\n shardBy: ShardBy;\n allocationDescriptions: IAppengineAllocationDescription[];\n}\n\nexport class AppengineLoadBalancerUpsertDescription implements ILoadBalancerUpsertCommand, IAppengineLoadBalancer {\n public credentials: string;\n public account: string;\n public loadBalancerName: string;\n public name: string;\n public splitDescription: IAppengineTrafficSplitDescription;\n public split?: IAppengineTrafficSplit;\n public migrateTraffic: boolean;\n public region: string;\n public cloudProvider: string;\n public serverGroups?: any[];\n\n public static convertTrafficSplitToTrafficSplitDescription(\n split: IAppengineTrafficSplit,\n ): IAppengineTrafficSplitDescription {\n const allocationDescriptions = reduce(\n split.allocations,\n (acc: IAppengineAllocationDescription[], allocation: number, serverGroupName: string) => {\n return acc.concat({ serverGroupName, allocation, locatorType: 'fromExisting' });\n },\n [],\n );\n\n return { shardBy: split.shardBy, allocationDescriptions };\n }\n\n constructor(loadBalancer: IAppengineLoadBalancer) {\n this.credentials = loadBalancer.account || loadBalancer.credentials;\n this.account = this.credentials;\n this.cloudProvider = loadBalancer.cloudProvider;\n this.loadBalancerName = loadBalancer.name;\n this.name = loadBalancer.name;\n this.region = loadBalancer.region;\n this.migrateTraffic = loadBalancer.migrateTraffic || false;\n this.serverGroups = loadBalancer.serverGroups;\n }\n\n public mapAllocationsToDecimals() {\n this.splitDescription.allocationDescriptions.forEach((description) => {\n description.allocation = description.allocation / 100;\n });\n }\n\n public mapAllocationsToPercentages() {\n this.splitDescription.allocationDescriptions.forEach((description) => {\n // An allocation percent has at most one decimal place.\n description.allocation = Math.round(description.allocation * 1000) / 10;\n });\n }\n}\n\nexport class AppengineLoadBalancerTransformer {\n public static $inject = ['$q'];\n constructor(private $q: ng.IQService) {}\n\n public normalizeLoadBalancer(loadBalancer: ILoadBalancer): PromiseLike<ILoadBalancer> {\n loadBalancer.provider = loadBalancer.type;\n loadBalancer.instanceCounts = this.buildInstanceCounts(loadBalancer.serverGroups);\n loadBalancer.instances = [];\n loadBalancer.serverGroups.forEach((serverGroup) => {\n serverGroup.account = loadBalancer.account;\n serverGroup.region = loadBalancer.region;\n\n if (serverGroup.detachedInstances) {\n serverGroup.detachedInstances = (serverGroup.detachedInstances as any).map((id: string) => ({ id }));\n }\n serverGroup.instances = serverGroup.instances\n .concat(serverGroup.detachedInstances || [])\n .map((instance: any) => this.transformInstance(instance, loadBalancer));\n });\n\n const activeServerGroups = filter(loadBalancer.serverGroups, { isDisabled: false });\n loadBalancer.instances = chain(activeServerGroups).map('instances').flatten().value() as IInstance[];\n return this.$q.resolve(loadBalancer);\n }\n\n public convertLoadBalancerForEditing(\n loadBalancer: IAppengineLoadBalancer,\n application: Application,\n ): PromiseLike<IAppengineLoadBalancer> {\n return application\n .getDataSource('loadBalancers')\n .ready()\n .then(() => {\n const upToDateLoadBalancer = application\n .getDataSource('loadBalancers')\n .data.find((candidate: ILoadBalancer) => {\n return (\n candidate.name === loadBalancer.name &&\n (candidate.account === loadBalancer.account || candidate.account === loadBalancer.credentials)\n );\n });\n\n if (upToDateLoadBalancer) {\n loadBalancer.serverGroups = cloneDeep(upToDateLoadBalancer.serverGroups);\n }\n return loadBalancer;\n });\n }\n\n public convertLoadBalancerToUpsertDescription(\n loadBalancer: IAppengineLoadBalancer,\n ): AppengineLoadBalancerUpsertDescription {\n return new AppengineLoadBalancerUpsertDescription(loadBalancer);\n }\n\n private buildInstanceCounts(serverGroups: IServerGroup[]): IInstanceCounts {\n const instanceCounts: IInstanceCounts = chain(serverGroups)\n .map('instances')\n .flatten()\n .reduce(\n (acc: IInstanceCounts, instance: any) => {\n if (has(instance, 'health.state')) {\n acc[camelCase(instance.health.state)]++;\n }\n return acc;\n },\n { up: 0, down: 0, outOfService: 0, succeeded: 0, failed: 0, starting: 0, unknown: 0 },\n )\n .value();\n\n instanceCounts.outOfService += chain(serverGroups).map('detachedInstances').flatten().value().length;\n return instanceCounts;\n }\n\n private transformInstance(instance: any, loadBalancer: ILoadBalancer) {\n instance.provider = loadBalancer.type;\n instance.account = loadBalancer.account;\n instance.region = loadBalancer.region;\n instance.loadBalancers = [loadBalancer.name];\n const health = instance.health || {};\n instance.healthState = get(instance, 'health.state') || 'OutOfService';\n instance.health = [health];\n\n return instance as IInstance;\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_TRANSFORMER = 'spinnaker.appengine.loadBalancer.transformer.service';\n\nmodule(APPENGINE_LOAD_BALANCER_TRANSFORMER, []).service(\n 'appengineLoadBalancerTransformer',\n AppengineLoadBalancerTransformer,\n);\n","function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","import type { StateService } from '@uirouter/angularjs';\nimport type { IController } from 'angular';\nimport { module } from 'angular';\nimport type { IModalServiceInstance } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { Application } from '@spinnaker/core';\nimport { LoadBalancerWriter, TaskMonitor } from '@spinnaker/core';\n\nimport type { AppengineLoadBalancerTransformer, IAppengineTrafficSplitDescription } from '../../transformer';\nimport { AppengineLoadBalancerUpsertDescription } from '../../transformer';\n\nimport './wizard.less';\n\nclass AppengineLoadBalancerWizardController implements IController {\n public state = { loading: true };\n public loadBalancer: AppengineLoadBalancerUpsertDescription;\n public heading: string;\n public submitButtonLabel: string;\n public taskMonitor: TaskMonitor;\n\n public static $inject = [\n '$scope',\n '$state',\n '$uibModalInstance',\n 'application',\n 'loadBalancer',\n 'isNew',\n 'forPipelineConfig',\n 'appengineLoadBalancerTransformer',\n 'wizardSubFormValidation',\n ];\n constructor(\n public $scope: ng.IScope,\n private $state: StateService,\n private $uibModalInstance: IModalServiceInstance,\n private application: Application,\n loadBalancer: AppengineLoadBalancerUpsertDescription,\n public isNew: boolean,\n private forPipelineConfig: boolean,\n private appengineLoadBalancerTransformer: AppengineLoadBalancerTransformer,\n private wizardSubFormValidation: any,\n ) {\n this.submitButtonLabel = this.forPipelineConfig ? 'Done' : 'Update';\n\n if (this.isNew) {\n this.heading = 'Create New Load Balancer';\n } else {\n this.heading = `Edit ${[\n loadBalancer.name,\n loadBalancer.region,\n loadBalancer.account || loadBalancer.credentials,\n ].join(':')}`;\n this.appengineLoadBalancerTransformer\n .convertLoadBalancerForEditing(loadBalancer, application)\n .then((convertedLoadBalancer) => {\n this.loadBalancer = this.appengineLoadBalancerTransformer.convertLoadBalancerToUpsertDescription(\n convertedLoadBalancer,\n );\n if (loadBalancer.split && !this.loadBalancer.splitDescription) {\n this.loadBalancer.splitDescription = AppengineLoadBalancerUpsertDescription.convertTrafficSplitToTrafficSplitDescription(\n loadBalancer.split,\n );\n } else {\n this.loadBalancer.splitDescription = loadBalancer.splitDescription;\n }\n this.loadBalancer.mapAllocationsToPercentages();\n this.setTaskMonitor();\n this.initializeFormValidation();\n this.state.loading = false;\n });\n }\n }\n\n public submit(): any {\n const description = cloneDeep(this.loadBalancer);\n description.mapAllocationsToDecimals();\n delete description.serverGroups;\n\n if (this.forPipelineConfig) {\n return this.$uibModalInstance.close(description);\n } else {\n return this.taskMonitor.submit(() => {\n return LoadBalancerWriter.upsertLoadBalancer(description, this.application, 'Update');\n });\n }\n }\n\n public cancel(): void {\n this.$uibModalInstance.dismiss();\n }\n\n public showSubmitButton(): boolean {\n return this.wizardSubFormValidation.subFormsAreValid();\n }\n\n private setTaskMonitor(): void {\n this.taskMonitor = new TaskMonitor({\n application: this.application,\n title: 'Updating your load balancer',\n modalInstance: this.$uibModalInstance,\n onTaskComplete: () => this.onTaskComplete(),\n });\n }\n\n private initializeFormValidation(): void {\n this.wizardSubFormValidation\n .config({ form: 'form', scope: this.$scope })\n .register({\n page: 'basic-settings',\n subForm: 'basicSettingsForm',\n validators: [\n {\n watchString: 'ctrl.loadBalancer.splitDescription',\n validator: (splitDescription: IAppengineTrafficSplitDescription): boolean => {\n return (\n splitDescription.allocationDescriptions.reduce(\n (sum, description) => sum + description.allocation,\n 0,\n ) === 100\n );\n },\n watchDeep: true,\n },\n ],\n })\n .register({ page: 'advanced-settings', subForm: 'advancedSettingsForm' });\n }\n\n private onTaskComplete(): void {\n this.application.getDataSource('loadBalancers').refresh();\n this.application.getDataSource('loadBalancers').onNextRefresh(this.$scope, () => this.onApplicationRefresh());\n }\n\n private onApplicationRefresh(): void {\n // If the user has already closed the modal, do not navigate to the new details view\n if ((this.$scope as any).$$destroyed) {\n // $$destroyed is not in the ng.IScope interface\n return;\n }\n\n this.$uibModalInstance.dismiss();\n const newStateParams = {\n name: this.loadBalancer.name,\n accountId: this.loadBalancer.credentials,\n region: this.loadBalancer.region,\n provider: 'appengine',\n };\n\n if (!this.$state.includes('**.loadBalancerDetails')) {\n this.$state.go('.loadBalancerDetails', newStateParams);\n } else {\n this.$state.go('^.loadBalancerDetails', newStateParams);\n }\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_WIZARD_CTRL = 'spinnaker.appengine.loadBalancer.wizard.controller';\n\nmodule(APPENGINE_LOAD_BALANCER_WIZARD_CTRL, []).controller(\n 'appengineLoadBalancerWizardCtrl',\n AppengineLoadBalancerWizardController,\n);\n","import type { StateService } from '@uirouter/angularjs';\nimport type { IController, IScope } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { Application, ILoadBalancer, ILoadBalancerDeleteCommand } from '@spinnaker/core';\nimport { ConfirmationModalService, LoadBalancerWriter } from '@spinnaker/core';\nimport type { IAppengineLoadBalancer } from '../../domain';\n\ninterface ILoadBalancerFromStateParams {\n accountId: string;\n region: string;\n name: string;\n}\n\nclass AppengineLoadBalancerDetailsController implements IController {\n public state = { loading: true };\n private loadBalancerFromParams: ILoadBalancerFromStateParams;\n public loadBalancer: IAppengineLoadBalancer;\n public dispatchRules: string[] = [];\n\n public static $inject = ['$uibModal', '$state', '$scope', 'loadBalancer', 'app'];\n constructor(\n private $uibModal: IModalService,\n private $state: StateService,\n private $scope: IScope,\n loadBalancer: ILoadBalancerFromStateParams,\n private app: Application,\n ) {\n this.loadBalancerFromParams = loadBalancer;\n this.app\n .getDataSource('loadBalancers')\n .ready()\n .then(() => this.extractLoadBalancer());\n }\n\n public editLoadBalancer(): void {\n this.$uibModal.open({\n templateUrl: require('../configure/wizard/wizard.html'),\n controller: 'appengineLoadBalancerWizardCtrl as ctrl',\n size: 'lg',\n resolve: {\n application: () => this.app,\n loadBalancer: () => cloneDeep(this.loadBalancer),\n isNew: () => false,\n forPipelineConfig: () => false,\n },\n });\n }\n\n public deleteLoadBalancer(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Deleting ' + this.loadBalancer.name,\n };\n\n const submitMethod = () => {\n const loadBalancer: ILoadBalancerDeleteCommand = {\n cloudProvider: this.loadBalancer.cloudProvider,\n loadBalancerName: this.loadBalancer.name,\n credentials: this.loadBalancer.account,\n };\n return LoadBalancerWriter.deleteLoadBalancer(loadBalancer, this.app);\n };\n\n ConfirmationModalService.confirm({\n header: 'Really delete ' + this.loadBalancer.name + '?',\n buttonText: 'Delete ' + this.loadBalancer.name,\n body: this.getConfirmationModalBodyHtml(),\n account: this.loadBalancer.account,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n });\n }\n\n public canDeleteLoadBalancer(): boolean {\n return this.loadBalancer.name !== 'default';\n }\n\n private extractLoadBalancer(): void {\n this.loadBalancer = this.app.getDataSource('loadBalancers').data.find((test: ILoadBalancer) => {\n return test.name === this.loadBalancerFromParams.name && test.account === this.loadBalancerFromParams.accountId;\n }) as IAppengineLoadBalancer;\n\n if (this.loadBalancer) {\n this.state.loading = false;\n this.buildDispatchRules();\n this.app.getDataSource('loadBalancers').onRefresh(this.$scope, () => this.extractLoadBalancer());\n } else {\n this.autoClose();\n }\n }\n\n private buildDispatchRules(): void {\n this.dispatchRules = [];\n if (this.loadBalancer && this.loadBalancer.dispatchRules) {\n this.loadBalancer.dispatchRules.forEach((rule) => {\n if (rule.service === this.loadBalancer.name) {\n this.dispatchRules.push(rule.domain + rule.path);\n }\n });\n }\n }\n\n private getConfirmationModalBodyHtml(): string {\n const serverGroupNames = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);\n const hasAny = serverGroupNames ? serverGroupNames.length > 0 : false;\n const hasMoreThanOne = serverGroupNames ? serverGroupNames.length > 1 : false;\n\n // HTML accepted by the confirmationModalService is static (i.e., not managed by angular).\n if (hasAny) {\n if (hasMoreThanOne) {\n const listOfServerGroupNames = serverGroupNames.map((name) => `<li>${name}</li>`).join('');\n return `<div class=\"alert alert-warning\">\n <p>\n Deleting <b>${this.loadBalancer.name}</b> will destroy the following server groups:\n <ul>\n ${listOfServerGroupNames}\n </ul>\n </p>\n </div>\n `;\n } else {\n return `<div class=\"alert alert-warning\">\n <p>\n Deleting <b>${this.loadBalancer.name}</b> will destroy <b>${serverGroupNames[0]}</b>.\n </p>\n </div>\n `;\n }\n } else {\n return null;\n }\n }\n\n private autoClose(): void {\n if (this.$scope.$$destroyed) {\n return;\n } else {\n this.$state.params.allowModalToStayOpen = true;\n this.$state.go('^', null, { location: 'replace' });\n }\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_DETAILS_CTRL = 'spinnaker.appengine.loadBalancerDetails.controller';\nmodule(APPENGINE_LOAD_BALANCER_DETAILS_CTRL, []).controller(\n 'appengineLoadBalancerDetailsCtrl',\n AppengineLoadBalancerDetailsController,\n);\n","import { module } from 'angular';\n\nimport { APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS } from './configure/wizard/advancedSettings.component';\nimport { APPENGINE_ALLOCATION_CONFIGURATION_ROW } from './configure/wizard/allocationConfigurationRow.component';\nimport { APPENGINE_LOAD_BALANCER_BASIC_SETTINGS } from './configure/wizard/basicSettings.component';\nimport { APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW } from './configure/wizard/stageAllocationConfigurationRow.component';\nimport { APPENGINE_LOAD_BALANCER_WIZARD_CTRL } from './configure/wizard/wizard.controller';\nimport { APPENGINE_LOAD_BALANCER_DETAILS_CTRL } from './details/details.controller';\nimport { APPENGINE_LOAD_BALANCER_TRANSFORMER } from './transformer';\n\nexport const APPENGINE_LOAD_BALANCER_MODULE = 'spinnaker.appengine.loadBalancer.module';\n\nmodule(APPENGINE_LOAD_BALANCER_MODULE, [\n APPENGINE_ALLOCATION_CONFIGURATION_ROW,\n APPENGINE_LOAD_BALANCER_DETAILS_CTRL,\n APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS,\n APPENGINE_LOAD_BALANCER_BASIC_SETTINGS,\n APPENGINE_LOAD_BALANCER_TRANSFORMER,\n APPENGINE_LOAD_BALANCER_WIZARD_CTRL,\n APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW,\n]);\n","export class AppengineHealth {\n public static PLATFORM = 'App Engine Service';\n}\n","import type { IController } from 'angular';\n\nimport { AccountService, StageConstants } from '@spinnaker/core';\nimport { AppengineHealth } from '../../common/appengineHealth';\nimport type { IAppengineAccount, IAppengineStageScope } from '../../domain';\n\nexport class AppengineStageCtrl implements IController {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n $scope.platformHealth = AppengineHealth.PLATFORM;\n }\n\n public setStageRegion(): void {\n const selected = this.$scope.accounts.find((account) => account.name === this.$scope.stage.credentials);\n if (selected && selected.name) {\n AccountService.getAccountDetails(selected.name).then((accountDetails: IAppengineAccount) => {\n this.$scope.stage.region = accountDetails.region;\n });\n }\n }\n\n protected setStageCloudProvider(): void {\n this.$scope.stage.cloudProvider = 'appengine';\n }\n\n protected setAccounts(): PromiseLike<void> {\n return AccountService.listAccounts('appengine').then((accounts: IAppengineAccount[]) => {\n this.$scope.accounts = accounts;\n });\n }\n\n protected setTargets(): void {\n this.$scope.targets = StageConstants.TARGET_LIST;\n\n if (!this.$scope.stage.target) {\n this.$scope.stage.target = this.$scope.targets[0].val;\n }\n }\n\n protected setStageCredentials(): void {\n if (!this.$scope.stage.credentials && this.$scope.application.defaultCredentials.appengine) {\n this.$scope.stage.credentials = this.$scope.application.defaultCredentials.appengine;\n }\n }\n}\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineDestroyAsgStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n }\n}\n\nexport const APPENGINE_DESTROY_ASG_STAGE = 'spinnaker.appengine.pipeline.stage.destroyAsgStage';\n\nmodule(APPENGINE_DESTROY_ASG_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n provides: 'destroyServerGroup',\n key: 'destroyServerGroup',\n cloudProvider: 'appengine',\n templateUrl: require('./destroyAsgStage.html'),\n executionStepLabelUrl: require('./destroyAsgStepLabel.html'),\n validators: [\n {\n type: 'targetImpedance',\n message:\n 'This pipeline will attempt to destroy a server group without deploying a new version into the same cluster.',\n },\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineDestroyAsgStageCtrl', AppengineDestroyAsgStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineDisableAsgStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_DISABLE_ASG_STAGE = 'spinnaker.appengine.pipeline.stage.disableAsgStage';\n\nmodule(APPENGINE_DISABLE_ASG_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n provides: 'disableServerGroup',\n key: 'disableServerGroup',\n cloudProvider: 'appengine',\n templateUrl: require('./disableAsgStage.html'),\n executionStepLabelUrl: require('./disableAsgStepLabel.html'),\n validators: [\n {\n type: 'targetImpedance',\n message:\n 'This pipeline will attempt to disable a server group without deploying a new version into the same cluster.',\n },\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineDisableAsgStageCtrl', AppengineDisableAsgStageCtrl);\n","import type { IController } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService, IModalServiceInstance } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { Application, ILoadBalancer } from '@spinnaker/core';\nimport { CloudProviderRegistry } from '@spinnaker/core';\n\nclass AppengineLoadBalancerChoiceModalCtrl implements IController {\n public state = { loading: true };\n public loadBalancers: ILoadBalancer[];\n public selectedLoadBalancer: ILoadBalancer;\n\n public static $inject = ['$uibModal', '$uibModalInstance', 'application'];\n constructor(\n private $uibModal: IModalService,\n private $uibModalInstance: IModalServiceInstance,\n private application: Application,\n ) {\n this.initialize();\n }\n\n public submit(): void {\n const config = CloudProviderRegistry.getValue('appengine', 'loadBalancer');\n const updatedLoadBalancerPromise = this.$uibModal.open({\n templateUrl: config.createLoadBalancerTemplateUrl,\n controller: `${config.createLoadBalancerController} as ctrl`,\n size: 'lg',\n resolve: {\n application: () => this.application,\n loadBalancer: () => cloneDeep(this.selectedLoadBalancer),\n isNew: () => false,\n forPipelineConfig: () => true,\n },\n }).result;\n\n this.$uibModalInstance.close(updatedLoadBalancerPromise);\n }\n\n public cancel(): void {\n this.$uibModalInstance.dismiss();\n }\n\n private initialize(): void {\n this.application\n .getDataSource('loadBalancers')\n .ready()\n .then(() => {\n this.loadBalancers = (this.application.loadBalancers.data as ILoadBalancer[]).filter(\n (candidate) => candidate.cloudProvider === 'appengine',\n );\n\n if (this.loadBalancers.length) {\n this.selectedLoadBalancer = this.loadBalancers[0];\n }\n this.state.loading = false;\n });\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL = 'spinnaker.appengine.loadBalancerChoiceModal.controller';\nmodule(APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL, []).controller(\n 'appengineLoadBalancerChoiceModelCtrl',\n AppengineLoadBalancerChoiceModalCtrl,\n);\n","import type { IController } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { ILoadBalancer } from '@spinnaker/core';\nimport { CloudProviderRegistry, Registry } from '@spinnaker/core';\n\nimport { APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL } from './loadBalancerChoice.modal.controller';\n\nclass AppengineEditLoadBalancerStageCtrl implements IController {\n public static $inject = ['$scope', '$uibModal'];\n constructor(public $scope: any, private $uibModal: IModalService) {\n $scope.stage.loadBalancers = $scope.stage.loadBalancers || [];\n $scope.stage.cloudProvider = 'appengine';\n }\n\n public addLoadBalancer(): void {\n this.$uibModal\n .open({\n templateUrl: require('./loadBalancerChoice.modal.html'),\n controller: `appengineLoadBalancerChoiceModelCtrl as ctrl`,\n resolve: {\n application: () => this.$scope.application,\n },\n })\n .result.then((newLoadBalancer: ILoadBalancer) => {\n this.$scope.stage.loadBalancers.push(newLoadBalancer);\n })\n .catch(() => {});\n }\n\n public editLoadBalancer(index: number) {\n const config = CloudProviderRegistry.getValue('appengine', 'loadBalancer');\n this.$uibModal\n .open({\n templateUrl: config.createLoadBalancerTemplateUrl,\n controller: `${config.createLoadBalancerController} as ctrl`,\n size: 'lg',\n resolve: {\n application: () => this.$scope.application,\n loadBalancer: () => cloneDeep(this.$scope.stage.loadBalancers[index]),\n isNew: () => false,\n forPipelineConfig: () => true,\n },\n })\n .result.then((updatedLoadBalancer: ILoadBalancer) => {\n this.$scope.stage.loadBalancers[index] = updatedLoadBalancer;\n })\n .catch(() => {});\n }\n\n public removeLoadBalancer(index: number): void {\n this.$scope.stage.loadBalancers.splice(index, 1);\n }\n}\n\nexport const APPENGINE_EDIT_LOAD_BALANCER_STAGE = 'spinnaker.appengine.pipeline.stage.editLoadBalancerStage';\nmodule(APPENGINE_EDIT_LOAD_BALANCER_STAGE, [APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL])\n .config(() => {\n Registry.pipeline.registerStage({\n label: 'Edit Load Balancer',\n description: 'Edits a load balancer',\n key: 'upsertAppEngineLoadBalancers',\n cloudProvider: 'appengine',\n templateUrl: require('./editLoadBalancerStage.html'),\n executionDetailsUrl: require('./editLoadBalancerExecutionDetails.html'),\n executionConfigSections: ['editLoadBalancerConfig', 'taskStatus'],\n controller: 'appengineEditLoadBalancerStageCtrl',\n controllerAs: 'editLoadBalancerStageCtrl',\n validators: [],\n });\n })\n .controller('appengineEditLoadBalancerStageCtrl', AppengineEditLoadBalancerStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineEnableAsgStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_ENABLE_ASG_STAGE = 'spinnaker.appengine.pipeline.stage.enableAsgStage';\n\nmodule(APPENGINE_ENABLE_ASG_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n provides: 'enableServerGroup',\n key: 'enableServerGroup',\n cloudProvider: 'appengine',\n templateUrl: require('./enableAsgStage.html'),\n executionStepLabelUrl: require('./enableAsgStepLabel.html'),\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineEnableAsgStageCtrl', AppengineEnableAsgStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport type { IAppengineStage, IAppengineStageScope } from '../../../domain/index';\n\ninterface IAppengineShrinkClusterStage extends IAppengineStage {\n shrinkToSize: number;\n allowDeleteActive: boolean;\n retainLargerOverNewer: string | boolean;\n}\n\nclass AppengineShrinkClusterStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(public $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n super.setStageCloudProvider();\n super.setStageCredentials();\n\n const stage = $scope.stage as IAppengineShrinkClusterStage;\n if (stage.shrinkToSize === undefined) {\n stage.shrinkToSize = 1;\n }\n\n if (stage.allowDeleteActive === undefined) {\n stage.allowDeleteActive = false;\n }\n\n if (stage.retainLargerOverNewer === undefined) {\n stage.retainLargerOverNewer = 'false';\n }\n\n stage.retainLargerOverNewer = stage.retainLargerOverNewer.toString();\n }\n\n public pluralize(str: string, val: number): string {\n return val === 1 ? str : str + 's';\n }\n}\n\nexport const APPENGINE_SHRINK_CLUSTER_STAGE = 'spinnaker.appengine.pipeline.stage.shrinkClusterStage';\n\nmodule(APPENGINE_SHRINK_CLUSTER_STAGE, [])\n .config(function () {\n Registry.pipeline.registerStage({\n provides: 'shrinkCluster',\n key: 'shrinkCluster',\n cloudProvider: 'appengine',\n templateUrl: require('./shrinkClusterStage.html'),\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'shrinkToSize', fieldLabel: 'shrink to [X] Server Groups' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineShrinkClusterStageCtrl', AppengineShrinkClusterStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineStartServerGroupStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(public $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_START_SERVER_GROUP_STAGE = 'spinnaker.appengine.pipeline.stage.startServerGroupStage';\n\nmodule(APPENGINE_START_SERVER_GROUP_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n label: 'Start Server Group',\n description: 'Starts a server group.',\n key: 'startAppEngineServerGroup',\n templateUrl: require('./startServerGroupStage.html'),\n executionDetailsUrl: require('./startServerGroupExecutionDetails.html'),\n executionConfigSections: ['startServerGroupConfig', 'taskStatus'],\n executionStepLabelUrl: require('./startServerGroupStepLabel.html'),\n controller: 'appengineStartServerGroupStageCtrl',\n controllerAs: 'startServerGroupStageCtrl',\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n cloudProvider: 'appengine',\n });\n })\n .controller('appengineStartServerGroupStageCtrl', AppengineStartServerGroupStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain/index';\n\nclass AppengineStopServerGroupStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(public $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_STOP_SERVER_GROUP_STAGE = 'spinnaker.appengine.pipeline.stage.stopServerGroupStage';\n\nmodule(APPENGINE_STOP_SERVER_GROUP_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n label: 'Stop Server Group',\n description: 'Stops a server group.',\n key: 'stopAppEngineServerGroup',\n templateUrl: require('./stopServerGroupStage.html'),\n executionDetailsUrl: require('./stopServerGroupExecutionDetails.html'),\n executionConfigSections: ['stopServerGroupConfig', 'taskStatus'],\n executionStepLabelUrl: require('./stopServerGroupStepLabel.html'),\n controller: 'appengineStopServerGroupStageCtrl',\n controllerAs: 'stopServerGroupStageCtrl',\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n cloudProvider: 'appengine',\n });\n })\n .controller('appengineStopServerGroupStageCtrl', AppengineStopServerGroupStageCtrl);\n","import { module } from 'angular';\n\nimport { APPENGINE_DESTROY_ASG_STAGE } from './stages/destroyAsg/appengineDestroyAsgStage';\nimport { APPENGINE_DISABLE_ASG_STAGE } from './stages/disableAsg/appengineDisableAsgStage';\nimport { APPENGINE_EDIT_LOAD_BALANCER_STAGE } from './stages/editLoadBalancer/appengineEditLoadBalancerStage';\nimport { APPENGINE_ENABLE_ASG_STAGE } from './stages/enableAsg/appengineEnableAsgStage';\nimport { APPENGINE_SHRINK_CLUSTER_STAGE } from './stages/shrinkCluster/appengineShrinkClusterStage';\nimport { APPENGINE_START_SERVER_GROUP_STAGE } from './stages/startServerGroup/appengineStartServerGroupStage';\nimport { APPENGINE_STOP_SERVER_GROUP_STAGE } from './stages/stopServerGroup/appengineStopServerGroupStage';\n\nexport const APPENGINE_PIPELINE_MODULE = 'spinnaker.appengine.pipeline.module';\nmodule(APPENGINE_PIPELINE_MODULE, [\n APPENGINE_DESTROY_ASG_STAGE,\n APPENGINE_DISABLE_ASG_STAGE,\n APPENGINE_EDIT_LOAD_BALANCER_STAGE,\n APPENGINE_ENABLE_ASG_STAGE,\n APPENGINE_SHRINK_CLUSTER_STAGE,\n APPENGINE_START_SERVER_GROUP_STAGE,\n APPENGINE_STOP_SERVER_GROUP_STAGE,\n]);\n","import type { FormikProps } from 'formik';\nimport { get } from 'lodash';\nimport React from 'react';\nimport { from as observableFrom, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nimport type { Application, IAccount, IServerGroup, IServerGroupFilter, IStage } from '@spinnaker/core';\nimport { AppListExtractor, FormikFormField, ReactSelectInput } from '@spinnaker/core';\n\nexport interface IFormikAccountRegionSelectorProps {\n accounts: IAccount[];\n application: Application;\n cloudProvider: string;\n componentName?: string;\n credentialsField?: string;\n formik: FormikProps<IStage>;\n}\n\nexport interface IFormikAccountRegionSelectorState {\n availableRegions: string[];\n cloudProvider: string;\n componentName: string;\n credentialsField: string;\n}\n\nexport class FormikAccountRegionSelector extends React.Component<\n IFormikAccountRegionSelectorProps,\n IFormikAccountRegionSelectorState\n> {\n private destroy$ = new Subject();\n\n constructor(props: IFormikAccountRegionSelectorProps) {\n super(props);\n const credentialsField = props.credentialsField || 'credentials';\n this.state = {\n availableRegions: [],\n cloudProvider: props.cloudProvider,\n componentName: props.componentName || '',\n credentialsField,\n };\n }\n\n public componentDidMount(): void {\n const { componentName, formik } = this.props;\n const { credentialsField } = this.state;\n const credentials = get(\n formik.values,\n componentName ? `${componentName}.${credentialsField}` : `${credentialsField}`,\n undefined,\n );\n this.setRegionList(credentials);\n }\n\n public componentWillUnmount(): void {\n this.destroy$.next();\n }\n\n private setRegionList = (credentials: string): void => {\n const { application } = this.props;\n const accountFilter: IServerGroupFilter = (serverGroup: IServerGroup) =>\n serverGroup ? serverGroup.account === credentials : true;\n observableFrom(application.ready())\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n const availableRegions = AppListExtractor.getRegions([application], accountFilter);\n availableRegions.sort();\n this.setState({ availableRegions });\n });\n };\n\n public accountChanged = (credentials: string): void => {\n this.setRegionList(credentials);\n };\n\n public render() {\n const { accounts } = this.props;\n const { credentialsField, availableRegions, componentName } = this.state;\n return (\n <div className=\"col-md-9\">\n <div className=\"sp-margin-m-bottom\">\n <FormikFormField\n name={componentName ? `${componentName}.${credentialsField}` : `${credentialsField}`}\n label=\"Account\"\n input={(props) => (\n <ReactSelectInput\n {...props}\n stringOptions={accounts && accounts.map((acc: IAccount) => acc.name)}\n clearable={false}\n />\n )}\n onChange={this.accountChanged}\n required={true}\n />\n </div>\n\n <div className=\"sp-margin-m-bottom\">\n <FormikFormField\n name={componentName ? `${componentName}.region` : 'region'}\n label=\"Region\"\n input={(props) => <ReactSelectInput {...props} stringOptions={availableRegions} clearable={false} />}\n required={true}\n />\n </div>\n </div>\n );\n }\n}\n","import React from 'react';\nimport { from as observableFrom, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nimport type { IAccount, IArtifact, IExpectedArtifact, IFormikStageConfigInjectedProps } from '@spinnaker/core';\nimport {\n AccountService,\n ArtifactTypePatterns,\n excludeAllTypesExcept,\n StageArtifactSelectorDelegate,\n} from '@spinnaker/core';\nimport { FormikAccountRegionSelector } from '../../../common/FormikAccountRegionSelector';\n\nexport interface IAppEngineDeployConfigSettingsState {\n accounts: IAccount[];\n}\n\nexport class DeployAppengineConfigForm extends React.Component<\n IFormikStageConfigInjectedProps,\n IAppEngineDeployConfigSettingsState\n> {\n private static readonly excludedArtifactTypes = excludeAllTypesExcept(\n ArtifactTypePatterns.BITBUCKET_FILE,\n ArtifactTypePatterns.CUSTOM_OBJECT,\n ArtifactTypePatterns.EMBEDDED_BASE64,\n ArtifactTypePatterns.GCS_OBJECT,\n ArtifactTypePatterns.GITHUB_FILE,\n ArtifactTypePatterns.GITLAB_FILE,\n ArtifactTypePatterns.S3_OBJECT,\n ArtifactTypePatterns.HTTP_FILE,\n ArtifactTypePatterns.ORACLE_OBJECT,\n );\n\n private destroy$ = new Subject();\n public state: IAppEngineDeployConfigSettingsState = {\n accounts: [],\n };\n\n public componentDidMount() {\n observableFrom(AccountService.listAccounts('appengine'))\n .pipe(takeUntil(this.destroy$))\n .subscribe((accounts) => this.setState({ accounts }));\n }\n\n private onTemplateArtifactEdited = (artifact: IArtifact, name: string) => {\n this.props.formik.setFieldValue(`${name}.id`, null);\n this.props.formik.setFieldValue(`${name}.artifact`, artifact);\n this.props.formik.setFieldValue(`${name}.account`, artifact.artifactAccount);\n };\n\n private onTemplateArtifactSelected = (id: string, name: string) => {\n this.props.formik.setFieldValue(`${name}.id`, id);\n this.props.formik.setFieldValue(`${name}.artifact`, null);\n };\n\n private removeInputArtifact = (name: string) => {\n this.props.formik.setFieldValue(name, null);\n };\n\n private getInputArtifact = (stage: any, name: string) => {\n if (!stage[name]) {\n return {\n account: '',\n id: '',\n };\n } else {\n return stage[name];\n }\n };\n\n public render() {\n const stage = this.props.formik.values;\n const accounts = this.state.accounts;\n return (\n <div>\n <div className=\"col-md-offset-0 col-md-9\">\n <h4>Basic Settings</h4>\n </div>\n <div>\n <FormikAccountRegionSelector\n componentName={''}\n accounts={accounts}\n application={this.props.application}\n cloudProvider={'appengine'}\n credentialsField={'account'}\n formik={this.props.formik}\n />\n </div>\n <div className=\"col-md-offset-0 col-md-9\">\n <h4>Configuration Settings</h4>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'cronArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'cronArtifact').id}\n label=\"Cron Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'cronArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'cronArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('cronArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'dispatchArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'dispatchArtifact').id}\n label=\"Dispatch Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'dispatchArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'dispatchArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('dispatchArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'indexArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'indexArtifact').id}\n label=\"Index Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'indexArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'indexArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('indexArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'queueArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'queueArtifact').id}\n label=\"Queue Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'queueArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'queueArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('queueArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n }\n}\n","import type { FormikErrors } from 'formik';\nimport { cloneDeep } from 'lodash';\nimport React from 'react';\n\nimport type { IStage, IStageConfigProps } from '@spinnaker/core';\nimport { FormikStageConfig, FormValidator } from '@spinnaker/core';\n\nimport { DeployAppengineConfigForm } from './DeployAppengineConfigForm';\n\nexport function DeployAppengineConfigurationConfig({ application, pipeline, stage, updateStage }: IStageConfigProps) {\n const stageWithDefaults = React.useMemo(() => {\n return {\n ...cloneDeep(stage),\n };\n }, []);\n\n return (\n <FormikStageConfig\n application={application}\n onChange={updateStage}\n pipeline={pipeline}\n stage={stageWithDefaults}\n validate={validateDeployAppengineConfigurationStage}\n render={(props) => <DeployAppengineConfigForm {...props} />}\n />\n );\n}\n\nexport function validateDeployAppengineConfigurationStage(stage: IStage): FormikErrors<IStage> {\n const formValidator = new FormValidator(stage);\n formValidator.field('account').required();\n formValidator.field('region').required();\n return formValidator.validateForm();\n}\n","import { ExecutionArtifactTab, ExecutionDetailsTasks, Registry } from '@spinnaker/core';\n\nimport {\n DeployAppengineConfigurationConfig,\n validateDeployAppengineConfigurationStage,\n} from './DeployAppengineConfigurationConfig';\n\nexport const DEPLOY_APPENGINE_CONFIG_STAGE_KEY = 'deployAppEngineConfiguration';\n\nRegistry.pipeline.registerStage({\n label: 'Deploy App Engine Configuration',\n description: 'Deploy index, dispatch, cron, and queue configuration to App Engine.',\n key: DEPLOY_APPENGINE_CONFIG_STAGE_KEY,\n component: DeployAppengineConfigurationConfig,\n producesArtifacts: false,\n cloudProvider: 'appengine',\n executionDetailsSections: [ExecutionDetailsTasks, ExecutionArtifactTab],\n validateFn: validateDeployAppengineConfigurationStage,\n});\n","import type { IProviderSettings } from '@spinnaker/core';\nimport { SETTINGS } from '@spinnaker/core';\n\nexport interface IAppengineProviderSettings extends IProviderSettings {\n defaults: {\n account?: string;\n };\n}\n\nexport const AppengineProviderSettings: IAppengineProviderSettings = (SETTINGS.providers\n .appengine as IAppengineProviderSettings) || { defaults: {} };\nif (AppengineProviderSettings) {\n AppengineProviderSettings.resetToOriginal = SETTINGS.resetProvider('appengine');\n}\n","import type { IQService } from 'angular';\nimport { module } from 'angular';\n\nimport type {\n Application,\n IArtifact,\n IArtifactAccountPair,\n IBuildTrigger,\n IExpectedArtifact,\n IGitTrigger,\n IPipeline,\n IStage,\n} from '@spinnaker/core';\nimport { AccountService, StorageAccountReader } from '@spinnaker/core';\nimport { AppengineProviderSettings } from '../../appengine.settings';\nimport type {\n GitCredentialType,\n IAppengineAccount,\n IAppengineGitTrigger,\n IAppengineJenkinsTrigger,\n IAppengineServerGroup,\n} from '../../domain';\n\nimport type { AppengineDeployDescription } from '../transformer';\n\nexport interface IAppengineServerGroupCommand {\n application?: string;\n stack?: string;\n freeFormDetails?: string;\n configFilepaths?: string[];\n configFiles?: string[];\n configArtifacts?: IArtifactAccountPair[];\n applicationDirectoryRoot: string;\n branch?: string;\n repositoryUrl?: string;\n credentials: string;\n region: string;\n selectedProvider: string;\n promote?: boolean;\n stopPreviousVersion?: boolean;\n suppressVersionString?: boolean;\n type?: string;\n backingData: any;\n viewState: IViewState;\n strategy?: string;\n strategyApplication?: string;\n strategyPipeline?: string;\n fromTrigger?: boolean;\n trigger?: IAppengineGitTrigger | IAppengineJenkinsTrigger;\n gitCredentialType?: GitCredentialType;\n storageAccountName?: string; // GCS only\n interestingHealthProviderNames: string[];\n fromArtifact: boolean;\n expectedArtifactId: string;\n expectedArtifact?: IArtifact;\n sourceType: string;\n containerImageUrl?: string;\n}\n\nexport enum AppengineSourceType {\n GCS = 'gcs',\n GIT = 'git',\n ARTIFACT = 'artifact',\n CONTAINER_IMAGE = 'containerImage',\n}\n\nexport interface IViewState {\n mode: string;\n submitButtonLabel: string;\n disableStrategySelection: boolean;\n stage?: IStage;\n pipeline?: IPipeline;\n}\n\nexport class AppengineServerGroupCommandBuilder {\n private static getTriggerOptions(pipeline: IPipeline): Array<IAppengineGitTrigger | IAppengineJenkinsTrigger> {\n return (pipeline.triggers || [])\n .filter((trigger) => trigger.type === 'git' || trigger.type === 'jenkins' || trigger.type === 'travis')\n .map((trigger: IGitTrigger | IBuildTrigger) => {\n if (trigger.type === 'git') {\n return {\n source: trigger.source,\n project: trigger.project,\n slug: trigger.slug,\n branch: trigger.branch,\n type: 'git',\n };\n } else {\n return { master: trigger.master, job: trigger.job, type: trigger.type };\n }\n });\n }\n\n private static getExpectedArtifacts(pipeline: IPipeline): IExpectedArtifact[] {\n return pipeline.expectedArtifacts || [];\n }\n\n public static $inject = ['$q'];\n constructor(private $q: IQService) {}\n\n public buildNewServerGroupCommand(\n app: Application,\n selectedProvider: string,\n mode = 'create',\n ): PromiseLike<IAppengineServerGroupCommand> {\n if (selectedProvider == null) {\n selectedProvider = 'appengine';\n }\n const dataToFetch = {\n accounts: AccountService.getAllAccountDetailsForProvider('appengine'),\n storageAccounts: StorageAccountReader.getStorageAccounts(),\n };\n\n const viewState: IViewState = {\n mode,\n submitButtonLabel: this.getSubmitButtonLabel(mode),\n disableStrategySelection: mode === 'create',\n };\n\n return this.$q.all(dataToFetch).then((backingData: any) => {\n const credentials = this.getCredentials(backingData.accounts);\n const region = this.getRegion(backingData.accounts, credentials);\n\n return {\n application: app.name,\n backingData,\n viewState,\n fromArtifact: false,\n credentials,\n region,\n selectedProvider,\n interestingHealthProviderNames: [],\n sourceType: AppengineSourceType.GIT,\n } as IAppengineServerGroupCommand;\n });\n }\n\n public buildServerGroupCommandFromExisting(\n app: Application,\n serverGroup: IAppengineServerGroup,\n ): PromiseLike<IAppengineServerGroupCommand> {\n return this.buildNewServerGroupCommand(app, 'appengine', 'clone').then((command) => {\n command.stack = serverGroup.stack;\n command.freeFormDetails = serverGroup.detail;\n return command;\n });\n }\n\n public buildNewServerGroupCommandForPipeline(\n _stage: IStage,\n pipeline: IPipeline,\n ): PromiseLike<{\n viewState: {\n stage: IStage;\n pipeline: IPipeline;\n };\n backingData: {\n triggerOptions: Array<IAppengineGitTrigger | IAppengineJenkinsTrigger>;\n expectedArtifacts: IExpectedArtifact[];\n };\n }> {\n // We can't copy server group configuration for App Engine, and can't build the full command here because we don't have\n // access to the application.\n return this.$q.when({\n viewState: {\n pipeline,\n stage: _stage,\n },\n backingData: {\n triggerOptions: AppengineServerGroupCommandBuilder.getTriggerOptions(pipeline),\n expectedArtifacts: AppengineServerGroupCommandBuilder.getExpectedArtifacts(pipeline),\n },\n });\n }\n\n public buildServerGroupCommandFromPipeline(\n app: Application,\n cluster: AppengineDeployDescription,\n _stage: IStage,\n pipeline: IPipeline,\n ): PromiseLike<IAppengineServerGroupCommand> {\n return this.buildNewServerGroupCommand(app, 'appengine', 'editPipeline').then(\n (command: IAppengineServerGroupCommand) => {\n command = {\n ...command,\n ...cluster,\n backingData: {\n ...command.backingData,\n triggerOptions: AppengineServerGroupCommandBuilder.getTriggerOptions(pipeline),\n expectedArtifacts: AppengineServerGroupCommandBuilder.getExpectedArtifacts(pipeline),\n },\n credentials: cluster.account || command.credentials,\n viewState: {\n ...command.viewState,\n stage: _stage,\n pipeline,\n },\n } as IAppengineServerGroupCommand;\n return command;\n },\n );\n }\n\n private getCredentials(accounts: IAppengineAccount[]): string {\n const accountNames: string[] = (accounts || []).map((account) => account.name);\n const defaultCredentials: string = AppengineProviderSettings.defaults.account;\n\n return accountNames.includes(defaultCredentials) ? defaultCredentials : accountNames[0];\n }\n\n private getRegion(accounts: IAppengineAccount[], credentials: string): string {\n const account = accounts.find((_account) => _account.name === credentials);\n return account ? account.region : null;\n }\n\n private getSubmitButtonLabel(mode: string): string {\n switch (mode) {\n case 'createPipeline':\n return 'Add';\n case 'editPipeline':\n return 'Done';\n case 'clone':\n return 'Clone';\n default:\n return 'Create';\n }\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_COMMAND_BUILDER = 'spinnaker.appengine.serverGroupCommandBuilder.service';\n\nmodule(APPENGINE_SERVER_GROUP_COMMAND_BUILDER, []).service(\n 'appengineServerGroupCommandBuilder',\n AppengineServerGroupCommandBuilder,\n);\n","import type { StateService } from '@uirouter/angularjs';\nimport type { IController, IControllerService, IScope } from 'angular';\nimport { extend, module } from 'angular';\nimport { set } from 'lodash';\n\nimport type { IArtifact, IExpectedArtifact } from '@spinnaker/core';\nimport {\n ArtifactTypePatterns,\n excludeAllTypesExcept,\n ExpectedArtifactSelectorViewController,\n NgAppEngineDeployArtifactDelegate,\n} from '@spinnaker/core';\nimport type { GitCredentialType, IAppengineAccount } from '../../../domain/index';\n\nimport type { IAppengineServerGroupCommand } from '../serverGroupCommandBuilder.service';\nimport { AppengineSourceType } from '../serverGroupCommandBuilder.service';\n\ninterface IAppengineBasicSettingsScope extends IScope {\n command: IAppengineServerGroupCommand;\n}\n\nclass AppengineServerGroupBasicSettingsCtrl implements IController {\n public static $inject = ['$scope', '$state', '$controller', '$uibModalStack'];\n\n constructor(\n public $scope: IAppengineBasicSettingsScope,\n $state: StateService,\n $controller: IControllerService,\n $uibModalStack: any,\n ) {\n extend(\n this,\n $controller('BasicSettingsMixin', {\n $scope,\n imageReader: null,\n $uibModalStack,\n $state,\n }),\n );\n\n if (!this.$scope.command.gitCredentialType) {\n this.onAccountChange();\n }\n\n this.$scope.containerArtifactDelegate = new NgAppEngineDeployArtifactDelegate($scope, [\n ArtifactTypePatterns.DOCKER_IMAGE,\n ]);\n this.$scope.containerArtifactController = new ExpectedArtifactSelectorViewController(\n this.$scope.containerArtifactDelegate,\n );\n this.$scope.gcsArtifactDelegate = new NgAppEngineDeployArtifactDelegate($scope, [ArtifactTypePatterns.GCS_OBJECT]);\n this.$scope.gcsArtifactController = new ExpectedArtifactSelectorViewController(this.$scope.gcsArtifactDelegate);\n }\n\n public isGitSource(): boolean {\n return this.$scope.command.sourceType === AppengineSourceType.GIT;\n }\n\n public isGcsSource(): boolean {\n return this.$scope.command.sourceType === AppengineSourceType.GCS;\n }\n\n public isContainerImageSource(): boolean {\n return this.$scope.command.sourceType === AppengineSourceType.CONTAINER_IMAGE;\n }\n\n public toggleResolveViaTrigger(): void {\n this.$scope.command.fromTrigger = !this.$scope.command.fromTrigger;\n delete this.$scope.command.trigger;\n delete this.$scope.command.branch;\n }\n\n public onTriggerChange(): void {\n set(this, '$scope.command.trigger.matchBranchOnRegex', undefined);\n }\n\n public onAccountChange(): void {\n const account = this.findAccountInBackingData();\n if (account) {\n this.$scope.command.gitCredentialType = this.getSupportedGitCredentialTypes()[0];\n this.$scope.command.region = account.region;\n } else {\n this.$scope.command.gitCredentialType = 'NONE';\n delete this.$scope.command.region;\n }\n }\n\n public getSupportedGitCredentialTypes(): GitCredentialType[] {\n const account = this.findAccountInBackingData();\n if (account && account.supportedGitCredentialTypes) {\n return account.supportedGitCredentialTypes;\n } else {\n return ['NONE'];\n }\n }\n\n public humanReadableGitCredentialType(type: GitCredentialType): string {\n switch (type) {\n case 'HTTPS_USERNAME_PASSWORD':\n return 'HTTPS with username and password';\n case 'HTTPS_GITHUB_OAUTH_TOKEN':\n return 'HTTPS with Github OAuth token';\n case 'SSH':\n return 'SSH';\n case 'NONE':\n return 'No credentials';\n default:\n return 'No credentials';\n }\n }\n\n public readonly excludedGcsArtifactTypes = excludeAllTypesExcept(ArtifactTypePatterns.GCS_OBJECT);\n public readonly excludedContainerArtifactTypes = excludeAllTypesExcept(ArtifactTypePatterns.DOCKER_IMAGE);\n\n public onExpectedArtifactEdited = (artifact: IArtifact): void => {\n this.$scope.$applyAsync(() => {\n this.$scope.command.expectedArtifactId = null;\n this.$scope.command.expectedArtifact = artifact;\n });\n };\n\n public onExpectedArtifactSelected = (expectedArtifact: IExpectedArtifact): void => {\n this.onChangeExpectedArtifactId(expectedArtifact.id);\n };\n\n public onChangeExpectedArtifactId = (artifactId: string): void => {\n this.$scope.$applyAsync(() => {\n this.$scope.command.expectedArtifactId = artifactId;\n this.$scope.command.expectedArtifact = null;\n });\n };\n\n public onExpectedArtifactAccountSelected = (accountName: string): void => {\n this.$scope.$applyAsync(() => {\n this.$scope.command.storageAccountName = accountName;\n });\n };\n\n private findAccountInBackingData(): IAppengineAccount {\n return this.$scope.command.backingData.accounts.find((account: IAppengineAccount) => {\n return this.$scope.command.credentials === account.name;\n });\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL = 'spinnaker.appengine.basicSettings.controller';\n\nmodule(APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL, []).controller(\n 'appengineServerGroupBasicSettingsCtrl',\n AppengineServerGroupBasicSettingsCtrl,\n);\n","import type { IController, IScope } from 'angular';\nimport { module } from 'angular';\n\nimport type { IArtifact, IArtifactAccount, IArtifactAccountPair } from '@spinnaker/core';\nimport {\n AccountService,\n ExpectedArtifactSelectorViewController,\n NgAppengineConfigArtifactDelegate,\n} from '@spinnaker/core';\n\nimport { AppengineSourceType } from '../serverGroupCommandBuilder.service';\n\nimport './serverGroupWizard.less';\n\nexport interface IAppengineConfigFileConfigurerCtrlCommand {\n configFiles: string[];\n configArtifacts: ConfigArtifact[];\n sourceType: string;\n}\n\nclass ConfigArtifact implements IArtifactAccountPair {\n public $scope: IScope;\n public controller: ExpectedArtifactSelectorViewController;\n public delegate: NgAppengineConfigArtifactDelegate;\n public id: string;\n public account: string;\n public artifact?: IArtifact;\n\n constructor($scope: IScope, pair: IArtifactAccountPair = { id: '', account: '' }) {\n const unserializable = { configurable: false, enumerable: false, writable: false };\n this.id = pair?.id;\n this.account = pair.account || pair?.artifact?.artifactAccount;\n this.artifact = pair?.artifact;\n Object.defineProperty(this, '$scope', { ...unserializable, value: $scope });\n const delegate = new NgAppengineConfigArtifactDelegate(this);\n const controller = new ExpectedArtifactSelectorViewController(delegate);\n Object.defineProperty(this, 'delegate', { ...unserializable, value: delegate });\n Object.defineProperty(this, 'controller', { ...unserializable, value: controller });\n }\n}\n\nclass AppengineConfigFileConfigurerCtrl implements IController {\n private artifactAccounts: IArtifactAccount[] = [];\n public command: IAppengineConfigFileConfigurerCtrlCommand;\n\n public static $inject = ['$scope'];\n constructor(public $scope: IScope) {}\n\n public $onInit(): void {\n if (!this.command.configFiles) {\n this.command.configFiles = [];\n }\n if (!this.command.configArtifacts) {\n this.command.configArtifacts = [];\n }\n if (!this.$scope.command) {\n this.$scope.command = this.command;\n }\n this.command.configArtifacts = this.command.configArtifacts.map((artifactAccountPair) => {\n return new ConfigArtifact(this.$scope, artifactAccountPair);\n });\n AccountService.getArtifactAccounts().then((accounts: IArtifactAccount[]) => {\n this.artifactAccounts = accounts;\n this.command.configArtifacts.forEach((a: ConfigArtifact) => {\n a.delegate.setAccounts(accounts);\n a.controller.updateAccounts(a.delegate.getSelectedExpectedArtifact());\n });\n });\n }\n\n public addConfigFile(): void {\n this.command.configFiles.push('');\n }\n\n public addConfigArtifact(): void {\n const artifact = new ConfigArtifact(this.$scope, { id: '', account: '' });\n artifact.delegate.setAccounts(this.artifactAccounts);\n artifact.controller.updateAccounts(artifact.delegate.getSelectedExpectedArtifact());\n this.command.configArtifacts.push(artifact);\n }\n\n public deleteConfigFile(index: number): void {\n this.command.configFiles.splice(index, 1);\n }\n\n public deleteConfigArtifact(index: number): void {\n this.command.configArtifacts.splice(index, 1);\n }\n\n public mapTabToSpaces(event: any) {\n if (event.which === 9) {\n event.preventDefault();\n const cursorPosition = event.target.selectionStart;\n const inputValue = event.target.value;\n event.target.value = `${inputValue.substring(0, cursorPosition)} ${inputValue.substring(cursorPosition)}`;\n event.target.selectionStart += 2;\n }\n }\n\n public isContainerImageSource(): boolean {\n return this.command.sourceType === AppengineSourceType.CONTAINER_IMAGE;\n }\n\n public updateConfigArtifacts = (configArtifacts: ConfigArtifact[]): void => {\n this.$scope.$applyAsync(() => {\n this.command.configArtifacts = configArtifacts;\n });\n };\n}\n\nconst appengineConfigFileConfigurerComponent: ng.IComponentOptions = {\n bindings: { command: '=' },\n controller: AppengineConfigFileConfigurerCtrl,\n templateUrl: require('./configFiles.component.html'),\n};\n\nexport const APPENGINE_CONFIG_FILE_CONFIGURER = 'spinnaker.appengine.configFileConfigurer.component';\nmodule(APPENGINE_CONFIG_FILE_CONFIGURER, []).component(\n 'appengineConfigFileConfigurer',\n appengineConfigFileConfigurerComponent,\n);\n","import { module } from 'angular';\n\nconst appengineDynamicBranchLabelComponent: ng.IComponentOptions = {\n bindings: { trigger: '<' },\n template: `\n <span ng-if=\"$ctrl.trigger.type === 'git'\">\n Resolved at runtime by <b>{{$ctrl.trigger.source}}</b> trigger: {{$ctrl.trigger.project}}/{{$ctrl.trigger.slug}}<span ng-if=\"$ctrl.trigger.branch\">:{{$ctrl.trigger.branch}}</span>\n </span>\n <span ng-if=\"$ctrl.trigger.type === 'jenkins'\">\n Resolved at runtime by <b>Jenkins</b> trigger: {{$ctrl.trigger.master}}/{{$ctrl.trigger.job}}\n </span>\n `,\n};\n\nexport const APPENGINE_DYNAMIC_BRANCH_LABEL = 'spinnaker.appengine.dynamicBranchLabel.component';\nmodule(APPENGINE_DYNAMIC_BRANCH_LABEL, []).component(\n 'appengineDynamicBranchLabel',\n appengineDynamicBranchLabelComponent,\n);\n","import type { IController, IScope } from 'angular';\nimport { copy, module } from 'angular';\nimport type { IModalInstanceService } from 'angular-ui-bootstrap';\nimport { get, merge } from 'lodash';\n\nimport type { Application, ServerGroupWriter } from '@spinnaker/core';\nimport { SERVER_GROUP_WRITER, TaskMonitor } from '@spinnaker/core';\nimport { AppengineHealth } from '../../../common/appengineHealth';\n\nimport { APPENGINE_CONFIG_FILE_CONFIGURER } from './configFiles.component';\nimport { APPENGINE_DYNAMIC_BRANCH_LABEL } from './dynamicBranchLabel.component';\nimport type {\n AppengineServerGroupCommandBuilder,\n IAppengineServerGroupCommand,\n} from '../serverGroupCommandBuilder.service';\n\nimport './serverGroupWizard.less';\n\nclass AppengineCloneServerGroupCtrl implements IController {\n public pages: { [pageKey: string]: string } = {\n basicSettings: require('./basicSettings.html'),\n advancedSettings: require('./advancedSettings.html'),\n };\n public state = {\n loading: true,\n };\n public taskMonitor: TaskMonitor;\n\n public static $inject = [\n '$scope',\n '$uibModalInstance',\n 'serverGroupCommand',\n 'application',\n 'serverGroupWriter',\n 'appengineServerGroupCommandBuilder',\n ];\n constructor(\n public $scope: IScope,\n private $uibModalInstance: IModalInstanceService,\n public serverGroupCommand: IAppengineServerGroupCommand,\n private application: Application,\n private serverGroupWriter: ServerGroupWriter,\n appengineServerGroupCommandBuilder: AppengineServerGroupCommandBuilder,\n ) {\n if (['create', 'clone', 'editPipeline'].includes(get<string>(serverGroupCommand, 'viewState.mode'))) {\n this.$scope.command = serverGroupCommand;\n this.state.loading = false;\n this.initialize();\n } else {\n appengineServerGroupCommandBuilder\n .buildNewServerGroupCommand(application, 'appengine', 'createPipeline')\n .then((constructedCommand) => {\n this.$scope.command = merge(constructedCommand, serverGroupCommand);\n // Re-establish references to the original pipeline and stage objects so that\n // we don't mutate copies of them when assigning expected artifacts.\n this.$scope.command.viewState.pipeline = serverGroupCommand.viewState.pipeline;\n this.$scope.command.viewState.stage = serverGroupCommand.viewState.stage;\n this.state.loading = false;\n this.initialize();\n });\n }\n }\n\n public cancel(): void {\n this.$uibModalInstance.dismiss();\n }\n\n public submit(): void {\n const mode = this.$scope.command.viewState.mode;\n if (['editPipeline', 'createPipeline'].includes(mode)) {\n return this.$uibModalInstance.close(this.$scope.command);\n } else {\n const command = copy(this.$scope.command);\n // Make sure we're sending off a create operation, because there's no such thing as clone for App Engine.\n command.viewState.mode = 'create';\n const submitMethod = () => this.serverGroupWriter.cloneServerGroup(command, this.$scope.application);\n this.taskMonitor.submit(submitMethod);\n\n return null;\n }\n }\n\n private initialize(): void {\n this.$scope.application = this.application;\n this.taskMonitor = new TaskMonitor({\n application: this.application,\n title: 'Creating your server group',\n modalInstance: this.$uibModalInstance,\n });\n this.$scope.showPlatformHealthOnlyOverride = this.application.attributes.platformHealthOnlyShowOverride;\n this.$scope.platformHealth = AppengineHealth.PLATFORM;\n if (this.application.attributes.platformHealthOnly) {\n this.$scope.command.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_CLONE_SERVER_GROUP_CTRL = 'spinnaker.appengine.cloneServerGroup.controller';\nmodule(APPENGINE_CLONE_SERVER_GROUP_CTRL, [\n SERVER_GROUP_WRITER,\n APPENGINE_DYNAMIC_BRANCH_LABEL,\n APPENGINE_CONFIG_FILE_CONFIGURER,\n]).controller('appengineCloneServerGroupCtrl', AppengineCloneServerGroupCtrl);\n","import classNames from 'classnames';\nimport React from 'react';\n\nimport type { IArtifact, IArtifactAccountPair, IExpectedArtifact, IPipeline, IStage } from '@spinnaker/core';\nimport { StageArtifactSelector } from '@spinnaker/core';\n\ninterface IConfigFileArtifactListProps {\n configArtifacts: IArtifactAccountPair[];\n pipeline: IPipeline;\n stage: IStage;\n updateConfigArtifacts: (configArtifacts: any[]) => void;\n}\n\nexport const ConfigFileArtifactList = (props: IConfigFileArtifactListProps) => {\n const addConfigArtifact = () => {\n props.updateConfigArtifacts(props.configArtifacts.concat([{ id: '', account: '' }]));\n };\n\n const deleteConfigArtifact = (index: number) => {\n const newConfigArtifacts = [...props.configArtifacts];\n newConfigArtifacts.splice(index, 1);\n props.updateConfigArtifacts(newConfigArtifacts);\n };\n\n const onExpectedArtifactEdited = (artifact: IArtifact, index: number): void => {\n const newConfigArtifacts = [...props.configArtifacts];\n newConfigArtifacts.splice(index, 1, { ...newConfigArtifacts[index], id: null, artifact });\n props.updateConfigArtifacts(newConfigArtifacts);\n };\n\n const onExpectedArtifactSelected = (expectedArtifact: IExpectedArtifact, index: number): void => {\n onChangeExpectedArtifactId(expectedArtifact.id, index);\n };\n\n const onChangeExpectedArtifactId = (id: string, index: number): void => {\n const newConfigArtifacts = [...props.configArtifacts];\n newConfigArtifacts.splice(index, 1, { ...newConfigArtifacts[index], id, artifact: null });\n props.updateConfigArtifacts(newConfigArtifacts);\n };\n\n return (\n <>\n {props.configArtifacts.map((a, i) => {\n return (\n <div\n key={a.id}\n className={classNames('artifact-configuration-section col-md-12', {\n 'last-entry': props.configArtifacts.length - 1 === i,\n })}\n >\n <div className=\"col-md-9\">\n <StageArtifactSelector\n artifact={a.artifact}\n excludedArtifactTypePatterns={[]}\n expectedArtifactId={a.artifact == null ? a.id : null}\n onArtifactEdited={(artifact: IArtifact) => {\n onExpectedArtifactEdited(artifact, i);\n }}\n onExpectedArtifactSelected={(expectedArtifact: IExpectedArtifact) => {\n onExpectedArtifactSelected(expectedArtifact, i);\n }}\n pipeline={props.pipeline}\n stage={props.stage}\n />\n </div>\n <div className=\"col-md-1\">\n <button type=\"button\" className=\"btn btn-sm btn-default\" onClick={() => deleteConfigArtifact(i)}>\n <span className=\"glyphicon glyphicon-trash\" /> Delete\n </button>\n </div>\n </div>\n );\n })}\n <div className=\"col-md-7 col-md-offset-3\">\n <button className=\"btn btn-block btn-add-trigger add-new\" onClick={() => addConfigArtifact()}>\n <span className=\"glyphicon glyphicon-plus-sign\" /> Add Config Artifact\n </button>\n </div>\n </>\n );\n};\n","import { module } from 'angular';\nimport { react2angular } from 'react2angular';\n\nimport { withErrorBoundary } from '@spinnaker/core';\n\nimport { ConfigFileArtifactList } from './ConfigFileArtifactList';\n\nexport const CONFIG_FILE_ARTIFACT_LIST = 'spinnaker.appengine.configFileArtifactList.component';\n\nmodule(CONFIG_FILE_ARTIFACT_LIST, []).component(\n 'configFileArtifactList',\n react2angular(withErrorBoundary(ConfigFileArtifactList, 'configFileArtifactList'), [\n 'configArtifacts',\n 'pipeline',\n 'stage',\n 'updateConfigArtifacts',\n ]),\n);\n","import { module } from 'angular';\n\nimport type { Application, IJob, ITask, ITaskCommand } from '@spinnaker/core';\nimport { TaskExecutor } from '@spinnaker/core';\nimport type { IAppengineServerGroup } from '../../domain/index';\n\ninterface IAppengineServerGroupWriteJob extends IJob {\n serverGroupName: string;\n region: string;\n credentials: string;\n cloudProvider: string;\n}\n\nexport class AppengineServerGroupWriter {\n public startServerGroup(serverGroup: IAppengineServerGroup, application: Application): PromiseLike<ITask> {\n const job = this.buildJob(serverGroup, application, 'startAppEngineServerGroup');\n\n const command: ITaskCommand = {\n job: [job],\n application,\n description: `Start Server Group: ${serverGroup.name}`,\n };\n\n return TaskExecutor.executeTask(command);\n }\n\n public stopServerGroup(serverGroup: IAppengineServerGroup, application: Application): PromiseLike<ITask> {\n const job = this.buildJob(serverGroup, application, 'stopAppEngineServerGroup');\n\n const command: ITaskCommand = {\n job: [job],\n application,\n description: `Stop Server Group: ${serverGroup.name}`,\n };\n\n return TaskExecutor.executeTask(command);\n }\n\n private buildJob(\n serverGroup: IAppengineServerGroup,\n application: Application,\n type: string,\n ): IAppengineServerGroupWriteJob {\n return {\n type,\n region: serverGroup.region,\n serverGroupName: serverGroup.name,\n credentials: serverGroup.account,\n cloudProvider: 'appengine',\n application: application.name,\n };\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_WRITER = 'spinnaker.appengine.serverGroup.write.service';\n\nmodule(APPENGINE_SERVER_GROUP_WRITER, []).service('appengineServerGroupWriter', AppengineServerGroupWriter);\n","import type { IController, IScope } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService } from 'angular-ui-bootstrap';\nimport { cloneDeep, map, mapValues, reduce } from 'lodash';\n\nimport type {\n Application,\n IConfirmationModalParams,\n ILoadBalancer,\n IServerGroup,\n ITaskMonitorConfig,\n ServerGroupWriter,\n} from '@spinnaker/core';\nimport {\n ConfirmationModalService,\n SERVER_GROUP_WRITER,\n ServerGroupReader,\n ServerGroupWarningMessageService,\n} from '@spinnaker/core';\n\nimport { AppengineHealth } from '../../common/appengineHealth';\nimport type { AppengineServerGroupCommandBuilder } from '../configure/serverGroupCommandBuilder.service';\nimport type { IAppengineLoadBalancer, IAppengineServerGroup } from '../../domain/index';\nimport type { AppengineServerGroupWriter } from '../writer/serverGroup.write.service';\nimport { APPENGINE_SERVER_GROUP_WRITER } from '../writer/serverGroup.write.service';\n\ninterface IPrivateScope extends IScope {\n $$destroyed: boolean;\n}\n\ninterface IServerGroupFromStateParams {\n accountId: string;\n region: string;\n name: string;\n}\n\nclass AppengineServerGroupDetailsController implements IController {\n public state = { loading: true };\n public serverGroup: IAppengineServerGroup;\n\n private static buildExpectedAllocationsTable(expectedAllocations: { [key: string]: number }): string {\n const tableRows = map(expectedAllocations, (allocation, serverGroupName) => {\n return `\n <tr>\n <td>${serverGroupName}</td>\n <td>${allocation * 100}%</td>\n </tr>`;\n }).join('');\n\n return `\n <table class=\"table table-condensed\">\n <thead>\n <tr>\n <th>Server Group</th>\n <th>Allocation</th>\n </tr>\n </thead>\n <tbody>\n ${tableRows}\n </tbody>\n </table>`;\n }\n\n public static $inject = [\n '$state',\n '$scope',\n '$uibModal',\n 'serverGroup',\n 'app',\n 'serverGroupWriter',\n 'appengineServerGroupWriter',\n 'appengineServerGroupCommandBuilder',\n ];\n constructor(\n private $state: any,\n private $scope: IPrivateScope,\n private $uibModal: IModalService,\n serverGroup: IServerGroupFromStateParams,\n public app: Application,\n private serverGroupWriter: ServerGroupWriter,\n private appengineServerGroupWriter: AppengineServerGroupWriter,\n private appengineServerGroupCommandBuilder: AppengineServerGroupCommandBuilder,\n ) {\n this.app\n .ready()\n .then(() => this.extractServerGroup(serverGroup))\n .then(() => {\n if (!this.$scope.$$destroyed) {\n this.app.getDataSource('serverGroups').onRefresh(this.$scope, () => this.extractServerGroup(serverGroup));\n }\n })\n .catch(() => this.autoClose());\n }\n\n public canDisableServerGroup(): boolean {\n if (this.serverGroup) {\n if (this.serverGroup.disabled) {\n return false;\n }\n\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);\n if (expectedAllocations) {\n return Object.keys(expectedAllocations).length > 0;\n } else {\n return false;\n }\n } else {\n return false;\n }\n }\n\n public canDestroyServerGroup(): boolean {\n if (this.serverGroup) {\n if (this.serverGroup.disabled) {\n return true;\n }\n\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);\n if (expectedAllocations) {\n return Object.keys(expectedAllocations).length > 0;\n } else {\n return false;\n }\n } else {\n return false;\n }\n }\n\n public destroyServerGroup(): void {\n const stateParams = {\n name: this.serverGroup.name,\n accountId: this.serverGroup.account,\n region: this.serverGroup.region,\n };\n\n const taskMonitor = {\n application: this.app,\n title: 'Destroying ' + this.serverGroup.name,\n onTaskComplete: () => {\n if (this.$state.includes('**.serverGroup', stateParams)) {\n this.$state.go('^');\n }\n },\n };\n\n const submitMethod = (params: any) => this.serverGroupWriter.destroyServerGroup(this.serverGroup, this.app, params);\n\n const confirmationModalParams = {\n header: 'Really destroy ' + this.serverGroup.name + '?',\n buttonText: 'Destroy ' + this.serverGroup.name,\n account: this.serverGroup.account,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n askForReason: true,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n body: this.getBodyTemplate(this.serverGroup, this.app),\n interestingHealthProviderNames: [] as string[],\n };\n\n if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {\n confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public enableServerGroup(): void {\n const taskMonitor: ITaskMonitorConfig = {\n application: this.app,\n title: 'Enabling ' + this.serverGroup.name,\n };\n\n const submitMethod = (params: any) =>\n this.serverGroupWriter.enableServerGroup(this.serverGroup, this.app, { ...params });\n\n const modalBody = `<div class=\"well well-sm\">\n <p>\n Enabling <b>${this.serverGroup.name}</b> will set its traffic allocation for\n <b>${this.serverGroup.loadBalancers[0]}</b> to 100%.\n </p>\n <p>\n If you would like more fine-grained control over your server groups' allocations,\n edit <b>${this.serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.\n </p>\n </div>\n `;\n\n const confirmationModalParams = {\n header: 'Really enable ' + this.serverGroup.name + '?',\n buttonText: 'Enable ' + this.serverGroup.name,\n body: modalBody,\n account: this.serverGroup.account,\n taskMonitorConfig: taskMonitor,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n submitMethod,\n askForReason: true,\n interestingHealthProviderNames: [] as string[],\n };\n\n if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {\n confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public disableServerGroup(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Disabling ' + this.serverGroup.name,\n };\n\n const submitMethod = (params: any) =>\n this.serverGroupWriter.disableServerGroup(this.serverGroup, this.app.name, params);\n\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);\n const modalBody = `<div class=\"well well-sm\">\n <p>\n For App Engine, a disable operation sets this server group's allocation\n to 0% and sets the other enabled server groups' allocations to their relative proportions\n before the disable operation. The approximate allocations that will result from this operation are shown below.\n </p>\n <p>\n If you would like more fine-grained control over your server groups' allocations,\n edit <b>${this.serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.\n </p>\n <div class=\"row\">\n <div class=\"col-md-12\">\n ${AppengineServerGroupDetailsController.buildExpectedAllocationsTable(expectedAllocations)}\n </div>\n </div>\n </div>\n `;\n\n const confirmationModalParams = {\n header: 'Really disable ' + this.serverGroup.name + '?',\n buttonText: 'Disable ' + this.serverGroup.name,\n body: modalBody,\n account: this.serverGroup.account,\n taskMonitorConfig: taskMonitor,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n submitMethod,\n askForReason: true,\n interestingHealthProviderNames: [] as string[],\n };\n\n if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {\n confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public stopServerGroup(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Stopping ' + this.serverGroup.name,\n };\n\n const submitMethod = () => this.appengineServerGroupWriter.stopServerGroup(this.serverGroup, this.app);\n\n let modalBody: string;\n if (!this.serverGroup.disabled) {\n modalBody = `<div class=\"alert alert-danger\">\n <p>Stopping this server group will scale it down to zero instances.</p>\n <p>\n This server group is currently serving traffic from <b>${this.serverGroup.loadBalancers[0]}</b>.\n Traffic directed to this server group after it has been stopped will not be handled.\n </p>\n </div>`;\n }\n\n const confirmationModalParams = {\n header: 'Really stop ' + this.serverGroup.name + '?',\n buttonText: 'Stop ' + this.serverGroup.name,\n account: this.serverGroup.account,\n body: modalBody,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n askForReason: true,\n };\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public startServerGroup(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Starting ' + this.serverGroup.name,\n };\n\n const submitMethod = () => this.appengineServerGroupWriter.startServerGroup(this.serverGroup, this.app);\n\n const confirmationModalParams = {\n header: 'Really start ' + this.serverGroup.name + '?',\n buttonText: 'Start ' + this.serverGroup.name,\n account: this.serverGroup.account,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n askForReason: true,\n };\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public cloneServerGroup(): void {\n this.$uibModal.open({\n templateUrl: require('../configure/wizard/serverGroupWizard.html'),\n controller: 'appengineCloneServerGroupCtrl as ctrl',\n size: 'lg',\n resolve: {\n title: () => 'Clone ' + this.serverGroup.name,\n application: () => this.app,\n serverGroup: () => this.serverGroup,\n serverGroupCommand: () =>\n this.appengineServerGroupCommandBuilder.buildServerGroupCommandFromExisting(this.app, this.serverGroup),\n },\n });\n }\n\n public canStartServerGroup(): boolean {\n if (this.canStartOrStopServerGroup()) {\n return this.serverGroup.servingStatus === 'STOPPED';\n } else {\n return false;\n }\n }\n\n public canStopServerGroup(): boolean {\n if (this.canStartOrStopServerGroup()) {\n return this.serverGroup.servingStatus === 'SERVING';\n } else {\n return false;\n }\n }\n\n private canStartOrStopServerGroup(): boolean {\n const isFlex = this.serverGroup.env === 'FLEXIBLE';\n return isFlex || ['MANUAL', 'BASIC'].includes(this.serverGroup.scalingPolicy?.type);\n }\n\n private getBodyTemplate(serverGroup: IAppengineServerGroup, app: Application): string {\n let template = '';\n const params: IConfirmationModalParams = {};\n ServerGroupWarningMessageService.addDestroyWarningMessage(app, serverGroup, params);\n if (params.body) {\n template += params.body;\n }\n\n if (!serverGroup.disabled) {\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(serverGroup, app);\n\n template += `\n <div class=\"well well-sm\">\n <p>\n A destroy operation will first disable this server group.\n </p>\n <p>\n For App Engine, a disable operation sets this server group's allocation\n to 0% and sets the other enabled server groups' allocations to their relative proportions\n before the disable operation. The approximate allocations that will result from this operation are shown below.\n </p>\n <p>\n If you would like more fine-grained control over your server groups' allocations,\n edit <b>${serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.\n </p>\n <div class=\"row\">\n <div class=\"col-md-12\">\n ${AppengineServerGroupDetailsController.buildExpectedAllocationsTable(expectedAllocations)}\n </div>\n </div>\n </div>\n `;\n }\n\n return template;\n }\n\n private expectedAllocationsAfterDisableOperation(\n serverGroup: IServerGroup,\n app: Application,\n ): { [key: string]: number } {\n const loadBalancer = app.getDataSource('loadBalancers').data.find((toCheck: IAppengineLoadBalancer): boolean => {\n const allocations = toCheck.split?.allocations ?? {};\n const enabledServerGroups = Object.keys(allocations);\n return enabledServerGroups.includes(serverGroup.name);\n });\n\n if (loadBalancer) {\n let allocations = cloneDeep(loadBalancer.split.allocations);\n delete allocations[serverGroup.name];\n const denominator = reduce(allocations, (partialSum: number, allocation: number) => partialSum + allocation, 0);\n const precision = loadBalancer.split.shardBy === 'COOKIE' ? 1000 : 100;\n allocations = mapValues(\n allocations,\n (allocation) => Math.round((allocation / denominator) * precision) / precision,\n );\n return allocations;\n } else {\n return null;\n }\n }\n\n private autoClose(): void {\n if (this.$scope.$$destroyed) {\n return;\n } else {\n this.$state.params.allowModalToStayOpen = true;\n this.$state.go('^', null, { location: 'replace' });\n }\n }\n\n private extractServerGroup(fromParams: IServerGroupFromStateParams): PromiseLike<void> {\n return ServerGroupReader.getServerGroup(\n this.app.name,\n fromParams.accountId,\n fromParams.region,\n fromParams.name,\n ).then((serverGroupDetails: IServerGroup) => {\n let fromApp = this.app.getDataSource('serverGroups').data.find((toCheck: IServerGroup) => {\n return (\n toCheck.name === fromParams.name &&\n toCheck.account === fromParams.accountId &&\n toCheck.region === fromParams.region\n );\n });\n\n if (!fromApp) {\n this.app.getDataSource('loadBalancers').data.some((loadBalancer: ILoadBalancer) => {\n if (loadBalancer.account === fromParams.accountId) {\n return loadBalancer.serverGroups.some((toCheck: IServerGroup) => {\n let result = false;\n if (toCheck.name === fromParams.name) {\n fromApp = toCheck;\n result = true;\n }\n return result;\n });\n } else {\n return false;\n }\n });\n }\n\n this.serverGroup = { ...serverGroupDetails, ...fromApp };\n this.state.loading = false;\n });\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_DETAILS_CTRL = 'spinnaker.appengine.serverGroup.details.controller';\n\nmodule(APPENGINE_SERVER_GROUP_DETAILS_CTRL, [APPENGINE_SERVER_GROUP_WRITER, SERVER_GROUP_WRITER]).controller(\n 'appengineServerGroupDetailsCtrl',\n AppengineServerGroupDetailsController,\n);\n","import { module } from 'angular';\n\nimport type { IArtifact, IArtifactAccountPair, IServerGroup } from '@spinnaker/core';\n\nimport type { IAppengineServerGroupCommand } from './configure/serverGroupCommandBuilder.service';\nimport type { GitCredentialType, IAppengineGitTrigger, IAppengineJenkinsTrigger } from '../domain/index';\n\nexport class AppengineDeployDescription {\n public cloudProvider = 'appengine';\n public provider = 'appengine';\n public credentials: string;\n public account: string;\n public application: string;\n public stack?: string;\n public freeFormDetails?: string;\n public repositoryUrl: string;\n public branch: string;\n public configFilepaths: string[];\n public configFiles: string[];\n public configArtifacts: IArtifactAccountPair[];\n public applicationDirectoryRoot: string;\n public promote?: boolean;\n public stopPreviousVersion?: boolean;\n public type: string;\n public region: string;\n public strategy?: string;\n public strategyApplication?: string;\n public strategyPipeline?: string;\n public fromTrigger?: boolean;\n public trigger?: IAppengineGitTrigger | IAppengineJenkinsTrigger;\n public gitCredentialType: GitCredentialType;\n public interestingHealthProviderNames: string[];\n public expectedArtifactId: string;\n public expectedArtifact: IArtifact;\n public fromArtifact: boolean;\n public sourceType: string;\n public storageAccountName?: string;\n public containerImageUrl?: string;\n public suppressVersionString?: boolean;\n\n constructor(command: IAppengineServerGroupCommand) {\n this.credentials = command.credentials;\n this.account = command.credentials;\n this.application = command.application;\n this.stack = command.stack;\n this.freeFormDetails = command.freeFormDetails;\n this.repositoryUrl = command.repositoryUrl;\n this.branch = command.branch;\n this.configFilepaths = command.configFilepaths;\n this.promote = command.promote;\n this.stopPreviousVersion = command.stopPreviousVersion;\n this.type = command.type;\n this.region = command.region;\n this.strategy = command.strategy;\n this.strategyApplication = command.strategyApplication;\n this.strategyPipeline = command.strategyPipeline;\n this.fromTrigger = command.fromTrigger;\n this.trigger = command.trigger;\n this.gitCredentialType = command.gitCredentialType;\n this.configFiles = command.configFiles;\n this.configArtifacts = command.configArtifacts.filter((a) => !!a.id || !!a.artifact);\n this.applicationDirectoryRoot = command.applicationDirectoryRoot;\n this.interestingHealthProviderNames = command.interestingHealthProviderNames || [];\n this.expectedArtifactId = command.expectedArtifactId;\n this.expectedArtifact = command.expectedArtifact;\n this.fromArtifact = command.fromArtifact;\n this.sourceType = command.sourceType;\n this.storageAccountName = command.storageAccountName;\n this.containerImageUrl = command.containerImageUrl;\n this.suppressVersionString = command.suppressVersionString;\n }\n}\n\nexport class AppengineServerGroupTransformer {\n public static $inject = ['$q'];\n constructor(private $q: ng.IQService) {}\n\n public normalizeServerGroup(serverGroup: IServerGroup): PromiseLike<IServerGroup> {\n return this.$q.resolve(serverGroup);\n }\n\n public convertServerGroupCommandToDeployConfiguration(command: IAppengineServerGroupCommand) {\n return new AppengineDeployDescription(command);\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_TRANSFORMER = 'spinnaker.appengine.serverGroup.transformer.service';\n\nmodule(APPENGINE_SERVER_GROUP_TRANSFORMER, []).service(\n 'appengineServerGroupTransformer',\n AppengineServerGroupTransformer,\n);\n","import type { IApplicationNameValidator, IValidationResult } from '@spinnaker/core';\nimport { ApplicationNameValidator } from '@spinnaker/core';\n\n// See https://cloud.google.com/appengine/docs/admin-api/reference/rest/v1/apps.services.versions#Version\nclass AppengineApplicationNameValidator implements IApplicationNameValidator {\n public validate(name = ''): IValidationResult {\n const warnings: string[] = [];\n const errors: string[] = [];\n if (name.length) {\n this.validateSpecialCharacters(name, errors);\n this.validateLength(name, warnings, errors);\n }\n return { warnings, errors };\n }\n\n private validateSpecialCharacters(name: string, errors: string[]): void {\n const pattern = /^[a-z0-9]*$/g;\n if (!pattern.test(name)) {\n errors.push('Only numbers and lowercase letters are allowed.');\n }\n }\n\n private validateLength(name: string, warnings: string[], errors: string[]): void {\n if (name.length > 58) {\n errors.push('The maximum length for an App Engine application name is 63 characters.');\n return;\n }\n if (name.length > 48) {\n if (name.length >= 56) {\n warnings.push('You will not be able to include a stack or detail field for clusters.');\n } else {\n const remaining = 56 - name.length;\n warnings.push(`If you plan to include a stack or detail field for clusters, you will only have\n ${remaining} character${remaining > 1 ? 's' : ''} to do so.`);\n }\n }\n }\n}\n\nApplicationNameValidator.registerValidator('appengine', new AppengineApplicationNameValidator());\n","import { module } from 'angular';\n\nimport { CloudProviderRegistry, DeploymentStrategyRegistry } from '@spinnaker/core';\n\nimport { APPENGINE_COMPONENT_URL_DETAILS } from './common/componentUrlDetails.component';\nimport { APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM } from './common/conditionalDescriptionListItem.component';\nimport { APPENGINE_LOAD_BALANCER_CREATE_MESSAGE } from './common/loadBalancerMessage.component';\nimport './helpContents/appengineHelpContents';\nimport { APPENGINE_INSTANCE_DETAILS_CTRL } from './instance/details/details.controller';\nimport { APPENGINE_LOAD_BALANCER_MODULE } from './loadBalancer/loadBalancer.module';\nimport logo from './logo/appengine.logo.png';\nimport { APPENGINE_PIPELINE_MODULE } from './pipeline/pipeline.module';\nimport './pipeline/stages/deployAppengineConfig/deployAppengineConfigStage';\nimport { APPENGINE_SERVER_GROUP_COMMAND_BUILDER } from './serverGroup/configure/serverGroupCommandBuilder.service';\nimport { APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL } from './serverGroup/configure/wizard/basicSettings.controller';\nimport { APPENGINE_CLONE_SERVER_GROUP_CTRL } from './serverGroup/configure/wizard/cloneServerGroup.controller';\nimport { CONFIG_FILE_ARTIFACT_LIST } from './serverGroup/configure/wizard/configFileArtifactList.module';\nimport { APPENGINE_SERVER_GROUP_DETAILS_CTRL } from './serverGroup/details/details.controller';\nimport { APPENGINE_SERVER_GROUP_TRANSFORMER } from './serverGroup/transformer';\nimport { APPENGINE_SERVER_GROUP_WRITER } from './serverGroup/writer/serverGroup.write.service';\nimport './validation/ApplicationNameValidator';\n\nimport './logo/appengine.logo.less';\n\nexport const APPENGINE_MODULE = 'spinnaker.appengine';\n\nmodule(APPENGINE_MODULE, [\n APPENGINE_CLONE_SERVER_GROUP_CTRL,\n APPENGINE_COMPONENT_URL_DETAILS,\n APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM,\n APPENGINE_INSTANCE_DETAILS_CTRL,\n APPENGINE_LOAD_BALANCER_CREATE_MESSAGE,\n APPENGINE_LOAD_BALANCER_MODULE,\n APPENGINE_PIPELINE_MODULE,\n APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL,\n APPENGINE_SERVER_GROUP_COMMAND_BUILDER,\n APPENGINE_SERVER_GROUP_DETAILS_CTRL,\n APPENGINE_SERVER_GROUP_TRANSFORMER,\n APPENGINE_SERVER_GROUP_WRITER,\n CONFIG_FILE_ARTIFACT_LIST,\n]).config(() => {\n CloudProviderRegistry.registerProvider('appengine', {\n name: 'App Engine',\n instance: {\n detailsTemplateUrl: require('./instance/details/details.html'),\n detailsController: 'appengineInstanceDetailsCtrl',\n },\n serverGroup: {\n transformer: 'appengineServerGroupTransformer',\n detailsController: 'appengineServerGroupDetailsCtrl',\n detailsTemplateUrl: require('./serverGroup/details/details.html'),\n commandBuilder: 'appengineServerGroupCommandBuilder',\n cloneServerGroupController: 'appengineCloneServerGroupCtrl',\n cloneServerGroupTemplateUrl: require('./serverGroup/configure/wizard/serverGroupWizard.html'),\n skipUpstreamStageCheck: true,\n },\n loadBalancer: {\n transformer: 'appengineLoadBalancerTransformer',\n createLoadBalancerTemplateUrl: require('./loadBalancer/configure/wizard/wizard.html'),\n createLoadBalancerController: 'appengineLoadBalancerWizardCtrl',\n detailsTemplateUrl: require('./loadBalancer/details/details.html'),\n detailsController: 'appengineLoadBalancerDetailsCtrl',\n },\n logo: {\n path: logo,\n },\n });\n});\n\nDeploymentStrategyRegistry.registerProvider('appengine', ['custom']);\n","export default \"appengine.logoc2c312af6aa99037.png\""],"names":["appengineComponentUrlDetailsComponent","bindings","component","template","APPENGINE_COMPONENT_URL_DETAILS","module","AppengineConditionalDescriptionListItemCtrl","constructor","$filter","this","$onInit","label","key","$inject","appengineConditionalDescriptionListItem","transclude","keyLabel","valueLabel","controller","APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM","APPENGINE_LOAD_BALANCER_CREATE_MESSAGE","showCreateMessage","columnOffset","columns","templateUrl","value","forEach","entry","HelpContentsRegistry","register","AppengineInstanceDetailsController","$q","app","instance","state","loading","upToolTip","outOfServiceToolTip","ready","then","retrieveInstance","instanceDetails","catch","instanceIdNotFound","instanceId","terminateInstance","cloneDeep","shortName","name","substring","placement","taskMonitor","application","title","onTaskComplete","$state","includes","go","ConfirmationModalService","confirm","header","buttonText","account","taskMonitorConfig","submitMethod","InstanceWriter","cloudProvider","instanceManager","flattenDeep","getDataSource","data","map","loadBalancer","serverGroups","find","dataSource","instances","some","possibleMatch","id","recentHistoryExtraData","region","category","serverGroup","RecentHistoryService","addExtraDataToLatest","InstanceReader","getInstanceDetails","reject","APPENGINE_INSTANCE_DETAILS_CTRL","appengineLoadBalancerAdvancedSettingsComponent","error","disableMigrateTraffic","splitDescription","allocationDescriptions","length","targetServerGroupName","serverGroupName","targetServerGroup","candidate","allowsGradualTrafficMigration","APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS","appengineAllocationConfigurationRowComponent","allocationDescription","removeAllocation","serverGroupOptions","onAllocationChange","getServerGroupOptions","uniq","concat","APPENGINE_ALLOCATION_CONFIGURATION_ROW","appengineLoadBalancerSettingsComponent","forPipelineConfig","updateServerGroupOptions","addAllocation","remainingServerGroups","serverGroupsWithoutAllocation","push","allocation","locatorType","shardBy","index","splice","allocationIsInvalid","reduce","sum","showAddButton","showShardByOptions","migrateTraffic","initializeAsTextInput","serverGroupsWithAllocation","description","allServerGroups","difference","APPENGINE_LOAD_BALANCER_BASIC_SETTINGS","AppengineStageAllocationLabelCtrl","mapTargetCoordinateToLabel","targetCoordinate","target","StageConstants","TARGET_LIST","t","val","$doCheck","setInputViewValue","inputViewValue","cluster","targetLabel","appengineStageAllocationLabel","appengineStageAllocationConfigurationRow","targets","clusterFilter","AppListExtractor","clusterFilterForCredentialsAndRegion","clusterList","getClusters","onLocatorTypeChange","APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW","AppengineLoadBalancerUpsertDescription","convertTrafficSplitToTrafficSplitDescription","split","allocations","acc","credentials","loadBalancerName","mapAllocationsToDecimals","mapAllocationsToPercentages","Math","round","AppengineLoadBalancerTransformer","normalizeLoadBalancer","provider","type","instanceCounts","buildInstanceCounts","detachedInstances","transformInstance","activeServerGroups","filter","isDisabled","chain","flatten","resolve","convertLoadBalancerForEditing","upToDateLoadBalancer","convertLoadBalancerToUpsertDescription","has","camelCase","health","up","down","outOfService","succeeded","failed","starting","unknown","loadBalancers","healthState","get","APPENGINE_LOAD_BALANCER_TRANSFORMER","styleInject","css","ref","insertAt","document","head","getElementsByTagName","style","createElement","firstChild","insertBefore","appendChild","styleSheet","cssText","createTextNode","service","AppengineLoadBalancerWizardController","$scope","$uibModalInstance","isNew","appengineLoadBalancerTransformer","wizardSubFormValidation","submitButtonLabel","heading","join","convertedLoadBalancer","setTaskMonitor","initializeFormValidation","submit","close","LoadBalancerWriter","upsertLoadBalancer","cancel","dismiss","showSubmitButton","subFormsAreValid","TaskMonitor","modalInstance","config","form","scope","page","subForm","validators","watchString","validator","watchDeep","refresh","onNextRefresh","onApplicationRefresh","$$destroyed","newStateParams","accountId","APPENGINE_LOAD_BALANCER_WIZARD_CTRL","AppengineLoadBalancerDetailsController","$uibModal","dispatchRules","loadBalancerFromParams","extractLoadBalancer","editLoadBalancer","open","size","deleteLoadBalancer","body","getConfirmationModalBodyHtml","canDeleteLoadBalancer","test","buildDispatchRules","onRefresh","autoClose","rule","domain","path","serverGroupNames","hasAny","hasMoreThanOne","listOfServerGroupNames","params","allowModalToStayOpen","location","APPENGINE_LOAD_BALANCER_DETAILS_CTRL","APPENGINE_LOAD_BALANCER_MODULE","AppengineHealth","PLATFORM","AppengineStageCtrl","platformHealth","setStageRegion","selected","accounts","stage","AccountService","getAccountDetails","accountDetails","setStageCloudProvider","setAccounts","listAccounts","setTargets","setStageCredentials","defaultCredentials","appengine","AppengineDestroyAsgStageCtrl","super","APPENGINE_DESTROY_ASG_STAGE","Registry","pipeline","registerStage","provides","executionStepLabelUrl","message","fieldName","fieldLabel","AppengineDisableAsgStageCtrl","attributes","platformHealthOnlyShowOverride","platformHealthOnly","interestingHealthProviderNames","APPENGINE_DISABLE_ASG_STAGE","AppengineLoadBalancerChoiceModalCtrl","initialize","CloudProviderRegistry","getValue","updatedLoadBalancerPromise","createLoadBalancerTemplateUrl","createLoadBalancerController","selectedLoadBalancer","result","APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL","AppengineEditLoadBalancerStageCtrl","addLoadBalancer","newLoadBalancer","updatedLoadBalancer","removeLoadBalancer","APPENGINE_EDIT_LOAD_BALANCER_STAGE","executionDetailsUrl","executionConfigSections","controllerAs","AppengineEnableAsgStageCtrl","APPENGINE_ENABLE_ASG_STAGE","AppengineShrinkClusterStageCtrl","shrinkToSize","allowDeleteActive","retainLargerOverNewer","toString","pluralize","str","APPENGINE_SHRINK_CLUSTER_STAGE","AppengineStartServerGroupStageCtrl","APPENGINE_START_SERVER_GROUP_STAGE","AppengineStopServerGroupStageCtrl","APPENGINE_STOP_SERVER_GROUP_STAGE","APPENGINE_PIPELINE_MODULE","FormikAccountRegionSelector","React","Component","props","destroy$","Subject","setRegionList","accountFilter","observableFrom","pipe","takeUntil","subscribe","availableRegions","getRegions","sort","setState","accountChanged","credentialsField","componentName","componentDidMount","formik","values","componentWillUnmount","next","render","className","FormikFormField","input","ReactSelectInput","stringOptions","clearable","onChange","required","_DeployAppengineConfigForm","arguments","onTemplateArtifactEdited","artifact","setFieldValue","artifactAccount","onTemplateArtifactSelected","removeInputArtifact","getInputArtifact","StageArtifactSelectorDelegate","excludedArtifactTypePatterns","excludedArtifactTypes","expectedArtifactId","onArtifactEdited","helpKey","onExpectedArtifactSelected","onClick","DeployAppengineConfigForm","validateDeployAppengineConfigurationStage","formValidator","FormValidator","field","validateForm","excludeAllTypesExcept","ArtifactTypePatterns","BITBUCKET_FILE","CUSTOM_OBJECT","EMBEDDED_BASE64","GCS_OBJECT","GITHUB_FILE","GITLAB_FILE","S3_OBJECT","HTTP_FILE","ORACLE_OBJECT","updateStage","stageWithDefaults","useMemo","FormikStageConfig","validate","producesArtifacts","executionDetailsSections","ExecutionDetailsTasks","ExecutionArtifactTab","validateFn","AppengineProviderSettings","SETTINGS","providers","defaults","AppengineSourceType","AppengineSourceType2","resetToOriginal","resetProvider","_AppengineServerGroupCommandBuilder","getTriggerOptions","triggers","trigger","source","project","slug","branch","master","job","getExpectedArtifacts","expectedArtifacts","buildNewServerGroupCommand","selectedProvider","mode","dataToFetch","getAllAccountDetailsForProvider","storageAccounts","StorageAccountReader","getStorageAccounts","viewState","getSubmitButtonLabel","disableStrategySelection","all","backingData","getCredentials","getRegion","fromArtifact","sourceType","GIT","buildServerGroupCommandFromExisting","command","stack","freeFormDetails","detail","buildNewServerGroupCommandForPipeline","_stage","when","triggerOptions","buildServerGroupCommandFromPipeline","accountNames","_account","AppengineServerGroupCommandBuilder","APPENGINE_SERVER_GROUP_COMMAND_BUILDER","AppengineServerGroupBasicSettingsCtrl","$controller","$uibModalStack","excludedGcsArtifactTypes","excludedContainerArtifactTypes","DOCKER_IMAGE","onExpectedArtifactEdited","$applyAsync","expectedArtifact","onChangeExpectedArtifactId","artifactId","onExpectedArtifactAccountSelected","accountName","storageAccountName","extend","imageReader","gitCredentialType","onAccountChange","containerArtifactDelegate","NgAppEngineDeployArtifactDelegate","containerArtifactController","ExpectedArtifactSelectorViewController","gcsArtifactDelegate","gcsArtifactController","isGitSource","isGcsSource","GCS","isContainerImageSource","CONTAINER_IMAGE","toggleResolveViaTrigger","fromTrigger","onTriggerChange","set","findAccountInBackingData","getSupportedGitCredentialTypes","supportedGitCredentialTypes","humanReadableGitCredentialType","APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL","ConfigArtifact","pair","_a","unserializable","configurable","enumerable","writable","Object","defineProperty","delegate","NgAppengineConfigArtifactDelegate","AppengineConfigFileConfigurerCtrl","artifactAccounts","updateConfigArtifacts","configArtifacts","configFiles","artifactAccountPair","getArtifactAccounts","a","updateAccounts","getSelectedExpectedArtifact","addConfigFile","addConfigArtifact","deleteConfigFile","deleteConfigArtifact","mapTabToSpaces","event","which","preventDefault","cursorPosition","selectionStart","inputValue","appengineConfigFileConfigurerComponent","APPENGINE_CONFIG_FILE_CONFIGURER","appengineDynamicBranchLabelComponent","APPENGINE_DYNAMIC_BRANCH_LABEL","AppengineCloneServerGroupCtrl","serverGroupCommand","serverGroupWriter","appengineServerGroupCommandBuilder","pages","basicSettings","advancedSettings","constructedCommand","merge","copy","cloneServerGroup","showPlatformHealthOnlyOverride","APPENGINE_CLONE_SERVER_GROUP_CTRL","SERVER_GROUP_WRITER","CONFIG_FILE_ARTIFACT_LIST","react2angular","withErrorBoundary","newConfigArtifacts","i","classNames","StageArtifactSelector","APPENGINE_SERVER_GROUP_WRITER","startServerGroup","buildJob","TaskExecutor","executeTask","stopServerGroup","_AppengineServerGroupDetailsController","appengineServerGroupWriter","extractServerGroup","buildExpectedAllocationsTable","expectedAllocations","canDisableServerGroup","disabled","expectedAllocationsAfterDisableOperation","keys","canDestroyServerGroup","destroyServerGroup","stateParams","confirmationModalParams","askForReason","platformHealthType","getBodyTemplate","enableServerGroup","modalBody","disableServerGroup","canStartServerGroup","canStartOrStopServerGroup","servingStatus","canStopServerGroup","env","scalingPolicy","ServerGroupWarningMessageService","addDestroyWarningMessage","toCheck","_b","denominator","partialSum","precision","mapValues","fromParams","ServerGroupReader","getServerGroup","serverGroupDetails","fromApp","AppengineServerGroupDetailsController","APPENGINE_SERVER_GROUP_DETAILS_CTRL","AppengineDeployDescription","repositoryUrl","configFilepaths","promote","stopPreviousVersion","strategy","strategyApplication","strategyPipeline","applicationDirectoryRoot","containerImageUrl","suppressVersionString","AppengineServerGroupTransformer","normalizeServerGroup","convertServerGroupCommandToDeployConfiguration","APPENGINE_SERVER_GROUP_TRANSFORMER","ApplicationNameValidator","registerValidator","warnings","errors","validateSpecialCharacters","validateLength","remaining","APPENGINE_MODULE","registerProvider","detailsTemplateUrl","detailsController","transformer","commandBuilder","cloneServerGroupController","cloneServerGroupTemplateUrl","skipUpstreamStageCheck","logo","DeploymentStrategyRegistry"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/common/componentUrlDetails.component.ts","../src/common/conditionalDescriptionListItem.component.ts","../src/common/loadBalancerMessage.component.ts","../src/helpContents/appengineHelpContents.ts","../src/instance/details/details.controller.ts","../src/loadBalancer/configure/wizard/advancedSettings.component.ts","../src/loadBalancer/configure/wizard/allocationConfigurationRow.component.ts","../src/loadBalancer/configure/wizard/basicSettings.component.ts","../src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.ts","../src/loadBalancer/transformer.ts","../../../node_modules/style-inject/dist/style-inject.es.js","../src/loadBalancer/configure/wizard/wizard.controller.ts","../src/loadBalancer/details/details.controller.ts","../src/loadBalancer/loadBalancer.module.ts","../src/common/appengineHealth.ts","../src/pipeline/stages/appengineStage.controller.ts","../src/pipeline/stages/destroyAsg/appengineDestroyAsgStage.ts","../src/pipeline/stages/disableAsg/appengineDisableAsgStage.ts","../src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.ts","../src/pipeline/stages/editLoadBalancer/appengineEditLoadBalancerStage.ts","../src/pipeline/stages/enableAsg/appengineEnableAsgStage.ts","../src/pipeline/stages/shrinkCluster/appengineShrinkClusterStage.ts","../src/pipeline/stages/startServerGroup/appengineStartServerGroupStage.ts","../src/pipeline/stages/stopServerGroup/appengineStopServerGroupStage.ts","../src/pipeline/pipeline.module.ts","../src/common/FormikAccountRegionSelector.tsx","../src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigForm.tsx","../src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigurationConfig.tsx","../src/pipeline/stages/deployAppengineConfig/deployAppengineConfigStage.ts","../src/appengine.settings.ts","../src/serverGroup/configure/serverGroupCommandBuilder.service.ts","../src/serverGroup/configure/wizard/basicSettings.controller.ts","../src/serverGroup/configure/wizard/configFiles.component.ts","../src/serverGroup/configure/wizard/dynamicBranchLabel.component.ts","../src/serverGroup/configure/wizard/cloneServerGroup.controller.ts","../src/serverGroup/configure/wizard/ConfigFileArtifactList.tsx","../src/serverGroup/configure/wizard/configFileArtifactList.module.ts","../src/serverGroup/writer/serverGroup.write.service.ts","../src/serverGroup/details/details.controller.ts","../src/serverGroup/transformer.ts","../src/validation/ApplicationNameValidator.ts","../src/appengine.module.ts","../src/logo/appengine.logo.png"],"sourcesContent":["import type { IComponentOptions } from 'angular';\nimport { module } from 'angular';\n\nconst appengineComponentUrlDetailsComponent: IComponentOptions = {\n bindings: { component: '<' },\n template: `\n <dt>HTTPS</dt>\n <dl class=\"small\">\n <a href=\"{{$ctrl.component.httpsUrl}}\" target=\"_blank\">{{$ctrl.component.httpsUrl}}</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 <dt>HTTP</dt>\n <dl class=\"small\">\n <a href=\"{{$ctrl.component.httpUrl}}\" target=\"_blank\">{{$ctrl.component.httpUrl}}</a>\n <copy-to-clipboard class=\"copy-to-clipboard copy-to-clipboard-sm\"\n tool-tip=\"'Copy URL to clipboard'\"\n text=\"$ctrl.component.httpUrl\"></copy-to-clipboard>\n </dl>\n `,\n};\n\nexport const APPENGINE_COMPONENT_URL_DETAILS = 'spinnaker.appengine.componentUrlDetails.component';\n\nmodule(APPENGINE_COMPONENT_URL_DETAILS, []).component(\n 'appengineComponentUrlDetails',\n appengineComponentUrlDetailsComponent,\n);\n","import type { IComponentOptions, IController, IFilterService } from 'angular';\nimport { module } from 'angular';\n\nclass AppengineConditionalDescriptionListItemCtrl implements IController {\n public label: string;\n public key: string;\n public component: any;\n\n public static $inject = ['$filter'];\n constructor(private $filter: IFilterService) {}\n\n public $onInit(): void {\n if (!this.label) {\n this.label = this.$filter<Function>('robotToHuman')(this.key);\n }\n }\n}\n\nconst appengineConditionalDescriptionListItem: IComponentOptions = {\n bindings: { label: '@', key: '@', component: '<' },\n transclude: {\n keyLabel: '?keyText',\n valueLabel: '?valueLabel',\n },\n template: `\n <dt ng-if=\"$ctrl.component[$ctrl.key]\">{{$ctrl.label}}<span ng-transclude=\"keyLabel\"></span></dt>\n <dd ng-if=\"$ctrl.component[$ctrl.key]\">{{$ctrl.component[$ctrl.key]}}<span ng-transclude=\"valueLabel\"></span></dd>\n `,\n controller: AppengineConditionalDescriptionListItemCtrl,\n};\n\nexport const APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM = 'spinnaker.appengine.conditionalDescriptionListItem';\n\nmodule(APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM, []).component(\n 'appengineConditionalDtDd',\n appengineConditionalDescriptionListItem,\n);\n","import { module } from 'angular';\n\nconst appengineLoadBalancerMessageComponent: ng.IComponentOptions = {\n bindings: { showCreateMessage: '<', columnOffset: '@', columns: '@' },\n templateUrl: require('./loadBalancerMessage.component.html'),\n};\n\nexport const APPENGINE_LOAD_BALANCER_CREATE_MESSAGE = 'spinnaker.appengine.loadBalancer.createMessage.component';\n\nmodule(APPENGINE_LOAD_BALANCER_CREATE_MESSAGE, []).component(\n 'appengineLoadBalancerMessage',\n appengineLoadBalancerMessageComponent,\n);\n","import { HelpContentsRegistry } from '@spinnaker/core';\n\nconst helpContents = [\n {\n key: 'appengine.serverGroup.gcs.repositoryUrl',\n value: `The full URL to the GCS bucket or TAR file containing the source files for this deployment,\n including 'gs://'. For example, <b>gs://my-bucket/my-app</b> or <b>gs://my-bucket/app.tar</b>.`,\n },\n {\n key: 'appengine.serverGroup.git.repositoryUrl',\n value: `The full URL to the git repository containing the source files for this deployment,\n including protocol. For example, <b>https://github.com/spinnaker/deck.git</b>`,\n },\n {\n key: 'appengine.serverGroup.gitCredentialType',\n value: `The credential type that will be used to access the git repository for this deployment.\n You can configure these credentials alongside your App Engine credentials.`,\n },\n {\n key: 'appengine.serverGroup.branch',\n value: 'The name of the branch in the above git repository to be used for this deployment.',\n },\n {\n key: 'appengine.serverGroup.applicationDirectoryRoot',\n value: `(Optional) Path to the directory root of the application to be deployed,\n starting from the root of the git repository. This is the directory from which\n <code>gcloud app deploy</code> will be run.`,\n },\n {\n key: 'appengine.serverGroup.configFilepaths',\n value: `Paths to App Engine application configuration files, starting from the application directory root,\n specified above. In most cases, this will be <code>app.yaml</code> or <code>cron.yaml</code>,\n but could be <code>path/to/app.yaml</code> or <code>path/to/cron.yaml</code>.`,\n },\n {\n key: 'appengine.serverGroup.configFiles',\n value: `<p>(Optional) The contents of an App Engine config file (e.g., an <code>app.yaml</code> or\n <code>cron.yaml</code> file). These files should not conflict with the config filepaths above:\n if you include, for example, the contents of an <code>app.yaml</code>\n file here, you should <b>not</b> specify the file path to an <code>app.yaml</code> above.<br></p>\n <p>If this is a pipeline stage, you can use Spinnaker Pipeline Expressions here.</p>`,\n },\n {\n key: 'appengine.serverGroup.configFilesRequired',\n value: `<p>The contents of an App Engine config file (e.g., an <code>app.yaml</code> or\n <code>cron.yaml</code> file).</p>\n <p>An <code>app.yaml</code> file is required and must have <code>runtime: custom</code> in\n order to deploy successfully.</p>\n <p>If this is a pipeline stage, you can use Spinnaker Pipeline Expressions here.</p>`,\n },\n {\n key: 'appengine.serverGroup.matchBranchOnRegex',\n value: `(Optional) A Jenkins trigger may produce details from multiple repositories and branches.\n Spinnaker will use the regex specified here to help resolve a branch for the deployment.\n If Spinnaker cannot resolve exactly one branch from the trigger, this pipeline will fail.`,\n },\n {\n key: 'appengine.serverGroup.promote',\n value: 'If selected, the newly deployed server group will receive all traffic.',\n },\n {\n key: 'appengine.serverGroup.stopPreviousVersion',\n value: `If selected, the previously running server group in this server group's <b>service</b>\n (Spinnaker load balancer) will be stopped. This option will be respected only if this server group will\n be receiving all traffic and the previous server group is using manual scaling.`,\n },\n {\n key: 'appengine.serverGroup.containerImageUrl',\n value: `The full URL to the container image to use for deployment. The URL must be one of the valid GCR hostnames,\n for example <b>gcr.io/my-project/image:tag</b>`,\n },\n {\n key: 'appengine.serverGroup.suppress-version-string',\n value: `Spinnaker automatically versions your server groups. This means deployments through Spinnaker receive a\n short version string at the end of their name, like \"v001\". In most cases you will want to keep this\n version as part of the name. Preventing this string from being added to your server group will stop\n it from being considered when rolling back, promoting new versions or executing deployment strategies.\n If you are certain that you do not want the version string applied to this server group then check\n this box.`,\n },\n {\n key: 'appengine.loadBalancer.shardBy.cookie',\n value:\n 'Diversion based on a specially named cookie, \"GOOGAPPUID.\" The cookie must be set by the application itself or no diversion will occur.',\n },\n {\n key: 'appengine.loadBalancer.shardBy.ip',\n value: 'Diversion based on applying the modulus operation to a fingerprint of the IP address.',\n },\n {\n key: 'appengine.loadBalancer.migrateTraffic',\n value: `If selected, traffic will be gradually shifted to a single version. For gradual traffic migration,\n the target version must be located within instances that are configured for\n both warmup requests and automatic scaling.\n Gradual traffic migration is not supported in the App Engine flexible environment.`,\n },\n {\n key: 'appengine.loadBalancer.allocations',\n value: 'An allocation is the percent of traffic directed to a server group.',\n },\n {\n key: 'appengine.loadBalancer.textLocator',\n value: `Either the name of a server group, or a Spinnaker Pipeline Expression\n that resolves to the name of a server group.`,\n },\n {\n key: 'appengine.instance.availability',\n value: `\n An instance's <b>availability</b> is determined by its version (Spinnaker server group).\n <ul>\n <li>Manual scaling versions use resident instances</li>\n <li>Basic scaling versions use dynamic instances</li>\n <li>Auto scaling versions use dynamic instances - but if you specify a number, N,\n of minimum idle instances, the first N instances will be resident,\n and additional dynamic instances will be created as necessary.\n </li>\n </ul>`,\n },\n {\n key: 'appengine.instance.averageLatency',\n value: 'Average latency over the last minute in milliseconds.',\n },\n {\n key: 'appengine.instance.vmStatus',\n value: 'Status of the virtual machine where this instance lives.',\n },\n {\n key: 'appengine.instance.qps',\n value: 'Average queries per second over the last minute.',\n },\n {\n key: 'appengine.instance.errors',\n value: 'Number of errors since this instance was started.',\n },\n {\n key: 'appengine.instance.requests',\n value: 'Number of requests since this instance was started.',\n },\n];\n\nhelpContents.forEach((entry) => HelpContentsRegistry.register(entry.key, entry.value));\n","import type { IController, IQService } from 'angular';\nimport { module } from 'angular';\nimport { cloneDeep, flattenDeep } from 'lodash';\n\nimport type { Application, ILoadBalancer } from '@spinnaker/core';\nimport { ConfirmationModalService, InstanceReader, InstanceWriter, RecentHistoryService } from '@spinnaker/core';\nimport type { IAppengineInstance } from '../../domain';\n\ninterface InstanceFromStateParams {\n instanceId: string;\n}\n\ninterface InstanceManager {\n account: string;\n region: string;\n category: string; // e.g., serverGroup, loadBalancer.\n name: string; // Parent resource name, not instance name.\n instances: IAppengineInstance[];\n}\n\nclass AppengineInstanceDetailsController implements IController {\n public state = { loading: true };\n public instance: IAppengineInstance;\n public instanceIdNotFound: string;\n public upToolTip = \"An App Engine instance is 'Up' if a load balancer is directing traffic to its server group.\";\n public outOfServiceToolTip = `\n An App Engine instance is 'Out Of Service' if no load balancers are directing traffic to its server group.`;\n\n public static $inject = ['$q', 'app', 'instance'];\n\n constructor(private $q: IQService, private app: Application, instance: InstanceFromStateParams) {\n this.app\n .ready()\n .then(() => this.retrieveInstance(instance))\n .then((instanceDetails) => {\n this.instance = instanceDetails;\n this.state.loading = false;\n })\n .catch(() => {\n this.instanceIdNotFound = instance.instanceId;\n this.state.loading = false;\n });\n }\n\n public terminateInstance(): void {\n const instance = cloneDeep(this.instance) as any;\n const shortName = `${this.instance.name.substring(0, 10)}...`;\n instance.placement = {};\n instance.instanceId = instance.name;\n\n const taskMonitor = {\n application: this.app,\n title: 'Terminating ' + shortName,\n onTaskComplete() {\n if (this.$state.includes('**.instanceDetails', { instanceId: instance.name })) {\n this.$state.go('^');\n }\n },\n };\n\n const submitMethod = () => {\n return InstanceWriter.terminateInstance(instance, this.app, { cloudProvider: 'appengine' });\n };\n\n ConfirmationModalService.confirm({\n header: 'Really terminate ' + shortName + '?',\n buttonText: 'Terminate ' + shortName,\n account: instance.account,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n });\n }\n\n private retrieveInstance(instance: InstanceFromStateParams): PromiseLike<IAppengineInstance> {\n const instanceLocatorPredicate = (dataSource: InstanceManager) => {\n return dataSource.instances.some((possibleMatch) => possibleMatch.id === instance.instanceId);\n };\n\n const dataSources: InstanceManager[] = flattenDeep([\n this.app.getDataSource('serverGroups').data,\n this.app.getDataSource('loadBalancers').data,\n this.app.getDataSource('loadBalancers').data.map((loadBalancer: ILoadBalancer) => loadBalancer.serverGroups),\n ]);\n\n const instanceManager = dataSources.find(instanceLocatorPredicate);\n\n if (instanceManager) {\n const recentHistoryExtraData: { [key: string]: string } = {\n region: instanceManager.region,\n account: instanceManager.account,\n };\n if (instanceManager.category === 'serverGroup') {\n recentHistoryExtraData.serverGroup = instanceManager.name;\n }\n RecentHistoryService.addExtraDataToLatest('instances', recentHistoryExtraData);\n\n return InstanceReader.getInstanceDetails(\n instanceManager.account,\n instanceManager.region,\n instance.instanceId,\n ).then((instanceDetails: IAppengineInstance) => {\n instanceDetails.account = instanceManager.account;\n instanceDetails.region = instanceManager.region;\n return instanceDetails;\n });\n } else {\n return this.$q.reject();\n }\n }\n}\n\nexport const APPENGINE_INSTANCE_DETAILS_CTRL = 'spinnaker.appengine.instanceDetails.controller';\nmodule(APPENGINE_INSTANCE_DETAILS_CTRL, []).controller(\n 'appengineInstanceDetailsCtrl',\n AppengineInstanceDetailsController,\n);\n","import type { IComponentOptions, IController } from 'angular';\nimport { module } from 'angular';\n\nimport type { AppengineLoadBalancerUpsertDescription } from '../../transformer';\n\nclass AppengineLoadBalancerAdvancedSettingsCtrl implements IController {\n public state = { error: false };\n public loadBalancer: AppengineLoadBalancerUpsertDescription;\n\n public disableMigrateTraffic(): boolean {\n if (this.loadBalancer.splitDescription.allocationDescriptions.length !== 1) {\n return true;\n } else {\n const targetServerGroupName = this.loadBalancer.splitDescription.allocationDescriptions[0].serverGroupName;\n const targetServerGroup = this.loadBalancer.serverGroups.find(\n (candidate) => candidate.name === targetServerGroupName,\n );\n\n if (targetServerGroup) {\n return !targetServerGroup.allowsGradualTrafficMigration;\n } else {\n // If the target server group name is not in the load balancer's server groups, then hopefully we are in\n // a pipeline stage - we'll leave it up to the user to make smart decisions.\n return false;\n }\n }\n }\n}\n\nconst appengineLoadBalancerAdvancedSettingsComponent: IComponentOptions = {\n bindings: { loadBalancer: '=', application: '<' },\n template: `\n <ng-form name=\"advancedSettingsForm\">\n <div class=\"row\">\n <div class=\"form-group\">\n <div class=\"col-md-3 sm-label-right\">\n Migrate Traffic <help-field key=\"appengine.loadBalancer.migrateTraffic\"></help-field>\n </div>\n <div class=\"col-md-9\">\n <div class=\"checkbox\">\n <input type=\"checkbox\" ng-disabled=\"$ctrl.disableMigrateTraffic() && !($ctrl.loadBalancer.migrateTraffic = false)\" ng-model=\"$ctrl.loadBalancer.migrateTraffic\">\n </div>\n </div>\n </div>\n </div>\n </ng-form>\n `,\n controller: AppengineLoadBalancerAdvancedSettingsCtrl,\n};\n\nexport const APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS = 'spinnaker.appengine.loadBalancer.advancedSettings.component';\n\nmodule(APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS, []).component(\n 'appengineLoadBalancerAdvancedSettings',\n appengineLoadBalancerAdvancedSettingsComponent,\n);\n","import type { IComponentOptions, IController } from 'angular';\nimport { module } from 'angular';\nimport { uniq } from 'lodash';\n\nimport type { IAppengineAllocationDescription } from '../../transformer';\n\nclass AppengineAllocationConfigurationRowCtrl implements IController {\n public allocationDescription: IAppengineAllocationDescription;\n public serverGroupOptions: string[];\n\n public getServerGroupOptions(): string[] {\n if (this.allocationDescription.serverGroupName) {\n return uniq(this.serverGroupOptions.concat(this.allocationDescription.serverGroupName));\n } else {\n return this.serverGroupOptions;\n }\n }\n}\n\nconst appengineAllocationConfigurationRowComponent: IComponentOptions = {\n bindings: {\n allocationDescription: '<',\n removeAllocation: '&',\n serverGroupOptions: '<',\n onAllocationChange: '&',\n },\n template: `\n <div class=\"form-group\">\n <div class=\"row\">\n <div class=\"col-md-7\">\n <ui-select ng-model=\"$ctrl.allocationDescription.serverGroupName\"\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.allocation\"\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 `,\n controller: AppengineAllocationConfigurationRowCtrl,\n};\n\nexport const APPENGINE_ALLOCATION_CONFIGURATION_ROW = 'spinnaker.appengine.allocationConfigurationRow.component';\n\nmodule(APPENGINE_ALLOCATION_CONFIGURATION_ROW, []).component(\n 'appengineAllocationConfigurationRow',\n appengineAllocationConfigurationRowComponent,\n);\n","import type { IController } from 'angular';\nimport { module } from 'angular';\nimport { difference } from 'lodash';\n\nimport type { AppengineLoadBalancerUpsertDescription } from '../../transformer';\n\nclass AppengineLoadBalancerSettingsController implements IController {\n public loadBalancer: AppengineLoadBalancerUpsertDescription;\n public serverGroupOptions: string[];\n public forPipelineConfig: boolean;\n\n public $onInit(): void {\n this.updateServerGroupOptions();\n }\n\n public addAllocation(): void {\n const remainingServerGroups = this.serverGroupsWithoutAllocation();\n if (remainingServerGroups.length) {\n this.loadBalancer.splitDescription.allocationDescriptions.push({\n serverGroupName: remainingServerGroups[0],\n allocation: 0,\n locatorType: 'fromExisting',\n });\n if (\n this.loadBalancer.splitDescription.allocationDescriptions.length > 1 &&\n !this.loadBalancer.splitDescription.shardBy\n ) {\n this.loadBalancer.splitDescription.shardBy = 'IP';\n }\n this.updateServerGroupOptions();\n } else if (this.forPipelineConfig) {\n this.loadBalancer.splitDescription.allocationDescriptions.push({\n allocation: 0,\n locatorType: 'text',\n serverGroupName: '',\n });\n }\n }\n\n public removeAllocation(index: number): void {\n this.loadBalancer.splitDescription.allocationDescriptions.splice(index, 1);\n this.updateServerGroupOptions();\n }\n\n public allocationIsInvalid(): boolean {\n return (\n this.loadBalancer.splitDescription.allocationDescriptions.reduce(\n (sum, allocationDescription) => sum + allocationDescription.allocation,\n 0,\n ) !== 100\n );\n }\n\n public updateServerGroupOptions(): void {\n this.serverGroupOptions = this.serverGroupsWithoutAllocation();\n }\n\n public showAddButton(): boolean {\n if (this.forPipelineConfig) {\n return true;\n } else {\n return this.serverGroupsWithoutAllocation().length > 0;\n }\n }\n\n public showShardByOptions(): boolean {\n return this.loadBalancer.splitDescription.allocationDescriptions.length > 1 || this.loadBalancer.migrateTraffic;\n }\n\n public initializeAsTextInput(serverGroupName: string): boolean {\n if (this.forPipelineConfig) {\n return !this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name).includes(serverGroupName);\n } else {\n return false;\n }\n }\n\n private serverGroupsWithoutAllocation(): string[] {\n const serverGroupsWithAllocation = this.loadBalancer.splitDescription.allocationDescriptions.map(\n (description) => description.serverGroupName,\n );\n const allServerGroups = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);\n return difference(allServerGroups, serverGroupsWithAllocation);\n }\n}\n\nconst appengineLoadBalancerSettingsComponent: ng.IComponentOptions = {\n bindings: { loadBalancer: '=', forPipelineConfig: '<', application: '<' },\n controller: AppengineLoadBalancerSettingsController,\n templateUrl: require('./basicSettings.component.html'),\n};\n\nexport const APPENGINE_LOAD_BALANCER_BASIC_SETTINGS = 'spinnaker.appengine.loadBalancerSettings.component';\n\nmodule(APPENGINE_LOAD_BALANCER_BASIC_SETTINGS, []).component(\n 'appengineLoadBalancerBasicSettings',\n appengineLoadBalancerSettingsComponent,\n);\n","import type { IComponentOptions, IController } from 'angular';\nimport { module } from 'angular';\nimport { uniq } from 'lodash';\n\nimport type { Application } from '@spinnaker/core';\nimport { AppListExtractor, StageConstants } from '@spinnaker/core';\n\nimport type { IAppengineAllocationDescription } from '../../transformer';\n\nclass AppengineStageAllocationLabelCtrl implements IController {\n public inputViewValue: string;\n private allocationDescription: IAppengineAllocationDescription;\n\n private static mapTargetCoordinateToLabel(targetCoordinate: string): string {\n const target = StageConstants.TARGET_LIST.find((t) => t.val === targetCoordinate);\n if (target) {\n return target.label;\n } else {\n return null;\n }\n }\n\n public $doCheck(): void {\n this.setInputViewValue();\n }\n\n private setInputViewValue(): void {\n switch (this.allocationDescription.locatorType) {\n case 'text':\n this.inputViewValue = this.allocationDescription.serverGroupName;\n break;\n case 'fromExisting':\n this.inputViewValue = this.allocationDescription.serverGroupName;\n break;\n case 'targetCoordinate':\n if (this.allocationDescription.cluster && this.allocationDescription.target) {\n const targetLabel = AppengineStageAllocationLabelCtrl.mapTargetCoordinateToLabel(\n this.allocationDescription.target,\n );\n this.inputViewValue = `${targetLabel} (${this.allocationDescription.cluster})`;\n } else {\n this.inputViewValue = null;\n }\n break;\n default:\n this.inputViewValue = null;\n break;\n }\n }\n}\n\nconst appengineStageAllocationLabel: IComponentOptions = {\n bindings: { allocationDescription: '<' },\n controller: AppengineStageAllocationLabelCtrl,\n template: `<input ng-model=\"$ctrl.inputViewValue\" type=\"text\" class=\"form-control input-sm\" readonly/>`,\n};\n\nclass AppengineStageAllocationConfigurationRowCtrl implements IController {\n public allocationDescription: IAppengineAllocationDescription;\n public serverGroupOptions: string[];\n public targets = StageConstants.TARGET_LIST;\n public clusterList: string[];\n public onAllocationChange: Function;\n private application: Application;\n private region: string;\n private account: string;\n\n public $onInit() {\n const clusterFilter = AppListExtractor.clusterFilterForCredentialsAndRegion(this.account, this.region);\n this.clusterList = AppListExtractor.getClusters([this.application], clusterFilter);\n }\n\n public getServerGroupOptions(): string[] {\n if (this.allocationDescription.serverGroupName) {\n return uniq(this.serverGroupOptions.concat(this.allocationDescription.serverGroupName));\n } else {\n return this.serverGroupOptions;\n }\n }\n\n public onLocatorTypeChange(): void {\n // Prevents pipeline expressions (or non-existent server groups) from entering the dropdown.\n if (!this.serverGroupOptions.includes(this.allocationDescription.serverGroupName)) {\n delete this.allocationDescription.serverGroupName;\n }\n this.onAllocationChange();\n }\n}\n\nconst appengineStageAllocationConfigurationRow: IComponentOptions = {\n bindings: {\n application: '<',\n region: '@',\n account: '@',\n allocationDescription: '<',\n removeAllocation: '&',\n serverGroupOptions: '<',\n onAllocationChange: '&',\n },\n controller: AppengineStageAllocationConfigurationRowCtrl,\n templateUrl: require('./stageAllocationConfigurationRow.component.html'),\n};\n\nexport const APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW =\n 'spinnaker.appengine.stageAllocationConfigurationRow.component';\nmodule(APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW, [])\n .component('appengineStageAllocationConfigurationRow', appengineStageAllocationConfigurationRow)\n .component('appengineStageAllocationLabel', appengineStageAllocationLabel);\n","import { module } from 'angular';\nimport { camelCase, chain, cloneDeep, filter, get, has, reduce } from 'lodash';\n\nimport type {\n Application,\n IInstance,\n IInstanceCounts,\n ILoadBalancer,\n ILoadBalancerUpsertCommand,\n IServerGroup,\n} from '@spinnaker/core';\nimport type { IAppengineLoadBalancer, IAppengineTrafficSplit, ShardBy } from '../domain/index';\n\nexport interface IAppengineAllocationDescription {\n serverGroupName?: string;\n target?: string;\n cluster?: string;\n allocation: number;\n locatorType: 'fromExisting' | 'targetCoordinate' | 'text';\n}\n\nexport interface IAppengineTrafficSplitDescription {\n shardBy: ShardBy;\n allocationDescriptions: IAppengineAllocationDescription[];\n}\n\nexport class AppengineLoadBalancerUpsertDescription implements ILoadBalancerUpsertCommand, IAppengineLoadBalancer {\n public credentials: string;\n public account: string;\n public loadBalancerName: string;\n public name: string;\n public splitDescription: IAppengineTrafficSplitDescription;\n public split?: IAppengineTrafficSplit;\n public migrateTraffic: boolean;\n public region: string;\n public cloudProvider: string;\n public serverGroups?: any[];\n\n public static convertTrafficSplitToTrafficSplitDescription(\n split: IAppengineTrafficSplit,\n ): IAppengineTrafficSplitDescription {\n const allocationDescriptions = reduce(\n split.allocations,\n (acc: IAppengineAllocationDescription[], allocation: number, serverGroupName: string) => {\n return acc.concat({ serverGroupName, allocation, locatorType: 'fromExisting' });\n },\n [],\n );\n\n return { shardBy: split.shardBy, allocationDescriptions };\n }\n\n constructor(loadBalancer: IAppengineLoadBalancer) {\n this.credentials = loadBalancer.account || loadBalancer.credentials;\n this.account = this.credentials;\n this.cloudProvider = loadBalancer.cloudProvider;\n this.loadBalancerName = loadBalancer.name;\n this.name = loadBalancer.name;\n this.region = loadBalancer.region;\n this.migrateTraffic = loadBalancer.migrateTraffic || false;\n this.serverGroups = loadBalancer.serverGroups;\n }\n\n public mapAllocationsToDecimals() {\n this.splitDescription.allocationDescriptions.forEach((description) => {\n description.allocation = description.allocation / 100;\n });\n }\n\n public mapAllocationsToPercentages() {\n this.splitDescription.allocationDescriptions.forEach((description) => {\n // An allocation percent has at most one decimal place.\n description.allocation = Math.round(description.allocation * 1000) / 10;\n });\n }\n}\n\nexport class AppengineLoadBalancerTransformer {\n public static $inject = ['$q'];\n constructor(private $q: ng.IQService) {}\n\n public normalizeLoadBalancer(loadBalancer: ILoadBalancer): PromiseLike<ILoadBalancer> {\n loadBalancer.provider = loadBalancer.type;\n loadBalancer.instanceCounts = this.buildInstanceCounts(loadBalancer.serverGroups);\n loadBalancer.instances = [];\n loadBalancer.serverGroups.forEach((serverGroup) => {\n serverGroup.account = loadBalancer.account;\n serverGroup.region = loadBalancer.region;\n\n if (serverGroup.detachedInstances) {\n serverGroup.detachedInstances = (serverGroup.detachedInstances as any).map((id: string) => ({ id }));\n }\n serverGroup.instances = serverGroup.instances\n .concat(serverGroup.detachedInstances || [])\n .map((instance: any) => this.transformInstance(instance, loadBalancer));\n });\n\n const activeServerGroups = filter(loadBalancer.serverGroups, { isDisabled: false });\n loadBalancer.instances = chain(activeServerGroups).map('instances').flatten().value() as IInstance[];\n return this.$q.resolve(loadBalancer);\n }\n\n public convertLoadBalancerForEditing(\n loadBalancer: IAppengineLoadBalancer,\n application: Application,\n ): PromiseLike<IAppengineLoadBalancer> {\n return application\n .getDataSource('loadBalancers')\n .ready()\n .then(() => {\n const upToDateLoadBalancer = application\n .getDataSource('loadBalancers')\n .data.find((candidate: ILoadBalancer) => {\n return (\n candidate.name === loadBalancer.name &&\n (candidate.account === loadBalancer.account || candidate.account === loadBalancer.credentials)\n );\n });\n\n if (upToDateLoadBalancer) {\n loadBalancer.serverGroups = cloneDeep(upToDateLoadBalancer.serverGroups);\n }\n return loadBalancer;\n });\n }\n\n public convertLoadBalancerToUpsertDescription(\n loadBalancer: IAppengineLoadBalancer,\n ): AppengineLoadBalancerUpsertDescription {\n return new AppengineLoadBalancerUpsertDescription(loadBalancer);\n }\n\n private buildInstanceCounts(serverGroups: IServerGroup[]): IInstanceCounts {\n const instanceCounts: IInstanceCounts = chain(serverGroups)\n .map('instances')\n .flatten()\n .reduce(\n (acc: IInstanceCounts, instance: any) => {\n if (has(instance, 'health.state')) {\n acc[camelCase(instance.health.state)]++;\n }\n return acc;\n },\n { up: 0, down: 0, outOfService: 0, succeeded: 0, failed: 0, starting: 0, unknown: 0 },\n )\n .value();\n\n instanceCounts.outOfService += chain(serverGroups).map('detachedInstances').flatten().value().length;\n return instanceCounts;\n }\n\n private transformInstance(instance: any, loadBalancer: ILoadBalancer) {\n instance.provider = loadBalancer.type;\n instance.account = loadBalancer.account;\n instance.region = loadBalancer.region;\n instance.loadBalancers = [loadBalancer.name];\n const health = instance.health || {};\n instance.healthState = get(instance, 'health.state') || 'OutOfService';\n instance.health = [health];\n\n return instance as IInstance;\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_TRANSFORMER = 'spinnaker.appengine.loadBalancer.transformer.service';\n\nmodule(APPENGINE_LOAD_BALANCER_TRANSFORMER, []).service(\n 'appengineLoadBalancerTransformer',\n AppengineLoadBalancerTransformer,\n);\n","function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","import type { StateService } from '@uirouter/angularjs';\nimport type { IController } from 'angular';\nimport { module } from 'angular';\nimport type { IModalServiceInstance } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { Application } from '@spinnaker/core';\nimport { LoadBalancerWriter, TaskMonitor } from '@spinnaker/core';\n\nimport type { AppengineLoadBalancerTransformer, IAppengineTrafficSplitDescription } from '../../transformer';\nimport { AppengineLoadBalancerUpsertDescription } from '../../transformer';\n\nimport './wizard.less';\n\nclass AppengineLoadBalancerWizardController implements IController {\n public state = { loading: true };\n public loadBalancer: AppengineLoadBalancerUpsertDescription;\n public heading: string;\n public submitButtonLabel: string;\n public taskMonitor: TaskMonitor;\n\n public static $inject = [\n '$scope',\n '$state',\n '$uibModalInstance',\n 'application',\n 'loadBalancer',\n 'isNew',\n 'forPipelineConfig',\n 'appengineLoadBalancerTransformer',\n 'wizardSubFormValidation',\n ];\n constructor(\n public $scope: ng.IScope,\n private $state: StateService,\n private $uibModalInstance: IModalServiceInstance,\n private application: Application,\n loadBalancer: AppengineLoadBalancerUpsertDescription,\n public isNew: boolean,\n private forPipelineConfig: boolean,\n private appengineLoadBalancerTransformer: AppengineLoadBalancerTransformer,\n private wizardSubFormValidation: any,\n ) {\n this.submitButtonLabel = this.forPipelineConfig ? 'Done' : 'Update';\n\n if (this.isNew) {\n this.heading = 'Create New Load Balancer';\n } else {\n this.heading = `Edit ${[\n loadBalancer.name,\n loadBalancer.region,\n loadBalancer.account || loadBalancer.credentials,\n ].join(':')}`;\n this.appengineLoadBalancerTransformer\n .convertLoadBalancerForEditing(loadBalancer, application)\n .then((convertedLoadBalancer) => {\n this.loadBalancer = this.appengineLoadBalancerTransformer.convertLoadBalancerToUpsertDescription(\n convertedLoadBalancer,\n );\n if (loadBalancer.split && !this.loadBalancer.splitDescription) {\n this.loadBalancer.splitDescription = AppengineLoadBalancerUpsertDescription.convertTrafficSplitToTrafficSplitDescription(\n loadBalancer.split,\n );\n } else {\n this.loadBalancer.splitDescription = loadBalancer.splitDescription;\n }\n this.loadBalancer.mapAllocationsToPercentages();\n this.setTaskMonitor();\n this.initializeFormValidation();\n this.state.loading = false;\n });\n }\n }\n\n public submit(): any {\n const description = cloneDeep(this.loadBalancer);\n description.mapAllocationsToDecimals();\n delete description.serverGroups;\n\n if (this.forPipelineConfig) {\n return this.$uibModalInstance.close(description);\n } else {\n return this.taskMonitor.submit(() => {\n return LoadBalancerWriter.upsertLoadBalancer(description, this.application, 'Update');\n });\n }\n }\n\n public cancel(): void {\n this.$uibModalInstance.dismiss();\n }\n\n public showSubmitButton(): boolean {\n return this.wizardSubFormValidation.subFormsAreValid();\n }\n\n private setTaskMonitor(): void {\n this.taskMonitor = new TaskMonitor({\n application: this.application,\n title: 'Updating your load balancer',\n modalInstance: this.$uibModalInstance,\n onTaskComplete: () => this.onTaskComplete(),\n });\n }\n\n private initializeFormValidation(): void {\n this.wizardSubFormValidation\n .config({ form: 'form', scope: this.$scope })\n .register({\n page: 'basic-settings',\n subForm: 'basicSettingsForm',\n validators: [\n {\n watchString: 'ctrl.loadBalancer.splitDescription',\n validator: (splitDescription: IAppengineTrafficSplitDescription): boolean => {\n return (\n splitDescription.allocationDescriptions.reduce(\n (sum, description) => sum + description.allocation,\n 0,\n ) === 100\n );\n },\n watchDeep: true,\n },\n ],\n })\n .register({ page: 'advanced-settings', subForm: 'advancedSettingsForm' });\n }\n\n private onTaskComplete(): void {\n this.application.getDataSource('loadBalancers').refresh();\n this.application.getDataSource('loadBalancers').onNextRefresh(this.$scope, () => this.onApplicationRefresh());\n }\n\n private onApplicationRefresh(): void {\n // If the user has already closed the modal, do not navigate to the new details view\n if ((this.$scope as any).$$destroyed) {\n // $$destroyed is not in the ng.IScope interface\n return;\n }\n\n this.$uibModalInstance.dismiss();\n const newStateParams = {\n name: this.loadBalancer.name,\n accountId: this.loadBalancer.credentials,\n region: this.loadBalancer.region,\n provider: 'appengine',\n };\n\n if (!this.$state.includes('**.loadBalancerDetails')) {\n this.$state.go('.loadBalancerDetails', newStateParams);\n } else {\n this.$state.go('^.loadBalancerDetails', newStateParams);\n }\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_WIZARD_CTRL = 'spinnaker.appengine.loadBalancer.wizard.controller';\n\nmodule(APPENGINE_LOAD_BALANCER_WIZARD_CTRL, []).controller(\n 'appengineLoadBalancerWizardCtrl',\n AppengineLoadBalancerWizardController,\n);\n","import type { StateService } from '@uirouter/angularjs';\nimport type { IController, IScope } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { Application, ILoadBalancer, ILoadBalancerDeleteCommand } from '@spinnaker/core';\nimport { ConfirmationModalService, LoadBalancerWriter } from '@spinnaker/core';\nimport type { IAppengineLoadBalancer } from '../../domain';\n\ninterface ILoadBalancerFromStateParams {\n accountId: string;\n region: string;\n name: string;\n}\n\nclass AppengineLoadBalancerDetailsController implements IController {\n public state = { loading: true };\n private loadBalancerFromParams: ILoadBalancerFromStateParams;\n public loadBalancer: IAppengineLoadBalancer;\n public dispatchRules: string[] = [];\n\n public static $inject = ['$uibModal', '$state', '$scope', 'loadBalancer', 'app'];\n constructor(\n private $uibModal: IModalService,\n private $state: StateService,\n private $scope: IScope,\n loadBalancer: ILoadBalancerFromStateParams,\n private app: Application,\n ) {\n this.loadBalancerFromParams = loadBalancer;\n this.app\n .getDataSource('loadBalancers')\n .ready()\n .then(() => this.extractLoadBalancer());\n }\n\n public editLoadBalancer(): void {\n this.$uibModal.open({\n templateUrl: require('../configure/wizard/wizard.html'),\n controller: 'appengineLoadBalancerWizardCtrl as ctrl',\n size: 'lg',\n resolve: {\n application: () => this.app,\n loadBalancer: () => cloneDeep(this.loadBalancer),\n isNew: () => false,\n forPipelineConfig: () => false,\n },\n });\n }\n\n public deleteLoadBalancer(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Deleting ' + this.loadBalancer.name,\n };\n\n const submitMethod = () => {\n const loadBalancer: ILoadBalancerDeleteCommand = {\n cloudProvider: this.loadBalancer.cloudProvider,\n loadBalancerName: this.loadBalancer.name,\n credentials: this.loadBalancer.account,\n };\n return LoadBalancerWriter.deleteLoadBalancer(loadBalancer, this.app);\n };\n\n ConfirmationModalService.confirm({\n header: 'Really delete ' + this.loadBalancer.name + '?',\n buttonText: 'Delete ' + this.loadBalancer.name,\n body: this.getConfirmationModalBodyHtml(),\n account: this.loadBalancer.account,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n });\n }\n\n public canDeleteLoadBalancer(): boolean {\n return this.loadBalancer.name !== 'default';\n }\n\n private extractLoadBalancer(): void {\n this.loadBalancer = this.app.getDataSource('loadBalancers').data.find((test: ILoadBalancer) => {\n return test.name === this.loadBalancerFromParams.name && test.account === this.loadBalancerFromParams.accountId;\n }) as IAppengineLoadBalancer;\n\n if (this.loadBalancer) {\n this.state.loading = false;\n this.buildDispatchRules();\n this.app.getDataSource('loadBalancers').onRefresh(this.$scope, () => this.extractLoadBalancer());\n } else {\n this.autoClose();\n }\n }\n\n private buildDispatchRules(): void {\n this.dispatchRules = [];\n if (this.loadBalancer && this.loadBalancer.dispatchRules) {\n this.loadBalancer.dispatchRules.forEach((rule) => {\n if (rule.service === this.loadBalancer.name) {\n this.dispatchRules.push(rule.domain + rule.path);\n }\n });\n }\n }\n\n private getConfirmationModalBodyHtml(): string {\n const serverGroupNames = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);\n const hasAny = serverGroupNames ? serverGroupNames.length > 0 : false;\n const hasMoreThanOne = serverGroupNames ? serverGroupNames.length > 1 : false;\n\n // HTML accepted by the confirmationModalService is static (i.e., not managed by angular).\n if (hasAny) {\n if (hasMoreThanOne) {\n const listOfServerGroupNames = serverGroupNames.map((name) => `<li>${name}</li>`).join('');\n return `<div class=\"alert alert-warning\">\n <p>\n Deleting <b>${this.loadBalancer.name}</b> will destroy the following server groups:\n <ul>\n ${listOfServerGroupNames}\n </ul>\n </p>\n </div>\n `;\n } else {\n return `<div class=\"alert alert-warning\">\n <p>\n Deleting <b>${this.loadBalancer.name}</b> will destroy <b>${serverGroupNames[0]}</b>.\n </p>\n </div>\n `;\n }\n } else {\n return null;\n }\n }\n\n private autoClose(): void {\n if (this.$scope.$$destroyed) {\n return;\n } else {\n this.$state.params.allowModalToStayOpen = true;\n this.$state.go('^', null, { location: 'replace' });\n }\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_DETAILS_CTRL = 'spinnaker.appengine.loadBalancerDetails.controller';\nmodule(APPENGINE_LOAD_BALANCER_DETAILS_CTRL, []).controller(\n 'appengineLoadBalancerDetailsCtrl',\n AppengineLoadBalancerDetailsController,\n);\n","import { module } from 'angular';\n\nimport { APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS } from './configure/wizard/advancedSettings.component';\nimport { APPENGINE_ALLOCATION_CONFIGURATION_ROW } from './configure/wizard/allocationConfigurationRow.component';\nimport { APPENGINE_LOAD_BALANCER_BASIC_SETTINGS } from './configure/wizard/basicSettings.component';\nimport { APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW } from './configure/wizard/stageAllocationConfigurationRow.component';\nimport { APPENGINE_LOAD_BALANCER_WIZARD_CTRL } from './configure/wizard/wizard.controller';\nimport { APPENGINE_LOAD_BALANCER_DETAILS_CTRL } from './details/details.controller';\nimport { APPENGINE_LOAD_BALANCER_TRANSFORMER } from './transformer';\n\nexport const APPENGINE_LOAD_BALANCER_MODULE = 'spinnaker.appengine.loadBalancer.module';\n\nmodule(APPENGINE_LOAD_BALANCER_MODULE, [\n APPENGINE_ALLOCATION_CONFIGURATION_ROW,\n APPENGINE_LOAD_BALANCER_DETAILS_CTRL,\n APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS,\n APPENGINE_LOAD_BALANCER_BASIC_SETTINGS,\n APPENGINE_LOAD_BALANCER_TRANSFORMER,\n APPENGINE_LOAD_BALANCER_WIZARD_CTRL,\n APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW,\n]);\n","export class AppengineHealth {\n public static PLATFORM = 'App Engine Service';\n}\n","import type { IController } from 'angular';\n\nimport { AccountService, StageConstants } from '@spinnaker/core';\nimport { AppengineHealth } from '../../common/appengineHealth';\nimport type { IAppengineAccount, IAppengineStageScope } from '../../domain';\n\nexport class AppengineStageCtrl implements IController {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n $scope.platformHealth = AppengineHealth.PLATFORM;\n }\n\n public setStageRegion(): void {\n const selected = this.$scope.accounts.find((account) => account.name === this.$scope.stage.credentials);\n if (selected && selected.name) {\n AccountService.getAccountDetails(selected.name).then((accountDetails: IAppengineAccount) => {\n this.$scope.stage.region = accountDetails.region;\n });\n }\n }\n\n protected setStageCloudProvider(): void {\n this.$scope.stage.cloudProvider = 'appengine';\n }\n\n protected setAccounts(): PromiseLike<void> {\n return AccountService.listAccounts('appengine').then((accounts: IAppengineAccount[]) => {\n this.$scope.accounts = accounts;\n });\n }\n\n protected setTargets(): void {\n this.$scope.targets = StageConstants.TARGET_LIST;\n\n if (!this.$scope.stage.target) {\n this.$scope.stage.target = this.$scope.targets[0].val;\n }\n }\n\n protected setStageCredentials(): void {\n if (!this.$scope.stage.credentials && this.$scope.application.defaultCredentials.appengine) {\n this.$scope.stage.credentials = this.$scope.application.defaultCredentials.appengine;\n }\n }\n}\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineDestroyAsgStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n }\n}\n\nexport const APPENGINE_DESTROY_ASG_STAGE = 'spinnaker.appengine.pipeline.stage.destroyAsgStage';\n\nmodule(APPENGINE_DESTROY_ASG_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n provides: 'destroyServerGroup',\n key: 'destroyServerGroup',\n cloudProvider: 'appengine',\n templateUrl: require('./destroyAsgStage.html'),\n executionStepLabelUrl: require('./destroyAsgStepLabel.html'),\n validators: [\n {\n type: 'targetImpedance',\n message:\n 'This pipeline will attempt to destroy a server group without deploying a new version into the same cluster.',\n },\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineDestroyAsgStageCtrl', AppengineDestroyAsgStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineDisableAsgStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_DISABLE_ASG_STAGE = 'spinnaker.appengine.pipeline.stage.disableAsgStage';\n\nmodule(APPENGINE_DISABLE_ASG_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n provides: 'disableServerGroup',\n key: 'disableServerGroup',\n cloudProvider: 'appengine',\n templateUrl: require('./disableAsgStage.html'),\n executionStepLabelUrl: require('./disableAsgStepLabel.html'),\n validators: [\n {\n type: 'targetImpedance',\n message:\n 'This pipeline will attempt to disable a server group without deploying a new version into the same cluster.',\n },\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineDisableAsgStageCtrl', AppengineDisableAsgStageCtrl);\n","import type { IController } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService, IModalServiceInstance } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { Application, ILoadBalancer } from '@spinnaker/core';\nimport { CloudProviderRegistry } from '@spinnaker/core';\n\nclass AppengineLoadBalancerChoiceModalCtrl implements IController {\n public state = { loading: true };\n public loadBalancers: ILoadBalancer[];\n public selectedLoadBalancer: ILoadBalancer;\n\n public static $inject = ['$uibModal', '$uibModalInstance', 'application'];\n constructor(\n private $uibModal: IModalService,\n private $uibModalInstance: IModalServiceInstance,\n private application: Application,\n ) {\n this.initialize();\n }\n\n public submit(): void {\n const config = CloudProviderRegistry.getValue('appengine', 'loadBalancer');\n const updatedLoadBalancerPromise = this.$uibModal.open({\n templateUrl: config.createLoadBalancerTemplateUrl,\n controller: `${config.createLoadBalancerController} as ctrl`,\n size: 'lg',\n resolve: {\n application: () => this.application,\n loadBalancer: () => cloneDeep(this.selectedLoadBalancer),\n isNew: () => false,\n forPipelineConfig: () => true,\n },\n }).result;\n\n this.$uibModalInstance.close(updatedLoadBalancerPromise);\n }\n\n public cancel(): void {\n this.$uibModalInstance.dismiss();\n }\n\n private initialize(): void {\n this.application\n .getDataSource('loadBalancers')\n .ready()\n .then(() => {\n this.loadBalancers = (this.application.loadBalancers.data as ILoadBalancer[]).filter(\n (candidate) => candidate.cloudProvider === 'appengine',\n );\n\n if (this.loadBalancers.length) {\n this.selectedLoadBalancer = this.loadBalancers[0];\n }\n this.state.loading = false;\n });\n }\n}\n\nexport const APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL = 'spinnaker.appengine.loadBalancerChoiceModal.controller';\nmodule(APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL, []).controller(\n 'appengineLoadBalancerChoiceModelCtrl',\n AppengineLoadBalancerChoiceModalCtrl,\n);\n","import type { IController } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService } from 'angular-ui-bootstrap';\nimport { cloneDeep } from 'lodash';\n\nimport type { ILoadBalancer } from '@spinnaker/core';\nimport { CloudProviderRegistry, Registry } from '@spinnaker/core';\n\nimport { APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL } from './loadBalancerChoice.modal.controller';\n\nclass AppengineEditLoadBalancerStageCtrl implements IController {\n public static $inject = ['$scope', '$uibModal'];\n constructor(public $scope: any, private $uibModal: IModalService) {\n $scope.stage.loadBalancers = $scope.stage.loadBalancers || [];\n $scope.stage.cloudProvider = 'appengine';\n }\n\n public addLoadBalancer(): void {\n this.$uibModal\n .open({\n templateUrl: require('./loadBalancerChoice.modal.html'),\n controller: `appengineLoadBalancerChoiceModelCtrl as ctrl`,\n resolve: {\n application: () => this.$scope.application,\n },\n })\n .result.then((newLoadBalancer: ILoadBalancer) => {\n this.$scope.stage.loadBalancers.push(newLoadBalancer);\n })\n .catch(() => {});\n }\n\n public editLoadBalancer(index: number) {\n const config = CloudProviderRegistry.getValue('appengine', 'loadBalancer');\n this.$uibModal\n .open({\n templateUrl: config.createLoadBalancerTemplateUrl,\n controller: `${config.createLoadBalancerController} as ctrl`,\n size: 'lg',\n resolve: {\n application: () => this.$scope.application,\n loadBalancer: () => cloneDeep(this.$scope.stage.loadBalancers[index]),\n isNew: () => false,\n forPipelineConfig: () => true,\n },\n })\n .result.then((updatedLoadBalancer: ILoadBalancer) => {\n this.$scope.stage.loadBalancers[index] = updatedLoadBalancer;\n })\n .catch(() => {});\n }\n\n public removeLoadBalancer(index: number): void {\n this.$scope.stage.loadBalancers.splice(index, 1);\n }\n}\n\nexport const APPENGINE_EDIT_LOAD_BALANCER_STAGE = 'spinnaker.appengine.pipeline.stage.editLoadBalancerStage';\nmodule(APPENGINE_EDIT_LOAD_BALANCER_STAGE, [APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL])\n .config(() => {\n Registry.pipeline.registerStage({\n label: 'Edit Load Balancer',\n description: 'Edits a load balancer',\n key: 'upsertAppEngineLoadBalancers',\n cloudProvider: 'appengine',\n templateUrl: require('./editLoadBalancerStage.html'),\n executionDetailsUrl: require('./editLoadBalancerExecutionDetails.html'),\n executionConfigSections: ['editLoadBalancerConfig', 'taskStatus'],\n controller: 'appengineEditLoadBalancerStageCtrl',\n controllerAs: 'editLoadBalancerStageCtrl',\n validators: [],\n });\n })\n .controller('appengineEditLoadBalancerStageCtrl', AppengineEditLoadBalancerStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineEnableAsgStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(protected $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_ENABLE_ASG_STAGE = 'spinnaker.appengine.pipeline.stage.enableAsgStage';\n\nmodule(APPENGINE_ENABLE_ASG_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n provides: 'enableServerGroup',\n key: 'enableServerGroup',\n cloudProvider: 'appengine',\n templateUrl: require('./enableAsgStage.html'),\n executionStepLabelUrl: require('./enableAsgStepLabel.html'),\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineEnableAsgStageCtrl', AppengineEnableAsgStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport type { IAppengineStage, IAppengineStageScope } from '../../../domain/index';\n\ninterface IAppengineShrinkClusterStage extends IAppengineStage {\n shrinkToSize: number;\n allowDeleteActive: boolean;\n retainLargerOverNewer: string | boolean;\n}\n\nclass AppengineShrinkClusterStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(public $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n super.setStageCloudProvider();\n super.setStageCredentials();\n\n const stage = $scope.stage as IAppengineShrinkClusterStage;\n if (stage.shrinkToSize === undefined) {\n stage.shrinkToSize = 1;\n }\n\n if (stage.allowDeleteActive === undefined) {\n stage.allowDeleteActive = false;\n }\n\n if (stage.retainLargerOverNewer === undefined) {\n stage.retainLargerOverNewer = 'false';\n }\n\n stage.retainLargerOverNewer = stage.retainLargerOverNewer.toString();\n }\n\n public pluralize(str: string, val: number): string {\n return val === 1 ? str : str + 's';\n }\n}\n\nexport const APPENGINE_SHRINK_CLUSTER_STAGE = 'spinnaker.appengine.pipeline.stage.shrinkClusterStage';\n\nmodule(APPENGINE_SHRINK_CLUSTER_STAGE, [])\n .config(function () {\n Registry.pipeline.registerStage({\n provides: 'shrinkCluster',\n key: 'shrinkCluster',\n cloudProvider: 'appengine',\n templateUrl: require('./shrinkClusterStage.html'),\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'shrinkToSize', fieldLabel: 'shrink to [X] Server Groups' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n });\n })\n .controller('appengineShrinkClusterStageCtrl', AppengineShrinkClusterStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain';\n\nclass AppengineStartServerGroupStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(public $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_START_SERVER_GROUP_STAGE = 'spinnaker.appengine.pipeline.stage.startServerGroupStage';\n\nmodule(APPENGINE_START_SERVER_GROUP_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n label: 'Start Server Group',\n description: 'Starts a server group.',\n key: 'startAppEngineServerGroup',\n templateUrl: require('./startServerGroupStage.html'),\n executionDetailsUrl: require('./startServerGroupExecutionDetails.html'),\n executionConfigSections: ['startServerGroupConfig', 'taskStatus'],\n executionStepLabelUrl: require('./startServerGroupStepLabel.html'),\n controller: 'appengineStartServerGroupStageCtrl',\n controllerAs: 'startServerGroupStageCtrl',\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n cloudProvider: 'appengine',\n });\n })\n .controller('appengineStartServerGroupStageCtrl', AppengineStartServerGroupStageCtrl);\n","import { module } from 'angular';\n\nimport { Registry } from '@spinnaker/core';\n\nimport { AppengineStageCtrl } from '../appengineStage.controller';\nimport { AppengineHealth } from '../../../common/appengineHealth';\nimport type { IAppengineStageScope } from '../../../domain/index';\n\nclass AppengineStopServerGroupStageCtrl extends AppengineStageCtrl {\n public static $inject = ['$scope'];\n constructor(public $scope: IAppengineStageScope) {\n super($scope);\n\n super.setAccounts().then(() => {\n super.setStageRegion();\n });\n\n super.setStageCloudProvider();\n super.setTargets();\n super.setStageCredentials();\n\n if (\n $scope.stage.isNew &&\n $scope.application.attributes.platformHealthOnlyShowOverride &&\n $scope.application.attributes.platformHealthOnly\n ) {\n $scope.stage.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_STOP_SERVER_GROUP_STAGE = 'spinnaker.appengine.pipeline.stage.stopServerGroupStage';\n\nmodule(APPENGINE_STOP_SERVER_GROUP_STAGE, [])\n .config(() => {\n Registry.pipeline.registerStage({\n label: 'Stop Server Group',\n description: 'Stops a server group.',\n key: 'stopAppEngineServerGroup',\n templateUrl: require('./stopServerGroupStage.html'),\n executionDetailsUrl: require('./stopServerGroupExecutionDetails.html'),\n executionConfigSections: ['stopServerGroupConfig', 'taskStatus'],\n executionStepLabelUrl: require('./stopServerGroupStepLabel.html'),\n controller: 'appengineStopServerGroupStageCtrl',\n controllerAs: 'stopServerGroupStageCtrl',\n validators: [\n { type: 'requiredField', fieldName: 'cluster' },\n { type: 'requiredField', fieldName: 'target' },\n { type: 'requiredField', fieldName: 'credentials', fieldLabel: 'account' },\n ],\n cloudProvider: 'appengine',\n });\n })\n .controller('appengineStopServerGroupStageCtrl', AppengineStopServerGroupStageCtrl);\n","import { module } from 'angular';\n\nimport { APPENGINE_DESTROY_ASG_STAGE } from './stages/destroyAsg/appengineDestroyAsgStage';\nimport { APPENGINE_DISABLE_ASG_STAGE } from './stages/disableAsg/appengineDisableAsgStage';\nimport { APPENGINE_EDIT_LOAD_BALANCER_STAGE } from './stages/editLoadBalancer/appengineEditLoadBalancerStage';\nimport { APPENGINE_ENABLE_ASG_STAGE } from './stages/enableAsg/appengineEnableAsgStage';\nimport { APPENGINE_SHRINK_CLUSTER_STAGE } from './stages/shrinkCluster/appengineShrinkClusterStage';\nimport { APPENGINE_START_SERVER_GROUP_STAGE } from './stages/startServerGroup/appengineStartServerGroupStage';\nimport { APPENGINE_STOP_SERVER_GROUP_STAGE } from './stages/stopServerGroup/appengineStopServerGroupStage';\n\nexport const APPENGINE_PIPELINE_MODULE = 'spinnaker.appengine.pipeline.module';\nmodule(APPENGINE_PIPELINE_MODULE, [\n APPENGINE_DESTROY_ASG_STAGE,\n APPENGINE_DISABLE_ASG_STAGE,\n APPENGINE_EDIT_LOAD_BALANCER_STAGE,\n APPENGINE_ENABLE_ASG_STAGE,\n APPENGINE_SHRINK_CLUSTER_STAGE,\n APPENGINE_START_SERVER_GROUP_STAGE,\n APPENGINE_STOP_SERVER_GROUP_STAGE,\n]);\n","import type { FormikProps } from 'formik';\nimport { get } from 'lodash';\nimport React from 'react';\nimport { from as observableFrom, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nimport type { Application, IAccount, IServerGroup, IServerGroupFilter, IStage } from '@spinnaker/core';\nimport { AppListExtractor, FormikFormField, ReactSelectInput } from '@spinnaker/core';\n\nexport interface IFormikAccountRegionSelectorProps {\n accounts: IAccount[];\n application: Application;\n cloudProvider: string;\n componentName?: string;\n credentialsField?: string;\n formik: FormikProps<IStage>;\n}\n\nexport interface IFormikAccountRegionSelectorState {\n availableRegions: string[];\n cloudProvider: string;\n componentName: string;\n credentialsField: string;\n}\n\nexport class FormikAccountRegionSelector extends React.Component<\n IFormikAccountRegionSelectorProps,\n IFormikAccountRegionSelectorState\n> {\n private destroy$ = new Subject();\n\n constructor(props: IFormikAccountRegionSelectorProps) {\n super(props);\n const credentialsField = props.credentialsField || 'credentials';\n this.state = {\n availableRegions: [],\n cloudProvider: props.cloudProvider,\n componentName: props.componentName || '',\n credentialsField,\n };\n }\n\n public componentDidMount(): void {\n const { componentName, formik } = this.props;\n const { credentialsField } = this.state;\n const credentials = get(\n formik.values,\n componentName ? `${componentName}.${credentialsField}` : `${credentialsField}`,\n undefined,\n );\n this.setRegionList(credentials);\n }\n\n public componentWillUnmount(): void {\n this.destroy$.next();\n }\n\n private setRegionList = (credentials: string): void => {\n const { application } = this.props;\n const accountFilter: IServerGroupFilter = (serverGroup: IServerGroup) =>\n serverGroup ? serverGroup.account === credentials : true;\n observableFrom(application.ready())\n .pipe(takeUntil(this.destroy$))\n .subscribe(() => {\n const availableRegions = AppListExtractor.getRegions([application], accountFilter);\n availableRegions.sort();\n this.setState({ availableRegions });\n });\n };\n\n public accountChanged = (credentials: string): void => {\n this.setRegionList(credentials);\n };\n\n public render() {\n const { accounts } = this.props;\n const { credentialsField, availableRegions, componentName } = this.state;\n return (\n <div className=\"col-md-9\">\n <div className=\"sp-margin-m-bottom\">\n <FormikFormField\n name={componentName ? `${componentName}.${credentialsField}` : `${credentialsField}`}\n label=\"Account\"\n input={(props) => (\n <ReactSelectInput\n {...props}\n stringOptions={accounts && accounts.map((acc: IAccount) => acc.name)}\n clearable={false}\n />\n )}\n onChange={this.accountChanged}\n required={true}\n />\n </div>\n\n <div className=\"sp-margin-m-bottom\">\n <FormikFormField\n name={componentName ? `${componentName}.region` : 'region'}\n label=\"Region\"\n input={(props) => <ReactSelectInput {...props} stringOptions={availableRegions} clearable={false} />}\n required={true}\n />\n </div>\n </div>\n );\n }\n}\n","import React from 'react';\nimport { from as observableFrom, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nimport type { IAccount, IArtifact, IExpectedArtifact, IFormikStageConfigInjectedProps } from '@spinnaker/core';\nimport {\n AccountService,\n ArtifactTypePatterns,\n excludeAllTypesExcept,\n StageArtifactSelectorDelegate,\n} from '@spinnaker/core';\nimport { FormikAccountRegionSelector } from '../../../common/FormikAccountRegionSelector';\n\nexport interface IAppEngineDeployConfigSettingsState {\n accounts: IAccount[];\n}\n\nexport class DeployAppengineConfigForm extends React.Component<\n IFormikStageConfigInjectedProps,\n IAppEngineDeployConfigSettingsState\n> {\n private static readonly excludedArtifactTypes = excludeAllTypesExcept(\n ArtifactTypePatterns.BITBUCKET_FILE,\n ArtifactTypePatterns.CUSTOM_OBJECT,\n ArtifactTypePatterns.EMBEDDED_BASE64,\n ArtifactTypePatterns.GCS_OBJECT,\n ArtifactTypePatterns.GITHUB_FILE,\n ArtifactTypePatterns.GITLAB_FILE,\n ArtifactTypePatterns.S3_OBJECT,\n ArtifactTypePatterns.HTTP_FILE,\n ArtifactTypePatterns.ORACLE_OBJECT,\n );\n\n private destroy$ = new Subject();\n public state: IAppEngineDeployConfigSettingsState = {\n accounts: [],\n };\n\n public componentDidMount() {\n observableFrom(AccountService.listAccounts('appengine'))\n .pipe(takeUntil(this.destroy$))\n .subscribe((accounts) => this.setState({ accounts }));\n }\n\n private onTemplateArtifactEdited = (artifact: IArtifact, name: string) => {\n this.props.formik.setFieldValue(`${name}.id`, null);\n this.props.formik.setFieldValue(`${name}.artifact`, artifact);\n this.props.formik.setFieldValue(`${name}.account`, artifact.artifactAccount);\n };\n\n private onTemplateArtifactSelected = (id: string, name: string) => {\n this.props.formik.setFieldValue(`${name}.id`, id);\n this.props.formik.setFieldValue(`${name}.artifact`, null);\n };\n\n private removeInputArtifact = (name: string) => {\n this.props.formik.setFieldValue(name, null);\n };\n\n private getInputArtifact = (stage: any, name: string) => {\n if (!stage[name]) {\n return {\n account: '',\n id: '',\n };\n } else {\n return stage[name];\n }\n };\n\n public render() {\n const stage = this.props.formik.values;\n const accounts = this.state.accounts;\n return (\n <div>\n <div className=\"col-md-offset-0 col-md-9\">\n <h4>Basic Settings</h4>\n </div>\n <div>\n <FormikAccountRegionSelector\n componentName={''}\n accounts={accounts}\n application={this.props.application}\n cloudProvider={'appengine'}\n credentialsField={'account'}\n formik={this.props.formik}\n />\n </div>\n <div className=\"col-md-offset-0 col-md-9\">\n <h4>Configuration Settings</h4>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'cronArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'cronArtifact').id}\n label=\"Cron Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'cronArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'cronArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('cronArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'dispatchArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'dispatchArtifact').id}\n label=\"Dispatch Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'dispatchArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'dispatchArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('dispatchArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'indexArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'indexArtifact').id}\n label=\"Index Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'indexArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'indexArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('indexArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n <div>\n <div className=\"col-md-offset-1 col-md-9\">\n <StageArtifactSelectorDelegate\n artifact={this.getInputArtifact(stage, 'queueArtifact').artifact}\n excludedArtifactTypePatterns={DeployAppengineConfigForm.excludedArtifactTypes}\n expectedArtifactId={this.getInputArtifact(stage, 'queueArtifact').id}\n label=\"Queue Artifact\"\n onArtifactEdited={(artifact) => {\n this.onTemplateArtifactEdited(artifact, 'queueArtifact');\n }}\n helpKey={''}\n onExpectedArtifactSelected={(artifact: IExpectedArtifact) =>\n this.onTemplateArtifactSelected(artifact.id, 'queueArtifact')\n }\n pipeline={this.props.pipeline}\n stage={stage}\n />\n </div>\n <div className=\"col-md-1\">\n <div className=\"form-control-static\">\n <button onClick={() => this.removeInputArtifact('queueArtifact')}>\n <span className=\"glyphicon glyphicon-trash\" />\n <span className=\"sr-only\">Remove field</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n }\n}\n","import type { FormikErrors } from 'formik';\nimport { cloneDeep } from 'lodash';\nimport React from 'react';\n\nimport type { IStage, IStageConfigProps } from '@spinnaker/core';\nimport { FormikStageConfig, FormValidator } from '@spinnaker/core';\n\nimport { DeployAppengineConfigForm } from './DeployAppengineConfigForm';\n\nexport function DeployAppengineConfigurationConfig({ application, pipeline, stage, updateStage }: IStageConfigProps) {\n const stageWithDefaults = React.useMemo(() => {\n return {\n ...cloneDeep(stage),\n };\n }, []);\n\n return (\n <FormikStageConfig\n application={application}\n onChange={updateStage}\n pipeline={pipeline}\n stage={stageWithDefaults}\n validate={validateDeployAppengineConfigurationStage}\n render={(props) => <DeployAppengineConfigForm {...props} />}\n />\n );\n}\n\nexport function validateDeployAppengineConfigurationStage(stage: IStage): FormikErrors<IStage> {\n const formValidator = new FormValidator(stage);\n formValidator.field('account').required();\n formValidator.field('region').required();\n return formValidator.validateForm();\n}\n","import { ExecutionArtifactTab, ExecutionDetailsTasks, Registry } from '@spinnaker/core';\n\nimport {\n DeployAppengineConfigurationConfig,\n validateDeployAppengineConfigurationStage,\n} from './DeployAppengineConfigurationConfig';\n\nexport const DEPLOY_APPENGINE_CONFIG_STAGE_KEY = 'deployAppEngineConfiguration';\n\nRegistry.pipeline.registerStage({\n label: 'Deploy App Engine Configuration',\n description: 'Deploy index, dispatch, cron, and queue configuration to App Engine.',\n key: DEPLOY_APPENGINE_CONFIG_STAGE_KEY,\n component: DeployAppengineConfigurationConfig,\n producesArtifacts: false,\n cloudProvider: 'appengine',\n executionDetailsSections: [ExecutionDetailsTasks, ExecutionArtifactTab],\n validateFn: validateDeployAppengineConfigurationStage,\n});\n","import type { IProviderSettings } from '@spinnaker/core';\nimport { SETTINGS } from '@spinnaker/core';\n\nexport interface IAppengineProviderSettings extends IProviderSettings {\n defaults: {\n account?: string;\n };\n}\n\nexport const AppengineProviderSettings: IAppengineProviderSettings = (SETTINGS.providers\n .appengine as IAppengineProviderSettings) || { defaults: {} };\nif (AppengineProviderSettings) {\n AppengineProviderSettings.resetToOriginal = SETTINGS.resetProvider('appengine');\n}\n","import type { IQService } from 'angular';\nimport { module } from 'angular';\n\nimport type {\n Application,\n IArtifact,\n IArtifactAccountPair,\n IBuildTrigger,\n IExpectedArtifact,\n IGitTrigger,\n IPipeline,\n IStage,\n} from '@spinnaker/core';\nimport { AccountService, StorageAccountReader } from '@spinnaker/core';\nimport { AppengineProviderSettings } from '../../appengine.settings';\nimport type {\n GitCredentialType,\n IAppengineAccount,\n IAppengineGitTrigger,\n IAppengineJenkinsTrigger,\n IAppengineServerGroup,\n} from '../../domain';\n\nimport type { AppengineDeployDescription } from '../transformer';\n\nexport interface IAppengineServerGroupCommand {\n application?: string;\n stack?: string;\n freeFormDetails?: string;\n configFilepaths?: string[];\n configFiles?: string[];\n configArtifacts?: IArtifactAccountPair[];\n applicationDirectoryRoot: string;\n branch?: string;\n repositoryUrl?: string;\n credentials: string;\n region: string;\n selectedProvider: string;\n promote?: boolean;\n stopPreviousVersion?: boolean;\n suppressVersionString?: boolean;\n type?: string;\n backingData: any;\n viewState: IViewState;\n strategy?: string;\n strategyApplication?: string;\n strategyPipeline?: string;\n fromTrigger?: boolean;\n trigger?: IAppengineGitTrigger | IAppengineJenkinsTrigger;\n gitCredentialType?: GitCredentialType;\n storageAccountName?: string; // GCS only\n interestingHealthProviderNames: string[];\n fromArtifact: boolean;\n expectedArtifactId: string;\n expectedArtifact?: IArtifact;\n sourceType: string;\n containerImageUrl?: string;\n}\n\nexport enum AppengineSourceType {\n GCS = 'gcs',\n GIT = 'git',\n ARTIFACT = 'artifact',\n CONTAINER_IMAGE = 'containerImage',\n}\n\nexport interface IViewState {\n mode: string;\n submitButtonLabel: string;\n disableStrategySelection: boolean;\n stage?: IStage;\n pipeline?: IPipeline;\n}\n\nexport class AppengineServerGroupCommandBuilder {\n private static getTriggerOptions(pipeline: IPipeline): Array<IAppengineGitTrigger | IAppengineJenkinsTrigger> {\n return (pipeline.triggers || [])\n .filter((trigger) => trigger.type === 'git' || trigger.type === 'jenkins' || trigger.type === 'travis')\n .map((trigger: IGitTrigger | IBuildTrigger) => {\n if (trigger.type === 'git') {\n return {\n source: trigger.source,\n project: trigger.project,\n slug: trigger.slug,\n branch: trigger.branch,\n type: 'git',\n };\n } else {\n return { master: trigger.master, job: trigger.job, type: trigger.type };\n }\n });\n }\n\n private static getExpectedArtifacts(pipeline: IPipeline): IExpectedArtifact[] {\n return pipeline.expectedArtifacts || [];\n }\n\n public static $inject = ['$q'];\n constructor(private $q: IQService) {}\n\n public buildNewServerGroupCommand(\n app: Application,\n selectedProvider: string,\n mode = 'create',\n ): PromiseLike<IAppengineServerGroupCommand> {\n if (selectedProvider == null) {\n selectedProvider = 'appengine';\n }\n const dataToFetch = {\n accounts: AccountService.getAllAccountDetailsForProvider('appengine'),\n storageAccounts: StorageAccountReader.getStorageAccounts(),\n };\n\n const viewState: IViewState = {\n mode,\n submitButtonLabel: this.getSubmitButtonLabel(mode),\n disableStrategySelection: mode === 'create',\n };\n\n return this.$q.all(dataToFetch).then((backingData: any) => {\n const credentials = this.getCredentials(backingData.accounts);\n const region = this.getRegion(backingData.accounts, credentials);\n\n return {\n application: app.name,\n backingData,\n viewState,\n fromArtifact: false,\n credentials,\n region,\n selectedProvider,\n interestingHealthProviderNames: [],\n sourceType: AppengineSourceType.GIT,\n } as IAppengineServerGroupCommand;\n });\n }\n\n public buildServerGroupCommandFromExisting(\n app: Application,\n serverGroup: IAppengineServerGroup,\n ): PromiseLike<IAppengineServerGroupCommand> {\n return this.buildNewServerGroupCommand(app, 'appengine', 'clone').then((command) => {\n command.stack = serverGroup.stack;\n command.freeFormDetails = serverGroup.detail;\n return command;\n });\n }\n\n public buildNewServerGroupCommandForPipeline(\n _stage: IStage,\n pipeline: IPipeline,\n ): PromiseLike<{\n viewState: {\n stage: IStage;\n pipeline: IPipeline;\n };\n backingData: {\n triggerOptions: Array<IAppengineGitTrigger | IAppengineJenkinsTrigger>;\n expectedArtifacts: IExpectedArtifact[];\n };\n }> {\n // We can't copy server group configuration for App Engine, and can't build the full command here because we don't have\n // access to the application.\n return this.$q.when({\n viewState: {\n pipeline,\n stage: _stage,\n },\n backingData: {\n triggerOptions: AppengineServerGroupCommandBuilder.getTriggerOptions(pipeline),\n expectedArtifacts: AppengineServerGroupCommandBuilder.getExpectedArtifacts(pipeline),\n },\n });\n }\n\n public buildServerGroupCommandFromPipeline(\n app: Application,\n cluster: AppengineDeployDescription,\n _stage: IStage,\n pipeline: IPipeline,\n ): PromiseLike<IAppengineServerGroupCommand> {\n return this.buildNewServerGroupCommand(app, 'appengine', 'editPipeline').then(\n (command: IAppengineServerGroupCommand) => {\n command = {\n ...command,\n ...cluster,\n backingData: {\n ...command.backingData,\n triggerOptions: AppengineServerGroupCommandBuilder.getTriggerOptions(pipeline),\n expectedArtifacts: AppengineServerGroupCommandBuilder.getExpectedArtifacts(pipeline),\n },\n credentials: cluster.account || command.credentials,\n viewState: {\n ...command.viewState,\n stage: _stage,\n pipeline,\n },\n } as IAppengineServerGroupCommand;\n return command;\n },\n );\n }\n\n private getCredentials(accounts: IAppengineAccount[]): string {\n const accountNames: string[] = (accounts || []).map((account) => account.name);\n const defaultCredentials: string = AppengineProviderSettings.defaults.account;\n\n return accountNames.includes(defaultCredentials) ? defaultCredentials : accountNames[0];\n }\n\n private getRegion(accounts: IAppengineAccount[], credentials: string): string {\n const account = accounts.find((_account) => _account.name === credentials);\n return account ? account.region : null;\n }\n\n private getSubmitButtonLabel(mode: string): string {\n switch (mode) {\n case 'createPipeline':\n return 'Add';\n case 'editPipeline':\n return 'Done';\n case 'clone':\n return 'Clone';\n default:\n return 'Create';\n }\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_COMMAND_BUILDER = 'spinnaker.appengine.serverGroupCommandBuilder.service';\n\nmodule(APPENGINE_SERVER_GROUP_COMMAND_BUILDER, []).service(\n 'appengineServerGroupCommandBuilder',\n AppengineServerGroupCommandBuilder,\n);\n","import type { StateService } from '@uirouter/angularjs';\nimport type { IController, IControllerService, IScope } from 'angular';\nimport { extend, module } from 'angular';\nimport { set } from 'lodash';\n\nimport type { IArtifact, IExpectedArtifact } from '@spinnaker/core';\nimport {\n ArtifactTypePatterns,\n excludeAllTypesExcept,\n ExpectedArtifactSelectorViewController,\n NgAppEngineDeployArtifactDelegate,\n} from '@spinnaker/core';\nimport type { GitCredentialType, IAppengineAccount } from '../../../domain/index';\n\nimport type { IAppengineServerGroupCommand } from '../serverGroupCommandBuilder.service';\nimport { AppengineSourceType } from '../serverGroupCommandBuilder.service';\n\ninterface IAppengineBasicSettingsScope extends IScope {\n command: IAppengineServerGroupCommand;\n}\n\nclass AppengineServerGroupBasicSettingsCtrl implements IController {\n public static $inject = ['$scope', '$state', '$controller', '$uibModalStack'];\n\n constructor(\n public $scope: IAppengineBasicSettingsScope,\n $state: StateService,\n $controller: IControllerService,\n $uibModalStack: any,\n ) {\n extend(\n this,\n $controller('BasicSettingsMixin', {\n $scope,\n imageReader: null,\n $uibModalStack,\n $state,\n }),\n );\n\n if (!this.$scope.command.gitCredentialType) {\n this.onAccountChange();\n }\n\n this.$scope.containerArtifactDelegate = new NgAppEngineDeployArtifactDelegate($scope, [\n ArtifactTypePatterns.DOCKER_IMAGE,\n ]);\n this.$scope.containerArtifactController = new ExpectedArtifactSelectorViewController(\n this.$scope.containerArtifactDelegate,\n );\n this.$scope.gcsArtifactDelegate = new NgAppEngineDeployArtifactDelegate($scope, [ArtifactTypePatterns.GCS_OBJECT]);\n this.$scope.gcsArtifactController = new ExpectedArtifactSelectorViewController(this.$scope.gcsArtifactDelegate);\n }\n\n public isGitSource(): boolean {\n return this.$scope.command.sourceType === AppengineSourceType.GIT;\n }\n\n public isGcsSource(): boolean {\n return this.$scope.command.sourceType === AppengineSourceType.GCS;\n }\n\n public isContainerImageSource(): boolean {\n return this.$scope.command.sourceType === AppengineSourceType.CONTAINER_IMAGE;\n }\n\n public toggleResolveViaTrigger(): void {\n this.$scope.command.fromTrigger = !this.$scope.command.fromTrigger;\n delete this.$scope.command.trigger;\n delete this.$scope.command.branch;\n }\n\n public onTriggerChange(): void {\n set(this, '$scope.command.trigger.matchBranchOnRegex', undefined);\n }\n\n public onAccountChange(): void {\n const account = this.findAccountInBackingData();\n if (account) {\n this.$scope.command.gitCredentialType = this.getSupportedGitCredentialTypes()[0];\n this.$scope.command.region = account.region;\n } else {\n this.$scope.command.gitCredentialType = 'NONE';\n delete this.$scope.command.region;\n }\n }\n\n public getSupportedGitCredentialTypes(): GitCredentialType[] {\n const account = this.findAccountInBackingData();\n if (account && account.supportedGitCredentialTypes) {\n return account.supportedGitCredentialTypes;\n } else {\n return ['NONE'];\n }\n }\n\n public humanReadableGitCredentialType(type: GitCredentialType): string {\n switch (type) {\n case 'HTTPS_USERNAME_PASSWORD':\n return 'HTTPS with username and password';\n case 'HTTPS_GITHUB_OAUTH_TOKEN':\n return 'HTTPS with Github OAuth token';\n case 'SSH':\n return 'SSH';\n case 'NONE':\n return 'No credentials';\n default:\n return 'No credentials';\n }\n }\n\n public readonly excludedGcsArtifactTypes = excludeAllTypesExcept(ArtifactTypePatterns.GCS_OBJECT);\n public readonly excludedContainerArtifactTypes = excludeAllTypesExcept(ArtifactTypePatterns.DOCKER_IMAGE);\n\n public onExpectedArtifactEdited = (artifact: IArtifact): void => {\n this.$scope.$applyAsync(() => {\n this.$scope.command.expectedArtifactId = null;\n this.$scope.command.expectedArtifact = artifact;\n });\n };\n\n public onExpectedArtifactSelected = (expectedArtifact: IExpectedArtifact): void => {\n this.onChangeExpectedArtifactId(expectedArtifact.id);\n };\n\n public onChangeExpectedArtifactId = (artifactId: string): void => {\n this.$scope.$applyAsync(() => {\n this.$scope.command.expectedArtifactId = artifactId;\n this.$scope.command.expectedArtifact = null;\n });\n };\n\n public onExpectedArtifactAccountSelected = (accountName: string): void => {\n this.$scope.$applyAsync(() => {\n this.$scope.command.storageAccountName = accountName;\n });\n };\n\n private findAccountInBackingData(): IAppengineAccount {\n return this.$scope.command.backingData.accounts.find((account: IAppengineAccount) => {\n return this.$scope.command.credentials === account.name;\n });\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL = 'spinnaker.appengine.basicSettings.controller';\n\nmodule(APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL, []).controller(\n 'appengineServerGroupBasicSettingsCtrl',\n AppengineServerGroupBasicSettingsCtrl,\n);\n","import type { IController, IScope } from 'angular';\nimport { module } from 'angular';\n\nimport type { IArtifact, IArtifactAccount, IArtifactAccountPair } from '@spinnaker/core';\nimport {\n AccountService,\n ExpectedArtifactSelectorViewController,\n NgAppengineConfigArtifactDelegate,\n} from '@spinnaker/core';\n\nimport { AppengineSourceType } from '../serverGroupCommandBuilder.service';\n\nimport './serverGroupWizard.less';\n\nexport interface IAppengineConfigFileConfigurerCtrlCommand {\n configFiles: string[];\n configArtifacts: ConfigArtifact[];\n sourceType: string;\n}\n\nclass ConfigArtifact implements IArtifactAccountPair {\n public $scope: IScope;\n public controller: ExpectedArtifactSelectorViewController;\n public delegate: NgAppengineConfigArtifactDelegate;\n public id: string;\n public account: string;\n public artifact?: IArtifact;\n\n constructor($scope: IScope, pair: IArtifactAccountPair = { id: '', account: '' }) {\n const unserializable = { configurable: false, enumerable: false, writable: false };\n this.id = pair?.id;\n this.account = pair.account || pair?.artifact?.artifactAccount;\n this.artifact = pair?.artifact;\n Object.defineProperty(this, '$scope', { ...unserializable, value: $scope });\n const delegate = new NgAppengineConfigArtifactDelegate(this);\n const controller = new ExpectedArtifactSelectorViewController(delegate);\n Object.defineProperty(this, 'delegate', { ...unserializable, value: delegate });\n Object.defineProperty(this, 'controller', { ...unserializable, value: controller });\n }\n}\n\nclass AppengineConfigFileConfigurerCtrl implements IController {\n private artifactAccounts: IArtifactAccount[] = [];\n public command: IAppengineConfigFileConfigurerCtrlCommand;\n\n public static $inject = ['$scope'];\n constructor(public $scope: IScope) {}\n\n public $onInit(): void {\n if (!this.command.configFiles) {\n this.command.configFiles = [];\n }\n if (!this.command.configArtifacts) {\n this.command.configArtifacts = [];\n }\n if (!this.$scope.command) {\n this.$scope.command = this.command;\n }\n this.command.configArtifacts = this.command.configArtifacts.map((artifactAccountPair) => {\n return new ConfigArtifact(this.$scope, artifactAccountPair);\n });\n AccountService.getArtifactAccounts().then((accounts: IArtifactAccount[]) => {\n this.artifactAccounts = accounts;\n this.command.configArtifacts.forEach((a: ConfigArtifact) => {\n a.delegate.setAccounts(accounts);\n a.controller.updateAccounts(a.delegate.getSelectedExpectedArtifact());\n });\n });\n }\n\n public addConfigFile(): void {\n this.command.configFiles.push('');\n }\n\n public addConfigArtifact(): void {\n const artifact = new ConfigArtifact(this.$scope, { id: '', account: '' });\n artifact.delegate.setAccounts(this.artifactAccounts);\n artifact.controller.updateAccounts(artifact.delegate.getSelectedExpectedArtifact());\n this.command.configArtifacts.push(artifact);\n }\n\n public deleteConfigFile(index: number): void {\n this.command.configFiles.splice(index, 1);\n }\n\n public deleteConfigArtifact(index: number): void {\n this.command.configArtifacts.splice(index, 1);\n }\n\n public mapTabToSpaces(event: any) {\n if (event.which === 9) {\n event.preventDefault();\n const cursorPosition = event.target.selectionStart;\n const inputValue = event.target.value;\n event.target.value = `${inputValue.substring(0, cursorPosition)} ${inputValue.substring(cursorPosition)}`;\n event.target.selectionStart += 2;\n }\n }\n\n public isContainerImageSource(): boolean {\n return this.command.sourceType === AppengineSourceType.CONTAINER_IMAGE;\n }\n\n public updateConfigArtifacts = (configArtifacts: ConfigArtifact[]): void => {\n this.$scope.$applyAsync(() => {\n this.command.configArtifacts = configArtifacts;\n });\n };\n}\n\nconst appengineConfigFileConfigurerComponent: ng.IComponentOptions = {\n bindings: { command: '=' },\n controller: AppengineConfigFileConfigurerCtrl,\n templateUrl: require('./configFiles.component.html'),\n};\n\nexport const APPENGINE_CONFIG_FILE_CONFIGURER = 'spinnaker.appengine.configFileConfigurer.component';\nmodule(APPENGINE_CONFIG_FILE_CONFIGURER, []).component(\n 'appengineConfigFileConfigurer',\n appengineConfigFileConfigurerComponent,\n);\n","import { module } from 'angular';\n\nconst appengineDynamicBranchLabelComponent: ng.IComponentOptions = {\n bindings: { trigger: '<' },\n template: `\n <span ng-if=\"$ctrl.trigger.type === 'git'\">\n Resolved at runtime by <b>{{$ctrl.trigger.source}}</b> trigger: {{$ctrl.trigger.project}}/{{$ctrl.trigger.slug}}<span ng-if=\"$ctrl.trigger.branch\">:{{$ctrl.trigger.branch}}</span>\n </span>\n <span ng-if=\"$ctrl.trigger.type === 'jenkins'\">\n Resolved at runtime by <b>Jenkins</b> trigger: {{$ctrl.trigger.master}}/{{$ctrl.trigger.job}}\n </span>\n `,\n};\n\nexport const APPENGINE_DYNAMIC_BRANCH_LABEL = 'spinnaker.appengine.dynamicBranchLabel.component';\nmodule(APPENGINE_DYNAMIC_BRANCH_LABEL, []).component(\n 'appengineDynamicBranchLabel',\n appengineDynamicBranchLabelComponent,\n);\n","import type { IController, IScope } from 'angular';\nimport { copy, module } from 'angular';\nimport type { IModalInstanceService } from 'angular-ui-bootstrap';\nimport { get, merge } from 'lodash';\n\nimport type { Application, ServerGroupWriter } from '@spinnaker/core';\nimport { SERVER_GROUP_WRITER, TaskMonitor } from '@spinnaker/core';\nimport { AppengineHealth } from '../../../common/appengineHealth';\n\nimport { APPENGINE_CONFIG_FILE_CONFIGURER } from './configFiles.component';\nimport { APPENGINE_DYNAMIC_BRANCH_LABEL } from './dynamicBranchLabel.component';\nimport type {\n AppengineServerGroupCommandBuilder,\n IAppengineServerGroupCommand,\n} from '../serverGroupCommandBuilder.service';\n\nimport './serverGroupWizard.less';\n\nclass AppengineCloneServerGroupCtrl implements IController {\n public pages: { [pageKey: string]: string } = {\n basicSettings: require('./basicSettings.html'),\n advancedSettings: require('./advancedSettings.html'),\n };\n public state = {\n loading: true,\n };\n public taskMonitor: TaskMonitor;\n\n public static $inject = [\n '$scope',\n '$uibModalInstance',\n 'serverGroupCommand',\n 'application',\n 'serverGroupWriter',\n 'appengineServerGroupCommandBuilder',\n ];\n constructor(\n public $scope: IScope,\n private $uibModalInstance: IModalInstanceService,\n public serverGroupCommand: IAppengineServerGroupCommand,\n private application: Application,\n private serverGroupWriter: ServerGroupWriter,\n appengineServerGroupCommandBuilder: AppengineServerGroupCommandBuilder,\n ) {\n if (['create', 'clone', 'editPipeline'].includes(get<string>(serverGroupCommand, 'viewState.mode'))) {\n this.$scope.command = serverGroupCommand;\n this.state.loading = false;\n this.initialize();\n } else {\n appengineServerGroupCommandBuilder\n .buildNewServerGroupCommand(application, 'appengine', 'createPipeline')\n .then((constructedCommand) => {\n this.$scope.command = merge(constructedCommand, serverGroupCommand);\n // Re-establish references to the original pipeline and stage objects so that\n // we don't mutate copies of them when assigning expected artifacts.\n this.$scope.command.viewState.pipeline = serverGroupCommand.viewState.pipeline;\n this.$scope.command.viewState.stage = serverGroupCommand.viewState.stage;\n this.state.loading = false;\n this.initialize();\n });\n }\n }\n\n public cancel(): void {\n this.$uibModalInstance.dismiss();\n }\n\n public submit(): void {\n const mode = this.$scope.command.viewState.mode;\n if (['editPipeline', 'createPipeline'].includes(mode)) {\n return this.$uibModalInstance.close(this.$scope.command);\n } else {\n const command = copy(this.$scope.command);\n // Make sure we're sending off a create operation, because there's no such thing as clone for App Engine.\n command.viewState.mode = 'create';\n const submitMethod = () => this.serverGroupWriter.cloneServerGroup(command, this.$scope.application);\n this.taskMonitor.submit(submitMethod);\n\n return null;\n }\n }\n\n private initialize(): void {\n this.$scope.application = this.application;\n this.taskMonitor = new TaskMonitor({\n application: this.application,\n title: 'Creating your server group',\n modalInstance: this.$uibModalInstance,\n });\n this.$scope.showPlatformHealthOnlyOverride = this.application.attributes.platformHealthOnlyShowOverride;\n this.$scope.platformHealth = AppengineHealth.PLATFORM;\n if (this.application.attributes.platformHealthOnly) {\n this.$scope.command.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n }\n}\n\nexport const APPENGINE_CLONE_SERVER_GROUP_CTRL = 'spinnaker.appengine.cloneServerGroup.controller';\nmodule(APPENGINE_CLONE_SERVER_GROUP_CTRL, [\n SERVER_GROUP_WRITER,\n APPENGINE_DYNAMIC_BRANCH_LABEL,\n APPENGINE_CONFIG_FILE_CONFIGURER,\n]).controller('appengineCloneServerGroupCtrl', AppengineCloneServerGroupCtrl);\n","import classNames from 'classnames';\nimport React from 'react';\n\nimport type { IArtifact, IArtifactAccountPair, IExpectedArtifact, IPipeline, IStage } from '@spinnaker/core';\nimport { StageArtifactSelector } from '@spinnaker/core';\n\ninterface IConfigFileArtifactListProps {\n configArtifacts: IArtifactAccountPair[];\n pipeline: IPipeline;\n stage: IStage;\n updateConfigArtifacts: (configArtifacts: any[]) => void;\n}\n\nexport const ConfigFileArtifactList = (props: IConfigFileArtifactListProps) => {\n const addConfigArtifact = () => {\n props.updateConfigArtifacts(props.configArtifacts.concat([{ id: '', account: '' }]));\n };\n\n const deleteConfigArtifact = (index: number) => {\n const newConfigArtifacts = [...props.configArtifacts];\n newConfigArtifacts.splice(index, 1);\n props.updateConfigArtifacts(newConfigArtifacts);\n };\n\n const onExpectedArtifactEdited = (artifact: IArtifact, index: number): void => {\n const newConfigArtifacts = [...props.configArtifacts];\n newConfigArtifacts.splice(index, 1, { ...newConfigArtifacts[index], id: null, artifact });\n props.updateConfigArtifacts(newConfigArtifacts);\n };\n\n const onExpectedArtifactSelected = (expectedArtifact: IExpectedArtifact, index: number): void => {\n onChangeExpectedArtifactId(expectedArtifact.id, index);\n };\n\n const onChangeExpectedArtifactId = (id: string, index: number): void => {\n const newConfigArtifacts = [...props.configArtifacts];\n newConfigArtifacts.splice(index, 1, { ...newConfigArtifacts[index], id, artifact: null });\n props.updateConfigArtifacts(newConfigArtifacts);\n };\n\n return (\n <>\n {props.configArtifacts.map((a, i) => {\n return (\n <div\n key={a.id}\n className={classNames('artifact-configuration-section col-md-12', {\n 'last-entry': props.configArtifacts.length - 1 === i,\n })}\n >\n <div className=\"col-md-9\">\n <StageArtifactSelector\n artifact={a.artifact}\n excludedArtifactTypePatterns={[]}\n expectedArtifactId={a.artifact == null ? a.id : null}\n onArtifactEdited={(artifact: IArtifact) => {\n onExpectedArtifactEdited(artifact, i);\n }}\n onExpectedArtifactSelected={(expectedArtifact: IExpectedArtifact) => {\n onExpectedArtifactSelected(expectedArtifact, i);\n }}\n pipeline={props.pipeline}\n stage={props.stage}\n />\n </div>\n <div className=\"col-md-1\">\n <button type=\"button\" className=\"btn btn-sm btn-default\" onClick={() => deleteConfigArtifact(i)}>\n <span className=\"glyphicon glyphicon-trash\" /> Delete\n </button>\n </div>\n </div>\n );\n })}\n <div className=\"col-md-7 col-md-offset-3\">\n <button className=\"btn btn-block btn-add-trigger add-new\" onClick={() => addConfigArtifact()}>\n <span className=\"glyphicon glyphicon-plus-sign\" /> Add Config Artifact\n </button>\n </div>\n </>\n );\n};\n","import { module } from 'angular';\nimport { react2angular } from 'react2angular';\n\nimport { withErrorBoundary } from '@spinnaker/core';\n\nimport { ConfigFileArtifactList } from './ConfigFileArtifactList';\n\nexport const CONFIG_FILE_ARTIFACT_LIST = 'spinnaker.appengine.configFileArtifactList.component';\n\nmodule(CONFIG_FILE_ARTIFACT_LIST, []).component(\n 'configFileArtifactList',\n react2angular(withErrorBoundary(ConfigFileArtifactList, 'configFileArtifactList'), [\n 'configArtifacts',\n 'pipeline',\n 'stage',\n 'updateConfigArtifacts',\n ]),\n);\n","import { module } from 'angular';\n\nimport type { Application, IJob, ITask, ITaskCommand } from '@spinnaker/core';\nimport { TaskExecutor } from '@spinnaker/core';\nimport type { IAppengineServerGroup } from '../../domain/index';\n\ninterface IAppengineServerGroupWriteJob extends IJob {\n serverGroupName: string;\n region: string;\n credentials: string;\n cloudProvider: string;\n}\n\nexport class AppengineServerGroupWriter {\n public startServerGroup(serverGroup: IAppengineServerGroup, application: Application): PromiseLike<ITask> {\n const job = this.buildJob(serverGroup, application, 'startAppEngineServerGroup');\n\n const command: ITaskCommand = {\n job: [job],\n application,\n description: `Start Server Group: ${serverGroup.name}`,\n };\n\n return TaskExecutor.executeTask(command);\n }\n\n public stopServerGroup(serverGroup: IAppengineServerGroup, application: Application): PromiseLike<ITask> {\n const job = this.buildJob(serverGroup, application, 'stopAppEngineServerGroup');\n\n const command: ITaskCommand = {\n job: [job],\n application,\n description: `Stop Server Group: ${serverGroup.name}`,\n };\n\n return TaskExecutor.executeTask(command);\n }\n\n private buildJob(\n serverGroup: IAppengineServerGroup,\n application: Application,\n type: string,\n ): IAppengineServerGroupWriteJob {\n return {\n type,\n region: serverGroup.region,\n serverGroupName: serverGroup.name,\n credentials: serverGroup.account,\n cloudProvider: 'appengine',\n application: application.name,\n };\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_WRITER = 'spinnaker.appengine.serverGroup.write.service';\n\nmodule(APPENGINE_SERVER_GROUP_WRITER, []).service('appengineServerGroupWriter', AppengineServerGroupWriter);\n","import type { IController, IScope } from 'angular';\nimport { module } from 'angular';\nimport type { IModalService } from 'angular-ui-bootstrap';\nimport { cloneDeep, map, mapValues, reduce } from 'lodash';\n\nimport type {\n Application,\n IConfirmationModalParams,\n ILoadBalancer,\n IServerGroup,\n ITaskMonitorConfig,\n ServerGroupWriter,\n} from '@spinnaker/core';\nimport {\n ConfirmationModalService,\n SERVER_GROUP_WRITER,\n ServerGroupReader,\n ServerGroupWarningMessageService,\n} from '@spinnaker/core';\n\nimport { AppengineHealth } from '../../common/appengineHealth';\nimport type { AppengineServerGroupCommandBuilder } from '../configure/serverGroupCommandBuilder.service';\nimport type { IAppengineLoadBalancer, IAppengineServerGroup } from '../../domain/index';\nimport type { AppengineServerGroupWriter } from '../writer/serverGroup.write.service';\nimport { APPENGINE_SERVER_GROUP_WRITER } from '../writer/serverGroup.write.service';\n\ninterface IPrivateScope extends IScope {\n $$destroyed: boolean;\n}\n\ninterface IServerGroupFromStateParams {\n accountId: string;\n region: string;\n name: string;\n}\n\nclass AppengineServerGroupDetailsController implements IController {\n public state = { loading: true };\n public serverGroup: IAppengineServerGroup;\n\n private static buildExpectedAllocationsTable(expectedAllocations: { [key: string]: number }): string {\n const tableRows = map(expectedAllocations, (allocation, serverGroupName) => {\n return `\n <tr>\n <td>${serverGroupName}</td>\n <td>${allocation * 100}%</td>\n </tr>`;\n }).join('');\n\n return `\n <table class=\"table table-condensed\">\n <thead>\n <tr>\n <th>Server Group</th>\n <th>Allocation</th>\n </tr>\n </thead>\n <tbody>\n ${tableRows}\n </tbody>\n </table>`;\n }\n\n public static $inject = [\n '$state',\n '$scope',\n '$uibModal',\n 'serverGroup',\n 'app',\n 'serverGroupWriter',\n 'appengineServerGroupWriter',\n 'appengineServerGroupCommandBuilder',\n ];\n constructor(\n private $state: any,\n private $scope: IPrivateScope,\n private $uibModal: IModalService,\n serverGroup: IServerGroupFromStateParams,\n public app: Application,\n private serverGroupWriter: ServerGroupWriter,\n private appengineServerGroupWriter: AppengineServerGroupWriter,\n private appengineServerGroupCommandBuilder: AppengineServerGroupCommandBuilder,\n ) {\n this.app\n .ready()\n .then(() => this.extractServerGroup(serverGroup))\n .then(() => {\n if (!this.$scope.$$destroyed) {\n this.app.getDataSource('serverGroups').onRefresh(this.$scope, () => this.extractServerGroup(serverGroup));\n }\n })\n .catch(() => this.autoClose());\n }\n\n public canDisableServerGroup(): boolean {\n if (this.serverGroup) {\n if (this.serverGroup.disabled) {\n return false;\n }\n\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);\n if (expectedAllocations) {\n return Object.keys(expectedAllocations).length > 0;\n } else {\n return false;\n }\n } else {\n return false;\n }\n }\n\n public canDestroyServerGroup(): boolean {\n if (this.serverGroup) {\n if (this.serverGroup.disabled) {\n return true;\n }\n\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);\n if (expectedAllocations) {\n return Object.keys(expectedAllocations).length > 0;\n } else {\n return false;\n }\n } else {\n return false;\n }\n }\n\n public destroyServerGroup(): void {\n const stateParams = {\n name: this.serverGroup.name,\n accountId: this.serverGroup.account,\n region: this.serverGroup.region,\n };\n\n const taskMonitor = {\n application: this.app,\n title: 'Destroying ' + this.serverGroup.name,\n onTaskComplete: () => {\n if (this.$state.includes('**.serverGroup', stateParams)) {\n this.$state.go('^');\n }\n },\n };\n\n const submitMethod = (params: any) => this.serverGroupWriter.destroyServerGroup(this.serverGroup, this.app, params);\n\n const confirmationModalParams = {\n header: 'Really destroy ' + this.serverGroup.name + '?',\n buttonText: 'Destroy ' + this.serverGroup.name,\n account: this.serverGroup.account,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n askForReason: true,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n body: this.getBodyTemplate(this.serverGroup, this.app),\n interestingHealthProviderNames: [] as string[],\n };\n\n if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {\n confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public enableServerGroup(): void {\n const taskMonitor: ITaskMonitorConfig = {\n application: this.app,\n title: 'Enabling ' + this.serverGroup.name,\n };\n\n const submitMethod = (params: any) =>\n this.serverGroupWriter.enableServerGroup(this.serverGroup, this.app, { ...params });\n\n const modalBody = `<div class=\"well well-sm\">\n <p>\n Enabling <b>${this.serverGroup.name}</b> will set its traffic allocation for\n <b>${this.serverGroup.loadBalancers[0]}</b> to 100%.\n </p>\n <p>\n If you would like more fine-grained control over your server groups' allocations,\n edit <b>${this.serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.\n </p>\n </div>\n `;\n\n const confirmationModalParams = {\n header: 'Really enable ' + this.serverGroup.name + '?',\n buttonText: 'Enable ' + this.serverGroup.name,\n body: modalBody,\n account: this.serverGroup.account,\n taskMonitorConfig: taskMonitor,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n submitMethod,\n askForReason: true,\n interestingHealthProviderNames: [] as string[],\n };\n\n if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {\n confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public disableServerGroup(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Disabling ' + this.serverGroup.name,\n };\n\n const submitMethod = (params: any) =>\n this.serverGroupWriter.disableServerGroup(this.serverGroup, this.app.name, params);\n\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);\n const modalBody = `<div class=\"well well-sm\">\n <p>\n For App Engine, a disable operation sets this server group's allocation\n to 0% and sets the other enabled server groups' allocations to their relative proportions\n before the disable operation. The approximate allocations that will result from this operation are shown below.\n </p>\n <p>\n If you would like more fine-grained control over your server groups' allocations,\n edit <b>${this.serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.\n </p>\n <div class=\"row\">\n <div class=\"col-md-12\">\n ${AppengineServerGroupDetailsController.buildExpectedAllocationsTable(expectedAllocations)}\n </div>\n </div>\n </div>\n `;\n\n const confirmationModalParams = {\n header: 'Really disable ' + this.serverGroup.name + '?',\n buttonText: 'Disable ' + this.serverGroup.name,\n body: modalBody,\n account: this.serverGroup.account,\n taskMonitorConfig: taskMonitor,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n submitMethod,\n askForReason: true,\n interestingHealthProviderNames: [] as string[],\n };\n\n if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {\n confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];\n }\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public stopServerGroup(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Stopping ' + this.serverGroup.name,\n };\n\n const submitMethod = () => this.appengineServerGroupWriter.stopServerGroup(this.serverGroup, this.app);\n\n let modalBody: string;\n if (!this.serverGroup.disabled) {\n modalBody = `<div class=\"alert alert-danger\">\n <p>Stopping this server group will scale it down to zero instances.</p>\n <p>\n This server group is currently serving traffic from <b>${this.serverGroup.loadBalancers[0]}</b>.\n Traffic directed to this server group after it has been stopped will not be handled.\n </p>\n </div>`;\n }\n\n const confirmationModalParams = {\n header: 'Really stop ' + this.serverGroup.name + '?',\n buttonText: 'Stop ' + this.serverGroup.name,\n account: this.serverGroup.account,\n body: modalBody,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n askForReason: true,\n };\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public startServerGroup(): void {\n const taskMonitor = {\n application: this.app,\n title: 'Starting ' + this.serverGroup.name,\n };\n\n const submitMethod = () => this.appengineServerGroupWriter.startServerGroup(this.serverGroup, this.app);\n\n const confirmationModalParams = {\n header: 'Really start ' + this.serverGroup.name + '?',\n buttonText: 'Start ' + this.serverGroup.name,\n account: this.serverGroup.account,\n platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,\n platformHealthType: AppengineHealth.PLATFORM,\n taskMonitorConfig: taskMonitor,\n submitMethod,\n askForReason: true,\n };\n\n ConfirmationModalService.confirm(confirmationModalParams);\n }\n\n public cloneServerGroup(): void {\n this.$uibModal.open({\n templateUrl: require('../configure/wizard/serverGroupWizard.html'),\n controller: 'appengineCloneServerGroupCtrl as ctrl',\n size: 'lg',\n resolve: {\n title: () => 'Clone ' + this.serverGroup.name,\n application: () => this.app,\n serverGroup: () => this.serverGroup,\n serverGroupCommand: () =>\n this.appengineServerGroupCommandBuilder.buildServerGroupCommandFromExisting(this.app, this.serverGroup),\n },\n });\n }\n\n public canStartServerGroup(): boolean {\n if (this.canStartOrStopServerGroup()) {\n return this.serverGroup.servingStatus === 'STOPPED';\n } else {\n return false;\n }\n }\n\n public canStopServerGroup(): boolean {\n if (this.canStartOrStopServerGroup()) {\n return this.serverGroup.servingStatus === 'SERVING';\n } else {\n return false;\n }\n }\n\n private canStartOrStopServerGroup(): boolean {\n const isFlex = this.serverGroup.env === 'FLEXIBLE';\n return isFlex || ['MANUAL', 'BASIC'].includes(this.serverGroup.scalingPolicy?.type);\n }\n\n private getBodyTemplate(serverGroup: IAppengineServerGroup, app: Application): string {\n let template = '';\n const params: IConfirmationModalParams = {};\n ServerGroupWarningMessageService.addDestroyWarningMessage(app, serverGroup, params);\n if (params.body) {\n template += params.body;\n }\n\n if (!serverGroup.disabled) {\n const expectedAllocations = this.expectedAllocationsAfterDisableOperation(serverGroup, app);\n\n template += `\n <div class=\"well well-sm\">\n <p>\n A destroy operation will first disable this server group.\n </p>\n <p>\n For App Engine, a disable operation sets this server group's allocation\n to 0% and sets the other enabled server groups' allocations to their relative proportions\n before the disable operation. The approximate allocations that will result from this operation are shown below.\n </p>\n <p>\n If you would like more fine-grained control over your server groups' allocations,\n edit <b>${serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.\n </p>\n <div class=\"row\">\n <div class=\"col-md-12\">\n ${AppengineServerGroupDetailsController.buildExpectedAllocationsTable(expectedAllocations)}\n </div>\n </div>\n </div>\n `;\n }\n\n return template;\n }\n\n private expectedAllocationsAfterDisableOperation(\n serverGroup: IServerGroup,\n app: Application,\n ): { [key: string]: number } {\n const loadBalancer = app.getDataSource('loadBalancers').data.find((toCheck: IAppengineLoadBalancer): boolean => {\n const allocations = toCheck.split?.allocations ?? {};\n const enabledServerGroups = Object.keys(allocations);\n return enabledServerGroups.includes(serverGroup.name);\n });\n\n if (loadBalancer) {\n let allocations = cloneDeep(loadBalancer.split.allocations);\n delete allocations[serverGroup.name];\n const denominator = reduce(allocations, (partialSum: number, allocation: number) => partialSum + allocation, 0);\n const precision = loadBalancer.split.shardBy === 'COOKIE' ? 1000 : 100;\n allocations = mapValues(\n allocations,\n (allocation) => Math.round((allocation / denominator) * precision) / precision,\n );\n return allocations;\n } else {\n return null;\n }\n }\n\n private autoClose(): void {\n if (this.$scope.$$destroyed) {\n return;\n } else {\n this.$state.params.allowModalToStayOpen = true;\n this.$state.go('^', null, { location: 'replace' });\n }\n }\n\n private extractServerGroup(fromParams: IServerGroupFromStateParams): PromiseLike<void> {\n return ServerGroupReader.getServerGroup(\n this.app.name,\n fromParams.accountId,\n fromParams.region,\n fromParams.name,\n ).then((serverGroupDetails: IServerGroup) => {\n let fromApp = this.app.getDataSource('serverGroups').data.find((toCheck: IServerGroup) => {\n return (\n toCheck.name === fromParams.name &&\n toCheck.account === fromParams.accountId &&\n toCheck.region === fromParams.region\n );\n });\n\n if (!fromApp) {\n this.app.getDataSource('loadBalancers').data.some((loadBalancer: ILoadBalancer) => {\n if (loadBalancer.account === fromParams.accountId) {\n return loadBalancer.serverGroups.some((toCheck: IServerGroup) => {\n let result = false;\n if (toCheck.name === fromParams.name) {\n fromApp = toCheck;\n result = true;\n }\n return result;\n });\n } else {\n return false;\n }\n });\n }\n\n this.serverGroup = { ...serverGroupDetails, ...fromApp };\n this.state.loading = false;\n });\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_DETAILS_CTRL = 'spinnaker.appengine.serverGroup.details.controller';\n\nmodule(APPENGINE_SERVER_GROUP_DETAILS_CTRL, [APPENGINE_SERVER_GROUP_WRITER, SERVER_GROUP_WRITER]).controller(\n 'appengineServerGroupDetailsCtrl',\n AppengineServerGroupDetailsController,\n);\n","import { module } from 'angular';\n\nimport type { IArtifact, IArtifactAccountPair, IServerGroup } from '@spinnaker/core';\n\nimport type { IAppengineServerGroupCommand } from './configure/serverGroupCommandBuilder.service';\nimport type { GitCredentialType, IAppengineGitTrigger, IAppengineJenkinsTrigger } from '../domain/index';\n\nexport class AppengineDeployDescription {\n public cloudProvider = 'appengine';\n public provider = 'appengine';\n public credentials: string;\n public account: string;\n public application: string;\n public stack?: string;\n public freeFormDetails?: string;\n public repositoryUrl: string;\n public branch: string;\n public configFilepaths: string[];\n public configFiles: string[];\n public configArtifacts: IArtifactAccountPair[];\n public applicationDirectoryRoot: string;\n public promote?: boolean;\n public stopPreviousVersion?: boolean;\n public type: string;\n public region: string;\n public strategy?: string;\n public strategyApplication?: string;\n public strategyPipeline?: string;\n public fromTrigger?: boolean;\n public trigger?: IAppengineGitTrigger | IAppengineJenkinsTrigger;\n public gitCredentialType: GitCredentialType;\n public interestingHealthProviderNames: string[];\n public expectedArtifactId: string;\n public expectedArtifact: IArtifact;\n public fromArtifact: boolean;\n public sourceType: string;\n public storageAccountName?: string;\n public containerImageUrl?: string;\n public suppressVersionString?: boolean;\n\n constructor(command: IAppengineServerGroupCommand) {\n this.credentials = command.credentials;\n this.account = command.credentials;\n this.application = command.application;\n this.stack = command.stack;\n this.freeFormDetails = command.freeFormDetails;\n this.repositoryUrl = command.repositoryUrl;\n this.branch = command.branch;\n this.configFilepaths = command.configFilepaths;\n this.promote = command.promote;\n this.stopPreviousVersion = command.stopPreviousVersion;\n this.type = command.type;\n this.region = command.region;\n this.strategy = command.strategy;\n this.strategyApplication = command.strategyApplication;\n this.strategyPipeline = command.strategyPipeline;\n this.fromTrigger = command.fromTrigger;\n this.trigger = command.trigger;\n this.gitCredentialType = command.gitCredentialType;\n this.configFiles = command.configFiles;\n this.configArtifacts = command.configArtifacts.filter((a) => !!a.id || !!a.artifact);\n this.applicationDirectoryRoot = command.applicationDirectoryRoot;\n this.interestingHealthProviderNames = command.interestingHealthProviderNames || [];\n this.expectedArtifactId = command.expectedArtifactId;\n this.expectedArtifact = command.expectedArtifact;\n this.fromArtifact = command.fromArtifact;\n this.sourceType = command.sourceType;\n this.storageAccountName = command.storageAccountName;\n this.containerImageUrl = command.containerImageUrl;\n this.suppressVersionString = command.suppressVersionString;\n }\n}\n\nexport class AppengineServerGroupTransformer {\n public static $inject = ['$q'];\n constructor(private $q: ng.IQService) {}\n\n public normalizeServerGroup(serverGroup: IServerGroup): PromiseLike<IServerGroup> {\n return this.$q.resolve(serverGroup);\n }\n\n public convertServerGroupCommandToDeployConfiguration(command: IAppengineServerGroupCommand) {\n return new AppengineDeployDescription(command);\n }\n}\n\nexport const APPENGINE_SERVER_GROUP_TRANSFORMER = 'spinnaker.appengine.serverGroup.transformer.service';\n\nmodule(APPENGINE_SERVER_GROUP_TRANSFORMER, []).service(\n 'appengineServerGroupTransformer',\n AppengineServerGroupTransformer,\n);\n","import type { IApplicationNameValidator, IValidationResult } from '@spinnaker/core';\nimport { ApplicationNameValidator } from '@spinnaker/core';\n\n// See https://cloud.google.com/appengine/docs/admin-api/reference/rest/v1/apps.services.versions#Version\nclass AppengineApplicationNameValidator implements IApplicationNameValidator {\n public validate(name = ''): IValidationResult {\n const warnings: string[] = [];\n const errors: string[] = [];\n if (name.length) {\n this.validateSpecialCharacters(name, errors);\n this.validateLength(name, warnings, errors);\n }\n return { warnings, errors };\n }\n\n private validateSpecialCharacters(name: string, errors: string[]): void {\n const pattern = /^[a-z0-9]*$/g;\n if (!pattern.test(name)) {\n errors.push('Only numbers and lowercase letters are allowed.');\n }\n }\n\n private validateLength(name: string, warnings: string[], errors: string[]): void {\n if (name.length > 58) {\n errors.push('The maximum length for an App Engine application name is 63 characters.');\n return;\n }\n if (name.length > 48) {\n if (name.length >= 56) {\n warnings.push('You will not be able to include a stack or detail field for clusters.');\n } else {\n const remaining = 56 - name.length;\n warnings.push(`If you plan to include a stack or detail field for clusters, you will only have\n ${remaining} character${remaining > 1 ? 's' : ''} to do so.`);\n }\n }\n }\n}\n\nApplicationNameValidator.registerValidator('appengine', new AppengineApplicationNameValidator());\n","import { module } from 'angular';\n\nimport { CloudProviderRegistry, DeploymentStrategyRegistry } from '@spinnaker/core';\n\nimport { APPENGINE_COMPONENT_URL_DETAILS } from './common/componentUrlDetails.component';\nimport { APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM } from './common/conditionalDescriptionListItem.component';\nimport { APPENGINE_LOAD_BALANCER_CREATE_MESSAGE } from './common/loadBalancerMessage.component';\nimport './helpContents/appengineHelpContents';\nimport { APPENGINE_INSTANCE_DETAILS_CTRL } from './instance/details/details.controller';\nimport { APPENGINE_LOAD_BALANCER_MODULE } from './loadBalancer/loadBalancer.module';\nimport logo from './logo/appengine.logo.png';\nimport { APPENGINE_PIPELINE_MODULE } from './pipeline/pipeline.module';\nimport './pipeline/stages/deployAppengineConfig/deployAppengineConfigStage';\nimport { APPENGINE_SERVER_GROUP_COMMAND_BUILDER } from './serverGroup/configure/serverGroupCommandBuilder.service';\nimport { APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL } from './serverGroup/configure/wizard/basicSettings.controller';\nimport { APPENGINE_CLONE_SERVER_GROUP_CTRL } from './serverGroup/configure/wizard/cloneServerGroup.controller';\nimport { CONFIG_FILE_ARTIFACT_LIST } from './serverGroup/configure/wizard/configFileArtifactList.module';\nimport { APPENGINE_SERVER_GROUP_DETAILS_CTRL } from './serverGroup/details/details.controller';\nimport { APPENGINE_SERVER_GROUP_TRANSFORMER } from './serverGroup/transformer';\nimport { APPENGINE_SERVER_GROUP_WRITER } from './serverGroup/writer/serverGroup.write.service';\nimport './validation/ApplicationNameValidator';\n\nimport './logo/appengine.logo.less';\n\nexport const APPENGINE_MODULE = 'spinnaker.appengine';\n\nmodule(APPENGINE_MODULE, [\n APPENGINE_CLONE_SERVER_GROUP_CTRL,\n APPENGINE_COMPONENT_URL_DETAILS,\n APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM,\n APPENGINE_INSTANCE_DETAILS_CTRL,\n APPENGINE_LOAD_BALANCER_CREATE_MESSAGE,\n APPENGINE_LOAD_BALANCER_MODULE,\n APPENGINE_PIPELINE_MODULE,\n APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL,\n APPENGINE_SERVER_GROUP_COMMAND_BUILDER,\n APPENGINE_SERVER_GROUP_DETAILS_CTRL,\n APPENGINE_SERVER_GROUP_TRANSFORMER,\n APPENGINE_SERVER_GROUP_WRITER,\n CONFIG_FILE_ARTIFACT_LIST,\n]).config(() => {\n CloudProviderRegistry.registerProvider('appengine', {\n name: 'App Engine',\n instance: {\n detailsTemplateUrl: require('./instance/details/details.html'),\n detailsController: 'appengineInstanceDetailsCtrl',\n },\n serverGroup: {\n transformer: 'appengineServerGroupTransformer',\n detailsController: 'appengineServerGroupDetailsCtrl',\n detailsTemplateUrl: require('./serverGroup/details/details.html'),\n commandBuilder: 'appengineServerGroupCommandBuilder',\n cloneServerGroupController: 'appengineCloneServerGroupCtrl',\n cloneServerGroupTemplateUrl: require('./serverGroup/configure/wizard/serverGroupWizard.html'),\n skipUpstreamStageCheck: true,\n },\n loadBalancer: {\n transformer: 'appengineLoadBalancerTransformer',\n createLoadBalancerTemplateUrl: require('./loadBalancer/configure/wizard/wizard.html'),\n createLoadBalancerController: 'appengineLoadBalancerWizardCtrl',\n detailsTemplateUrl: require('./loadBalancer/details/details.html'),\n detailsController: 'appengineLoadBalancerDetailsCtrl',\n },\n logo: {\n path: logo,\n },\n });\n});\n\nDeploymentStrategyRegistry.registerProvider('appengine', ['custom']);\n","export default \"appengine.logoc2c312af6aa99037.png\""],"names":["appengineComponentUrlDetailsComponent","bindings","component","template","APPENGINE_COMPONENT_URL_DETAILS","module","AppengineConditionalDescriptionListItemCtrl","constructor","$filter","this","$onInit","label","key","$inject","appengineConditionalDescriptionListItem","transclude","keyLabel","valueLabel","controller","APPENGINE_CONDITIONAL_DESCRIPTION_LIST_ITEM","APPENGINE_LOAD_BALANCER_CREATE_MESSAGE","showCreateMessage","columnOffset","columns","templateUrl","value","forEach","entry","HelpContentsRegistry","register","AppengineInstanceDetailsController","$q","app","instance","state","loading","upToolTip","outOfServiceToolTip","ready","then","retrieveInstance","instanceDetails","catch","instanceIdNotFound","instanceId","terminateInstance","cloneDeep","shortName","name","substring","placement","taskMonitor","application","title","onTaskComplete","$state","includes","go","ConfirmationModalService","confirm","header","buttonText","account","taskMonitorConfig","submitMethod","InstanceWriter","cloudProvider","instanceManager","flattenDeep","getDataSource","data","map","loadBalancer","serverGroups","find","dataSource","instances","some","possibleMatch","id","recentHistoryExtraData","region","category","serverGroup","RecentHistoryService","addExtraDataToLatest","InstanceReader","getInstanceDetails","reject","APPENGINE_INSTANCE_DETAILS_CTRL","appengineLoadBalancerAdvancedSettingsComponent","error","disableMigrateTraffic","splitDescription","allocationDescriptions","length","targetServerGroupName","serverGroupName","targetServerGroup","candidate","allowsGradualTrafficMigration","APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS","appengineAllocationConfigurationRowComponent","allocationDescription","removeAllocation","serverGroupOptions","onAllocationChange","getServerGroupOptions","uniq","concat","APPENGINE_ALLOCATION_CONFIGURATION_ROW","appengineLoadBalancerSettingsComponent","forPipelineConfig","updateServerGroupOptions","addAllocation","remainingServerGroups","serverGroupsWithoutAllocation","push","allocation","locatorType","shardBy","index","splice","allocationIsInvalid","reduce","sum","showAddButton","showShardByOptions","migrateTraffic","initializeAsTextInput","serverGroupsWithAllocation","description","allServerGroups","difference","APPENGINE_LOAD_BALANCER_BASIC_SETTINGS","AppengineStageAllocationLabelCtrl","mapTargetCoordinateToLabel","targetCoordinate","target","StageConstants","TARGET_LIST","t","val","$doCheck","setInputViewValue","inputViewValue","cluster","targetLabel","appengineStageAllocationLabel","appengineStageAllocationConfigurationRow","targets","clusterFilter","AppListExtractor","clusterFilterForCredentialsAndRegion","clusterList","getClusters","onLocatorTypeChange","APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW","AppengineLoadBalancerUpsertDescription","convertTrafficSplitToTrafficSplitDescription","split","allocations","acc","credentials","loadBalancerName","mapAllocationsToDecimals","mapAllocationsToPercentages","Math","round","AppengineLoadBalancerTransformer","normalizeLoadBalancer","provider","type","instanceCounts","buildInstanceCounts","detachedInstances","transformInstance","activeServerGroups","filter","isDisabled","chain","flatten","resolve","convertLoadBalancerForEditing","upToDateLoadBalancer","convertLoadBalancerToUpsertDescription","has","camelCase","health","up","down","outOfService","succeeded","failed","starting","unknown","loadBalancers","healthState","get","APPENGINE_LOAD_BALANCER_TRANSFORMER","styleInject","css","ref","insertAt","document","head","getElementsByTagName","style","createElement","firstChild","insertBefore","appendChild","styleSheet","cssText","createTextNode","service","AppengineLoadBalancerWizardController","$scope","$uibModalInstance","isNew","appengineLoadBalancerTransformer","wizardSubFormValidation","submitButtonLabel","heading","join","convertedLoadBalancer","setTaskMonitor","initializeFormValidation","submit","close","LoadBalancerWriter","upsertLoadBalancer","cancel","dismiss","showSubmitButton","subFormsAreValid","TaskMonitor","modalInstance","config","form","scope","page","subForm","validators","watchString","validator","watchDeep","refresh","onNextRefresh","onApplicationRefresh","$$destroyed","newStateParams","accountId","APPENGINE_LOAD_BALANCER_WIZARD_CTRL","AppengineLoadBalancerDetailsController","$uibModal","dispatchRules","loadBalancerFromParams","extractLoadBalancer","editLoadBalancer","open","size","deleteLoadBalancer","body","getConfirmationModalBodyHtml","canDeleteLoadBalancer","test","buildDispatchRules","onRefresh","autoClose","rule","domain","path","serverGroupNames","hasAny","hasMoreThanOne","listOfServerGroupNames","params","allowModalToStayOpen","location","APPENGINE_LOAD_BALANCER_DETAILS_CTRL","APPENGINE_LOAD_BALANCER_MODULE","AppengineHealth","PLATFORM","AppengineStageCtrl","platformHealth","setStageRegion","selected","accounts","stage","AccountService","getAccountDetails","accountDetails","setStageCloudProvider","setAccounts","listAccounts","setTargets","setStageCredentials","defaultCredentials","appengine","AppengineDestroyAsgStageCtrl","super","APPENGINE_DESTROY_ASG_STAGE","Registry","pipeline","registerStage","provides","executionStepLabelUrl","message","fieldName","fieldLabel","AppengineDisableAsgStageCtrl","attributes","platformHealthOnlyShowOverride","platformHealthOnly","interestingHealthProviderNames","APPENGINE_DISABLE_ASG_STAGE","AppengineLoadBalancerChoiceModalCtrl","initialize","CloudProviderRegistry","getValue","updatedLoadBalancerPromise","createLoadBalancerTemplateUrl","createLoadBalancerController","selectedLoadBalancer","result","APPENGINE_LOAD_BALANCER_CHOICE_MODAL_CTRL","AppengineEditLoadBalancerStageCtrl","addLoadBalancer","newLoadBalancer","updatedLoadBalancer","removeLoadBalancer","APPENGINE_EDIT_LOAD_BALANCER_STAGE","executionDetailsUrl","executionConfigSections","controllerAs","AppengineEnableAsgStageCtrl","APPENGINE_ENABLE_ASG_STAGE","AppengineShrinkClusterStageCtrl","shrinkToSize","allowDeleteActive","retainLargerOverNewer","toString","pluralize","str","APPENGINE_SHRINK_CLUSTER_STAGE","AppengineStartServerGroupStageCtrl","APPENGINE_START_SERVER_GROUP_STAGE","AppengineStopServerGroupStageCtrl","APPENGINE_STOP_SERVER_GROUP_STAGE","APPENGINE_PIPELINE_MODULE","FormikAccountRegionSelector","React","Component","props","destroy$","Subject","setRegionList","accountFilter","observableFrom","pipe","takeUntil","subscribe","availableRegions","getRegions","sort","setState","accountChanged","credentialsField","componentName","componentDidMount","formik","values","componentWillUnmount","next","render","className","FormikFormField","input","ReactSelectInput","stringOptions","clearable","onChange","required","_DeployAppengineConfigForm","arguments","onTemplateArtifactEdited","artifact","setFieldValue","artifactAccount","onTemplateArtifactSelected","removeInputArtifact","getInputArtifact","StageArtifactSelectorDelegate","excludedArtifactTypePatterns","excludedArtifactTypes","expectedArtifactId","onArtifactEdited","helpKey","onExpectedArtifactSelected","onClick","excludeAllTypesExcept","ArtifactTypePatterns","BITBUCKET_FILE","CUSTOM_OBJECT","EMBEDDED_BASE64","GCS_OBJECT","GITHUB_FILE","GITLAB_FILE","S3_OBJECT","HTTP_FILE","ORACLE_OBJECT","DeployAppengineConfigForm","validateDeployAppengineConfigurationStage","formValidator","FormValidator","field","validateForm","updateStage","stageWithDefaults","useMemo","FormikStageConfig","validate","producesArtifacts","executionDetailsSections","ExecutionDetailsTasks","ExecutionArtifactTab","validateFn","AppengineProviderSettings","SETTINGS","providers","defaults","resetToOriginal","resetProvider","AppengineSourceType","_AppengineServerGroupCommandBuilder","getTriggerOptions","triggers","trigger","source","project","slug","branch","master","job","getExpectedArtifacts","expectedArtifacts","buildNewServerGroupCommand","selectedProvider","mode","dataToFetch","getAllAccountDetailsForProvider","storageAccounts","StorageAccountReader","getStorageAccounts","viewState","getSubmitButtonLabel","disableStrategySelection","all","backingData","getCredentials","getRegion","fromArtifact","sourceType","buildServerGroupCommandFromExisting","command","stack","freeFormDetails","detail","buildNewServerGroupCommandForPipeline","_stage","when","triggerOptions","buildServerGroupCommandFromPipeline","accountNames","_account","AppengineServerGroupCommandBuilder","APPENGINE_SERVER_GROUP_COMMAND_BUILDER","AppengineServerGroupBasicSettingsCtrl","$controller","$uibModalStack","excludedGcsArtifactTypes","excludedContainerArtifactTypes","DOCKER_IMAGE","onExpectedArtifactEdited","$applyAsync","expectedArtifact","onChangeExpectedArtifactId","artifactId","onExpectedArtifactAccountSelected","accountName","storageAccountName","extend","imageReader","gitCredentialType","onAccountChange","containerArtifactDelegate","NgAppEngineDeployArtifactDelegate","containerArtifactController","ExpectedArtifactSelectorViewController","gcsArtifactDelegate","gcsArtifactController","isGitSource","GIT","isGcsSource","GCS","isContainerImageSource","CONTAINER_IMAGE","toggleResolveViaTrigger","fromTrigger","onTriggerChange","set","findAccountInBackingData","getSupportedGitCredentialTypes","supportedGitCredentialTypes","humanReadableGitCredentialType","APPENGINE_SERVER_GROUP_BASIC_SETTINGS_CTRL","ConfigArtifact","pair","_a","unserializable","configurable","enumerable","writable","Object","defineProperty","delegate","NgAppengineConfigArtifactDelegate","AppengineConfigFileConfigurerCtrl","artifactAccounts","updateConfigArtifacts","configArtifacts","configFiles","artifactAccountPair","getArtifactAccounts","a","updateAccounts","getSelectedExpectedArtifact","addConfigFile","addConfigArtifact","deleteConfigFile","deleteConfigArtifact","mapTabToSpaces","event","which","preventDefault","cursorPosition","selectionStart","inputValue","appengineConfigFileConfigurerComponent","APPENGINE_CONFIG_FILE_CONFIGURER","appengineDynamicBranchLabelComponent","APPENGINE_DYNAMIC_BRANCH_LABEL","AppengineCloneServerGroupCtrl","serverGroupCommand","serverGroupWriter","appengineServerGroupCommandBuilder","pages","basicSettings","advancedSettings","constructedCommand","merge","copy","cloneServerGroup","showPlatformHealthOnlyOverride","APPENGINE_CLONE_SERVER_GROUP_CTRL","SERVER_GROUP_WRITER","CONFIG_FILE_ARTIFACT_LIST","react2angular","withErrorBoundary","newConfigArtifacts","i","classNames","StageArtifactSelector","APPENGINE_SERVER_GROUP_WRITER","startServerGroup","buildJob","TaskExecutor","executeTask","stopServerGroup","_AppengineServerGroupDetailsController","appengineServerGroupWriter","extractServerGroup","buildExpectedAllocationsTable","expectedAllocations","canDisableServerGroup","disabled","expectedAllocationsAfterDisableOperation","keys","canDestroyServerGroup","destroyServerGroup","stateParams","confirmationModalParams","askForReason","platformHealthType","getBodyTemplate","enableServerGroup","modalBody","disableServerGroup","canStartServerGroup","canStartOrStopServerGroup","servingStatus","canStopServerGroup","env","scalingPolicy","ServerGroupWarningMessageService","addDestroyWarningMessage","toCheck","_b","denominator","partialSum","precision","mapValues","fromParams","ServerGroupReader","getServerGroup","serverGroupDetails","fromApp","AppengineServerGroupDetailsController","APPENGINE_SERVER_GROUP_DETAILS_CTRL","AppengineDeployDescription","repositoryUrl","configFilepaths","promote","stopPreviousVersion","strategy","strategyApplication","strategyPipeline","applicationDirectoryRoot","containerImageUrl","suppressVersionString","AppengineServerGroupTransformer","normalizeServerGroup","convertServerGroupCommandToDeployConfiguration","APPENGINE_SERVER_GROUP_TRANSFORMER","ApplicationNameValidator","registerValidator","warnings","errors","validateSpecialCharacters","validateLength","remaining","APPENGINE_MODULE","registerProvider","detailsTemplateUrl","detailsController","transformer","commandBuilder","cloneServerGroupController","cloneServerGroupTemplateUrl","skipUpstreamStageCheck","logo","DeploymentStrategyRegistry"],"mappings":"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","x_google_ignoreList":[10]}