Passed tokens may now be promises.

Tokens passed to token-requiring API methods may now also be promises,
permitting promise-based request chaining across API's. For example:

keystone
  .issueToken()
  .then((token) => glance.imageList(token));

...or:

const tokenPromise = keystone.issueToken();

Promise.all([
  glance.imageList(tokenPromise),
  neutron.networkList(tokenPromise),
  nova.flavorList(tokenPromise)
]).then(([images, networks, flavors]) => {
  return nova.instanceCreate( ... );
});

These updates have been wrapped into a private method, which can
be used for other API's as well. revokeToken is the noted exception,
as it may have to resolve TWO tokens (auth and subject).

Change-Id: I24e0a1e979d2aaedc6a25e378bd9d99f51ece595
This commit is contained in:
Michael Krotscheck 2016-08-26 12:14:35 -07:00
parent c98bc9cd23
commit 3bce487421
1 changed files with 35 additions and 14 deletions

View File

@ -56,6 +56,30 @@ export default class Keystone {
return pointer;
}
/**
* This method builds common components of a keystone request. It converts any passed token
* into a promise, resolves the base URL, and then passes the results as an .all() promise,
* which may be destructured in a followup request.
*
* @param {Promise|String} token A promise, or string, representing a token.
* @returns {Promise} A promise which resolves with [url, token].
* @private
*/
_requestComponents (token = null) {
// Make sure the token is a promise.
let headerPromise = Promise
.resolve(token)
.then((token) => {
if (token) {
return {
'X-Auth-Token': token
};
}
return {};
});
return Promise.all([this.serviceEndpoint(), headerPromise]);
}
/**
* Retrieve all the API versions available.
*
@ -186,13 +210,15 @@ export default class Keystone {
* @returns {Promise.<T>} A promise which will resolve if the token has been successfully revoked.
*/
tokenRevoke (token, adminToken = null) {
let headers = {
'X-Subject-Token': token,
'X-Auth-Token': adminToken || token
};
return this.serviceEndpoint()
.then((url) => this.http.httpRequest('DELETE', `${url}auth/tokens`, headers));
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));
}
/**
@ -202,14 +228,9 @@ export default class Keystone {
* @returns {Promise.<T>} A promise which will resolve with the service catalog.
*/
catalogList (token = null) {
const headers = {};
if (token) {
headers['X-Auth-Token'] = token;
}
return this
.serviceEndpoint()
.then((url) => this.http.httpRequest('GET', `${url}auth/catalog`, headers))
._requestComponents(token)
.then(([url, headers]) => this.http.httpRequest('GET', `${url}auth/catalog`, headers))
.then((response) => response.json())
.then((body) => body.catalog);
}