Skip to content

Commit

Permalink
CLDSRV-497 Fix BackbeatClient.putMetadata with versionID
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas2bert committed Jan 24, 2024
1 parent 5dbf5d9 commit b32be1d
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 34 deletions.
35 changes: 1 addition & 34 deletions tests/functional/raw-node/test/routes/routeBackbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { models, versioning } = require('arsenal');
const versionIdUtils = versioning.VersionID;
const { ObjectMD } = models;

const { makeRequest } = require('../../utils/makeRequest');
const { makeRequest, makeBackbeatRequest } = require('../../utils/makeRequest');
const BucketUtility = require('../../../aws-node-sdk/lib/utility/bucket-util');

const ipAddress = process.env.IP ? process.env.IP : '127.0.0.1';
Expand Down Expand Up @@ -86,39 +86,6 @@ function checkVersionData(s3, bucket, objectKey, versionId, dataValue, done) {
});
}

/** makeBackbeatRequest - utility function to generate a request going
* through backbeat route
* @param {object} params - params for making request
* @param {string} params.method - request method
* @param {string} params.bucket - bucket name
* @param {string} params.objectKey - object key
* @param {string} params.subCommand - subcommand to backbeat
* @param {object} [params.headers] - headers and their string values
* @param {object} [params.authCredentials] - authentication credentials
* @param {object} params.authCredentials.accessKey - access key
* @param {object} params.authCredentials.secretKey - secret key
* @param {string} [params.requestBody] - request body contents
* @param {object} [params.queryObj] - query params
* @param {function} callback - with error and response parameters
* @return {undefined} - and call callback
*/
function makeBackbeatRequest(params, callback) {
const { method, headers, bucket, objectKey, resourceType,
authCredentials, requestBody, queryObj } = params;
const options = {
authCredentials,
hostname: ipAddress,
port: 8000,
method,
headers,
path: `/_/backbeat/${resourceType}/${bucket}/${objectKey}`,
requestBody,
jsonResponse: true,
queryObj,
};
makeRequest(options, callback);
}

function updateStorageClass(data, storageClass) {
let parsedBody;
try {
Expand Down
175 changes: 175 additions & 0 deletions tests/functional/raw-node/test/routes/routeBackbeatForReplication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
const assert = require('assert');
const async = require('async');
const { models } = require('arsenal');
const { ObjectMD } = models;

const { makeBackbeatRequest } = require('../../utils/makeRequest');
const BucketUtility = require('../../../aws-node-sdk/lib/utility/bucket-util');

const describeSkipIfAWS = process.env.AWS_ON_AIR ? describe.skip : describe;

const backbeatAuthCredentials = {
accessKey: 'accessKey1',
secretKey: 'verySecretKey1',
};

const testData = 'testkey data';

describeSkipIfAWS('backbeat routes for replication', () => {
const bucketUtil = new BucketUtility(
'default', { signatureVersion: 'v4' });
const s3 = bucketUtil.s3;

const bucketSource = 'backbeatbucket-replication-source';
const bucketDestination = 'backbeatbucket-replication-destination';
const keyName = 'key0';
const storageClass = 'foo';

beforeEach(done =>
bucketUtil.emptyIfExists(bucketSource)
.then(() => s3.createBucket({ Bucket: bucketSource }).promise())
.then(() => bucketUtil.emptyIfExists(bucketDestination))
.then(() => s3.createBucket({ Bucket: bucketDestination }).promise())
.then(() => done(), err => done(err))
);

afterEach(done =>
bucketUtil.empty(bucketSource)
.then(() => s3.deleteBucket({ Bucket: bucketSource }).promise())
.then(() => bucketUtil.empty(bucketDestination))
.then(() => s3.deleteBucket({ Bucket: bucketDestination }).promise())
.then(() => done(), err => done(err))
);

it('should successfully replicate a null version', done => {
let objMD;
return async.series([
next => s3.putObject({ Bucket: bucketSource, Key: keyName, Body: new Buffer(testData) }, next),
next => s3.putBucketVersioning({ Bucket: bucketSource, VersioningConfiguration: { Status: 'Enabled' } },
next),
next => s3.putBucketVersioning({ Bucket: bucketDestination, VersioningConfiguration:
{ Status: 'Enabled' } }, next),
next => makeBackbeatRequest({
method: 'GET',
resourceType: 'metadata',
bucket: bucketSource,
objectKey: keyName,
queryObj: {
versionId: 'null',
},
authCredentials: backbeatAuthCredentials,
}, (err, data) => {
if (err) {
return next(err);
}
objMD = JSON.parse(data.body).Body;
return next();
}),
next => makeBackbeatRequest({
method: 'PUT',
resourceType: 'metadata',
bucket: bucketDestination,
objectKey: keyName,
queryObj: {
versionId: 'null',
},
authCredentials: backbeatAuthCredentials,
requestBody: objMD,
}, next),
next => s3.headObject({ Bucket: bucketDestination, Key: keyName, VersionId: 'null' }, next),
next => s3.listObjectVersions({ Bucket: bucketDestination }, next),
], (err, data) => {
if (err) {
return done(err);
}
const headObjectRes = data[5];
assert.strictEqual(headObjectRes.VersionId, 'null');

const listObjectVersionsRes = data[6];
const { Versions } = listObjectVersionsRes;

assert.strictEqual(Versions.length, 1);

const [currentVersion] = Versions;
assert.strictEqual(currentVersion.IsLatest, true);
assert.strictEqual(currentVersion.VersionId, 'null');
return done();
});
});

it('should successfully replicate a null version and update it', done => {
let objMD;
return async.series([
next => s3.putObject({ Bucket: bucketSource, Key: keyName, Body: new Buffer(testData) }, next),
next => s3.putBucketVersioning({ Bucket: bucketSource, VersioningConfiguration: { Status: 'Enabled' } },
next),
next => s3.putBucketVersioning({ Bucket: bucketDestination, VersioningConfiguration:
{ Status: 'Enabled' } }, next),
next => makeBackbeatRequest({
method: 'GET',
resourceType: 'metadata',
bucket: bucketSource,
objectKey: keyName,
queryObj: {
versionId: 'null',
},
authCredentials: backbeatAuthCredentials,
}, (err, data) => {
if (err) {
return next(err);
}
objMD = JSON.parse(data.body).Body;
return next();
}),
next => makeBackbeatRequest({
method: 'PUT',
resourceType: 'metadata',
bucket: bucketDestination,
objectKey: keyName,
queryObj: {
versionId: 'null',
},
authCredentials: backbeatAuthCredentials,
requestBody: objMD,
}, next),
next => {
const { result, error } = ObjectMD.createFromBlob(objMD);
if (error) {
return next(error);
}
result.setAmzStorageClass(storageClass);
return makeBackbeatRequest({
method: 'PUT',
resourceType: 'metadata',
bucket: bucketDestination,
objectKey: keyName,
queryObj: {
versionId: 'null',
},
authCredentials: backbeatAuthCredentials,
requestBody: result.getSerialized(),
}, next);
},
next => s3.headObject({ Bucket: bucketDestination, Key: keyName, VersionId: 'null' }, next),
next => s3.listObjectVersions({ Bucket: bucketDestination }, next),
], (err, data) => {
if (err) {
return done(err);
}
const headObjectRes = data[6];
assert.strictEqual(headObjectRes.VersionId, 'null');
assert.strictEqual(headObjectRes.StorageClass, storageClass);

const listObjectVersionsRes = data[7];
const { Versions } = listObjectVersionsRes;

assert.strictEqual(Versions.length, 1);

const [currentVersion] = Versions;
assert.strictEqual(currentVersion.IsLatest, true);
assert.strictEqual(currentVersion.VersionId, 'null');
assert.strictEqual(currentVersion.StorageClass, storageClass);
return done();
});
});
});
34 changes: 34 additions & 0 deletions tests/functional/raw-node/utils/makeRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,42 @@ function makeGcpRequest(params, callback) {
makeRequest(options, callback);
}

/** makeBackbeatRequest - utility function to generate a request going
* through backbeat route
* @param {object} params - params for making request
* @param {string} params.method - request method
* @param {string} params.bucket - bucket name
* @param {string} params.objectKey - object key
* @param {string} params.subCommand - subcommand to backbeat
* @param {object} [params.headers] - headers and their string values
* @param {object} [params.authCredentials] - authentication credentials
* @param {object} params.authCredentials.accessKey - access key
* @param {object} params.authCredentials.secretKey - secret key
* @param {string} [params.requestBody] - request body contents
* @param {object} [params.queryObj] - query params
* @param {function} callback - with error and response parameters
* @return {undefined} - and call callback
*/
function makeBackbeatRequest(params, callback) {
const { method, headers, bucket, objectKey, resourceType,
authCredentials, requestBody, queryObj } = params;
const options = {
authCredentials,
hostname: ipAddress,
port: 8000,
method,
headers,
path: `/_/backbeat/${resourceType}/${bucket}/${objectKey}`,
requestBody,
jsonResponse: true,
queryObj,
};
makeRequest(options, callback);
}

module.exports = {
makeRequest,
makeS3Request,
makeGcpRequest,
makeBackbeatRequest,
};

0 comments on commit b32be1d

Please sign in to comment.