Compare commits
3 Commits
developmen
...
w/8.5/bugf
Author | SHA1 | Date |
---|---|---|
Nicolas Humbert | 667a4677f3 | |
bert-e | 7b0daa3d85 | |
Nicolas Humbert | 048a10b191 |
|
@ -472,16 +472,28 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) {
|
|||
omVal[headerName] = objMd[headerName];
|
||||
});
|
||||
}
|
||||
|
||||
const versionId = decodeVersionId(request.query);
|
||||
const versioning = bucketInfo.isVersioningEnabled();
|
||||
const options = {};
|
||||
if (versionId || omVal.replicationInfo.isNFS) {
|
||||
// specify both 'versioning' and 'versionId' to create a "new"
|
||||
// version (updating master as well) but with specified
|
||||
// versionId
|
||||
options.versioning = bucketInfo.isVersioningEnabled();
|
||||
options.versioning = versioning;
|
||||
options.versionId = versionId;
|
||||
}
|
||||
|
||||
if (versionId === 'null') {
|
||||
const nullVersionId = objMd && objMd.versionId;
|
||||
if (versioning && !nullVersionId) {
|
||||
// If the null version does not have a version id, it is a current null version.
|
||||
// To update the metadata of a current version, versioning is set to false
|
||||
options.versioning = false;
|
||||
}
|
||||
options.versionId = nullVersionId;
|
||||
}
|
||||
|
||||
// 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
|
||||
// none was provided in the object metadata value.
|
||||
|
|
|
@ -3,7 +3,8 @@ const AWS = require('aws-sdk');
|
|||
const async = require('async');
|
||||
const crypto = require('crypto');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { versioning } = require('arsenal');
|
||||
const { models, versioning } = require('arsenal');
|
||||
const { ObjectMD } = models;
|
||||
const versionIdUtils = versioning.VersionID;
|
||||
|
||||
const { makeid } = require('../../unit/helpers');
|
||||
|
@ -39,6 +40,7 @@ const TEST_BUCKET = 'backbeatbucket';
|
|||
const TEST_ENCRYPTED_BUCKET = 'backbeatbucket-encrypted';
|
||||
const TEST_KEY = 'fookey';
|
||||
const NONVERSIONED_BUCKET = 'backbeatbucket-non-versioned';
|
||||
const BUCKET_FOR_NULL_VERSION = 'backbeatbucket-null-version';
|
||||
|
||||
const testArn = 'aws::iam:123456789012:user/bart';
|
||||
const testKey = 'testkey';
|
||||
|
@ -132,6 +134,21 @@ function checkObjectData(s3, bucket, objectKey, dataValue, done) {
|
|||
});
|
||||
}
|
||||
|
||||
function updateStorageClass(data, storageClass) {
|
||||
let parsedBody;
|
||||
try {
|
||||
parsedBody = JSON.parse(data.body);
|
||||
} catch (err) {
|
||||
return { error: err };
|
||||
}
|
||||
const { result, error } = ObjectMD.createFromBlob(parsedBody.Body);
|
||||
if (error) {
|
||||
return { error };
|
||||
}
|
||||
result.setAmzStorageClass(storageClass);
|
||||
return { result };
|
||||
}
|
||||
|
||||
/** makeBackbeatRequest - utility function to generate a request going
|
||||
* through backbeat route
|
||||
* @param {object} params - params for making request
|
||||
|
@ -275,6 +292,296 @@ describe.skip('backbeat routes', () => {
|
|||
});
|
||||
|
||||
describe('backbeat PUT routes', () => {
|
||||
describe('null version', () => {
|
||||
beforeEach(done => s3.createBucket({ Bucket: BUCKET_FOR_NULL_VERSION }, done));
|
||||
afterEach(done => {
|
||||
bucketUtil.empty(BUCKET_FOR_NULL_VERSION)
|
||||
.then(() => s3.deleteBucket({ Bucket: BUCKET_FOR_NULL_VERSION }).promise())
|
||||
.then(() => done());
|
||||
});
|
||||
|
||||
it('should update metadata of a current null version', done => {
|
||||
const bucket = BUCKET_FOR_NULL_VERSION;
|
||||
const keyName = 'key0';
|
||||
const storageClass = 'foo';
|
||||
let objMD;
|
||||
return async.series([
|
||||
next => s3.putObject({ Bucket: bucket, Key: keyName, Body: new Buffer(testData) }, next),
|
||||
next => s3.putBucketVersioning({ Bucket: bucket, VersioningConfiguration: { Status: 'Enabled' } },
|
||||
next),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'GET',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
}, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
const { error, result } = updateStorageClass(data, storageClass);
|
||||
if (error) {
|
||||
return next(error);
|
||||
}
|
||||
objMD = result;
|
||||
return next();
|
||||
}),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'PUT',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
requestBody: objMD.getSerialized(),
|
||||
}, next),
|
||||
next => s3.headObject({ Bucket: bucket, Key: keyName, VersionId: 'null' }, next),
|
||||
next => s3.listObjectVersions({ Bucket: bucket }, next),
|
||||
], (err, data) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const headObjectRes = data[4];
|
||||
assert.strictEqual(headObjectRes.VersionId, 'null');
|
||||
assert.strictEqual(headObjectRes.StorageClass, storageClass);
|
||||
|
||||
const listObjectVersionsRes = data[5];
|
||||
const versions = listObjectVersionsRes.Versions;
|
||||
assert.strictEqual(versions.length, 1);
|
||||
const version = versions[0];
|
||||
assert.strictEqual(version.Key, keyName);
|
||||
assert.strictEqual(version.VersionId, 'null');
|
||||
assert.strictEqual(version.StorageClass, storageClass);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should update metadata of a non-current null version', done => {
|
||||
const bucket = BUCKET_FOR_NULL_VERSION;
|
||||
const keyName = 'key0';
|
||||
const storageClass = 'foo';
|
||||
let objMD;
|
||||
let expectedVersionId;
|
||||
return async.series([
|
||||
next => s3.putObject({ Bucket: bucket, Key: keyName, Body: new Buffer(testData) }, next),
|
||||
next => s3.putBucketVersioning({ Bucket: bucket, VersioningConfiguration: { Status: 'Enabled' } },
|
||||
next),
|
||||
next => s3.putObject({ Bucket: bucket, Key: keyName, Body: new Buffer(testData) }, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
expectedVersionId = data.VersionId;
|
||||
return next();
|
||||
}),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'GET',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
}, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
const { error, result } = updateStorageClass(data, storageClass);
|
||||
if (error) {
|
||||
return next(error);
|
||||
}
|
||||
objMD = result;
|
||||
return next();
|
||||
}),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'PUT',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
requestBody: objMD.getSerialized(),
|
||||
}, next),
|
||||
next => s3.headObject({ Bucket: bucket, Key: keyName, VersionId: 'null' }, next),
|
||||
next => s3.listObjectVersions({ Bucket: bucket }, next),
|
||||
], (err, data) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const headObjectRes = data[5];
|
||||
assert.strictEqual(headObjectRes.VersionId, 'null');
|
||||
assert.strictEqual(headObjectRes.StorageClass, storageClass);
|
||||
|
||||
const listObjectVersionsRes = data[6];
|
||||
const versions = listObjectVersionsRes.Versions;
|
||||
assert.strictEqual(versions.length, 2);
|
||||
|
||||
const currentVersions = versions.filter(v => v.IsLatest);
|
||||
assert.strictEqual(currentVersions.length, 1);
|
||||
const currentVersion = currentVersions[0];
|
||||
assert.strictEqual(currentVersion.Key, keyName);
|
||||
assert.strictEqual(currentVersion.VersionId, expectedVersionId);
|
||||
assert.strictEqual(currentVersion.StorageClass, 'STANDARD');
|
||||
|
||||
const nonCurrentVersions = versions.filter(v => !v.IsLatest);
|
||||
assert.strictEqual(nonCurrentVersions.length, 1);
|
||||
const nonCurrentVersion = nonCurrentVersions[0];
|
||||
assert.strictEqual(nonCurrentVersion.Key, keyName);
|
||||
assert.strictEqual(nonCurrentVersion.VersionId, 'null');
|
||||
assert.strictEqual(nonCurrentVersion.StorageClass, storageClass);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should update metadata of a non-version object', done => {
|
||||
const bucket = BUCKET_FOR_NULL_VERSION;
|
||||
const keyName = 'key0';
|
||||
const storageClass = 'foo';
|
||||
let objMD;
|
||||
return async.series([
|
||||
next => s3.putObject({ Bucket: bucket, Key: keyName, Body: new Buffer(testData) }, next),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'GET',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
}, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
const { error, result } = updateStorageClass(data, storageClass);
|
||||
if (error) {
|
||||
return next(error);
|
||||
}
|
||||
objMD = result;
|
||||
return next();
|
||||
}),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'PUT',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
requestBody: objMD.getSerialized(),
|
||||
}, next),
|
||||
next => s3.headObject({ Bucket: bucket, Key: keyName }, next),
|
||||
next => s3.listObjectVersions({ Bucket: bucket }, next),
|
||||
], (err, data) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
const headObjectRes = data[3];
|
||||
assert(!headObjectRes.VersionId);
|
||||
assert.strictEqual(headObjectRes.StorageClass, storageClass);
|
||||
|
||||
const listObjectVersionsRes = data[4];
|
||||
const versions = listObjectVersionsRes.Versions;
|
||||
assert.strictEqual(versions.length, 1);
|
||||
const currentVersion = versions[0];
|
||||
assert.strictEqual(currentVersion.Key, keyName);
|
||||
assert.strictEqual(currentVersion.VersionId, 'null');
|
||||
assert.strictEqual(currentVersion.StorageClass, storageClass);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should update metadata of the current null version created after suspending versioning', done => {
|
||||
const bucket = BUCKET_FOR_NULL_VERSION;
|
||||
const keyName = 'key0';
|
||||
const storageClass = 'foo';
|
||||
let expectedVersionId;
|
||||
let objMD;
|
||||
return async.series([
|
||||
next => s3.putBucketVersioning({ Bucket: bucket, VersioningConfiguration: { Status: 'Enabled' } },
|
||||
next),
|
||||
next => s3.putObject({ Bucket: bucket, Key: keyName, Body: new Buffer(testData) }, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
expectedVersionId = data.VersionId;
|
||||
return next();
|
||||
}),
|
||||
next => s3.putBucketVersioning({ Bucket: bucket, VersioningConfiguration: { Status: 'Suspended' } },
|
||||
next),
|
||||
next => s3.putObject({ Bucket: bucket, Key: keyName, Body: new Buffer(testData) }, next),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'GET',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
}, (err, data) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
const { error, result } = updateStorageClass(data, storageClass);
|
||||
if (error) {
|
||||
return next(error);
|
||||
}
|
||||
objMD = result;
|
||||
return next();
|
||||
}),
|
||||
next => makeBackbeatRequest({
|
||||
method: 'PUT',
|
||||
resourceType: 'metadata',
|
||||
bucket,
|
||||
objectKey: keyName,
|
||||
queryObj: {
|
||||
versionId: 'null',
|
||||
},
|
||||
authCredentials: backbeatAuthCredentials,
|
||||
requestBody: objMD.getSerialized(),
|
||||
}, next),
|
||||
next => s3.headObject({ Bucket: bucket, Key: keyName, VersionId: 'null' }, next),
|
||||
next => s3.listObjectVersions({ Bucket: bucket }, 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.Versions;
|
||||
assert.strictEqual(versions.length, 2);
|
||||
|
||||
const currentVersions = versions.filter(v => v.IsLatest);
|
||||
assert.strictEqual(currentVersions.length, 1);
|
||||
const currentVersion = currentVersions[0];
|
||||
assert.strictEqual(currentVersion.Key, keyName);
|
||||
assert.strictEqual(currentVersion.VersionId, 'null');
|
||||
assert.strictEqual(currentVersion.StorageClass, storageClass);
|
||||
|
||||
const nonCurrentVersions = versions.filter(v => !v.IsLatest);
|
||||
assert.strictEqual(nonCurrentVersions.length, 1);
|
||||
const nonCurrentVersion = nonCurrentVersions[0];
|
||||
assert.strictEqual(nonCurrentVersion.Key, keyName);
|
||||
assert.strictEqual(nonCurrentVersion.VersionId, expectedVersionId);
|
||||
assert.strictEqual(nonCurrentVersion.StorageClass, 'STANDARD');
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PUT data + metadata should create a new complete object',
|
||||
() => {
|
||||
[{
|
||||
|
|
Loading…
Reference in New Issue