Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: re-throw original exception and preserve message in compute client #668

Merged
merged 2 commits into from
Apr 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 18 additions & 30 deletions src/auth/computeclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class Compute extends OAuth2Client {
data = await gcpMetadata.instance(tokenPath);
} catch (e) {
e.message = `Could not refresh access token: ${e.message}`;
this.wrapError(e);
throw e;
}
const tokens = data as Credentials;
Expand All @@ -82,36 +83,23 @@ export class Compute extends OAuth2Client {
return {tokens, res: null};
}

protected requestAsync<T>(opts: GaxiosOptions, retry = false):
GaxiosPromise<T> {
return super.requestAsync<T>(opts, retry).catch(e => {
const res = (e as GaxiosError).response;
if (res && res.status) {
let helpfulMessage = null;
if (res.status === 403) {
helpfulMessage =
'A Forbidden error was returned while attempting to retrieve an access ' +
'token for the Compute Engine built-in service account. This may be because the Compute ' +
'Engine instance does not have the correct permission scopes specified.';
} else if (res.status === 404) {
helpfulMessage =
'A Not Found error was returned while attempting to retrieve an access' +
'token for the Compute Engine built-in service account. This may be because the Compute ' +
'Engine instance does not have any permission scopes specified.';
}
if (helpfulMessage) {
if (e && e.message && !retry) {
helpfulMessage += ' ' + e.message;
}
if (e) {
e.message = helpfulMessage;
} else {
e = new Error(helpfulMessage);
(e as NodeJS.ErrnoException).code = res.status.toString();
}
}
protected wrapError(e: GaxiosError) {
const res = e.response;
if (res && res.status) {
e.code = res.status.toString();
if (res.status === 403) {
e.message =
'A Forbidden error was returned while attempting to retrieve an access ' +
'token for the Compute Engine built-in service account. This may be because the Compute ' +
'Engine instance does not have the correct permission scopes specified: ' +
e.message;
} else if (res.status === 404) {
e.message =
'A Not Found error was returned while attempting to retrieve an access' +
'token for the Compute Engine built-in service account. This may be because the Compute ' +
'Engine instance does not have any permission scopes specified: ' +
e.message;
}
throw e;
});
}
}
}
24 changes: 4 additions & 20 deletions test/test.compute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ function mockExample() {
}

// set up compute client.
let sandbox: sinon.SinonSandbox;
const sandbox = sinon.createSandbox();
let compute: Compute;
beforeEach(() => {
compute = new Compute();
sandbox = sinon.createSandbox();
});

afterEach(() => {
Expand Down Expand Up @@ -129,37 +128,22 @@ it('should return false for createScopedRequired', () => {
});

it('should return a helpful message on request response.statusCode 403', async () => {
// Mock the credentials object. Make sure there's no expiry_date set.
compute.credentials = {refresh_token: 'hello', access_token: 'goodbye'};

const scopes = [
nock(url).get('/').reply(403), nock(HOST_ADDRESS).get(tokenPath).reply(403)
];

const scope = mockToken(403);
const expected = new RegExp(
'A Forbidden error was returned while attempting to retrieve an access ' +
'token for the Compute Engine built-in service account. This may be because the ' +
'Compute Engine instance does not have the correct permission scopes specified. ' +
'Could not refresh access token.');

await assertRejects(compute.request({url}), expected);
scopes.forEach(s => s.done());
scope.done();
});

it('should return a helpful message on request response.statusCode 404', async () => {
// Mock the credentials object.
compute.credentials = {
refresh_token: 'hello',
access_token: 'goodbye',
expiry_date: (new Date(9999, 1, 1)).getTime()
};
// Mock the request method to return a 404.
const scope = nock(url).get('/').reply(404);
const scope = mockToken(404);
const expected = new RegExp(
'A Not Found error was returned while attempting to retrieve an access' +
'token for the Compute Engine built-in service account. This may be because the ' +
'Compute Engine instance does not have any permission scopes specified.');

await assertRejects(compute.request({url}), expected);
scope.done();
});
Expand Down