Highlighting active instances
diff --git a/views/ngXosViews/serviceTopology/env/default.js b/views/ngXosViews/serviceTopology/env/default.js
index 58fbc70..3cd8646 100644
--- a/views/ngXosViews/serviceTopology/env/default.js
+++ b/views/ngXosViews/serviceTopology/env/default.js
@@ -8,6 +8,6 @@
module.exports = {
host: 'http://clnode078.clemson.cloudlab.us:9999/',
- xoscsrftoken: '2jDJ7XxDBkpBg3gEr8ckHDHirxV9bjdZ',
- xossessionid: 'f9z9mj57jyqe3bpg8hrhohdopi929k9n'
+ xoscsrftoken: 'rAOyEY6TnfHM2pCPbknMkkSTn92Il3lv',
+ xossessionid: 'hgw3sukg8w6ec8w8rr8txradxgluiidx'
};
diff --git a/views/ngXosViews/serviceTopology/spec/sample.test.js b/views/ngXosViews/serviceTopology/spec/sample.test.js
index 45630e9..56f7c8b 100644
--- a/views/ngXosViews/serviceTopology/spec/sample.test.js
+++ b/views/ngXosViews/serviceTopology/spec/sample.test.js
@@ -38,7 +38,9 @@
const levelRelations = [
{
- provider_service: 1
+ provider_service: 1,
+ service_specific_attribute: '{"instance_id": "instance1"}',
+ subscriber_tenant: 2
},
{
provider_service: 2
@@ -62,8 +64,15 @@
let levelServices = Service.findLevelServices(levelRelations, services);
expect(levelServices.length).toBe(2);
});
+
+ it('should retrieve all service specific information', () => {
+ let info = Service.findSpecificInformation(levelRelations, 1);
+ expect(info.instance_id).toBe('instance1');
+ });
});
+
+
describe('given a list of services and a list of relations', () => {
const services = [
@@ -160,24 +169,34 @@
const instances = [
[
{
- humanReadableName: 'first-slice-instance-1'
+ humanReadableName: 'first-slice-instance-1',
+ id: 1
},
{
- humanReadableName: 'first-slice-instance-2'
+ humanReadableName: 'first-slice-instance-2',
+ id: 2
}
],
[
{
- humanReadableName: 'second-slice-instance'
+ humanReadableName: 'second-slice-instance',
+ id: 3
}
]
];
+ const service = {
+ service_specific_attribute: {
+ instance_id: 1
+ }
+ };
+
it('should create a tree grouping instances', () => {
- const res = Service.buildServiceInterfacesTree(slices, instances);
+ const res = Service.buildServiceInterfacesTree(service, slices, instances);
expect(res[0].name).toBe('First');
expect(res[0].children[0].name).toBe('first-slice-instance-1');
+ expect(res[0].children[0].active).toBeTruthy();
expect(res[0].children[1].name).toBe('first-slice-instance-2');
expect(res[1].name).toBe('Second');
diff --git a/views/ngXosViews/serviceTopology/src/css/serviceTopology.css b/views/ngXosViews/serviceTopology/src/css/serviceTopology.css
index cc2b130..283967c 100644
--- a/views/ngXosViews/serviceTopology/src/css/serviceTopology.css
+++ b/views/ngXosViews/serviceTopology/src/css/serviceTopology.css
@@ -51,6 +51,10 @@
}
.node.instance rect {
+ stroke: #ccc;
+}
+
+.node.instance rect.active {
stroke: #ff8b00;
}
@@ -74,6 +78,10 @@
stroke: rgba(157, 4, 183, 0.29);
}
.link.instance{
+ stroke: #ccc;
+}
+
+.link.instance.active{
stroke: rgba(255, 138, 0, 0.65);
}
diff --git a/views/ngXosViews/serviceTopology/src/js/d3.js b/views/ngXosViews/serviceTopology/src/js/d3.js
index 59c3b5f..4672325 100644
--- a/views/ngXosViews/serviceTopology/src/js/d3.js
+++ b/views/ngXosViews/serviceTopology/src/js/d3.js
@@ -181,7 +181,8 @@
width: 20,
height: 20,
x: -10,
- y: -10
+ y: -10,
+ class: d => d.active ?'' : 'active'
});
nodeEnter.append('text')
@@ -235,7 +236,7 @@
// Enter any new links at the parent's previous position.
link.enter().insert('path', 'g')
- .attr('class', d => `link ${d.target.type}`)
+ .attr('class', d => `link ${d.target.type} ${d.target.active ? '' : 'active'}`)
.attr('d', function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
@@ -278,7 +279,7 @@
.duration(serviceTopologyConfig.duration)
.attr('r', serviceTopologyConfig.circle.selectedRadius);
- ServiceRelation.getServiceInterfaces(d.service.id)
+ ServiceRelation.getServiceInterfaces(d.service)
.then(interfaceTree => {
const isDetailed = lodash.find(d.children, {type: 'slice'});
diff --git a/views/ngXosViews/serviceTopology/src/js/services.js b/views/ngXosViews/serviceTopology/src/js/services.js
index b3ac3b0..12dedaf 100644
--- a/views/ngXosViews/serviceTopology/src/js/services.js
+++ b/views/ngXosViews/serviceTopology/src/js/services.js
@@ -40,6 +40,22 @@
});
};
+ const findSpecificInformation = (tenants, rootId) => {
+ var tenants = lodash.filter(tenants, service => {
+ return service.provider_service === rootId && service.subscriber_tenant;
+ });
+
+ var info;
+
+ tenants.forEach((tenant) => {
+ if(tenant.service_specific_attribute){
+ info = JSON.parse(tenant.service_specific_attribute);
+ }
+ });
+
+ return info;
+ };
+
// find all the service defined by a given array of relations
const findLevelServices = (relations, services) => {
const levelServices = [];
@@ -52,14 +68,6 @@
const buildLevel = (tenants, services, rootService, parentName = null) => {
- const tree = {
- name: rootService.humanReadableName,
- parent: parentName,
- type: 'service',
- service: rootService,
- children: []
- };
-
// build an array of unlinked services
// these are the services that should still placed in the tree
var unlinkedServices = lodash.difference(services, [rootService]);
@@ -73,6 +81,16 @@
// remove this item from the list (performance
unlinkedServices = lodash.difference(unlinkedServices, levelServices);
+ rootService.service_specific_attribute = findSpecificInformation(tenants, rootService.id);
+
+ const tree = {
+ name: rootService.humanReadableName,
+ parent: parentName,
+ type: 'service',
+ service: rootService,
+ children: []
+ };
+
lodash.forEach(levelServices, (service) => {
tree.children.push(buildLevel(tenants, unlinkedServices, service, rootService.humanReadableName));
});
@@ -127,7 +145,15 @@
return deferred.promise;
};
- const buildServiceInterfacesTree = (slices, instances) => {
+ const buildServiceInterfacesTree = (service, slices, instances) => {
+
+ const isActive = (service, instance) => {
+ if(service.service_specific_attribute){
+ return service.service_specific_attribute.instance_id === instance.id;
+ }
+ return false;
+ }
+
var interfaceTree = [];
lodash.forEach(slices, (slice, i) => {
let current = {
@@ -135,11 +161,13 @@
slice: slice,
type: 'slice',
children: instances[i].map((instance) => {
+
return {
name: instance.humanReadableName,
children: [],
type: 'instance',
- instance: instance
+ instance: instance,
+ active: isActive(service, instance)
};
})
@@ -149,12 +177,12 @@
return interfaceTree;
};
- const getServiceInterfaces = (serviceId) => {
+ const getServiceInterfaces = (service) => {
var deferred = $q.defer();
var _slices;
- Slice.query({service: serviceId}).$promise
+ Slice.query({service: service.id}).$promise
.then((slices) => {
_slices = slices;
const promisesArr = slices.reduce((promises, slice) => {
@@ -169,7 +197,7 @@
return $q.all(promisesArr);
})
.then((instances) => {
- deferred.resolve(buildServiceInterfacesTree(_slices, instances));
+ deferred.resolve(buildServiceInterfacesTree(service, _slices, instances));
});
return deferred.promise;
@@ -184,7 +212,8 @@
findLevelServices: findLevelServices,
depthOf: depthOf,
getServiceInterfaces: getServiceInterfaces,
- buildServiceInterfacesTree: buildServiceInterfacesTree
+ buildServiceInterfacesTree: buildServiceInterfacesTree,
+ findSpecificInformation: findSpecificInformation
}
});