Skip to content

Commit 36b4f2f

Browse files
committed
Updates for Service Instance & Bindings
Updates for service instances. Prep to allow updates to chosen parameters for instance and bindings.
1 parent c9a5d1a commit 36b4f2f

19 files changed

+1118
-231
lines changed

app/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ <h1>JavaScript Required</h1>
232232
<script src="scripts/services/resourceAlerts.js"></script>
233233
<script src="scripts/services/listRowUtils.js"></script>
234234
<script src="scripts/services/ownerReferences.js"></script>
235+
<script src="scripts/services/serviceInstances.js"></script>
235236
<script src="scripts/controllers/landingPage.js"></script>
236237
<script src="scripts/controllers/projects.js"></script>
237238
<script src="scripts/controllers/pods.js"></script>
@@ -255,6 +256,8 @@ <h1>JavaScript Required</h1>
255256
<script src="scripts/controllers/statefulSet.js"></script>
256257
<script src="scripts/controllers/services.js"></script>
257258
<script src="scripts/controllers/service.js"></script>
259+
<script src="scripts/controllers/serviceInstances.js"></script>
260+
<script src="scripts/controllers/serviceInstance.js"></script>
258261
<script src="scripts/controllers/secrets.js"></script>
259262
<script src="scripts/controllers/secret.js"></script>
260263
<script src="scripts/controllers/createSecret.js"></script>

app/scripts/app.js

+10
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@ angular
271271
controller: 'ServiceController',
272272
reloadOnSearch: false
273273
})
274+
.when('/project/:project/browse/service-instances', {
275+
templateUrl: 'views/service-instances.html',
276+
controller: 'ServiceInstancesController',
277+
reloadOnSearch: false
278+
})
279+
.when('/project/:project/browse/service-instances/:instance', {
280+
templateUrl: 'views/browse/service-instance.html',
281+
controller: 'ServiceInstanceController',
282+
reloadOnSearch: false
283+
})
274284
.when('/project/:project/browse/storage', {
275285
templateUrl: 'views/storage.html',
276286
controller: 'StorageController',

app/scripts/constants.js

+17
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,23 @@ angular.extend(window.OPENSHIFT_CONSTANTS, {
190190
prefixes: [
191191
"/browse/routes/"
192192
]
193+
},
194+
{
195+
label: "Provisioned Services",
196+
href: "/browse/service-instances",
197+
prefixes: [
198+
"/browse/service-instances/"
199+
],
200+
isValid: function(){
201+
return _.get(window.OPENSHIFT_CONSTANTS, 'ENABLE_TECH_PREVIEW_FEATURE.service_catalog_landing_page');
202+
},
203+
canI: {
204+
resource: {
205+
group: 'servicecatalog.k8s.io',
206+
resource: 'instances'
207+
},
208+
verb: 'list'
209+
}
193210
}
194211
]
195212
}
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
'use strict';
2+
3+
angular.module('openshiftConsole')
4+
.controller('ServiceInstanceController', function ($scope,
5+
$filter,
6+
$routeParams,
7+
DataService,
8+
ProjectsService) {
9+
$scope.alerts = {};
10+
//$scope.displayName = null;
11+
$scope.projectName = $routeParams.project;
12+
$scope.serviceInstance = null;
13+
$scope.serviceClass = null;
14+
$scope.serviceClasses = {};
15+
16+
$scope.breadcrumbs = [
17+
{
18+
title: "Provisioned Services",
19+
link: "project/" + $routeParams.project + "/browse/service-instances"
20+
}
21+
];
22+
23+
var watches = [];
24+
25+
/*var setDisplayName = function() {
26+
if(!$scope.serviceInstance || !$scope.serviceClasses) {
27+
return;
28+
}
29+
30+
$scope.displayName = $filter('serviceInstanceDisplayName')($scope.serviceInstance, $scope.serviceClasses);
31+
};*/
32+
33+
var updateBreadCrumbs = function() {
34+
$scope.breadcrumbs.push({
35+
title: $filter('serviceInstanceDisplayName')($scope.serviceInstance, $scope.serviceClasses)
36+
});
37+
};
38+
39+
var updateServiceClassMetadata = function() {
40+
if(!$scope.serviceInstance || !$scope.serviceClasses) {
41+
return;
42+
}
43+
44+
updateBreadCrumbs();
45+
46+
var serviceClassName = _.get($scope.serviceInstance.spec, 'serviceClassName');
47+
$scope.serviceClass = _.get($scope.serviceClasses, [serviceClassName]);
48+
$scope.plan = _.find(_.get($scope.serviceClass, 'plans'), {name: $scope.serviceInstance.spec.planName });
49+
};
50+
51+
var serviceResolved = function(service, action) {
52+
$scope.loaded = true;
53+
$scope.serviceInstance = service;
54+
55+
if (action === "DELETED") {
56+
$scope.alerts["deleted"] = {
57+
type: "warning",
58+
message: "This provisioned service has been deleted."
59+
};
60+
}
61+
62+
//setDisplayName();
63+
updateServiceClassMetadata();
64+
};
65+
66+
ProjectsService
67+
.get($routeParams.project)
68+
.then(_.spread(function(project, context) {
69+
$scope.project = project;
70+
$scope.projectContext = context;
71+
72+
DataService
73+
.get({
74+
group: 'servicecatalog.k8s.io',
75+
resource: 'instances'
76+
}, $routeParams.instance, context, { errorNotification: false })
77+
.then(function(service) {
78+
79+
serviceResolved(service);
80+
81+
/*watches.push(DataService.watchObject({
82+
group: 'servicecatalog.k8s.io',
83+
resource: 'instances'
84+
}, $routeParams.instance, context, serviceResolved));*/
85+
/*watches.push(DataService.watch({
86+
group: 'servicecatalog.k8s.io',
87+
resource: 'bindings'
88+
}, context, function(bindings) {
89+
$scope.bindings = _.filter(bindings.by('metadata.name'), { spec: { instanceRef: { name: instance.metadata.name } } });
90+
}));*/
91+
92+
}, function(error) {
93+
$scope.loaded = true;
94+
$scope.alerts["load"] = {
95+
type: "error",
96+
message: "The service details could not be loaded.",
97+
details: $filter('getErrorDetails')(error)
98+
};
99+
});
100+
101+
DataService.list({
102+
group: 'servicecatalog.k8s.io',
103+
resource: 'serviceclasses'
104+
}, context, function(serviceClasses) {
105+
$scope.serviceClasses = serviceClasses.by('metadata.name');
106+
//setDisplayName();
107+
updateServiceClassMetadata();
108+
});
109+
110+
$scope.$on('$destroy', function(){
111+
DataService.unwatchAll(watches);
112+
});
113+
114+
}));
115+
});
+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
'use strict';
2+
3+
angular.module('openshiftConsole')
4+
.controller('ServiceInstancesController', function ($scope,
5+
$filter,
6+
$routeParams,
7+
APIService,
8+
BindingService,
9+
Constants,
10+
DataService,
11+
LabelFilter,
12+
Logger,
13+
ProjectsService) {
14+
$scope.alerts = {};
15+
$scope.applicationsByBinding = {};
16+
$scope.bindings = {};
17+
$scope.bindableServiceInstances = {};
18+
//$scope.bindingsByApplicationUID = {};
19+
$scope.bindingsByInstanceRef = {};
20+
$scope.emptyMessage = "Loading...";
21+
$scope.labelSuggestions = {};
22+
$scope.projectName = $routeParams.project;
23+
$scope.serviceClasses = {};
24+
$scope.serviceInstances = {};
25+
$scope.unfilteredServiceInstances = {};
26+
27+
var watches = [];
28+
29+
var updateFilter = function() {
30+
$scope.serviceInstances = LabelFilter.getLabelSelector().select($scope.unfilteredServiceInstances);
31+
};
32+
33+
var sortServiceInstances = function() {
34+
$scope.bindableServiceInstances = BindingService.filterBindableServiceInstances($scope.unfilteredServiceInstances, $scope.serviceClasses);
35+
$scope.unfilteredServiceInstances = BindingService.sortServiceInstances($scope.unfilteredServiceInstances, $scope.serviceClasses);
36+
};
37+
38+
var groupBindings = function() {
39+
// Build two maps:
40+
// - Bindings by the UID of the target object
41+
// - API objects by binding name
42+
/*
43+
state.bindingsByApplicationUID = {};
44+
state.applicationsByBinding = {};
45+
//state.deleteableBindingsByApplicationUID = {};
46+
47+
// If there are no bindings, nothing to do.
48+
if (_.isEmpty(state.bindings)) {
49+
return;
50+
}
51+
52+
// All objects that can be a target for bindings.
53+
var objectsByKind = [
54+
overview.deployments,
55+
overview.deploymentConfigs,
56+
overview.vanillaReplicationControllers,
57+
overview.vanillaReplicaSets,
58+
overview.statefulSets
59+
];
60+
61+
// Make sure all the binding targets have loaded first.
62+
if (_.some(objectsByKind, function(collection) { return !collection; })) {
63+
return;
64+
}
65+
66+
// Build a map of pod preset selectors by binding name.
67+
var podPresetSelectors = {};
68+
_.each(state.bindings, function(binding) {
69+
var podPresetSelector = _.get(binding, 'spec.alphaPodPresetTemplate.selector');
70+
if (podPresetSelector) {
71+
podPresetSelectors[binding.metadata.name] = new LabelSelector(podPresetSelector);
72+
}
73+
});
74+
75+
_.each(objectsByKind, function(collection) {
76+
_.each(collection, function(apiObject) {
77+
// Key by UID since name is not unique across different kinds.
78+
var applicationUID = getUID(apiObject);
79+
80+
// Create a selector for the potential binding target to check if the
81+
// pod preset covers the selector.
82+
var applicationSelector = new LabelSelector(_.get(apiObject, 'spec.selector'));
83+
state.bindingsByApplicationUID[applicationUID] = [];
84+
state.deleteableBindingsByApplicationUID[applicationUID] = [];
85+
86+
// Look at each pod preset selector to see if it covers this API object selector.
87+
_.each(podPresetSelectors, function(podPresetSelector, bindingName) {
88+
if (podPresetSelector.covers(applicationSelector)) {
89+
// Keep a map of the target UID to the binding and the binding to
90+
// the target. We want to show bindings both in the "application"
91+
// object rows and the service instance rows.
92+
state.bindingsByApplicationUID[applicationUID].push(state.bindings[bindingName]);
93+
if (!_.get(state.bindings[bindingName], 'metadata.deletionTimestamp')) {
94+
state.deleteableBindingsByApplicationUID[applicationUID].push(state.bindings[bindingName]);
95+
}
96+
state.applicationsByBinding[bindingName] = state.applicationsByBinding[bindingName] || [];
97+
state.applicationsByBinding[bindingName].push(apiObject);
98+
}
99+
});
100+
});
101+
});
102+
103+
$scope.bindingsByInstanceRef = _.reduce(state.bindingsByInstanceRef, function(result, bindingList, key) {
104+
result[key] = _.sortBy(bindingList, function(binding) {
105+
var apps = _.get(state.applicationsByBinding, [binding.metadata.name]);
106+
var firstName = _.get(_.head(apps), ['metadata', 'name']);
107+
return firstName || binding.metadata.name;
108+
});
109+
return result;
110+
}, {});*/
111+
};
112+
113+
ProjectsService
114+
.get($routeParams.project)
115+
.then(_.spread(function(project, context) {
116+
$scope.project = project;
117+
$scope.projectContext = context;
118+
119+
watches.push(DataService.watch({
120+
group: 'servicecatalog.k8s.io',
121+
resource: 'bindings'
122+
}, context, function(bindings) {
123+
$scope.bindings = bindings.by('metadata.name');
124+
$scope.bindingsByInstanceRef = _.groupBy($scope.bindings, 'spec.instanceRef.name');
125+
groupBindings();
126+
//refreshSecrets(context);
127+
}));
128+
129+
watches.push(DataService.watch({
130+
group: 'servicecatalog.k8s.io',
131+
resource: 'instances'
132+
}, context, function(serviceInstances) {
133+
$scope.emptyMessage = "No provisioned services to show";
134+
$scope.unfilteredServiceInstances = serviceInstances.by('metadata.name');
135+
136+
//_.each($scope.unfilteredServiceInstances, function (instance) {
137+
// var notifications = ResourceAlertsService.getServiceInstanceAlerts(instance);
138+
// setNotifications(instance, notifications);
139+
//});
140+
141+
sortServiceInstances();
142+
updateFilter();
143+
updateFilterWarning();
144+
145+
LabelFilter.addLabelSuggestionsFromResources($scope.unfilteredServiceInstances, $scope.labelSuggestions);
146+
LabelFilter.setLabelSuggestions($scope.labelSuggestions);
147+
148+
Logger.log("provisioned services (subscribe)", $scope.unfilteredServiceInstances);
149+
}));
150+
151+
DataService.list({
152+
group: 'servicecatalog.k8s.io',
153+
resource: 'serviceclasses'
154+
}, context, function(serviceClasses) {
155+
$scope.serviceClasses = serviceClasses.by('metadata.name');
156+
sortServiceInstances();
157+
updateFilter();
158+
});
159+
160+
function updateFilterWarning() {
161+
if (!LabelFilter.getLabelSelector().isEmpty() && _.isEmpty($scope.serviceInstances) && !_.isEmpty($scope.unfilteredServiceInstances)) {
162+
$scope.alerts["all-instances-filtered"] = {
163+
type: "warning",
164+
details: "The active filters are hiding all provisioned services."
165+
};
166+
}
167+
else {
168+
delete $scope.alerts["all-instances-filtered"];
169+
}
170+
}
171+
172+
LabelFilter.onActiveFiltersChanged(function(labelSelector) {
173+
// trigger a digest loop
174+
$scope.$evalAsync(function() {
175+
$scope.serviceInstances = labelSelector.select($scope.unfilteredServiceInstances);
176+
updateFilterWarning();
177+
});
178+
});
179+
180+
$scope.$on('$destroy', function(){
181+
DataService.unwatchAll(watches);
182+
});
183+
184+
}));
185+
});

app/scripts/directives/overview/serviceBinding.js

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
bindings: {
1010
namespace: '<',
1111
binding: '<',
12+
refApiObject: '<?',
1213
serviceClasses: '<',
1314
serviceInstances: '<'
1415
},

0 commit comments

Comments
 (0)