Skip to content

Commit bf9e99f

Browse files
committed
Merge branch 'improvement/CLDSRV-717-unify-test-backbeat-route' into q/9.0
2 parents d61f966 + 4e4f7ff commit bf9e99f

File tree

5 files changed

+127
-73
lines changed

5 files changed

+127
-73
lines changed

lib/routes/routeBackbeat.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,9 @@ function routeBackbeat(clientIP, request, response, log) {
14631463
// Attach the apiMethod method to the request, so it can used by monitoring in the server
14641464
// eslint-disable-next-line no-param-reassign
14651465
request.apiMethod = 'routeBackbeat';
1466+
const contentLength = request.headers['x-amz-decoded-content-length'] || request.headers['content-length'];
1467+
// eslint-disable-next-line no-param-reassign
1468+
request.parsedContentLength = Number.parseInt(contentLength?.toString() ?? '', 10);
14661469
log.addDefaultFields({
14671470
clientIP,
14681471
url: request.url,

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
"ft_backbeat": "cd tests/functional/backbeat && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 40000 *.js --exit",
9494
"ft_node": "cd tests/functional/raw-node && yarn test",
9595
"ft_node_routes": "cd tests/functional/raw-node && yarn run test-routes",
96-
"ft_node_route_backbeat": "cd tests/functional/raw-node && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 40000 test/routes/routeBackbeat.js --exit",
96+
"ft_route_backbeat": "cd tests/multipleBackend/routes && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 40000 routeBackbeat.js routeBackbeatForReplication.js --exit",
9797
"ft_gcp": "cd tests/functional/raw-node && yarn run test-gcp",
9898
"ft_healthchecks": "cd tests/functional/healthchecks && yarn test",
9999
"ft_s3cmd": "cd tests/functional/s3cmd && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 40000 *.js --exit",
@@ -107,7 +107,6 @@
107107
"ft_sse_before_migration": "cd tests/functional/sse-kms-migration && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 10000 cleanup.js beforeMigration.js --exit",
108108
"ft_sse_migration": "cd tests/functional/sse-kms-migration && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 10000 migration.js --exit",
109109
"ft_sse_arn": "cd tests/functional/sse-kms-migration && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json -t 10000 cleanup.js arnPrefix.js --exit",
110-
"install_ft_deps": "yarn install aws-sdk@2.28.0 bluebird@3.3.1 mocha@2.3.4 mocha-junit-reporter@1.23.1 tv4@1.2.7",
111110
"lint": "eslint $(git ls-files '*.js')",
112111
"lint_md": "mdlint $(git ls-files '*.md')",
113112
"mem_backend": "S3BACKEND=mem node index.js",

tests/functional/aws-node-sdk/lib/utility/test-utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ if (config.backends.data === 'multiple') {
1111
describeSkipIfNotMultipleOrCeph = isCEPH ? describe.skip : describe.skip; // always skip
1212
}
1313

14+
function hasLocation(lc) {
15+
return config.locationConstraints[lc] !== undefined;
16+
}
17+
1418
module.exports = {
1519
isCEPH,
1620
itSkipCeph,
1721
describeSkipIfCeph,
1822
describeSkipIfNotMultiple,
1923
describeSkipIfNotMultipleOrCeph,
24+
hasLocation,
2025
};

tests/functional/aws-node-sdk/test/multipleBackend/utils.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,25 @@ let gcpBucket;
4747
let gcpBucketMPU;
4848

4949
if (config.backends.data === 'multiple') {
50-
const awsConfig = getRealAwsConfig(awsLocation);
51-
awsS3 = new AWS.S3(awsConfig);
52-
awsBucket = config.locationConstraints[awsLocation].details.bucketName;
53-
54-
const gcpConfig = getRealAwsConfig(gcpLocation);
55-
gcpClient = new GCP(gcpConfig);
56-
gcpBucket = config.locationConstraints[gcpLocation].details.bucketName;
57-
gcpBucketMPU =
58-
config.locationConstraints[gcpLocation].details.mpuBucketName;
50+
if (config.locationConstraints[awsLocation]) {
51+
const awsConfig = getRealAwsConfig(awsLocation);
52+
awsS3 = new AWS.S3(awsConfig);
53+
awsBucket = config.locationConstraints[awsLocation].details.bucketName;
54+
} else {
55+
process.stdout.write(`LocationConstraint for aws '${awsLocation}' not found in ${
56+
Object.keys(config.locationConstraints)}\n`);
57+
}
58+
59+
if (config.locationConstraints[gcpLocation]) {
60+
const gcpConfig = getRealAwsConfig(gcpLocation);
61+
gcpClient = new GCP(gcpConfig);
62+
gcpBucket = config.locationConstraints[gcpLocation].details.bucketName;
63+
gcpBucketMPU =
64+
config.locationConstraints[gcpLocation].details.mpuBucketName;
65+
} else {
66+
process.stdout.write(`LocationConstraint for gcp '${gcpLocation}' not found in ${
67+
Object.keys(config.locationConstraints)}\n`);
68+
}
5969
}
6070

6171

tests/multipleBackend/routes/routeBackbeat.js

Lines changed: 99 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const assert = require('assert');
2-
const AWS = require('aws-sdk');
32
const async = require('async');
43
const crypto = require('crypto');
54
const { v4: uuidv4 } = require('uuid');
@@ -8,23 +7,23 @@ const versionIdUtils = versioning.VersionID;
87

98
const { makeid } = require('../../unit/helpers');
109
const { makeRequest, makeBackbeatRequest } = require('../../functional/raw-node/utils/makeRequest');
11-
const BucketUtility =
12-
require('../../functional/aws-node-sdk/lib/utility/bucket-util');
13-
const { describeSkipIfNotMultipleOrCeph, itSkipCeph } = require('../../functional/aws-node-sdk/lib/utility/test-utils');
10+
const BucketUtility = require('../../functional/aws-node-sdk/lib/utility/bucket-util');
11+
const {
12+
describeSkipIfNotMultipleOrCeph,
13+
itSkipCeph,
14+
hasLocation
15+
} = require('../../functional/aws-node-sdk/lib/utility/test-utils');
1416
const {
1517
awsLocation,
18+
awsS3: awsClient,
19+
awsBucket,
1620
azureLocation,
1721
getAzureContainerName,
1822
getAzureClient,
1923
} = require('../../functional/aws-node-sdk/test/multipleBackend/utils');
20-
const { getRealAwsConfig } =
21-
require('../../functional/aws-node-sdk/test/support/awsConfig');
2224
const { getCredentials } = require('../../functional/aws-node-sdk/test/support/credentials');
2325
const { config } = require('../../../lib/Config');
2426

25-
const awsConfig = getRealAwsConfig(awsLocation);
26-
const awsClient = new AWS.S3(awsConfig);
27-
const awsBucket = config.locationConstraints[awsLocation].details.bucketName;
2827
const azureClient = getAzureClient();
2928
const containerName = getAzureContainerName(azureLocation);
3029

@@ -85,6 +84,11 @@ const testMd = {
8584
},
8685
};
8786

87+
// S3_TESTVAL_OWNERCANONICALID variable is used by Integration that runs E2E tests with real Vault account.
88+
if (process.env.S3_TESTVAL_OWNERCANONICALID) {
89+
testMd['owner-id'] = process.env.S3_TESTVAL_OWNERCANONICALID;
90+
}
91+
8892
const nonVersionedTestMd = {
8993
'owner-display-name': 'Bart',
9094
'owner-id': ('79a59df900b949e55d96a1e698fbaced' +
@@ -165,6 +169,11 @@ function updateStorageClass(data, storageClass) {
165169
function generateUniqueBucketName(prefix, suffix = uuidv4()) {
166170
return `${prefix}-${suffix.substring(0, 8)}`.substring(0, 63);
167171
}
172+
const describeIfLocationAws = hasLocation(awsLocation) ? describe : describe.skip;
173+
const itIfLocationAwsSkipCeph = hasLocation(awsLocation) ? itSkipCeph : it.skip;
174+
const itIfLocationAws = hasLocation(awsLocation) ? it : it.skip;
175+
const itIfLocationAzure = hasLocation(azureLocation) ? it : it.skip;
176+
const itSkipS3C = process.env.S3_END_TO_END ? it.skip : it;
168177

169178
// FIXME: does not pass for Ceph, see CLDSRV-443
170179
describeSkipIfNotMultipleOrCeph('backbeat DELETE routes', () => {
@@ -280,7 +289,7 @@ describe('backbeat routes', () => {
280289
.then(() => done())
281290
.catch(err => {
282291
process.stdout.write(`Error creating bucket: ${err}\n`);
283-
throw err;
292+
done(err);
284293
});
285294
});
286295

@@ -766,7 +775,8 @@ describe('backbeat routes', () => {
766775
});
767776
});
768777

769-
it('should create a new null version if versioning suspended and delete marker null version', done => {
778+
// TODO fix broken on S3C with metadata backend,create 2 null Versions
779+
itSkipS3C('should create a new null version if versioning suspended and delete marker null version', done => {
770780
let objMD;
771781
return async.series([
772782
next => s3.putBucketVersioning({ Bucket: bucket, VersioningConfiguration: { Status: 'Suspended' } },
@@ -1657,7 +1667,7 @@ describe('backbeat routes', () => {
16571667
});
16581668
});
16591669

1660-
itSkipCeph('should PUT tags for a non-versioned bucket', function test(done) {
1670+
itIfLocationAwsSkipCeph('should PUT tags for a non-versioned bucket (awslocation)', function test(done) {
16611671
this.timeout(10000);
16621672
const bucket = NONVERSIONED_BUCKET;
16631673
const awsKey = uuidv4();
@@ -2165,6 +2175,8 @@ describe('backbeat routes', () => {
21652175
});
21662176
});
21672177
describe('backbeat authorization checks', () => {
2178+
const { accessKeyId: accessKeyLisa, secretAccessKey: secretAccessKeyLisa } = getCredentials('lisa');
2179+
21682180
[{ method: 'PUT', resourceType: 'metadata' },
21692181
{ method: 'PUT', resourceType: 'data' }].forEach(test => {
21702182
const queryObj = test.resourceType === 'data' ? { v2: '' } : {};
@@ -2211,8 +2223,8 @@ describe('backbeat routes', () => {
22112223
objectKey: TEST_KEY, resourceType: test.resourceType,
22122224
queryObj,
22132225
authCredentials: {
2214-
accessKey: 'accessKey2',
2215-
secretKey: 'verySecretKey2',
2226+
accessKey: accessKeyLisa,
2227+
secretKey: secretAccessKeyLisa,
22162228
},
22172229
},
22182230
err => {
@@ -2242,44 +2254,59 @@ describe('backbeat routes', () => {
22422254
});
22432255
});
22442256
});
2245-
it('GET /_/backbeat/api/... should respond with ' +
2246-
'503 on authenticated requests (API server down)',
2247-
done => {
2248-
const options = {
2249-
authCredentials: {
2250-
accessKey: 'accessKey2',
2251-
secretKey: 'verySecretKey2',
2252-
},
2253-
hostname: ipAddress,
2254-
port: 8000,
2255-
method: 'GET',
2256-
path: '/_/backbeat/api/crr/failed',
2257-
jsonResponse: true,
2258-
};
2259-
makeRequest(options, err => {
2260-
assert(err);
2261-
assert.strictEqual(err.statusCode, 503);
2262-
assert.strictEqual(err.code, 'ServiceUnavailable');
2263-
done();
2264-
});
2265-
});
2266-
it('GET /_/backbeat/api/... should respond with ' +
2267-
'403 Forbidden if the request is unauthenticated',
2268-
done => {
2269-
const options = {
2270-
hostname: ipAddress,
2271-
port: 8000,
2272-
method: 'GET',
2273-
path: '/_/backbeat/api/crr/failed',
2274-
jsonResponse: true,
2275-
};
2276-
makeRequest(options, err => {
2277-
assert(err);
2278-
assert.strictEqual(err.statusCode, 403);
2279-
assert.strictEqual(err.code, 'AccessDenied');
2280-
done();
2281-
});
2282-
});
2257+
2258+
const apiProxy = !!config.backbeat;
2259+
describe(`when api proxy is ${apiProxy ? '' : 'NOT '}configured`, () => {
2260+
const errors = {
2261+
403: 'AccessDenied',
2262+
405: 'MethodNotAllowed',
2263+
503: 'ServiceUnavailable',
2264+
};
2265+
2266+
it(`GET /_/backbeat/api/... should respond with ${
2267+
apiProxy ? 503 : 405
2268+
} on authenticated requests (API server down)`,
2269+
done => {
2270+
const options = {
2271+
authCredentials: {
2272+
accessKey: accessKeyLisa,
2273+
secretKey: secretAccessKeyLisa,
2274+
},
2275+
hostname: ipAddress,
2276+
port: 8000,
2277+
method: 'GET',
2278+
path: '/_/backbeat/api/crr/failed',
2279+
jsonResponse: true,
2280+
};
2281+
makeRequest(options, err => {
2282+
assert(err);
2283+
const expected = apiProxy ? 503 : 405;
2284+
assert.strictEqual(err.statusCode, expected);
2285+
assert.strictEqual(err.code, errors[expected]);
2286+
done();
2287+
});
2288+
});
2289+
2290+
it(`GET /_/backbeat/api/... should respond with ${
2291+
apiProxy ? 403 : 405
2292+
} if the request is unauthenticated`,
2293+
done => {
2294+
const options = {
2295+
hostname: ipAddress,
2296+
port: 8000,
2297+
method: 'GET',
2298+
path: '/_/backbeat/api/crr/failed',
2299+
jsonResponse: true,
2300+
};
2301+
makeRequest(options, err => {
2302+
assert(err);
2303+
const expected = apiProxy ? 403 : 405;
2304+
assert.strictEqual(err.statusCode, expected);
2305+
assert.strictEqual(err.code, errors[expected]);
2306+
done();
2307+
});
2308+
});
2309+
});
22832310
});
22842311

22852312
describe('GET Metadata route', () => {
@@ -2303,6 +2330,7 @@ describe('backbeat routes', () => {
23032330
versionId: versionIdUtils.encode(testMd.versionId),
23042331
},
23052332
}, (err, data) => {
2333+
assert.ifError(err);
23062334
const parsedBody = JSON.parse(JSON.parse(data.body).Body);
23072335
assert.strictEqual(data.statusCode, 200);
23082336
assert.deepStrictEqual(parsedBody, testMd);
@@ -2320,7 +2348,10 @@ describe('backbeat routes', () => {
23202348
},
23212349
}, (err, data) => {
23222350
assert.strictEqual(data.statusCode, 404);
2323-
assert.strictEqual(JSON.parse(data.body).code, 'NoSuchBucket');
2351+
const body = JSON.parse(data.body);
2352+
assert.strictEqual(body.code, 'NoSuchBucket');
2353+
// err is parsed data.body + statusCode
2354+
assert.deepStrictEqual(err, { ...body, statusCode: data.statusCode });
23242355
done();
23252356
});
23262357
});
@@ -2335,12 +2366,16 @@ describe('backbeat routes', () => {
23352366
},
23362367
}, (err, data) => {
23372368
assert.strictEqual(data.statusCode, 404);
2338-
assert.strictEqual(JSON.parse(data.body).code, 'ObjNotFound');
2369+
const body = JSON.parse(data.body);
2370+
assert.strictEqual(body.code, 'ObjNotFound');
2371+
// err is parsed data.body + statusCode
2372+
assert.deepStrictEqual(err, { ...body, statusCode: data.statusCode });
23392373
done();
23402374
});
23412375
});
23422376
});
2343-
describe('backbeat multipart upload operations', function test() {
2377+
2378+
describeIfLocationAws('backbeat multipart upload operations (external location)', function test() {
23442379
this.timeout(10000);
23452380

23462381
// The ceph image does not support putting tags during initiate MPU.
@@ -2551,12 +2586,13 @@ describe('backbeat routes', () => {
25512586
}, err => {
25522587
// should error out as location shall no longer exist
25532588
assert(err);
2589+
assert.strictEqual(err.statusCode, 503);
25542590
done();
25552591
}),
25562592
], done);
25572593
});
25582594

2559-
itSkipCeph('should batch delete a versioned AWS location', done => {
2595+
itIfLocationAwsSkipCeph('should batch delete a versioned AWS location', done => {
25602596
let versionId;
25612597
const awsKey = `${TEST_BUCKET}/batch-delete-test-key-${makeid(8)}`;
25622598

@@ -2618,7 +2654,8 @@ describe('backbeat routes', () => {
26182654
done();
26192655
});
26202656
});
2621-
it('should skip batch delete of a non-existent location', done => {
2657+
// TODO: unskip test when S3C-9123 is fixed
2658+
itSkipS3C('should skip batch delete of a non-existent location', done => {
26222659
async.series([
26232660
done => {
26242661
const options = {
@@ -2653,7 +2690,7 @@ describe('backbeat routes', () => {
26532690
], done);
26542691
});
26552692

2656-
it('should not put delete tags if the source is not Azure and ' +
2693+
itIfLocationAws('should not put delete tags if the source is not Azure and ' +
26572694
'if-unmodified-since header is not provided', done => {
26582695
const awsKey = uuidv4();
26592696
async.series([
@@ -2696,7 +2733,7 @@ describe('backbeat routes', () => {
26962733
], done);
26972734
});
26982735

2699-
itSkipCeph('should not put tags if the source is not Azure and ' +
2736+
itIfLocationAwsSkipCeph('should not put tags if the source is not Azure and ' +
27002737
'if-unmodified-since condition is not met', done => {
27012738
const awsKey = uuidv4();
27022739
async.series([
@@ -2741,7 +2778,7 @@ describe('backbeat routes', () => {
27412778
], done);
27422779
});
27432780

2744-
itSkipCeph('should put tags if the source is not Azure and ' +
2781+
itIfLocationAwsSkipCeph('should put tags if the source is not Azure and ' +
27452782
'if-unmodified-since condition is met', done => {
27462783
const awsKey = uuidv4();
27472784
let lastModified;
@@ -2811,7 +2848,7 @@ describe('backbeat routes', () => {
28112848
], done);
28122849
});
28132850

2814-
it('should not delete the object if the source is Azure and ' +
2851+
itIfLocationAzure('should not delete the object if the source is Azure and ' +
28152852
'if-unmodified-since condition is not met', done => {
28162853
const blob = uuidv4();
28172854
async.series([
@@ -2857,7 +2894,7 @@ describe('backbeat routes', () => {
28572894
], done);
28582895
});
28592896

2860-
it('should delete the object if the source is Azure and ' +
2897+
itIfLocationAzure('should delete the object if the source is Azure and ' +
28612898
'if-unmodified-since condition is met', done => {
28622899
const blob = uuidv4();
28632900
let lastModified;

0 commit comments

Comments
 (0)