From 0ba0ea9668847d39c356021034f7ee708c2406d5 Mon Sep 17 00:00:00 2001 From: Corentin Ardeois Date: Mon, 21 Nov 2016 14:09:00 -0500 Subject: [PATCH] Add imageList to Openstack wrapper This patch integrated glance into Openstack wrapper, allowing imageList to be used Change-Id: I64e5d432224aa673ab1e6ace3e927af2f8b3a13f --- src/glance.js | 3 +- src/openstack.js | 25 +++++++++++ test/functional/openstackTest.js | 13 ++++++ test/unit/openstackTest.js | 71 ++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/glance.js b/src/glance.js index 33521e2..3dfc80f 100644 --- a/src/glance.js +++ b/src/glance.js @@ -58,7 +58,8 @@ export default class Glance extends AbstractService { /** * List the images available on glance. * - * @param {String} token An authorization token, or a promise which will resolve into one. + * @param {(String|Promise.)} token An authorization token, or a promise which will resolve + * into one. * @returns {Promise.} A promise which will resolve with the list of images. */ imageList(token = null) { diff --git a/src/openstack.js b/src/openstack.js index b1e9bb4..46109d1 100644 --- a/src/openstack.js +++ b/src/openstack.js @@ -1,5 +1,6 @@ import Keystone from "./keystone"; import Neutron from "./neutron"; +import Glance from "./glance"; export default class OpenStack { /** @@ -34,6 +35,16 @@ export default class OpenStack { .then((neutron) => neutron.networkList(this._token)); } + /** + * List the images available on glance. + * + * @returns {Promise.} A promise which will resolve with the list of images. + */ + imageList() { + return this._glance + .then((glance) => glance.imageList(this._token)); + } + /** * Keystone component. * @@ -62,6 +73,20 @@ export default class OpenStack { return this._neutronPromise; } + /** + * Glance component. + * + * @returns {Promise.} A promise which will resolve with Glance instance. + * @private + */ + get _glance() { + if (!this._glancePromise) { + this._glancePromise = this._getComponentConfigFor('glance') + .then((componentConfig) => new Glance(componentConfig)); + } + return this._glancePromise; + } + /** * Token issued from Keystone. * diff --git a/test/functional/openstackTest.js b/test/functional/openstackTest.js index c1ac912..4ccd7ba 100644 --- a/test/functional/openstackTest.js +++ b/test/functional/openstackTest.js @@ -20,4 +20,17 @@ describe("OpenStack", () => { }); }); + describe("imageList()", () => { + it("should return the images as an array.", (done) => { + const openstack = new OpenStack(devstackConfig); + + openstack.imageList() + .then((images) => { + expect(images.length > 0).toBeTruthy(); + done(); + }) + .catch((error) => done.fail(error)); + }); + }); + }); diff --git a/test/unit/openstackTest.js b/test/unit/openstackTest.js index 832db55..1b2b82b 100644 --- a/test/unit/openstackTest.js +++ b/test/unit/openstackTest.js @@ -2,9 +2,11 @@ import OpenStack from "../../src/openstack"; import * as openStackMockData from './helpers/data/openstack'; import * as neutronMockData from './helpers/data/neutron'; import * as keystoneMockData from './helpers/data/keystone'; +import * as glanceMockData from './helpers/data/glance'; import fetchMock from 'fetch-mock'; import Neutron from "../../src/neutron"; import Keystone from "../../src/keystone"; +import Glance from "../../src/glance"; describe("Simple test", () => { @@ -47,6 +49,23 @@ describe("Simple test", () => { }); }); + describe('imageList', () => { + it('should fetch imageList from glance', (done) => { + const openstack = new OpenStack(openStackMockData.config()); + const glance = mockGlance(openstack); + const imagesData = glanceMockData.imageList('token').response.images; + + spyOn(glance, 'imageList').and.returnValue(Promise.resolve(imagesData)); + + openstack.imageList() + .then((images) => { + expect(images.length).toBe(3); + done(); + }) + .catch((error) => done.fail(error)); + }); + }); + describe('_neutron', () => { it('creates Neutron instance with the correct endpoint', (done) => { const token = 'test_token'; @@ -111,6 +130,52 @@ describe("Simple test", () => { }); }); + describe('_glance', () => { + it('creates Glance instance with the correct endpoint', (done) => { + const token = 'test_token'; + const openstack = new OpenStack(openStackMockData.config()); + 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._glance + .then((glance) => { + expect(keystone.catalogList).toHaveBeenCalledWith(token); + expect(glance).toEqual(jasmine.any(Glance)); + expect(glance.endpointUrl).toEqual('http://192.168.99.99:9292'); + done(); + }) + .catch((error) => done.fail(error)); + }); + + it('should cache Glance instance and Keystone token', (done) => { + const openstack = new OpenStack(openStackMockData.config()); + const tokenIssueMock = keystoneMockData.tokenIssue(); + const catalogListMock = keystoneMockData.catalogList('test_token'); + + fetchMock.mock(keystoneMockData.root()); + fetchMock.mock(tokenIssueMock); + fetchMock.mock(catalogListMock); + + openstack._glance + .then((glance) => { + expect(glance).toEqual(jasmine.any(Glance)); + expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1); + expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1); + return openstack._glance; + }) + .then((glance) => { + expect(glance).toEqual(jasmine.any(Glance)); + expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1); + expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1); + done(); + }) + .catch((error) => done.fail(error)); + }); + }); + describe('_token', () => { it('should fetch the token and cache it', (done) => { const openstack = new OpenStack(openStackMockData.config()); @@ -145,4 +210,10 @@ describe("Simple test", () => { return neutron; } + function mockGlance(openstack) { + const glance = new Glance(glanceMockData.config); + openstack._glancePromise = Promise.resolve(glance); + return glance; + } + });