From c072761b18e4690c352ed0348651725b9e9c2269 Mon Sep 17 00:00:00 2001 From: chrisb Date: Sat, 30 Jan 2016 11:46:41 -0800 Subject: [PATCH 001/151] get provider, vpcId from configured security group --- .../securityGroup/details/securityGroupDetail.controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/modules/amazon/securityGroup/details/securityGroupDetail.controller.js b/app/scripts/modules/amazon/securityGroup/details/securityGroupDetail.controller.js index 40dec6cda7e..33f37fd9b54 100644 --- a/app/scripts/modules/amazon/securityGroup/details/securityGroupDetail.controller.js +++ b/app/scripts/modules/amazon/securityGroup/details/securityGroupDetail.controller.js @@ -102,8 +102,8 @@ module.exports = angular.module('spinnaker.securityGroup.aws.details.controller' var submitMethod = function () { return securityGroupWriter.deleteSecurityGroup(securityGroup, application, { - cloudProvider: $scope.securityGroup.type, - vpcId: $scope.securityGroup.vpcId, + cloudProvider: securityGroup.provider, + vpcId: securityGroup.vpcId, }); }; From 38997b267192222e5dd40a758609871a3a620561 Mon Sep 17 00:00:00 2001 From: duftler Date: Mon, 1 Feb 2016 14:17:51 -0500 Subject: [PATCH 002/151] Rename rebakeControlEnabled to roscoMode, as it now guards more than just the single Rebake control. Add support to Bake Stage for optional Template File Name field (it is only rendered if roscoMode is enabled). --- app/scripts/modules/core/help/helpContents.js | 1 + .../core/pipeline/config/stages/bake/aws/awsBakeStage.js | 2 +- .../stages/bake/aws/bakeExecutionDetails.controller.js | 2 +- .../config/stages/bake/aws/bakeExecutionDetails.html | 6 ++++-- .../core/pipeline/config/stages/bake/aws/bakeStage.html | 9 +++++++-- .../stages/bake/gce/bakeExecutionDetails.controller.js | 2 +- .../config/stages/bake/gce/bakeExecutionDetails.html | 6 ++++-- .../core/pipeline/config/stages/bake/gce/bakeStage.html | 9 +++++++-- .../core/pipeline/config/stages/bake/gce/gceBakeStage.js | 2 +- settings.js | 2 +- 10 files changed, 28 insertions(+), 13 deletions(-) diff --git a/app/scripts/modules/core/help/helpContents.js b/app/scripts/modules/core/help/helpContents.js index 1b9013482f3..495c6c23887 100644 --- a/app/scripts/modules/core/help/helpContents.js +++ b/app/scripts/modules/core/help/helpContents.js @@ -157,6 +157,7 @@ module.exports = angular.module('spinnaker.core.help.contents', []) 'pipeline.config.bake.amiSuffix': '

(Optional) String of date in format YYYYMMDDHHmm, default is calculated from timestamp,

', 'pipeline.config.bake.enhancedNetworking': '

(Optional) Enable enhanced networking (sr-iov) support for image (requires hvm and trusty base_os).

', 'pipeline.config.bake.amiName': '

(Optional) Default = $package-$arch-$ami_suffix-$store_type

', + 'pipeline.config.bake.templateFileName': '

(Optional) The explicit packer template to use, instead of resolving one from rosco\'s configuration.

', 'pipeline.config.gce.bake.baseImage': '

(Optional) A GCE image name. For example: ubuntu-1204-precise-v20150910.

', 'pipeline.config.manualJudgment.instructions': '

(Optional) Instructions are shown to the user when making a manual judgment.

May contain HTML.

', 'pipeline.config.manualJudgment.failPipeline': '' + diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/aws/awsBakeStage.js b/app/scripts/modules/core/pipeline/config/stages/bake/aws/awsBakeStage.js index 9bffd8a48be..bfa2291afb9 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/aws/awsBakeStage.js +++ b/app/scripts/modules/core/pipeline/config/stages/bake/aws/awsBakeStage.js @@ -80,7 +80,7 @@ module.exports = angular.module('spinnaker.core.pipeline.stage.aws.bakeStage', [ if (!$scope.stage.baseLabel && $scope.baseLabelOptions && $scope.baseLabelOptions.length) { $scope.stage.baseLabel = $scope.baseLabelOptions[0]; } - $scope.viewState.rebakeControlEnabled = settings.feature.rebakeControlEnabled; + $scope.viewState.roscoMode = settings.feature.roscoMode; $scope.viewState.loading = false; }); } diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.controller.js b/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.controller.js index 9fe57e92766..6fa31b572fc 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.controller.js +++ b/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.controller.js @@ -22,7 +22,7 @@ module.exports = angular.module('spinnaker.core.pipeline.stage.bake.aws.executio $scope.provider = $scope.stage.context.cloudProviderType || 'aws'; }); - $scope.rebakeControlEnabled = settings.feature.rebakeControlEnabled; + $scope.roscoMode = settings.feature.roscoMode; $scope.bakeryDetailUrl = $interpolate(settings.bakeryDetailUrl); } diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.html b/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.html index 99317af6b15..6188f919096 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.html +++ b/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeExecutionDetails.html @@ -24,8 +24,10 @@
{{stage.context.storeType | uppercase}}
Label
{{stage.context.baseLabel}}
-
Rebake
-
{{stage.context.rebake || false}}
+
Rebake
+
{{stage.context.rebake || false}}
+
Template
+
{{stage.context.templateFileName}}
diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeStage.html b/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeStage.html index bdfcd6546bf..d5e177e69da 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeStage.html +++ b/app/scripts/modules/core/pipeline/config/stages/bake/aws/bakeStage.html @@ -44,8 +44,8 @@

{{baseLabel}} - - + +
+ + + diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.controller.js b/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.controller.js index de193575365..9c8fe93f740 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.controller.js +++ b/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.controller.js @@ -22,7 +22,7 @@ module.exports = angular.module('spinnaker.core.pipeline.stage.bake.gce.executio $scope.provider = $scope.stage.context.cloudProviderType || 'gce'; }); - $scope.rebakeControlEnabled = settings.feature.rebakeControlEnabled; + $scope.roscoMode = settings.feature.roscoMode; $scope.bakeryDetailUrl = $interpolate(settings.bakeryDetailUrl); } diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.html b/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.html index 53376636f28..9728f5451f3 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.html +++ b/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeExecutionDetails.html @@ -20,8 +20,10 @@
{{stage.context.baseOs}}
Label
{{stage.context.baseLabel}}
-
Rebake
-
{{stage.context.rebake || false}}
+
Rebake
+
{{stage.context.rebake || false}}
+
Template
+
{{stage.context.templateFileName}}
diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeStage.html b/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeStage.html index 5ed6873a4af..e0c3673be4b 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeStage.html +++ b/app/scripts/modules/core/pipeline/config/stages/bake/gce/bakeStage.html @@ -21,8 +21,8 @@
- - + +
+ + + diff --git a/app/scripts/modules/core/pipeline/config/stages/bake/gce/gceBakeStage.js b/app/scripts/modules/core/pipeline/config/stages/bake/gce/gceBakeStage.js index f689c0fdc92..72daf4683f0 100644 --- a/app/scripts/modules/core/pipeline/config/stages/bake/gce/gceBakeStage.js +++ b/app/scripts/modules/core/pipeline/config/stages/bake/gce/gceBakeStage.js @@ -53,7 +53,7 @@ module.exports = angular.module('spinnaker.core.pipeline.stage.gce.bakeStage', [ if (!$scope.stage.baseLabel && $scope.baseLabelOptions && $scope.baseLabelOptions.length) { $scope.stage.baseLabel = $scope.baseLabelOptions[0]; } - $scope.viewState.rebakeControlEnabled = settings.feature.rebakeControlEnabled; + $scope.viewState.roscoMode = settings.feature.roscoMode; $scope.viewState.loading = false; }); } diff --git a/settings.js b/settings.js index d7c2e084237..020670ff577 100644 --- a/settings.js +++ b/settings.js @@ -58,7 +58,7 @@ window.spinnakerSettings = { fastProperty: true, vpcMigrator: true, clusterDiff: true, - rebakeControlEnabled: false, + roscoMode: false, netflixMode: false, }, }; From 1984b34d7895ae2e88d23a176150504e38e26539 Mon Sep 17 00:00:00 2001 From: bfarrell Date: Mon, 1 Feb 2016 19:48:56 -0800 Subject: [PATCH 003/151] Update manual jdgment state to allow inputs to be set and utilized at execution time. --- app/scripts/modules/core/help/helpContents.js | 3 +- .../manualJudgment/manualJudgment.service.js | 5 ++- ...nualJudgmentExecutionDetails.controller.js | 7 ++-- .../manualJudgmentExecutionDetails.html | 13 +++++++- .../manualJudgment/manualJudgmentStage.html | 33 +++++++++++++++++++ .../manualJudgment/manualJudgmentStage.js | 12 +++++++ 6 files changed, 65 insertions(+), 8 deletions(-) diff --git a/app/scripts/modules/core/help/helpContents.js b/app/scripts/modules/core/help/helpContents.js index 495c6c23887..c82745eb9f4 100644 --- a/app/scripts/modules/core/help/helpContents.js +++ b/app/scripts/modules/core/help/helpContents.js @@ -157,12 +157,13 @@ module.exports = angular.module('spinnaker.core.help.contents', []) 'pipeline.config.bake.amiSuffix': '

(Optional) String of date in format YYYYMMDDHHmm, default is calculated from timestamp,

', 'pipeline.config.bake.enhancedNetworking': '

(Optional) Enable enhanced networking (sr-iov) support for image (requires hvm and trusty base_os).

', 'pipeline.config.bake.amiName': '

(Optional) Default = $package-$arch-$ami_suffix-$store_type

', - 'pipeline.config.bake.templateFileName': '

(Optional) The explicit packer template to use, instead of resolving one from rosco\'s configuration.

', 'pipeline.config.gce.bake.baseImage': '

(Optional) A GCE image name. For example: ubuntu-1204-precise-v20150910.

', 'pipeline.config.manualJudgment.instructions': '

(Optional) Instructions are shown to the user when making a manual judgment.

May contain HTML.

', 'pipeline.config.manualJudgment.failPipeline': '' + '

Checked - the overall pipeline will fail whenever the manual judgment is negative.

' + '

Unchecked - the overall pipeline will continue executing but this particular branch will stop.

', + 'pipeline.config.manualJudgment.judgmentInputs': '

(Optional) Entries populate input dropdown when making manual judgment.

' + + '

Selected value can be used in precondition to determine branching. e.g. execution.stages[n].context.judgmentInput==value

', 'pipeline.config.failPipeline': '' + '

Checked - the overall pipeline will fail whenever the stage fails.

' + '

Unchecked - the overall pipeline will continue executing but this particular branch will stop.

', diff --git a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgment.service.js b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgment.service.js index 0c25188fbad..83c9fb954dd 100644 --- a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgment.service.js +++ b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgment.service.js @@ -20,16 +20,15 @@ module.exports = angular }; }; - let provideJudgment = (execution, stage, judgment) => { + let provideJudgment = (execution, stage, judgment, input) => { var targetUrl = [settings.gateUrl, 'pipelines', execution.id, 'stages', stage.id].join('/'); var deferred = $q.defer(); var request = { method: 'PATCH', url: targetUrl, - data: {judgmentStatus: judgment}, + data: {judgmentStatus: judgment, judgmentInput: input}, timeout: settings.pollSchedule * 2 + 5000, // TODO: replace with apiHost call }; - $http(request) .success(() => { executionService.waitUntilExecutionMatches(execution.id, buildMatcher(stage, judgment, deferred)) diff --git a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.controller.js b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.controller.js index fad5ab9514b..6517b12b69c 100644 --- a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.controller.js +++ b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.controller.js @@ -16,6 +16,7 @@ module.exports = angular $scope.viewState = { submitting: false, judgmentDecision: null, + judgmentInput: null, error: false, }; @@ -38,12 +39,12 @@ module.exports = angular $scope.viewState.error = true; } - this.provideJudgment = (judgmentDecision) => { + this.provideJudgment = (judgmentDecision, judgmentInput) => { $scope.viewState.submitting = true; $scope.viewState.error = false; $scope.viewState.judgmentDecision = judgmentDecision; - return manualJudgmentService.provideJudgment($scope.execution, $scope.stage, judgmentDecision) + $scope.viewState.judgmentInput = judgmentInput; + return manualJudgmentService.provideJudgment($scope.execution, $scope.stage, judgmentDecision, judgmentInput) .then(judgmentMade, judgmentFailure); }; - }); diff --git a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html index a37df204fc1..4823da085d2 100644 --- a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html +++ b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html @@ -10,12 +10,23 @@

{{ stage.endTime | timestamp }}
+
Input
+
{{ stage.context.judgmentInput | robotToHuman}}
Instructions
- diff --git a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html index d9e71beaee8..82ad24cef2e 100644 --- a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html +++ b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html @@ -13,6 +13,39 @@
+ + + + + + + + + + + + + + + + + + + +
Input ValueActions
+
+ +
+
+ Remove +
+ +
+
diff --git a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.js b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.js index 87df5f66782..ca8d9503377 100644 --- a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.js +++ b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.js @@ -19,6 +19,7 @@ module.exports = angular.module('spinnaker.core.pipeline.stage.manualJudgmentSta .controller('ManualJudgmentStageCtrl', function($scope, $uibModal) { $scope.stage.notifications = $scope.stage.notifications || []; + $scope.stage.judgmentInputs = $scope.stage.judgmentInputs || []; $scope.stage.failPipeline = ($scope.stage.failPipeline === undefined ? true : $scope.stage.failPipeline); this.addNotification = function() { @@ -40,4 +41,15 @@ module.exports = angular.module('spinnaker.core.pipeline.stage.manualJudgmentSta $scope.stage.notifications.splice(idx, 1); }; + this.addJudgmentInput = function() { + if (!$scope.stage.judgmentInputs) { + $scope.stage.judgmentInputs = []; + } + var judgmentInput = {}; + $scope.stage.judgmentInputs.push(judgmentInput); + }; + + this.removeJudgmentInput = function (idx) { + $scope.stage.judgmentInputs.splice(idx, 1); + }; }); From 703cd203bcd5af14366d82c0df0deb5e2db6bdcc Mon Sep 17 00:00:00 2001 From: Brendan Farrell Date: Mon, 1 Feb 2016 21:55:55 -0600 Subject: [PATCH 004/151] Readd deleted help message. --- app/scripts/modules/core/help/helpContents.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/scripts/modules/core/help/helpContents.js b/app/scripts/modules/core/help/helpContents.js index c82745eb9f4..c01b224a21d 100644 --- a/app/scripts/modules/core/help/helpContents.js +++ b/app/scripts/modules/core/help/helpContents.js @@ -157,6 +157,7 @@ module.exports = angular.module('spinnaker.core.help.contents', []) 'pipeline.config.bake.amiSuffix': '

(Optional) String of date in format YYYYMMDDHHmm, default is calculated from timestamp,

', 'pipeline.config.bake.enhancedNetworking': '

(Optional) Enable enhanced networking (sr-iov) support for image (requires hvm and trusty base_os).

', 'pipeline.config.bake.amiName': '

(Optional) Default = $package-$arch-$ami_suffix-$store_type

', + 'pipeline.config.bake.templateFileName': '

(Optional) The explicit packer template to use, instead of resolving one from rosco\'s configuration.

', 'pipeline.config.gce.bake.baseImage': '

(Optional) A GCE image name. For example: ubuntu-1204-precise-v20150910.

', 'pipeline.config.manualJudgment.instructions': '

(Optional) Instructions are shown to the user when making a manual judgment.

May contain HTML.

', 'pipeline.config.manualJudgment.failPipeline': '' + From 0f9e1ce75a8fc29d9c2c11984408b7a79c247ed6 Mon Sep 17 00:00:00 2001 From: chrisb Date: Mon, 1 Feb 2016 22:28:09 -0800 Subject: [PATCH 005/151] style tweaks to judgment inputs --- app/scripts/modules/core/help/helpContents.js | 8 ++++++-- app/scripts/modules/core/modal/modals.less | 4 ++++ .../manualJudgmentExecutionDetails.html | 4 ++-- .../manualJudgment/manualJudgmentStage.html | 19 ++++++++----------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/app/scripts/modules/core/help/helpContents.js b/app/scripts/modules/core/help/helpContents.js index c01b224a21d..ec04d61fdf3 100644 --- a/app/scripts/modules/core/help/helpContents.js +++ b/app/scripts/modules/core/help/helpContents.js @@ -163,8 +163,12 @@ module.exports = angular.module('spinnaker.core.help.contents', []) 'pipeline.config.manualJudgment.failPipeline': '' + '

Checked - the overall pipeline will fail whenever the manual judgment is negative.

' + '

Unchecked - the overall pipeline will continue executing but this particular branch will stop.

', - 'pipeline.config.manualJudgment.judgmentInputs': '

(Optional) Entries populate input dropdown when making manual judgment.

' + - '

Selected value can be used in precondition to determine branching. e.g. execution.stages[n].context.judgmentInput==value

', + 'pipeline.config.manualJudgment.judgmentInputs': '

(Optional) Entries populate a dropdown displayed when ' + + 'performing a manual judgment.

' + + '

The selected value can be used in a subsequent Check Preconditions stage to determine branching.

' + + '

For example, if the user selects "rollback" from this list of options, that branch can be activated by using the ' + + 'expression: ' + + 'execution.stages[n].context.judgmentInput=="rollback"

', 'pipeline.config.failPipeline': '' + '

Checked - the overall pipeline will fail whenever the stage fails.

' + '

Unchecked - the overall pipeline will continue executing but this particular branch will stop.

', diff --git a/app/scripts/modules/core/modal/modals.less b/app/scripts/modules/core/modal/modals.less index 833d6b7fa68..fcb6b7f9498 100644 --- a/app/scripts/modules/core/modal/modals.less +++ b/app/scripts/modules/core/modal/modals.less @@ -237,6 +237,10 @@ select.select2 { background: #ffffff; } +abbr.select2-search-choice-close { + margin-top: 0; +} + .select2-container-multi { &.select2-container-active { .select2-choices { diff --git a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html index 4823da085d2..637129a8d7f 100644 --- a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html +++ b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentExecutionDetails.html @@ -12,12 +12,12 @@
Input
{{ stage.context.judgmentInput | robotToHuman}}
-
Instructions
+
Instructions
-
+

Judgment Input

{{$select.selected.value}} diff --git a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html index 82ad24cef2e..a5bfcf0705e 100644 --- a/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html +++ b/app/scripts/modules/core/pipeline/config/stages/manualJudgment/manualJudgmentStage.html @@ -13,25 +13,22 @@
- +
- - + + - @@ -52,7 +49,7 @@ - + @@ -63,8 +60,8 @@ - From 86bb98ad8a90e586731cb7bc82a8b8a6b6a9d396 Mon Sep 17 00:00:00 2001 From: chrisb Date: Tue, 2 Feb 2016 07:51:45 -0800 Subject: [PATCH 006/151] fdescribe -> describe --- app/scripts/modules/netflix/migrator/migrator.service.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/modules/netflix/migrator/migrator.service.spec.js b/app/scripts/modules/netflix/migrator/migrator.service.spec.js index b9bf7e2027b..d7e2cbde4d9 100644 --- a/app/scripts/modules/netflix/migrator/migrator.service.spec.js +++ b/app/scripts/modules/netflix/migrator/migrator.service.spec.js @@ -1,6 +1,6 @@ 'use strict'; -fdescribe('Service: migrator', function () { +describe('Service: migrator', function () { var service, $q, $scope, taskExecutor; From cabf0a97aad02205cb9273b89eb4ec0f2bb4cf4f Mon Sep 17 00:00:00 2001 From: chrisb Date: Tue, 2 Feb 2016 09:20:43 -0800 Subject: [PATCH 007/151] show instance details view when single instance selected in multiselect mode --- .../cluster/filter/clusterFilter.model.js | 51 ++++++++++++++++--- .../filter/clusterFilter.model.spec.js | 45 +++++++++++++--- app/scripts/modules/core/cluster/rollups.less | 4 -- .../details/multipleInstances.controller.js | 15 +++--- .../instance/instanceListBody.directive.js | 20 +------- 5 files changed, 95 insertions(+), 40 deletions(-) diff --git a/app/scripts/modules/core/cluster/filter/clusterFilter.model.js b/app/scripts/modules/core/cluster/filter/clusterFilter.model.js index 2bd4edc87bd..4cff4ca2d1b 100644 --- a/app/scripts/modules/core/cluster/filter/clusterFilter.model.js +++ b/app/scripts/modules/core/cluster/filter/clusterFilter.model.js @@ -54,16 +54,39 @@ module.exports = angular }; this.syncNavigation = () => { - let instancesSelected = 0; - this.multiselectInstanceGroups.forEach((instanceGroup) => { - instancesSelected += instanceGroup.instanceIds.length; - }); + // this method gets called on page initialization, so if we're deep linked to an instance details view, leave it + if (!this.multiselectInstanceGroups.length && $state.params.instanceId) { + return; + } + + let instancesSelected = this.multiselectInstanceGroups.reduce((acc, group) => acc + group.instanceIds.length, 0); + + if (instancesSelected === 1) { + // if there's just one instance selected and we're not showing instance details, do so + if (!$state.includes('**.instanceDetails')) { + let [match] = this.multiselectInstanceGroups.filter((group) => group.instanceIds.length), + params = {provider: match.cloudProvider, instanceId: match.instanceIds[0]}; + if ($state.includes('**.clusters.*')) { + $state.go('^.instanceDetails', params); + } else { + $state.go('.instanceDetails', params); + } + } + return; + } + + // if the user just de-selected the one instance, close the details view + if (this.sortFilter.listInstances && $state.includes('**.instanceDetails') && instancesSelected === 0) { + $state.go('^'); + } if ($state.includes('**.multipleInstances') && !instancesSelected) { $state.go('^'); } - if (!$state.includes('**.multipleInstances') && instancesSelected) { + if (!$state.includes('**.multipleInstances') && instancesSelected > 1) { + // user selected multiple instances if ($state.includes('**.clusters.*')) { + // from a child state, e.g. instanceDetails $state.go('^.multipleInstances'); } else { $state.go('.multipleInstances'); @@ -71,6 +94,14 @@ module.exports = angular } }; + this.clearAllMultiselectGroups = () => { + this.multiselectInstanceGroups.forEach((instanceGroup) => { + instanceGroup.instanceIds.length = 0; + instanceGroup.selectAll = false; + }); + this.multiselectInstancesStream.onNext(); + }; + this.getOrCreateMultiselectInstanceGroup = (serverGroup) => { let serverGroupName = serverGroup.name, account = serverGroup.account, @@ -83,12 +114,17 @@ module.exports = angular instanceGroup.cloudProvider === cloudProvider; }); if (!result) { + // when creating a new group, include an instance ID if we're deep-linked into the details view + let params = $state.params; + let instanceIds = (serverGroup.instances || []) + .filter((instance) => instance.provider === params.provider && instance.id === params.instanceId) + .map((instance) => instance.id); result = { serverGroup: serverGroupName, account: account, region: region, cloudProvider: cloudProvider, - instanceIds: [], + instanceIds: instanceIds, instances: [], // populated by details controller selectAll: false, }; @@ -178,6 +214,9 @@ module.exports = angular if (movingFromClusterState(toState, fromState)) { this.saveState(fromState, fromParams, mostRecentParams); } + if ($state.includes('**.instanceDetails') && this.sortFilter.listInstances && isClusterState(toState.name)) { + this.clearAllMultiselectGroups(); + } }; $rootScope.$on('$stateChangeStart', this.handleStateChangeStart); diff --git a/app/scripts/modules/core/cluster/filter/clusterFilter.model.spec.js b/app/scripts/modules/core/cluster/filter/clusterFilter.model.spec.js index 5d91903c9ac..e99bddb2995 100644 --- a/app/scripts/modules/core/cluster/filter/clusterFilter.model.spec.js +++ b/app/scripts/modules/core/cluster/filter/clusterFilter.model.spec.js @@ -22,6 +22,7 @@ describe('Cluster Filter Model', function () { this.currentStates = []; spyOn($state, 'includes').and.callFake((substate) => this.currentStates.indexOf(substate) > -1); spyOn($state, 'go').and.callFake((newState) => this.result = newState); + $state.params = {}; }); describe('syncNavigation', function () { @@ -32,30 +33,54 @@ describe('Cluster Filter Model', function () { it('navigates to multipleInstances child view when not already there and instances are selected', function () { this.instanceGroup.instanceIds.push('i-123'); - this.currentStates = ['**.clusters.*']; + this.instanceGroup.instanceIds.push('i-124'); + this.currentStates = ['**.clusters']; ClusterFilterModel.syncNavigation(); - expect(this.result).toBe('^.multipleInstances'); + expect(this.result).toBe('.multipleInstances'); + }); + + it('navigates to instanceDetails child view when not already there and an instance is selected', function () { + this.instanceGroup.instanceIds.push('i-123'); + this.currentStates = ['**.clusters']; + ClusterFilterModel.syncNavigation(); + expect(this.result).toBe('.instanceDetails'); }); it('navigates to multipleInstances sibling view when not already there and instances are selected', function () { this.instanceGroup.instanceIds.push('i-123'); - this.currentStates = ['**.clusters.instanceDetails']; + this.instanceGroup.instanceIds.push('i-124'); + this.currentStates = ['**.clusters.*', '**.clusters.instanceDetails']; ClusterFilterModel.syncNavigation(); - expect(this.result).toBe('.multipleInstances'); + expect(this.result).toBe('^.multipleInstances'); + }); + + it('navigates to instanceDetails sibling view when not already there and instances are selected', function () { + this.instanceGroup.instanceIds.push('i-124'); + this.currentStates = ['**.clusters.*', '**.clusters.instanceDetails']; + ClusterFilterModel.syncNavigation(); + expect(this.result).toBe('^.instanceDetails'); }); it('does not navigate when already in multipleInstances view', function () { this.instanceGroup.instanceIds.push('i-123'); - this.currentStates = ['**.multipleInstances']; + this.instanceGroup.instanceIds.push('i-124'); + this.currentStates = ['**.clusters.*', '**.multipleInstances']; ClusterFilterModel.syncNavigation(); expect(this.result).toBe(null); }); it('navigates away from multipleInstances view when no instances are selected', function () { - this.currentStates = ['**.multipleInstances']; + this.currentStates = ['**.clusters.*', '**.multipleInstances']; ClusterFilterModel.syncNavigation(); expect(this.result).toBe('^'); }); + + it('navigates to instanceDetails view when just one instance remains selected', function () { + this.instanceGroup.instanceIds.push('i-123'); + this.currentStates = ['**.clusters.*', '**.multipleInstances']; + ClusterFilterModel.syncNavigation(); + expect(this.result).toBe('^.instanceDetails'); + }); }); describe('getOrCreateMultiselectInstanceGroup', function () { @@ -97,6 +122,14 @@ describe('Cluster Filter Model', function () { let test = ClusterFilterModel.getOrCreateMultiselectInstanceGroup(this.serverGroup); expect(test).not.toBe(this.original); }); + + it('includes instance id if present in state params', function () { + $state.params = { provider: 'aws', instanceId: 'i-123' }; + this.serverGroup.instances = [ { id: 'i-123', provider: 'aws' } ]; + this.serverGroup.name = 'asg-v002'; + let test = ClusterFilterModel.getOrCreateMultiselectInstanceGroup(this.serverGroup); + expect(test.instanceIds).toEqual(['i-123']); + }); }); describe('toggleMultiselectInstance', function () { diff --git a/app/scripts/modules/core/cluster/rollups.less b/app/scripts/modules/core/cluster/rollups.less index 820f3ce2b84..4b344beabb6 100644 --- a/app/scripts/modules/core/cluster/rollups.less +++ b/app/scripts/modules/core/cluster/rollups.less @@ -76,10 +76,6 @@ font-size: 200%; margin: 0; } - tr.instance-row:hover > td.no-hover { - background-color: #ffffff; - cursor: default; - } a.instance { margin: 0; display: inline-block; diff --git a/app/scripts/modules/core/instance/details/multipleInstances.controller.js b/app/scripts/modules/core/instance/details/multipleInstances.controller.js index 6b779c5d76a..79e6ea8f623 100644 --- a/app/scripts/modules/core/instance/details/multipleInstances.controller.js +++ b/app/scripts/modules/core/instance/details/multipleInstances.controller.js @@ -200,17 +200,15 @@ module.exports = angular.module('spinnaker.core.instance.details.multipleInstanc }; }; - + let countInstances = () => { + return ClusterFilterModel.multiselectInstanceGroups.reduce((acc, group) => acc + group.instanceIds.length, 0); + }; let retrieveInstances = () => { - this.instancesCount = 0; + this.instancesCount = countInstances(); this.selectedGroups = ClusterFilterModel.multiselectInstanceGroups .filter((group) => group.instanceIds.length) .map(makeServerGroupModel); - - this.selectedGroups.forEach((group) => { - this.instancesCount += group.instances.length; - }); }; let multiselectWatcher = ClusterFilterModel.multiselectInstancesStream.subscribe(retrieveInstances); @@ -219,6 +217,11 @@ module.exports = angular.module('spinnaker.core.instance.details.multipleInstanc retrieveInstances(); $scope.$on('$destroy', () => { + // if there's just one instance selected, this is being destroyed because we're moving to the instanceDetails + // view; otherwise, deselect any instances because the user is closing the panel explicitly + if (countInstances() !== 1) { + ClusterFilterModel.clearAllMultiselectGroups(); + } refreshWatcher.dispose(); multiselectWatcher.dispose(); }); diff --git a/app/scripts/modules/core/instance/instanceListBody.directive.js b/app/scripts/modules/core/instance/instanceListBody.directive.js index 94db4d364f2..d3e62072acc 100644 --- a/app/scripts/modules/core/instance/instanceListBody.directive.js +++ b/app/scripts/modules/core/instance/instanceListBody.directive.js @@ -23,8 +23,6 @@ module.exports = angular.module('spinnaker.core.instance.instanceListBody.direct instanceGroup = ClusterFilterModel.getOrCreateMultiselectInstanceGroup(scope.serverGroup), activeInstance = null; - var base = elem.parent().inheritedData('$uiView').state; - function toggleSelection(instanceId) { ClusterFilterModel.toggleMultiselectInstance(scope.serverGroup, instanceId); } @@ -35,7 +33,7 @@ module.exports = angular.module('spinnaker.core.instance.instanceListBody.direct function buildInstanceCheckboxCell(instance) { let isChecked = ClusterFilterModel.instanceIsMultiselected(scope.serverGroup, instance.id); - return ``; + return ``; } function buildInstanceIdCell(instance) { @@ -208,12 +206,6 @@ module.exports = angular.module('spinnaker.core.instance.instanceListBody.direct elem.click(function(event) { $timeout(function() { if (event.target) { - let $target = $(event.target); - if ($target.is(':checkbox')) { - toggleSelection(event.target.getAttribute('data-instance-id')); - event.preventDefault(); - return; - } // anything handled by ui-sref or actual links should be ignored if (event.isDefaultPrevented() || (event.originalEvent && (event.originalEvent.defaultPrevented || event.originalEvent.target.href))) { return; @@ -225,15 +217,7 @@ module.exports = angular.module('spinnaker.core.instance.instanceListBody.direct if (activeInstance) { $('tr[data-instance-id="' + activeInstance.instanceId + '"]', elem).removeClass('active'); } - var targetRow = $targetRow.get(0); - var params = { - instanceId: targetRow.getAttribute('data-instance-id'), - provider: targetRow.getAttribute('data-provider') - }; - activeInstance = params; - // also stolen from uiSref directive - $state.go('.instanceDetails', params, {relative: base, inherit: true}); - $targetRow.addClass('active'); + toggleSelection($targetRow.attr('data-instance-id')); event.preventDefault(); } }); From b8f256977bb074bc8619db32759947f887ba8fb4 Mon Sep 17 00:00:00 2001 From: Zan Thrash Date: Wed, 3 Feb 2016 11:51:21 -0800 Subject: [PATCH 008/151] SPIN-1453: Adding new ACA Config selector to FP ACA screen. This selector gets a list of all previous Canary Configs for a given app. When the user selects a previous confg it populates the Canary Config form with the values. This can eventually go into the ACA pipeline stage I just want to get it out there and get some feedback from users. --- .../netflix/canary/canary.read.service.js | 9 ++- .../canaryConfigSelector.directive.html | 19 +++++++ .../canary/canaryConfigSelector.directive.js | 57 +++++++++++++++++++ app/scripts/modules/netflix/canary/index.js | 3 +- .../fastPropertyAcaConfigForm.directive.html | 17 +++++- 5 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 app/scripts/modules/netflix/canary/canaryConfigSelector.directive.html create mode 100644 app/scripts/modules/netflix/canary/canaryConfigSelector.directive.js diff --git a/app/scripts/modules/netflix/canary/canary.read.service.js b/app/scripts/modules/netflix/canary/canary.read.service.js index 05db2d49e31..1020686d2eb 100644 --- a/app/scripts/modules/netflix/canary/canary.read.service.js +++ b/app/scripts/modules/netflix/canary/canary.read.service.js @@ -9,12 +9,17 @@ module.exports = angular ]) .factory('canaryReadService', function(Restangular) { - function getCanaryById(canaryId) { + let getCanaryById = (canaryId) => { return Restangular.one('canaries').one(canaryId).get(); - } + }; + + let getCanaryConfigsByApplication = (applicationName) => { + return Restangular.one('canaryConfigs').one(applicationName).getList(); + }; return { getCanaryById: getCanaryById, + getCanaryConfigsByApplication: getCanaryConfigsByApplication }; }); diff --git a/app/scripts/modules/netflix/canary/canaryConfigSelector.directive.html b/app/scripts/modules/netflix/canary/canaryConfigSelector.directive.html new file mode 100644 index 00000000000..241246dd8a3 --- /dev/null +++ b/app/scripts/modules/netflix/canary/canaryConfigSelector.directive.html @@ -0,0 +1,19 @@ +
+
+ + + + {{$select.selected.name}} + + + + {{option.name}} + + + +
+
diff --git a/app/scripts/modules/netflix/canary/canaryConfigSelector.directive.js b/app/scripts/modules/netflix/canary/canaryConfigSelector.directive.js new file mode 100644 index 00000000000..777e50a032c --- /dev/null +++ b/app/scripts/modules/netflix/canary/canaryConfigSelector.directive.js @@ -0,0 +1,57 @@ +'use strict'; + +let angular = require('angular'); + +module.exports = angular + .module('spinnaker.netfilx.widgits.canaryConfigSelector.directive', [ + require('./canary.read.service'), + require('../../core/utils/lodash') + ]) + .directive('canaryConfigSelector', () => { + return { + scope: {}, + bindToController: { + model: '=' , + applicationName: '=' + }, + templateUrl: require('./canaryConfigSelector.directive.html'), + controllerAs: 'vm', + controller: function($scope, canaryReadService, _) { + let vm = this; + + vm.selectorChanged = (model) => { + if (model) { + vm.model = model; + vm.model.successfulScore = model.canarySuccessCriteria.canaryResultScore; + vm.model.unhealthyScore = model.canaryHealthCheckHandler.minimumCanaryResultScore; + vm.model.resultStrategy = model.combinedCanaryResultStrategy; + } + }; + + vm.isNameInConfigList = (selectedName) => { + return getSelected(vm.canaryConfigs, selectedName).length ? true : false; + }; + + let setOptions = (results) => { + vm.canaryConfigs = results; + return vm.canaryConfigs; + }; + + let getSelected = _.curry((canaryConfigs = [], canaryName) => { + return canaryConfigs.filter((config) => config.name === canaryName); + }); + + let findConfigAndSet = _.flowRight(vm.selectorChanged, _.first, getSelected); + + $scope.$watch('vm.model.name', function(newVal) { + if(newVal !== undefined) { + findConfigAndSet(vm.canaryConfigs, newVal); + } + }); + + canaryReadService.getCanaryConfigsByApplication(vm.applicationName) + .then(setOptions); + + } + }; + }); diff --git a/app/scripts/modules/netflix/canary/index.js b/app/scripts/modules/netflix/canary/index.js index 43852d89240..999f0820710 100644 --- a/app/scripts/modules/netflix/canary/index.js +++ b/app/scripts/modules/netflix/canary/index.js @@ -4,5 +4,6 @@ let angular = require('angular'); module.exports = angular .module('spinnaker.core.canary', [ - require('./canaryAnalysisNameSelector.directive.js') + require('./canaryAnalysisNameSelector.directive.js'), + require('./canaryConfigSelector.directive') ]); diff --git a/app/scripts/modules/netflix/fastProperties/modal/wizard/fastPropertyAcaConfigForm.directive.html b/app/scripts/modules/netflix/fastProperties/modal/wizard/fastPropertyAcaConfigForm.directive.html index 54858700f2c..0c028bd2e44 100644 --- a/app/scripts/modules/netflix/fastProperties/modal/wizard/fastPropertyAcaConfigForm.directive.html +++ b/app/scripts/modules/netflix/fastProperties/modal/wizard/fastPropertyAcaConfigForm.directive.html @@ -21,6 +21,18 @@

Canary Config

+
+
+ Configs +
+
+ + +
+
+
Name @@ -65,8 +77,8 @@

Canary Config

class="form-control input-sm" ng-model="newFP.property.canary.resultStrategy" > - - + +
@@ -198,5 +210,4 @@
Analysis Config
- {{newFP.startScope}} From 7fcc842e7af3d6cce4178a1d5e49d9eaeabf2fdd Mon Sep 17 00:00:00 2001 From: chrisb Date: Thu, 4 Feb 2016 07:59:06 -0800 Subject: [PATCH 009/151] update security group submit button should say "Update" --- .../amazon/securityGroup/configure/EditSecurityGroupCtrl.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/scripts/modules/amazon/securityGroup/configure/EditSecurityGroupCtrl.js b/app/scripts/modules/amazon/securityGroup/configure/EditSecurityGroupCtrl.js index 6d1c5d2653a..8e1bf724e63 100644 --- a/app/scripts/modules/amazon/securityGroup/configure/EditSecurityGroupCtrl.js +++ b/app/scripts/modules/amazon/securityGroup/configure/EditSecurityGroupCtrl.js @@ -32,6 +32,8 @@ module.exports = angular.module('spinnaker.securityGroup.aws.edit.controller', [ securityGroup: securityGroup, })); + $scope.isNew = false; + $scope.taskMonitor = taskMonitorService.buildTaskMonitor({ application: application, title: 'Updating your security group', From 77d846eae3c7efc56579f1347c31c08d240d6897 Mon Sep 17 00:00:00 2001 From: Zan Thrash Date: Thu, 4 Feb 2016 14:32:58 -0800 Subject: [PATCH 010/151] SPIN-1415: Evict Local Storage if there is an exception on setItem Our current strategy to only clear out the infrastructureCaches if there is an exception thrown on insert. As the app has grown we have added more and more to Local Storage resulting in the possibility of exhausting the 5MB of space given in most browsers. This change simply evicts the entire local storage (restricted to the namespace of the url), when there is an insert exception. This change also reduces the TTL of the 'collapsible section cache' from 30 days to 7 days. --- .../core/cache/collapsibleSectionStateCache.js | 2 +- app/scripts/modules/core/cache/deckCacheFactory.js | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/app/scripts/modules/core/cache/collapsibleSectionStateCache.js b/app/scripts/modules/core/cache/collapsibleSectionStateCache.js index 806832468a8..546601b70e7 100644 --- a/app/scripts/modules/core/cache/collapsibleSectionStateCache.js +++ b/app/scripts/modules/core/cache/collapsibleSectionStateCache.js @@ -12,7 +12,7 @@ module.exports = angular.module('spinnaker.core.cache.collapsibleSectionState', try { CacheFactory.createCache(cacheId, { - maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days + maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days deleteOnExpire: 'aggressive', storageMode: 'localStorage', }); diff --git a/app/scripts/modules/core/cache/deckCacheFactory.js b/app/scripts/modules/core/cache/deckCacheFactory.js index 2e892441102..c4bf808d9a0 100644 --- a/app/scripts/modules/core/cache/deckCacheFactory.js +++ b/app/scripts/modules/core/cache/deckCacheFactory.js @@ -60,16 +60,7 @@ module.exports = angular.module('spinnaker.core.cache.deckCacheFactory', [ window.localStorage.setItem(k, v); } catch (e) { $log.warn('Local Storage Error! Clearing caches and trying again.\nException:', e); - for (var key in window.localStorage) { - // invalidate keystore for any angular caches - if (key.match(/angular-cache\.caches\.infrastructure:.*.\.keys/)) { - window.localStorage.setItem(key, '[]'); - } - // clear the data itself - if (key.match(/angular-cache\.caches\.infrastructure:.*.\.data\./)) { - window.localStorage.removeItem(key); - } - } + window.localStorage.clear(); window.localStorage.setItem(k, v); } }, From ebc036c1dde47772d5e69a9875cfa4d0086ebcec Mon Sep 17 00:00:00 2001 From: Zan Thrash Date: Sat, 6 Feb 2016 12:57:58 -0800 Subject: [PATCH 011/151] Angular got bumped to 1.5.0 causing issues with ui-select. I'm pinning Angular to the latest 1.4 release (1.4.9). --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 955cfdef380..250ca750c8f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "dependencies": { "Select2": "git://github.com/select2/select2.git#3.4.8", - "angular": "^1.4.1", + "angular": "~1.4.1", "angular-animate": "^1.4.1", "angular-cache": "^4.2.2", "angular-debounce": "git://github.com/shahata/angular-debounce.git#0.1.7", From 2e2c763dca255ba071466b8c98e4f42210e4bbe2 Mon Sep 17 00:00:00 2001 From: chrisb Date: Mon, 1 Feb 2016 13:34:07 -0800 Subject: [PATCH 012/151] provide svg logo for cloud foundry --- app/scripts/modules/cloudfoundry/cf.module.js | 4 +++- app/scripts/modules/cloudfoundry/logo/cf.logo.less | 8 ++++++++ app/scripts/modules/cloudfoundry/logo/cf.logo.svg | 1 + .../modules/cloudfoundry/{ => logo}/logo_cf.png | Bin 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 app/scripts/modules/cloudfoundry/logo/cf.logo.less create mode 100644 app/scripts/modules/cloudfoundry/logo/cf.logo.svg rename app/scripts/modules/cloudfoundry/{ => logo}/logo_cf.png (100%) diff --git a/app/scripts/modules/cloudfoundry/cf.module.js b/app/scripts/modules/cloudfoundry/cf.module.js index 50f9663a06f..a50392a9577 100644 --- a/app/scripts/modules/cloudfoundry/cf.module.js +++ b/app/scripts/modules/cloudfoundry/cf.module.js @@ -2,6 +2,8 @@ let angular = require('angular'); +require('./logo/cf.logo.less'); + // load all templates into the $templateCache var templates = require.context('./', true, /\.html$/); templates.keys().forEach(function(key) { @@ -35,7 +37,7 @@ module.exports = angular.module('spinnaker.cf', [ cloudProviderRegistryProvider.registerProvider('cf', { name: 'Cloud Foundry', logo: { - path: require('./logo_cf.png'), + path: require('./logo/logo_cf.png'), }, cache: { configurer: 'cfCacheConfigurer', diff --git a/app/scripts/modules/cloudfoundry/logo/cf.logo.less b/app/scripts/modules/cloudfoundry/logo/cf.logo.less new file mode 100644 index 00000000000..b600630eef1 --- /dev/null +++ b/app/scripts/modules/cloudfoundry/logo/cf.logo.less @@ -0,0 +1,8 @@ +cloud-provider-logo { + .icon-cf { + mask: url('cf.logo.svg') no-repeat 50% 50%; + -webkit-mask: url('cf.logo.svg') no-repeat 50% 0%; + mask-size: cover; + -webkit-mask-size: cover; + } +} diff --git a/app/scripts/modules/cloudfoundry/logo/cf.logo.svg b/app/scripts/modules/cloudfoundry/logo/cf.logo.svg new file mode 100644 index 00000000000..97d5e36fc55 --- /dev/null +++ b/app/scripts/modules/cloudfoundry/logo/cf.logo.svg @@ -0,0 +1 @@ +cf-logo \ No newline at end of file diff --git a/app/scripts/modules/cloudfoundry/logo_cf.png b/app/scripts/modules/cloudfoundry/logo/logo_cf.png similarity index 100% rename from app/scripts/modules/cloudfoundry/logo_cf.png rename to app/scripts/modules/cloudfoundry/logo/logo_cf.png From da307abdd4eee07e3269549c8e09e4297d904591 Mon Sep 17 00:00:00 2001 From: chrisb Date: Thu, 4 Feb 2016 00:00:11 -0800 Subject: [PATCH 013/151] v2 modal wizard (aws only) --- app/scripts/modules/amazon/aws.module.js | 1 + .../instance/awsInstanceType.service.js | 61 ------- .../configure/advancedSettings.html | 42 +++++ .../createLoadBalancer.controller.js | 11 +- .../configure/createLoadBalancer.html | 30 ++- .../createLoadBalancerProperties.html | 12 -- .../configure/editLoadBalancer.html | 26 ++- .../loadBalancer/configure/healthCheck.html | 124 +++---------- .../loadBalancer/configure/listeners.html | 17 -- ...cerAvailabilityZoneSelector.directive.html | 4 +- .../configure/securityGroups.html | 18 +- .../details/loadBalancerDetail.controller.js | 2 + .../clone/cloneSecurityGroup.html | 8 +- .../configure/createSecurityGroup.html | 20 +- .../configure/createSecurityGroupIngress.html | 11 -- .../createSecurityGroupProperties.html | 12 -- .../configure/editSecurityGroup.html | 17 +- .../details/securityGroupDetail.controller.js | 2 + .../serverGroup.configure.aws.module.js | 22 ++- .../serverGroupCommandBuilder.service.js | 3 + .../serverGroupConfiguration.service.js | 3 + .../serverGroupConfiguration.service.spec.js | 29 +-- .../wizard/CloneServerGroup.aws.controller.js | 62 +++---- .../CloneServerGroup.aws.controller.spec.js | 23 ++- .../ServerGroupAdvancedSettings.controller.js | 20 -- ...ServerGroupInstanceArchetype.controller.js | 29 --- .../ServerGroupInstanceType.controller.js | 11 -- .../configure/wizard/advancedSettings.html | 141 -------------- .../advancedSettings/advancedSettings.html | 128 +++++++++++++ .../ServerGroupCapacity.controller.js | 26 --- .../configure/wizard/capacity/capacity.html | 26 +-- .../capacity/capacityFooter.directive.html | 15 -- .../capacity/capacityFooter.directive.js | 26 --- .../configure/wizard/capacity/zones.html | 4 + .../configure/wizard/instanceArchetype.html | 20 -- .../configure/wizard/instanceType.html | 20 -- .../wizard/instanceType/instanceType.html | 8 + .../configure/wizard/loadBalancers.html | 60 ------ .../ServerGroupLoadBalancers.controller.js | 9 +- .../loadBalancerSelector.directive.html | 44 +++++ .../loadBalancerSelector.directive.js | 32 ++++ .../wizard/loadBalancers/loadBalancers.html | 3 + .../ServerGroupBasicSettings.controller.js | 17 +- .../wizard/{ => location}/basicSettings.html | 13 -- .../ServerGroupSecurityGroups.controller.js | 17 -- .../wizard/securityGroups/securityGroups.html | 20 +- .../securityGroupsFooter.directive.html | 14 -- .../securityGroupsFooter.directive.js | 25 --- .../configure/wizard/serverGroupWizard.html | 43 +++-- .../deployInitializer.controller.js | 6 +- .../deployInitializerCtrl.spec.js | 0 .../templateSelection.html | 4 +- .../availabilityZoneSelector.directive.html | 0 .../availabilityZoneSelector.directive.js | 0 .../azRebalanceSelector.directive.html | 0 .../azRebalanceSelector.directive.js | 0 .../serverGroupDetails.aws.controller.js | 1 + .../configure/wizard/templateSelection.html | 2 +- .../configure/wizard/templateSelection.html | 2 +- .../modal/editApplication.controller.modal.js | 15 +- .../application/modal/editApplication.html | 10 +- .../core/cluster/allClusters.controller.js | 1 + app/scripts/modules/core/cluster/rollups.less | 1 + .../executionGroup.directive.html | 2 +- .../executionGroup/executionGroup.less | 4 + .../executions/executions.controller.js | 2 +- .../core/instance/instanceSelection.less | 4 +- .../core/loadBalancer/AllLoadBalancersCtrl.js | 1 + .../modules/core/modal/modal.module.js | 3 + .../core/modal/modalOverlay.directive.js | 6 +- app/scripts/modules/core/modal/modals.less | 172 +++++++++--------- .../core/modal/wizard/modalWizard.less | 99 ++++++++++ .../modal/wizard/v2modalWizard.directive.html | 33 ++++ .../modal/wizard/v2modalWizard.directive.js | 32 ++++ .../modal/wizard/v2modalWizard.service.js | 86 +++++++++ .../modal/wizard/v2wizardPage.directive.html | 11 ++ .../modal/wizard/v2wizardPage.directive.js | 44 +++++ .../config/stages/deploy/deployStage.js | 2 + .../modules/core/presentation/main.less | 9 + .../configureProject.modal.controller.js | 6 + .../configure/configureProject.modal.html | 26 ++- .../configure/projectApplications.modal.html | 14 -- .../configure/projectClusters.modal.html | 14 -- .../configure/projectConfig.modal.html | 11 -- .../configure/projectPipelines.modal.html | 10 - .../infrastructure.controller.js | 1 + .../securityGroup/AllSecurityGroupsCtrl.js | 1 + .../v2InstanceTypeSelector.directive.js | 70 +++++++ .../common/v2instanceArchetype.directive.html | 36 ++++ .../v2instanceArchetypeSelector.directive.js | 120 ++++++++++++ .../core/task/monitor/taskMonitor.html | 2 +- .../core/utils/scrollTo/scrollTo.service.js | 4 +- .../stickyHeader/stickyHeader.directive.js | 16 +- .../core/utils/waypoints/waypoint.service.js | 26 ++- .../application/editApplication.modal.html | 12 +- .../modal/wizard/fastPropertyWizard.html | 2 +- app/scripts/modules/netflix/netflix.module.js | 2 +- .../report/reservationReport.directive.js | 29 +-- .../awsServerGroupSecurityGroups.html | 17 -- .../capacity/awsServerGroupCapacity.html | 31 ---- .../capacity/awsServerGroupCapacity.html | 21 +++ .../awsServerGroupSecurityGroups.html | 5 + .../serverGroupCommandConfigurer.service.js | 20 +- .../templateOverrides.module.js | 4 +- .../configure/wizard/templateSelection.html | 2 +- 105 files changed, 1278 insertions(+), 1107 deletions(-) create mode 100644 app/scripts/modules/amazon/loadBalancer/configure/advancedSettings.html delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/ServerGroupAdvancedSettings.controller.js delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/ServerGroupInstanceArchetype.controller.js delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/ServerGroupInstanceType.controller.js delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/advancedSettings.html create mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/advancedSettings/advancedSettings.html delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/capacity/ServerGroupCapacity.controller.js delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/capacity/capacityFooter.directive.html delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/capacity/capacityFooter.directive.js create mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/capacity/zones.html delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/instanceArchetype.html delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/instanceType.html create mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/instanceType/instanceType.html delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/loadBalancers.html rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => loadBalancers}/ServerGroupLoadBalancers.controller.js (69%) create mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/loadBalancers/loadBalancerSelector.directive.html create mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/loadBalancers/loadBalancerSelector.directive.js create mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/loadBalancers/loadBalancers.html rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => location}/ServerGroupBasicSettings.controller.js (78%) rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => location}/basicSettings.html (91%) delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/securityGroups/ServerGroupSecurityGroups.controller.js delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/securityGroups/securityGroupsFooter.directive.html delete mode 100644 app/scripts/modules/amazon/serverGroup/configure/wizard/securityGroups/securityGroupsFooter.directive.js rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => templateSelection}/deployInitializer.controller.js (94%) rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => templateSelection}/deployInitializerCtrl.spec.js (100%) rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => templateSelection}/templateSelection.html (96%) rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => zones}/availabilityZoneSelector.directive.html (100%) rename app/scripts/modules/amazon/serverGroup/configure/wizard/{ => zones}/availabilityZoneSelector.directive.js (100%) rename app/scripts/modules/amazon/serverGroup/configure/wizard/{capacity => zones}/azRebalanceSelector.directive.html (100%) rename app/scripts/modules/amazon/serverGroup/configure/wizard/{capacity => zones}/azRebalanceSelector.directive.js (100%) create mode 100644 app/scripts/modules/core/modal/wizard/modalWizard.less create mode 100644 app/scripts/modules/core/modal/wizard/v2modalWizard.directive.html create mode 100644 app/scripts/modules/core/modal/wizard/v2modalWizard.directive.js create mode 100644 app/scripts/modules/core/modal/wizard/v2modalWizard.service.js create mode 100644 app/scripts/modules/core/modal/wizard/v2wizardPage.directive.html create mode 100644 app/scripts/modules/core/modal/wizard/v2wizardPage.directive.js create mode 100644 app/scripts/modules/core/serverGroup/configure/common/v2InstanceTypeSelector.directive.js create mode 100644 app/scripts/modules/core/serverGroup/configure/common/v2instanceArchetype.directive.html create mode 100644 app/scripts/modules/core/serverGroup/configure/common/v2instanceArchetypeSelector.directive.js delete mode 100644 app/scripts/modules/netflix/serverGroup/awsServerGroupSecurityGroups.html delete mode 100644 app/scripts/modules/netflix/serverGroup/capacity/awsServerGroupCapacity.html create mode 100644 app/scripts/modules/netflix/serverGroup/wizard/capacity/awsServerGroupCapacity.html create mode 100644 app/scripts/modules/netflix/serverGroup/wizard/securityGroups/awsServerGroupSecurityGroups.html rename app/scripts/modules/netflix/serverGroup/{ => wizard}/serverGroupCommandConfigurer.service.js (77%) diff --git a/app/scripts/modules/amazon/aws.module.js b/app/scripts/modules/amazon/aws.module.js index 09d49cda3c5..5c1c48345c1 100644 --- a/app/scripts/modules/amazon/aws.module.js +++ b/app/scripts/modules/amazon/aws.module.js @@ -46,6 +46,7 @@ module.exports = angular.module('spinnaker.aws', [ ]) .config(function(cloudProviderRegistryProvider) { cloudProviderRegistryProvider.registerProvider('aws', { + v2wizard: true, name: 'Amazon', logo: { path: require('./logo/amazon.logo.svg'), diff --git a/app/scripts/modules/amazon/instance/awsInstanceType.service.js b/app/scripts/modules/amazon/instance/awsInstanceType.service.js index 65c899f7199..f06a176ae9e 100644 --- a/app/scripts/modules/amazon/instance/awsInstanceType.service.js +++ b/app/scripts/modules/amazon/instance/awsInstanceType.service.js @@ -167,91 +167,30 @@ module.exports = angular.module('spinnaker.aws.instanceType.service', [ { type: 'general', label: 'General Purpose', - description: 'Instances that provide a balance of compute, memory, and network resources', families: [ m3 ], icon: 'hdd' }, { type: 'memory', label: 'High Memory', - description: 'Instances that are optimized for memory-intensive applications', families: [ r3 ], icon: 'hdd' }, { type: 'micro', label: 'Micro Utility', - description: 'Instances that provide relatively small amounts of memory and CPU power', families: [t2, m3micro], icon: 'hdd' }, { type: 'custom', label: 'Custom Type', - description: 'Select the instance type below.', families: [], icon: 'asterisk' } ]; - function calculateStorage(type) { - if (!type || !type.storage) { - return 0; - } - return type.storage.count * type.storage.size; - } - - function buildStats(category) { - var stats = { - cpu: { - min: Number.MAX_VALUE, - max: -Number.MAX_VALUE - }, - memory: { - min: Number.MAX_VALUE, - max: -Number.MAX_VALUE - }, - storage: { - min: Number.MAX_VALUE, - max: -Number.MAX_VALUE - }, - costFactor: { - min: Number.MAX_VALUE, - max: -Number.MAX_VALUE - }, - families: [] - }; - - if (category.families && category.families.length) { - category.families.forEach(function(family) { - stats.families.push(family.type); - var cpuMin = _.min(family.instanceTypes, 'cpu').cpu || Number.MAX_VALUE, - cpuMax = _.max(family.instanceTypes, 'cpu').cpu || -Number.MAX_VALUE, - memoryMin = _.min(family.instanceTypes, 'memory').memory || Number.MAX_VALUE, - memoryMax = _.max(family.instanceTypes, 'memory').memory || -Number.MAX_VALUE, - storageMin = calculateStorage(_.min(family.instanceTypes, calculateStorage)) || Number.MAX_VALUE, - storageMax = calculateStorage(_.max(family.instanceTypes, calculateStorage)) || -Number.MAX_VALUE, - costFactorMin = _.min(family.instanceTypes, 'costFactor').costFactor || Number.MAX_VALUE, - costFactorMax = _.max(family.instanceTypes, 'costFactor').costFactor || -Number.MAX_VALUE; - - stats.cpu.min = Math.min(stats.cpu.min, cpuMin); - stats.cpu.max = Math.max(stats.cpu.max, cpuMax); - stats.memory.min = Math.min(stats.memory.min, memoryMin); - stats.memory.max = Math.max(stats.memory.max, memoryMax); - stats.storage.min = Math.min(stats.storage.min, storageMin); - stats.storage.max = Math.max(stats.storage.max, storageMax); - stats.costFactor.min = Math.min(stats.costFactor.min, costFactorMin); - stats.costFactor.max = Math.max(stats.costFactor.max, costFactorMax); - }); - } - - return stats; - } - function getCategories() { - categories.map(function(category) { - category.stats = buildStats(category); - }); return $q.when(categories); } diff --git a/app/scripts/modules/amazon/loadBalancer/configure/advancedSettings.html b/app/scripts/modules/amazon/loadBalancer/configure/advancedSettings.html new file mode 100644 index 00000000000..987ac80da82 --- /dev/null +++ b/app/scripts/modules/amazon/loadBalancer/configure/advancedSettings.html @@ -0,0 +1,42 @@ +
+
+ +
+
+ Timeout +
+
+ +
+
+ +
+
+ Interval +
+
+ +
+
+ +
+
+ Healthy Threshold +
+
+ +
+
+ +
+
+ Unhealthy Threshold +
+
+ +
+
+ + +
+
\ No newline at end of file diff --git a/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.controller.js b/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.controller.js index d5b624e4a56..494adff1121 100644 --- a/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.controller.js +++ b/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.controller.js @@ -9,7 +9,7 @@ module.exports = angular.module('spinnaker.loadBalancer.aws.create.controller', require('../../../core/account/account.service.js'), require('../loadBalancer.transformer.js'), require('../../../core/securityGroup/securityGroup.read.service.js'), - require('../../../core/modal/wizard/modalWizard.service.js'), + require('../../../core/modal/wizard/v2modalWizard.service.js'), require('../../../core/task/monitor/taskMonitorService.js'), require('../../subnet/subnet.read.service.js'), require('../../../core/cache/cacheInitializer.js'), @@ -24,7 +24,7 @@ module.exports = angular.module('spinnaker.loadBalancer.aws.create.controller', .controller('awsCreateLoadBalancerCtrl', function($scope, $modalInstance, $state, _, accountService, awsLoadBalancerTransformer, securityGroupReader, cacheInitializer, infrastructureCaches, loadBalancerReader, - modalWizardService, loadBalancerWriter, taskMonitorService, + v2modalWizardService, loadBalancerWriter, taskMonitorService, subnetReader, namingService, settings, application, loadBalancer, isNew) { @@ -35,6 +35,7 @@ module.exports = angular.module('spinnaker.loadBalancer.aws.create.controller', securityGroups: require('./securityGroups.html'), listeners: require('./listeners.html'), healthCheck: require('./healthCheck.html'), + advancedSettings: require('./advancedSettings.html'), }; $scope.isNew = isNew; @@ -180,7 +181,7 @@ module.exports = angular.module('spinnaker.loadBalancer.aws.create.controller', }); $scope.loadBalancer.securityGroups = _.unique(existingNames); if ($scope.state.removedSecurityGroups.length) { - modalWizardService.getWizard().markDirty('Security Groups'); + v2modalWizardService.markDirty('Security Groups'); } } else { clearSecurityGroups(); @@ -337,10 +338,10 @@ module.exports = angular.module('spinnaker.loadBalancer.aws.create.controller', updateAvailableSecurityGroups(availableVpcIds); if (subnetPurpose) { $scope.loadBalancer.vpcId = availableVpcIds.length ? availableVpcIds[0] : null; - modalWizardService.getWizard().includePage('Security Groups'); + v2modalWizardService.includePage('Security Groups'); } else { $scope.loadBalancer.vpcId = null; - modalWizardService.getWizard().excludePage('Security Groups'); + v2modalWizardService.excludePage('Security Groups'); } }; diff --git a/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.html b/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.html index 8bea8983983..107e1b552cb 100644 --- a/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.html +++ b/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancer.html @@ -1,14 +1,24 @@ - - + + - - + + - - + + - - + + - - + + + + + + \ No newline at end of file diff --git a/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancerProperties.html b/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancerProperties.html index 1f1bbf51332..86b26fe1fa3 100644 --- a/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancerProperties.html +++ b/app/scripts/modules/amazon/loadBalancer/configure/createLoadBalancerProperties.html @@ -70,16 +70,4 @@

- diff --git a/app/scripts/modules/amazon/loadBalancer/configure/editLoadBalancer.html b/app/scripts/modules/amazon/loadBalancer/configure/editLoadBalancer.html index 91ac2548e26..63d97e653d7 100644 --- a/app/scripts/modules/amazon/loadBalancer/configure/editLoadBalancer.html +++ b/app/scripts/modules/amazon/loadBalancer/configure/editLoadBalancer.html @@ -1,11 +1,21 @@ - - + + - - + + - - + + - - + + + + + + \ No newline at end of file diff --git a/app/scripts/modules/amazon/loadBalancer/configure/healthCheck.html b/app/scripts/modules/amazon/loadBalancer/configure/healthCheck.html index 3bd52b3df1c..3e96a6e6f7f 100644 --- a/app/scripts/modules/amazon/loadBalancer/configure/healthCheck.html +++ b/app/scripts/modules/amazon/loadBalancer/configure/healthCheck.html @@ -1,101 +1,29 @@
-
Input ValueActionsOptionActions
-
-
- Remove + + Remove
Type DetailsActionsActions
{{notification.address}} - + Remove
- - - - - - - - - - - - - - - -
ProtocolPortPath
-
- - - - -
-
-

Advanced Settings

-
- -
- -
-
- Timeout -
-
- -
-
- -
-
- Interval -
-
- -
-
- -
-
- Healthy Threshold -
-
- -
-
- -
-
- Unhealthy Threshold -
-
- -
-
- - -
-
- - - - - - -
-
Detail (optional)
-
+
Detail (optional)
+
-
Description
-
+
Description
+
-
Account
-
+
Account
+
-
Regions
-
- - -

(Select an account)

+
+
-
-
VPC
-
- -

(Select an account)

-

(Select at least one region)

-
-
-
@@ -39,41 +39,37 @@

Region
{{securityGroup.region}}
-
VPC
-
-
Description
+ +
Description:
{{securityGroup.description}}
- -
None
- + +
None
-
IP Range
-
{{ipRangeRule.range.ip}}{{ipRangeRule.range.cidr}}
-
Port Ranges
-
- {{ipRangeRule.protocol}}: {{portRange.startPort}} → {{portRange.endPort}} -
-
-
- -
None
- -
-
Security Group
-
- - {{rule.securityGroup.name}} ({{rule.securityGroup.id}}) - -
-
Port Ranges
-
- {{rule.protocol}}: {{portRange.startPort}} → {{portRange.endPort}} -
+ ng-repeat="rule in securityGroup.securityRules | orderBy: 'rule.priority'"> +
Name
+
{{rule.name}}
+
Priority
+
{{rule.priority}}
+
Direction
+
{{rule.direction}}
+
Access
+
{{rule.access}}
+
Protocol
+
{{rule.protocol}}
+
Src Addr Prefix
+
{{rule.sourceAddressPrefix}}
+
Src Port Range
+
{{rule.sourcePortRange}}
+
Dest Addr Prefix
+
{{rule.destinationAddressPrefix}}
+
Dest Port Range
+
{{rule.destinationPortRange}}
+
+

diff --git a/app/scripts/modules/azure/securityGroup/securityGroup.reader.js b/app/scripts/modules/azure/securityGroup/securityGroup.reader.js index c2c1c054da2..2b878ab9c73 100644 --- a/app/scripts/modules/azure/securityGroup/securityGroup.reader.js +++ b/app/scripts/modules/azure/securityGroup/securityGroup.reader.js @@ -7,7 +7,10 @@ module.exports = angular.module('spinnaker.azure.securityGroup.reader', [ .factory('azureSecurityGroupReader', function () { function resolveIndexedSecurityGroup(indexedSecurityGroups, container, securityGroupId) { - return indexedSecurityGroups[container.account][container.region][securityGroupId]; + + //hack to get around securityGroupId not matching id in indexedSecurityGroups. + var temp = securityGroupId.split('/'); + return indexedSecurityGroups[container.account][container.region][temp[temp.length - 1]]; } return { diff --git a/app/scripts/modules/azure/securityGroup/securityGroup.transformer.js b/app/scripts/modules/azure/securityGroup/securityGroup.transformer.js index e4705ccbc0a..d10d166e5c4 100644 --- a/app/scripts/modules/azure/securityGroup/securityGroup.transformer.js +++ b/app/scripts/modules/azure/securityGroup/securityGroup.transformer.js @@ -3,21 +3,10 @@ let angular = require('angular'); module.exports = angular.module('spinnaker.azure.securityGroup.transformer', [ - require('../vpc/vpc.read.service.js'), ]) - .factory('azureSecurityGroupTransformer', function (vpcReader) { + .factory('azureSecurityGroupTransformer', function () { - function normalizeSecurityGroup(securityGroup) { - return vpcReader.listVpcs().then(addVpcNameToSecurityGroup(securityGroup)); - } - - function addVpcNameToSecurityGroup(securityGroup) { - return function(vpcs) { - var matches = vpcs.filter(function(test) { - return test.id === securityGroup.vpcId; - }); - securityGroup.vpcName = matches.length ? matches[0].name : ''; - }; + function normalizeSecurityGroup() { } return { diff --git a/app/scripts/modules/azure/securityGroup/securityGroup.write.service.js b/app/scripts/modules/azure/securityGroup/securityGroup.write.service.js new file mode 100644 index 00000000000..ba06d546690 --- /dev/null +++ b/app/scripts/modules/azure/securityGroup/securityGroup.write.service.js @@ -0,0 +1,56 @@ +'use strict'; + +let angular = require('angular'); + +module.exports = angular + .module('spinnaker.azure.securityGroup.write.service', [ + require('../../core/utils/lodash.js'), + require('../../core/task/taskExecutor.js'), + require('../../core/cache/infrastructureCaches.js'), + ]) + .factory('azureSecurityGroupWriter', function(_, infrastructureCaches, taskExecutor) { + + + function upsertSecurityGroup(securityGroup, application, descriptor, params = {}) { + + // We want to extend params with all attributes from securityGroup, but only if they don't already exist. + _.assign(params, securityGroup, function(value, other) { + return _.isUndefined(value) ? other : value; + }); + + var operation = taskExecutor.executeTask({ + job: [params], + application: application, + description: descriptor + ' Security Group: ' + name + }); + + infrastructureCaches.clearCache('securityGroup'); + + return operation; + } + + function deleteSecurityGroup(securityGroup, application, params = {}) { + params.type = 'deleteSecurityGroup'; + params.securityGroup = securityGroup.name; + params.regions = [securityGroup.region]; + params.credentials = securityGroup.accountId; + params.cloudProvider = securityGroup.providerType; + params.appName = application.name; + + var operation = taskExecutor.executeTask({ + job: [params], + application: application, + description: 'Delete security group: ' + securityGroup.name + ' in ' + securityGroup.accountId + ':' + securityGroup.region + }); + + infrastructureCaches.clearCache('securityGroup'); + + return operation; + } + + return { + deleteSecurityGroup: deleteSecurityGroup, + upsertSecurityGroup: upsertSecurityGroup + }; + + }); diff --git a/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.service.js b/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.service.js index cd43a163a0a..4c5dc046e08 100644 --- a/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.service.js +++ b/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.service.js @@ -3,255 +3,41 @@ let angular = require('angular'); module.exports = angular.module('spinnaker.azure.serverGroupCommandBuilder.service', [ - require('exports?"restangular"!imports?_=lodash!restangular'), - require('../../../core/account/account.service.js'), - require('../../../netflix/serverGroup/diff/diff.service.js'), - require('../../subnet/subnet.read.service.js'), - require('../../../core/instance/instanceTypeService.js'), - require('../../../core/naming/naming.service.js'), - require('./serverGroupConfiguration.service.js'), - require('../../../core/utils/lodash.js'), ]) - .factory('azureServerGroupCommandBuilder', function (settings, Restangular, $exceptionHandler, $q, diffService, - accountService, subnetReader, namingService, instanceTypeService, - azureServerGroupConfigurationService, _) { + .factory('azureServerGroupCommandBuilder', function (settings) { function buildNewServerGroupCommand (application, defaults) { defaults = defaults || {}; - var regionsKeyedByAccountLoader = accountService.getRegionsKeyedByAccount('azure'); var defaultCredentials = defaults.account || application.defaultCredentials || settings.providers.azure.defaults.account; var defaultRegion = defaults.region || application.defaultRegion || settings.providers.azure.defaults.region; - var preferredZonesLoader = accountService.getAvailabilityZonesForAccountAndRegion('azure', defaultCredentials, defaultRegion); - - var clusterDiffLoader = function() { return []; }; - if (application.name) { - clusterDiffLoader = diffService.getClusterDiffForAccount(defaultCredentials, application.name); - } - - return $q.all({ - preferredZones: preferredZonesLoader, - regionsKeyedByAccount: regionsKeyedByAccountLoader, - clusterDiff: clusterDiffLoader, - }) - .then(function (asyncData) { - var availabilityZones = asyncData.preferredZones; - - var regions = asyncData.regionsKeyedByAccount[defaultCredentials]; - var keyPair = regions ? regions.defaultKeyPair : null; - - return { - application: application.name, - credentials: defaultCredentials, - region: defaultRegion, - strategy: '', - capacity: { - min: 1, - max: 1, - desired: 1 - }, - targetHealthyDeployPercentage: 100, - cooldown: 10, - healthCheckType: 'EC2', - healthCheckGracePeriod: 600, - instanceMonitoring: false, - ebsOptimized: false, - selectedProvider: 'azure', - iamRole: 'BaseIAMRole', // TODO: should not be hard coded here - - terminationPolicies: ['Default'], - vpcId: null, - availabilityZones: availabilityZones, - keyPair: keyPair, - suspendedProcesses: [], - securityGroups: [], - viewState: { - instanceProfile: 'custom', - allImageSelection: null, - useAllImageSelection: false, - useSimpleCapacity: true, - usePreferredZones: true, - mode: defaults.mode || 'create', - disableStrategySelection: true, - clusterDiff: asyncData.clusterDiff, - }, - }; - }); - } - - function buildServerGroupCommandFromPipeline(application, originalCluster) { - - var pipelineCluster = _.cloneDeep(originalCluster); - var region = Object.keys(pipelineCluster.availabilityZones)[0]; - var instanceTypeCategoryLoader = instanceTypeService.getCategoryForInstanceType('azure', pipelineCluster.instanceType); - var commandOptions = { account: pipelineCluster.account, region: region }; - var asyncLoader = $q.all({command: buildNewServerGroupCommand(application, commandOptions), instanceProfile: instanceTypeCategoryLoader}); - - return asyncLoader.then(function(asyncData) { - var command = asyncData.command; - var zones = pipelineCluster.availabilityZones[region]; - var usePreferredZones = zones.join(',') === command.availabilityZones.join(','); - - var viewState = { - instanceProfile: asyncData.instanceProfile, - disableImageSelection: true, - useSimpleCapacity: pipelineCluster.capacity.min === pipelineCluster.capacity.max && pipelineCluster.useSourceCapacity !== true, - usePreferredZones: usePreferredZones, - mode: 'editPipeline', - submitButtonLabel: 'Done', - templatingEnabled: true, - }; - - var viewOverrides = { - region: region, - credentials: pipelineCluster.account, - availabilityZones: pipelineCluster.availabilityZones[region], - viewState: viewState, - }; - - pipelineCluster.strategy = pipelineCluster.strategy || ''; - - return angular.extend({}, command, pipelineCluster, viewOverrides); - }); - - } - - // Only used to prepare view requiring template selecting - function buildNewServerGroupCommandForPipeline() { - return $q.when({ + return { + application: application.name, + credentials: defaultCredentials, + region: defaultRegion, + strategy: '', + capacity: { + min: 1, + max: 1, + desired: 1 + }, + selectedProvider: 'azure', + securityGroups: [], viewState: { - requiresTemplateSelection: true, - } - }); - } - - function buildUpdateServerGroupCommand(serverGroup) { - var command = { - type: 'modifyAsg', - asgs: [ - { asgName: serverGroup.name, region: serverGroup.region } - ], - cooldown: serverGroup.asg.defaultCooldown, - healthCheckGracePeriod: serverGroup.asg.healthCheckGracePeriod, - healthCheckType: serverGroup.asg.healthCheckType, - terminationPolicies: angular.copy(serverGroup.asg.terminationPolicies), - credentials: serverGroup.account + instanceProfile: 'custom', + allImageSelection: null, + useAllImageSelection: false, + useSimpleCapacity: true, + usePreferredZones: true, + mode: defaults.mode || 'create', + disableStrategySelection: true, + }, }; - azureServerGroupConfigurationService.configureUpdateCommand(command); - return command; - } - - function buildServerGroupCommandFromExisting(application, serverGroup, mode) { - mode = mode || 'clone'; - - var preferredZonesLoader = accountService.getPreferredZonesByAccount(); - var subnetsLoader = subnetReader.listSubnets(); - - var serverGroupName = namingService.parseServerGroupName(serverGroup.asg.autoScalingGroupName); - var clusterName = namingService.getClusterName(application.name, serverGroupName.stack, serverGroupName.freeFormDetails); - var clusterDiffLoader = diffService.getClusterDiffForAccount(serverGroup.account, clusterName); - - var instanceType = serverGroup.launchConfig ? serverGroup.launchConfig.instanceType : null; - var instanceTypeCategoryLoader = instanceTypeService.getCategoryForInstanceType('azure', instanceType); - - var asyncLoader = $q.all({ - preferredZones: preferredZonesLoader, - subnets: subnetsLoader, - instanceProfile: instanceTypeCategoryLoader, - clusterDiff: clusterDiffLoader, - }); - - return asyncLoader.then(function(asyncData) { - var zones = serverGroup.asg.availabilityZones.sort(); - var usePreferredZones = false; - var preferredZonesForAccount = asyncData.preferredZones[serverGroup.account]; - if (preferredZonesForAccount) { - var preferredZones = preferredZonesForAccount[serverGroup.region].sort(); - usePreferredZones = zones.join(',') === preferredZones.join(','); - } - - var command = { - application: application.name, - strategy: '', - stack: serverGroupName.stack, - freeFormDetails: serverGroupName.freeFormDetails, - credentials: serverGroup.account, - cooldown: serverGroup.asg.defaultCooldown, - healthCheckGracePeriod: serverGroup.asg.healthCheckGracePeriod, - healthCheckType: serverGroup.asg.healthCheckType, - terminationPolicies: serverGroup.asg.terminationPolicies, - loadBalancers: serverGroup.asg.loadBalancerNames, - region: serverGroup.region, - useSourceCapacity: false, - capacity: { - 'min': serverGroup.asg.minSize, - 'max': serverGroup.asg.maxSize, - 'desired': serverGroup.asg.desiredCapacity - }, - targetHealthyDeployPercentage: 100, - availabilityZones: zones, - selectedProvider: 'azure', - source: { - account: serverGroup.account, - region: serverGroup.region, - asgName: serverGroup.asg.autoScalingGroupName, - }, - suspendedProcesses: (serverGroup.asg.suspendedProcesses || []).map((process) => process.processName), - viewState: { - instanceProfile: asyncData.instanceProfile, - allImageSelection: null, - useAllImageSelection: false, - useSimpleCapacity: serverGroup.asg.minSize === serverGroup.asg.maxSize, - usePreferredZones: usePreferredZones, - mode: mode, - isNew: false, - clusterDiff: asyncData.clusterDiff, - }, - }; - - if (mode === 'clone') { - command.useSourceCapacity = true; - command.viewState.useSimpleCapacity = false; - } - - var vpcZoneIdentifier = serverGroup.asg.vpczoneIdentifier; - if (vpcZoneIdentifier !== '') { - var subnetId = vpcZoneIdentifier.split(',')[0]; - var subnet = _(asyncData.subnets).find({'id': subnetId}); - command.subnetType = subnet.purpose; - command.vpcId = subnet.vpcId; - } else { - command.subnetType = ''; - command.vpcId = null; - } - - if (serverGroup.launchConfig) { - angular.extend(command, { - instanceType: serverGroup.launchConfig.instanceType, - iamRole: serverGroup.launchConfig.iamInstanceProfile, - keyPair: serverGroup.launchConfig.keyName, - associatePublicIpAddress: serverGroup.launchConfig.associatePublicIpAddress, - ramdiskId: serverGroup.launchConfig.ramdiskId, - instanceMonitoring: serverGroup.launchConfig.instanceMonitoring.enabled, - ebsOptimized: serverGroup.launchConfig.ebsOptimized, - }); - command.viewState.imageId = serverGroup.launchConfig.imageId; - } - - if (serverGroup.launchConfig && serverGroup.launchConfig.securityGroups.length) { - command.securityGroups = serverGroup.launchConfig.securityGroups; - } - return command; - }); } return { buildNewServerGroupCommand: buildNewServerGroupCommand, - buildServerGroupCommandFromExisting: buildServerGroupCommandFromExisting, - buildNewServerGroupCommandForPipeline: buildNewServerGroupCommandForPipeline, - buildServerGroupCommandFromPipeline: buildServerGroupCommandFromPipeline, - buildUpdateServerGroupCommand: buildUpdateServerGroupCommand, }; }); diff --git a/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.spec.js b/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.spec.js index bb762daaf72..104cbacdb28 100644 --- a/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.spec.js +++ b/app/scripts/modules/azure/serverGroup/configure/serverGroupCommandBuilder.spec.js @@ -27,78 +27,30 @@ describe('create server group commands', function() { - it('initializes to default values, setting usePreferredZone flag to true', function () { + it('initializes to default values.', function () { var command = null; - this.azureServerGroupCommandBuilder.buildNewServerGroupCommand({name: 'appo'}, 'azure').then(function(result) { + this.azureServerGroupCommandBuilder.buildNewServerGroupCommand({name: 'appo'}, {account: 'azure-cred1', region: 'westus'}).then(function(result) { command = result; }); this.$scope.$digest(); - expect(command.viewState.usePreferredZones).toBe(true); - expect(command.availabilityZones).toEqual(['a', 'b', 'c']); - }); - - it('sets usePreferredZones flag based on initial value', function() { - spyOn(this.instanceTypeService, 'getCategoryForInstanceType').and.returnValue(this.$q.when('custom')); - var baseServerGroup = { - account: 'prod', - region: 'us-west-1', - asg: { - availabilityZones: ['g', 'h', 'i'], - vpczoneIdentifier: '', - }, - }; - var command = null; - - this.azureServerGroupCommandBuilder.buildServerGroupCommandFromExisting({name: 'appo'}, baseServerGroup).then(function(result) { - command = result; - }); - - this.$scope.$digest(); - - expect(command.viewState.usePreferredZones).toBe(true); - expect(command.availabilityZones).toEqual(['g', 'h', 'i']); - - baseServerGroup.asg.availabilityZones = ['g']; - - this.azureServerGroupCommandBuilder.buildServerGroupCommandFromExisting({name: 'appo'}, baseServerGroup).then(function(result) { - command = result; - }); - - this.$scope.$digest(); - - expect(command.viewState.usePreferredZones).toBe(false); - expect(command.availabilityZones).toEqual(['g']); - - }); - - it('sets profile and instance type if available', function() { - spyOn(this.instanceTypeService, 'getCategoryForInstanceType').and.returnValue(this.$q.when('selectedProfile')); - - var baseServerGroup = { - account: 'prod', - region: 'us-west-1', - asg: { - availabilityZones: ['g', 'h', 'i'], - vpczoneIdentifier: '', - }, - launchConfig: { - instanceType: 'something-custom', - instanceMonitoring: {}, - securityGroups: [], - }, - }; - var command = null; - - this.azureServerGroupCommandBuilder.buildServerGroupCommandFromExisting({name: 'appo'}, baseServerGroup).then(function(result) { - command = result; - }); - - this.$scope.$digest(); - - expect(command.viewState.instanceProfile).toBe('selectedProfile'); - expect(command.instanceType).toBe('something-custom'); + expect(command.application).toEqual('appo'); + expect(command.credentials).toEqual('azure-cred1'); + expect(command.region).toEqual('westus'); + expect(command.strategy).toEqual(''); + expect(command.capacity.min).toEqual(1); + expect(command.capacity.max).toEqual(1); + expect(command.capacity.desired).toEqual(1); + expect(command.selectedProvider).toEqual('azure'); + expect(command.securityGroups).toEqual([]); + expect(command.viewState.instanceProfile).toEqual('custom'); + expect(command.viewState.allImageSelection).toBe(null); + expect(command.viewState.useAllImageSelection).toBe(false); + expect(command.viewState.useSimpleCapacity).toBe(true); + expect(command.viewState.usePrefereedZones).toBe(true); + expect(command.viewState.mode).toEqual('create'); + expect(command.viewState.disableStrategySelection).toBe(true); }); }); diff --git a/app/scripts/modules/azure/serverGroup/configure/wizard/CloneServerGroup.azure.controller.js b/app/scripts/modules/azure/serverGroup/configure/wizard/CloneServerGroup.azure.controller.js index 5919daf9ced..1c5f7a7b0c6 100644 --- a/app/scripts/modules/azure/serverGroup/configure/wizard/CloneServerGroup.azure.controller.js +++ b/app/scripts/modules/azure/serverGroup/configure/wizard/CloneServerGroup.azure.controller.js @@ -16,7 +16,7 @@ module.exports = angular.module('spinnaker.azure.cloneServerGroup.controller', [ $scope.pages = { templateSelection: require('./templateSelection.html'), basicSettings: require('./basicSettings.html'), -/* loadBalancers: require('./loadBalancers.html'), +/* loadBalancers: require('./loadBalancers.html'), securityGroups: require('./securityGroups.html'), instanceArchetype: require('./instanceArchetype.html'), instanceType: require('./instanceType.html'), @@ -164,19 +164,16 @@ module.exports = angular.module('spinnaker.azure.cloneServerGroup.controller', [ } this.isValid = function () { - //TODO:larrygug - modify to fit Azure model. Need to change the command object completely. return $scope.command && - ($scope.command.viewState.useAllImageSelection ? $scope.command.viewState.allImageSelection !== null : $scope.command.amiName !== null) && ($scope.command.application !== null) && - ($scope.command.credentials !== null) && ($scope.command.instanceType !== null) && - ($scope.command.region !== null) && ($scope.command.availabilityZones !== null) && - ($scope.command.capacity.min !== null) && ($scope.command.capacity.max !== null) && - ($scope.command.capacity.desired !== null) && + ($scope.command.credentials !== null) && + ($scope.command.region !== null) && modalWizardService.getWizard().isComplete(); }; this.showSubmitButton = function () { - return modalWizardService.getWizard().allPagesVisited(); + //return modalWizardService.getWizard().allPagesVisited(); + return true; }; this.submit = function () { diff --git a/app/scripts/modules/azure/serverGroup/configure/wizard/basicSettings.html b/app/scripts/modules/azure/serverGroup/configure/wizard/basicSettings.html index 8b91bf8a686..3df21383126 100644 --- a/app/scripts/modules/azure/serverGroup/configure/wizard/basicSettings.html +++ b/app/scripts/modules/azure/serverGroup/configure/wizard/basicSettings.html @@ -36,7 +36,7 @@ class="form-control input-sm" ng-pattern="basicSettingsCtrl.detailPattern" name="details" - ng-model="command.freeFormDetails"/> + ng-model="command.details"/>
@@ -121,8 +121,8 @@
-
diff --git a/app/scripts/modules/azure/serverGroup/details/serverGroupDetails.azure.controller.js b/app/scripts/modules/azure/serverGroup/details/serverGroupDetails.azure.controller.js index b61a2d40c5e..0bbdb079e39 100644 --- a/app/scripts/modules/azure/serverGroup/details/serverGroupDetails.azure.controller.js +++ b/app/scripts/modules/azure/serverGroup/details/serverGroupDetails.azure.controller.js @@ -9,7 +9,6 @@ module.exports = angular.module('spinnaker.azure.serverGroup.details.controller' require('../../../core/confirmationModal/confirmationModal.service.js'), require('../../../core/serverGroup/serverGroup.write.service.js'), require('../../../core/utils/lodash.js'), - require('../../vpc/vpcTag.directive.js'), require('./scalingProcesses/autoScalingProcess.service.js'), require('../../../core/serverGroup/serverGroup.read.service.js'), require('../configure/serverGroupCommandBuilder.service.js'), diff --git a/app/scripts/modules/azure/serverGroup/serverGroup.transformer.js b/app/scripts/modules/azure/serverGroup/serverGroup.transformer.js index c4441c41544..6912583b368 100644 --- a/app/scripts/modules/azure/serverGroup/serverGroup.transformer.js +++ b/app/scripts/modules/azure/serverGroup/serverGroup.transformer.js @@ -3,57 +3,53 @@ let angular = require('angular'); module.exports = angular.module('spinnaker.azure.serverGroup.transformer', [ - require('../../core/utils/lodash.js'), - require('../vpc/vpc.read.service.js'), ]) - .factory('azureServerGroupTransformer', function (_, azureVpcReader) { + .factory('azureServerGroupTransformer', function () { - function normalizeServerGroup(serverGroup) { - serverGroup.instances.forEach((instance) => { instance.vpcId = serverGroup.vpcId; }); - return azureVpcReader.listVpcs().then(addVpcNameToServerGroup(serverGroup)); - } - - function addVpcNameToServerGroup(serverGroup) { - return function(vpcs) { - var matches = vpcs.filter(function(test) { - return test.id === serverGroup.vpcId; - }); - serverGroup.vpcName = matches.length ? matches[0].name : ''; - return serverGroup; + function convertServerGroupCommandToDeployConfiguration(base) { + var command = { + name: base.application, + cloudProvider: base.selectedProvider, + application: base.application, + stack: base.stack, + detail: base.details, + credentials: base.credentials, + region: base.region, + user: '[anonymous]', + upgradePolicy: 'Manual', + type: 'createServerGroup', + + image: { + publisher: 'Canonical', + offer: 'UbuntuServer', + sku: '15.10', + version: 'latest', + }, + + sku: { + name: 'Standard_A1', + tier: 'Standard', + capacity: 2, + }, + + osConfig: { + adminUserName: 'spinnakeruser', + adminPassword: '!Qnti**234', + }, }; - } - function convertServerGroupCommandToDeployConfiguration(base) { - // use _.defaults to avoid copying the backingData, which is huge and expensive to copy over - var command = _.defaults({backingData: [], viewState: []}, base); - if (base.viewState.mode !== 'clone') { - delete command.source; - } - if (base.viewState.useAllImageSelection) { - command.amiName = base.viewState.allImageSelection; + if (typeof base.stack != 'undefined') { + command.name = command.name + '-' + base.stack; } - command.availabilityZones = {}; - command.availabilityZones[command.region] = base.availabilityZones; - command.account = command.credentials; - if (!command.ramdiskId) { - delete command.ramdiskId; // TODO: clean up in kato? - should ignore if empty string - } - delete command.region; - delete command.viewState; - delete command.backingData; - delete command.selectedProvider; - delete command.instanceProfile; - delete command.vpcId; - - if (!command.subnetType) { - delete command.subnetType; + if(typeof base.details != 'undefined') { + command.name = command.name + '-' + base.details; } + return command; } return { convertServerGroupCommandToDeployConfiguration: convertServerGroupCommandToDeployConfiguration, - normalizeServerGroup: normalizeServerGroup, }; }); diff --git a/app/scripts/modules/azure/serverGroup/serverGroup.transformer.spec.js b/app/scripts/modules/azure/serverGroup/serverGroup.transformer.spec.js index dc072894836..be07b089333 100644 --- a/app/scripts/modules/azure/serverGroup/serverGroup.transformer.spec.js +++ b/app/scripts/modules/azure/serverGroup/serverGroup.transformer.spec.js @@ -2,7 +2,7 @@ describe('azureServerGroupTransformer', function () { - var transformer, azureVpcReader, $q, $scope; + var transformer, $q, $scope; beforeEach( window.module( @@ -11,80 +11,57 @@ describe('azureServerGroupTransformer', function () { ); beforeEach(function () { - window.inject(function (_azureServerGroupTransformer_, _azureVpcReader_, _$q_, $rootScope) { + window.inject(function (_azureServerGroupTransformer_, $rootScope) { transformer = _azureServerGroupTransformer_; - azureVpcReader = _azureVpcReader_; - $q = _$q_; $scope = $rootScope.$new(); }); }); - describe('normalize server group', function () { - beforeEach(function() { - spyOn(azureVpcReader, 'listVpcs').and.returnValue($q.when([ - {account: 'test', region: 'us-east-1', id: 'vpc-1', name: 'main'} - ])); - }); + describe('command transforms', function () { - it('adds vpc name to server group', function () { - var serverGroup = { - account: 'test', - region: 'us-east-1', - vpcId: 'vpc-1', - instances: [], + it('sets name correctly with no stack or detail', function () { + var base = { + application: 'myApp' }; - transformer.normalizeServerGroup(serverGroup); - $scope.$digest(); - expect(serverGroup.vpcName).toBe('main'); + + var transformed = transformer.convertServerGroupCommandToDeployConfiguration(base); + + expect(transformed.name).toBe('myApp'); + }); - it('adds empty vpc name when no vpcId found on server group', function () { - var serverGroup = { - account: 'test', - region: 'us-east-1', - instances: [], + it('it sets name correctly with only stack', function () { + var command = { + stack: 's1', + application: 'theApp' }; - transformer.normalizeServerGroup(serverGroup); - $scope.$digest(); - expect(serverGroup.vpcName).toBe(''); - }); - }); - describe('command transforms', function () { + var transformed = transformer.convertServerGroupCommandToDeployConfiguration(command); - it('sets amiName from allImageSelection', function () { + expect(transformed.name).toBe('theApp-s1'); + }); + + it('it sets name correctly with only detail', function () { var command = { - viewState: { - mode: 'create', - useAllImageSelection: true, - allImageSelection: 'something-packagebase', - }, - application: { name: 'theApp'} + details: 'd1', + application: 'theApp' }; var transformed = transformer.convertServerGroupCommandToDeployConfiguration(command); - expect(transformed.amiName).toBe('something-packagebase'); - + expect(transformed.name).toBe('theApp-d1'); }); - it('removes subnetType property when null', function () { + it('it sets name correctly with both stack and detail', function () { var command = { - viewState: { - mode: 'create', - useAllImageSelection: true, - allImageSelection: 'something-packagebase', - }, - subnetType: null, - application: { name: 'theApp'} + stack: 's1', + details: 'd1', + application: 'theApp' }; var transformed = transformer.convertServerGroupCommandToDeployConfiguration(command); - expect(transformed.subnetType).toBe(undefined); - command.subnetType = 'internal'; - transformed = transformer.convertServerGroupCommandToDeployConfiguration(command); - expect(transformed.subnetType).toBe('internal'); + expect(transformed.name).toBe('theApp-s1-d1'); }); }); diff --git a/app/scripts/modules/azure/vpc/vpc.module.js b/app/scripts/modules/azure/vpc/vpc.module.js deleted file mode 100644 index cd2ef791bd0..00000000000 --- a/app/scripts/modules/azure/vpc/vpc.module.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -let angular = require('angular'); - -module.exports = angular - .module('spinnaker.azure.vpc', [ - require('./vpc.read.service.js') - ]); diff --git a/app/scripts/modules/azure/vpc/vpc.read.service.js b/app/scripts/modules/azure/vpc/vpc.read.service.js deleted file mode 100644 index 844aace6382..00000000000 --- a/app/scripts/modules/azure/vpc/vpc.read.service.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - - -let angular = require('angular'); - -module.exports = angular - .module('spinnaker.azure.vpc.read.service', [ - require('exports?"restangular"!imports?_=lodash!restangular'), - require('../../core/utils/lodash.js'), - require('../../core/cache/infrastructureCaches.js') - ]) - .factory('azureVpcReader', function ($q, Restangular, infrastructureCaches ) { - - function listVpcs() { - return Restangular.all('vpcs') - .withHttpConfig({cache: infrastructureCaches.vpcs}) - .getList() - .then(function(vpcs) { - return vpcs.map(function(vpc) { - vpc.label = vpc.name; - vpc.deprecated = !!vpc.deprecated; - if (vpc.deprecated) { - vpc.label += ' (deprecated)'; - } - return vpc.plain(); - }); - }); - } - - function getVpcName(id) { - return listVpcs().then(function(vpcs) { - var matches = vpcs.filter(function(test) { - return test.id === id; - }); - return matches.length ? matches[0].name : null; - }); - } - - return { - listVpcs: listVpcs, - getVpcName: getVpcName, - }; - - }); diff --git a/app/scripts/modules/azure/vpc/vpc.read.service.spec.js b/app/scripts/modules/azure/vpc/vpc.read.service.spec.js deleted file mode 100644 index 04ce399b69d..00000000000 --- a/app/scripts/modules/azure/vpc/vpc.read.service.spec.js +++ /dev/null @@ -1,71 +0,0 @@ -'use strict'; - -describe('vpcReader', function() { - - var service, $http, $scope; - - beforeEach( - window.module( - require('./vpc.read.service.js') - ) - ); - - beforeEach(window.inject(function ($httpBackend, $rootScope, _azureVpcReader_) { - service = _azureVpcReader_; - $http = $httpBackend; - $scope = $rootScope.$new(); - })); - - beforeEach(function() { - $http.whenGET('/vpcs').respond(200, [ - { name: 'vpc1', id: 'vpc-1', deprecated: true }, - { name: 'vpc2', id: 'vpc-2', deprecated: false }, - { name: 'vpc3', id: 'vpc-3' }, - ]); - }); - - - it('adds label to vpc, including (deprecated) if deprecated field is true', function () { - - var result = null; - - service.listVpcs().then(function(vpcs) { result = vpcs; }); - - $http.flush(); - $scope.$digest(); - - expect(result[0].label).toBe('vpc1 (deprecated)'); - expect(result[0].deprecated).toBe(true); - expect(result[1].label).toBe('vpc2'); - expect(result[1].deprecated).toBe(false); - expect(result[2].label).toBe('vpc3'); - expect(result[2].deprecated).toBe(false); - }); - - it('retrieves vpc name - not label - from id', function() { - - var result = null; - - service.getVpcName('vpc-1').then(function(name) { result = name; }); - - $http.flush(); - $scope.$digest(); - - expect(result).toBe('vpc1'); - - service.getVpcName('vpc-2').then(function(name) { result = name; }); - - $http.flush(); - $scope.$digest(); - - expect(result).toBe('vpc2'); - - service.getVpcName('vpc-4').then(function(name) { result = name; }); - - $http.flush(); - $scope.$digest(); - - expect(result).toBe(null); - }); - -}); diff --git a/app/scripts/modules/azure/vpc/vpcTag.directive.js b/app/scripts/modules/azure/vpc/vpcTag.directive.js deleted file mode 100644 index 9a4c57e8c5b..00000000000 --- a/app/scripts/modules/azure/vpc/vpcTag.directive.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -let angular = require('angular'); - -module.exports = angular.module('spinnaker.azure.vpc.tag.directive', [ - require('./vpc.read.service.js'), -]) - .directive('azureVpcTag', function(vpcReader) { - return { - restrict: 'E', - scope: { - vpcId: '=', - }, - template: '{{vpcLabel}}', - link: function(scope) { - function applyLabel() { - if (!scope.vpcId) { - scope.vpcLabel = 'None (EC2 Classic)'; - } else { - vpcReader.getVpcName(scope.vpcId).then(function (name) { - scope.vpcLabel = '(' + scope.vpcId + ')'; - - if (name) { - scope.vpcLabel = name + ' ' + scope.vpcLabel; - } - }); - } - } - - scope.$watch('vpcId', applyLabel, true); - } - }; - }); diff --git a/app/scripts/modules/azure/vpc/vpcTag.directive.spec.js b/app/scripts/modules/azure/vpc/vpcTag.directive.spec.js deleted file mode 100644 index c3a5fe9cfbc..00000000000 --- a/app/scripts/modules/azure/vpc/vpcTag.directive.spec.js +++ /dev/null @@ -1,65 +0,0 @@ - 'use strict'; - - xdescribe('Directives: azureVpcTag', function () { - - var $q, vpcReader; - - beforeEach( - window.module( - require('./vpcTag.directive.js'), - require('./vpc.read.service.js') - ) - ); - - beforeEach(window.inject(function ($rootScope, $compile, _$q_, _azureVpcReader_) { - this.scope = $rootScope.$new(); - this.compile = $compile; - $q = _$q_; - vpcReader = _azureVpcReader_; - })); - - describe('vpc tag rendering - no VPC provided', function () { - - it('displays default message when no vpcId supplied', function () { - var domNode = this.compile('')(this.scope); - this.scope.$digest(); - expect(domNode.find('span').text()).toBe('None (EC2 Classic)'); - }); - - it('displays default message when undefined vpcId supplied', function () { - var domNode = this.compile('')(this.scope); - this.scope.$digest(); - expect(domNode.find('span').text()).toBe('None (EC2 Classic)'); - }); - - it('displays default message when null vpcId supplied', function () { - this.scope.vpcId = null; - var domNode = this.compile('')(this.scope); - this.scope.$digest(); - expect(domNode.find('span').text()).toBe('None (EC2 Classic)'); - }); - }); - - describe('vpc tag rendering - VPC provided', function () { - - it('displays vpc name when found', function() { - spyOn(vpcReader, 'getVpcName').and.callFake(function() { - return $q.when('Main VPC'); - }); - this.scope.vpcId = 'vpc-1'; - var domNode = this.compile('')(this.scope); - this.scope.$digest(); - expect(domNode.find('span').text()).toBe('Main VPC (vpc-1)'); - }); - - it('displays vpc id when not found', function() { - spyOn(vpcReader, 'getVpcName').and.callFake(function() { - return $q.when(null); - }); - this.scope.vpcId = 'vpc-2'; - var domNode = this.compile('')(this.scope); - this.scope.$digest(); - expect(domNode.find('span').text()).toBe('(vpc-2)'); - }); - }); - }); diff --git a/app/scripts/modules/core/help/helpContents.js b/app/scripts/modules/core/help/helpContents.js index ec04d61fdf3..6c3cf404e34 100644 --- a/app/scripts/modules/core/help/helpContents.js +++ b/app/scripts/modules/core/help/helpContents.js @@ -112,7 +112,7 @@ module.exports = angular.module('spinnaker.core.help.contents', []) 'gce.serverGroup.customMetadata.startup-script': 'This script will run automatically on every boot.', 'gce.serverGroup.preemptibility': 'A preemptible VM costs much less, but lasts only 24 hours. It can be terminated sooner due to system demands.', 'gce.serverGroup.automaticRestart': 'Compute Engine can automatically restart VM instances if they are terminated for non-user-initiated reasons (maintenance event, hardware failure, software failure, etc.).', - 'gce.serverGroup.onHostMaintenance': 'When Compute Engine performs periodic infrastructure maintenance it can migrate your VM instances to other hardware without downtime.', + 'gce.serverGroup.onHostMaintenance': 'When Cosdfgdsfmpute Engine performs periodic infrastructure maintenance it can migrate your VM instances to other hardware without downtime.', 'gce.serverGroup.securityGroups.implicit': 'Firewall rules with no target tags defined will permit incoming connections that match the ingress rules to all instances in the network.', 'gce.serverGroup.autoscaling.targetCPUUsage': 'Autoscaling adds or removes VMs in the group to maintain this level of CPU usage on each VM.', 'gce.serverGroup.autoscaling.targetHTTPLoadBalancingUsage': 'Autoscaling adds or removes VMs in the group to maintain this usage of load-balancing capacity. This value is a percentage of the \'Maximum rate\' setting of the load balancer this group is used by.', @@ -154,7 +154,7 @@ module.exports = angular.module('spinnaker.core.help.contents', []) 'pipeline.config.bake.package': '

The name of the package you want installed (without any version identifiers).

' + '

If your build produces a deb file named "myapp_1.27-h343", you would want to enter "myapp" here.

', 'pipeline.config.bake.baseAmi': '

(Optional) ami-????????

', - 'pipeline.config.bake.amiSuffix': '

(Optional) String of date in format YYYYMMDDHHmm, default is calculated from timestamp,

', + 'pipeline.config.bake.amiSuffix': '

(Optionsdfgdsfal) String of date in format YYYYMMDDHHmm, default is calculated from timestamp,

', 'pipeline.config.bake.enhancedNetworking': '

(Optional) Enable enhanced networking (sr-iov) support for image (requires hvm and trusty base_os).

', 'pipeline.config.bake.amiName': '

(Optional) Default = $package-$arch-$ami_suffix-$store_type

', 'pipeline.config.bake.templateFileName': '

(Optional) The explicit packer template to use, instead of resolving one from rosco\'s configuration.

', @@ -199,8 +199,12 @@ module.exports = angular.module('spinnaker.core.help.contents', []) '

Note: values for "DayOfWeek" are 1-7, where Sunday is 1, Monday is 2, etc. You can also use MON,TUE,WED, etc.', 'cluster.description': '

A cluster is a collection of server groups with the same name (stack + detail) in the same account.

', +<<<<<<< HEAD 'pipeline.config.findAmi.cluster': 'The cluster to look at when selecting the image to use in this pipeline.', +======= + 'pipeline.config.findAmi.cluster': 'The cluster to look at when selecting the AMI to use in this pipeline.', +>>>>>>> fa75c9d... Fixes to security groups to work with cloud driver 'pipeline.config.dependsOn': 'Declares which stages must be run before this stage begins.', 'pipeline.config.parallel.execution': '

Enabling parallel stage execution allows you to run stages only after dependent ' + 'stages have completed.

By configuring a pipeline this way, you can reduce the time it takes to run.

', @@ -266,4 +270,12 @@ module.exports = angular.module('spinnaker.core.help.contents', []) 'user.verification': 'Typing into this verification field is annoying! But it serves as a reminder that you are ' + 'changing something in an account deemed important, and prevents you from accidentally changing something ' + 'when you meant to click on the "Cancel" button.', + 'azure.securityGroup.ingress.description': 'Friendly description of the rule you want to enable (limit 80 chars.)', + 'azure.securityGroup.ingress.priority': 'Rules are processed in priority order; the lower the number, the higher the priority. We recommend leaving gaps between rules - 100, 200, 300, etc. - so that it\'s easier to add new rules without having to edit existing rules. There are several default rules that can be overridden with priority (65000, 65001 and 65500). For more information visit http://portal.azure.com.' , + 'azure.securityGroup.ingress.source': 'The source filter can be Any, an IP address range or a default tag(\'Internet\', \'VirtualNetwork\', \AzureLoadBalancer\'). It specifies the incoming traffic from a specific source IP address range (CIDR format) that will be allowed or denied by this rule.', + 'azure.securityGroup.ingress.sourcePortRange': 'The source port range can be a single port, such as 80, or a port range, such as 1024-65535. This specifies from which ports incoming traffic will be allowed or denied by this rule. Provide an asterisk (*) to allow traffic from clients connecting from any port.', + 'azure.securityGroup.ingress.destination': 'The destination filter can be Any, an IP address range or a default tag(\'Internet\', \'VirtualNetwork\', \AzureLoadBalancer\'). It specifies the outgoing traffic from a specific destination IP address range (CIDR format) that will be allowed or denied by this rule.', + 'azure.securityGroup.ingress.destinationPortRange': 'The destination port range can be a single port, such as 80, or a port range, such as 1024-65535. This specifies from which destination ports traffic will be allowed or denied by this rule. Provide an asterisk (*) to allow traffic from clients connecting from any port.', + 'azure.securityGroup.ingress.direction': 'Specifies whether the rule is for inbound or outbound traffic.', + 'azure.securityGroup.ingress.actions': 'To adjust the priority of a rule, move it up or down in the list of rules. Rules at the top of the list have the highest priority.', }); diff --git a/settings.js b/settings.js index 020670ff577..c0ab4cb233c 100644 --- a/settings.js +++ b/settings.js @@ -17,7 +17,7 @@ window.spinnakerSettings = { azure: { defaults: { account: 'azure-test', - region: 'West US' + region: 'westus' }, }, aws: { From c5630323327cefe99d4c0e6f91d5ff34dfd0e6b8 Mon Sep 17 00:00:00 2001 From: Adam Jordens Date: Mon, 8 Feb 2016 12:27:01 -0800 Subject: [PATCH 018/151] ForceCacheRefresh tasks should not be hidden --- app/scripts/modules/core/task/displayableTasks.filter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/modules/core/task/displayableTasks.filter.js b/app/scripts/modules/core/task/displayableTasks.filter.js index 17c0733590b..8c0880089b3 100644 --- a/app/scripts/modules/core/task/displayableTasks.filter.js +++ b/app/scripts/modules/core/task/displayableTasks.filter.js @@ -5,7 +5,7 @@ let angular = require('angular'); module.exports = angular.module('spinnaker.pipelines.stages.core.displayableTasks.filter', []) .filter('displayableTasks', function() { var blacklist = [ - 'forceCacheRefresh', 'stageStart', 'stageEnd' + 'stageStart', 'stageEnd' ]; return function(input) { if (input) { From 35df504c9cb3d194a5590e1ab6ba99c02a7c5c0b Mon Sep 17 00:00:00 2001 From: chrisb Date: Mon, 1 Feb 2016 13:29:15 -0800 Subject: [PATCH 019/151] update pipeline migrator for classic -> vpc0 --- .../netflix/migrator/migrator.service.js | 2 +- .../netflix/migrator/migrator.service.spec.js | 21 +- .../pipeline/pipeline.migrator.directive.js | 195 +++++++++--------- .../pipeline/pipeline.migrator.modal.html | 64 +++--- 4 files changed, 148 insertions(+), 134 deletions(-) diff --git a/app/scripts/modules/netflix/migrator/migrator.service.js b/app/scripts/modules/netflix/migrator/migrator.service.js index 2b2b7449de5..f4c6692304d 100644 --- a/app/scripts/modules/netflix/migrator/migrator.service.js +++ b/app/scripts/modules/netflix/migrator/migrator.service.js @@ -49,7 +49,7 @@ module.exports = angular if (tideTask.taskComplete && tideTask.taskComplete.status === 'failure') { return tideTask.taskComplete.message; } - return null; + return task.failureMessage; } function getPreview(task) { diff --git a/app/scripts/modules/netflix/migrator/migrator.service.spec.js b/app/scripts/modules/netflix/migrator/migrator.service.spec.js index d7e2cbde4d9..ec2c48c4c4d 100644 --- a/app/scripts/modules/netflix/migrator/migrator.service.spec.js +++ b/app/scripts/modules/netflix/migrator/migrator.service.spec.js @@ -161,7 +161,7 @@ describe('Service: migrator', function () { it('only returns message if task finished and failed', function () { - expect(this.getException()).toBe(null); + expect(this.getException()).toBeUndefined(); this.tideTask = { taskComplete: { @@ -169,7 +169,7 @@ describe('Service: migrator', function () { } }; - expect(this.getException()).toBe(null); + expect(this.getException()).toBeUndefined(); this.tideTask = { taskComplete: { @@ -181,6 +181,23 @@ describe('Service: migrator', function () { expect(this.getException()).toEqual('the error'); }); + it('falls back to failure message from task if present', function () { + + this.tideTask = { + taskComplete: { + status: 'failure', + message: 'tide failed', + }, + }; + + this.task.failureMessage = 'task failed'; + expect(this.getException()).toBe('tide failed'); + + this.tideTask.taskComplete = {}; + expect(this.getException()).toBe('task failed'); + + }); + }); }); diff --git a/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.directive.js b/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.directive.js index 93053afa836..03e9f5aff80 100644 --- a/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.directive.js +++ b/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.directive.js @@ -8,14 +8,13 @@ module.exports = angular .module('spinnaker.migrator.pipeline.directive', [ require('angular-ui-bootstrap'), require('../../../amazon/vpc/vpc.read.service.js'), - require('../../../amazon/subnet/subnet.read.service.js'), require('../../../core/config/settings.js'), require('../migrator.service.js'), - require('../../../core/utils/lodash.js'), require('../../../core/presentation/autoScroll/autoScroll.directive.js'), require('../../../core/pipeline/config/services/pipelineConfigService.js'), require('../../../core/utils/scrollTo/scrollTo.service.js'), require('../../../core/cache/cacheInitializer.js'), + require('../../../core/task/task.read.service.js'), ]) .directive('pipelineMigrator', function () { return { @@ -30,63 +29,46 @@ module.exports = angular controllerAs: 'migratorActionCtrl', }; }) - .controller('PipelineMigratorActionCtrl', function ($scope, $uibModal, vpcReader, settings, subnetReader, _) { + .controller('PipelineMigratorActionCtrl', function ($scope, $uibModal, vpcReader, settings) { $scope.showAction = false; $scope.submittingTemplateUrl = require('../migrator.modal.submitting.html'); - var subnets, - actionableDeployStages = []; + var actionableDeployStages = []; function testCluster(stage) { return function(cluster) { - var region = cluster.availabilityZones ? Object.keys(cluster.availabilityZones)[0] : null; - var account = cluster.account; - var subnetType = cluster.subnetType; - if (subnetType) { - var subnetMatches = _(subnets) - .filter({account: account, region: region, purpose: subnetType}) - .reject({target: 'elb'}) - .valueOf(); - if (subnetMatches.length) { - return vpcReader.getVpcName(subnetMatches[0].vpcId).then(function (vpc) { - if (vpc === 'Main') { - $scope.showAction = true; - if (cluster.strategy === 'highlander' || cluster.strategy === 'redblack') { - actionableDeployStages.push({strategy: cluster.strategy, name: stage.name}); - } - } - }); + if (!cluster.subnetType && cluster.provider === 'aws') { + $scope.showAction = true; + if (cluster.strategy !== '') { + actionableDeployStages.push({strategy: cluster.strategy, name: stage.name}); } } }; } if (settings.feature.vpcMigrator) { - subnetReader.listSubnets().then(function (loadedSubnets) { - subnets = loadedSubnets; - var stages = $scope.pipeline.stages || []; - stages.forEach(function (stage) { - if (stage.type === 'deploy') { - var clusters = stage.clusters || []; - clusters.forEach(testCluster(stage)); - } - if (stage.type === 'canary') { - var clusterPairs = stage.clusterPairs || []; - clusterPairs.forEach(function (clusterPair) { - testCluster(stage)(clusterPair.baseline); - testCluster(stage)(clusterPair.canary); - }); - } - }); + var stages = $scope.pipeline.stages || []; + stages.forEach((stage) => { + if (stage.type === 'deploy') { + var clusters = stage.clusters || []; + clusters.forEach(testCluster(stage)); + } + if (stage.type === 'canary') { + var clusterPairs = stage.clusterPairs || []; + clusterPairs.forEach((clusterPair) => { + testCluster(stage)(clusterPair.baseline); + testCluster(stage)(clusterPair.canary); + }); + } }); } this.previewMigration = function () { $uibModal.open({ templateUrl: require('./pipeline.migrator.modal.html'), - controller: 'PipelineMigratorCtrl as ctrl', + controller: 'PipelineMigratorCtrl as vm', resolve: { pipeline: function () { return $scope.pipeline; @@ -94,9 +76,6 @@ module.exports = angular application: function () { return $scope.application; }, - type: function() { - return $scope.type; - }, actionableDeployStages: function() { return actionableDeployStages; }, @@ -104,87 +83,105 @@ module.exports = angular }); }; }) - .controller('PipelineMigratorCtrl', function ($scope, pipeline, application, type, actionableDeployStages, - $modalInstance, + .controller('PipelineMigratorCtrl', function ($scope, pipeline, application, actionableDeployStages, + $modalInstance, taskReader, $timeout, $state, migratorService, pipelineConfigService, scrollToService, cacheInitializer) { - $scope.application = application; - $scope.pipeline = pipeline; - $scope.actionableDeployStages = actionableDeployStages; + this.submittingTemplateUrl = require('../migrator.modal.submitting.html'); + + this.actionableDeployStages = actionableDeployStages; - $scope.viewState = { + this.viewState = { computing: true, + executing: false, + error: false, + migrationComplete: false, }; - var source = { pipelineId: pipeline.id, vpcName: 'Main', }, - target = { vpcName: 'vpc0', }; - - - var migrationConfig = { - application: application, - type: 'deepCopyPipeline', - name: pipeline.name, - source: source, - target: target, - dryRun: true, + // shared component used by "submitting" overlay to indicate what's being operated against + this.component = { + name: pipeline.name }; - var dryRun = migratorService.executeMigration(migrationConfig); + // Async handlers - dryRun.deferred.promise.then( - function () { - $scope.viewState.computing = false; - $scope.preview = dryRun.executionPlan; - }, - function (error) { - $scope.viewState.computing = false; - $scope.viewState.error = error; + let errorMode = (error) => { + this.viewState.computing = false; + this.viewState.executing = false; + this.viewState.error = error || 'An unknown error occurred. Please try again later.'; + if (!error && this.task && this.task.getTideException()) { + this.viewState.error = this.task.getTideException(); } - ); + }; - this.cancel = function () { - dryRun.deferred.promise.cancelled = true; - if ($scope.executor) { - $scope.executor.deferred.promise.cancelled = true; - } - $modalInstance.dismiss(); + let dryRunComplete = () => { + this.viewState.computing = false; + this.preview = this.task.getPreview(); }; - this.submit = function () { - $scope.viewState.executing = true; - migrationConfig.dryRun = false; - var executor = migratorService.executeMigration(migrationConfig); - executor.deferred.promise.then( - function () { - $scope.viewState.executing = false; - $scope.viewState.migrationComplete = true; - reinitialize(); - }, - function (error) { - $scope.viewState.executing = false; - $scope.viewState.error = error; - } - ); - $scope.executor = executor; + let dryRunStarted = (task) => { + this.task = task; + taskReader.waitUntilTaskCompletes(application.name, task).then(dryRunComplete, errorMode); }; - function reinitialize() { - pipelineConfigService.getPipelinesForApplication(application.name).then(function (pipelines) { + let reinitialize = () => { + pipelineConfigService.getPipelinesForApplication(application.name).then((pipelines) => { application.pipelines = pipelines; // TODO: pipeline ID is not yet populated in the task result from Tide, so build it out based on name - var newPipelines = pipelines.filter(function(test) { + var [newPipeline] = pipelines.filter(function(test) { return test.name.indexOf(pipeline.name + ' - vpc0') === 0; }); - if (newPipelines && newPipelines.length) { - scrollToService.scrollTo('pipeline-config-' + newPipelines[0].id, '.execution-groups', 180); + if (newPipeline) { + $state.go('^.pipelineConfig', {pipelineId: newPipeline.id}); } - if ($scope.preview.securityGroups && $scope.preview.securityGroups.length) { + if (this.preview.securityGroups && this.preview.securityGroups.length) { cacheInitializer.refreshCache('securityGroups'); } - if ($scope.preview.loadBalancers && $scope.preview.loadBalancers.length) { + if (this.preview.loadBalancers && this.preview.loadBalancers.length) { cacheInitializer.refreshCache('loadBalancers'); } }); - } + }; + + let migrationComplete = () => { + this.viewState.executing = false; + this.viewState.migrationComplete = true; + reinitialize(); + }; + + let migrationStarted = (task) => { + this.task = task; + taskReader.waitUntilTaskCompletes(application.name, task).then(migrationComplete, errorMode); + }; + + var source = { pipelineId: pipeline.id }, + target = { vpcName: 'vpc0', }; + + + var migrationConfig = { + application: application, + type: 'deepCopyPipeline', + name: pipeline.name, + source: source, + target: target, + dryRun: true, + }; + + // Generate preview + let executor = migratorService.executeMigration(migrationConfig); + + executor.then(dryRunStarted, errorMode); + + this.cancel = () => { + $timeout.cancel(this.task.poller); + $modalInstance.dismiss(); + }; + + this.submit = () => { + this.viewState.executing = true; + migrationConfig.dryRun = false; + let executor = migratorService.executeMigration(migrationConfig); + executor.then(migrationStarted, errorMode); + }; }); diff --git a/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.modal.html b/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.modal.html index 81714b7c875..23b4e20e67d 100644 --- a/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.modal.html +++ b/app/scripts/modules/netflix/migrator/pipeline/pipeline.migrator.modal.html @@ -1,13 +1,13 @@
-
+

- - - - - - + + + diff --git a/app/scripts/modules/google/serverGroup/configure/wizard/capacity.html b/app/scripts/modules/google/serverGroup/configure/wizard/capacity.html index 2495ac57fa0..337d3680d4a 100644 --- a/app/scripts/modules/google/serverGroup/configure/wizard/capacity.html +++ b/app/scripts/modules/google/serverGroup/configure/wizard/capacity.html @@ -1,20 +1,3 @@
- +
diff --git a/app/scripts/modules/google/serverGroup/configure/wizard/instanceArchetype.html b/app/scripts/modules/google/serverGroup/configure/wizard/instanceArchetype.html deleted file mode 100644 index 38c1ccd4d74..00000000000 --- a/app/scripts/modules/google/serverGroup/configure/wizard/instanceArchetype.html +++ /dev/null @@ -1,20 +0,0 @@ -
- - -
diff --git a/app/scripts/modules/google/serverGroup/configure/wizard/instanceType.html b/app/scripts/modules/google/serverGroup/configure/wizard/instanceType.html index 1ae13d2b1eb..efe9a763be8 100644 --- a/app/scripts/modules/google/serverGroup/configure/wizard/instanceType.html +++ b/app/scripts/modules/google/serverGroup/configure/wizard/instanceType.html @@ -1,20 +1,8 @@ -
-
diff --git a/app/scripts/modules/google/serverGroup/configure/wizard/templateSelection.html b/app/scripts/modules/google/serverGroup/configure/wizard/templateSelection.html index 240f6fc4fca..e1b4bf02868 100644 --- a/app/scripts/modules/google/serverGroup/configure/wizard/templateSelection.html +++ b/app/scripts/modules/google/serverGroup/configure/wizard/templateSelection.html @@ -6,16 +6,13 @@

Template Selection