Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/routes/routeBackbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -472,12 +472,13 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) {
omVal[headerName] = objMd[headerName];
});
}
const versionId = decodeVersionId(request.query);
// specify both 'versioning' and 'versionId' to create a "new"
// version (updating master as well) but with specified
// versionId
const options = {
versioning: bucketInfo.isVersioningEnabled(),
versionId: omVal.versionId,
versionId,
};
// If the object is from a source bucket without versioning (i.e. NFS),
// then we want to create a version for the replica object even though
Expand All @@ -501,6 +502,7 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) {
pushReplicationMetric(objMd, omVal, bucketName, objectKey, log);
if (objMd &&
headers['x-scal-replication-content'] !== 'METADATA' &&
versionId &&
locationKeysHaveChanged(objMd.location, omVal.location)) {
log.info('removing old data locations', {
method: 'putMetadata',
Expand Down
109 changes: 106 additions & 3 deletions tests/functional/raw-node/test/routes/routeBackbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const testMd = {
},
'nullVersionId': '99999999999999999999RG001 ',
'isDeleteMarker': false,
'versionId': '98505119639965999999RG001 9',
'versionId': '98505119639965999999RG001 ',
'replicationInfo': {
status: 'COMPLETED',
backends: [{ site: 'zenko', status: 'PENDING' }],
Expand Down Expand Up @@ -416,8 +416,7 @@ describeSkipIfAWS('backbeat routes', () => {
});
});

it('should remove old object data locations if version is overwritten',
done => {
it('should remove old object data locations if version is overwritten', done => {
let oldLocation;
const testKeyOldData = `${testKey}-old-data`;
async.waterfall([next => {
Expand All @@ -443,6 +442,9 @@ describeSkipIfAWS('backbeat routes', () => {
method: 'PUT', bucket: TEST_BUCKET,
objectKey: testKey,
resourceType: 'metadata',
queryObj: {
versionId: versionIdUtils.encode(testMd.versionId),
},
authCredentials: backbeatAuthCredentials,
requestBody: JSON.stringify(newMd),
}, next);
Expand Down Expand Up @@ -485,6 +487,9 @@ describeSkipIfAWS('backbeat routes', () => {
method: 'PUT', bucket: TEST_BUCKET,
objectKey: testKey,
resourceType: 'metadata',
queryObj: {
versionId: versionIdUtils.encode(testMd.versionId),
},
authCredentials: backbeatAuthCredentials,
requestBody: JSON.stringify(newMd),
}, next);
Expand Down Expand Up @@ -516,6 +521,7 @@ describeSkipIfAWS('backbeat routes', () => {
done();
});
});

it('should not remove data locations on replayed metadata PUT',
done => {
let serializedNewMd;
Expand All @@ -540,6 +546,9 @@ describeSkipIfAWS('backbeat routes', () => {
method: 'PUT', bucket: TEST_BUCKET,
objectKey: testKey,
resourceType: 'metadata',
queryObj: {
versionId: versionIdUtils.encode(testMd.versionId),
},
authCredentials: backbeatAuthCredentials,
requestBody: serializedNewMd,
}, (err, response) => {
Expand All @@ -563,6 +572,97 @@ describeSkipIfAWS('backbeat routes', () => {
done();
});
});

it('should create a new version when no versionId is passed in query string', done => {
let newVersion;
async.waterfall([next => {
// put object's data locations
makeBackbeatRequest({
method: 'PUT', bucket: TEST_BUCKET,
objectKey: testKey,
resourceType: 'data',
headers: {
'content-length': testData.length,
'content-md5': testDataMd5,
'x-scal-canonical-id': testArn,
},
authCredentials: backbeatAuthCredentials,
requestBody: testData }, next);
}, (response, next) => {
assert.strictEqual(response.statusCode, 200);
// put object metadata
const oldMd = Object.assign({}, testMd);
oldMd.location = JSON.parse(response.body);
makeBackbeatRequest({
method: 'PUT', bucket: TEST_BUCKET,
objectKey: testKey,
resourceType: 'metadata',
queryObj: {
versionId: versionIdUtils.encode(testMd.versionId),
},
authCredentials: backbeatAuthCredentials,
requestBody: JSON.stringify(oldMd),
}, next);
}, (response, next) => {
assert.strictEqual(response.statusCode, 200);
const parsedResponse = JSON.parse(response.body);
assert.strictEqual(parsedResponse.versionId, testMd.versionId);
// create new data locations
makeBackbeatRequest({
method: 'PUT', bucket: TEST_BUCKET,
objectKey: testKey,
resourceType: 'data',
headers: {
'content-length': testData.length,
'content-md5': testDataMd5,
'x-scal-canonical-id': testArn,
},
authCredentials: backbeatAuthCredentials,
requestBody: testData }, next);
}, (response, next) => {
assert.strictEqual(response.statusCode, 200);
// create a new version with the new data locations,
// not passing 'versionId' in the query string
const newMd = Object.assign({}, testMd);
newMd.location = JSON.parse(response.body);
makeBackbeatRequest({
method: 'PUT', bucket: TEST_BUCKET,
objectKey: testKey,
resourceType: 'metadata',
authCredentials: backbeatAuthCredentials,
requestBody: JSON.stringify(newMd),
}, next);
}, (response, next) => {
assert.strictEqual(response.statusCode, 200);
const parsedResponse = JSON.parse(response.body);
newVersion = parsedResponse.versionId;
assert.notStrictEqual(newVersion, testMd.versionId);
// give some time for the async deletes to complete,
// then check that we can read the latest version
setTimeout(() => s3.getObject({
Bucket: TEST_BUCKET,
Key: testKey,
}, (err, data) => {
assert.ifError(err);
assert.strictEqual(data.Body.toString(), testData);
next();
}), 1000);
}, next => {
// check that the previous object version is still readable
s3.getObject({
Bucket: TEST_BUCKET,
Key: testKey,
VersionId: versionIdUtils.encode(testMd.versionId),
}, (err, data) => {
assert.ifError(err);
assert.strictEqual(data.Body.toString(), testData);
next();
});
}], err => {
assert.ifError(err);
done();
});
});
});
describe('backbeat authorization checks', () => {
[{ method: 'PUT', resourceType: 'metadata' },
Expand Down Expand Up @@ -649,6 +749,9 @@ describeSkipIfAWS('backbeat routes', () => {
method: 'PUT', bucket: TEST_BUCKET,
objectKey: TEST_KEY,
resourceType: 'metadata',
queryObj: {
versionId: versionIdUtils.encode(testMd.versionId),
},
authCredentials: backbeatAuthCredentials,
requestBody: JSON.stringify(testMd),
}, done));
Expand Down