Update eslint and switch to standard
The openstack eslint package is just really not needed at this point. Use standardjs and run --fix on it. Switch away from using node 8 to run linters and tests. Change-Id: I51f68d4ec30c8da5d1601ef00045e53f90d0554b
This commit is contained in:
parent
7f843d7ecb
commit
346f7eeda0
20
.eslintrc
20
.eslintrc
|
@ -1,6 +1,16 @@
|
|||
extends: openstack/es2015
|
||||
|
||||
parser: babel-eslint
|
||||
plugins:
|
||||
- standard
|
||||
rules:
|
||||
space-before-function-paren:
|
||||
- 2
|
||||
- never
|
||||
no-var: error
|
||||
no-console: off
|
||||
semi: [error, never]
|
||||
quotes: [error, single]
|
||||
lines-between-class-members: error
|
||||
extends:
|
||||
- eslint:recommended
|
||||
env:
|
||||
browser: true
|
||||
es6: true
|
||||
jasmine: true
|
||||
node: true
|
||||
|
|
|
@ -1,27 +1,26 @@
|
|||
/*eslint no-process-env: "off" */
|
||||
import fs from 'fs';
|
||||
import karma from 'karma/lib/config';
|
||||
import path from 'path';
|
||||
/* eslint no-process-env: "off" */
|
||||
import fs from 'fs'
|
||||
import karma from 'karma/lib/config'
|
||||
import path from 'path'
|
||||
|
||||
function getDevstackConfig() {
|
||||
const karmaConfig = karma.parseConfig(path.resolve('./karma.conf.js'));
|
||||
function getDevstackConfig () {
|
||||
const karmaConfig = karma.parseConfig(path.resolve('./karma.conf.js'))
|
||||
|
||||
return getCorsConfig('$KEYSTONE_CONF', karmaConfig) +
|
||||
getCorsConfig('$GLANCE_API_CONF', karmaConfig) +
|
||||
getCorsConfig('$NEUTRON_CONF', karmaConfig) +
|
||||
getCorsConfig('$NOVA_CONF', karmaConfig);
|
||||
|
||||
getCorsConfig('$NOVA_CONF', karmaConfig)
|
||||
}
|
||||
|
||||
function getCorsConfig(service, karmaConfig) {
|
||||
function getCorsConfig (service, karmaConfig) {
|
||||
return `[[post-config|${service}]]
|
||||
[cors]
|
||||
allowed_origin=http://localhost:${karmaConfig.port}
|
||||
`;
|
||||
`
|
||||
}
|
||||
|
||||
fs.appendFile(process.env.BASE + '/new/devstack/local.conf', getDevstackConfig(), (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import webpackConfig from './webpack.config.babel';
|
||||
import path from 'path';
|
||||
import webpackConfig from './webpack.config.babel'
|
||||
import path from 'path'
|
||||
|
||||
export default (config) => {
|
||||
// test mode based on basePath parameter (eg. test/unit, test/functional)
|
||||
const testDir = config.basePath ? path.basename(config.basePath) : 'unit';
|
||||
const testDir = config.basePath ? path.basename(config.basePath) : 'unit'
|
||||
|
||||
config.set({
|
||||
|
||||
|
@ -69,9 +69,9 @@ export default (config) => {
|
|||
|
||||
// Generate a coverage report in /cover/karma
|
||||
coverageReporter: {
|
||||
type: 'html', //produces a html document after code is run
|
||||
dir: '../../cover/' + testDir + '/browser/' //path to created html doc
|
||||
},
|
||||
type: 'html', // produces a html document after code is run
|
||||
dir: '../../cover/' + testDir + '/browser/' // path to created html doc
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require('@babel/register');
|
||||
module.exports = require('./karma.conf.babel').default;
|
||||
require('@babel/register')
|
||||
module.exports = require('./karma.conf.babel').default
|
||||
|
|
|
@ -41,11 +41,12 @@
|
|||
"@babel/preset-env": "^7.0.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-plugin-istanbul": "^6.0.0",
|
||||
"babel-plugin-transform-inline-environment-variables": "^6.8.0",
|
||||
"eslint": "^3.0.0",
|
||||
"eslint-config-openstack": "4.0.1",
|
||||
"eslint": "^7.1.0",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"fetch-mock": "^5.0.5",
|
||||
"jasmine": "^3.5.0",
|
||||
"js-yaml": "^3.14.0",
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* the License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import AbstractService from './util/abstractService';
|
||||
import AbstractService from './util/abstractService'
|
||||
|
||||
/**
|
||||
* A list of all supported versions. Please keep this array sorted by most recent.
|
||||
|
@ -23,10 +23,9 @@ import AbstractService from './util/abstractService';
|
|||
*/
|
||||
const supportedGlanceVersions = [
|
||||
'v2.3'
|
||||
];
|
||||
]
|
||||
|
||||
export default class Glance extends AbstractService {
|
||||
|
||||
/**
|
||||
* This class provides direct, idempotent, low-level access to the Glance API of a specific
|
||||
* cloud. The constructor requires that you provide a specific glance interface endpoint
|
||||
|
@ -42,17 +41,17 @@ export default class Glance extends AbstractService {
|
|||
* }
|
||||
* @param {{}} endpointConfig The configuration element for a specific glance endpoint.
|
||||
*/
|
||||
constructor(endpointConfig) {
|
||||
constructor (endpointConfig) {
|
||||
// Sanity checks.
|
||||
if (!endpointConfig || !endpointConfig.url) {
|
||||
throw new Error('An endpoint configuration is required.');
|
||||
throw new Error('An endpoint configuration is required.')
|
||||
}
|
||||
// Clone the config, so that this instance is immutable
|
||||
// at runtime (no modifying the config after the fact).
|
||||
endpointConfig = Object.assign({}, endpointConfig);
|
||||
endpointConfig = Object.assign({}, endpointConfig)
|
||||
|
||||
super(endpointConfig.url, supportedGlanceVersions);
|
||||
this._config = endpointConfig;
|
||||
super(endpointConfig.url, supportedGlanceVersions)
|
||||
this._config = endpointConfig
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,11 +61,11 @@ export default class Glance extends AbstractService {
|
|||
* into one.
|
||||
* @returns {Promise.<T>} A promise which will resolve with the list of images.
|
||||
*/
|
||||
imageList(token = null) {
|
||||
imageList (token = null) {
|
||||
return this
|
||||
._requestComponents(token)
|
||||
.then(([url, headers]) => this.http.httpRequest('GET', `${url}images`, headers))
|
||||
.then((response) => response.json())
|
||||
.then((body) => body.images);
|
||||
.then((body) => body.images)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export {default as Keystone} from './keystone';
|
||||
export {default as Glance} from './glance';
|
||||
export {default as Neutron} from './neutron';
|
||||
export {default as OpenStack} from './openstack';
|
||||
export { default as Keystone } from './keystone'
|
||||
export { default as Glance } from './glance'
|
||||
export { default as Neutron } from './neutron'
|
||||
export { default as OpenStack } from './openstack'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import AbstractService from './util/abstractService';
|
||||
import AbstractService from './util/abstractService'
|
||||
|
||||
/**
|
||||
* A list of all supported versions. Please keep this array sorted by most recent.
|
||||
|
@ -8,10 +8,9 @@ import AbstractService from './util/abstractService';
|
|||
*/
|
||||
const supportedKeystoneVersions = [
|
||||
'v3.1'
|
||||
];
|
||||
]
|
||||
|
||||
export default class Keystone extends AbstractService {
|
||||
|
||||
/**
|
||||
* This class provides direct, idempotent, low-level access to the Keystone API of a specific
|
||||
* cloud. The constructor requires that you provide a configuration object for a specific
|
||||
|
@ -22,17 +21,17 @@ export default class Keystone extends AbstractService {
|
|||
* @param {{}} cloudConfig The configuration object for a specific cloud.
|
||||
* @see http://docs.openstack.org/developer/os-client-config/#site-specific-file-locations
|
||||
*/
|
||||
constructor(cloudConfig) {
|
||||
constructor (cloudConfig) {
|
||||
// Sanity checks.
|
||||
if (!cloudConfig) {
|
||||
throw new Error('A configuration is required.');
|
||||
throw new Error('A configuration is required.')
|
||||
}
|
||||
// Clone the config, so that this instance is immutable
|
||||
// at runtime (no modifying the config after the fact).
|
||||
cloudConfig = Object.assign({}, cloudConfig);
|
||||
cloudConfig = Object.assign({}, cloudConfig)
|
||||
|
||||
super(cloudConfig.auth.auth_url, supportedKeystoneVersions);
|
||||
this.cloudConfig = cloudConfig;
|
||||
super(cloudConfig.auth.auth_url, supportedKeystoneVersions)
|
||||
this.cloudConfig = cloudConfig
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,18 +43,18 @@ export default class Keystone extends AbstractService {
|
|||
* @returns {String} The value found in the config, or null.
|
||||
* @ignore
|
||||
*/
|
||||
_safeConfigGet(path) {
|
||||
let segments = path.split('.');
|
||||
let pointer = this.cloudConfig;
|
||||
_safeConfigGet (path) {
|
||||
const segments = path.split('.')
|
||||
let pointer = this.cloudConfig
|
||||
while (segments.length > 0) {
|
||||
let prop = segments.shift();
|
||||
if (pointer.hasOwnProperty(prop)) {
|
||||
pointer = pointer[prop];
|
||||
const prop = segments.shift()
|
||||
if (Object.prototype.hasOwnProperty.call(pointer, prop)) {
|
||||
pointer = pointer[prop]
|
||||
} else {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
}
|
||||
return pointer;
|
||||
return pointer
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,9 +63,9 @@ export default class Keystone extends AbstractService {
|
|||
* @returns {Promise.<Object[]>} A promise that will resolve with the list of raw versions.
|
||||
* @protected
|
||||
*/
|
||||
_rawVersions() {
|
||||
_rawVersions () {
|
||||
return super._rawVersions()
|
||||
.then((versions) => versions.values);
|
||||
.then((versions) => versions.values)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,7 +91,7 @@ export default class Keystone extends AbstractService {
|
|||
* Not required if a project ID is given.
|
||||
* @returns {Promise.<T>} A promise which will resolve with a valid token.
|
||||
*/
|
||||
tokenIssue({
|
||||
tokenIssue ({
|
||||
user_id: userId = this._safeConfigGet('auth.user_id'),
|
||||
username = this._safeConfigGet('auth.username'),
|
||||
password = this._safeConfigGet('auth.password'),
|
||||
|
@ -103,32 +102,32 @@ export default class Keystone extends AbstractService {
|
|||
project_domain_id: projectDomainId = this._safeConfigGet('auth.project_domain_id'),
|
||||
project_domain_name: projectDomainName = this._safeConfigGet('auth.project_domain_name')
|
||||
} = {}) {
|
||||
let project;
|
||||
let user = {password};
|
||||
let project
|
||||
const user = { password }
|
||||
|
||||
if (userId) {
|
||||
user.id = userId;
|
||||
user.id = userId
|
||||
} else if (username) {
|
||||
user.name = username;
|
||||
user.name = username
|
||||
if (userDomainId) {
|
||||
user.domain = {id: userDomainId};
|
||||
user.domain = { id: userDomainId }
|
||||
} else if (userDomainName) {
|
||||
user.domain = {name: userDomainName};
|
||||
user.domain = { name: userDomainName }
|
||||
} else {
|
||||
user.domain = {id: 'default'};
|
||||
user.domain = { id: 'default' }
|
||||
}
|
||||
}
|
||||
|
||||
if (projectId) {
|
||||
project = {id: projectId};
|
||||
project = { id: projectId }
|
||||
} else if (projectName) {
|
||||
project = {name: projectName};
|
||||
project = { name: projectName }
|
||||
if (projectDomainId) {
|
||||
project.domain = {id: projectDomainId};
|
||||
project.domain = { id: projectDomainId }
|
||||
} else if (projectDomainName) {
|
||||
project.domain = {name: projectDomainName};
|
||||
project.domain = { name: projectDomainName }
|
||||
} else {
|
||||
project.domain = {id: 'default'};
|
||||
project.domain = { id: 'default' }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,18 +135,18 @@ export default class Keystone extends AbstractService {
|
|||
auth: {
|
||||
identity: {
|
||||
methods: ['password'],
|
||||
password: {user}
|
||||
password: { user }
|
||||
},
|
||||
scope: project ? {project} : 'unscoped'
|
||||
scope: project ? { project } : 'unscoped'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return this
|
||||
.serviceEndpoint()
|
||||
.then((url) => this.http.httpPost(`${url}auth/tokens`, body))
|
||||
.then((response) => {
|
||||
return response.headers.get('X-Subject-Token');
|
||||
});
|
||||
return response.headers.get('X-Subject-Token')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,16 +156,16 @@ export default class Keystone extends AbstractService {
|
|||
* @param {String} adminToken An optional admin token.
|
||||
* @returns {Promise.<T>} A promise which will resolve if the token has been successfully revoked.
|
||||
*/
|
||||
tokenRevoke(token, adminToken = null) {
|
||||
tokenRevoke (token, adminToken = null) {
|
||||
return Promise
|
||||
.all([this.serviceEndpoint(), token, adminToken])
|
||||
.then(([url, token, adminToken]) => {
|
||||
return [url, {
|
||||
'X-Subject-Token': token,
|
||||
'X-Auth-Token': adminToken || token
|
||||
}];
|
||||
}]
|
||||
})
|
||||
.then(([url, headers]) => this.http.httpRequest('DELETE', `${url}auth/tokens`, headers));
|
||||
.then(([url, headers]) => this.http.httpRequest('DELETE', `${url}auth/tokens`, headers))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,17 +174,17 @@ export default class Keystone extends AbstractService {
|
|||
* @param {String} token The authorization token.
|
||||
* @returns {Promise.<T>} A promise which will resolve with information about the token.
|
||||
*/
|
||||
tokenInfo(token) {
|
||||
tokenInfo (token) {
|
||||
return Promise
|
||||
.all([this.serviceEndpoint(), token])
|
||||
.then(([url, token]) => {
|
||||
return [url, {
|
||||
'X-Subject-Token': token,
|
||||
'X-Auth-Token': token
|
||||
}];
|
||||
}]
|
||||
})
|
||||
.then(([url, headers]) => this.http.httpRequest('GET', `${url}auth/tokens`, headers))
|
||||
.then((response) => response.json());
|
||||
.then((response) => response.json())
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -194,11 +193,11 @@ export default class Keystone extends AbstractService {
|
|||
* @param {String} token The authorization token.
|
||||
* @returns {Promise.<T>} A promise which will resolve with the service catalog.
|
||||
*/
|
||||
catalogList(token = null) {
|
||||
catalogList (token = null) {
|
||||
return this
|
||||
._requestComponents(token)
|
||||
.then(([url, headers]) => this.http.httpRequest('GET', `${url}auth/catalog`, headers))
|
||||
.then((response) => response.json())
|
||||
.then((body) => body.catalog);
|
||||
.then((body) => body.catalog)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* the License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import AbstractService from './util/abstractService';
|
||||
import AbstractService from './util/abstractService'
|
||||
|
||||
/**
|
||||
* A list of all supported versions. Please keep this array sorted by most recent.
|
||||
|
@ -23,10 +23,9 @@ import AbstractService from './util/abstractService';
|
|||
*/
|
||||
const supportedNeutronVersions = [
|
||||
'v2.0'
|
||||
];
|
||||
]
|
||||
|
||||
export default class Neutron extends AbstractService {
|
||||
|
||||
/**
|
||||
* This class provides direct, idempotent, low-level access to the Neutron API of a specific
|
||||
* cloud. The constructor requires that you provide a specific neutron interface endpoint
|
||||
|
@ -42,16 +41,16 @@ export default class Neutron extends AbstractService {
|
|||
* }
|
||||
* @param {{}} endpointConfig The configuration element for a specific glance endpoint.
|
||||
*/
|
||||
constructor(endpointConfig) {
|
||||
constructor (endpointConfig) {
|
||||
// Sanity checks.
|
||||
if (!endpointConfig || !endpointConfig.url) {
|
||||
throw new Error('An endpoint configuration is required.');
|
||||
throw new Error('An endpoint configuration is required.')
|
||||
}
|
||||
// Clone the config, so that this instance is immutable
|
||||
// at runtime (no modifying the config after the fact).
|
||||
endpointConfig = Object.assign({}, endpointConfig);
|
||||
endpointConfig = Object.assign({}, endpointConfig)
|
||||
|
||||
super(endpointConfig.url, supportedNeutronVersions);
|
||||
super(endpointConfig.url, supportedNeutronVersions)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,11 +59,11 @@ export default class Neutron extends AbstractService {
|
|||
* @param {String} token An authorization token, or a promise which will resolve into one.
|
||||
* @returns {Promise.<T>} A promise which will resolve with the list of networks.
|
||||
*/
|
||||
networkList(token = null) {
|
||||
networkList (token = null) {
|
||||
return this
|
||||
._requestComponents(token)
|
||||
.then(([url, headers]) => this.http.httpRequest('GET', `${url}/networks`, headers))
|
||||
.then((response) => response.json())
|
||||
.then((body) => body.networks);
|
||||
.then((body) => body.networks)
|
||||
}
|
||||
}
|
||||
|
|
19
src/nova.js
19
src/nova.js
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import AbstractService from "./util/abstractService";
|
||||
import AbstractService from './util/abstractService'
|
||||
|
||||
/**
|
||||
* A list of all supported versions. Please keep this array sorted by most recent.
|
||||
|
@ -24,10 +24,9 @@ import AbstractService from "./util/abstractService";
|
|||
*/
|
||||
const supportedNovaVersions = [
|
||||
'v2.1'
|
||||
];
|
||||
]
|
||||
|
||||
export default class Nova extends AbstractService {
|
||||
|
||||
/**
|
||||
* This class provides direct, idempotent, low-level access to the Nova API of a specific
|
||||
* cloud. The constructor requires that you provide a specific nova interface endpoint
|
||||
|
@ -43,17 +42,17 @@ export default class Nova extends AbstractService {
|
|||
* }
|
||||
* @param {{}} endpointConfig The configuration element for a specific nova endpoint.
|
||||
*/
|
||||
constructor(endpointConfig) {
|
||||
constructor (endpointConfig) {
|
||||
// Sanity checks.
|
||||
if (!endpointConfig || !endpointConfig.url) {
|
||||
throw new Error('An endpoint configuration is required.');
|
||||
throw new Error('An endpoint configuration is required.')
|
||||
}
|
||||
// Clone the config, so that this instance is immutable
|
||||
// at runtime (no modifying the config after the fact).
|
||||
endpointConfig = Object.assign({}, endpointConfig);
|
||||
endpointConfig = Object.assign({}, endpointConfig)
|
||||
|
||||
super(endpointConfig.url, supportedNovaVersions);
|
||||
this._config = endpointConfig;
|
||||
super(endpointConfig.url, supportedNovaVersions)
|
||||
this._config = endpointConfig
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,11 +61,11 @@ export default class Nova extends AbstractService {
|
|||
* @param {String} token An authorization token, or a promise which will resolve into one.
|
||||
* @returns {Promise.<T>} A promise which will resolve with the list of flavors.
|
||||
*/
|
||||
flavorList(token = null) {
|
||||
flavorList (token = null) {
|
||||
return this
|
||||
._requestComponents(token)
|
||||
.then(([url, headers]) => this.http.httpRequest('GET', `${url}flavors`, headers))
|
||||
.then((response) => response.json())
|
||||
.then((body) => body.flavors);
|
||||
.then((body) => body.flavors)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Keystone from "./keystone";
|
||||
import Neutron from "./neutron";
|
||||
import Glance from "./glance";
|
||||
import Nova from "./nova";
|
||||
import Keystone from './keystone'
|
||||
import Neutron from './neutron'
|
||||
import Glance from './glance'
|
||||
import Nova from './nova'
|
||||
|
||||
export default class OpenStack {
|
||||
/**
|
||||
|
@ -9,21 +9,21 @@ export default class OpenStack {
|
|||
*
|
||||
* @param {{}} cloudConfig The configuration object for a specific cloud.
|
||||
*/
|
||||
constructor(cloudConfig) {
|
||||
constructor (cloudConfig) {
|
||||
// Sanity checks.
|
||||
if (!cloudConfig) {
|
||||
throw new Error('A configuration is required.');
|
||||
throw new Error('A configuration is required.')
|
||||
}
|
||||
// Clone the config, so that this instance is immutable
|
||||
// at runtime (no modifying the config after the fact).
|
||||
cloudConfig = Object.assign({}, cloudConfig);
|
||||
cloudConfig = Object.assign({}, cloudConfig)
|
||||
|
||||
this.cloudConfig = cloudConfig;
|
||||
this.cloudConfig = cloudConfig
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
getConfig () {
|
||||
// Returns the config instance
|
||||
return this.cloudConfig;
|
||||
return this.cloudConfig
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,9 +31,9 @@ export default class OpenStack {
|
|||
*
|
||||
* @returns {Promise.<T>} A promise which will resolve with the list of networks.
|
||||
*/
|
||||
networkList() {
|
||||
networkList () {
|
||||
return this._neutron
|
||||
.then((neutron) => neutron.networkList(this._token));
|
||||
.then((neutron) => neutron.networkList(this._token))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,9 +41,9 @@ export default class OpenStack {
|
|||
*
|
||||
* @returns {Promise.<T>} A promise which will resolve with the list of images.
|
||||
*/
|
||||
imageList() {
|
||||
imageList () {
|
||||
return this._glance
|
||||
.then((glance) => glance.imageList(this._token));
|
||||
.then((glance) => glance.imageList(this._token))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,9 +51,9 @@ export default class OpenStack {
|
|||
*
|
||||
* @returns {Promise.<T>} A promise which will resolve with the list of flavors.
|
||||
*/
|
||||
flavorList() {
|
||||
flavorList () {
|
||||
return this._nova
|
||||
.then((nova) => nova.flavorList(this._token));
|
||||
.then((nova) => nova.flavorList(this._token))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,12 +62,12 @@ export default class OpenStack {
|
|||
* @returns {Promise.<Keystone>} A promise which will resolve with Keystone instance.
|
||||
* @private
|
||||
*/
|
||||
get _keystone() {
|
||||
get _keystone () {
|
||||
if (!this._keystonePromise) {
|
||||
this._keystonePromise = Promise.resolve(new Keystone(this.getConfig()));
|
||||
this._keystonePromise = Promise.resolve(new Keystone(this.getConfig()))
|
||||
}
|
||||
|
||||
return this._keystonePromise;
|
||||
return this._keystonePromise
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,12 +76,12 @@ export default class OpenStack {
|
|||
* @returns {Promise.<Neutron>} A promise which will resolve with Neutron instance.
|
||||
* @private
|
||||
*/
|
||||
get _neutron() {
|
||||
get _neutron () {
|
||||
if (!this._neutronPromise) {
|
||||
this._neutronPromise = this._getComponentConfigFor('neutron')
|
||||
.then((componentConfig) => new Neutron(componentConfig));
|
||||
.then((componentConfig) => new Neutron(componentConfig))
|
||||
}
|
||||
return this._neutronPromise;
|
||||
return this._neutronPromise
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,12 +90,12 @@ export default class OpenStack {
|
|||
* @returns {Promise.<Glance>} A promise which will resolve with Glance instance.
|
||||
* @private
|
||||
*/
|
||||
get _glance() {
|
||||
get _glance () {
|
||||
if (!this._glancePromise) {
|
||||
this._glancePromise = this._getComponentConfigFor('glance')
|
||||
.then((componentConfig) => new Glance(componentConfig));
|
||||
.then((componentConfig) => new Glance(componentConfig))
|
||||
}
|
||||
return this._glancePromise;
|
||||
return this._glancePromise
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,12 +104,12 @@ export default class OpenStack {
|
|||
* @returns {Promise.<Nova>} A promise which will resolve with Nova instance.
|
||||
* @private
|
||||
*/
|
||||
get _nova() {
|
||||
get _nova () {
|
||||
if (!this._novaPromise) {
|
||||
this._novaPromise = this._getComponentConfigFor('nova')
|
||||
.then((componentConfig) => new Nova(componentConfig));
|
||||
.then((componentConfig) => new Nova(componentConfig))
|
||||
}
|
||||
return this._novaPromise;
|
||||
return this._novaPromise
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,11 +118,11 @@ export default class OpenStack {
|
|||
* @returns {Promise.<T>} A promise which will resolve with the token.
|
||||
* @private
|
||||
*/
|
||||
get _token() {
|
||||
get _token () {
|
||||
if (!this._tokenPromise) {
|
||||
this._tokenPromise = this._keystone.then((k) => k.tokenIssue());
|
||||
this._tokenPromise = this._keystone.then((k) => k.tokenIssue())
|
||||
}
|
||||
return this._tokenPromise;
|
||||
return this._tokenPromise
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,14 +132,13 @@ export default class OpenStack {
|
|||
* @returns {Promise.<{}>} A promise which will resolve with the component config.
|
||||
* @private
|
||||
*/
|
||||
_getComponentConfigFor(name) {
|
||||
const config = this.getConfig();
|
||||
_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) => {
|
||||
return endpoint.region === config.region_name && endpoint.interface === 'public';
|
||||
}));
|
||||
return endpoint.region === config.region_name && endpoint.interface === 'public'
|
||||
}))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,12 +14,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Http from './http';
|
||||
import Version from './version';
|
||||
import URL from 'url-parse';
|
||||
import Http from './http'
|
||||
import Version from './version'
|
||||
import URL from 'url-parse'
|
||||
|
||||
export default class AbstractService {
|
||||
|
||||
/**
|
||||
* This class provides an abstract implementation of our services, which includes logic common to
|
||||
* all of our services.
|
||||
|
@ -27,9 +26,9 @@ export default class AbstractService {
|
|||
* @param {string} endpointUrl The endpoint URL.
|
||||
* @param {Array} supportedVersions The list of all supported versions.
|
||||
*/
|
||||
constructor(endpointUrl, supportedVersions) {
|
||||
this._endpointUrl = endpointUrl;
|
||||
this._supportedVersions = supportedVersions;
|
||||
constructor (endpointUrl, supportedVersions) {
|
||||
this._endpointUrl = endpointUrl
|
||||
this._supportedVersions = supportedVersions
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,11 +36,11 @@ export default class AbstractService {
|
|||
*
|
||||
* @returns {Http} Our HTTP service instance.
|
||||
*/
|
||||
get http() {
|
||||
get http () {
|
||||
if (!this._http) {
|
||||
this._http = new Http();
|
||||
this._http = new Http()
|
||||
}
|
||||
return this._http;
|
||||
return this._http
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,8 +48,8 @@ export default class AbstractService {
|
|||
*
|
||||
* @returns {Array} The list of all supported versions, or empty array.
|
||||
*/
|
||||
get supportedVersions() {
|
||||
return this._supportedVersions || [];
|
||||
get supportedVersions () {
|
||||
return this._supportedVersions || []
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,8 +57,8 @@ export default class AbstractService {
|
|||
*
|
||||
* @returns {string} The URL of our service.
|
||||
*/
|
||||
get endpointUrl() {
|
||||
return this._endpointUrl;
|
||||
get endpointUrl () {
|
||||
return this._endpointUrl
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,14 +66,14 @@ export default class AbstractService {
|
|||
*
|
||||
* @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;
|
||||
});
|
||||
});
|
||||
const version = new Version(rawVersion.id)
|
||||
version.links = rawVersion.links
|
||||
return version
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,26 +82,26 @@ export default class AbstractService {
|
|||
* @returns {Promise.<Object[]>} A promise that will resolve with the list of raw versions.
|
||||
* @protected
|
||||
*/
|
||||
_rawVersions() {
|
||||
_rawVersions () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.http
|
||||
.httpGet(this._endpointUrl)
|
||||
.catch((response) => {
|
||||
if (response.status === 401) {
|
||||
let rootUrl = new URL(this._endpointUrl);
|
||||
rootUrl.set('pathname', '/');
|
||||
rootUrl.set('query', '');
|
||||
rootUrl.set('hash', '');
|
||||
const rootUrl = new URL(this._endpointUrl)
|
||||
rootUrl.set('pathname', '/')
|
||||
rootUrl.set('query', '')
|
||||
rootUrl.set('hash', '')
|
||||
|
||||
return this.http.httpGet(rootUrl.href);
|
||||
return this.http.httpGet(rootUrl.href)
|
||||
} else {
|
||||
throw response;
|
||||
throw response
|
||||
}
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((body) => resolve(body.versions))
|
||||
.catch(reject);
|
||||
});
|
||||
.catch(reject)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,17 +109,17 @@ export default class AbstractService {
|
|||
*
|
||||
* @returns {Promise.<Version>} A promise that will resolve with the specific API version.
|
||||
*/
|
||||
version() {
|
||||
version () {
|
||||
return this
|
||||
.versions()
|
||||
.then((versions) => {
|
||||
for (let version of versions) {
|
||||
for (const version of versions) {
|
||||
if (this.supportedVersions.find(version.supports)) {
|
||||
return version;
|
||||
return version
|
||||
}
|
||||
}
|
||||
throw new Error("No supported API version available.");
|
||||
});
|
||||
throw new Error('No supported API version available.')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,22 +127,22 @@ export default class AbstractService {
|
|||
*
|
||||
* @returns {Promise.<T>|*} A promise which will resolve with the endpoint URL string.
|
||||
*/
|
||||
serviceEndpoint() {
|
||||
serviceEndpoint () {
|
||||
if (!this._endpointPromise) {
|
||||
this._endpointPromise = this.version()
|
||||
.then((version) => {
|
||||
if (version.links) {
|
||||
for (let i = 0; i < version.links.length; i++) {
|
||||
let link = version.links[i];
|
||||
const link = version.links[i]
|
||||
if (link.rel === 'self' && link.href) {
|
||||
return link.href;
|
||||
return link.href
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error("No service endpoint discovered.");
|
||||
});
|
||||
throw new Error('No service endpoint discovered.')
|
||||
})
|
||||
}
|
||||
return this._endpointPromise;
|
||||
return this._endpointPromise
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,18 +154,18 @@ export default class AbstractService {
|
|||
* @returns {Promise} A promise which resolves with [url, token].
|
||||
* @private
|
||||
*/
|
||||
_requestComponents(token = null) {
|
||||
_requestComponents (token = null) {
|
||||
// Make sure the token is a promise.
|
||||
let headerPromise = Promise
|
||||
const headerPromise = Promise
|
||||
.resolve(token)
|
||||
.then((token) => {
|
||||
if (token) {
|
||||
return {
|
||||
'X-Auth-Token': token
|
||||
};
|
||||
}
|
||||
return {};
|
||||
});
|
||||
return Promise.all([this.serviceEndpoint(), headerPromise]);
|
||||
}
|
||||
return {}
|
||||
})
|
||||
return Promise.all([this.serviceEndpoint(), headerPromise])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import 'isomorphic-fetch';
|
||||
import log from 'loglevel';
|
||||
import 'isomorphic-fetch'
|
||||
import log from 'loglevel'
|
||||
|
||||
/**
|
||||
* This utility class provides an abstraction layer for HTTP calls via fetch(). Its purpose is
|
||||
|
@ -33,7 +33,6 @@ import log from 'loglevel';
|
|||
* - Other features.
|
||||
*/
|
||||
export default class Http {
|
||||
|
||||
/**
|
||||
* The default headers which will be sent with every request. A copy of these headers will be
|
||||
* added to the Request instance passed through the interceptor chain, and may be
|
||||
|
@ -41,18 +40,18 @@ export default class Http {
|
|||
*
|
||||
* @returns {{string: string}} A mapping of 'headerName': 'headerValue'
|
||||
*/
|
||||
get defaultHeaders() {
|
||||
return this._defaultHeaders;
|
||||
get defaultHeaders () {
|
||||
return this._defaultHeaders
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new HTTP handler.
|
||||
*/
|
||||
constructor() {
|
||||
constructor () {
|
||||
// Add default response interceptors.
|
||||
this._defaultHeaders = {
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,40 +63,39 @@ export default class Http {
|
|||
* @param {{}} body The body. It will be JSON-Encoded by the handler.
|
||||
* @returns {Promise} A promise which will resolve with the processed request response.
|
||||
*/
|
||||
httpRequest(method, url, headers = {}, body) {
|
||||
|
||||
httpRequest (method, url, headers = {}, body) {
|
||||
// Sanitize the headers...
|
||||
headers = Object.assign({}, headers, this.defaultHeaders);
|
||||
headers = Object.assign({}, headers, this.defaultHeaders)
|
||||
|
||||
// Build the request
|
||||
const init = {method, headers};
|
||||
const init = { method, headers }
|
||||
|
||||
// The Request() constructor will throw an error if the method is GET/HEAD, and there's a body.
|
||||
if (['GET', 'HEAD'].indexOf(method) === -1 && body) {
|
||||
init.body = JSON.stringify(body);
|
||||
init.body = JSON.stringify(body)
|
||||
}
|
||||
const request = new Request(url, init);
|
||||
const request = new Request(url, init)
|
||||
|
||||
// Build the wrapper promise.
|
||||
return new Promise((resolve, reject) => {
|
||||
log.debug('-->', `HTTP ${method}`, url, JSON.stringify(headers), JSON.stringify(body));
|
||||
let promise = fetch(request.url, init);
|
||||
log.debug('-->', `HTTP ${method}`, url, JSON.stringify(headers), JSON.stringify(body))
|
||||
const promise = fetch(request.url, init)
|
||||
|
||||
// Fetch will treat all http responses (2xx, 3xx, 4xx, 5xx, etc) as successful responses.
|
||||
// This will catch all 4xx and 5xx responses and return them to the catch() handler. Note
|
||||
// that it's up to the downstream developer to determine whether what they received is an
|
||||
// error or a failed response.
|
||||
promise.then((response) => {
|
||||
log.debug('<--', `HTTP ${response.status}`);
|
||||
log.debug('<--', `HTTP ${response.status}`)
|
||||
if (response.status >= 400) {
|
||||
return reject(response);
|
||||
return reject(response)
|
||||
} else {
|
||||
return response;
|
||||
return response
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
promise.then((response) => resolve(response), (error) => reject(error));
|
||||
});
|
||||
promise.then((response) => resolve(response), (error) => reject(error))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,8 +104,8 @@ export default class Http {
|
|||
* @param {String} url The request URL.
|
||||
* @returns {Promise} A promise which will resolve with the processed request response.
|
||||
*/
|
||||
httpGet(url) {
|
||||
return this.httpRequest('GET', url, {}, null);
|
||||
httpGet (url) {
|
||||
return this.httpRequest('GET', url, {}, null)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,8 +115,8 @@ export default class Http {
|
|||
* @param {{}} body The body. It will be JSON-Encoded by the handler.
|
||||
* @returns {Promise} A promise which will resolve with the processed request response.
|
||||
*/
|
||||
httpPut(url, body) {
|
||||
return this.httpRequest('PUT', url, {}, body);
|
||||
httpPut (url, body) {
|
||||
return this.httpRequest('PUT', url, {}, body)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,8 +126,8 @@ export default class Http {
|
|||
* @param {{}} body The body. It will be JSON-Encoded by the handler.
|
||||
* @returns {Promise} A promise which will resolve with the processed request response.
|
||||
*/
|
||||
httpPost(url, body) {
|
||||
return this.httpRequest('POST', url, {}, body);
|
||||
httpPost (url, body) {
|
||||
return this.httpRequest('POST', url, {}, body)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,7 +136,7 @@ export default class Http {
|
|||
* @param {String} url The request URL.
|
||||
* @returns {Promise} A promise which will resolve with the processed request response.
|
||||
*/
|
||||
httpDelete(url) {
|
||||
return this.httpRequest('DELETE', url, {}, null);
|
||||
httpDelete (url) {
|
||||
return this.httpRequest('DELETE', url, {}, null)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
* comparable instance.
|
||||
*/
|
||||
export default class Version {
|
||||
|
||||
/**
|
||||
* The name of the service.
|
||||
*
|
||||
* @returns {String|*|null} The name of the service, or null.
|
||||
*/
|
||||
get service() {
|
||||
return this._service || null;
|
||||
get service () {
|
||||
return this._service || null
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,8 +33,8 @@ export default class Version {
|
|||
*
|
||||
* @returns {Number} The major version number
|
||||
*/
|
||||
get major() {
|
||||
return this._major || 0;
|
||||
get major () {
|
||||
return this._major || 0
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,8 +42,8 @@ export default class Version {
|
|||
*
|
||||
* @returns {Number} The minor version number
|
||||
*/
|
||||
get minor() {
|
||||
return this._minor || 0;
|
||||
get minor () {
|
||||
return this._minor || 0
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,8 +51,8 @@ export default class Version {
|
|||
*
|
||||
* @returns {Number} The patch version number.
|
||||
*/
|
||||
get patch() {
|
||||
return this._patch || 0;
|
||||
get patch () {
|
||||
return this._patch || 0
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,8 +60,8 @@ export default class Version {
|
|||
*
|
||||
* @returns {Object[]} The list of links.
|
||||
*/
|
||||
get links() {
|
||||
return this._links || null;
|
||||
get links () {
|
||||
return this._links || null
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,9 +69,9 @@ export default class Version {
|
|||
*
|
||||
* @param {Object[]} links The links to be set
|
||||
*/
|
||||
set links(links) {
|
||||
set links (links) {
|
||||
if (Array.isArray(links)) {
|
||||
this._links = links;
|
||||
this._links = links
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,37 +81,37 @@ export default class Version {
|
|||
* @param {String} [service] The name of the service.
|
||||
* @param {String} versionString The version string for this service.
|
||||
*/
|
||||
constructor(service, versionString) {
|
||||
constructor (service, versionString) {
|
||||
// Sanitize input
|
||||
if (typeof service !== 'string') {
|
||||
service = undefined;
|
||||
service = undefined
|
||||
}
|
||||
if (typeof versionString !== 'string') {
|
||||
versionString = undefined;
|
||||
versionString = undefined
|
||||
}
|
||||
|
||||
if (versionString === undefined) {
|
||||
versionString = service;
|
||||
versionString = service
|
||||
} else {
|
||||
this._service = service;
|
||||
this._service = service
|
||||
}
|
||||
|
||||
// Sanity check before running regex.
|
||||
if (!versionString || !versionString.match) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const results = versionString.match(/^(([^ ]+) )?v?(([0-9]+)(\.([0-9]+)(.([0-9]+))?)?)$/);
|
||||
const results = versionString.match(/^(([^ ]+) )?v?(([0-9]+)(\.([0-9]+)(.([0-9]+))?)?)$/)
|
||||
if (results) {
|
||||
this._service = results[2] || this._service; // regex takes precedence
|
||||
this._major = parseInt(results[4], 10);
|
||||
this._minor = parseInt(results[6], 10);
|
||||
this._patch = parseInt(results[8], 10);
|
||||
this._service = results[2] || this._service // regex takes precedence
|
||||
this._major = parseInt(results[4], 10)
|
||||
this._minor = parseInt(results[6], 10)
|
||||
this._patch = parseInt(results[8], 10)
|
||||
}
|
||||
this._links = null;
|
||||
this._links = null
|
||||
|
||||
this.equals = this.equals.bind(this);
|
||||
this.supports = this.supports.bind(this);
|
||||
this.equals = this.equals.bind(this)
|
||||
this.supports = this.supports.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,20 +120,20 @@ export default class Version {
|
|||
* @param {String|Version} version The version to compare to.
|
||||
* @returns {boolean} True if they are exactly the same, otherwise false.
|
||||
*/
|
||||
equals(version) {
|
||||
equals (version) {
|
||||
if (!(version instanceof Version)) {
|
||||
// is it a parseable string?
|
||||
if (typeof version === 'string') {
|
||||
version = new Version(version);
|
||||
version = new Version(version)
|
||||
} else {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return version.major === this.major &&
|
||||
version.minor === this.minor &&
|
||||
version.patch === this.patch &&
|
||||
version.service === this.service;
|
||||
version.service === this.service
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,30 +143,30 @@ export default class Version {
|
|||
* @param {String|Version} version the version to support.
|
||||
* @returns {boolean} True if the version is compatible, otherwise false
|
||||
*/
|
||||
supports(version) {
|
||||
supports (version) {
|
||||
if (!(version instanceof Version)) {
|
||||
if (typeof version === 'string') {
|
||||
version = new Version(version);
|
||||
version = new Version(version)
|
||||
} else {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const compatibleVersion = version.service === this.service &&
|
||||
version.major === this.major &&
|
||||
version.minor <= this.minor;
|
||||
version.minor <= this.minor
|
||||
|
||||
if (compatibleVersion && version.minor === this.minor) {
|
||||
return version.patch <= this.patch;
|
||||
return version.patch <= this.patch
|
||||
}
|
||||
return compatibleVersion;
|
||||
return compatibleVersion
|
||||
}
|
||||
|
||||
toString() {
|
||||
let version = `${this.major}.${this.minor}`;
|
||||
toString () {
|
||||
let version = `${this.major}.${this.minor}`
|
||||
if (this.patch) {
|
||||
version = `${version}.${this.patch}`;
|
||||
version = `${version}.${this.patch}`
|
||||
}
|
||||
return version;
|
||||
return version
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,71 +14,69 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import config from "./helpers/cloudsConfig";
|
||||
import Version from '../../src/util/version';
|
||||
import Glance from "../../src/glance";
|
||||
import Keystone from "../../src/keystone";
|
||||
import log from 'loglevel';
|
||||
import config from './helpers/cloudsConfig'
|
||||
import Version from '../../src/util/version'
|
||||
import Glance from '../../src/glance'
|
||||
import Keystone from '../../src/keystone'
|
||||
import log from 'loglevel'
|
||||
|
||||
log.setLevel("DEBUG");
|
||||
log.setLevel('DEBUG')
|
||||
|
||||
describe("Glance", () => {
|
||||
describe('Glance', () => {
|
||||
// Create a keystone instance and extract the glance API endpoint.
|
||||
let devstackConfig = config.clouds.devstack;
|
||||
let keystone = new Keystone(devstackConfig);
|
||||
let tokenPromise = keystone.tokenIssue();
|
||||
const devstackConfig = config.clouds.devstack
|
||||
const keystone = new Keystone(devstackConfig)
|
||||
const tokenPromise = keystone.tokenIssue()
|
||||
|
||||
let configPromise = tokenPromise
|
||||
const configPromise = tokenPromise
|
||||
.then((token) => keystone.catalogList(token))
|
||||
.then((catalog) => catalog.find((entry) => entry.name === 'glance'))
|
||||
.then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public'));
|
||||
.then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public'))
|
||||
|
||||
describe("versions()", () => {
|
||||
it("should return a list of all versions available on this clouds' glance", (done) => {
|
||||
describe('versions()', () => {
|
||||
it('should return a list of all versions available on this clouds\' glance', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Glance(config))
|
||||
.then((glance) => glance.versions())
|
||||
.then((versions) => {
|
||||
// Quick sanity check.
|
||||
expect(versions.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(versions.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("version()", () => {
|
||||
describe('version()', () => {
|
||||
/**
|
||||
* This test acts as a canary, to inform the SDK developers that the Glance API
|
||||
* has changed in a significant way.
|
||||
*/
|
||||
it("should return a supported version.", (done) => {
|
||||
it('should return a supported version.', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Glance(config))
|
||||
.then((glance) => glance.version())
|
||||
.then((apiVersion) => {
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy();
|
||||
done();
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("imageList()", () => {
|
||||
|
||||
describe('imageList()', () => {
|
||||
/**
|
||||
* Assert that we can get a list of images.
|
||||
*/
|
||||
it("should return a supported version.", (done) => {
|
||||
it('should return a supported version.', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Glance(config))
|
||||
.then((glance) => glance.imageList(tokenPromise))
|
||||
.then((images) => {
|
||||
expect(images.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(images.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*eslint no-sync: "off"*/
|
||||
import yaml from 'js-yaml';
|
||||
import fs from 'fs';
|
||||
import cloudsYamlPath from './cloudsYamlPath';
|
||||
/* eslint no-sync: "off" */
|
||||
import yaml from 'js-yaml'
|
||||
import fs from 'fs'
|
||||
import cloudsYamlPath from './cloudsYamlPath'
|
||||
|
||||
const clouds = yaml.safeLoad(fs.readFileSync(cloudsYamlPath, 'utf8'));
|
||||
const clouds = yaml.safeLoad(fs.readFileSync(cloudsYamlPath, 'utf8'))
|
||||
|
||||
export default clouds;
|
||||
export default clouds
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
/*eslint no-process-env: "off", no-sync: "off"*/
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
/* eslint no-process-env: "off", no-sync: "off" */
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
const resolvePaths = [
|
||||
'./clouds.yaml',
|
||||
process.env.HOME + '/.config/openstack/clouds.yaml',
|
||||
'/etc/openstack/clouds.yaml'
|
||||
];
|
||||
]
|
||||
|
||||
function fileExists(path) {
|
||||
function fileExists (path) {
|
||||
try {
|
||||
fs.statSync(path);
|
||||
return true;
|
||||
fs.statSync(path)
|
||||
return true
|
||||
} catch (err) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const cloudFiles = resolvePaths.filter(fileExists);
|
||||
|
||||
export default cloudFiles.length > 0 ? path.resolve(cloudFiles[0]) : 'clouds.yaml';
|
||||
const cloudFiles = resolvePaths.filter(fileExists)
|
||||
|
||||
export default cloudFiles.length > 0 ? path.resolve(cloudFiles[0]) : 'clouds.yaml'
|
||||
|
|
|
@ -14,81 +14,81 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Version from '../../src/util/version';
|
||||
import Keystone from "../../src/keystone";
|
||||
import config from "./helpers/cloudsConfig";
|
||||
import log from 'loglevel';
|
||||
import Version from '../../src/util/version'
|
||||
import Keystone from '../../src/keystone'
|
||||
import config from './helpers/cloudsConfig'
|
||||
import log from 'loglevel'
|
||||
|
||||
log.setLevel("DEBUG");
|
||||
log.setLevel('DEBUG')
|
||||
|
||||
describe("Keystone", () => {
|
||||
let devstackConfig = config.clouds.devstack;
|
||||
let adminConfig = config.clouds['devstack-admin'];
|
||||
let keystone = new Keystone(devstackConfig);
|
||||
describe('Keystone', () => {
|
||||
const devstackConfig = config.clouds.devstack
|
||||
const adminConfig = config.clouds['devstack-admin']
|
||||
const keystone = new Keystone(devstackConfig)
|
||||
|
||||
describe("versions()", () => {
|
||||
it("should return a list of all versions available on this clouds' keystone", (done) => {
|
||||
describe('versions()', () => {
|
||||
it('should return a list of all versions available on this clouds\' keystone', (done) => {
|
||||
keystone.versions()
|
||||
.then((versions) => {
|
||||
// Quick sanity check.
|
||||
expect(versions.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(versions.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
});
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("version()", () => {
|
||||
describe('version()', () => {
|
||||
/**
|
||||
* This test acts as a canary, to inform the SDK developers that the Keystone API
|
||||
* has changed in a significant way.
|
||||
*/
|
||||
it("should return a supported version.", (done) => {
|
||||
it('should return a supported version.', (done) => {
|
||||
keystone.version()
|
||||
.then((apiVersion) => {
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy();
|
||||
done();
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy()
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
});
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("tokenIssue()", () => {
|
||||
let keystone = null;
|
||||
describe('tokenIssue()', () => {
|
||||
let keystone = null
|
||||
|
||||
beforeEach(() => {
|
||||
keystone = new Keystone(config.clouds.devstack);
|
||||
});
|
||||
keystone = new Keystone(config.clouds.devstack)
|
||||
})
|
||||
|
||||
it("should 'just work' by using provided credentials from the config.", (done) => {
|
||||
it('should "just work" by using provided credentials from the config.', (done) => {
|
||||
keystone
|
||||
.tokenIssue()
|
||||
.then((token) => {
|
||||
expect(token).not.toBeNull();
|
||||
done();
|
||||
expect(token).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("should permit passing your own user, password, and project.", (done) => {
|
||||
it('should permit passing your own user, password, and project.', (done) => {
|
||||
keystone
|
||||
.tokenIssue(adminConfig.auth)
|
||||
.then((token) => {
|
||||
expect(token).not.toBeNull();
|
||||
done();
|
||||
expect(token).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an exception if invalid username and password are provided.", (done) => {
|
||||
it('should throw an exception if invalid username and password are provided.', (done) => {
|
||||
keystone
|
||||
.tokenIssue({
|
||||
username: 'foo',
|
||||
|
@ -96,12 +96,12 @@ describe("Keystone", () => {
|
|||
})
|
||||
.then((token) => done.fail(token))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("should throw an exception if invalid project is provided.", (done) => {
|
||||
it('should throw an exception if invalid project is provided.', (done) => {
|
||||
keystone
|
||||
.tokenIssue({
|
||||
project_id: 'foo',
|
||||
|
@ -109,12 +109,12 @@ describe("Keystone", () => {
|
|||
})
|
||||
.then((token) => done.fail(token))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("should throw an exception if invalid user domain is provided.", (done) => {
|
||||
it('should throw an exception if invalid user domain is provided.', (done) => {
|
||||
keystone
|
||||
.tokenIssue({
|
||||
user_domain_id: 'foo',
|
||||
|
@ -122,127 +122,127 @@ describe("Keystone", () => {
|
|||
})
|
||||
.then((token) => done.fail(token))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("tokenRevoke()", () => {
|
||||
let keystone = null;
|
||||
describe('tokenRevoke()', () => {
|
||||
let keystone = null
|
||||
|
||||
beforeEach(() => {
|
||||
keystone = new Keystone(config.clouds.devstack);
|
||||
});
|
||||
keystone = new Keystone(config.clouds.devstack)
|
||||
})
|
||||
|
||||
it("should permit self-revocation.", (done) => {
|
||||
it('should permit self-revocation.', (done) => {
|
||||
keystone
|
||||
.tokenIssue()
|
||||
.then((token) => {
|
||||
return keystone.tokenRevoke(token);
|
||||
return keystone.tokenRevoke(token)
|
||||
})
|
||||
.then((response) => {
|
||||
expect(response.status).toBe(204); // No content
|
||||
done();
|
||||
expect(response.status).toBe(204) // No content
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("should allow an admin to revoke another token.", (done) => {
|
||||
let adminToken;
|
||||
let adminKeystone = new Keystone(adminConfig);
|
||||
it('should allow an admin to revoke another token.', (done) => {
|
||||
let adminToken
|
||||
const adminKeystone = new Keystone(adminConfig)
|
||||
|
||||
adminKeystone.tokenIssue() // Get an admin token.
|
||||
.then((token) => {
|
||||
adminToken = token;
|
||||
return keystone.tokenIssue(); // Regular token.
|
||||
adminToken = token
|
||||
return keystone.tokenIssue() // Regular token.
|
||||
})
|
||||
.then((token) => keystone.tokenRevoke(token, adminToken))
|
||||
.then((response) => {
|
||||
expect(response.status).toBe(204); // No content
|
||||
done();
|
||||
expect(response.status).toBe(204) // No content
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an exception if invalid token is provided.", (done) => {
|
||||
it('should throw an exception if invalid token is provided.', (done) => {
|
||||
keystone
|
||||
.tokenRevoke('not_a_valid_token')
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("tokenInfo()", () => {
|
||||
let keystone = null;
|
||||
describe('tokenInfo()', () => {
|
||||
let keystone = null
|
||||
|
||||
beforeEach(() => {
|
||||
keystone = new Keystone(config.clouds.devstack);
|
||||
});
|
||||
keystone = new Keystone(config.clouds.devstack)
|
||||
})
|
||||
|
||||
it("should retrieve info about a token.", (done) => {
|
||||
it('should retrieve info about a token.', (done) => {
|
||||
keystone
|
||||
.tokenIssue()
|
||||
.then((token) => {
|
||||
return keystone.tokenInfo(token);
|
||||
return keystone.tokenInfo(token)
|
||||
})
|
||||
.then((info) => {
|
||||
expect('token' in info).toBe(true);
|
||||
done();
|
||||
expect('token' in info).toBe(true)
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw an exception if invalid token is provided.", (done) => {
|
||||
it('should throw an exception if invalid token is provided.', (done) => {
|
||||
keystone
|
||||
.tokenRevoke('not_a_valid_token')
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("catalogList()", () => {
|
||||
let keystone = null;
|
||||
describe('catalogList()', () => {
|
||||
let keystone = null
|
||||
|
||||
beforeEach(() => {
|
||||
keystone = new Keystone(config.clouds.devstack);
|
||||
});
|
||||
keystone = new Keystone(config.clouds.devstack)
|
||||
})
|
||||
|
||||
it("should list a catalog.", (done) => {
|
||||
it('should list a catalog.', (done) => {
|
||||
keystone
|
||||
.tokenIssue()
|
||||
.then((token) => {
|
||||
return keystone.catalogList(token);
|
||||
return keystone.catalogList(token)
|
||||
})
|
||||
.then((catalog) => {
|
||||
expect(catalog.length).not.toBe(0);
|
||||
done();
|
||||
expect(catalog.length).not.toBe(0)
|
||||
done()
|
||||
})
|
||||
.catch((response) => response.json()
|
||||
.then((body) => done.fail(JSON.stringify(body)))
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("should error if not authenticated.", (done) => {
|
||||
it('should error if not authenticated.', (done) => {
|
||||
keystone
|
||||
.catalogList()
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,67 +14,66 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import config from "./helpers/cloudsConfig";
|
||||
import Version from '../../src/util/version';
|
||||
import Neutron from "../../src/neutron";
|
||||
import Keystone from "../../src/keystone";
|
||||
import log from 'loglevel';
|
||||
import config from './helpers/cloudsConfig'
|
||||
import Version from '../../src/util/version'
|
||||
import Neutron from '../../src/neutron'
|
||||
import Keystone from '../../src/keystone'
|
||||
import log from 'loglevel'
|
||||
|
||||
log.setLevel("DEBUG");
|
||||
log.setLevel('DEBUG')
|
||||
|
||||
describe("neutron", () => {
|
||||
describe('neutron', () => {
|
||||
// Create a keystone instance and extract the neutron API endpoint.
|
||||
let devstackConfig = config.clouds.devstack;
|
||||
let keystone = new Keystone(devstackConfig);
|
||||
let tokenPromise = keystone.tokenIssue();
|
||||
const devstackConfig = config.clouds.devstack
|
||||
const keystone = new Keystone(devstackConfig)
|
||||
const tokenPromise = keystone.tokenIssue()
|
||||
|
||||
let configPromise = tokenPromise
|
||||
const configPromise = tokenPromise
|
||||
.then((token) => keystone.catalogList(token))
|
||||
.then((catalog) => catalog.find((entry) => entry.name === 'neutron'))
|
||||
.then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public'));
|
||||
.then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public'))
|
||||
|
||||
describe("versions()", () => {
|
||||
it("should return a list of all versions available on this clouds' neutron", (done) => {
|
||||
describe('versions()', () => {
|
||||
it('should return a list of all versions available on this clouds\' neutron', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Neutron(config))
|
||||
.then((neutron) => neutron.versions())
|
||||
.then((versions) => {
|
||||
// Quick sanity check.
|
||||
expect(versions.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(versions.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("version()", () => {
|
||||
describe('version()', () => {
|
||||
/**
|
||||
* This test acts as a canary, to inform the SDK developers that the Neutron API
|
||||
* has changed in a significant way.
|
||||
*/
|
||||
it("should return a supported version.", (done) => {
|
||||
it('should return a supported version.', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Neutron(config))
|
||||
.then((neutron) => neutron.version())
|
||||
.then((apiVersion) => {
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy();
|
||||
done();
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("networkList()", () => {
|
||||
it("should return the networks as an array.", (done) => {
|
||||
describe('networkList()', () => {
|
||||
it('should return the networks as an array.', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Neutron(config))
|
||||
.then((neutron) => neutron.networkList(tokenPromise))
|
||||
.then((networks) => {
|
||||
expect(networks.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(networks.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,56 +14,55 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import config from "./helpers/cloudsConfig";
|
||||
import Version from '../../src/util/version';
|
||||
import Nova from "../../src/nova";
|
||||
import Keystone from "../../src/keystone";
|
||||
import log from 'loglevel';
|
||||
import config from './helpers/cloudsConfig'
|
||||
import Version from '../../src/util/version'
|
||||
import Nova from '../../src/nova'
|
||||
import Keystone from '../../src/keystone'
|
||||
import log from 'loglevel'
|
||||
|
||||
log.setLevel("DEBUG");
|
||||
log.setLevel('DEBUG')
|
||||
|
||||
describe("Nova", () => {
|
||||
describe('Nova', () => {
|
||||
// Create a keystone instance and extract the nova API endpoint.
|
||||
let devstackConfig = config.clouds.devstack;
|
||||
let keystone = new Keystone(devstackConfig);
|
||||
let tokenPromise = keystone.tokenIssue();
|
||||
const devstackConfig = config.clouds.devstack
|
||||
const keystone = new Keystone(devstackConfig)
|
||||
const tokenPromise = keystone.tokenIssue()
|
||||
|
||||
let configPromise = tokenPromise
|
||||
const configPromise = tokenPromise
|
||||
.then((token) => keystone.catalogList(token))
|
||||
.then((catalog) => catalog.find((entry) => entry.name === 'nova'))
|
||||
.then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public'));
|
||||
.then((entry) => entry.endpoints.find((endpoint) => endpoint.interface === 'public'))
|
||||
|
||||
describe("version()", () => {
|
||||
describe('version()', () => {
|
||||
/**
|
||||
* This test acts as a canary, to inform the SDK developers that the Nova API
|
||||
* has changed in a significant way.
|
||||
*/
|
||||
it("should return a supported version.", (done) => {
|
||||
it('should return a supported version.', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Nova(config))
|
||||
.then((nova) => nova.version())
|
||||
.then((apiVersion) => {
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy();
|
||||
done();
|
||||
expect(apiVersion instanceof Version).not.toBeFalsy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("flavorList()", () => {
|
||||
|
||||
describe('flavorList()', () => {
|
||||
/**
|
||||
* Assert that we can get a list of flavors.
|
||||
*/
|
||||
it("should return a list of flavors.", (done) => {
|
||||
it('should return a list of flavors.', (done) => {
|
||||
configPromise
|
||||
.then((config) => new Nova(config))
|
||||
.then((nova) => nova.flavorList(tokenPromise))
|
||||
.then((flavors) => {
|
||||
expect(flavors.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(flavors.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,49 +1,48 @@
|
|||
import config from "./helpers/cloudsConfig";
|
||||
import OpenStack from "../../src/openstack";
|
||||
import log from 'loglevel';
|
||||
import config from './helpers/cloudsConfig'
|
||||
import OpenStack from '../../src/openstack'
|
||||
import log from 'loglevel'
|
||||
|
||||
log.setLevel("DEBUG");
|
||||
log.setLevel('DEBUG')
|
||||
|
||||
describe("OpenStack", () => {
|
||||
let devstackConfig = config.clouds.devstack;
|
||||
describe('OpenStack', () => {
|
||||
const devstackConfig = config.clouds.devstack
|
||||
|
||||
describe("networkList()", () => {
|
||||
it("should return the networks as an array.", (done) => {
|
||||
const openstack = new OpenStack(devstackConfig);
|
||||
describe('networkList()', () => {
|
||||
it('should return the networks as an array.', (done) => {
|
||||
const openstack = new OpenStack(devstackConfig)
|
||||
|
||||
openstack.networkList()
|
||||
.then((networks) => {
|
||||
expect(networks.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(networks.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("imageList()", () => {
|
||||
it("should return the images as an array.", (done) => {
|
||||
const openstack = new OpenStack(devstackConfig);
|
||||
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();
|
||||
expect(images.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("flavorList()", () => {
|
||||
it("should return the flavors as an array.", (done) => {
|
||||
const openstack = new OpenStack(devstackConfig);
|
||||
describe('flavorList()', () => {
|
||||
it('should return the flavors as an array.', (done) => {
|
||||
const openstack = new OpenStack(devstackConfig)
|
||||
|
||||
openstack.flavorList()
|
||||
.then((flavors) => {
|
||||
expect(flavors.length > 0).toBeTruthy();
|
||||
done();
|
||||
expect(flavors.length > 0).toBeTruthy()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Jasmine from 'jasmine';
|
||||
import Jasmine from 'jasmine'
|
||||
|
||||
const jasmine = new Jasmine();
|
||||
jasmine.loadConfigFile('test/functional/jasmine.json');
|
||||
jasmine.execute();
|
||||
const jasmine = new Jasmine()
|
||||
jasmine.loadConfigFile('test/functional/jasmine.json')
|
||||
jasmine.execute()
|
||||
|
|
|
@ -14,76 +14,75 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Glance from "../../src/glance.js";
|
||||
import * as mockData from "./helpers/data/glance";
|
||||
import fetchMock from "fetch-mock";
|
||||
import Glance from '../../src/glance.js'
|
||||
import * as mockData from './helpers/data/glance'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
describe('Glance', () => {
|
||||
|
||||
afterEach(fetchMock.restore);
|
||||
afterEach(fetchMock.restore)
|
||||
|
||||
it('should export a class', () => {
|
||||
const glance = new Glance(mockData.config);
|
||||
expect(glance).toBeDefined();
|
||||
});
|
||||
const glance = new Glance(mockData.config)
|
||||
expect(glance).toBeDefined()
|
||||
})
|
||||
|
||||
it('should throw an error for an empty config', () => {
|
||||
expect(() => new Glance()).toThrow();
|
||||
});
|
||||
expect(() => new Glance()).toThrow()
|
||||
})
|
||||
|
||||
describe("serviceEndpoint()", () => {
|
||||
it("Should return a valid endpoint to the glance API.", (done) => {
|
||||
const glance = new Glance(mockData.config);
|
||||
describe('serviceEndpoint()', () => {
|
||||
it('Should return a valid endpoint to the glance API.', (done) => {
|
||||
const glance = new Glance(mockData.config)
|
||||
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockData.root())
|
||||
|
||||
glance.serviceEndpoint()
|
||||
.then((endpoint) => {
|
||||
expect(endpoint).toEqual('http://192.168.99.99:9292/v2/');
|
||||
done();
|
||||
expect(endpoint).toEqual('http://192.168.99.99:9292/v2/')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("imageList()", () => {
|
||||
let glance = null;
|
||||
describe('imageList()', () => {
|
||||
let glance = null
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock(mockData.root());
|
||||
glance = new Glance(mockData.config);
|
||||
});
|
||||
fetchMock.mock(mockData.root())
|
||||
glance = new Glance(mockData.config)
|
||||
})
|
||||
|
||||
it("should return the images as an array.", (done) => {
|
||||
const token = 'test_token';
|
||||
it('should return the images as an array.', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
fetchMock.mock(mockData.imageList(token));
|
||||
fetchMock.mock(mockData.imageList(token))
|
||||
glance
|
||||
.imageList(token)
|
||||
.then((images) => {
|
||||
expect(images.length).not.toBe(0);
|
||||
done();
|
||||
expect(images.length).not.toBe(0)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not cache its results", (done) => {
|
||||
const token = 'test_token';
|
||||
it('Should not cache its results', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
let mockOptions = mockData.imageList(token);
|
||||
fetchMock.mock(mockOptions);
|
||||
const mockOptions = mockData.imageList(token)
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
glance
|
||||
.imageList(token)
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return glance.imageList(token);
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return glance.imageList(token)
|
||||
})
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -25,100 +25,100 @@
|
|||
* format, rather just the subsection pointing to a particular cloud.
|
||||
*/
|
||||
const glanceConfig = {
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9292/",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "0b8b5f0f14904136ab5a4f83f27ec49a"
|
||||
};
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9292/',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: '0b8b5f0f14904136ab5a4f83f27ec49a'
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new FetchMock configuration for the root endpoint.
|
||||
*
|
||||
* @returns {{}} A full FetchMock configuration for Glance's Root Resource.
|
||||
*/
|
||||
function rootResponse() {
|
||||
function rootResponse () {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99:9292/',
|
||||
response: {
|
||||
versions: [
|
||||
{
|
||||
status: "CURRENT",
|
||||
id: "v2.5",
|
||||
status: 'CURRENT',
|
||||
id: 'v2.5',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99:9292/v2/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99:9292/v2/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v2.3",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v2.3',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99:9292/v2/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99:9292/v2/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v2.2",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v2.2',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99:9292/v2/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99:9292/v2/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v2.1",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v2.1',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99:9292/v2/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99:9292/v2/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v2.0",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v2.0',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99:9292/v2/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99:9292/v2/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v1.1",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v1.1',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99:9292/v1/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99:9292/v1/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v1.0",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v1.0',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99:9292/v1/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99:9292/v1/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function imageList(token) {
|
||||
function imageList (token) {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99:9292/v2/images',
|
||||
|
@ -195,10 +195,10 @@ function imageList(token) {
|
|||
schema: '/v2/schemas/images',
|
||||
first: '/v2/images'
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
export {
|
||||
glanceConfig as config,
|
||||
rootResponse as root,
|
||||
imageList
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,302 +32,302 @@ const cloudConfig = {
|
|||
project_name: 'js-openstack-lib',
|
||||
auth_url: 'http://192.168.99.99/'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const catalogListData = [
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99/identity_v2_admin",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "940664e070864b638dfafc53cfcbe887"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99/identity_v2_admin',
|
||||
region: 'RegionOne',
|
||||
interface: 'admin',
|
||||
id: '940664e070864b638dfafc53cfcbe887'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99/identity",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "c3707565bccb407c888040fa9b7e77b0"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99/identity',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: 'c3707565bccb407c888040fa9b7e77b0'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99/identity",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "fb28f261810449ea98b2df646b847a74"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99/identity',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: 'fb28f261810449ea98b2df646b847a74'
|
||||
}
|
||||
],
|
||||
type: "identity",
|
||||
id: "0599684d07a145659fa858c1deb4e885",
|
||||
name: "keystone"
|
||||
type: 'identity',
|
||||
id: '0599684d07a145659fa858c1deb4e885',
|
||||
name: 'keystone'
|
||||
},
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v3/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "611a5108ef0b4f999ad439b0e1abd9da"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v3/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: '611a5108ef0b4f999ad439b0e1abd9da'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v3/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "ae08047e33d848c8b1c77f99bc572e22"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v3/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: 'ae08047e33d848c8b1c77f99bc572e22'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v3/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "e26c6757baa549469772e16e03c051b8"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v3/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'admin',
|
||||
id: 'e26c6757baa549469772e16e03c051b8'
|
||||
}
|
||||
],
|
||||
type: "volumev3",
|
||||
id: "1092f88a41c64fc7b0331fce96e7df6c",
|
||||
name: "cinderv3"
|
||||
type: 'volumev3',
|
||||
id: '1092f88a41c64fc7b0331fce96e7df6c',
|
||||
name: 'cinderv3'
|
||||
},
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v1/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "14ad1642b0874816a7ff08eb0e24be87"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v1/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: '14ad1642b0874816a7ff08eb0e24be87'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v1/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "8bb7b28802d44e9d80fbb358a3e133af"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v1/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: '8bb7b28802d44e9d80fbb358a3e133af'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v1/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "c271745ff29c4c9d829ab3187d41cab7"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v1/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'admin',
|
||||
id: 'c271745ff29c4c9d829ab3187d41cab7'
|
||||
}
|
||||
],
|
||||
type: "volume",
|
||||
id: "5067360b6f264558945b7d2c312dd126",
|
||||
name: "cinder"
|
||||
type: 'volume',
|
||||
id: '5067360b6f264558945b7d2c312dd126',
|
||||
name: 'cinder'
|
||||
},
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9292",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "0b8b5f0f14904136ab5a4f83f27ec49a"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9292',
|
||||
region: 'RegionOne',
|
||||
interface: 'admin',
|
||||
id: '0b8b5f0f14904136ab5a4f83f27ec49a'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9292",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "97c90e43e1fe473b85ef47627006dcdd"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9292',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: '97c90e43e1fe473b85ef47627006dcdd'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9292",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "ee114418c77a45d2a3cc28240dc4281d"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9292',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: 'ee114418c77a45d2a3cc28240dc4281d'
|
||||
}
|
||||
],
|
||||
type: "image",
|
||||
id: "6512ca68fbd543928768201198cd7e42",
|
||||
name: "glance"
|
||||
type: 'image',
|
||||
id: '6512ca68fbd543928768201198cd7e42',
|
||||
name: 'glance'
|
||||
},
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8774/v2.1",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "14129d81da0e44abae0c082c535b58cc"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8774/v2.1',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: '14129d81da0e44abae0c082c535b58cc'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8774/v2.1",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "be681632633d4a62a781148c2fedd6aa"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8774/v2.1',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: 'be681632633d4a62a781148c2fedd6aa'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8774/v2.1",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "f8979efb0903442a9068d57fce4eafb2"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8774/v2.1',
|
||||
region: 'RegionOne',
|
||||
interface: 'admin',
|
||||
id: 'f8979efb0903442a9068d57fce4eafb2'
|
||||
}
|
||||
],
|
||||
type: "compute",
|
||||
id: "6d3dd68ae2224fd39503342220b5d2c2",
|
||||
name: "nova"
|
||||
type: 'compute',
|
||||
id: '6d3dd68ae2224fd39503342220b5d2c2',
|
||||
name: 'nova'
|
||||
},
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8774/v2/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "308f5ed663a7417db3f078f7e3b66db8"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8774/v2/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'admin',
|
||||
id: '308f5ed663a7417db3f078f7e3b66db8'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8774/v2/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "9f08e41e8156498ba01b5cc83cc9e1da"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8774/v2/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: '9f08e41e8156498ba01b5cc83cc9e1da'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8774/v2/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "b855d4c048f1468f9df5a9950ae811c6"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8774/v2/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: 'b855d4c048f1468f9df5a9950ae811c6'
|
||||
}
|
||||
],
|
||||
type: "compute_legacy",
|
||||
id: "8ca07a04d03145a094c404b5edf70c18",
|
||||
name: "nova_legacy"
|
||||
type: 'compute_legacy',
|
||||
id: '8ca07a04d03145a094c404b5edf70c18',
|
||||
name: 'nova_legacy'
|
||||
},
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v2/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "2b6e28e0aade41b5b80baa9012e54ca4"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v2/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: '2b6e28e0aade41b5b80baa9012e54ca4'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v2/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "79c96252a8ab4c7181ef4fe97237c314"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v2/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'admin',
|
||||
id: '79c96252a8ab4c7181ef4fe97237c314'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8776/v2/8b2aa635109f4d0ab355e18a269d341f",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "8d4cbc86845a4ecb90f19903636205a7"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8776/v2/8b2aa635109f4d0ab355e18a269d341f',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: '8d4cbc86845a4ecb90f19903636205a7'
|
||||
}
|
||||
],
|
||||
type: "volumev2",
|
||||
id: "a7967e90d1044b1fa6d80b033f1da510",
|
||||
name: "cinderv2"
|
||||
type: 'volumev2',
|
||||
id: 'a7967e90d1044b1fa6d80b033f1da510',
|
||||
name: 'cinderv2'
|
||||
},
|
||||
{
|
||||
endpoints: [
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9696/",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "7033fa4ebed74e3fa51753162150a1f2"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9696/',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: '7033fa4ebed74e3fa51753162150a1f2'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9696/",
|
||||
region: "RegionOne",
|
||||
interface: "internal",
|
||||
id: "7aa942d402a34d4c90454b9d84285855"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9696/',
|
||||
region: 'RegionOne',
|
||||
interface: 'internal',
|
||||
id: '7aa942d402a34d4c90454b9d84285855'
|
||||
},
|
||||
{
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9696/",
|
||||
region: "RegionOne",
|
||||
interface: "admin",
|
||||
id: "bd8db1bafe41489bbbc45641e525ee7d"
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9696/',
|
||||
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: '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: 'RegionOne',
|
||||
interface: 'RegionTwo',
|
||||
id: '7aa942d402a34d4c90454b9d84285855'
|
||||
},
|
||||
{
|
||||
region_id: "RegionTwo",
|
||||
url: "http://192.168.99.100:9696/",
|
||||
region: "RegionTwo",
|
||||
interface: "admin",
|
||||
id: "bd8db1bafe41489bbbc45641e525ee7d"
|
||||
region_id: 'RegionTwo',
|
||||
url: 'http://192.168.99.100:9696/',
|
||||
region: 'RegionTwo',
|
||||
interface: 'admin',
|
||||
id: 'bd8db1bafe41489bbbc45641e525ee7d'
|
||||
}
|
||||
],
|
||||
type: "network",
|
||||
id: "f36b9e68ef114769b85024513ee61047",
|
||||
name: "neutron"
|
||||
type: 'network',
|
||||
id: 'f36b9e68ef114769b85024513ee61047',
|
||||
name: 'neutron'
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
const tokenInfoData = {
|
||||
is_domain: false,
|
||||
methods: [
|
||||
"password"
|
||||
'password'
|
||||
],
|
||||
roles: [
|
||||
{
|
||||
id: "cfa75a8719f544e2903e5899785b0cf0",
|
||||
name: "anotherrole"
|
||||
id: 'cfa75a8719f544e2903e5899785b0cf0',
|
||||
name: 'anotherrole'
|
||||
},
|
||||
{
|
||||
id: "5f8126fad6704a999a3651955c7d8219",
|
||||
name: "Member"
|
||||
id: '5f8126fad6704a999a3651955c7d8219',
|
||||
name: 'Member'
|
||||
}
|
||||
],
|
||||
is_admin_project: false,
|
||||
project: {
|
||||
domain: {
|
||||
id: "default",
|
||||
name: "Default"
|
||||
id: 'default',
|
||||
name: 'Default'
|
||||
},
|
||||
id: "8b2aa635109f4d0ab355e18a269d341f",
|
||||
name: "demo"
|
||||
id: '8b2aa635109f4d0ab355e18a269d341f',
|
||||
name: 'demo'
|
||||
},
|
||||
catalog: catalogListData,
|
||||
expires_at: "2016-08-19T18:04:11.157434Z",
|
||||
expires_at: '2016-08-19T18:04:11.157434Z',
|
||||
user: {
|
||||
domain: {
|
||||
id: "default",
|
||||
name: "Default"
|
||||
id: 'default',
|
||||
name: 'Default'
|
||||
},
|
||||
id: "d56a64f45da0450a826ede637be64304",
|
||||
name: "demo"
|
||||
id: 'd56a64f45da0450a826ede637be64304',
|
||||
name: 'demo'
|
||||
},
|
||||
audit_ids: [
|
||||
"FtgqCjtuR2-V36loBJ8mxQ"
|
||||
'FtgqCjtuR2-V36loBJ8mxQ'
|
||||
],
|
||||
issued_at: "2016-08-19T17:04:11.157456Z"
|
||||
};
|
||||
issued_at: '2016-08-19T17:04:11.157456Z'
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new FetchMock configuration for the root endpoint.
|
||||
*
|
||||
* @returns {{}} A full FetchMock configuration for Keystone's Root Resource.
|
||||
*/
|
||||
function rootResponse() {
|
||||
function rootResponse () {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99/',
|
||||
|
@ -335,56 +335,56 @@ function rootResponse() {
|
|||
versions: {
|
||||
values: [
|
||||
{
|
||||
status: "stable",
|
||||
updated: "2016-10-06T00:00:00Z",
|
||||
"media-types": [
|
||||
status: 'stable',
|
||||
updated: '2016-10-06T00:00:00Z',
|
||||
'media-types': [
|
||||
{
|
||||
base: "application/json",
|
||||
type: "application/vnd.openstack.identity-v3+json"
|
||||
base: 'application/json',
|
||||
type: 'application/vnd.openstack.identity-v3+json'
|
||||
}
|
||||
],
|
||||
id: "v3.7",
|
||||
id: 'v3.7',
|
||||
links: [
|
||||
{
|
||||
href: "http://docs.openstack.org/",
|
||||
type: "text/html",
|
||||
rel: "describedby"
|
||||
href: 'http://docs.openstack.org/',
|
||||
type: 'text/html',
|
||||
rel: 'describedby'
|
||||
},
|
||||
{
|
||||
href: "http://192.168.99.99/identity_v2_admin/v3/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99/identity_v2_admin/v3/',
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "deprecated",
|
||||
updated: "2016-08-04T00:00:00Z",
|
||||
"media-types": [
|
||||
status: 'deprecated',
|
||||
updated: '2016-08-04T00:00:00Z',
|
||||
'media-types': [
|
||||
{
|
||||
base: "application/json",
|
||||
type: "application/vnd.openstack.identity-v2.0+json"
|
||||
base: 'application/json',
|
||||
type: 'application/vnd.openstack.identity-v2.0+json'
|
||||
}
|
||||
],
|
||||
id: "v2.0",
|
||||
id: 'v2.0',
|
||||
links: [
|
||||
{
|
||||
href: "http://192.168.99.99/identity_v2_admin/v2.0/",
|
||||
rel: "self"
|
||||
href: 'http://192.168.99.99/identity_v2_admin/v2.0/',
|
||||
rel: 'self'
|
||||
},
|
||||
{
|
||||
href: "http://docs.openstack.org/",
|
||||
type: "text/html",
|
||||
rel: "describedby"
|
||||
href: 'http://docs.openstack.org/',
|
||||
type: 'text/html',
|
||||
rel: 'describedby'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function tokenIssue() {
|
||||
function tokenIssue () {
|
||||
return {
|
||||
method: 'POST',
|
||||
matcher: 'http://192.168.99.99/identity_v2_admin/v3/auth/tokens',
|
||||
|
@ -397,10 +397,10 @@ function tokenIssue() {
|
|||
token: tokenInfoData
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function tokenRevoke(token, adminToken = null) {
|
||||
function tokenRevoke (token, adminToken = null) {
|
||||
return {
|
||||
method: 'DELETE',
|
||||
matcher: 'http://192.168.99.99/identity_v2_admin/v3/auth/tokens',
|
||||
|
@ -411,10 +411,10 @@ function tokenRevoke(token, adminToken = null) {
|
|||
response: {
|
||||
status: 204
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function tokenInfo(token) {
|
||||
function tokenInfo (token) {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99/identity_v2_admin/v3/auth/tokens',
|
||||
|
@ -427,10 +427,10 @@ function tokenInfo(token) {
|
|||
token: tokenInfoData
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function catalogList(token) {
|
||||
function catalogList (token) {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99/identity_v2_admin/v3/auth/catalog',
|
||||
|
@ -440,7 +440,7 @@ function catalogList(token) {
|
|||
response: {
|
||||
catalog: catalogListData
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
|
@ -449,5 +449,5 @@ export {
|
|||
tokenIssue,
|
||||
tokenRevoke,
|
||||
tokenInfo,
|
||||
catalogList,
|
||||
};
|
||||
catalogList
|
||||
}
|
||||
|
|
|
@ -25,19 +25,19 @@
|
|||
* format but a subsection of service endpoint return by keystone's catalog.
|
||||
*/
|
||||
const neutronConfig = {
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:9696/",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "0b8b5f0f14904136ab5a4f83f27ec49a"
|
||||
};
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:9696/',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: '0b8b5f0f14904136ab5a4f83f27ec49a'
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new FetchMock configuration for the root endpoint.
|
||||
*
|
||||
* @returns {{}} A full FetchMock configuration for Neutron's Root Resource.
|
||||
*/
|
||||
function rootResponse() {
|
||||
function rootResponse () {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99:9696/',
|
||||
|
@ -55,10 +55,10 @@ function rootResponse() {
|
|||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function networkList(token) {
|
||||
function networkList (token) {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99:9696/v2.0/networks',
|
||||
|
@ -103,11 +103,11 @@ function networkList(token) {
|
|||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
neutronConfig as config,
|
||||
rootResponse as root,
|
||||
networkList
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,40 +24,40 @@
|
|||
* A catalog entry that matches what we expect from the Keystone Catalog for nova compute.
|
||||
*/
|
||||
const novaConfig = {
|
||||
region_id: "RegionOne",
|
||||
url: "http://192.168.99.99:8774/v2.1",
|
||||
region: "RegionOne",
|
||||
interface: "public",
|
||||
id: "be681632633d4a62a781148c2fedd6aa"
|
||||
};
|
||||
region_id: 'RegionOne',
|
||||
url: 'http://192.168.99.99:8774/v2.1',
|
||||
region: 'RegionOne',
|
||||
interface: 'public',
|
||||
id: 'be681632633d4a62a781148c2fedd6aa'
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a new FetchMock configuration for the root endpoint.
|
||||
*
|
||||
* @returns {{}} A full FetchMock configuration for Nova's Root Resource.
|
||||
*/
|
||||
function rootResponse() {
|
||||
function rootResponse () {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99:8774/',
|
||||
response: {
|
||||
versions: [{
|
||||
status: "CURRENT",
|
||||
updated: "2013-07-23T11:33:21Z",
|
||||
links: [{href: "http://192.168.99.99:8774/v2.1/", rel: "self"}],
|
||||
min_version: "2.1",
|
||||
version: "2.38",
|
||||
id: "v2.1"
|
||||
status: 'CURRENT',
|
||||
updated: '2013-07-23T11:33:21Z',
|
||||
links: [{ href: 'http://192.168.99.99:8774/v2.1/', rel: 'self' }],
|
||||
min_version: '2.1',
|
||||
version: '2.38',
|
||||
id: 'v2.1'
|
||||
}, {
|
||||
status: "SUPPORTED",
|
||||
updated: "2011-01-21T11:33:21Z",
|
||||
links: [{href: "http://192.168.99.99:8774/v2/", rel: "self"}],
|
||||
min_version: "",
|
||||
version: "",
|
||||
id: "v2.0"
|
||||
status: 'SUPPORTED',
|
||||
updated: '2011-01-21T11:33:21Z',
|
||||
links: [{ href: 'http://192.168.99.99:8774/v2/', rel: 'self' }],
|
||||
min_version: '',
|
||||
version: '',
|
||||
id: 'v2.0'
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,14 +66,14 @@ function rootResponse() {
|
|||
* @param {String} version The version ID.
|
||||
* @return {{}} A FetchMock configuration for this request's response.
|
||||
*/
|
||||
function versionedRootResponse(version = 'v2.1') {
|
||||
function versionedRootResponse (version = 'v2.1') {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: `http://192.168.99.99:8774/${version}`,
|
||||
response: {
|
||||
status: 401
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,7 +82,7 @@ function versionedRootResponse(version = 'v2.1') {
|
|||
* @param {String} token An auth token.
|
||||
* @return {{}} A FetchMock configuration for this request's response.
|
||||
*/
|
||||
function flavorList(token) {
|
||||
function flavorList (token) {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: 'http://192.168.99.99:8774/v2.1/flavors',
|
||||
|
@ -91,92 +91,92 @@ function flavorList(token) {
|
|||
},
|
||||
response: {
|
||||
flavors: [{
|
||||
id: "1",
|
||||
id: '1',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/1", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/1", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/1', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/1', rel: 'bookmark' }
|
||||
],
|
||||
name: "m1.tiny"
|
||||
name: 'm1.tiny'
|
||||
}, {
|
||||
id: "2",
|
||||
id: '2',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/2", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/2", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/2', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/2', rel: 'bookmark' }
|
||||
],
|
||||
name: "m1.small"
|
||||
name: 'm1.small'
|
||||
}, {
|
||||
id: "3",
|
||||
id: '3',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/3", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/3", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/3', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/3', rel: 'bookmark' }
|
||||
],
|
||||
name: "m1.medium"
|
||||
name: 'm1.medium'
|
||||
}, {
|
||||
id: "4",
|
||||
id: '4',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/4", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/4", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/4', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/4', rel: 'bookmark' }
|
||||
],
|
||||
name: "m1.large"
|
||||
name: 'm1.large'
|
||||
}, {
|
||||
id: "42",
|
||||
id: '42',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/42", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/42", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/42', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/42', rel: 'bookmark' }
|
||||
],
|
||||
name: "m1.nano"
|
||||
name: 'm1.nano'
|
||||
}, {
|
||||
id: "5",
|
||||
id: '5',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/5", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/5", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/5', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/5', rel: 'bookmark' }
|
||||
],
|
||||
name: "m1.xlarge"
|
||||
name: 'm1.xlarge'
|
||||
}, {
|
||||
id: "84",
|
||||
id: '84',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/84", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/84", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/84', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/84', rel: 'bookmark' }
|
||||
],
|
||||
name: "m1.micro"
|
||||
name: 'm1.micro'
|
||||
}, {
|
||||
id: "c1",
|
||||
id: 'c1',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/c1", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/c1", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/c1', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/c1', rel: 'bookmark' }
|
||||
],
|
||||
name: "cirros256"
|
||||
name: 'cirros256'
|
||||
}, {
|
||||
id: "d1",
|
||||
id: 'd1',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/d1", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/d1", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/d1', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/d1', rel: 'bookmark' }
|
||||
],
|
||||
name: "ds512M"
|
||||
name: 'ds512M'
|
||||
}, {
|
||||
id: "d2",
|
||||
id: 'd2',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/d2", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/d2", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/d2', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/d2', rel: 'bookmark' }
|
||||
],
|
||||
name: "ds1G"
|
||||
name: 'ds1G'
|
||||
}, {
|
||||
id: "d3",
|
||||
id: 'd3',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/d3", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/d3", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/d3', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/d3', rel: 'bookmark' }
|
||||
],
|
||||
name: "ds2G"
|
||||
name: 'ds2G'
|
||||
}, {
|
||||
id: "d4",
|
||||
id: 'd4',
|
||||
links: [
|
||||
{href: "http://192.168.99.99:8774/v2.1/flavors/d4", rel: "self"},
|
||||
{href: "http://192.168.99.99:8774/flavors/d4", rel: "bookmark"}
|
||||
{ href: 'http://192.168.99.99:8774/v2.1/flavors/d4', rel: 'self' },
|
||||
{ href: 'http://192.168.99.99:8774/flavors/d4', rel: 'bookmark' }
|
||||
],
|
||||
name: "ds4G"
|
||||
name: 'ds4G'
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
|
@ -184,4 +184,4 @@ export {
|
|||
rootResponse as root,
|
||||
versionedRootResponse as rootVersion,
|
||||
flavorList
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* @param {String} regionName A region name to use
|
||||
* @returns {{}} a cloud config object.
|
||||
*/
|
||||
function cloudConfig(regionName = 'RegionOne') {
|
||||
function cloudConfig (regionName = 'RegionOne') {
|
||||
return {
|
||||
region_name: regionName,
|
||||
auth: {
|
||||
|
@ -34,9 +34,9 @@ function cloudConfig(regionName = 'RegionOne') {
|
|||
project_name: 'js-openstack-lib',
|
||||
auth_url: 'http://192.168.99.99/'
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
cloudConfig as config,
|
||||
};
|
||||
cloudConfig as config
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
/**
|
||||
* URLs to match the test data below.
|
||||
*/
|
||||
const rootUrl = "http://example.com/";
|
||||
const subUrl = `${rootUrl}v1`;
|
||||
const rootUrl = 'http://example.com/'
|
||||
const subUrl = `${rootUrl}v1`
|
||||
|
||||
/**
|
||||
* A mock list of supported versions for the below requests.
|
||||
|
@ -32,72 +32,72 @@ const subUrl = `${rootUrl}v1`;
|
|||
*/
|
||||
const versions = [
|
||||
'v2.3'
|
||||
];
|
||||
]
|
||||
|
||||
/**
|
||||
* Build a new FetchMock configuration for the versions (root) endpoint.
|
||||
*
|
||||
* @returns {{}} A full FetchMock configuration for a versions resource.
|
||||
*/
|
||||
function rootResponse() {
|
||||
function rootResponse () {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: rootUrl,
|
||||
response: {
|
||||
versions: [
|
||||
{
|
||||
status: "CURRENT",
|
||||
id: "v2.3",
|
||||
status: 'CURRENT',
|
||||
id: 'v2.3',
|
||||
links: [
|
||||
{
|
||||
href: `${rootUrl}v2/`,
|
||||
rel: "self"
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v2.2",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v2.2',
|
||||
links: [
|
||||
{
|
||||
href: `${rootUrl}v2/`,
|
||||
rel: "self"
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v2.1",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v2.1',
|
||||
links: [
|
||||
{
|
||||
href: `${rootUrl}v2/`,
|
||||
rel: "self"
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v1.1",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v1.1',
|
||||
links: [
|
||||
{
|
||||
href: `${rootUrl}v1/`,
|
||||
rel: "self"
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
status: "SUPPORTED",
|
||||
id: "v1.0",
|
||||
status: 'SUPPORTED',
|
||||
id: 'v1.0',
|
||||
links: [
|
||||
{
|
||||
href: `${rootUrl}v1/`,
|
||||
rel: "self"
|
||||
rel: 'self'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,14 +106,14 @@ function rootResponse() {
|
|||
* @param {int} httpStatus The HTTP status for the response.
|
||||
* @returns {{}} A full FetchMock configuration a failing request..
|
||||
*/
|
||||
function subResponse(httpStatus = 401) {
|
||||
function subResponse (httpStatus = 401) {
|
||||
return {
|
||||
method: 'GET',
|
||||
matcher: subUrl,
|
||||
response: {
|
||||
status: httpStatus
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
|
@ -122,4 +122,4 @@ export {
|
|||
versions,
|
||||
rootResponse,
|
||||
subResponse
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,332 +1,330 @@
|
|||
import Keystone from '../../src/keystone.js';
|
||||
import * as mockData from './helpers/data/keystone';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import Keystone from '../../src/keystone.js'
|
||||
import * as mockData from './helpers/data/keystone'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
describe('Keystone', () => {
|
||||
|
||||
afterEach(fetchMock.restore);
|
||||
afterEach(fetchMock.restore)
|
||||
|
||||
it('should export a class', () => {
|
||||
const keystone = new Keystone(mockData.config);
|
||||
expect(keystone).toBeDefined();
|
||||
});
|
||||
const keystone = new Keystone(mockData.config)
|
||||
expect(keystone).toBeDefined()
|
||||
})
|
||||
|
||||
it('should throw an error for an empty config', () => {
|
||||
expect(() => new Keystone()).toThrow();
|
||||
});
|
||||
expect(() => new Keystone()).toThrow()
|
||||
})
|
||||
|
||||
describe("serviceEndpoint()", () => {
|
||||
it("Should return a valid endpoint to the keystone API.", (done) => {
|
||||
const keystone = new Keystone(mockData.config);
|
||||
describe('serviceEndpoint()', () => {
|
||||
it('Should return a valid endpoint to the keystone API.', (done) => {
|
||||
const keystone = new Keystone(mockData.config)
|
||||
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockData.root())
|
||||
|
||||
keystone.serviceEndpoint()
|
||||
.then((endpoint) => {
|
||||
expect(endpoint).toEqual('http://192.168.99.99/identity_v2_admin/v3/');
|
||||
done();
|
||||
expect(endpoint).toEqual('http://192.168.99.99/identity_v2_admin/v3/')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("tokenIssue()", () => {
|
||||
describe('tokenIssue()', () => {
|
||||
it('should "just work" by using provided credentials from the config.', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
it("should 'just work' by using provided credentials from the config.", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue()
|
||||
.then((token) => {
|
||||
expect(token).toEqual('test_token'); // From mock data
|
||||
done();
|
||||
expect(token).toEqual('test_token') // From mock data
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should support authentication with a user ID", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
it('should support authentication with a user ID', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
const userId = 'userId';
|
||||
const userId = 'userId'
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue({
|
||||
user_id: userId
|
||||
})
|
||||
.then(() => {
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body);
|
||||
expect(requestBody.auth.identity.password.user.id).toEqual(userId);
|
||||
done();
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body)
|
||||
expect(requestBody.auth.identity.password.user.id).toEqual(userId)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should support authentication with a username and a user domain ID", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
it('should support authentication with a username and a user domain ID', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
const username = 'username';
|
||||
const userDomainId = 'userDomainId';
|
||||
const username = 'username'
|
||||
const userDomainId = 'userDomainId'
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue({
|
||||
username: username,
|
||||
user_domain_id: userDomainId
|
||||
})
|
||||
.then(() => {
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body);
|
||||
expect(requestBody.auth.identity.password.user.name).toEqual(username);
|
||||
expect(requestBody.auth.identity.password.user.domain.id).toEqual(userDomainId);
|
||||
done();
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body)
|
||||
expect(requestBody.auth.identity.password.user.name).toEqual(username)
|
||||
expect(requestBody.auth.identity.password.user.domain.id).toEqual(userDomainId)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should support authentication with a username and a user domain name", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
it('should support authentication with a username and a user domain name', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
const username = 'username';
|
||||
const userDomainName = 'userDomainName';
|
||||
const username = 'username'
|
||||
const userDomainName = 'userDomainName'
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue({
|
||||
username: username,
|
||||
user_domain_name: userDomainName
|
||||
})
|
||||
.then(() => {
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body);
|
||||
expect(requestBody.auth.identity.password.user.name).toEqual(username);
|
||||
expect(requestBody.auth.identity.password.user.domain.name).toEqual(userDomainName);
|
||||
done();
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body)
|
||||
expect(requestBody.auth.identity.password.user.name).toEqual(username)
|
||||
expect(requestBody.auth.identity.password.user.domain.name).toEqual(userDomainName)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should support authentication with a project ID", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
it('should support authentication with a project ID', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
const projectId = 'projectId';
|
||||
const projectId = 'projectId'
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue({
|
||||
project_id: projectId,
|
||||
project_id: projectId
|
||||
})
|
||||
.then(() => {
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body);
|
||||
expect(requestBody.auth.scope.project.id).toEqual(projectId);
|
||||
done();
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body)
|
||||
expect(requestBody.auth.scope.project.id).toEqual(projectId)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should support authentication with a project name and a project domain ID", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
it('should support authentication with a project name and a project domain ID', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
const projectName = 'projectName';
|
||||
const projectDomainId = 'projectDomainId';
|
||||
const projectName = 'projectName'
|
||||
const projectDomainId = 'projectDomainId'
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue({
|
||||
project_name: projectName,
|
||||
project_domain_id: projectDomainId
|
||||
})
|
||||
.then(() => {
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body);
|
||||
expect(requestBody.auth.scope.project.name).toEqual(projectName);
|
||||
expect(requestBody.auth.scope.project.domain.id).toEqual(projectDomainId);
|
||||
done();
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body)
|
||||
expect(requestBody.auth.scope.project.name).toEqual(projectName)
|
||||
expect(requestBody.auth.scope.project.domain.id).toEqual(projectDomainId)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should support authentication with a project name and a project domain name", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
it('should support authentication with a project name and a project domain name', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
const projectName = 'projectName';
|
||||
const projectDomainName = 'projectDomainName';
|
||||
const projectName = 'projectName'
|
||||
const projectDomainName = 'projectDomainName'
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue({
|
||||
project_name: projectName,
|
||||
project_domain_name: projectDomainName
|
||||
})
|
||||
.then(() => {
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body);
|
||||
expect(requestBody.auth.scope.project.name).toEqual(projectName);
|
||||
expect(requestBody.auth.scope.project.domain.name).toEqual(projectDomainName);
|
||||
done();
|
||||
const requestBody = JSON.parse(fetchMock.lastCall(mockOptions.matcher)[1].body)
|
||||
expect(requestBody.auth.scope.project.name).toEqual(projectName)
|
||||
expect(requestBody.auth.scope.project.domain.name).toEqual(projectDomainName)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not cache its results", (done) => {
|
||||
let mockOptions = mockData.tokenIssue();
|
||||
fetchMock.mock(mockData.root());
|
||||
fetchMock.mock(mockOptions);
|
||||
it('Should not cache its results', (done) => {
|
||||
const mockOptions = mockData.tokenIssue()
|
||||
fetchMock.mock(mockData.root())
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
const keystone = new Keystone(mockData.config);
|
||||
const keystone = new Keystone(mockData.config)
|
||||
keystone
|
||||
.tokenIssue()
|
||||
.then((token) => {
|
||||
expect(token).toEqual('test_token'); // From mock data
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return keystone.tokenIssue();
|
||||
expect(token).toEqual('test_token') // From mock data
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return keystone.tokenIssue()
|
||||
})
|
||||
.then((token) => {
|
||||
expect(token).toEqual('test_token'); // From mock data
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(token).toEqual('test_token') // From mock data
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("tokenRevoke()", () => {
|
||||
let keystone = null;
|
||||
describe('tokenRevoke()', () => {
|
||||
let keystone = null
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock(mockData.root());
|
||||
keystone = new Keystone(mockData.config);
|
||||
});
|
||||
fetchMock.mock(mockData.root())
|
||||
keystone = new Keystone(mockData.config)
|
||||
})
|
||||
|
||||
it("should return a 204 response on a valid revocation.", (done) => {
|
||||
const token = 'test_token';
|
||||
const adminToken = 'test_admin_token';
|
||||
it('should return a 204 response on a valid revocation.', (done) => {
|
||||
const token = 'test_token'
|
||||
const adminToken = 'test_admin_token'
|
||||
|
||||
fetchMock.mock(mockData.tokenRevoke(token, adminToken));
|
||||
fetchMock.mock(mockData.tokenRevoke(token, adminToken))
|
||||
keystone
|
||||
.tokenRevoke(token, adminToken)
|
||||
.then((response) => {
|
||||
expect(response.status).toEqual(204); // From mock data
|
||||
done();
|
||||
expect(response.status).toEqual(204) // From mock data
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not cache its results", (done) => {
|
||||
const token = 'test_token';
|
||||
it('Should not cache its results', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
let mockOptions = mockData.tokenRevoke(token);
|
||||
fetchMock.mock(mockOptions);
|
||||
const mockOptions = mockData.tokenRevoke(token)
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
keystone
|
||||
.tokenRevoke(token)
|
||||
.then((response) => {
|
||||
expect(response.status).toEqual(204);
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
expect(response.status).toEqual(204)
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
|
||||
// Yes, I realize that this should actually return an error since the token is no
|
||||
// longer valid, but we're testing for promise caching here, not valid http flow.
|
||||
return keystone.tokenRevoke(token);
|
||||
return keystone.tokenRevoke(token)
|
||||
})
|
||||
.then((response) => {
|
||||
expect(response.status).toEqual(204);
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(response.status).toEqual(204)
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("tokenInfo()", () => {
|
||||
let keystone = null;
|
||||
describe('tokenInfo()', () => {
|
||||
let keystone = null
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock(mockData.root());
|
||||
keystone = new Keystone(mockData.config);
|
||||
});
|
||||
fetchMock.mock(mockData.root())
|
||||
keystone = new Keystone(mockData.config)
|
||||
})
|
||||
|
||||
const token = 'test_token';
|
||||
const token = 'test_token'
|
||||
|
||||
it("should return information about a token", (done) => {
|
||||
fetchMock.mock(mockData.tokenInfo(token));
|
||||
it('should return information about a token', (done) => {
|
||||
fetchMock.mock(mockData.tokenInfo(token))
|
||||
keystone
|
||||
.tokenInfo(token)
|
||||
.then((info) => {
|
||||
expect(info.token).toBeDefined();
|
||||
done();
|
||||
expect(info.token).toBeDefined()
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not cache its results", (done) => {
|
||||
let mockOptions = mockData.tokenInfo(token);
|
||||
fetchMock.mock(mockOptions);
|
||||
it('Should not cache its results', (done) => {
|
||||
const mockOptions = mockData.tokenInfo(token)
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
keystone
|
||||
.tokenInfo(token)
|
||||
.then((info) => {
|
||||
expect(info.token).toBeDefined();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return keystone.tokenInfo(token);
|
||||
expect(info.token).toBeDefined()
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return keystone.tokenInfo(token)
|
||||
})
|
||||
.then((info) => {
|
||||
expect(info.token).toBeDefined();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(info.token).toBeDefined()
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("catalogList()", () => {
|
||||
let keystone = null;
|
||||
describe('catalogList()', () => {
|
||||
let keystone = null
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock(mockData.root());
|
||||
keystone = new Keystone(mockData.config);
|
||||
});
|
||||
fetchMock.mock(mockData.root())
|
||||
keystone = new Keystone(mockData.config)
|
||||
})
|
||||
|
||||
it("should return the catalog as an array.", (done) => {
|
||||
const token = 'test_token';
|
||||
it('should return the catalog as an array.', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
fetchMock.mock(mockData.catalogList(token));
|
||||
fetchMock.mock(mockData.catalogList(token))
|
||||
keystone
|
||||
.catalogList(token)
|
||||
.then((catalog) => {
|
||||
expect(catalog.length).not.toBe(0);
|
||||
done();
|
||||
expect(catalog.length).not.toBe(0)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not cache its results", (done) => {
|
||||
const token = 'test_token';
|
||||
it('Should not cache its results', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
let mockOptions = mockData.catalogList(token);
|
||||
fetchMock.mock(mockOptions);
|
||||
const mockOptions = mockData.catalogList(token)
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
keystone
|
||||
.catalogList(token)
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return keystone.catalogList(token);
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return keystone.catalogList(token)
|
||||
})
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,66 +14,65 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Neutron from '../../src/neutron.js';
|
||||
import * as mockData from './helpers/data/neutron';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import Neutron from '../../src/neutron.js'
|
||||
import * as mockData from './helpers/data/neutron'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
describe('neutron', () => {
|
||||
|
||||
afterEach(fetchMock.restore);
|
||||
afterEach(fetchMock.restore)
|
||||
|
||||
it('should export a class', () => {
|
||||
const neutron = new Neutron(mockData.config);
|
||||
expect(neutron).toBeDefined();
|
||||
});
|
||||
const neutron = new Neutron(mockData.config)
|
||||
expect(neutron).toBeDefined()
|
||||
})
|
||||
|
||||
it('should throw an error for an empty config', () => {
|
||||
try {
|
||||
const neutron = new Neutron();
|
||||
neutron.versions();
|
||||
const neutron = new Neutron()
|
||||
neutron.versions()
|
||||
} catch (e) {
|
||||
expect(e.message).toEqual('An endpoint configuration is required.');
|
||||
expect(e.message).toEqual('An endpoint configuration is required.')
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
describe("networkList()", () => {
|
||||
let neutron = null;
|
||||
describe('networkList()', () => {
|
||||
let neutron = null
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock(mockData.root());
|
||||
neutron = new Neutron(mockData.config);
|
||||
});
|
||||
fetchMock.mock(mockData.root())
|
||||
neutron = new Neutron(mockData.config)
|
||||
})
|
||||
|
||||
it("should return the networks as an array.", (done) => {
|
||||
const token = 'test_token';
|
||||
it('should return the networks as an array.', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
fetchMock.mock(mockData.networkList(token));
|
||||
fetchMock.mock(mockData.networkList(token))
|
||||
neutron
|
||||
.networkList(token)
|
||||
.then((networks) => {
|
||||
expect(networks.length).toBe(2);
|
||||
done();
|
||||
expect(networks.length).toBe(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not cache its results", (done) => {
|
||||
const token = 'test_token';
|
||||
it('Should not cache its results', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
let mockOptions = mockData.networkList(token);
|
||||
fetchMock.mock(mockOptions);
|
||||
const mockOptions = mockData.networkList(token)
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
neutron
|
||||
.networkList(token)
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return neutron.networkList(token);
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return neutron.networkList(token)
|
||||
})
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,62 +14,61 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Nova from "../../src/nova.js";
|
||||
import * as mockData from "./helpers/data/nova";
|
||||
import fetchMock from "fetch-mock";
|
||||
import Nova from '../../src/nova.js'
|
||||
import * as mockData from './helpers/data/nova'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
describe('Nova', () => {
|
||||
|
||||
afterEach(fetchMock.restore);
|
||||
afterEach(fetchMock.restore)
|
||||
|
||||
it('should export a class', () => {
|
||||
const nova = new Nova(mockData.config);
|
||||
expect(nova).toBeDefined();
|
||||
});
|
||||
const nova = new Nova(mockData.config)
|
||||
expect(nova).toBeDefined()
|
||||
})
|
||||
|
||||
it('should throw an error for an empty config', () => {
|
||||
expect(() => new Nova(null)).toThrow();
|
||||
});
|
||||
expect(() => new Nova(null)).toThrow()
|
||||
})
|
||||
|
||||
describe("flavorList()", () => {
|
||||
let nova = null;
|
||||
describe('flavorList()', () => {
|
||||
let nova = null
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock(mockData.rootVersion());
|
||||
fetchMock.mock(mockData.root());
|
||||
nova = new Nova(mockData.config);
|
||||
});
|
||||
fetchMock.mock(mockData.rootVersion())
|
||||
fetchMock.mock(mockData.root())
|
||||
nova = new Nova(mockData.config)
|
||||
})
|
||||
|
||||
it("should return the flavors as an array.", (done) => {
|
||||
const token = 'test_token';
|
||||
it('should return the flavors as an array.', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
fetchMock.mock(mockData.flavorList(token));
|
||||
fetchMock.mock(mockData.flavorList(token))
|
||||
nova
|
||||
.flavorList(token)
|
||||
.then((images) => {
|
||||
expect(images.length).not.toBe(0);
|
||||
done();
|
||||
expect(images.length).not.toBe(0)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not cache its results", (done) => {
|
||||
const token = 'test_token';
|
||||
it('Should not cache its results', (done) => {
|
||||
const token = 'test_token'
|
||||
|
||||
let mockOptions = mockData.flavorList(token);
|
||||
fetchMock.mock(mockOptions);
|
||||
const mockOptions = mockData.flavorList(token)
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
nova
|
||||
.flavorList(token)
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return nova.flavorList(token);
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return nova.flavorList(token)
|
||||
})
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,290 +1,288 @@
|
|||
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 * as novaMockData from './helpers/data/nova';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import Neutron from "../../src/neutron";
|
||||
import Keystone from "../../src/keystone";
|
||||
import Glance from "../../src/glance";
|
||||
import Nova from "../../src/nova";
|
||||
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 * as novaMockData from './helpers/data/nova'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import Neutron from '../../src/neutron'
|
||||
import Keystone from '../../src/keystone'
|
||||
import Glance from '../../src/glance'
|
||||
import Nova from '../../src/nova'
|
||||
|
||||
describe("Simple test", () => {
|
||||
describe('Simple test', () => {
|
||||
afterEach(fetchMock.restore)
|
||||
|
||||
afterEach(fetchMock.restore);
|
||||
it('should export a class', () => {
|
||||
const t = new OpenStack(openStackMockData.config())
|
||||
expect(t).toBeDefined()
|
||||
})
|
||||
|
||||
it("should export a class", () => {
|
||||
let t = new OpenStack(openStackMockData.config());
|
||||
expect(t).toBeDefined();
|
||||
});
|
||||
|
||||
it("should throw an error for an empty config", () => {
|
||||
it('should throw an error for an empty config', () => {
|
||||
try {
|
||||
let t = new OpenStack();
|
||||
t.getConfig();
|
||||
const t = new OpenStack()
|
||||
t.getConfig()
|
||||
} catch (e) {
|
||||
expect(e.message).toEqual('A configuration is required.');
|
||||
expect(e.message).toEqual('A configuration is required.')
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
it("getConfig should returns the config", () => {
|
||||
let openstack = new OpenStack(openStackMockData.config());
|
||||
let config = openstack.getConfig();
|
||||
expect(config.region_name).toEqual('RegionOne');
|
||||
});
|
||||
it('getConfig should returns the config', () => {
|
||||
const openstack = new OpenStack(openStackMockData.config())
|
||||
const config = openstack.getConfig()
|
||||
expect(config.region_name).toEqual('RegionOne')
|
||||
})
|
||||
|
||||
describe('networkList', () => {
|
||||
it('should fetch networkList from neutron', (done) => {
|
||||
const openstack = new OpenStack(openStackMockData.config());
|
||||
const neutron = mockNeutron(openstack);
|
||||
const networksData = neutronMockData.networkList('token').response.networks;
|
||||
const openstack = new OpenStack(openStackMockData.config())
|
||||
const neutron = mockNeutron(openstack)
|
||||
const networksData = neutronMockData.networkList('token').response.networks
|
||||
|
||||
spyOn(neutron, 'networkList').and.returnValue(Promise.resolve(networksData));
|
||||
spyOn(neutron, 'networkList').and.returnValue(Promise.resolve(networksData))
|
||||
|
||||
openstack.networkList()
|
||||
.then((networks) => {
|
||||
expect(networks.length).toBe(2);
|
||||
done();
|
||||
expect(networks.length).toBe(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
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;
|
||||
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));
|
||||
spyOn(glance, 'imageList').and.returnValue(Promise.resolve(imagesData))
|
||||
|
||||
openstack.imageList()
|
||||
.then((images) => {
|
||||
expect(images.length).toBe(3);
|
||||
done();
|
||||
expect(images.length).toBe(3)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe('flavorList', () => {
|
||||
it('should fetch flavorList from nova', (done) => {
|
||||
const openstack = new OpenStack(openStackMockData.config());
|
||||
const nova = mockNova(openstack);
|
||||
const flavorsData = novaMockData.flavorList('token').response.flavors;
|
||||
const openstack = new OpenStack(openStackMockData.config())
|
||||
const nova = mockNova(openstack)
|
||||
const flavorsData = novaMockData.flavorList('token').response.flavors
|
||||
|
||||
spyOn(nova, 'flavorList').and.returnValue(Promise.resolve(flavorsData));
|
||||
spyOn(nova, 'flavorList').and.returnValue(Promise.resolve(flavorsData))
|
||||
|
||||
openstack.flavorList()
|
||||
.then((flavors) => {
|
||||
expect(flavors.length).toBe(12);
|
||||
done();
|
||||
expect(flavors.length).toBe(12)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe('_neutron', () => {
|
||||
it('creates Neutron 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;
|
||||
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));
|
||||
spyOn(keystone, 'tokenIssue').and.returnValue(Promise.resolve(token))
|
||||
spyOn(keystone, 'catalogList').and.returnValue(Promise.resolve(catalogData))
|
||||
|
||||
openstack._neutron
|
||||
.then((neutron) => {
|
||||
expect(keystone.catalogList).toHaveBeenCalledWith(token);
|
||||
expect(neutron).toEqual(jasmine.any(Neutron));
|
||||
expect(neutron.endpointUrl).toEqual('http://192.168.99.99:9696/');
|
||||
done();
|
||||
expect(keystone.catalogList).toHaveBeenCalledWith(token)
|
||||
expect(neutron).toEqual(jasmine.any(Neutron))
|
||||
expect(neutron.endpointUrl).toEqual('http://192.168.99.99:9696/')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.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;
|
||||
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));
|
||||
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();
|
||||
expect(neutron).toEqual(jasmine.any(Neutron))
|
||||
expect(neutron.endpointUrl).toEqual('http://192.168.99.100:9696/')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it('should cache Neutron instance and Keystone token', (done) => {
|
||||
const openstack = new OpenStack(openStackMockData.config());
|
||||
const tokenIssueMock = keystoneMockData.tokenIssue();
|
||||
const catalogListMock = keystoneMockData.catalogList('test_token');
|
||||
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);
|
||||
fetchMock.mock(keystoneMockData.root())
|
||||
fetchMock.mock(tokenIssueMock)
|
||||
fetchMock.mock(catalogListMock)
|
||||
|
||||
openstack._neutron
|
||||
.then((neutron) => {
|
||||
expect(neutron).toEqual(jasmine.any(Neutron));
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1);
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1);
|
||||
return openstack._neutron;
|
||||
expect(neutron).toEqual(jasmine.any(Neutron))
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1)
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1)
|
||||
return openstack._neutron
|
||||
})
|
||||
.then((neutron) => {
|
||||
expect(neutron).toEqual(jasmine.any(Neutron));
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1);
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1);
|
||||
done();
|
||||
expect(neutron).toEqual(jasmine.any(Neutron))
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1)
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
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;
|
||||
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));
|
||||
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();
|
||||
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))
|
||||
})
|
||||
.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');
|
||||
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);
|
||||
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;
|
||||
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();
|
||||
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))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe('_nova', () => {
|
||||
it('creates Nova 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;
|
||||
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));
|
||||
spyOn(keystone, 'tokenIssue').and.returnValue(Promise.resolve(token))
|
||||
spyOn(keystone, 'catalogList').and.returnValue(Promise.resolve(catalogData))
|
||||
|
||||
openstack._nova
|
||||
.then((nova) => {
|
||||
expect(keystone.catalogList).toHaveBeenCalledWith(token);
|
||||
expect(nova).toEqual(jasmine.any(Nova));
|
||||
expect(nova.endpointUrl).toEqual('http://192.168.99.99:8774/v2.1');
|
||||
done();
|
||||
expect(keystone.catalogList).toHaveBeenCalledWith(token)
|
||||
expect(nova).toEqual(jasmine.any(Nova))
|
||||
expect(nova.endpointUrl).toEqual('http://192.168.99.99:8774/v2.1')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it('should cache Nova instance and Keystone token', (done) => {
|
||||
const openstack = new OpenStack(openStackMockData.config());
|
||||
const tokenIssueMock = keystoneMockData.tokenIssue();
|
||||
const catalogListMock = keystoneMockData.catalogList('test_token');
|
||||
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);
|
||||
fetchMock.mock(keystoneMockData.root())
|
||||
fetchMock.mock(tokenIssueMock)
|
||||
fetchMock.mock(catalogListMock)
|
||||
|
||||
openstack._nova
|
||||
.then((nova) => {
|
||||
expect(nova).toEqual(jasmine.any(Nova));
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1);
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1);
|
||||
return openstack._nova;
|
||||
expect(nova).toEqual(jasmine.any(Nova))
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1)
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1)
|
||||
return openstack._nova
|
||||
})
|
||||
.then((nova) => {
|
||||
expect(nova).toEqual(jasmine.any(Nova));
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1);
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1);
|
||||
done();
|
||||
expect(nova).toEqual(jasmine.any(Nova))
|
||||
expect(fetchMock.calls(tokenIssueMock.matcher).length).toEqual(1)
|
||||
expect(fetchMock.calls(catalogListMock.matcher).length).toEqual(1)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe('_token', () => {
|
||||
it('should fetch the token and cache it', (done) => {
|
||||
const openstack = new OpenStack(openStackMockData.config());
|
||||
const keystone = mockKeystone(openstack);
|
||||
const openstack = new OpenStack(openStackMockData.config())
|
||||
const keystone = mockKeystone(openstack)
|
||||
|
||||
spyOn(keystone, 'tokenIssue').and.returnValue(Promise.resolve('test_token'));
|
||||
spyOn(keystone, 'tokenIssue').and.returnValue(Promise.resolve('test_token'))
|
||||
|
||||
openstack._token
|
||||
.then((token) => {
|
||||
expect(token).toEqual('test_token');
|
||||
expect(keystone.tokenIssue.calls.count()).toEqual(1);
|
||||
return openstack._token;
|
||||
expect(token).toEqual('test_token')
|
||||
expect(keystone.tokenIssue.calls.count()).toEqual(1)
|
||||
return openstack._token
|
||||
})
|
||||
.then((token) => {
|
||||
expect(token).toEqual('test_token');
|
||||
expect(keystone.tokenIssue.calls.count()).toEqual(1);
|
||||
done();
|
||||
expect(token).toEqual('test_token')
|
||||
expect(keystone.tokenIssue.calls.count()).toEqual(1)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
function mockKeystone(openstack) {
|
||||
const keystone = new Keystone(keystoneMockData.config);
|
||||
openstack._keystonePromise = Promise.resolve(keystone);
|
||||
return keystone;
|
||||
function mockKeystone (openstack) {
|
||||
const keystone = new Keystone(keystoneMockData.config)
|
||||
openstack._keystonePromise = Promise.resolve(keystone)
|
||||
return keystone
|
||||
}
|
||||
|
||||
function mockNeutron(openstack) {
|
||||
const neutron = new Neutron(neutronMockData.config);
|
||||
openstack._neutronPromise = Promise.resolve(neutron);
|
||||
return neutron;
|
||||
function mockNeutron (openstack) {
|
||||
const neutron = new Neutron(neutronMockData.config)
|
||||
openstack._neutronPromise = Promise.resolve(neutron)
|
||||
return neutron
|
||||
}
|
||||
|
||||
function mockGlance(openstack) {
|
||||
const glance = new Glance(glanceMockData.config);
|
||||
openstack._glancePromise = Promise.resolve(glance);
|
||||
return glance;
|
||||
function mockGlance (openstack) {
|
||||
const glance = new Glance(glanceMockData.config)
|
||||
openstack._glancePromise = Promise.resolve(glance)
|
||||
return glance
|
||||
}
|
||||
|
||||
function mockNova(openstack) {
|
||||
const nova = new Nova(novaMockData.config);
|
||||
openstack._novaPromise = Promise.resolve(nova);
|
||||
return nova;
|
||||
function mockNova (openstack) {
|
||||
const nova = new Nova(novaMockData.config)
|
||||
openstack._novaPromise = Promise.resolve(nova)
|
||||
return nova
|
||||
}
|
||||
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Jasmine from 'jasmine';
|
||||
import Jasmine from 'jasmine'
|
||||
|
||||
const jasmine = new Jasmine();
|
||||
jasmine.loadConfigFile('test/unit/jasmine.json');
|
||||
jasmine.execute();
|
||||
const jasmine = new Jasmine()
|
||||
jasmine.loadConfigFile('test/unit/jasmine.json')
|
||||
jasmine.execute()
|
||||
|
|
|
@ -14,235 +14,231 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import AbstractService from "../../../src/util/abstractService";
|
||||
import * as mockData from "../helpers/data/versions";
|
||||
import fetchMock from "fetch-mock"; // Might as well use service
|
||||
import AbstractService from '../../../src/util/abstractService'
|
||||
import * as mockData from '../helpers/data/versions'
|
||||
import fetchMock from 'fetch-mock' // Might as well use service
|
||||
|
||||
describe('AbstractService', () => {
|
||||
|
||||
afterEach(fetchMock.restore);
|
||||
afterEach(fetchMock.restore)
|
||||
|
||||
it('should provide a singleton HTTP instance', () => {
|
||||
let service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
|
||||
expect(service._http).toBeUndefined();
|
||||
let http1 = service.http;
|
||||
expect(service._http).toBeDefined();
|
||||
expect(http1).not.toBeNull();
|
||||
let http2 = service.http;
|
||||
expect(http1).toBe(http2);
|
||||
});
|
||||
expect(service._http).toBeUndefined()
|
||||
const http1 = service.http
|
||||
expect(service._http).toBeDefined()
|
||||
expect(http1).not.toBeNull()
|
||||
const http2 = service.http
|
||||
expect(http1).toBe(http2)
|
||||
})
|
||||
|
||||
it('should return supported versions', () => {
|
||||
let service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
expect(service.supportedVersions).toEqual(mockData.versions);
|
||||
});
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
expect(service.supportedVersions).toEqual(mockData.versions)
|
||||
})
|
||||
|
||||
it('should return an empty array if no versions are configured', () => {
|
||||
let service = new AbstractService(mockData.rootUrl, null);
|
||||
expect(service.supportedVersions).toEqual([]);
|
||||
});
|
||||
const service = new AbstractService(mockData.rootUrl, null)
|
||||
expect(service.supportedVersions).toEqual([])
|
||||
})
|
||||
|
||||
describe("versions()", () => {
|
||||
describe('versions()', () => {
|
||||
it('Should return a list of all versions available from this resource', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
|
||||
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());
|
||||
fetchMock.mock(mockData.rootResponse())
|
||||
|
||||
service.versions()
|
||||
.then((versions) => {
|
||||
// Quick sanity check.
|
||||
expect(versions.length).toBe(5);
|
||||
expect(versions[0].major).toEqual(2);
|
||||
expect(versions[0].minor).toEqual(3);
|
||||
expect(versions[0].patch).toEqual(0);
|
||||
expect(versions[0].links).not.toBe(null);
|
||||
expect(versions[0].links[0].href).toEqual('http://example.com/v2/');
|
||||
done();
|
||||
expect(versions.length).toBe(5)
|
||||
expect(versions[0].major).toEqual(2)
|
||||
expect(versions[0].minor).toEqual(3)
|
||||
expect(versions[0].patch).toEqual(0)
|
||||
expect(versions[0].links).not.toBe(null)
|
||||
expect(versions[0].links[0].href).toEqual('http://example.com/v2/')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
// This test catches the case when the service catalog already points
|
||||
// at an API version.
|
||||
it("Should retry at the root URL if a 401 is encountered", (done) => {
|
||||
const service = new AbstractService(mockData.subUrl, mockData.versions);
|
||||
it('Should retry at the root URL if a 401 is encountered', (done) => {
|
||||
const service = new AbstractService(mockData.subUrl, mockData.versions)
|
||||
|
||||
fetchMock.mock(mockData.subResponse());
|
||||
fetchMock.mock(mockData.rootResponse());
|
||||
fetchMock.mock(mockData.subResponse())
|
||||
fetchMock.mock(mockData.rootResponse())
|
||||
|
||||
service.versions()
|
||||
.then((versions) => {
|
||||
// Quick sanity check.
|
||||
expect(versions.length).toBe(5);
|
||||
done();
|
||||
expect(versions.length).toBe(5)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should not retry at the root URL if a different status is encountered", (done) => {
|
||||
const service = new AbstractService(mockData.subUrl, mockData.versions);
|
||||
it('Should not retry at the root URL if a different status is encountered', (done) => {
|
||||
const service = new AbstractService(mockData.subUrl, mockData.versions)
|
||||
|
||||
fetchMock.mock(mockData.subResponse(500));
|
||||
fetchMock.mock(mockData.subResponse(500))
|
||||
|
||||
service.versions()
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("Should NOT cache its results", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
const mockOptions = mockData.rootResponse();
|
||||
it('Should NOT cache its results', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
const mockOptions = mockData.rootResponse()
|
||||
|
||||
fetchMock.mock(mockOptions);
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
service.versions()
|
||||
.then(() => {
|
||||
// Validate that the mock has only been invoked once
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return service.versions();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return service.versions()
|
||||
})
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("version()", () => {
|
||||
describe('version()', () => {
|
||||
it('Should return a supported version of the service API.', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
|
||||
it("Should return a supported version of the service API.", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
|
||||
fetchMock.mock(mockData.rootResponse());
|
||||
fetchMock.mock(mockData.rootResponse())
|
||||
|
||||
service.version()
|
||||
.then((version) => {
|
||||
expect(version.equals('v2.3')).toBe(true);
|
||||
done();
|
||||
expect(version.equals('v2.3')).toBe(true)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should return the latest compatible version of the service API.", (done) => {
|
||||
it('Should return the latest compatible version of the service API.', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, [
|
||||
'v2.0'
|
||||
]);
|
||||
])
|
||||
|
||||
fetchMock.mock(mockData.rootResponse());
|
||||
fetchMock.mock(mockData.rootResponse())
|
||||
|
||||
service.version()
|
||||
.then((version) => {
|
||||
expect(version.equals('v2.3')).toBe(true);
|
||||
done();
|
||||
expect(version.equals('v2.3')).toBe(true)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should throw an exception if no supported version is found.", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
it('Should throw an exception if no supported version is found.', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
|
||||
// Build an invalid mock object.
|
||||
const mockOptions = mockData.rootResponse();
|
||||
mockOptions.response.versions.shift();
|
||||
const mockOptions = mockData.rootResponse()
|
||||
mockOptions.response.versions.shift()
|
||||
|
||||
fetchMock.mock(mockOptions);
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
service.version()
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("Should NOT cache its results", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
const mockOptions = mockData.rootResponse();
|
||||
fetchMock.mock(mockOptions);
|
||||
it('Should NOT cache its results', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
const mockOptions = mockData.rootResponse()
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
service.version()
|
||||
.then(() => {
|
||||
// Validate that the mock has only been invoked once
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return service.version();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return service.version()
|
||||
})
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2);
|
||||
done();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(2)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
|
||||
describe("serviceEndpoint()", () => {
|
||||
describe('serviceEndpoint()', () => {
|
||||
it('Should return a valid endpoint to the API.', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
|
||||
it("Should return a valid endpoint to the API.", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
|
||||
fetchMock.mock(mockData.rootResponse());
|
||||
fetchMock.mock(mockData.rootResponse())
|
||||
|
||||
service.serviceEndpoint()
|
||||
.then((endpoint) => {
|
||||
expect(endpoint).toEqual('http://example.com/v2/');
|
||||
done();
|
||||
expect(endpoint).toEqual('http://example.com/v2/')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("Should throw an exception if no endpoint is provided.", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
it('Should throw an exception if no endpoint is provided.', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
|
||||
// Build an exception payload.
|
||||
const mockOptions = mockData.rootResponse();
|
||||
mockOptions.response.versions[0].links = [];
|
||||
fetchMock.mock(mockOptions);
|
||||
const mockOptions = mockData.rootResponse()
|
||||
mockOptions.response.versions[0].links = []
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
service.serviceEndpoint()
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("Should throw an exception if no links array exists.", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
it('Should throw an exception if no links array exists.', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
|
||||
// Build an exception payload.
|
||||
const mockOptions = mockData.rootResponse();
|
||||
delete mockOptions.response.versions[0].links;
|
||||
fetchMock.mock(mockOptions);
|
||||
const mockOptions = mockData.rootResponse()
|
||||
delete mockOptions.response.versions[0].links
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
service.serviceEndpoint()
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(error).not.toBeNull()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("Should cache its results", (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions);
|
||||
const mockOptions = mockData.rootResponse();
|
||||
fetchMock.mock(mockOptions);
|
||||
it('Should cache its results', (done) => {
|
||||
const service = new AbstractService(mockData.rootUrl, mockData.versions)
|
||||
const mockOptions = mockData.rootResponse()
|
||||
fetchMock.mock(mockOptions)
|
||||
|
||||
service.serviceEndpoint()
|
||||
.then(() => {
|
||||
// Validate that the mock has only been invoked once
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
return service.serviceEndpoint();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
return service.serviceEndpoint()
|
||||
})
|
||||
.then(() => {
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1);
|
||||
done();
|
||||
expect(fetchMock.calls(mockOptions.matcher).length).toEqual(1)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,122 +14,122 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Http from '../../../src/util/http.js';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import Http from '../../../src/util/http.js'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
describe('Http', () => {
|
||||
let http;
|
||||
const testUrl = 'https://example.com/';
|
||||
const testRequest = {lol: 'cat'};
|
||||
const testResponse = {foo: 'bar'};
|
||||
let http
|
||||
const testUrl = 'https://example.com/'
|
||||
const testRequest = { lol: 'cat' }
|
||||
const testResponse = { foo: 'bar' }
|
||||
|
||||
beforeEach(() => {
|
||||
http = new Http();
|
||||
});
|
||||
http = new Http()
|
||||
})
|
||||
|
||||
afterEach(fetchMock.restore);
|
||||
afterEach(fetchMock.restore)
|
||||
|
||||
it("should permit manually constructing requests", (done) => {
|
||||
fetchMock.get(testUrl, testResponse);
|
||||
it('should permit manually constructing requests', (done) => {
|
||||
fetchMock.get(testUrl, testResponse)
|
||||
|
||||
http.httpRequest('GET', testUrl)
|
||||
.then((response) => response.json())
|
||||
.then((body) => {
|
||||
expect(fetchMock.called(testUrl)).toBe(true);
|
||||
expect(body).toEqual(testResponse);
|
||||
done();
|
||||
expect(fetchMock.called(testUrl)).toBe(true)
|
||||
expect(body).toEqual(testResponse)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should make GET requests", (done) => {
|
||||
fetchMock.get(testUrl, testResponse);
|
||||
it('should make GET requests', (done) => {
|
||||
fetchMock.get(testUrl, testResponse)
|
||||
|
||||
http.httpGet(testUrl)
|
||||
.then((response) => response.json())
|
||||
.then((body) => {
|
||||
expect(fetchMock.called(testUrl)).toBe(true);
|
||||
expect(body).toEqual(testResponse);
|
||||
done();
|
||||
expect(fetchMock.called(testUrl)).toBe(true)
|
||||
expect(body).toEqual(testResponse)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should make PUT requests", (done) => {
|
||||
fetchMock.put(testUrl, testResponse, testRequest);
|
||||
it('should make PUT requests', (done) => {
|
||||
fetchMock.put(testUrl, testResponse, testRequest)
|
||||
|
||||
http.httpPut(testUrl, testRequest)
|
||||
.then((response) => response.json())
|
||||
.then((body) => {
|
||||
expect(fetchMock.called(testUrl)).toEqual(true);
|
||||
expect(body).toEqual(testResponse);
|
||||
done();
|
||||
expect(fetchMock.called(testUrl)).toEqual(true)
|
||||
expect(body).toEqual(testResponse)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should make POST requests", (done) => {
|
||||
fetchMock.post(testUrl, testResponse, testRequest);
|
||||
it('should make POST requests', (done) => {
|
||||
fetchMock.post(testUrl, testResponse, testRequest)
|
||||
|
||||
http.httpPost(testUrl, testRequest)
|
||||
.then((response) => response.json())
|
||||
.then((body) => {
|
||||
expect(fetchMock.called(testUrl)).toEqual(true);
|
||||
expect(body).toEqual(testResponse);
|
||||
done();
|
||||
expect(fetchMock.called(testUrl)).toEqual(true)
|
||||
expect(body).toEqual(testResponse)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should make DELETE requests", (done) => {
|
||||
fetchMock.delete(testUrl, testRequest);
|
||||
it('should make DELETE requests', (done) => {
|
||||
fetchMock.delete(testUrl, testRequest)
|
||||
|
||||
http.httpDelete(testUrl, testRequest)
|
||||
.then(() => {
|
||||
expect(fetchMock.called(testUrl)).toEqual(true);
|
||||
done();
|
||||
expect(fetchMock.called(testUrl)).toEqual(true)
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should permit setting default headers", (done) => {
|
||||
http.defaultHeaders['Custom-Header'] = 'Custom-Value';
|
||||
fetchMock.get(testUrl, testResponse);
|
||||
it('should permit setting default headers', (done) => {
|
||||
http.defaultHeaders['Custom-Header'] = 'Custom-Value'
|
||||
fetchMock.get(testUrl, testResponse)
|
||||
|
||||
http.httpGet(testUrl)
|
||||
.then(() => {
|
||||
let headers = fetchMock.lastOptions().headers;
|
||||
expect(headers['Custom-Header']).toEqual('Custom-Value');
|
||||
done();
|
||||
const headers = fetchMock.lastOptions().headers
|
||||
expect(headers['Custom-Header']).toEqual('Custom-Value')
|
||||
done()
|
||||
})
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
|
||||
it("should pass exceptions back to the invoker", (done) => {
|
||||
it('should pass exceptions back to the invoker', (done) => {
|
||||
fetchMock.get(testUrl, () => {
|
||||
throw new TypeError(); // Example- net::ERR_NAME_NOT_RESOLVED
|
||||
});
|
||||
throw new TypeError() // Example- net::ERR_NAME_NOT_RESOLVED
|
||||
})
|
||||
|
||||
http.httpGet(testUrl)
|
||||
.then((response) => done.fail(response))
|
||||
.catch((error) => {
|
||||
expect(error.stack).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(error.stack).toBeDefined()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("should pass failed requests to the catch block.", (done) => {
|
||||
fetchMock.get(testUrl, {status: 500, body: testResponse});
|
||||
it('should pass failed requests to the catch block.', (done) => {
|
||||
fetchMock.get(testUrl, { status: 500, body: testResponse })
|
||||
|
||||
http.httpGet(testUrl)
|
||||
.then((response) => done.fail(response))
|
||||
.catch((response) => {
|
||||
expect(response.status).toBe(500);
|
||||
done();
|
||||
});
|
||||
});
|
||||
expect(response.status).toBe(500)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it("should not interfere with mocks that have matching headers.", (done) => {
|
||||
it('should not interfere with mocks that have matching headers.', (done) => {
|
||||
fetchMock.mock({
|
||||
method: 'GET',
|
||||
matcher: testUrl,
|
||||
|
@ -137,11 +137,11 @@ describe('Http', () => {
|
|||
'Content-Type': 'application/json'
|
||||
},
|
||||
response: testResponse
|
||||
});
|
||||
})
|
||||
|
||||
http
|
||||
.httpRequest('GET', testUrl, {'Content-Type': 'application/json'})
|
||||
.httpRequest('GET', testUrl, { 'Content-Type': 'application/json' })
|
||||
.then(() => done())
|
||||
.catch((error) => done.fail(error));
|
||||
});
|
||||
});
|
||||
.catch((error) => done.fail(error))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,145 +14,143 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Version from '../../../src/util/version.js';
|
||||
import Version from '../../../src/util/version.js'
|
||||
|
||||
describe('Version', () => {
|
||||
it('should parse various header versions', () => {
|
||||
const testVersion = function (args, results) {
|
||||
const v = new Version(...args)
|
||||
expect(v.service).toBe(results[0])
|
||||
expect(v.major).toBe(results[1])
|
||||
expect(v.minor).toBe(results[2])
|
||||
expect(v.patch).toBe(results[3])
|
||||
}
|
||||
|
||||
it("should parse various header versions", () => {
|
||||
|
||||
const testVersion = function(args, results) {
|
||||
const v = new Version(...args);
|
||||
expect(v.service).toBe(results[0]);
|
||||
expect(v.major).toBe(results[1]);
|
||||
expect(v.minor).toBe(results[2]);
|
||||
expect(v.patch).toBe(results[3]);
|
||||
};
|
||||
|
||||
testVersion(['identity 1.2'], ['identity', 1, 2, 0]);
|
||||
testVersion(['identity 0.2'], ['identity', 0, 2, 0]);
|
||||
testVersion(['compute 2222222.09'], ['compute', 2222222, 9, 0]);
|
||||
testVersion(['compute 03.09'], ['compute', 3, 9, 0]);
|
||||
testVersion(['compute 03.0'], ['compute', 3, 0, 0]);
|
||||
testVersion(['compute 1'], ['compute', 1, 0, 0]);
|
||||
testVersion(['compute 0'], ['compute', 0, 0, 0]);
|
||||
testVersion(['v2.1.1'], [null, 2, 1, 1]);
|
||||
testVersion(['v2.1'], [null, 2, 1, 0]);
|
||||
testVersion(['v2'], [null, 2, 0, 0]);
|
||||
testVersion(['v'], [null, 0, 0, 0]);
|
||||
testVersion(['v0.2'], [null, 0, 2, 0]);
|
||||
testVersion(['2.1.1'], [null, 2, 1, 1]);
|
||||
testVersion(['2.1'], [null, 2, 1, 0]);
|
||||
testVersion(['2'], [null, 2, 0, 0]);
|
||||
testVersion([''], [null, 0, 0, 0]);
|
||||
testVersion(['0.2'], [null, 0, 2, 0]);
|
||||
testVersion(['compute', 'v2.1.1'], ['compute', 2, 1, 1]);
|
||||
testVersion(['compute', 'v2.1'], ['compute', 2, 1, 0]);
|
||||
testVersion(['compute', 'v2'], ['compute', 2, 0, 0]);
|
||||
testVersion(['compute', 'v'], ['compute', 0, 0, 0]);
|
||||
testVersion(['compute', 'v0.2'], ['compute', 0, 2, 0]);
|
||||
testVersion(['compute', '2.1.1'], ['compute', 2, 1, 1]);
|
||||
testVersion(['compute', '2.1'], ['compute', 2, 1, 0]);
|
||||
testVersion(['compute', '2'], ['compute', 2, 0, 0]);
|
||||
testVersion(['compute', ''], ['compute', 0, 0, 0]);
|
||||
testVersion(['compute', '0.2'], ['compute', 0, 2, 0]);
|
||||
testVersion(['identity 1.2'], ['identity', 1, 2, 0])
|
||||
testVersion(['identity 0.2'], ['identity', 0, 2, 0])
|
||||
testVersion(['compute 2222222.09'], ['compute', 2222222, 9, 0])
|
||||
testVersion(['compute 03.09'], ['compute', 3, 9, 0])
|
||||
testVersion(['compute 03.0'], ['compute', 3, 0, 0])
|
||||
testVersion(['compute 1'], ['compute', 1, 0, 0])
|
||||
testVersion(['compute 0'], ['compute', 0, 0, 0])
|
||||
testVersion(['v2.1.1'], [null, 2, 1, 1])
|
||||
testVersion(['v2.1'], [null, 2, 1, 0])
|
||||
testVersion(['v2'], [null, 2, 0, 0])
|
||||
testVersion(['v'], [null, 0, 0, 0])
|
||||
testVersion(['v0.2'], [null, 0, 2, 0])
|
||||
testVersion(['2.1.1'], [null, 2, 1, 1])
|
||||
testVersion(['2.1'], [null, 2, 1, 0])
|
||||
testVersion(['2'], [null, 2, 0, 0])
|
||||
testVersion([''], [null, 0, 0, 0])
|
||||
testVersion(['0.2'], [null, 0, 2, 0])
|
||||
testVersion(['compute', 'v2.1.1'], ['compute', 2, 1, 1])
|
||||
testVersion(['compute', 'v2.1'], ['compute', 2, 1, 0])
|
||||
testVersion(['compute', 'v2'], ['compute', 2, 0, 0])
|
||||
testVersion(['compute', 'v'], ['compute', 0, 0, 0])
|
||||
testVersion(['compute', 'v0.2'], ['compute', 0, 2, 0])
|
||||
testVersion(['compute', '2.1.1'], ['compute', 2, 1, 1])
|
||||
testVersion(['compute', '2.1'], ['compute', 2, 1, 0])
|
||||
testVersion(['compute', '2'], ['compute', 2, 0, 0])
|
||||
testVersion(['compute', ''], ['compute', 0, 0, 0])
|
||||
testVersion(['compute', '0.2'], ['compute', 0, 2, 0])
|
||||
|
||||
// Invalid inputs...
|
||||
testVersion([null, null], [null, 0, 0, 0]);
|
||||
testVersion([{}, {}], [null, 0, 0, 0]);
|
||||
testVersion([null, {}], [null, 0, 0, 0]);
|
||||
testVersion([{}, null], [null, 0, 0, 0]);
|
||||
});
|
||||
testVersion([null, null], [null, 0, 0, 0])
|
||||
testVersion([{}, {}], [null, 0, 0, 0])
|
||||
testVersion([null, {}], [null, 0, 0, 0])
|
||||
testVersion([{}, null], [null, 0, 0, 0])
|
||||
})
|
||||
|
||||
it("should test for correct equality", () => {
|
||||
const v1 = new Version("compute", "1.0.0");
|
||||
it('should test for correct equality', () => {
|
||||
const v1 = new Version('compute', '1.0.0')
|
||||
|
||||
// String tests...
|
||||
expect(v1.equals("compute 1.0.0")).toBe(true);
|
||||
expect(v1.equals("compute 1.0.1")).toBe(false);
|
||||
expect(v1.equals("identity 1.0.0")).toBe(false);
|
||||
expect(v1.equals('compute 1.0.0')).toBe(true)
|
||||
expect(v1.equals('compute 1.0.1')).toBe(false)
|
||||
expect(v1.equals('identity 1.0.0')).toBe(false)
|
||||
|
||||
// Version tests
|
||||
expect(v1.equals(new Version("compute 1.0.0"))).toBe(true);
|
||||
expect(v1.equals(new Version("compute 1.0.1"))).toBe(false);
|
||||
expect(v1.equals(new Version("identity 1.0.0"))).toBe(false);
|
||||
expect(v1.equals(new Version("1.0.0"))).toBe(false);
|
||||
expect(v1.equals(new Version('compute 1.0.0'))).toBe(true)
|
||||
expect(v1.equals(new Version('compute 1.0.1'))).toBe(false)
|
||||
expect(v1.equals(new Version('identity 1.0.0'))).toBe(false)
|
||||
expect(v1.equals(new Version('1.0.0'))).toBe(false)
|
||||
|
||||
// Other tests...
|
||||
expect(v1.equals({})).toBe(false);
|
||||
expect(v1.equals({})).toBe(false)
|
||||
|
||||
const v2 = new Version("1.0.0");
|
||||
const v2 = new Version('1.0.0')
|
||||
|
||||
// String tests...
|
||||
expect(v2.equals("compute 1.0.0")).toBe(false);
|
||||
expect(v2.equals("compute 1.0.1")).toBe(false);
|
||||
expect(v2.equals("1.0.0")).toBe(true);
|
||||
expect(v2.equals('compute 1.0.0')).toBe(false)
|
||||
expect(v2.equals('compute 1.0.1')).toBe(false)
|
||||
expect(v2.equals('1.0.0')).toBe(true)
|
||||
|
||||
// Version tests
|
||||
expect(v2.equals(new Version("compute 1.0.0"))).toBe(false);
|
||||
expect(v2.equals(new Version("compute 1.0.1"))).toBe(false);
|
||||
expect(v2.equals(new Version("identity 1.0.0"))).toBe(false);
|
||||
expect(v2.equals(new Version("1.0.0"))).toBe(true);
|
||||
expect(v2.equals(new Version('compute 1.0.0'))).toBe(false)
|
||||
expect(v2.equals(new Version('compute 1.0.1'))).toBe(false)
|
||||
expect(v2.equals(new Version('identity 1.0.0'))).toBe(false)
|
||||
expect(v2.equals(new Version('1.0.0'))).toBe(true)
|
||||
|
||||
// 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");
|
||||
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);
|
||||
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);
|
||||
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");
|
||||
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);
|
||||
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);
|
||||
});
|
||||
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");
|
||||
it('should store links', () => {
|
||||
const v1 = new Version('compute', '1.3.2')
|
||||
|
||||
expect(v1.links).toBe(null);
|
||||
expect(v1.links).toBe(null)
|
||||
|
||||
v1.links = 'wrong data';
|
||||
expect(v1.links).toBe(null);
|
||||
v1.links = 'wrong data'
|
||||
expect(v1.links).toBe(null)
|
||||
|
||||
v1.links = [
|
||||
{
|
||||
href: `http://example.org/v2/`,
|
||||
rel: "self"
|
||||
href: 'http://example.org/v2/',
|
||||
rel: 'self'
|
||||
}
|
||||
];
|
||||
expect(v1.links).not.toBe(null);
|
||||
expect(v1.links.length).toBe(1);
|
||||
]
|
||||
expect(v1.links).not.toBe(null)
|
||||
expect(v1.links.length).toBe(1)
|
||||
expect(v1.links[0]).toEqual({
|
||||
href: "http://example.org/v2/",
|
||||
rel: "self"
|
||||
});
|
||||
});
|
||||
});
|
||||
href: 'http://example.org/v2/',
|
||||
rel: 'self'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import cloudsYamlPath from './test/functional/helpers/cloudsYamlPath';
|
||||
import path from 'path'
|
||||
import webpack from 'webpack'
|
||||
import cloudsYamlPath from './test/functional/helpers/cloudsYamlPath'
|
||||
|
||||
export default {
|
||||
entry: ['./src/index.js'],
|
||||
|
@ -23,13 +23,13 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.NormalModuleReplacementPlugin(/helpers\/cloudsConfig/,
|
||||
'json!yaml!' + cloudsYamlPath)
|
||||
],
|
||||
node: {
|
||||
fs: "empty"
|
||||
fs: 'empty'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
- project:
|
||||
templates:
|
||||
- nodejs8-docs
|
||||
- nodejs8-jobs
|
||||
- nodejs8-publish-to-npm
|
||||
check:
|
||||
jobs:
|
||||
- nodejs-run-lint
|
||||
- nodejs-run-test-browser
|
||||
- js-openstack-lib-unit-tests-nodejs12
|
||||
gate:
|
||||
jobs:
|
||||
- nodejs-run-lint
|
||||
- nodejs-run-test-browser
|
||||
- js-openstack-lib-unit-tests-nodejs12
|
||||
experimental:
|
||||
jobs:
|
||||
|
|
Loading…
Reference in New Issue