Skip to content

Commit 3d6bbe7

Browse files
committed
Merge pull request #448 from mick/creds_lock
Add lock around AWS.MetadataService.loadCredentials()
2 parents b768e76 + 0c70713 commit 3d6bbe7

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

lib/metadata_service.js

+25-8
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,19 @@ AWS.MetadataService = inherit({
6767
var httpRequest = new AWS.HttpRequest('http://' + this.host + path);
6868
httpRequest.method = 'GET';
6969

70-
http.handleRequest(httpRequest, this.httpOptions, function(httpResponse) {
71-
httpResponse.on('data', function(chunk) { data += chunk.toString(); });
72-
httpResponse.on('end', function() { callback(null, data); });
73-
}, callback);
70+
process.nextTick(function() {
71+
http.handleRequest(httpRequest, this.httpOptions, function(httpResponse) {
72+
httpResponse.on('data', function(chunk) { data += chunk.toString(); });
73+
httpResponse.on('end', function() { callback(null, data); });
74+
}, callback);
75+
});
7476
},
7577

78+
/**
79+
* @api private
80+
*/
81+
loadCredentialsCallbacks: [],
82+
7683
/**
7784
* Loads a set of credentials stored in the instance metadata service
7885
*
@@ -86,18 +93,28 @@ AWS.MetadataService = inherit({
8693
loadCredentials: function loadCredentials(callback) {
8794
var self = this;
8895
var basePath = '/latest/meta-data/iam/security-credentials/';
96+
self.loadCredentialsCallbacks.push(callback);
97+
if (self.loadCredentialsCallbacks.length > 1) { return; }
98+
99+
function callbacks(err, creds) {
100+
var cb;
101+
while ((cb = self.loadCredentialsCallbacks.shift()) !== undefined) {
102+
cb(err, creds);
103+
}
104+
}
105+
89106
self.request(basePath, function (err, roleName) {
90-
if (err) callback(err);
107+
if (err) callbacks(err);
91108
else {
92109
roleName = roleName.split('\n')[0]; // grab first (and only) role
93110
self.request(basePath + roleName, function (credErr, credData) {
94-
if (credErr) callback(credErr);
111+
if (credErr) callbacks(credErr);
95112
else {
96113
try {
97114
var credentials = JSON.parse(credData);
98-
callback(null, credentials);
115+
callbacks(null, credentials);
99116
} catch (parseError) {
100-
callback(parseError);
117+
callbacks(parseError);
101118
}
102119
}
103120
});

test/metadata_service.spec.coffee

+15
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ if AWS.util.isNode()
3838
expect(data.Token).to.equal('TOKEN')
3939
done()
4040

41+
42+
it 'should load credentials from metadata service', (done) ->
43+
concurrency = countdown = 10
44+
for x in [1..concurrency]
45+
service.loadCredentials (err, data) ->
46+
expect(err).to.equal(null)
47+
expect(data.Code).to.equal('Success')
48+
expect(data.AccessKeyId).to.equal('KEY')
49+
expect(data.SecretAccessKey).to.equal('SECRET')
50+
expect(data.Token).to.equal('TOKEN')
51+
countdown--
52+
if countdown == 0
53+
done()
54+
55+
4156
it 'should fail if server is not up', (done) ->
4257
server.close(); server = null
4358
service = new AWS.MetadataService(host: '255.255.255.255')

0 commit comments

Comments
 (0)