DC-130 rev3: log.error on unexpected bridge status in /status + test asserting the log call (13 tests green)
This commit is contained in:
@@ -19,6 +19,10 @@ const FIXTURE_ROWS = {
|
||||
};
|
||||
|
||||
function buildApp(fetchT, env = {}) {
|
||||
return buildAppWithLogCapture(fetchT, env, { info: jest.fn(), warn: jest.fn(), error: jest.fn() });
|
||||
}
|
||||
|
||||
function buildAppWithLogCapture(fetchT, env = {}, log) {
|
||||
process.env.SHIPDECK_BRIDGE_URL = env.url !== undefined ? env.url : 'http://172.17.0.1:8977';
|
||||
process.env.SHIPDECK_BRIDGE_TOKEN_FILE = env.tokenFile !== undefined ? env.tokenFile : '';
|
||||
jest.resetModules();
|
||||
@@ -27,7 +31,7 @@ function buildApp(fetchT, env = {}) {
|
||||
asyncHandler: (fn) => async (req, res, next) => {
|
||||
try { await fn(req, res, next); } catch (e) { next(e); }
|
||||
},
|
||||
log: { info: jest.fn(), warn: jest.fn(), error: jest.fn() },
|
||||
log,
|
||||
auditLogger: { log: jest.fn(async () => {}) },
|
||||
fetchT,
|
||||
});
|
||||
@@ -41,11 +45,20 @@ function buildApp(fetchT, env = {}) {
|
||||
return app;
|
||||
}
|
||||
|
||||
// expose log on the fetcher wrapper for log-capture assertions
|
||||
function jsonFetcherWithLog(responses) {
|
||||
const calls = [];
|
||||
const log = { info: jest.fn(), warn: jest.fn(), error: jest.fn() };
|
||||
return { calls, log, fetchT: null };
|
||||
}
|
||||
|
||||
function jsonFetcher(responses) {
|
||||
// responses: map of "METHOD path" -> {status, body}
|
||||
const calls = [];
|
||||
return {
|
||||
const log = { info: jest.fn(), warn: jest.fn(), error: jest.fn() };
|
||||
const wrapper = {
|
||||
calls,
|
||||
log,
|
||||
fetchT: jest.fn(async (url, opts) => {
|
||||
const key = `${(opts && opts.method) || 'GET'} ${url.replace(/^https?:\/\/[^/]+/, '')}`;
|
||||
calls.push({ key, opts });
|
||||
@@ -56,6 +69,7 @@ function jsonFetcher(responses) {
|
||||
};
|
||||
}),
|
||||
};
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
describe('routes/deploys — feature gate', () => {
|
||||
@@ -155,16 +169,21 @@ describe('routes/deploys — proxied endpoints', () => {
|
||||
expect(body.error).toMatch(/bridge/i);
|
||||
});
|
||||
|
||||
test('GET /status maps unexpected bridge statuses to 502', async () => {
|
||||
test('GET /status maps unexpected bridge statuses to 502 with error logging', async () => {
|
||||
const f = jsonFetcher({
|
||||
'GET /api/status?service=helloworld': { status: 404, body: { ok: false, error: 'not found' } },
|
||||
});
|
||||
const app = buildApp(f.fetchT);
|
||||
const app = buildAppWithLogCapture(f.fetchT, {}, f.log);
|
||||
const server = app.listen(0);
|
||||
const port = server.address().port;
|
||||
const r = await fetch(`http://127.0.0.1:${port}/api/v1/deploys/status?service=helloworld`);
|
||||
server.close();
|
||||
expect(r.status).toBe(502);
|
||||
expect(f.log.error).toHaveBeenCalledWith(
|
||||
'deploys',
|
||||
'status probe: unexpected bridge response',
|
||||
expect.objectContaining({ service: 'helloworld', status: 404 }),
|
||||
);
|
||||
});
|
||||
|
||||
test('GET /status maps bridge connection failure to 502', async () => {
|
||||
|
||||
@@ -136,7 +136,12 @@ module.exports = function ({ asyncHandler, log, auditLogger, fetchT }) {
|
||||
}
|
||||
if (status !== 200) {
|
||||
// malformed upstream route or other unexpected bridge failure
|
||||
return errorResponse(res, 502, body && body.error ? body.error : 'unexpected bridge response');
|
||||
log.error('deploys', 'status probe: unexpected bridge response', {
|
||||
service,
|
||||
status,
|
||||
bridgeError: body && body.error ? String(body.error).slice(0, 200) : 'none',
|
||||
});
|
||||
return errorResponse(res, 502, 'shipdeck bridge protocol error (unexpected response, status ' + status + ')');
|
||||
}
|
||||
return ok(res, { ok: body.ok === true, output: body.output || '' });
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user