Added basic Keystone authentication
authenticate() is called outside the constructor so that the Keystone class plays nicely with Promises. (It would be weird for the constructor to return a Promise) Change-Id: I3f9008d4d954c340178c77ec0433c5a1ddc971d2
This commit is contained in:
parent
4e9cf48b43
commit
e09ccbd473
|
@ -0,0 +1,52 @@
|
|||
import 'isomorphic-fetch';
|
||||
import log from 'loglevel';
|
||||
|
||||
log.setLevel('INFO');
|
||||
|
||||
export default class Keystone {
|
||||
|
||||
constructor(cloudsConfig, cloudName) {
|
||||
if (cloudsConfig.clouds.hasOwnProperty(cloudName)) {
|
||||
this.cloudConfig = cloudsConfig.clouds[cloudName];
|
||||
} else {
|
||||
throw new Error('Config for this cloud not found');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
authenticate() {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
const body = {
|
||||
auth: {
|
||||
identity: {
|
||||
methods: ['password'],
|
||||
password: {
|
||||
user: {
|
||||
name: this.cloudConfig.auth.username,
|
||||
password: this.cloudConfig.auth.password
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const init = {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
body: JSON.stringify(body)
|
||||
};
|
||||
|
||||
return fetch(this.cloudConfig.auth.auth_url, init)
|
||||
.then((res) => {
|
||||
this.token = res.headers.get('X-Subject-Token');
|
||||
return res.json(); // This returns a promise...
|
||||
})
|
||||
.then((body) => {
|
||||
this.catalog = body.catalog || {};
|
||||
})
|
||||
.catch((reason) => {
|
||||
return reason;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import Keystone from '../../src/keystone.js';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
describe('Openstack connection test', () => {
|
||||
it('should export a class', () => {
|
||||
const keystone = new Keystone(aCloudsConfig('cloud1'), 'cloud1');
|
||||
expect(keystone).toBeDefined();
|
||||
});
|
||||
|
||||
it('should throw an error for an unknown cloud', () => {
|
||||
const cloudsConfig = aCloudsConfig('cloud1');
|
||||
const cloudName = 'cloud2';
|
||||
|
||||
try {
|
||||
const keystone = new Keystone(cloudsConfig, cloudName);
|
||||
keystone.authenticate();
|
||||
} catch (e) {
|
||||
expect(e.message).toEqual('Config for this cloud not found');
|
||||
}
|
||||
});
|
||||
|
||||
it('should authenticate', (done) => {
|
||||
const cloudsConfig = aCloudsConfig('cloud1');
|
||||
|
||||
const authUrl = cloudsConfig.clouds.cloud1.auth.auth_url;
|
||||
|
||||
const cloudName = 'cloud1';
|
||||
|
||||
fetchMock
|
||||
.post(authUrl, {
|
||||
body: {
|
||||
catalog: {
|
||||
foo: 'bar'
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
'X-Subject-Token': 'the-token'
|
||||
}
|
||||
});
|
||||
|
||||
const keystone = new Keystone(cloudsConfig, cloudName);
|
||||
|
||||
keystone.authenticate()
|
||||
.then(() => {
|
||||
expect(fetchMock.called(authUrl)).toEqual(true);
|
||||
expect(typeof keystone.token).toEqual('string');
|
||||
expect(keystone.token).toEqual('the-token');
|
||||
expect(keystone.catalog).toEqual({foo: 'bar'});
|
||||
done();
|
||||
})
|
||||
.catch((reason) => {
|
||||
expect(reason).toBeUndefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
function aCloudsConfig (name) {
|
||||
const cloudsConfig = {
|
||||
clouds: {}
|
||||
};
|
||||
|
||||
cloudsConfig.clouds[name] = {
|
||||
region_name: 'Region1',
|
||||
auth: {
|
||||
username: 'user',
|
||||
password: 'pass',
|
||||
project_name: 'js-openstack-lib',
|
||||
auth_url: 'http://keystone'
|
||||
}
|
||||
};
|
||||
|
||||
return cloudsConfig;
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue