Skip to content

Commit

Permalink
Check services for bindability before creating bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
jeff-phillips-18 committed Jun 8, 2017
1 parent ad1da6b commit c79065a
Show file tree
Hide file tree
Showing 10 changed files with 451 additions and 453 deletions.
25 changes: 14 additions & 11 deletions app/scripts/controllers/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ angular.module('openshiftConsole').controller('OverviewController', [
'OwnerReferencesService',
'PodsService',
'ProjectsService',
'BindingService',
'ResourceAlertsService',
'RoutesService',
OverviewController
Expand Down Expand Up @@ -50,6 +51,7 @@ function OverviewController($scope,
OwnerReferencesService,
PodsService,
ProjectsService,
BindingService,
ResourceAlertsService,
RoutesService) {
var overview = this;
Expand Down Expand Up @@ -1132,21 +1134,22 @@ function OverviewController($scope,
// extract & share
var sortServiceInstances = function() {
if(!state.serviceInstances && !state.serviceClasses) {
state.bindableServiceInstances = null;
return;
}
state.orderedServiceInstances = _.toArray(state.serviceInstances).sort(function(left, right) {
var leftName = _.get(state.serviceClasses, [left.spec.serviceClassName, 'osbMetadata', 'displayName']) || left.spec.serviceClassName;
var rightName = _.get(state.serviceClasses, [left.spec.serviceClassName, 'osbMetadata', 'displayName']) || right.spec.serviceClassName;

// Fall back to sorting by `metadata.name` if the display names are the
// same so that the sort is stable.
if (leftName === rightName) {
leftName = _.get(left, 'metadata.name', '');
rightName = _.get(right, 'metadata.name', '');
}

return leftName.localeCompare(rightName);
state.bindableServiceInstances = _.filter(state.serviceInstances, function(serviceInstance) {
return BindingService.isServiceBindable(serviceInstance, state.serviceClasses);
});

state.orderedServiceInstances = _.sortByAll(state.serviceInstances,
function(item) {
return _.get(state.serviceClasses, [item.spec.serviceClassName, 'osbMetadata', 'displayName']) || item.spec.serviceClassName;
},
function(item) {
return _.get(item, 'metadata.name', '');
}
);
};

var watches = [];
Expand Down
133 changes: 70 additions & 63 deletions app/scripts/directives/bindService.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

(function() {
(function() {
angular.module('openshiftConsole').component('bindService', {
controller: [
'$scope',
Expand Down Expand Up @@ -44,21 +44,14 @@
var sortServiceInstances = function() {
// wait till both service instances and service classes are available so that the sort is stable and items dont jump around
if (ctrl.serviceClasses && ctrl.serviceInstances) {
var instances = _.toArray(ctrl.serviceInstances);
instances.sort(function(left, right) {
var leftName = _.get(ctrl.serviceClasses, [left.spec.serviceClassName, 'osbMetadata', 'displayName']) || left.spec.serviceClassName;
var rightName = _.get(ctrl.serviceClasses, [left.spec.serviceClassName, 'osbMetadata', 'displayName']) || right.spec.serviceClassName;

// Fall back to sorting by `metadata.name` if the display names are the
// same so that the sort is stable.
if (leftName === rightName) {
leftName = _.get(left, 'metadata.name', '');
rightName = _.get(right, 'metadata.name', '');
ctrl.orderedServiceInstances = _.sortByAll(ctrl.serviceInstances,
function(item) {
return _.get(ctrl.serviceClasses, [item.spec.serviceClassName, 'osbMetadata', 'displayName']) || item.spec.serviceClassName;
},
function(item) {
return _.get(item, 'metadata.name', '');
}

return leftName.localeCompare(rightName);
});
ctrl.orderedServiceInstances = instances;
);
}
};

Expand All @@ -72,6 +65,7 @@
.concat(replicaSets)
.concat(statefulSets);
ctrl.applications = _.sortByAll(apiObjects, ['metadata.name', 'kind']);
ctrl.bindType = ctrl.applications.length ? "application" : "secret-only";
}
};

Expand All @@ -94,6 +88,61 @@
ctrl.bindService();
};


var loadApplications = function() {
var context = {
namespace: _.get(ctrl.target, 'metadata.namespace')
};

// Load all the "application" types
DataService.list('deploymentconfigs', context).then(function(deploymentConfigData) {
deploymentConfigs = _.toArray(deploymentConfigData.by('metadata.name'));
sortApplications();
});
DataService.list('replicationcontrollers', context).then(function(replicationControllerData) {
replicationControllers = _.reject(replicationControllerData.by('metadata.name'), $filter('hasDeploymentConfig'));
sortApplications();
});
DataService.list({
group: 'extensions',
resource: 'deployments'
}, context).then(function(deploymentData) {
deployments = _.toArray(deploymentData.by('metadata.name'));
sortApplications();
});
DataService.list({
group: 'extensions',
resource: 'replicasets'
}, context).then(function(replicaSetData) {
replicaSets = _.reject(replicaSetData.by('metadata.name'), $filter('hasDeployment'));
sortApplications();
});
DataService.list({
group: 'apps',
resource: 'statefulsets'
}, context).then(function(statefulSetData) {
statefulSets = _.toArray(statefulSetData.by('metadata.name'));
sortApplications();
});
};

var loadServiceInstances = function() {
var context = {
namespace: _.get(ctrl.target, 'metadata.namespace')
};

DataService.list({
group: 'servicecatalog.k8s.io',
resource: 'instances'
}, context).then(function(instances) {
ctrl.serviceInstances = instances.by('metadata.name');
if (!ctrl.serviceToBind) {
preselectService();
}
sortServiceInstances();
});
};

ctrl.$onInit = function() {
ctrl.serviceSelection = {};
var formStepLabel = (ctrl.target.kind === 'Instance') ? 'Applications' : 'Services';
Expand All @@ -115,9 +164,6 @@
}
];

var context = {
namespace: _.get(ctrl.target, 'metadata.namespace')
};
// We will want ServiceClasses either way for display purposes
DataService.list({
group: 'servicecatalog.k8s.io',
Expand All @@ -131,56 +177,17 @@
sortServiceInstances();
});

// TODO is it ever realistically possible for target to not be defined at this point
if (ctrl.target.kind === 'Instance') {
ctrl.shouldBindToApp = "true";
ctrl.bindType = "secret-only";
ctrl.appToBind = null;
ctrl.serviceToBind = ctrl.target.metadata.name;
// Load all the "application" types
DataService.list('deploymentconfigs', context).then(function(deploymentConfigData) {
deploymentConfigs = _.toArray(deploymentConfigData.by('metadata.name'));
sortApplications();
});
DataService.list('replicationcontrollers', context).then(function(replicationControllerData) {
replicationControllers = _.reject(replicationControllerData.by('metadata.name'), $filter('hasDeploymentConfig'));
sortApplications();
});
DataService.list({
group: 'extensions',
resource: 'deployments'
}, context).then(function(deploymentData) {
deployments = _.toArray(deploymentData.by('metadata.name'));
sortApplications();
});
DataService.list({
group: 'extensions',
resource: 'replicasets'
}, context).then(function(replicaSetData) {
replicaSets = _.reject(replicaSetData.by('metadata.name'), $filter('hasDeployment'));
sortApplications();
});
DataService.list({
group: 'apps',
resource: 'statefulsets'
}, context).then(function(statefulSetData) {
statefulSets = _.toArray(statefulSetData.by('metadata.name'));
sortApplications();
});
loadApplications();
}
else {
DataService.list({
group: 'servicecatalog.k8s.io',
resource: 'instances'
}, context).then(function(instances) {
ctrl.serviceInstances = instances.by('metadata.name');
if (!ctrl.serviceToBind) {
preselectService();
}
sortServiceInstances();
});
ctrl.bindType = 'application';
ctrl.appToBind = ctrl.target;
loadServiceInstances();
}
// TODO: handle not having any service instances when binding app to service
};

ctrl.$onDestroy = function() {
Expand All @@ -195,13 +202,13 @@

ctrl.bindService = function() {
var svcToBind = ctrl.target.kind === 'Instance' ? ctrl.target : ctrl.serviceInstances[ctrl.serviceToBind];
var appToBind = ctrl.target.kind !== 'Instance' ? ctrl.target : ctrl.appToBind;
var application = ctrl.bindType === 'application' ? _.get(ctrl.appToBind, 'metadata.name') : undefined;

var context = {
namespace: _.get(svcToBind, 'metadata.namespace')
};

BindingService.bindService(context, _.get(svcToBind, 'metadata.name'), _.get(appToBind, 'metadata.name')).then(function(binding){
BindingService.bindService(context, _.get(svcToBind, 'metadata.name'), application).then(function(binding){
ctrl.binding = binding;
ctrl.error = null;

Expand Down
6 changes: 5 additions & 1 deletion app/scripts/directives/overview/serviceInstanceRow.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
'use strict';

(function() {
(function() {
angular.module('openshiftConsole').component('serviceInstanceRow', {
controller: [
'$filter',
'$uibModal',
'DataService',
'BindingService',
'ListRowUtils',
'NotificationsService',
ServiceInstanceRow
Expand All @@ -22,6 +23,7 @@
function ServiceInstanceRow($filter,
$uibModal,
DataService,
BindingService,
ListRowUtils,
NotificationsService) {
var row = this;
Expand Down Expand Up @@ -51,6 +53,8 @@
return binding && _.get(row, ['state', 'secrets', binding.spec.secretName]);
};

row.isBindable = BindingService.isServiceBindable(row.apiObject, row.state.serviceClasses);

row.closeOverlayPanel = function() {
_.set(row, 'overlay.panelVisible', false);
};
Expand Down
13 changes: 0 additions & 13 deletions app/scripts/filters/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -1310,17 +1310,4 @@ angular.module('openshiftConsole')
var alternateBackends = _.get(route, 'spec.alternateBackends', []);
return !_.isEmpty(alternateBackends);
};
})
// TODO: these two filters are defined in origin-web-catalog but are not available, need to figure out why or move to common
.filter('applicationHasDeployment', function ($filter) {
var annotation = $filter('annotation');
return function (replicaSet) {
return annotation(replicaSet, 'deployment.kubernetes.io/revision');
};
})
.filter('applicationHasDeploymentConfig', function($filter) {
var annotationFilter = $filter('annotation');
return function (deployment) {
return annotationFilter(deployment, 'deploymentConfig');
};
});
5 changes: 2 additions & 3 deletions app/views/directives/bind-service/bind-service-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
service-class-name="ctrl.serviceClassName"
form-name="ctrl.selectionForm"
applications="ctrl.applications"
app-to-bind="ctrl.appToBind"
should-bind-to-app="ctrl.shouldBindToApp"
group-by-kind="ctrl.groupByKind">
bind-type="ctrl.bindType"
app-to-bind="ctrl.appToBind">
</bind-service-form>
</div>
1 change: 1 addition & 0 deletions app/views/directives/bind-service/results.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<bind-results error="ctrl.error"
binding="ctrl.binding"
service-to-bind="ctrl.serviceToBind"
bind-type="{{ctrl.bindType}}"
application-to-bind="ctrl.appToBind.metadata.name"
generated-secret-name="ctrl.generatedSecretName"
show-pod-presets="'pod_presets' | enableTechPreviewFeature"
Expand Down
2 changes: 1 addition & 1 deletion app/views/overview/_list-row-actions.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
</li>
<!-- FIXME: Can't enable canI checks on svc cat resources until we have aggregation
<li ng-if="(row.state.serviceInstances | hashSize) > 0 && {resource: 'bindings', group: 'servicecatalog.k8s.io'} | canI : 'create'" role="menuitem"> -->
<li ng-if="('pod_presets' | enableTechPreviewFeature) && (row.state.serviceInstances | hashSize) > 0" role="menuitem">
<li ng-if="('pod_presets' | enableTechPreviewFeature) && row.state.bindableServiceInstances.length" role="menuitem">
<a href="" ng-click="row.showOverlayPanel('bindService', {target: row.apiObject})">Create Binding</a>
</li>
<li ng-if="row.current && ('deploymentconfigs/log' | canI : 'get')" role="menuitem">
Expand Down
8 changes: 4 additions & 4 deletions app/views/overview/_service-instance-row.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ <h3>
<div class="list-pf-details">
<div ng-if="!row.expanded">
<div class="hidden-xs hidden-sm">
<span ng-if="!row.bindings.length">
<span ng-if="!row.bindings.length && row.isBindable">
<a href="" ng-click="row.showOverlayPanel('bindService', {target: row.apiObject})">Create Binding</a>
</span>
<span ng-if="row.bindings.length" class="component-label">Bindings</span>
Expand Down Expand Up @@ -44,7 +44,7 @@ <h3>
uib-dropdown-toggle
class="actions-dropdown-kebab"><i class="fa fa-ellipsis-v"></i><span class="sr-only">Actions</span></a>
<ul class="dropdown-menu dropdown-menu-right" uib-dropdown-menu role="menu">
<li role="menuitem">
<li role="menuitem" ng-if="row.isBindable">
<a href="" ng-click="row.showOverlayPanel('bindService', {target: row.apiObject})">Create Binding</a>
</li>
<li role="menuitem">
Expand Down Expand Up @@ -84,7 +84,7 @@ <h3>
<p class="pre-wrap" ng-bind-html="row.description | linky"></p>
</div>
</div>
<div class="section-title">
<div class="section-title" ng-if="row.isBindable || row.bindings">
Bindings
</div>
<div
Expand All @@ -108,7 +108,7 @@ <h3>
</a>
</div>
</div>
<div class="row">
<div class="row" ng-if="row.isBindable">
<div class="col-sm-12">
<a href="" ng-click="row.showOverlayPanel('bindService', {target: row.apiObject})">Create Binding</a>
</div>
Expand Down
Loading

0 comments on commit c79065a

Please sign in to comment.