Merge "Use serviceEndpoint compatible with versions"
This commit is contained in:
commit
f96704d7e4
|
@ -7,7 +7,7 @@ import AbstractService from './util/abstractService';
|
||||||
* @ignore
|
* @ignore
|
||||||
*/
|
*/
|
||||||
const supportedKeystoneVersions = [
|
const supportedKeystoneVersions = [
|
||||||
'v3.7'
|
'v3.1'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default class Keystone extends AbstractService {
|
export default class Keystone extends AbstractService {
|
||||||
|
@ -59,12 +59,13 @@ export default class Keystone extends AbstractService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all the API versions available.
|
* Retrieve all the raw API versions available.
|
||||||
*
|
*
|
||||||
* @returns {Promise.<T>} A promise that will resolve with the list of API versions.
|
* @returns {Promise.<Object[]>} A promise that will resolve with the list of raw versions.
|
||||||
|
* @protected
|
||||||
*/
|
*/
|
||||||
versions() {
|
_rawVersions() {
|
||||||
return super.versions()
|
return super._rawVersions()
|
||||||
.then((versions) => versions.values);
|
.then((versions) => versions.values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Http from './http';
|
import Http from './http';
|
||||||
|
import Version from './version';
|
||||||
import URL from 'url-parse';
|
import URL from 'url-parse';
|
||||||
|
|
||||||
export default class AbstractService {
|
export default class AbstractService {
|
||||||
|
@ -64,9 +65,25 @@ export default class AbstractService {
|
||||||
/**
|
/**
|
||||||
* Retrieve all the API versions available.
|
* Retrieve all the API versions available.
|
||||||
*
|
*
|
||||||
* @returns {Promise.<T>} A promise that will resolve with the list of API versions.
|
* @returns {Promise.<Version[]>} A promise that will resolve with the list of API versions.
|
||||||
*/
|
*/
|
||||||
versions() {
|
versions() {
|
||||||
|
return this._rawVersions().then((versions) => {
|
||||||
|
return versions.map((rawVersion) => {
|
||||||
|
const version = new Version(rawVersion.id);
|
||||||
|
version.links = rawVersion.links;
|
||||||
|
return version;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all the raw API versions available.
|
||||||
|
*
|
||||||
|
* @returns {Promise.<Object[]>} A promise that will resolve with the list of raw versions.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_rawVersions() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let promise = this.http
|
let promise = this.http
|
||||||
.httpGet(this._endpointUrl)
|
.httpGet(this._endpointUrl)
|
||||||
|
@ -92,14 +109,14 @@ export default class AbstractService {
|
||||||
/**
|
/**
|
||||||
* Retrieve the API version declaration that is currently in use by this instance.
|
* Retrieve the API version declaration that is currently in use by this instance.
|
||||||
*
|
*
|
||||||
* @returns {Promise.<T>} A promise that will resolve with the specific API version.
|
* @returns {Promise.<Version>} A promise that will resolve with the specific API version.
|
||||||
*/
|
*/
|
||||||
version() {
|
version() {
|
||||||
return this
|
return this
|
||||||
.versions()
|
.versions()
|
||||||
.then((versions) => {
|
.then((versions) => {
|
||||||
for (let version of versions) {
|
for (let version of versions) {
|
||||||
if (this.supportedVersions.indexOf(version.id) > -1) {
|
if (this.supportedVersions.find(version.supports)) {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,10 +56,30 @@ export default class Version {
|
||||||
return this._patch || 0;
|
return this._patch || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The links of the service
|
||||||
|
*
|
||||||
|
* @returns {Object[]} The list of links.
|
||||||
|
*/
|
||||||
|
get links() {
|
||||||
|
return this._links || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the links of the service
|
||||||
|
*
|
||||||
|
* @param {Object[]} links The links to be set
|
||||||
|
*/
|
||||||
|
set links(links) {
|
||||||
|
if (Array.isArray(links)) {
|
||||||
|
this._links = links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of a service version.
|
* Create a new instance of a service version.
|
||||||
*
|
*
|
||||||
* @param {String} service The name of the service.
|
* @param {String} [service] The name of the service.
|
||||||
* @param {String} versionString The version string for this service.
|
* @param {String} versionString The version string for this service.
|
||||||
*/
|
*/
|
||||||
constructor(service, versionString) {
|
constructor(service, versionString) {
|
||||||
|
@ -89,6 +109,10 @@ export default class Version {
|
||||||
this._minor = parseInt(results[6], 10);
|
this._minor = parseInt(results[6], 10);
|
||||||
this._patch = parseInt(results[8], 10);
|
this._patch = parseInt(results[8], 10);
|
||||||
}
|
}
|
||||||
|
this._links = null;
|
||||||
|
|
||||||
|
this.equals = this.equals.bind(this);
|
||||||
|
this.supports = this.supports.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,4 +136,38 @@ export default class Version {
|
||||||
version.patch === this.patch &&
|
version.patch === this.patch &&
|
||||||
version.service === this.service;
|
version.service === this.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies compatibility of this instance to another instance. Major version should be equal and
|
||||||
|
* minor version should be greater or equal than `version` parameter.
|
||||||
|
*
|
||||||
|
* @param {String|Version} version the version to support.
|
||||||
|
* @returns {boolean} True if the version is compatible, otherwise false
|
||||||
|
*/
|
||||||
|
supports(version) {
|
||||||
|
if (!(version instanceof Version)) {
|
||||||
|
if (typeof version === 'string') {
|
||||||
|
version = new Version(version);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const compatibleVersion = version.service === this.service &&
|
||||||
|
version.major === this.major &&
|
||||||
|
version.minor <= this.minor;
|
||||||
|
|
||||||
|
if (compatibleVersion && version.minor === this.minor) {
|
||||||
|
return version.patch <= this.patch;
|
||||||
|
}
|
||||||
|
return compatibleVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
let version = `${this.major}.${this.minor}`;
|
||||||
|
if (this.patch) {
|
||||||
|
version = `${version}.${this.patch}`;
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ describe("Glance", () => {
|
||||||
describe("version()", () => {
|
describe("version()", () => {
|
||||||
|
|
||||||
const supportedApiVersions = [
|
const supportedApiVersions = [
|
||||||
new Version('image 2.3')
|
new Version('2.4')
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,11 +61,7 @@ describe("Glance", () => {
|
||||||
configPromise
|
configPromise
|
||||||
.then((config) => new Glance(config))
|
.then((config) => new Glance(config))
|
||||||
.then((glance) => glance.version())
|
.then((glance) => glance.version())
|
||||||
.then((version) => {
|
.then((apiVersion) => {
|
||||||
|
|
||||||
// Quick sanity check.
|
|
||||||
const apiVersion = new Version('image', version.id);
|
|
||||||
|
|
||||||
for (let i = 0; i < supportedApiVersions.length; i++) {
|
for (let i = 0; i < supportedApiVersions.length; i++) {
|
||||||
let supportedVersion = supportedApiVersions[i];
|
let supportedVersion = supportedApiVersions[i];
|
||||||
if (apiVersion.equals(supportedVersion)) {
|
if (apiVersion.equals(supportedVersion)) {
|
||||||
|
@ -73,7 +69,7 @@ describe("Glance", () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fail("Current devstack glance version is not supported.");
|
fail(`Current devstack glance version (${apiVersion}) is not supported.`);
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch((error) => done.fail(error));
|
.catch((error) => done.fail(error));
|
||||||
|
|
|
@ -43,7 +43,7 @@ describe("Keystone", () => {
|
||||||
describe("version()", () => {
|
describe("version()", () => {
|
||||||
|
|
||||||
const supportedApiVersions = [
|
const supportedApiVersions = [
|
||||||
new Version('identity 3.7')
|
new Version('3.7')
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,11 +52,7 @@ describe("Keystone", () => {
|
||||||
*/
|
*/
|
||||||
it("should return a supported version.", (done) => {
|
it("should return a supported version.", (done) => {
|
||||||
keystone.version()
|
keystone.version()
|
||||||
.then((version) => {
|
.then((apiVersion) => {
|
||||||
|
|
||||||
// Quick sanity check.
|
|
||||||
const apiVersion = new Version('identity', version.id);
|
|
||||||
|
|
||||||
for (let i = 0; i < supportedApiVersions.length; i++) {
|
for (let i = 0; i < supportedApiVersions.length; i++) {
|
||||||
let supportedVersion = supportedApiVersions[i];
|
let supportedVersion = supportedApiVersions[i];
|
||||||
if (apiVersion.equals(supportedVersion)) {
|
if (apiVersion.equals(supportedVersion)) {
|
||||||
|
@ -64,7 +60,7 @@ describe("Keystone", () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fail("Current devstack keystone version is not supported.");
|
fail(`Current devstack keystone version (${apiVersion}) is not supported.`);
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch((response) => response.json()
|
.catch((response) => response.json()
|
||||||
|
|
|
@ -50,7 +50,7 @@ describe("neutron", () => {
|
||||||
describe("version()", () => {
|
describe("version()", () => {
|
||||||
|
|
||||||
const supportedApiVersions = [
|
const supportedApiVersions = [
|
||||||
new Version('network 2.0')
|
new Version('2.0')
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,11 +61,7 @@ describe("neutron", () => {
|
||||||
configPromise
|
configPromise
|
||||||
.then((config) => new Neutron(config))
|
.then((config) => new Neutron(config))
|
||||||
.then((neutron) => neutron.version())
|
.then((neutron) => neutron.version())
|
||||||
.then((version) => {
|
.then((apiVersion) => {
|
||||||
|
|
||||||
// Quick sanity check.
|
|
||||||
const apiVersion = new Version('network', version.id);
|
|
||||||
|
|
||||||
for (let i = 0; i < supportedApiVersions.length; i++) {
|
for (let i = 0; i < supportedApiVersions.length; i++) {
|
||||||
let supportedVersion = supportedApiVersions[i];
|
let supportedVersion = supportedApiVersions[i];
|
||||||
if (apiVersion.equals(supportedVersion)) {
|
if (apiVersion.equals(supportedVersion)) {
|
||||||
|
@ -73,7 +69,7 @@ describe("neutron", () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fail("Current devstack neutron version is not supported.");
|
fail(`Current devstack neutron version (${apiVersion}) is not supported.`);
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch((error) => done.fail(error));
|
.catch((error) => done.fail(error));
|
||||||
|
|
|
@ -31,21 +31,6 @@ describe('Glance', () => {
|
||||||
expect(() => new Glance()).toThrow();
|
expect(() => new Glance()).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("version()", () => {
|
|
||||||
it("Should return a supported version of the glance API.", (done) => {
|
|
||||||
const glance = new Glance(mockData.config);
|
|
||||||
|
|
||||||
fetchMock.mock(mockData.root());
|
|
||||||
|
|
||||||
glance.version()
|
|
||||||
.then((version) => {
|
|
||||||
expect(version.id).toEqual('v2.3');
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch((error) => done.fail(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("serviceEndpoint()", () => {
|
describe("serviceEndpoint()", () => {
|
||||||
it("Should return a valid endpoint to the glance API.", (done) => {
|
it("Should return a valid endpoint to the glance API.", (done) => {
|
||||||
const glance = new Glance(mockData.config);
|
const glance = new Glance(mockData.config);
|
||||||
|
|
|
@ -75,16 +75,6 @@ function rootResponse() {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
status: "SUPPORTED",
|
|
||||||
id: "v2.0",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
href: `${rootUrl}v2/`,
|
|
||||||
rel: "self"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
status: "SUPPORTED",
|
status: "SUPPORTED",
|
||||||
id: "v1.1",
|
id: "v1.1",
|
||||||
|
|
|
@ -15,43 +15,6 @@ describe('Keystone', () => {
|
||||||
expect(() => new Keystone()).toThrow();
|
expect(() => new Keystone()).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("versions()", () => {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keystone needs an explicit test, as it uses a slightly different data format
|
|
||||||
* than other services.
|
|
||||||
*/
|
|
||||||
it("Should return a list of all versions available on this clouds' keystone", (done) => {
|
|
||||||
const keystone = new Keystone(mockData.config);
|
|
||||||
|
|
||||||
fetchMock.mock(mockData.root());
|
|
||||||
|
|
||||||
keystone.versions()
|
|
||||||
.then((versions) => {
|
|
||||||
// Quick sanity check.
|
|
||||||
expect(versions.length).toBe(2);
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch((error) => done.fail(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("version()", () => {
|
|
||||||
|
|
||||||
it("Should return a supported version of the keystone API.", (done) => {
|
|
||||||
const keystone = new Keystone(mockData.config);
|
|
||||||
|
|
||||||
fetchMock.mock(mockData.root());
|
|
||||||
|
|
||||||
keystone.version()
|
|
||||||
.then((version) => {
|
|
||||||
expect(version.id).toEqual('v3.7');
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch((error) => done.fail(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("serviceEndpoint()", () => {
|
describe("serviceEndpoint()", () => {
|
||||||
it("Should return a valid endpoint to the keystone API.", (done) => {
|
it("Should return a valid endpoint to the keystone API.", (done) => {
|
||||||
const keystone = new Keystone(mockData.config);
|
const keystone = new Keystone(mockData.config);
|
||||||
|
|
|
@ -36,22 +36,6 @@ describe('neutron', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("versions()", () => {
|
|
||||||
it("Should return a list of all versions available on this clouds' NEUTRON", (done) => {
|
|
||||||
const neutron = new Neutron(mockData.config);
|
|
||||||
|
|
||||||
fetchMock.mock(mockData.root());
|
|
||||||
|
|
||||||
neutron.versions()
|
|
||||||
.then((versions) => {
|
|
||||||
// Quick sanity check.
|
|
||||||
expect(versions.length).toBe(1);
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch((error) => done.fail(error));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("networkList()", () => {
|
describe("networkList()", () => {
|
||||||
let neutron = null;
|
let neutron = null;
|
||||||
|
|
||||||
|
|
|
@ -53,21 +53,12 @@ describe('AbstractService', () => {
|
||||||
service.versions()
|
service.versions()
|
||||||
.then((versions) => {
|
.then((versions) => {
|
||||||
// Quick sanity check.
|
// Quick sanity check.
|
||||||
expect(versions.length).toBe(6);
|
expect(versions.length).toBe(5);
|
||||||
done();
|
expect(versions[0].major).toEqual(2);
|
||||||
})
|
expect(versions[0].minor).toEqual(3);
|
||||||
.catch((error) => done.fail(error));
|
expect(versions[0].patch).toEqual(0);
|
||||||
});
|
expect(versions[0].links).not.toBe(null);
|
||||||
|
expect(versions[0].links[0].href).toEqual('http://example.com/v2/');
|
||||||
it("Should return a list of all versions available from this resource", (done) => {
|
|
||||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
|
||||||
|
|
||||||
fetchMock.mock(mockData.rootResponse());
|
|
||||||
|
|
||||||
service.versions()
|
|
||||||
.then((versions) => {
|
|
||||||
// Quick sanity check.
|
|
||||||
expect(versions.length).toBe(6);
|
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch((error) => done.fail(error));
|
.catch((error) => done.fail(error));
|
||||||
|
@ -84,7 +75,7 @@ describe('AbstractService', () => {
|
||||||
service.versions()
|
service.versions()
|
||||||
.then((versions) => {
|
.then((versions) => {
|
||||||
// Quick sanity check.
|
// Quick sanity check.
|
||||||
expect(versions.length).toBe(6);
|
expect(versions.length).toBe(5);
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch((error) => done.fail(error));
|
.catch((error) => done.fail(error));
|
||||||
|
@ -132,7 +123,22 @@ describe('AbstractService', () => {
|
||||||
|
|
||||||
service.version()
|
service.version()
|
||||||
.then((version) => {
|
.then((version) => {
|
||||||
expect(version.id).toEqual('v2.3');
|
expect(version.equals('v2.3')).toBe(true);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch((error) => done.fail(error));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return the latest compatible version of the service API.", (done) => {
|
||||||
|
const service = new AbstractService(mockData.rootUrl, [
|
||||||
|
'v2.0'
|
||||||
|
]);
|
||||||
|
|
||||||
|
fetchMock.mock(mockData.rootResponse());
|
||||||
|
|
||||||
|
service.version()
|
||||||
|
.then((version) => {
|
||||||
|
expect(version.equals('v2.3')).toBe(true);
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch((error) => done.fail(error));
|
.catch((error) => done.fail(error));
|
||||||
|
|
|
@ -96,4 +96,63 @@ describe('Version', () => {
|
||||||
// Other tests...
|
// Other tests...
|
||||||
expect(v2.equals({})).toBe(false);
|
expect(v2.equals({})).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should test for correct compatibility", () => {
|
||||||
|
const v1 = new Version("compute", "1.3.2");
|
||||||
|
|
||||||
|
// String tests
|
||||||
|
expect(v1.supports("compute 1.0.0")).toBe(true);
|
||||||
|
expect(v1.supports("compute 1.0.1")).toBe(true);
|
||||||
|
expect(v1.supports("compute 1.3.0")).toBe(true);
|
||||||
|
expect(v1.supports("compute 1.3.3")).toBe(false);
|
||||||
|
expect(v1.supports("compute 1.4.0")).toBe(false);
|
||||||
|
expect(v1.supports("compute 2.3.0")).toBe(false);
|
||||||
|
|
||||||
|
// Version tests
|
||||||
|
expect(v1.supports(new Version("compute", "1.0.0"))).toBe(true);
|
||||||
|
expect(v1.supports(new Version("compute", "1.0.1"))).toBe(true);
|
||||||
|
expect(v1.supports(new Version("compute", "1.3.0"))).toBe(true);
|
||||||
|
expect(v1.supports(new Version("compute", "1.3.3"))).toBe(false);
|
||||||
|
expect(v1.supports(new Version("compute", "1.4.0"))).toBe(false);
|
||||||
|
expect(v1.supports(new Version("compute", "2.3.0"))).toBe(false);
|
||||||
|
|
||||||
|
const v2 = new Version("1.3.2");
|
||||||
|
// String tests
|
||||||
|
expect(v2.supports("1.0.0")).toBe(true);
|
||||||
|
expect(v2.supports("1.0.1")).toBe(true);
|
||||||
|
expect(v2.supports("1.3.0")).toBe(true);
|
||||||
|
expect(v2.supports("1.3.3")).toBe(false);
|
||||||
|
expect(v2.supports("1.4.0")).toBe(false);
|
||||||
|
expect(v2.supports("2.3.0")).toBe(false);
|
||||||
|
|
||||||
|
// Version tests
|
||||||
|
expect(v2.supports(new Version("1.0.0"))).toBe(true);
|
||||||
|
expect(v2.supports(new Version("1.0.1"))).toBe(true);
|
||||||
|
expect(v2.supports(new Version("1.3.0"))).toBe(true);
|
||||||
|
expect(v2.supports(new Version("1.3.3"))).toBe(false);
|
||||||
|
expect(v2.supports(new Version("1.4.0"))).toBe(false);
|
||||||
|
expect(v2.supports(new Version("2.3.0"))).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should store links", () => {
|
||||||
|
const v1 = new Version("compute", "1.3.2");
|
||||||
|
|
||||||
|
expect(v1.links).toBe(null);
|
||||||
|
|
||||||
|
v1.links = 'wrong data';
|
||||||
|
expect(v1.links).toBe(null);
|
||||||
|
|
||||||
|
v1.links = [
|
||||||
|
{
|
||||||
|
href: `http://example.org/v2/`,
|
||||||
|
rel: "self"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
expect(v1.links).not.toBe(null);
|
||||||
|
expect(v1.links.length).toBe(1);
|
||||||
|
expect(v1.links[0]).toEqual({
|
||||||
|
href: "http://example.org/v2/",
|
||||||
|
rel: "self"
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue