Skip to content

Commit

Permalink
Merge pull request #3507 from anotherchrisberry/cluster-fetch
Browse files Browse the repository at this point in the history
feat(clusters): fetch clusters on demand for very large apps
  • Loading branch information
anotherchrisberry committed Apr 10, 2017
2 parents 0241de0 + 0546161 commit 6a26ade
Show file tree
Hide file tree
Showing 30 changed files with 1,001 additions and 835 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import {ApplicationDataSourceRegistry} from './applicationDataSource.registry';
import {Application} from '../application.model';
import {LOAD_BALANCER_READ_SERVICE, LoadBalancerReader} from 'core/loadBalancer/loadBalancer.read.service';
import {SECURITY_GROUP_READER, SecurityGroupReader} from 'core/securityGroup/securityGroupReader.service';
import {CLUSTER_SERVICE, ClusterService} from 'core/cluster/cluster.service';

describe('Service: applicationReader', function () {

let applicationReader: ApplicationReader;
let securityGroupReader: SecurityGroupReader;
let loadBalancerReader: any;
let clusterService: any;
let clusterService: ClusterService;
let API: Api;
let $q: ng.IQService;
let $scope: ng.IScope;
Expand All @@ -26,14 +27,14 @@ describe('Service: applicationReader', function () {
require('../../serverGroup/serverGroup.dataSource'),
require('../../loadBalancer/loadBalancer.dataSource'),
SECURITY_GROUP_READER,
require('../../cluster/cluster.service'),
CLUSTER_SERVICE,
LOAD_BALANCER_READ_SERVICE,
)
);

beforeEach(
mock.inject(function (_applicationReader_: ApplicationReader, _securityGroupReader_: SecurityGroupReader,
_clusterService_: any, _API_: Api, _$q_: ng.IQService,
_clusterService_: ClusterService, _API_: Api, _$q_: ng.IQService,
_loadBalancerReader_: LoadBalancerReader, $rootScope: ng.IRootScopeService,
_applicationDataSourceRegistry_: ApplicationDataSourceRegistry) {
applicationReader = _applicationReader_;
Expand Down Expand Up @@ -74,22 +75,22 @@ describe('Service: applicationReader', function () {
it ('loads all data sources if dataSource attribute is missing', function () {
loadApplication();
expect(application.attributes.dataSources).toBeUndefined();
expect(clusterService.loadServerGroups.calls.count()).toBe(1);
expect((<Spy>clusterService.loadServerGroups).calls.count()).toBe(1);
expect((<Spy>securityGroupReader.getApplicationSecurityGroups).calls.count()).toBe(1);
expect(loadBalancerReader.loadLoadBalancers.calls.count()).toBe(1);
});

it ('loads all data sources if disabled dataSource attribute is an empty array', function () {
loadApplication({ enabled: [], disabled: []});
expect(clusterService.loadServerGroups.calls.count()).toBe(1);
expect((<Spy>clusterService.loadServerGroups).calls.count()).toBe(1);
expect((<Spy>securityGroupReader.getApplicationSecurityGroups).calls.count()).toBe(1);
expect(loadBalancerReader.loadLoadBalancers.calls.count()).toBe(1);
});

it ('only loads configured dataSources if attribute is non-empty', function () {
let dataSources = { enabled: ['serverGroups'], disabled: ['securityGroups', 'loadBalancers'] };
loadApplication(dataSources);
expect(clusterService.loadServerGroups.calls.count()).toBe(1);
expect((<Spy>clusterService.loadServerGroups).calls.count()).toBe(1);
expect((<Spy>securityGroupReader.getApplicationSecurityGroups).calls.count()).toBe(0);
expect(loadBalancerReader.loadLoadBalancers.calls.count()).toBe(0);

Expand Down
26 changes: 18 additions & 8 deletions app/scripts/modules/core/cluster/all.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h3>
<div class="form-group">
<button class="btn btn-xs btn-default" style="margin-left: 20px"
ng-class="{active: sortFilter.multiselect}"
ng-click="allClusters.toggleMultiselect()">
ng-click="ctrl.toggleMultiselect()">
<span class="glyphicon glyphicon-list visible-lg-inline"></span>
<span class="glyphicon glyphicon-list visible-md-inline visible-sm-inline" uib-tooltip="Edit multiple"></span>
<span class="visible-lg-inline">Edit multiple</span>
Expand All @@ -19,15 +19,15 @@ <h3>
<label>
<input type="checkbox"
ng-model="sortFilter.showAllInstances"
ng-change="allClusters.updateClusterGroups()"/>
ng-change="ctrl.updateClusterGroups()"/>
Instances
</label>
</div>
<div class="checkbox" is-visible="sortFilter.showAllInstances">
<label>
<input type="checkbox"
ng-model="sortFilter.listInstances"
ng-change="allClusters.updateClusterGroups()"/>
ng-change="ctrl.updateClusterGroups()"/>
with details
</label>
</div>
Expand All @@ -36,21 +36,31 @@ <h3>
</div>
<div class="col-lg-3 col-md-2 col-sm-2">
<div class="application-actions">
<button class="btn btn-sm btn-default" ng-click="allClusters.createServerGroup()">
<button class="btn btn-sm btn-default" ng-click="ctrl.createServerGroup()">
<span class="glyphicon glyphicon-plus-sign visible-lg-inline"></span>
<span class="glyphicon glyphicon-plus-sign visible-md-inline visible-sm-inline" uib-tooltip="Create Server Group"></span>
<span class="visible-lg-inline">{{allClusters.createLabel}}</span>
<span class="visible-lg-inline">{{ctrl.createLabel}}</span>
</button>
</div>
</div>
<filter-tags tags="tags" tag-cleared="allClusters.updateClusterGroups()" clear-filters="allClusters.clearFilters()"></filter-tags>
<filter-tags ng-if="!ctrl.dataSource.fetchOnDemand"
tags="tags"
tag-cleared="ctrl.updateClusterGroups()"
clear-filters="ctrl.clearFilters()"></filter-tags>
</div>

<div ng-if="ctrl.dataSource.fetchOnDemand">
<on-demand-cluster-picker application="ctrl.application"></on-demand-cluster-picker>
</div>

<div ng-if="ctrl.loadError">
<h4 class="text-center">There was an error loading the clusters for this application. We'll try again shortly.</h4>
</div>

<all-clusters-groupings class="content"
sticky-headers
groups="groups"
sort-filter="sortFilter"
app="allClusters.application"
initialized="allClusters.initialized"
app="ctrl.application"
initialized="ctrl.initialized"
></all-clusters-groupings>
22 changes: 18 additions & 4 deletions app/scripts/modules/core/cluster/allClusters.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {CLUSTER_FILTER_SERVICE} from 'core/cluster/filter/clusterFilter.service'
import {CLUSTER_POD_COMPONENT} from 'core/cluster/clusterPod.component';
import {SERVER_GROUP_COMMAND_BUILDER_SERVICE} from 'core/serverGroup/configure/common/serverGroupCommandBuilder.service';
import {CLUSTER_FILTER} from './filter/clusterFilter.component';
import {INSIGHT_NGMODULE} from 'core/insight/insight.module';

let angular = require('angular');

Expand All @@ -21,12 +22,13 @@ module.exports = angular.module('spinnaker.core.cluster.allClusters.controller',
SERVER_GROUP_COMMAND_BUILDER_SERVICE,
require('../filterModel/filter.tags.directive'),
require('../utils/waypoints/waypointContainer.directive'),
INSIGHT_NGMODULE.name,
require('angular-ui-bootstrap'),
CLOUD_PROVIDER_REGISTRY,
require('angular-ui-router'),
])
.controller('AllClustersCtrl', function($scope, app, $uibModal, $timeout, providerSelectionService, clusterFilterService, $state,
ClusterFilterModel, MultiselectModel, serverGroupCommandBuilder, cloudProviderRegistry) {
ClusterFilterModel, MultiselectModel, InsightFilterStateModel, serverGroupCommandBuilder, cloudProviderRegistry) {

if (app.serverGroups.disabled) {
$state.go('^.^' + app.dataSources.find(ds => ds.sref && !ds.disabled).sref, {}, {location: 'replace'});
Expand All @@ -36,12 +38,17 @@ module.exports = angular.module('spinnaker.core.cluster.allClusters.controller',
this.application = app;
ClusterFilterModel.activate();
this.initialized = false;
this.dataSource = app.getDataSource('serverGroups');
this.application = app;

$scope.sortFilter = ClusterFilterModel.sortFilter;

this.createLabel = 'Create Server Group';

let updateClusterGroups = () => {
if (app.getDataSource('serverGroups').fetchOnDemand) {
InsightFilterStateModel.filtersHidden = true;
}
ClusterFilterModel.applyParamsToUrl();
$scope.$evalAsync(() => {
clusterFilterService.updateClusterGroups(app);
Expand Down Expand Up @@ -84,15 +91,22 @@ module.exports = angular.module('spinnaker.core.cluster.allClusters.controller',

this.updateClusterGroups = _.debounce(updateClusterGroups, 200);

if (app.serverGroups.loaded) {
updateClusterGroups();
}
this.clustersLoadError = () => {
this.loadError = true;
this.initialized = true;
};

app.getDataSource('serverGroups').ready().then(
() => updateClusterGroups(),
() => this.clustersLoadError()
);

app.activeState = app.serverGroups;
app.serverGroups.onRefresh($scope, updateClusterGroups);
$scope.$on('$destroy', () => {
app.activeState = app;
MultiselectModel.clearAll();
InsightFilterStateModel.filtersHidden = false;
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
parent-heading="group.heading"
></cluster-pod>
</div>
<div ng-if="groups.length === 0">
<div ng-if="$ctrl.groups.length === 0 && !$ctrl.app.serverGroups.fetchOnDemand">
<h4 class="text-center">No server groups match the filters you've selected.</h4>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/modules/core/cluster/cluster.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import {CLUSTER_POD_COMPONENT} from 'core/cluster/clusterPod.component';
import {ALL_CLUSTERS_GROUPINGS_COMPONENT} from './allClustersGroupings.component';
import {ON_DEMAND_CLUSTER_PICKER_COMPONENT} from './onDemand/onDemandClusterPicker.component';

let angular = require('angular');

Expand All @@ -10,4 +11,5 @@ module.exports = angular
require('./allClusters.controller.js'),
ALL_CLUSTERS_GROUPINGS_COMPONENT,
CLUSTER_POD_COMPONENT,
ON_DEMAND_CLUSTER_PICKER_COMPONENT,
]);

0 comments on commit 6a26ade

Please sign in to comment.