Skip to content

(aws) Allow selection of VPC load balancers on Classic ASGs #2265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,18 @@ module.exports = angular.module('spinnaker.loadBalancer.aws.details.controller',
$scope.InsightFilterStateModel = InsightFilterStateModel;

function extractLoadBalancer() {
if (!loadBalancer.vpcId) {
loadBalancer.vpcId = null;
}
$scope.loadBalancer = app.loadBalancers.data.filter(function (test) {
var testVpc = test.vpcId || null;
return test.name === loadBalancer.name && test.region === loadBalancer.region && test.account === loadBalancer.accountId && testVpc === loadBalancer.vpcId;
})[0];
let [appLoadBalancer] = app.loadBalancers.data.filter(function (test) {
Copy link
Contributor

@zanthrash zanthrash May 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does wrapping a variable name in square brackets do? Is it to coerce the outputs of the filter into an array?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, exactly - it's using ES6 array destructuring. Since filter returns an array, this sets appLoadBalancer to the first item in the array (or undefined if the filter returns an empty collection).

return test.name === loadBalancer.name && test.region === loadBalancer.region && test.account === loadBalancer.accountId;
});

if ($scope.loadBalancer) {
var detailsLoader = loadBalancerReader.getLoadBalancerDetails($scope.loadBalancer.provider, loadBalancer.accountId, loadBalancer.region, loadBalancer.name);
if (appLoadBalancer) {
var detailsLoader = loadBalancerReader.getLoadBalancerDetails('aws', loadBalancer.accountId, loadBalancer.region, loadBalancer.name);
return detailsLoader.then(function(details) {
$scope.loadBalancer = appLoadBalancer;
$scope.state.loading = false;
var securityGroups = [];
var filtered = details.filter(function(test) {
return test.vpcid === loadBalancer.vpcId || (!test.vpcid && !loadBalancer.vpcId);
});
if (filtered.length) {
$scope.loadBalancer.elb = filtered[0];
if (details.length) {
$scope.loadBalancer.elb = details[0];
$scope.loadBalancer.account = loadBalancer.accountId;

if ($scope.loadBalancer.elb.availabilityZones) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,25 +331,46 @@ module.exports = angular.module('spinnaker.aws.serverGroup.configure.service', [
.flatten(true)
.filter({vpcId: command.vpcId})
.pluck('name')
.unique()
.valueOf()
.sort();
}

function getVpcLoadBalancerNames(command) {
return _(command.backingData.loadBalancers)
.pluck('accounts')
.flatten(true)
.filter({name: command.credentials})
.pluck('regions')
.flatten(true)
.filter({name: command.region})
.pluck('loadBalancers')
.flatten(true)
.filter('vpcId')
.pluck('name')
.valueOf()
.sort();
}

function configureLoadBalancerOptions(command) {
var result = { dirty: {} };
var current = command.loadBalancers;
var current = (command.loadBalancers || []).concat(command.vpcLoadBalancers || []);
var newLoadBalancers = getLoadBalancerNames(command);
var vpcLoadBalancers = getVpcLoadBalancerNames(command);

if (current && command.loadBalancers) {
var matched = _.intersection(newLoadBalancers, command.loadBalancers);
var valid = command.vpcId ? newLoadBalancers : newLoadBalancers.concat(vpcLoadBalancers);
var matched = _.intersection(valid, current);
var removed = _.xor(matched, current);
command.loadBalancers = matched;
command.loadBalancers = _.intersection(newLoadBalancers, matched);
if (!command.vpcId) {
command.vpcLoadBalancers = _.intersection(vpcLoadBalancers, matched);
}
if (removed.length) {
result.dirty.loadBalancers = removed;
}
}
command.backingData.filtered.loadBalancers = newLoadBalancers;
command.backingData.filtered.vpcLoadBalancers = vpcLoadBalancers;
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ describe('Service: awsServerGroupConfiguration', function () {
{
name: 'us-east-1',
loadBalancers: [
{ region: 'us-east-1', vpcId: null, name: 'elb-1' },
{ region: 'us-east-1', vpcId: 'vpc-1', name: 'elb-1' },
]
}
Expand All @@ -54,7 +53,6 @@ describe('Service: awsServerGroupConfiguration', function () {
{
name: 'us-east-1',
loadBalancers: [
{ region: 'us-east-1', vpcId: null, name: 'elb-2' },
{ region: 'us-east-1', vpcId: 'vpc-2', name: 'elb-2' },
]
},
Expand Down Expand Up @@ -193,7 +191,8 @@ describe('Service: awsServerGroupConfiguration', function () {
it('matches existing load balancers based on name - no VPC', function () {
var result = service.configureLoadBalancerOptions(this.command);

expect(this.command.loadBalancers).toEqual(['elb-1']);
expect(this.command.loadBalancers).toEqual([]);
expect(this.command.vpcLoadBalancers).toEqual(['elb-1']);
expect(result).toEqual({ dirty: { }});
});

Expand All @@ -214,6 +213,22 @@ describe('Service: awsServerGroupConfiguration', function () {
expect(result).toEqual({ dirty: { loadBalancers: ['elb-1']}});
});

it('moves load balancers to vpcLoadBalancers when vpc is de-selected', function () {
this.command.loadBalancers = ['elb-1'];
this.command.vpcId = 'vpc-1';
var result = service.configureLoadBalancerOptions(this.command);

expect(this.command.loadBalancers).toEqual(['elb-1']);
expect(result).toEqual({ dirty: {} });

this.command.vpcId = null;
result = service.configureLoadBalancerOptions(this.command);
expect(result).toEqual({ dirty: {} });
expect(this.command.vpcLoadBalancers).toEqual(['elb-1']);
expect(this.command.loadBalancers).toEqual([]);

});

it('sets dirty all unmatched load balancers - VPC', function () {
this.command.loadBalancers = ['elb-1', 'elb-2'];
this.command.vpcId = 'vpc-1';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,65 @@
<div class="row">
<div class="col-md-12" ng-if="vm.command.viewState.dirty.loadBalancers">
<div class="alert alert-warning">
<p><span class="glyphicon glyphicon-warning-sign"></span>
The following load balancers could not be found in the selected account/region/VPC and were removed:
</p>
<ul>
<li ng-repeat="loadBalancer in vm.command.viewState.dirty.loadBalancers">{{loadBalancer}}</li>
</ul>
<p class="text-right">
<a class="btn btn-sm btn-default dirty-flag-dismiss" href ng-click="vm.command.viewState.dirty.loadBalancers = null">Okay</a>
</p>
<div class="col-md-12" ng-if="vm.command.viewState.dirty.loadBalancers">
<div class="alert alert-warning">
<p><span class="glyphicon glyphicon-warning-sign"></span>
The following load balancers could not be found in the selected account/region/VPC and were removed:
</p>
<ul>
<li ng-repeat="loadBalancer in vm.command.viewState.dirty.loadBalancers">{{loadBalancer}}</li>
</ul>
<p class="text-right">
<a class="btn btn-sm btn-default dirty-flag-dismiss" href ng-click="vm.command.viewState.dirty.loadBalancers = null">Okay</a>
</p>
</div>
</div>
</div>

<div class="form-group">
<div class="col-md-3 sm-label-right"><b>Load Balancers</b></div>
<div class="col-md-9">
<ui-select ng-if="vm.command.backingData.filtered.loadBalancers.length"
multiple
ng-model="vm.command.loadBalancers"
class="form-control input-sm">
<ui-select-match>{{$item}}</ui-select-match>
<ui-select-choices repeat="loadBalancer in vm.command.backingData.filtered.loadBalancers | filter: $select.search">
<span ng-bind-html="loadBalancer | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
<div class="form-group">
<div class="col-md-3 sm-label-right"><b>Load Balancers</b></div>
<div class="col-md-9">
<ui-select ng-if="vm.command.backingData.filtered.loadBalancers.length"
multiple
ng-model="vm.command.loadBalancers"
class="form-control input-sm">
<ui-select-match>{{$item}}</ui-select-match>
<ui-select-choices repeat="loadBalancer in vm.command.backingData.filtered.loadBalancers | filter: $select.search">
<span ng-bind-html="loadBalancer | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
<div class="form-group" ng-if="!vm.command.vpcId">
<div ng-if="!vm.command.vpcLoadBalancers.length && !vm.showVpcLoadBalancers">
<div class="col-md-9 col-md-offset-3">
<a href ng-click="vm.showVpcLoadBalancers = true">Add VPC Load Balancers</a>
</div>
</div>
<div ng-if="vm.command.vpcLoadBalancers.length || vm.showVpcLoadBalancers">
<div class="col-md-3 sm-label-right"><b>VPC Load Balancers</b></div>
<div class="col-md-9">
<ui-select ng-if="vm.command.backingData.filtered.vpcLoadBalancers.length"
multiple
ng-model="vm.command.vpcLoadBalancers"
class="form-control input-sm">
<ui-select-match>{{$item}}</ui-select-match>
<ui-select-choices repeat="loadBalancer in vm.command.backingData.filtered.vpcLoadBalancers | filter: $select.search">
<span ng-bind-html="loadBalancer | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
</div>

<div class="form-group small" style="margin-top: 20px">
<div class="col-md-9 col-md-offset-3">
<p>
<span ng-if="vm.refreshing"><span class="small glyphicon glyphicon-refresh glyphicon-spinning"></span></span>
Load balancers
<span ng-if="!vm.refreshing">last refreshed {{ vm.getLoadBalancerRefreshTime() | timestamp }}</span>
<span ng-if="vm.refreshing"> refreshing...</span>
</p>
<p>If you're not finding a load balancer that was recently added,
<a href ng-click="vm.refreshLoadBalancers()">click here</a> to refresh the list.
</p>
<div class="form-group small" style="margin-top: 20px">
<div class="col-md-9 col-md-offset-3">
<p>
<span ng-if="vm.refreshing"><span class="small glyphicon glyphicon-refresh glyphicon-spinning"></span></span>
Load balancers
<span ng-if="!vm.refreshing">last refreshed {{ vm.getLoadBalancerRefreshTime() | timestamp }}</span>
<span ng-if="vm.refreshing"> refreshing...</span>
</p>
<p>If you're not finding a load balancer that was recently added,
<a href ng-click="vm.refreshLoadBalancers()">click here</a> to refresh the list.
</p>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ module.exports = angular.module('spinnaker.aws.serverGroup.transformer', [
command.cloudProvider = 'aws';
command.availabilityZones = {};
command.availabilityZones[command.region] = base.availabilityZones;
command.loadBalancers = (base.loadBalancers || []).concat(base.vpcLoadBalancers || []);
command.account = command.credentials;
if (!command.ramdiskId) {
delete command.ramdiskId; // TODO: clean up in kato? - should ignore if empty string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
</div>
<a
ng-repeat="loadBalancer in serverGroup.loadBalancers | orderBy:'toString()'"
ui-sref=".loadBalancerDetails({region: serverGroup.region, accountId: serverGroup.account, name: loadBalancer, vpcId: serverGroup.vpcId, provider: serverGroup.type})"
ui-sref=".loadBalancerDetails({region: serverGroup.region, accountId: serverGroup.account, name: loadBalancer, provider: serverGroup.type})"
>{{loadBalancer}}
</a>
</div>
<span class="btn-load-balancer" ng-if="serverGroup.loadBalancers.length <= maxDisplay">
<button
class="btn btn-link no-padding"
ng-repeat="loadBalancer in serverGroup.loadBalancers | orderBy:'toString()'"
ui-sref=".loadBalancerDetails({region: serverGroup.region, accountId: serverGroup.account, name: loadBalancer, vpcId: serverGroup.vpcId, provider: serverGroup.type})"
ui-sref=".loadBalancerDetails({region: serverGroup.region, accountId: serverGroup.account, name: loadBalancer, provider: serverGroup.type})"
ui-sref-active="active"
uib-tooltip="Load Balancer: {{loadBalancer}}">
<span class="icon">
Expand Down