UNPKG

@spotinst/spinnaker-deck

Version:

Spinnaker-Deck service, forked with support to Spotinst

513 lines (440 loc) 19.2 kB
'use strict'; import UIROUTER_ANGULARJS from '@uirouter/angularjs'; import * as angular from 'angular'; import _ from 'lodash'; import { AccountService, ClusterTargetBuilder, ConfirmationModalService, FirewallLabels, NetworkReader, SERVER_GROUP_WRITER, ServerGroupReader, ServerGroupTemplates, ServerGroupWarningMessageService, } from '@spinnaker/core'; import { GOOGLE_COMMON_XPNNAMING_GCE_SERVICE } from 'google/common/xpnNaming.gce.service'; import { GOOGLE_SERVERGROUP_DETAILS_AUTOSCALINGPOLICY_ADDAUTOSCALINGPOLICYBUTTON_COMPONENT } from './autoscalingPolicy/addAutoscalingPolicyButton.component'; import { GOOGLE_SERVERGROUP_DETAILS_AUTOSCALINGPOLICY_AUTOSCALINGPOLICY_DIRECTIVE } from './autoscalingPolicy/autoscalingPolicy.directive'; import { GOOGLE_SERVERGROUP_CONFIGURE_SERVERGROUPCOMMANDBUILDER_SERVICE } from '../configure/serverGroupCommandBuilder.service'; import { GOOGLE_SERVERGROUP_DETAILS_RESIZE_RESIZESERVERGROUP_CONTROLLER } from './resize/resizeServerGroup.controller'; import { GOOGLE_SERVERGROUP_DETAILS_ROLLBACK_ROLLBACKSERVERGROUP_CONTROLLER } from './rollback/rollbackServerGroup.controller'; import './serverGroupDetails.less'; require('../configure/serverGroup.configure.gce.module'); export const GOOGLE_SERVERGROUP_DETAILS_SERVERGROUPDETAILS_GCE_CONTROLLER = 'spinnaker.serverGroup.details.gce.controller'; export const name = GOOGLE_SERVERGROUP_DETAILS_SERVERGROUPDETAILS_GCE_CONTROLLER; // for backwards compatibility angular .module(GOOGLE_SERVERGROUP_DETAILS_SERVERGROUPDETAILS_GCE_CONTROLLER, [ UIROUTER_ANGULARJS, GOOGLE_SERVERGROUP_CONFIGURE_SERVERGROUPCOMMANDBUILDER_SERVICE, SERVER_GROUP_WRITER, GOOGLE_COMMON_XPNNAMING_GCE_SERVICE, GOOGLE_SERVERGROUP_DETAILS_RESIZE_RESIZESERVERGROUP_CONTROLLER, GOOGLE_SERVERGROUP_DETAILS_ROLLBACK_ROLLBACKSERVERGROUP_CONTROLLER, GOOGLE_SERVERGROUP_DETAILS_AUTOSCALINGPOLICY_AUTOSCALINGPOLICY_DIRECTIVE, GOOGLE_SERVERGROUP_DETAILS_AUTOSCALINGPOLICY_ADDAUTOSCALINGPOLICYBUTTON_COMPONENT, ]) .controller('gceServerGroupDetailsCtrl', [ '$scope', '$state', '$templateCache', '$interpolate', 'app', 'serverGroup', 'gceServerGroupCommandBuilder', '$uibModal', 'serverGroupWriter', 'gceXpnNamingService', function ( $scope, $state, $templateCache, $interpolate, app, serverGroup, gceServerGroupCommandBuilder, $uibModal, serverGroupWriter, gceXpnNamingService, ) { this.state = { loading: true, }; this.firewallsLabel = FirewallLabels.get('Firewalls'); this.application = app; const extractServerGroupSummary = () => { let summary = _.find(app.serverGroups.data, (toCheck) => { return ( toCheck.name === serverGroup.name && toCheck.account === serverGroup.accountId && toCheck.region === serverGroup.region ); }); if (!summary) { app.loadBalancers.data.some((loadBalancer) => { if (loadBalancer.account === serverGroup.accountId && loadBalancer.region === serverGroup.region) { return loadBalancer.serverGroups.some((possibleServerGroup) => { if (possibleServerGroup.name === serverGroup.name) { summary = possibleServerGroup; return true; } }); } }); } return summary; }; const autoClose = () => { if ($scope.$$destroyed) { return; } $state.go('^', { allowModalToStayOpen: true }, { location: 'replace' }); }; const cancelLoader = () => { this.state.loading = false; }; const retrieveServerGroup = () => { const summary = extractServerGroupSummary(); return ServerGroupReader.getServerGroup( app.name, serverGroup.accountId, serverGroup.region, serverGroup.name, ).then((details) => { cancelLoader(); angular.extend(details, summary); // it's possible the summary was not found because the clusters are still loading details.account = serverGroup.accountId; this.serverGroup = details; if (!_.isEmpty(this.serverGroup)) { if (details.securityGroups) { this.securityGroups = _.chain(details.securityGroups) .map((id) => { return ( _.find(app.securityGroups.data, { accountName: serverGroup.accountId, region: 'global', id: id }) || _.find(app.securityGroups.data, { accountName: serverGroup.accountId, region: 'global', name: id }) ); }) .compact() .value(); } this.serverGroup.zones.sort(); const projectId = gceXpnNamingService.deriveProjectId(this.serverGroup.launchConfig.instanceTemplate); this.serverGroup.logsLink = 'https://console.developers.google.com/project/' + projectId + '/logs?advancedFilter=resource.type=(gce_instance_group_manager OR gce_instance OR gce_autoscaler)%0A"' + this.serverGroup.name + '"'; this.serverGroup.network = getNetwork(projectId); retrieveSubnet(projectId); determineAssociatePublicIPAddress(); findStartupScript(); prepareAvailabilityPolicies(); prepareShieldedVmConfig(); prepareAutoHealingPolicy(); prepareAuthScopes(); prepareCurrentActions(); augmentTagsWithHelp(); configureEntityTagTargets(); processLabels(); } else { autoClose(); } }, autoClose); }; const findStartupScript = () => { if (_.has(this.serverGroup, 'launchConfig.instanceTemplate.properties.metadata.items')) { const metadataItems = this.serverGroup.launchConfig.instanceTemplate.properties.metadata.items; const startupScriptItem = _.find(metadataItems, (metadataItem) => { return metadataItem.key === 'startup-script'; }); if (startupScriptItem) { this.serverGroup.startupScript = startupScriptItem.value; } } }; const prepareAvailabilityPolicies = () => { if (_.has(this.serverGroup, 'launchConfig.instanceTemplate.properties.scheduling')) { const scheduling = this.serverGroup.launchConfig.instanceTemplate.properties.scheduling; this.serverGroup.availabilityPolicies = { preemptibility: scheduling.preemptible ? 'On' : 'Off', automaticRestart: scheduling.automaticRestart ? 'On' : 'Off', onHostMaintenance: scheduling.onHostMaintenance === 'MIGRATE' ? 'Migrate' : 'Terminate', }; } }; const prepareShieldedVmConfig = () => { if (_.has(this.serverGroup, 'launchConfig.instanceTemplate.properties.shieldedVmConfig')) { const shieldedVmConfig = this.serverGroup.launchConfig.instanceTemplate.properties.shieldedVmConfig; this.serverGroup.shieldedVmConfig = { enableSecureBoot: shieldedVmConfig.enableSecureBoot ? 'On' : 'Off', enableVtpm: shieldedVmConfig.enableVtpm ? 'On' : 'Off', enableIntegrityMonitoring: shieldedVmConfig.enableIntegrityMonitoring ? 'On' : 'Off', }; } }; const prepareAutoHealingPolicy = () => { if (this.serverGroup.autoHealingPolicy) { const autoHealingPolicy = this.serverGroup.autoHealingPolicy; const healthCheckUrl = autoHealingPolicy.healthCheck; this.serverGroup.autoHealingPolicyHealthCheck = healthCheckUrl ? _.last(healthCheckUrl.split('/')) : null; this.serverGroup.initialDelaySec = autoHealingPolicy.initialDelaySec; if (autoHealingPolicy.maxUnavailable) { if (typeof autoHealingPolicy.maxUnavailable.percent === 'number') { this.serverGroup.maxUnavailable = autoHealingPolicy.maxUnavailable.percent + '%'; } else { this.serverGroup.maxUnavailable = autoHealingPolicy.maxUnavailable.fixed + ' instances'; } } } }; const prepareAuthScopes = () => { if (_.has(this.serverGroup, 'launchConfig.instanceTemplate.properties.serviceAccounts')) { const serviceAccounts = this.serverGroup.launchConfig.instanceTemplate.properties.serviceAccounts; if (serviceAccounts.length) { const serviceAccount = this.serverGroup.launchConfig.instanceTemplate.properties.serviceAccounts[0]; this.serverGroup.serviceAccountEmail = serviceAccount.email; this.serverGroup.authScopes = _.map(serviceAccount.scopes, (authScope) => { return authScope.replace('https://www.googleapis.com/auth/', ''); }); } } }; const prepareCurrentActions = () => { if (this.serverGroup.currentActions) { this.serverGroup.currentActionsSummary = []; _.forOwn(this.serverGroup.currentActions, (value, key) => { if (key !== 'none' && value) { this.serverGroup.currentActionsSummary.push({ action: _.startCase(key), count: value }); } }); if (!this.serverGroup.currentActionsSummary.length) { delete this.serverGroup.currentActionsSummary; } } }; const augmentTagsWithHelp = () => { if (_.has(this.serverGroup, 'launchConfig.instanceTemplate.properties.tags.items') && this.securityGroups) { const helpMap = {}; this.serverGroup.launchConfig.instanceTemplate.properties.tags.items.forEach((tag) => { const securityGroupsMatches = _.filter(this.securityGroups, (securityGroup) => _.includes(securityGroup.targetTags, tag), ); const securityGroupMatchNames = _.map(securityGroupsMatches, 'name'); if (!_.isEmpty(securityGroupMatchNames)) { const groupOrGroups = securityGroupMatchNames.length > 1 ? 'groups' : 'group'; helpMap[tag] = 'This tag associates this server group with security ' + groupOrGroups + ' <em>' + securityGroupMatchNames.join(', ') + '</em>.'; } }); this.serverGroup.launchConfig.instanceTemplate.properties.tags.helpMap = helpMap; } }; const processLabels = () => { if (!_.size(this.serverGroup.instanceTemplateLabels)) { delete this.serverGroup.instanceTemplateLabels; } }; const getNetwork = (projectId) => { const networkUrl = _.get( this.serverGroup, 'launchConfig.instanceTemplate.properties.networkInterfaces[0].network', ); return gceXpnNamingService.decorateXpnResourceIfNecessary(projectId, networkUrl); }; const retrieveSubnet = (projectId) => { NetworkReader.listNetworksByProvider('gce').then((networks) => { const autoCreateSubnets = _.chain(networks) .filter({ account: this.serverGroup.account, id: this.serverGroup.network }) .map('autoCreateSubnets') .head() .value(); if (autoCreateSubnets) { this.serverGroup.subnet = '(Auto-select)'; } else { const subnetUrl = _.get( this.serverGroup, 'launchConfig.instanceTemplate.properties.networkInterfaces[0].subnetwork', ); this.serverGroup.subnet = gceXpnNamingService.decorateXpnResourceIfNecessary(projectId, subnetUrl); } }); }; const determineAssociatePublicIPAddress = () => { this.serverGroup.associatePublicIPAddress = _.has( this.serverGroup, 'launchConfig.instanceTemplate.properties.networkInterfaces[0].accessConfigs', ); }; retrieveServerGroup().then(() => { // If the user navigates away from the view before the initial retrieveServerGroup call completes, // do not bother subscribing to the refresh if (!$scope.$$destroyed) { app.serverGroups.onRefresh($scope, retrieveServerGroup); } }); this.destroyServerGroup = () => { const serverGroup = this.serverGroup; const taskMonitor = { application: app, title: 'Destroying ' + serverGroup.name, onTaskComplete: () => { if ($state.includes('**.serverGroup', stateParams)) { $state.go('^'); } }, }; const submitMethod = (params) => serverGroupWriter.destroyServerGroup(serverGroup, app, params); const stateParams = { name: serverGroup.name, accountId: serverGroup.account, region: serverGroup.region, }; const confirmationModalParams = { header: 'Really destroy ' + serverGroup.name + '?', buttonText: 'Destroy ' + serverGroup.name, account: serverGroup.account, taskMonitorConfig: taskMonitor, submitMethod: submitMethod, askForReason: true, platformHealthOnlyShowOverride: app.attributes.platformHealthOnlyShowOverride, platformHealthType: 'Google', }; ServerGroupWarningMessageService.addDestroyWarningMessage(app, serverGroup, confirmationModalParams); if (app.attributes.platformHealthOnlyShowOverride && app.attributes.platformHealthOnly) { confirmationModalParams.interestingHealthProviderNames = ['Google']; } ConfirmationModalService.confirm(confirmationModalParams); }; this.disableServerGroup = () => { const serverGroup = this.serverGroup; const taskMonitor = { application: app, title: 'Disabling ' + serverGroup.name, }; const submitMethod = (params) => serverGroupWriter.disableServerGroup(serverGroup, app, params); const confirmationModalParams = { header: 'Really disable ' + serverGroup.name + '?', buttonText: 'Disable ' + serverGroup.name, account: serverGroup.account, taskMonitorConfig: taskMonitor, platformHealthOnlyShowOverride: app.attributes.platformHealthOnlyShowOverride, platformHealthType: 'Google', submitMethod: submitMethod, askForReason: true, }; ServerGroupWarningMessageService.addDisableWarningMessage(app, serverGroup, confirmationModalParams); if (app.attributes.platformHealthOnlyShowOverride && app.attributes.platformHealthOnly) { confirmationModalParams.interestingHealthProviderNames = ['Google']; } ConfirmationModalService.confirm(confirmationModalParams); }; this.enableServerGroup = () => { const serverGroup = this.serverGroup; const taskMonitor = { application: app, title: 'Enabling ' + serverGroup.name, }; const submitMethod = (params) => serverGroupWriter.enableServerGroup(serverGroup, app, params); const confirmationModalParams = { header: 'Really enable ' + serverGroup.name + '?', buttonText: 'Enable ' + serverGroup.name, account: serverGroup.account, taskMonitorConfig: taskMonitor, platformHealthOnlyShowOverride: app.attributes.platformHealthOnlyShowOverride, platformHealthType: 'Google', submitMethod: submitMethod, askForReason: true, }; if (app.attributes.platformHealthOnlyShowOverride && app.attributes.platformHealthOnly) { confirmationModalParams.interestingHealthProviderNames = ['Google']; } ConfirmationModalService.confirm(confirmationModalParams); }; this.rollbackServerGroup = () => { $uibModal.open({ templateUrl: require('./rollback/rollbackServerGroup.html'), controller: 'gceRollbackServerGroupCtrl as ctrl', resolve: { serverGroup: () => this.serverGroup, disabledServerGroups: () => { const cluster = _.find(app.clusters, { name: this.serverGroup.cluster, account: this.serverGroup.account, }); return _.filter(cluster.serverGroups, { isDisabled: true, region: this.serverGroup.region }); }, application: () => app, }, }); }; this.resizeServerGroup = () => { $uibModal.open({ templateUrl: require('./resize/resizeServerGroup.html'), controller: 'gceResizeServerGroupCtrl as ctrl', resolve: { serverGroup: () => { return this.serverGroup; }, application: () => { return app; }, }, }); }; this.cloneServerGroup = (serverGroup) => { $uibModal.open({ templateUrl: require('../configure/wizard/serverGroupWizard.html'), controller: 'gceCloneServerGroupCtrl as ctrl', size: 'lg', resolve: { title: () => { return 'Clone ' + serverGroup.name; }, application: () => { return app; }, serverGroup: () => { return serverGroup; }, serverGroupCommand: () => { return gceServerGroupCommandBuilder.buildServerGroupCommandFromExisting(app, serverGroup); }, }, }); }; this.showStartupScript = () => { $scope.userDataModalTitle = 'Startup Script'; $scope.serverGroup = { name: this.serverGroup.name }; $scope.userData = this.serverGroup.startupScript; $uibModal.open({ templateUrl: ServerGroupTemplates.userData, scope: $scope, }); }; this.buildJenkinsLink = () => { if (this.serverGroup && this.serverGroup.buildInfo && this.serverGroup.buildInfo.buildInfoUrl) { return this.serverGroup.buildInfo.buildInfoUrl; } else if (this.serverGroup && this.serverGroup.buildInfo && this.serverGroup.buildInfo.jenkins) { const jenkins = this.serverGroup.buildInfo.jenkins; return jenkins.host + 'job/' + jenkins.name + '/' + jenkins.number; } return null; }; this.truncateCommitHash = () => { if (this.serverGroup && this.serverGroup.buildInfo && this.serverGroup.buildInfo.commit) { return this.serverGroup.buildInfo.commit.substring(0, 8); } return null; }; const configureEntityTagTargets = () => { this.entityTagTargets = ClusterTargetBuilder.buildClusterTargets(this.serverGroup); }; }, ]);