Skip to content
This repository was archived by the owner on Nov 20, 2025. It is now read-only.

Commit a5b107d

Browse files
fix: retry checking isGCE (#193)
1 parent 38ac616 commit a5b107d

2 files changed

Lines changed: 74 additions & 4 deletions

File tree

src/auth/googleauth.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import {AxiosError} from 'axios';
1718
import {exec} from 'child_process';
1819
import * as fs from 'fs';
1920
import * as os from 'os';
@@ -22,6 +23,7 @@ import * as stream from 'stream';
2223
import * as util from 'util';
2324

2425
import {DefaultTransporter, Transporter} from '../transporters';
26+
2527
import {Compute} from './computeclient';
2628
import {JWTInput} from './credentials';
2729
import {IAMAuth} from './iam';
@@ -223,7 +225,7 @@ export class GoogleAuth {
223225
* @returns A promise that resolves with the boolean.
224226
* @api private
225227
*/
226-
async _checkIsGCE(): Promise<boolean> {
228+
async _checkIsGCE(isRetry = false): Promise<boolean> {
227229
if (this.checkIsGCE !== undefined) {
228230
return this.checkIsGCE;
229231
}
@@ -236,9 +238,17 @@ export class GoogleAuth {
236238
this.checkIsGCE =
237239
res && res.headers && res.headers['metadata-flavor'] === 'Google';
238240
} catch (e) {
239-
if ((e as NodeJS.ErrnoException).code !== 'ENOTFOUND') {
240-
// Unexpected error occurred. TODO(ofrobots): retry if this was a
241-
// transient error.
241+
const isDNSError = (e as NodeJS.ErrnoException).code === 'ENOTFOUND';
242+
const ae = e as AxiosError;
243+
const is5xx = ae.response &&
244+
(ae.response.status >= 500 && ae.response.status < 600);
245+
if (is5xx) {
246+
// Unexpected error occurred. Retry once.
247+
if (!isRetry) {
248+
return await this._checkIsGCE(true);
249+
}
250+
throw e;
251+
} else if (!isDNSError) {
242252
throw e;
243253
}
244254
this.checkIsGCE = false;

test/test.googleauth.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,66 @@ describe('._checkIsGCE', () => {
12431243
assert.equal(false, auth.isGCE);
12441244
});
12451245

1246+
it('should retry the check for isGCE if it fails the first time',
1247+
async () => {
1248+
const auth = new GoogleAuth();
1249+
assert.notEqual(true, auth.isGCE);
1250+
// the first request will fail
1251+
const scope1 =
1252+
nock('http://metadata.google.internal').get('/').reply(500);
1253+
// the second one will succeed
1254+
const scope2 =
1255+
nock('http://metadata.google.internal').get('/').reply(200, null, {
1256+
'metadata-flavor': 'Google'
1257+
});
1258+
const isGCE = await auth._checkIsGCE();
1259+
assert.equal(true, auth.isGCE);
1260+
assert(scope1.isDone());
1261+
assert(scope2.isDone());
1262+
});
1263+
1264+
it('should not retry the check for isGCE if it fails with a 404',
1265+
async () => {
1266+
const auth = new GoogleAuth();
1267+
assert.notEqual(true, auth.isGCE);
1268+
// the first request will fail
1269+
const scope1 =
1270+
nock('http://metadata.google.internal').get('/').reply(404);
1271+
// the second one should never happen
1272+
const scope2 =
1273+
nock('http://metadata.google.internal').get('/').reply(404);
1274+
try {
1275+
const isGCE = await auth._checkIsGCE();
1276+
assert.notEqual(true, auth.isGCE);
1277+
} catch (e) {
1278+
return;
1279+
}
1280+
assert(scope1.isDone());
1281+
assert(!scope2.isDone());
1282+
assert.fail('Expected to throw');
1283+
});
1284+
1285+
it('should not retry the check for isGCE if it fails with an ENOTFOUND',
1286+
async () => {
1287+
const auth = new GoogleAuth();
1288+
assert.notEqual(true, auth.isGCE);
1289+
// the first request will fail
1290+
const scope1 =
1291+
nock('http://metadata.google.internal').get('/').replyWithError({
1292+
code: 'ENOTFOUND'
1293+
});
1294+
// the second one should never happen
1295+
const scope2 =
1296+
nock('http://metadata.google.internal').get('/').replyWithError({
1297+
code: 'ENOTFOUND'
1298+
});
1299+
1300+
const isGCE = await auth._checkIsGCE();
1301+
assert.notEqual(true, auth.isGCE);
1302+
assert(scope1.isDone());
1303+
assert(!scope2.isDone());
1304+
});
1305+
12461306
it('Does not execute the second time when running on GCE', async () => {
12471307
const auth = new GoogleAuth();
12481308

0 commit comments

Comments
 (0)