blob: 87db71106c261d05c14831e055371ae0dfadf8e9 [file] [log] [blame]
Matteo Scandolo8a64fa42016-01-21 11:21:03 -08001(function () {
2 'use strict';
3
4 angular.module('xos.serviceTopology')
5 .service('Services', function($resource){
Matteo Scandolof16b3792016-01-21 14:23:28 -08006 return $resource('/xos/services/:id', {id: '@id'});
7 })
8 .service('Tenant', function($resource){
9 return $resource('/xos/tenants');
10 })
Matteo Scandolo06f45d62016-01-21 15:38:06 -080011 .service('Slice', function($resource){
12 return $resource('/xos/slices', {id: '@id'});
13 })
14 .service('Instances', function($resource){
Matteo Scandolo170d3be2016-02-11 08:58:04 -080015 return $resource('/xos/instances', {id: '@id'}, {});
16 })
17 .service('Node', function($resource, $q, Instances){
18 return $resource('/xos/nodes', {id: '@id'}, {
19 queryWithInstances: {
20 method: 'GET',
21 isArray: true,
22 interceptor: {
23 response: function(res){
24
25 // TODO update the API to include instances in nodes
26 // http://stackoverflow.com/questions/14573102/how-do-i-include-related-model-fields-using-django-rest-framework
27
28 const deferred = $q.defer();
29
30 let requests = [];
31
32 angular.forEach(res.data, (node) => {
33 requests.push(Instances.query({node: node.id}).$promise);
34 })
35
36 $q.all(requests)
37 .then((list) => {
38 res.data.map((node, i) => {
39 node.instances = list[i];
40 return node;
41 });
42
43 deferred.resolve(res.data);
44 })
45
46 return deferred.promise;
47 }
48 }
49 }
50 });
Matteo Scandolo06f45d62016-01-21 15:38:06 -080051 })
Matteo Scandolo7547f042016-02-09 09:13:30 -080052 .service('Subscribers', function($resource, $q, SubscriberDevice){
53 return $resource('/xos/subscribers', {id: '@id'}, {
54 queryWithDevices: {
55 method: 'GET',
56 isArray: true,
57 interceptor: {
58 response: function(res){
Matteo Scandolo219b1a72016-02-09 11:19:22 -080059
60 /**
61 * For each subscriber retrieve devices and append them
62 */
63
Matteo Scandolo7547f042016-02-09 09:13:30 -080064 const deferred = $q.defer();
65
66 let requests = [];
67
68 angular.forEach(res.data, (subscriber) => {
Matteo Scandolo219b1a72016-02-09 11:19:22 -080069 requests.push(SubscriberDevice.query({id: subscriber.id}).$promise);
Matteo Scandolo7547f042016-02-09 09:13:30 -080070 })
71
72 $q.all(requests)
73 .then((list) => {
Matteo Scandolo7547f042016-02-09 09:13:30 -080074 res.data.map((subscriber, i) => {
75 subscriber.devices = list[i];
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080076 subscriber.type = 'subscriber';
77
78 subscriber.devices.map(d => d.type = 'device')
79
Matteo Scandolo7547f042016-02-09 09:13:30 -080080 return subscriber;
81 });
Matteo Scandolo219b1a72016-02-09 11:19:22 -080082
Matteo Scandolo9fe01af2016-02-09 16:01:49 -080083 // faking to have 2 subscriber
84 res.data.push(angular.copy(res.data[0]));
85
Matteo Scandolo7547f042016-02-09 09:13:30 -080086 deferred.resolve(res.data);
87 })
88
89 return deferred.promise;
90 }
91 }
92 }
93 });
94 })
95 .service('SubscriberDevice', function($resource){
96 return $resource('/xoslib/rs/subscriber/:id/users/', {id: '@id'});
Matteo Scandoloff7df762016-01-22 16:36:34 -080097 })
Matteo Scandolo071ef462016-01-25 12:00:42 -080098 .service('ServiceRelation', function($q, lodash, Services, Tenant, Slice, Instances){
Matteo Scandolof16b3792016-01-21 14:23:28 -080099
Matteo Scandolof2c99012016-01-25 10:10:38 -0800100 // count the mas depth of an object
101 const depthOf = (obj) => {
102 var depth = 0;
103 if (obj.children) {
104 obj.children.forEach(function (d) {
105 var tmpDepth = depthOf(d);
106 if (tmpDepth > depth) {
107 depth = tmpDepth
108 }
109 })
110 }
111 return 1 + depth
112 };
113
Matteo Scandolof16b3792016-01-21 14:23:28 -0800114 // find all the relation defined for a given root
115 const findLevelRelation = (tenants, rootId) => {
116 return lodash.filter(tenants, service => {
117 return service.subscriber_service === rootId;
118 });
119 };
120
Matteo Scandoloc9ebd922016-01-28 12:02:57 -0800121 const findSpecificInformation = (tenants, rootId) => {
122 var tenants = lodash.filter(tenants, service => {
123 return service.provider_service === rootId && service.subscriber_tenant;
124 });
125
126 var info;
127
128 tenants.forEach((tenant) => {
129 if(tenant.service_specific_attribute){
130 info = JSON.parse(tenant.service_specific_attribute);
131 }
132 });
133
134 return info;
135 };
136
Matteo Scandolof16b3792016-01-21 14:23:28 -0800137 // find all the service defined by a given array of relations
138 const findLevelServices = (relations, services) => {
139 const levelServices = [];
140 lodash.forEach(relations, (tenant) => {
141 var service = lodash.find(services, {id: tenant.provider_service});
142 levelServices.push(service);
143 });
144 return levelServices;
145 };
146
147 const buildLevel = (tenants, services, rootService, parentName = null) => {
148
Matteo Scandolof16b3792016-01-21 14:23:28 -0800149 // build an array of unlinked services
150 // these are the services that should still placed in the tree
151 var unlinkedServices = lodash.difference(services, [rootService]);
152
153 // find all relations relative to this rootElement
154 const levelRelation = findLevelRelation(tenants, rootService.id);
155
156 // find all items related to rootElement
157 const levelServices = findLevelServices(levelRelation, services);
158
159 // remove this item from the list (performance
160 unlinkedServices = lodash.difference(unlinkedServices, levelServices);
161
Matteo Scandoloc9ebd922016-01-28 12:02:57 -0800162 rootService.service_specific_attribute = findSpecificInformation(tenants, rootService.id);
163
164 const tree = {
165 name: rootService.humanReadableName,
166 parent: parentName,
167 type: 'service',
168 service: rootService,
169 children: []
170 };
171
Matteo Scandolof16b3792016-01-21 14:23:28 -0800172 lodash.forEach(levelServices, (service) => {
173 tree.children.push(buildLevel(tenants, unlinkedServices, service, rootService.humanReadableName));
174 });
175
Matteo Scandolof2c99012016-01-25 10:10:38 -0800176 // if it is the last element append internet
177 if(tree.children.length === 0){
178 tree.children.push({
Matteo Scandolo9fe01af2016-02-09 16:01:49 -0800179 name: 'Router',
180 type: 'router',
Matteo Scandolof2c99012016-01-25 10:10:38 -0800181 children: []
182 });
183 }
184
Matteo Scandolof16b3792016-01-21 14:23:28 -0800185 return tree;
186 };
187
Matteo Scandolocb12a1a2016-01-25 14:11:10 -0800188 const buildServiceTree = (services, tenants, subscriber = {id: 1, name: 'fakeSubs'}) => {
Matteo Scandolof16b3792016-01-21 14:23:28 -0800189
190 // find the root service
191 // it is the one attached to subsriber_root
192 // as now we have only one root so this can work
Matteo Scandoloff7df762016-01-22 16:36:34 -0800193 const rootServiceId = lodash.find(tenants, {subscriber_root: subscriber.id}).provider_service;
Matteo Scandolof16b3792016-01-21 14:23:28 -0800194 const rootService = lodash.find(services, {id: rootServiceId});
195
196 const serviceTree = buildLevel(tenants, services, rootService);
197
Matteo Scandoloff7df762016-01-22 16:36:34 -0800198 return {
199 name: subscriber.name,
200 parent: null,
Matteo Scandolof2c99012016-01-25 10:10:38 -0800201 type: 'subscriber',
Matteo Scandoloff7df762016-01-22 16:36:34 -0800202 children: [serviceTree]
203 };
204
Matteo Scandolof16b3792016-01-21 14:23:28 -0800205 };
206
Matteo Scandoloff7df762016-01-22 16:36:34 -0800207 const get = (subscriber) => {
Matteo Scandolof16b3792016-01-21 14:23:28 -0800208 var deferred = $q.defer();
209 var services, tenants;
210 Services.query().$promise
211 .then((res) => {
212 services = res;
213 return Tenant.query().$promise;
214 })
215 .then((res) => {
216 tenants = res;
Matteo Scandoloff7df762016-01-22 16:36:34 -0800217 deferred.resolve(buildServiceTree(services, tenants, subscriber));
Matteo Scandolof16b3792016-01-21 14:23:28 -0800218 })
219 .catch((e) => {
220 throw new Error(e);
221 });
222
223 return deferred.promise;
Matteo Scandolof2c99012016-01-25 10:10:38 -0800224 };
Matteo Scandoloff7df762016-01-22 16:36:34 -0800225
Matteo Scandolof2c99012016-01-25 10:10:38 -0800226 // export APIs
Matteo Scandolo5bf04572016-01-25 17:36:08 -0800227 return {
228 get: get,
229 buildLevel: buildLevel,
230 buildServiceTree: buildServiceTree,
231 findLevelRelation: findLevelRelation,
232 findLevelServices: findLevelServices,
233 depthOf: depthOf,
Matteo Scandoloc9ebd922016-01-28 12:02:57 -0800234 findSpecificInformation: findSpecificInformation
Matteo Scandolo5bf04572016-01-25 17:36:08 -0800235 }
Matteo Scandolo8a64fa42016-01-21 11:21:03 -0800236 });
237
238}());