From 0a4fb9f8b9e8c2a2fb60eb2cf22f80eb7a7b1b1a Mon Sep 17 00:00:00 2001 From: Corentin Ardeois Date: Tue, 25 Oct 2016 12:38:29 +0200 Subject: [PATCH] Added support for multi-region catalog OpenStack wrapper will read the 'region_name' from config, and use the correct endpoint matching this region Change-Id: I01049f3bed227eb1e11f9a1f7d338177e95aef34 --- src/openstack.js | 5 ++++- test/unit/helpers/data/keystone.js | 21 +++++++++++++++++++ test/unit/helpers/data/openstack.js | 23 +++++++++++++-------- test/unit/openstackTest.js | 32 ++++++++++++++++++++++------- 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/openstack.js b/src/openstack.js index 5df6332..b1e9bb4 100644 --- a/src/openstack.js +++ b/src/openstack.js @@ -83,10 +83,13 @@ export default class OpenStack { * @private */ _getComponentConfigFor(name) { + const config = this.getConfig(); return this._token .then((token) => this._keystone.then((keystone) => keystone.catalogList(token))) .then((catalog) => catalog.find((entry) => entry.name === name)) - .then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public')); + .then((entry) => entry.endpoints.find((endpoint) => { + return endpoint.region === config.region_name && endpoint.interface === 'public'; + })); } } diff --git a/test/unit/helpers/data/keystone.js b/test/unit/helpers/data/keystone.js index 12eedb3..f3752ca 100644 --- a/test/unit/helpers/data/keystone.js +++ b/test/unit/helpers/data/keystone.js @@ -253,6 +253,27 @@ const catalogListData = [ region: "RegionOne", interface: "admin", id: "bd8db1bafe41489bbbc45641e525ee7d" + }, + { + region_id: "RegionTwo", + url: "http://192.168.99.100:9696/", + region: "RegionTwo", + interface: "public", + id: "7033fa4ebed74e3fa51753162150a1f2" + }, + { + region_id: "RegionTwo", + url: "http://192.168.99.100:9696/", + region: "RegionOne", + interface: "RegionTwo", + id: "7aa942d402a34d4c90454b9d84285855" + }, + { + region_id: "RegionTwo", + url: "http://192.168.99.100:9696/", + region: "RegionTwo", + interface: "admin", + id: "bd8db1bafe41489bbbc45641e525ee7d" } ], type: "network", diff --git a/test/unit/helpers/data/openstack.js b/test/unit/helpers/data/openstack.js index 131aadd..5c14c4c 100644 --- a/test/unit/helpers/data/openstack.js +++ b/test/unit/helpers/data/openstack.js @@ -22,16 +22,21 @@ /** * Mock cloud configuration that matches our test data below. This is not a full clouds.yaml * format, rather just the subsection pointing to a particular cloud. + * @param {String} regionName A region name to use + * @returns {{}} a cloud config object. */ -const cloudConfig = { - region_name: 'Region1', - auth: { - username: 'user', - password: 'pass', - project_name: 'js-openstack-lib', - auth_url: 'http://192.168.99.99/' - } -}; +function cloudConfig(regionName = 'RegionOne') { + return { + region_name: regionName, + auth: { + username: 'user', + password: 'pass', + project_name: 'js-openstack-lib', + auth_url: 'http://192.168.99.99/' + } + }; +} + export { cloudConfig as config, }; diff --git a/test/unit/openstackTest.js b/test/unit/openstackTest.js index 4b349ca..832db55 100644 --- a/test/unit/openstackTest.js +++ b/test/unit/openstackTest.js @@ -11,7 +11,7 @@ describe("Simple test", () => { afterEach(fetchMock.restore); it("should export a class", () => { - let t = new OpenStack(openStackMockData.config); + let t = new OpenStack(openStackMockData.config()); expect(t).toBeDefined(); }); @@ -25,14 +25,14 @@ describe("Simple test", () => { }); it("getConfig should returns the config", () => { - let openstack = new OpenStack(openStackMockData.config); + let openstack = new OpenStack(openStackMockData.config()); let config = openstack.getConfig(); - expect(config.region_name).toEqual('Region1'); + expect(config.region_name).toEqual('RegionOne'); }); describe('networkList', () => { it('should fetch networkList from neutron', (done) => { - const openstack = new OpenStack(openStackMockData.config); + const openstack = new OpenStack(openStackMockData.config()); const neutron = mockNeutron(openstack); const networksData = neutronMockData.networkList('token').response.networks; @@ -50,7 +50,7 @@ describe("Simple test", () => { describe('_neutron', () => { it('creates Neutron instance with the correct endpoint', (done) => { const token = 'test_token'; - const openstack = new OpenStack(openStackMockData.config); + const openstack = new OpenStack(openStackMockData.config()); const keystone = mockKeystone(openstack); const catalogData = keystoneMockData.catalogList(token).response.catalog; @@ -67,8 +67,26 @@ describe("Simple test", () => { .catch((error) => done.fail(error)); }); + it('creates Neutron instance for the correct endpoint', (done) => { + const token = 'test_token'; + const openstack = new OpenStack(openStackMockData.config('RegionTwo')); + const keystone = mockKeystone(openstack); + const catalogData = keystoneMockData.catalogList(token).response.catalog; + + spyOn(keystone, 'tokenIssue').and.returnValue(Promise.resolve(token)); + spyOn(keystone, 'catalogList').and.returnValue(Promise.resolve(catalogData)); + + openstack._neutron + .then((neutron) => { + expect(neutron).toEqual(jasmine.any(Neutron)); + expect(neutron.endpointUrl).toEqual('http://192.168.99.100:9696/'); + done(); + }) + .catch((error) => done.fail(error)); + }); + it('should cache Neutron instance and Keystone token', (done) => { - const openstack = new OpenStack(openStackMockData.config); + const openstack = new OpenStack(openStackMockData.config()); const tokenIssueMock = keystoneMockData.tokenIssue(); const catalogListMock = keystoneMockData.catalogList('test_token'); @@ -95,7 +113,7 @@ describe("Simple test", () => { describe('_token', () => { it('should fetch the token and cache it', (done) => { - const openstack = new OpenStack(openStackMockData.config); + const openstack = new OpenStack(openStackMockData.config()); const keystone = mockKeystone(openstack); spyOn(keystone, 'tokenIssue').and.returnValue(Promise.resolve('test_token'));