diff --git a/lib/common/util.js b/lib/common/util.js index 2bb256a5fab..24c0781b749 100644 --- a/lib/common/util.js +++ b/lib/common/util.js @@ -344,6 +344,19 @@ function makeWritableStream(dup, options, onComplete) { module.exports.makeWritableStream = makeWritableStream; function makeAuthorizedRequest(config) { + var GAE_OR_GCE = !config || (!config.credentials && !config.keyFile); + + var missingCredentialsError = new Error(); + missingCredentialsError.message = [ + 'A connection to gcloud must be established via either a `keyFilename` ', + 'property or a `credentials` object.', + '\n\n', + 'See the "Getting Started with gcloud" section for more information:', + '\n\n', + '\thttps://googlecloudplatform.github.io/gcloud-node/#/docs/', + '\n' + ].join(''); + var authorize = gsa(config); function makeRequest(reqOpts, callback) { @@ -358,6 +371,12 @@ function makeAuthorizedRequest(config) { function onAuthorizedRequest(err, authorizedReqOpts) { if (err) { + if (GAE_OR_GCE && err.code === 'ENOTFOUND') { + // The metadata server wasn't found. The user must not actually be in + // a GAE or GCE environment. + throw missingCredentialsError; + } + if (err.code === 401 && ++tokenRefreshAttempts <= MAX_TOKEN_REFRESH_ATTEMPTS) { authorize(reqOpts, onAuthorizedRequest); diff --git a/test/common/util.js b/test/common/util.js index 3cb82b85758..44d4ab0fbac 100644 --- a/test/common/util.js +++ b/test/common/util.js @@ -14,7 +14,7 @@ * limitations under the License. */ -/*global describe, it */ +/*global describe, it, beforeEach */ 'use strict'; @@ -48,6 +48,10 @@ function fakeRequest() { } describe('common/util', function() { + beforeEach(function() { + gsa_Override = null; + }); + describe('arrayize', function() { it('should arrayize if the input is not an array', function(done) { var o = util.arrayize('text'); @@ -320,6 +324,22 @@ describe('common/util', function() { }); }); + it('should throw if not GCE/GAE & missing credentials', function() { + gsa_Override = function() { + return function authorize(reqOpts, callback) { + // Simulate the metadata server not existing. + callback({ code: 'ENOTFOUND' }); + }; + }; + + assert.throws(function() { + // Don't provide a keyFile or credentials object. + var connectionConfig = {}; + var makeRequest = util.makeAuthorizedRequest(connectionConfig); + makeRequest({}, util.noop); + }, /A connection to gcloud must be established/); + }); + it('should handle malformed key response', function(done) { var makeRequest = util.makeAuthorizedRequest({ credentials: {