Exporting Tosca from UI
Change-Id: Ie7e58ac5bd51a56d028daa1c1e2577e7723a8297
diff --git a/views/ngXosViews/serviceGrid/spec/sample.test.js b/views/ngXosViews/serviceGrid/spec/sample.test.js
deleted file mode 100644
index c026149..0000000
--- a/views/ngXosViews/serviceGrid/spec/sample.test.js
+++ /dev/null
@@ -1,37 +0,0 @@
-'use strict';
-
-describe('The User List', () => {
-
- var scope, element, isolatedScope, httpBackend;
-
- beforeEach(module('xos.serviceGrid'));
- beforeEach(module('templates'));
-
- beforeEach(inject(function($httpBackend, $compile, $rootScope){
-
- httpBackend = $httpBackend;
- // Setting up mock request
- $httpBackend.expectGET('/api/core/users/?no_hyperlinks=1').respond([
- {
- email: 'teo@onlab.us',
- firstname: 'Matteo',
- lastname: 'Scandolo'
- }
- ]);
-
- scope = $rootScope.$new();
- element = angular.element('<users-list></users-list>');
- $compile(element)(scope);
- scope.$digest();
- isolatedScope = element.isolateScope().vm;
- }));
-
- xit('should load 1 users', () => {
- httpBackend.flush();
- expect(isolatedScope.users.length).toBe(1);
- expect(isolatedScope.users[0].email).toEqual('teo@onlab.us');
- expect(isolatedScope.users[0].firstname).toEqual('Matteo');
- expect(isolatedScope.users[0].lastname).toEqual('Scandolo');
- });
-
-});
\ No newline at end of file
diff --git a/views/ngXosViews/serviceGrid/spec/services_encoder.test.js b/views/ngXosViews/serviceGrid/spec/services_encoder.test.js
new file mode 100644
index 0000000..3107b7f
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/services_encoder.test.js
@@ -0,0 +1,223 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+ describe('The Services Encoder Service', () => {
+
+ var service, rootScope, ArchiveManagerSpy, toscaBase;
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject(($rootScope, ArchiveManager, ServiceEncoder) => {
+ rootScope = $rootScope;
+ toscaBase = angular.copy(toscaBaseDefault);
+
+ ArchiveManagerSpy = ArchiveManager;
+ spyOn(ArchiveManagerSpy, 'createArchive');
+ spyOn(ArchiveManagerSpy, 'addFile');
+ service = ServiceEncoder;
+ }));
+
+ describe('the formatServiceProperties method', () => {
+
+ it('should return only the existing properties', (done) => {
+ service.formatServiceProperties({name: 'test', kind: 'vCPE'}, toscaBase)
+ .then(res => {
+ expect(res).toEqual({
+ topology_template:{
+ node_templates: {
+ 'service#test': {
+ type: 'tosca.nodes.VSGService',
+ properties: {kind: 'vCPE'}
+ }
+ }
+ }
+ });
+ done();
+ });
+ rootScope.$apply();
+ });
+
+ it('should return all properties', (done) => {
+ service.formatServiceProperties({
+ name: 'test',
+ kind: 'vCPE',
+ view_url: 'view_url',
+ icon_url: 'icon_url',
+ private_key_fn: 'private_key_fn'
+ }, toscaBase)
+ .then(res => {
+ expect(res).toEqual({
+ topology_template:{
+ node_templates: {
+ 'service#test': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ kind: 'vCPE',
+ view_url: 'view_url',
+ icon_url: 'icon_url',
+ private_key_fn: 'private_key_fn'
+ }
+ }
+ }
+ }
+ });
+ done();
+ });
+ rootScope.$apply();
+ });
+
+ describe('when a public key is provided', () => {
+ it('should add public_key and artifacts properties', (done) => {
+
+ let expected = {
+ topology_template:{
+ node_templates: {
+ 'service#test': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ kind: 'vCPE',
+ public_key: '{ get_artifact: [ SELF, pubkey, LOCAL_FILE] }'
+ },
+ artifacts: {
+ pubkey: '/opt/xos/tosca/test/test_rsa.pub'
+ }
+ }
+ }
+ }
+ };
+
+ service.formatServiceProperties({
+ kind: 'vCPE',
+ public_key: 'pkey',
+ name: 'test'
+ }, toscaBase)
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ rootScope.$apply();
+ });
+
+ it('should add public_key file to the archive', (done) => {
+ service.formatServiceProperties({
+ kind: 'vCPE',
+ public_key: 'pkey',
+ name: 'test'
+ }, toscaBase)
+ .then(res => {
+ expect(ArchiveManagerSpy.addFile).toHaveBeenCalledWith('test_rsa.pub', 'pkey');
+ done();
+ });
+ rootScope.$apply();
+ });
+ });
+ });
+
+ describe('the getServiceRequirements method', () => {
+ let TenantSpy, ServiceSpy, tenantQueryPromise;
+ beforeEach(inject(function(Tenants, Services, $q){
+
+ tenantQueryPromise= $q.defer();
+
+ TenantSpy = Tenants;
+ spyOn(TenantSpy, 'query').and.callFake(function(){
+ return {$promise: tenantQueryPromise.promise};
+ });
+
+ ServiceSpy = Services;
+ spyOn(ServiceSpy, 'get').and.callFake(function(p){
+ let d = $q.defer();
+ d.resolve({name: `deps_${p.id}`});
+ return {$promise: d.promise};
+ });
+ }));
+
+ it('should call the tenants service with correct params', () => {
+ service.getServiceRequirements({id: 1});
+ expect(TenantSpy.query).toHaveBeenCalledWith({subscriber_service: 1});
+ });
+
+ it('should not add requirements if the current service has no dependency', (done) => {
+ service.getServiceRequirements({id: 1}, {})
+ .then(res => {
+ expect(res).toEqual({});
+ done();
+ });
+ tenantQueryPromise.resolve();
+ rootScope.$apply();
+ });
+
+ it('should return a list of required service', () => {
+ service.getServiceRequirements({id: 1, name: 'test'}, {topology_template: {node_templates: {'service#test': {}}}})
+ .then(res => {
+ expect(res.topology_template.node_templates['service#test'].requirements).toEqual([
+ {
+ deps_3_tenant: {
+ node: 'service#deps_3',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ },
+ {
+ deps_4_tenant: {
+ node: 'service#deps_4',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ }
+ ]);
+ });
+ tenantQueryPromise.resolve([
+ {
+ subscriber_service: 1,
+ provider_service: 3
+ },
+ {
+ subscriber_service: 1,
+ provider_service: 4
+ }
+ ]);
+ rootScope.$apply();
+ });
+
+ it('should return a list of unique required service', () => {
+ service.getServiceRequirements({id: 1, name: 'test'}, {topology_template: {node_templates: {'service#test': {}}}})
+ .then(res => {
+ expect(res.topology_template.node_templates['service#test'].requirements).toEqual([
+ {
+ deps_3_tenant: {
+ node: 'service#deps_3',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ }
+ ]);
+ });
+ tenantQueryPromise.resolve([
+ {
+ subscriber_service: 1,
+ provider_service: 3
+ },
+ {
+ subscriber_service: 1,
+ provider_service: 3
+ }
+ ]);
+ rootScope.$apply();
+ });
+ });
+ });
+
+})();
+
diff --git a/views/ngXosViews/serviceGrid/spec/site_encoder.test.js b/views/ngXosViews/serviceGrid/spec/site_encoder.test.js
new file mode 100644
index 0000000..fdc6d50
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/site_encoder.test.js
@@ -0,0 +1,62 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+ describe('The Site Encoder service', () => {
+ let service, toscaBase, siteGetPromise, SiteSpy, rootScope;
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ const siteResponse = {
+ name: 'MySite'
+ };
+
+ const expected = [{
+ topology_template: {
+ node_templates: {
+ 'MySite': {
+ type: 'tosca.nodes.Site',
+ }
+ }
+ }
+ }, siteResponse];
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject((SiteEncoder, Sites, $q, $rootScope) => {
+ toscaBase = angular.copy(toscaBaseDefault);
+ service = SiteEncoder;
+ rootScope = $rootScope;
+
+ siteGetPromise= $q.defer();
+ SiteSpy = Sites;
+ spyOn(SiteSpy, 'get').and.callFake(function(){
+ return {$promise: siteGetPromise.promise};
+ });
+ }));
+
+ describe('given a Site Id', () => {
+ it('should return the correct JSON structure', (done) => {
+ service.buildTosca({id: 1}, toscaBase)
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ siteGetPromise.resolve(siteResponse);
+ rootScope.$apply();
+ });
+ });
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/spec/slices_encoder.test.js b/views/ngXosViews/serviceGrid/spec/slices_encoder.test.js
new file mode 100644
index 0000000..f32bc9a
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/slices_encoder.test.js
@@ -0,0 +1,103 @@
+/**
+ * © OpenCORD
+ *
+ * Visit http://guide.xosproject.org/devguide/addview/ for more information
+ *
+ * Created by teone on 6/22/16.
+ */
+
+(function () {
+ 'use strict';
+
+ describe('The Slices Encoder service', () => {
+
+ let service, toscaBase, sliceQueryPromise, SliceSpy, rootScope;
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ const slicesArray = [
+ {
+ name: 'Slice1',
+ description: 'Description1',
+ network: 'noauto'
+ },
+ {
+ name: 'Slice2',
+ description: 'Description2',
+ network: 'noauto'
+ }
+ ];
+
+ const expected = {
+ topology_template: {
+ node_templates: {
+ Slice1: {
+ description: 'Description1',
+ type: 'tosca.nodes.Slice',
+ properties: {
+ network: 'noauto'
+ },
+ requirements: [
+ {management: {node: 'management', relationship: 'tosca.relationships.ConnectsToNetwork'}},
+ {test_service: {node: 'service#test', relationship: 'tosca.relationships.MemberOfService'}}
+ ]
+ },
+ Slice2: {
+ description: 'Description2',
+ type: 'tosca.nodes.Slice',
+ properties: {
+ network: 'noauto'
+ },
+ requirements: [
+ {management: {node: 'management', relationship: 'tosca.relationships.ConnectsToNetwork'}},
+ {test_service: {node: 'service#test', relationship: 'tosca.relationships.MemberOfService'}}
+ ]
+ }
+ }
+ }
+ };
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject((SlicesEncoder, Slices, $q, $rootScope) => {
+ toscaBase = angular.copy(toscaBaseDefault);
+ service = SlicesEncoder;
+ rootScope = $rootScope;
+
+ sliceQueryPromise= $q.defer();
+ SliceSpy = Slices;
+ spyOn(SliceSpy, 'query').and.callFake(function(){
+ return {$promise: sliceQueryPromise.promise};
+ });
+ }));
+
+ describe('given a Slices array ', () => {
+ it('should return the correct JSON structure', (done) => {
+ service.buildTosca(slicesArray, toscaBase, 'test')
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ rootScope.$apply();
+ });
+ });
+
+ describe('given a service', () => {
+ it('should return the JSON structure for all related slices', (done) => {
+ service.getServiceSlices({id : 1, name: 'test'}, toscaBase)
+ .then(res => {
+ expect(res).toEqual(expected);
+ done();
+ });
+ sliceQueryPromise.resolve(slicesArray);
+ rootScope.$apply();
+ });
+ });
+ });
+})();
+
diff --git a/views/ngXosViews/serviceGrid/spec/tosca_encoder.test.js b/views/ngXosViews/serviceGrid/spec/tosca_encoder.test.js
new file mode 100644
index 0000000..d968419
--- /dev/null
+++ b/views/ngXosViews/serviceGrid/spec/tosca_encoder.test.js
@@ -0,0 +1,234 @@
+(function () {
+ 'use strict';
+ describe('The Tosca Encoder Service', () => {
+
+ var service, httpBackend, rootScope, ArchiveManagerSpy, toscaBase;
+
+ const serviceData = {
+ id: 1,
+ name: 'vsg',
+ kind: 'vCPE'
+ };
+
+ const toscaBaseDefault = {
+ topology_template: {
+ node_templates: {}
+ }
+ };
+
+ beforeEach(module('xos.serviceGrid'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject(function($httpBackend, $rootScope, ToscaEncoder, ArchiveManager){
+
+ httpBackend = $httpBackend;
+ rootScope = $rootScope;
+ toscaBase = angular.copy(toscaBaseDefault);
+ service = ToscaEncoder;
+ ArchiveManagerSpy = ArchiveManager;
+ spyOn(ArchiveManagerSpy, 'createArchive');
+ spyOn(ArchiveManagerSpy, 'addFile');
+ spyOn(ArchiveManagerSpy, 'download');
+ }));
+
+ describe('the serviceToTosca method', () => {
+
+ const fakePropertiesDefault = {
+ tosca_definitions_version: 'tosca_simple_yaml_1_0',
+ description: 'Just enough Tosca to get the vSG slice running on the CORD POD',
+ imports: [
+ 'custom_types/xos.yaml'
+ ],
+ topology_template:{
+ node_templates: {
+ 'service#vsg': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ view_url: 'viewUrl',
+ icon_url: 'iconUrl',
+ kind: 'vCPE'
+ }
+ }
+ }
+ }
+ };
+
+ const fakeRequirements = {
+ tosca_definitions_version: 'tosca_simple_yaml_1_0',
+ description: 'Just enough Tosca to get the vSG slice running on the CORD POD',
+ imports: [
+ 'custom_types/xos.yaml'
+ ],
+ topology_template:{
+ node_templates: {
+ 'service#vsg': {
+ type: 'tosca.nodes.VSGService',
+ properties: {
+ view_url: 'viewUrl',
+ icon_url: 'iconUrl',
+ kind: 'vCPE'
+ },
+ requirements: [
+ {
+ node: 'service#vrouter',
+ relationship: 'tosca.relationships.TenantOfService'
+ },
+ {
+ node: 'service#volt',
+ relationship: 'tosca.relationships.TenantOfService'
+ }
+ ]
+ }
+ }
+ }
+ };
+
+ const expectedWithoutRequirements = `tosca_definitions_version: tosca_simple_yaml_1_0
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+imports:
+ - custom_types/xos.yaml
+topology_template:
+ node_templates:
+ service#vsg:
+ type: tosca.nodes.VSGService
+ properties:
+ view_url: viewUrl
+ icon_url: iconUrl
+ kind: vCPE
+`;
+
+ const expectedWithRequirements = `tosca_definitions_version: tosca_simple_yaml_1_0
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+imports:
+ - custom_types/xos.yaml
+topology_template:
+ node_templates:
+ service#vsg:
+ type: tosca.nodes.VSGService
+ properties:
+ view_url: viewUrl
+ icon_url: iconUrl
+ kind: vCPE
+ requirements:
+ - node: service#vrouter
+ relationship: tosca.relationships.TenantOfService
+ - node: service#volt
+ relationship: tosca.relationships.TenantOfService
+`;
+
+ const expectedWithSlices = `tosca_definitions_version: tosca_simple_yaml_1_0
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+imports:
+ - custom_types/xos.yaml
+topology_template:
+ node_templates:
+ service#vsg:
+ type: tosca.nodes.VSGService
+ properties:
+ view_url: viewUrl
+ icon_url: iconUrl
+ kind: vCPE
+ service_slice:
+ description: A service slice
+ type: tosca.nodes.Slice
+ properties:
+ network: noauto
+`;
+
+ let formatPromise, requirementPromise, slicesPromise, fakeProperties, serviceEncoderSpy, slicesEncoderSpy;
+
+ beforeEach(inject(($q, ServiceEncoder, SlicesEncoder) => {
+
+ serviceEncoderSpy = ServiceEncoder;
+ slicesEncoderSpy = SlicesEncoder;
+
+ // clone the base property for mock
+ fakeProperties = angular.copy(fakePropertiesDefault);
+
+ // create the promises
+ // this will be resolved in the single IT block,
+ // to allow different resolutions
+ formatPromise = $q.defer();
+ requirementPromise = $q.defer();
+ slicesPromise = $q.defer();
+
+ // mock functions and return promises
+ spyOn(serviceEncoderSpy, 'formatServiceProperties').and.callFake(function(){
+ return formatPromise.promise;
+ });
+ spyOn(serviceEncoderSpy, 'getServiceRequirements').and.callFake(function(){
+ return requirementPromise.promise;
+ });
+ spyOn(slicesEncoderSpy, 'getServiceSlices').and.callFake(function(){
+ return slicesPromise.promise;
+ });
+ }));
+
+ it('should create a new archive', () => {
+ service.serviceToTosca(serviceData);
+ expect(ArchiveManagerSpy.createArchive).toHaveBeenCalled();
+ });
+
+ it('should add the service file to the archive', (done) => {
+ service.serviceToTosca(serviceData)
+ .then(() => {
+ expect(ArchiveManagerSpy.addFile).toHaveBeenCalledWith('vsg_service.yaml', expectedWithoutRequirements);
+ expect(ArchiveManagerSpy.download).toHaveBeenCalledWith('vsg');
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeProperties);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+
+ // IS IT REALLY USEFULL TO TEST THE CONVERTION TO YAML?
+ xit('should create a tosca spec with no requirements', (done) => {
+ service.serviceToTosca(serviceData)
+ .then(res => {
+ expect(res).toEqual(expectedWithoutRequirements);
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeProperties);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+
+ xit('should create a tosca spec with requirements', (done) => {
+ service.serviceToTosca(serviceData)
+ .then(res => {
+ expect(res).toEqual(expectedWithRequirements);
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeRequirements);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+
+ xit('should create a tosca spec with additional slices', (done) => {
+
+ // this is dirty, we are changing an object and shouldn't be done in tests
+ angular.extend(
+ fakeProperties.topology_template.node_templates, {service_slice: {
+ description: 'A service slice',
+ type: 'tosca.nodes.Slice',
+ properties: {
+ network: 'noauto'
+ }
+ }});
+
+ service.serviceToTosca(serviceData)
+ .then(res => {
+ expect(res).toEqual(expectedWithSlices);
+ done();
+ });
+ formatPromise.resolve(fakeProperties);
+ requirementPromise.resolve(fakeProperties);
+ slicesPromise.resolve(fakeProperties);
+ rootScope.$apply();
+ });
+ });
+ });
+}());
\ No newline at end of file