Skip to content

Commit d5ce3be

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 8b2ea90 commit d5ce3be

File tree

9 files changed

+878
-18
lines changed

9 files changed

+878
-18
lines changed

app/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ <h1>JavaScript Required</h1>
255255
<script src="scripts/controllers/statefulSet.js"></script>
256256
<script src="scripts/controllers/services.js"></script>
257257
<script src="scripts/controllers/service.js"></script>
258+
<script src="scripts/controllers/provisionedServices.js"></script>
259+
<script src="scripts/controllers/provisionedService.js"></script>
258260
<script src="scripts/controllers/secrets.js"></script>
259261
<script src="scripts/controllers/secret.js"></script>
260262
<script src="scripts/controllers/createSecret.js"></script>

app/scripts/app.js

Lines changed: 10 additions & 0 deletions
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/provisioned', {
275+
templateUrl: 'views/provisioned.html',
276+
controller: 'ProvisionedServicesController',
277+
reloadOnSearch: false
278+
})
279+
.when('/project/:project/browse/provisioned/:service', {
280+
templateUrl: 'views/browse/provisioned-service.html',
281+
controller: 'ProvisionedServiceController',
282+
reloadOnSearch: false
283+
})
274284
.when('/project/:project/browse/storage', {
275285
templateUrl: 'views/storage.html',
276286
controller: 'StorageController',

app/scripts/constants.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,13 @@ angular.extend(window.OPENSHIFT_CONSTANTS, {
190190
prefixes: [
191191
"/browse/routes/"
192192
]
193+
},
194+
{
195+
label: "Provisioned Services",
196+
href: "/browse/provisioned",
197+
prefixes: [
198+
"/browse/provisioned/"
199+
]
193200
}
194201
]
195202
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
'use strict';
2+
3+
/**
4+
* @ngdoc function
5+
* @name openshiftConsole.controller:ProvisionedServiceController
6+
* @description
7+
* Controller of the openshiftConsole
8+
*/
9+
angular.module('openshiftConsole')
10+
.controller('ProvisionedServiceController', function ($scope,
11+
$routeParams,
12+
DataService,
13+
ProjectsService,
14+
$filter) {
15+
$scope.projectName = $routeParams.project;
16+
$scope.service = null;
17+
$scope.services = null;
18+
$scope.alerts = {};
19+
$scope.renderOptions = $scope.renderOptions || {};
20+
$scope.renderOptions.hideFilterWidget = true;
21+
$scope.breadcrumbs = [
22+
{
23+
title: "Services",
24+
link: "project/" + $routeParams.project + "/browse/services"
25+
},
26+
{
27+
title: $routeParams.service
28+
}
29+
];
30+
31+
$scope.podFailureReasons = {
32+
"Pending": "This pod will not receive traffic until all of its containers have been created."
33+
};
34+
35+
var allPods = {};
36+
var watches = [];
37+
38+
// receives routes for the current service and maps service ports to each route name
39+
var getPortsByRoute = function() {
40+
if(!$scope.service) {
41+
return;
42+
}
43+
44+
$scope.portsByRoute = {};
45+
46+
_.each($scope.service.spec.ports, function(port) {
47+
var reachedByRoute = false;
48+
if(port.nodePort) {
49+
$scope.showNodePorts = true;
50+
}
51+
52+
_.each($scope.routesForService, function(route) {
53+
if(!route.spec.port || route.spec.port.targetPort === port.name ||
54+
route.spec.port.targetPort === port.targetPort) {
55+
$scope.portsByRoute[route.metadata.name] = $scope.portsByRoute[route.metadata.name] || [];
56+
$scope.portsByRoute[route.metadata.name].push(port);
57+
reachedByRoute = true;
58+
}
59+
});
60+
61+
if(!reachedByRoute) {
62+
$scope.portsByRoute[''] = $scope.portsByRoute[''] || [];
63+
$scope.portsByRoute[''].push(port);
64+
}
65+
});
66+
};
67+
68+
// receive pods for the current service scope only when the service object is available
69+
var getPodsForService = function() {
70+
$scope.podsForService = {};
71+
if (!$scope.service) {
72+
return;
73+
}
74+
75+
var ls = new LabelSelector($scope.service.spec.selector);
76+
$scope.podsForService = ls.select(allPods);
77+
};
78+
var serviceResolved = function(service, action) {
79+
$scope.loaded = true;
80+
$scope.service = service;
81+
82+
getPodsForService();
83+
getPortsByRoute();
84+
85+
if (action === "DELETED") {
86+
$scope.alerts["deleted"] = {
87+
type: "warning",
88+
message: "This service has been deleted."
89+
};
90+
}
91+
};
92+
93+
ProjectsService
94+
.get($routeParams.project)
95+
.then(_.spread(function(project, context) {
96+
$scope.project = project;
97+
$scope.projectContext = context;
98+
DataService
99+
.get("services", $routeParams.service, context, { errorNotification: false })
100+
.then(function(service) {
101+
serviceResolved(service);
102+
watches.push(DataService.watchObject("services", $routeParams.service, context, serviceResolved));
103+
}, function(e) {
104+
$scope.loaded = true;
105+
$scope.alerts["load"] = {
106+
type: "error",
107+
message: "The service details could not be loaded.",
108+
details: $filter('getErrorDetails')(e)
109+
};
110+
}
111+
);
112+
113+
watches.push(DataService.watch("services", context, function(services) {
114+
$scope.services = services.by("metadata.name");
115+
}));
116+
117+
watches.push(DataService.watch("pods", context, function(pods) {
118+
allPods = pods.by("metadata.name");
119+
getPodsForService();
120+
}));
121+
122+
watches.push(DataService.watch("endpoints", context, function(endpoints) {
123+
$scope.podsWithEndpoints = {};
124+
var svcEndpoint = endpoints.by("metadata.name")[$routeParams.service];
125+
if (!svcEndpoint) {
126+
return;
127+
}
128+
129+
_.each(svcEndpoint.subsets, function(subset) {
130+
_.each(subset.addresses, function(address) {
131+
if (_.get(address, "targetRef.kind") === "Pod") {
132+
$scope.podsWithEndpoints[address.targetRef.name] = true;
133+
}
134+
});
135+
});
136+
}));
137+
138+
watches.push(DataService.watch("routes", context, function(routes) {
139+
$scope.routesForService = {};
140+
angular.forEach(routes.by("metadata.name"), function(route) {
141+
if (route.spec.to.kind === "Service" &&
142+
route.spec.to.name === $routeParams.service) {
143+
$scope.routesForService[route.metadata.name] = route;
144+
}
145+
});
146+
147+
getPortsByRoute();
148+
Logger.log("routes (subscribe)", $scope.routesByService);
149+
}));
150+
151+
$scope.$on('$destroy', function(){
152+
DataService.unwatchAll(watches);
153+
});
154+
155+
}));
156+
});
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
'use strict';
2+
3+
/**
4+
* @ngdoc function
5+
* @name openshiftConsole.controller:ProvisionedServicesController
6+
* @description
7+
* # ProjectController
8+
* Controller of the openshiftConsole
9+
*/
10+
angular.module('openshiftConsole')
11+
.controller('ProvisionedServicesController', function ($routeParams,
12+
$scope,
13+
APIService,
14+
BindingService,
15+
Constants,
16+
DataService,
17+
ProjectsService,
18+
ResourceAlertsService,
19+
$filter,
20+
LabelFilter) {
21+
//Logger) {
22+
23+
var overview = this;
24+
var limitWatches = $filter('isIE')() || $filter('isEdge')();
25+
var DEFAULT_POLL_INTERVAL = 60 * 1000; // milliseconds
26+
27+
// Enable service catalog features if the new experience is enabled and the
28+
// servicecatalog.k8s.io resources are available.
29+
var SERVICE_CATALOG_ENABLED =
30+
_.get(Constants, 'ENABLE_TECH_PREVIEW_FEATURE.service_catalog_landing_page') &&
31+
APIService.apiInfo({ group: 'servicecatalog.k8s.io', resource: 'serviceclasses' }) &&
32+
APIService.apiInfo({ group: 'servicecatalog.k8s.io', resource: 'instances' }) &&
33+
APIService.apiInfo({ group: 'servicecatalog.k8s.io', resource: 'bindings' });
34+
35+
$scope.projectName = $routeParams.project;
36+
$scope.services = {};
37+
$scope.unfilteredServices = {};
38+
$scope.routesByService = {};
39+
$scope.routes = {};
40+
$scope.labelSuggestions = {};
41+
$scope.alerts = $scope.alerts || {};
42+
$scope.emptyMessage = "Loading...";
43+
$scope.emptyMessageRoutes = "Loading...";
44+
45+
var state = overview.state = {
46+
notificationsByObjectUID: {},
47+
serviceInstances: {}
48+
};
49+
50+
var getUID = function(apiObject) {
51+
return _.get(apiObject, 'metadata.uid');
52+
};
53+
54+
var setNotifications = function(apiObject, notifications) {
55+
var uid = getUID(apiObject);
56+
state.notificationsByObjectUID[uid] = notifications || {};
57+
};
58+
// TODO: code duplicated from directives/bindService.js
59+
// extract & share
60+
var sortServiceInstances = function() {
61+
if(!state.serviceInstances && !state.serviceClasses) {
62+
state.bindableServiceInstances = null;
63+
return;
64+
}
65+
66+
state.bindableServiceInstances = _.filter(state.serviceInstances, function(serviceInstance) {
67+
return BindingService.isServiceBindable(serviceInstance, state.serviceClasses);
68+
});
69+
70+
//
71+
//state.orderedServiceInstances = _.sortBy(state.serviceInstances,
72+
$scope.services = _.sortBy(state.serviceInstances,
73+
function(item) {
74+
return _.get(state.serviceClasses, [item.spec.serviceClassName, 'externalMetadata', 'displayName']) || item.spec.serviceClassName;
75+
},
76+
function(item) {
77+
return _.get(item, 'metadata.name', '');
78+
}
79+
);
80+
};
81+
82+
// Update the label filter suggestions for a list of objects. This should
83+
// only be called for filterable top-level items to avoid polluting the list.
84+
/*var updateLabelSuggestions = function(objects) {
85+
if (_.isEmpty(objects)) {
86+
return;
87+
}
88+
89+
LabelFilter.addLabelSuggestionsFromResources(objects, labelSuggestions);
90+
if (overview.viewBy !== 'pipeline') {
91+
LabelFilter.setLabelSuggestions(labelSuggestions);
92+
}
93+
};*/
94+
95+
96+
var watches = [];
97+
98+
ProjectsService
99+
.get($routeParams.project)
100+
.then(_.spread(function(project, context) {
101+
$scope.project = project;
102+
103+
/*watches.push(DataService.watch("services", context, function(services) {
104+
$scope.unfilteredServices = services.by("metadata.name");
105+
LabelFilter.addLabelSuggestionsFromResources($scope.unfilteredServices, $scope.labelSuggestions);
106+
LabelFilter.setLabelSuggestions($scope.labelSuggestions);
107+
$scope.services = LabelFilter.getLabelSelector().select($scope.unfilteredServices);
108+
$scope.emptyMessage = "No services to show";
109+
updateFilterWarning();
110+
111+
Logger.log("services (subscribe)", $scope.unfilteredServices);
112+
}));*/
113+
114+
var canI = $filter('canI');
115+
116+
$scope.emptyMessage = "No provisioned services to show";
117+
118+
if (SERVICE_CATALOG_ENABLED && canI({resource: 'instances', group: 'servicecatalog.k8s.io'}, 'watch')) {
119+
watches.push(DataService.watch({
120+
group: 'servicecatalog.k8s.io',
121+
resource: 'instances'
122+
}, context, function(serviceInstances) {
123+
state.serviceInstances = serviceInstances.by('metadata.name');
124+
_.each(state.serviceInstances, function(instance) {
125+
var notifications = ResourceAlertsService.getServiceInstanceAlerts(instance);
126+
setNotifications(instance, notifications);
127+
});
128+
sortServiceInstances();
129+
//updateLabelSuggestions(state.serviceInstances);
130+
//updateFilter();
131+
//$scope.emptyMessage = "No provisioned services to show";
132+
updateFilterWarning();
133+
134+
//Logger.log("provisioned services (subscribe)", $scope.unfilteredServices);
135+
136+
}, {poll: limitWatches, pollInterval: DEFAULT_POLL_INTERVAL}));
137+
}
138+
139+
function updateFilterWarning() {
140+
if (!LabelFilter.getLabelSelector().isEmpty() && $.isEmptyObject($scope.services) && !$.isEmptyObject($scope.unfilteredServices)) {
141+
$scope.alerts["provisioned-services"] = {
142+
type: "warning",
143+
details: "The active filters are hiding all services."
144+
};
145+
}
146+
else {
147+
delete $scope.alerts["provisioned-services"];
148+
}
149+
}
150+
151+
LabelFilter.onActiveFiltersChanged(function(labelSelector) {
152+
// trigger a digest loop
153+
$scope.$apply(function() {
154+
$scope.services = labelSelector.select($scope.unfilteredServices);
155+
updateFilterWarning();
156+
});
157+
});
158+
159+
$scope.$on('$destroy', function(){
160+
DataService.unwatchAll(watches);
161+
});
162+
163+
}));
164+
});

0 commit comments

Comments
 (0)