Compare commits
1 Commits
developmen
...
feature/CL
Author | SHA1 | Date |
---|---|---|
Nicolas Humbert | 590dfc7ec6 |
|
@ -8,7 +8,7 @@ const services = require('../../../services');
|
|||
const logger = require('../../../utilities/logger');
|
||||
const { dataStore } = require('./storeObject');
|
||||
const locationConstraintCheck = require('./locationConstraintCheck');
|
||||
const { versioningPreprocessing } = require('./versioning');
|
||||
const { versioningPreprocessing, overwritingVersioning } = require('./versioning');
|
||||
const removeAWSChunked = require('./removeAWSChunked');
|
||||
const getReplicationInfo = require('./getReplicationInfo');
|
||||
const { config } = require('../../../Config');
|
||||
|
@ -60,6 +60,9 @@ function _storeInMDandDeleteData(bucketName, dataGetInfo, cipherBundle,
|
|||
function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
|
||||
canonicalID, cipherBundle, request, isDeleteMarker, streamingV4Params,
|
||||
log, callback) {
|
||||
const putVersionId = request.headers['x-scal-s3-version-id'];
|
||||
const isPutVersion = putVersionId || putVersionId === '';
|
||||
|
||||
const size = isDeleteMarker ? 0 : request.parsedContentLength;
|
||||
// although the request method may actually be 'DELETE' if creating a
|
||||
// delete marker, for our purposes we consider this to be a 'PUT'
|
||||
|
@ -257,6 +260,16 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
|
|||
return next(null, dataGetInfoArr);
|
||||
},
|
||||
function getVersioningInfo(infoArr, next) {
|
||||
// if x-scal-s3-version-id header is specified, we overwrite the object/version metadata.
|
||||
if (isPutVersion) {
|
||||
return overwritingVersioning(bucketName, putVersionId, objMD, metadataStoreParams, log,
|
||||
(err, options) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
return next(null, options, infoArr);
|
||||
});
|
||||
}
|
||||
return versioningPreprocessing(bucketName, bucketMD,
|
||||
metadataStoreParams.objectKey, objMD, log, (err, options) => {
|
||||
if (err) {
|
||||
|
@ -278,6 +291,7 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
|
|||
metadataStoreParams.isNull = options.isNull;
|
||||
metadataStoreParams.nullVersionId = options.nullVersionId;
|
||||
metadataStoreParams.nullUploadId = options.nullUploadId;
|
||||
metadataStoreParams.masterVersionId = options.masterVersionId;
|
||||
return _storeInMDandDeleteData(bucketName, infoArr,
|
||||
cipherBundle, metadataStoreParams,
|
||||
options.dataToDelete, requestLogger, requestMethod, next);
|
||||
|
|
|
@ -10,6 +10,38 @@ const versionIdUtils = versioning.VersionID;
|
|||
const nonVersionedObjId =
|
||||
versionIdUtils.getInfVid(config.replicationGroupId);
|
||||
|
||||
/** _decodePutVersionId - decode the version id from x-scal-s3-version-id header
|
||||
* @param {string} [versionId] - version id from x-scal-s3-version-id header
|
||||
* @return {object} response
|
||||
* {string} response.decodedVid - decoded version ID
|
||||
* {boolean} response.isNull - if true, version is null or empty, false otherwise.
|
||||
* {Error} response.err - error
|
||||
*/
|
||||
function _decodePutVersionId(versionId) {
|
||||
const invalidErr = errors.InvalidArgument
|
||||
.customizeDescription('Invalid version id specified in x-scal-s3-version-id header');
|
||||
if (versionId || versionId === '') {
|
||||
if (versionId === '' || versionId === 'null') {
|
||||
return { decodedVid: nonVersionedObjId, isNull: true, err: null };
|
||||
}
|
||||
|
||||
let decoded;
|
||||
try {
|
||||
decoded = versionIdUtils.decode(versionId);
|
||||
} catch (err) {
|
||||
return { err: invalidErr };
|
||||
}
|
||||
|
||||
if (decoded instanceof Error) {
|
||||
return { err: invalidErr };
|
||||
}
|
||||
|
||||
return { decodedVid: decoded, isNull: false, err: null };
|
||||
}
|
||||
|
||||
return { decodedVid: undefined, isNull: false, err: null };
|
||||
}
|
||||
|
||||
/** decodedVidResult - decode the version id from a query object
|
||||
* @param {object} [reqQuery] - request query object
|
||||
* @param {string} [reqQuery.versionId] - version ID sent in request query
|
||||
|
@ -370,6 +402,69 @@ function preprocessingVersioningDelete(bucketName, bucketMD, objectMD,
|
|||
return callback(null, options);
|
||||
}
|
||||
|
||||
/** overwritingVersioning - return versioning information for S3 to handle
|
||||
* storing version metadata with a specific version id.
|
||||
* @param {string} bucketName - name of the bucket.
|
||||
* @param {string} putVersionId - version id from x-scal-s3-version-id header
|
||||
* @param {object} objMD - obj metadata of the master version
|
||||
* @param {object} metadataStoreParams - custom built object containing resource details.
|
||||
* @param {RequestLogger} log - logger instance
|
||||
* @param {function} cb - cb(err, options)
|
||||
* options.versionId - specific versionId to overwrite in metadata
|
||||
* ('' overwrites the master version)
|
||||
* options.versioning - (true/undefined) metadata instruction to create new ver
|
||||
* options.isNull - (true/undefined) whether new version is null or not
|
||||
* options.nullVersionId - if storing a null version in version history, the
|
||||
* version id of the null version
|
||||
* @return {undefined}
|
||||
*/
|
||||
function overwritingVersioning(bucketName, putVersionId, objMD, metadataStoreParams, log, cb) {
|
||||
const { err, decodedVid: decodedPutVersionId, isNull } = _decodePutVersionId(putVersionId);
|
||||
if (err) {
|
||||
log.error('invalid x-scal-s3-version-id header value', { error: err, putVersionId });
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
/* eslint-disable no-param-reassign */
|
||||
// CASE 1: overwriting the master null version or,
|
||||
// overwriting a non-versioned object.
|
||||
if (isNull && (objMD.isNull || !objMD.versionId)) {
|
||||
metadataStoreParams.creationTime = objMD['creation-time'];
|
||||
metadataStoreParams.lastModifiedDate = objMD['last-modified'];
|
||||
// masterVersionId is used instead of generating a new master version id.
|
||||
const options = { masterVersionId: objMD.versionId || '' };
|
||||
// NOTE: if object is not versioned we do not store the isNull property.
|
||||
if (objMD.versionId) {
|
||||
options.isNull = true;
|
||||
}
|
||||
return process.nextTick(() => cb(null, options));
|
||||
}
|
||||
|
||||
// CASE 2: overwriting a version id.
|
||||
const options = {
|
||||
versionId: decodedPutVersionId,
|
||||
};
|
||||
|
||||
// NOTE: We need to retrieve the specific object version ("versionMD") to ensure
|
||||
// that the rest of the original object properties remain intact.
|
||||
// NOTE: "objMD" holds the master version properties,
|
||||
return metadata.getObjectMD(bucketName, metadataStoreParams.objectKey, options, log,
|
||||
(err, versionMD) => {
|
||||
if (err) {
|
||||
log.error('version from x-scal-s3-version-id header does not exist',
|
||||
{ error: err, putVersionId });
|
||||
return cb(err);
|
||||
}
|
||||
metadataStoreParams.creationTime = versionMD['creation-time'];
|
||||
metadataStoreParams.lastModifiedDate = versionMD['last-modified'];
|
||||
// NOTE: set isNull property to true to overwrite a null version.
|
||||
options.isNull = versionMD.isNull;
|
||||
options.nullVersionId = versionMD.nullVersionId;
|
||||
return cb(null, options);
|
||||
});
|
||||
/* eslint-enable no-param-reassign */
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
decodeVersionId,
|
||||
getVersionIdResHeader,
|
||||
|
@ -378,4 +473,5 @@ module.exports = {
|
|||
getMasterState,
|
||||
versioningPreprocessing,
|
||||
preprocessingVersioningDelete,
|
||||
overwritingVersioning,
|
||||
};
|
||||
|
|
|
@ -97,7 +97,7 @@ const services = {
|
|||
lastModifiedDate, versioning, versionId, uploadId,
|
||||
tagging, taggingCopy, replicationInfo, defaultRetention,
|
||||
dataStoreName, creationTime, retentionMode, retentionDate,
|
||||
legalHold, originOp } = params;
|
||||
legalHold, originOp, masterVersionId } = params;
|
||||
log.trace('storing object in metadata');
|
||||
assert.strictEqual(typeof bucketName, 'string');
|
||||
const md = new ObjectMD();
|
||||
|
@ -163,6 +163,10 @@ const services = {
|
|||
md.setUploadId(uploadId);
|
||||
options.replayId = uploadId;
|
||||
}
|
||||
// used to overwrite master version.
|
||||
if (masterVersionId || masterVersionId === '') {
|
||||
options.masterVersionId = masterVersionId;
|
||||
}
|
||||
// information to store about the version and the null version id
|
||||
// in the object metadata
|
||||
const { isNull, nullVersionId, nullUploadId, isDeleteMarker } = params;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"homepage": "https://github.com/scality/S3#readme",
|
||||
"dependencies": {
|
||||
"@hapi/joi": "^17.1.0",
|
||||
"arsenal": "git+https://github.com/scality/Arsenal.git#8.1.47",
|
||||
"arsenal": "git+https://github.com/scality/Arsenal.git#feature/ARSN-202/overwrite",
|
||||
"async": "~2.5.0",
|
||||
"aws-sdk": "2.905.0",
|
||||
"azure-storage": "^2.1.0",
|
||||
|
|
|
@ -0,0 +1,523 @@
|
|||
const assert = require('assert');
|
||||
const async = require('async');
|
||||
const { versioning } = require('arsenal');
|
||||
|
||||
const { config } = require('../../../../../lib/Config');
|
||||
const withV4 = require('../support/withV4');
|
||||
const BucketUtility = require('../../lib/utility/bucket-util');
|
||||
const metadata = require('../../../../../lib/metadata/wrapper');
|
||||
const { DummyRequestLogger } = require('../../../../unit/helpers');
|
||||
const checkError = require('../../lib/utility/checkError');
|
||||
|
||||
const versionIdUtils = versioning.VersionID;
|
||||
|
||||
const log = new DummyRequestLogger();
|
||||
|
||||
const nonVersionedObjId =
|
||||
versionIdUtils.getInfVid(config.replicationGroupId);
|
||||
const bucketName = 'bucket1putversion27';
|
||||
const objectName = 'object1putversion';
|
||||
const mdListingParams = { listingType: 'DelimiterVersions', maxKeys: 1000 };
|
||||
|
||||
function _getMetadata(bucketName, objectName, versionId, cb) {
|
||||
let decodedVersionId;
|
||||
if (versionId) {
|
||||
if (versionId === 'null') {
|
||||
decodedVersionId = nonVersionedObjId;
|
||||
} else {
|
||||
decodedVersionId = versionIdUtils.decode(versionId);
|
||||
}
|
||||
if (decodedVersionId instanceof Error) {
|
||||
return cb(new Error('Invalid version id specified'));
|
||||
}
|
||||
}
|
||||
return metadata.getObjectMD(bucketName, objectName, { versionId: decodedVersionId },
|
||||
log, (err, objMD) => {
|
||||
if (err) {
|
||||
assert.equal(err, null, 'Getting object metadata: expected success, ' +
|
||||
`got error ${JSON.stringify(err)}`);
|
||||
}
|
||||
return cb(null, objMD);
|
||||
});
|
||||
}
|
||||
|
||||
function putObjectVersion(s3, params, vid, next) {
|
||||
const request = s3.putObject(params);
|
||||
request.on('build', () => {
|
||||
request.httpRequest.headers['x-scal-s3-version-id'] = vid;
|
||||
});
|
||||
return request.send(next);
|
||||
}
|
||||
|
||||
describe('PUT object with x-scal-s3-version-id header', () => {
|
||||
withV4(sigCfg => {
|
||||
let bucketUtil;
|
||||
let s3;
|
||||
|
||||
beforeEach(done => {
|
||||
bucketUtil = new BucketUtility('default', sigCfg);
|
||||
s3 = bucketUtil.s3;
|
||||
return metadata.setup(() =>
|
||||
s3.createBucket({ Bucket: bucketName }, err => {
|
||||
if (err) {
|
||||
assert.equal(err, null, 'Creating bucket: Expected success, ' +
|
||||
`got error ${JSON.stringify(err)}`);
|
||||
}
|
||||
done();
|
||||
}));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.stdout.write('Emptying bucket');
|
||||
return bucketUtil.empty(bucketName)
|
||||
.then(() => {
|
||||
process.stdout.write('Deleting bucket');
|
||||
return bucketUtil.deleteOne(bucketName);
|
||||
})
|
||||
.catch(err => {
|
||||
process.stdout.write('Error in afterEach');
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite an object', done => {
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putObject(params, next),
|
||||
(res, next) => _getMetadata(bucketName, objectName, undefined, next),
|
||||
(objMD, next) => {
|
||||
objMDBefore = objMD;
|
||||
return putObjectVersion(s3, params, '', next);
|
||||
},
|
||||
(res, next) => _getMetadata(bucketName, objectName, undefined, next),
|
||||
], (err, objMDAfter) => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite a versioned object', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
let vId;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, (err, res) => {
|
||||
vId = res.VersionId;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => _getMetadata(bucketName, objectName, undefined, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => putObjectVersion(s3, params, vId, err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, undefined, (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if version specified is invalid', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => putObjectVersion(s3, params, 'aJLWKz4Ko9IjBBgXKj5KQT.G9UHv0g7P', err => {
|
||||
checkError(err, 'InvalidArgument', 400);
|
||||
return next();
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if version specified does not exist', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => putObjectVersion(s3, params, '', err => {
|
||||
checkError(err, 'NoSuchKey', 404);
|
||||
return next();
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite a non-current null version', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, 'null', (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => putObjectVersion(s3, params, 'null', err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, 'null', (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite the lastest version and keep nullVersionId', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let vId;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, (err, res) => {
|
||||
vId = res.VersionId;
|
||||
return next(err);
|
||||
}),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => putObjectVersion(s3, params, vId, err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite a current null version', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const sParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Suspended',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => s3.putBucketVersioning(sParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, undefined, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => putObjectVersion(s3, params, '', err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, undefined, (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite a non-current versioned object', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
let vId;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => s3.putObject(params, (err, res) => {
|
||||
vId = res.VersionId;
|
||||
return next(err);
|
||||
}),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => putObjectVersion(s3, params, vId, err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite the current versioned object', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
let vId;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => s3.putObject(params, (err, res) => {
|
||||
vId = res.VersionId;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => putObjectVersion(s3, params, vId, err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite the current versioned object after bucket version suspended', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const sParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Suspended',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
let vId;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => s3.putObject(params, (err, res) => {
|
||||
vId = res.VersionId;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => s3.putBucketVersioning(sParams, err => next(err)),
|
||||
next => putObjectVersion(s3, params, vId, err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, vId, (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite the current versioned object after bucket version enabled', done => {
|
||||
const vParams = {
|
||||
Bucket: bucketName,
|
||||
VersioningConfiguration: {
|
||||
Status: 'Enabled',
|
||||
}
|
||||
};
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
|
||||
async.waterfall([
|
||||
next => s3.putObject(params, err => next(err)),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsBefore = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
next => _getMetadata(bucketName, objectName, undefined, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => s3.putBucketVersioning(vParams, err => next(err)),
|
||||
next => putObjectVersion(s3, params, 'null', err => next(err)),
|
||||
next => _getMetadata(bucketName, objectName, undefined, (err, objMD) => {
|
||||
objMDAfter = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => metadata.listObject(bucketName, mdListingParams, log, (err, res) => {
|
||||
versionsAfter = res.Versions;
|
||||
next(err);
|
||||
}),
|
||||
], err => {
|
||||
assert.equal(err, null, `Expected success got error ${JSON.stringify(err)}`);
|
||||
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -510,9 +510,9 @@ arraybuffer.slice@~0.0.7:
|
|||
optionalDependencies:
|
||||
ioctl "^2.0.2"
|
||||
|
||||
"arsenal@git+https://github.com/scality/Arsenal.git#8.1.47":
|
||||
"arsenal@git+https://github.com/scality/Arsenal.git#feature/ARSN-202/overwrite":
|
||||
version "8.1.47"
|
||||
resolved "git+https://github.com/scality/Arsenal.git#e37712e94f747de6c2118d0280da7370e8aedd69"
|
||||
resolved "git+https://github.com/scality/Arsenal.git#f91f75c97a6cd53cb8f61a00c29542826e582f03"
|
||||
dependencies:
|
||||
"@types/async" "^3.2.12"
|
||||
"@types/utf8" "^3.0.1"
|
||||
|
|
Loading…
Reference in New Issue