-
Notifications
You must be signed in to change notification settings - Fork 244
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CLDSRV-497 Fix BackbeatClient.putMetadata with versionID
Issue: When Cloudserver BackbeatClient.putMetadata() option fields are sent to Metadata through the query string, they are converted to strings. As a result, Metadata interprets the value undefined in the versionId field as an empty string (''). Background: Previously, the 'crrExistingObject' script used this bug/behavior as a workaround to generate an internal version ID to replicate null version (= objects created before versioning was enabled). However, this approach has led to inconsistencies, occasionally resulting in the creation of multiple null internal versions. Resolution: To address this issue, the 'crrExistingObject' workaround will be deprecated. Instead, Backbeat will be enhanced to support the replication of null versions directly, thereby ensuring more reliable and consistent behavior in handling versioning.
- Loading branch information
1 parent
7162577
commit 44a1c1c
Showing
4 changed files
with
221 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
175 changes: 175 additions & 0 deletions
175
tests/functional/raw-node/test/routes/routeBackbeatForReplication.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters