Compare commits
3 Commits
developmen
...
n2b/simple
Author | SHA1 | Date |
---|---|---|
Nicolas Humbert | 4a55b3cdcd | |
Nicolas Humbert | 0adb3c495f | |
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,11 @@ 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) {
|
||||
const options = overwritingVersioning(bucketName, putVersionId, objMD, metadataStoreParams);
|
||||
return process.nextTick(() => next(null, options, infoArr));
|
||||
}
|
||||
return versioningPreprocessing(bucketName, bucketMD,
|
||||
metadataStoreParams.objectKey, objMD, log, (err, options) => {
|
||||
if (err) {
|
||||
|
@ -278,6 +286,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,7 +10,32 @@ const versionIdUtils = versioning.VersionID;
|
|||
const nonVersionedObjId =
|
||||
versionIdUtils.getInfVid(config.replicationGroupId);
|
||||
|
||||
/** decodedVidResult - decode the version id from a query object
|
||||
/** decodeVID - decode the version id
|
||||
* @param {string} versionId - version ID
|
||||
* @return {(Error|string|undefined)} - return Invalid Argument if decryption
|
||||
* fails due to improper format, otherwise undefined or the decoded version id
|
||||
*/
|
||||
function decodeVID(versionId) {
|
||||
if (versionId === 'null') {
|
||||
return versionId;
|
||||
}
|
||||
|
||||
let decoded;
|
||||
const invalidErr = errors.InvalidArgument.customizeDescription('Invalid version id specified');
|
||||
try {
|
||||
decoded = versionIdUtils.decode(versionId);
|
||||
} catch (err) {
|
||||
return invalidErr;
|
||||
}
|
||||
|
||||
if (decoded instanceof Error) {
|
||||
return invalidErr;
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
/** decodeVersionId - decode the version id from a query object
|
||||
* @param {object} [reqQuery] - request query object
|
||||
* @param {string} [reqQuery.versionId] - version ID sent in request query
|
||||
* @return {(Error|string|undefined)} - return Invalid Argument if decryption
|
||||
|
@ -20,16 +45,7 @@ function decodeVersionId(reqQuery) {
|
|||
if (!reqQuery || !reqQuery.versionId) {
|
||||
return undefined;
|
||||
}
|
||||
let versionId = reqQuery.versionId;
|
||||
if (versionId === 'null') {
|
||||
return versionId;
|
||||
}
|
||||
versionId = versionIdUtils.decode(versionId);
|
||||
if (versionId instanceof Error) {
|
||||
return errors.InvalidArgument
|
||||
.customizeDescription('Invalid version id specified');
|
||||
}
|
||||
return versionId;
|
||||
return decodeVID(reqQuery.versionId);
|
||||
}
|
||||
|
||||
/** getVersionIdResHeader - return encrypted version ID if appropriate
|
||||
|
@ -370,6 +386,33 @@ 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
|
||||
* @param {object} metadataStoreParams - custom built object containing resource details.
|
||||
* @return {object} options
|
||||
* options.versionId - specific versionId to overwrite in metadata
|
||||
* 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
|
||||
*/
|
||||
function overwritingVersioning(bucketName, putVersionId, objMD, metadataStoreParams) {
|
||||
/* eslint-disable no-param-reassign */
|
||||
metadataStoreParams.creationTime = objMD['creation-time'];
|
||||
metadataStoreParams.lastModifiedDate = objMD['last-modified'];
|
||||
/* eslint-enable no-param-reassign */
|
||||
|
||||
const options = objMD.versionId ? { versionId:
|
||||
objMD.versionId } : {};
|
||||
|
||||
options.isNull = objMD.isNull;
|
||||
options.nullVersionId = objMD.nullVersionId;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
decodeVersionId,
|
||||
getVersionIdResHeader,
|
||||
|
@ -378,4 +421,6 @@ module.exports = {
|
|||
getMasterState,
|
||||
versioningPreprocessing,
|
||||
preprocessingVersioningDelete,
|
||||
overwritingVersioning,
|
||||
decodeVID,
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ const getReplicationInfo = require('./apiUtils/object/getReplicationInfo');
|
|||
const { data } = require('../data/wrapper');
|
||||
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
||||
const constants = require('../../constants');
|
||||
const { versioningPreprocessing, checkQueryVersionId }
|
||||
const { versioningPreprocessing, checkQueryVersionId, decodeVID, overwritingVersioning }
|
||||
= require('./apiUtils/object/versioning');
|
||||
const services = require('../services');
|
||||
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
||||
|
@ -94,6 +94,21 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
|||
let oldByteLength = null;
|
||||
const responseHeaders = {};
|
||||
|
||||
let versionId;
|
||||
const putVersionId = request.headers['x-scal-s3-version-id'];
|
||||
const isPutVersion = putVersionId || putVersionId === '';
|
||||
if (putVersionId) {
|
||||
const decodedVidResult = decodeVID(putVersionId);
|
||||
if (decodedVidResult instanceof Error) {
|
||||
log.trace('invalid x-scal-s3-version-id header', {
|
||||
versionId: putVersionId,
|
||||
error: decodedVidResult,
|
||||
});
|
||||
return process.nextTick(() => callback(decodedVidResult));
|
||||
}
|
||||
versionId = decodedVidResult;
|
||||
}
|
||||
|
||||
const queryContainsVersionId = checkQueryVersionId(request.query);
|
||||
if (queryContainsVersionId instanceof Error) {
|
||||
return callback(queryContainsVersionId);
|
||||
|
@ -119,6 +134,7 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
|||
// Required permissions for this action
|
||||
// at the destinationBucket level are same as objectPut
|
||||
requestType: 'objectPut',
|
||||
versionId,
|
||||
};
|
||||
metadataValidateBucketAndObj(metadataValParams, log, next);
|
||||
},
|
||||
|
@ -126,6 +142,13 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
|||
if (objMD) {
|
||||
oldByteLength = objMD['content-length'];
|
||||
}
|
||||
|
||||
if (isPutVersion && !objMD) {
|
||||
const err = putVersionId ? errors.NoSuchVersion : errors.NoSuchKey;
|
||||
log.trace('error no object metadata found', { method: 'objectPut', putVersionId });
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
services.metadataValidateMultipart(metadataValParams,
|
||||
(err, mpuBucket, mpuOverview, storedMetadata) => {
|
||||
if (err) {
|
||||
|
@ -297,6 +320,7 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
|||
contentMD5: aggregateETag,
|
||||
size: calculatedSize,
|
||||
multipart: true,
|
||||
isDeleteMarker: false,
|
||||
replicationInfo: getReplicationInfo(objectKey, destBucket,
|
||||
false, calculatedSize, REPLICATION_ACTION),
|
||||
originOp: 's3:ObjectCreated:CompleteMultipartUpload',
|
||||
|
@ -334,6 +358,14 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
|||
masterKeyId: destBucket.getSseMasterKeyId(),
|
||||
};
|
||||
}
|
||||
// if x-scal-s3-version-id header is specified, we overwrite the object/version metadata.
|
||||
if (isPutVersion) {
|
||||
const options = overwritingVersioning(bucketName, putVersionId, objMD, metaStoreParams);
|
||||
return process.nextTick(() => next(null, destBucket, dataLocations,
|
||||
metaStoreParams, mpuBucket, keysToDelete, aggregateETag,
|
||||
objMD, extraPartLocations, pseudoCipherBundle,
|
||||
completeObjData, options));
|
||||
}
|
||||
return versioningPreprocessing(bucketName,
|
||||
destBucket, objectKey, objMD, log, (err, options) => {
|
||||
if (err) {
|
||||
|
@ -347,22 +379,30 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
|||
});
|
||||
return next(err, destBucket);
|
||||
}
|
||||
const dataToDelete = options.dataToDelete;
|
||||
metaStoreParams.versionId = options.versionId;
|
||||
metaStoreParams.versioning = options.versioning;
|
||||
metaStoreParams.isNull = options.isNull;
|
||||
metaStoreParams.nullVersionId = options.nullVersionId;
|
||||
metaStoreParams.nullUploadId = options.nullUploadId;
|
||||
// const dataToDelete = options.dataToDelete;
|
||||
// metaStoreParams.versionId = options.versionId;
|
||||
// metaStoreParams.versioning = options.versioning;
|
||||
// metaStoreParams.isNull = options.isNull;
|
||||
// metaStoreParams.nullVersionId = options.nullVersionId;
|
||||
// metaStoreParams.nullUploadId = options.nullUploadId;
|
||||
return next(null, destBucket, dataLocations,
|
||||
metaStoreParams, mpuBucket, keysToDelete, aggregateETag,
|
||||
objMD, extraPartLocations, pseudoCipherBundle,
|
||||
dataToDelete, completeObjData);
|
||||
completeObjData, options);
|
||||
});
|
||||
},
|
||||
function storeAsNewObj(destinationBucket, dataLocations,
|
||||
metaStoreParams, mpuBucket, keysToDelete, aggregateETag, objMD,
|
||||
extraPartLocations, pseudoCipherBundle, dataToDelete,
|
||||
completeObjData, next) {
|
||||
extraPartLocations, pseudoCipherBundle,
|
||||
completeObjData, options, next) {
|
||||
|
||||
const dataToDelete = options.dataToDelete;
|
||||
metaStoreParams.versionId = options.versionId;
|
||||
metaStoreParams.versioning = options.versioning;
|
||||
metaStoreParams.isNull = options.isNull;
|
||||
metaStoreParams.nullVersionId = options.nullVersionId;
|
||||
metaStoreParams.nullUploadId = options.nullUploadId;
|
||||
|
||||
// For external backends (where completeObjData is not
|
||||
// null), the backend key does not change for new versions
|
||||
// of the same object (or rewrites for nonversioned
|
||||
|
@ -393,6 +433,9 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
|||
// metadata keys, which are likely to have failed in
|
||||
// the previous MPU completion attempt
|
||||
//
|
||||
console.log('objMD.location!!!', objMD.location);
|
||||
console.log('dataLocations!!!', dataLocations);
|
||||
console.log('locationKeysHaveChanged(objMD.location, dataLocations)!!!', locationKeysHaveChanged(objMD.location, dataLocations));
|
||||
if (!locationKeysHaveChanged(objMD.location, dataLocations)) {
|
||||
log.info('MPU complete request replay detected', {
|
||||
method: 'completeMultipartUpload.storeAsNewObj',
|
||||
|
|
|
@ -7,7 +7,7 @@ const { cleanUpBucket } = require('./apiUtils/bucket/bucketCreation');
|
|||
const { getObjectSSEConfiguration } = require('./apiUtils/bucket/bucketEncryption');
|
||||
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
||||
const createAndStoreObject = require('./apiUtils/object/createAndStoreObject');
|
||||
const { checkQueryVersionId } = require('./apiUtils/object/versioning');
|
||||
const { checkQueryVersionId, decodeVID } = require('./apiUtils/object/versioning');
|
||||
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
||||
const { pushMetric } = require('../utapi/utilities');
|
||||
const { validateHeaders } = require('./apiUtils/object/objectLockHelpers');
|
||||
|
@ -41,6 +41,24 @@ const versionIdUtils = versioning.VersionID;
|
|||
*/
|
||||
function objectPut(authInfo, request, streamingV4Params, log, callback) {
|
||||
log.debug('processing request', { method: 'objectPut' });
|
||||
|
||||
const putVersionId = request.headers['x-scal-s3-version-id'];
|
||||
const isPutVersion = putVersionId || putVersionId === '';
|
||||
|
||||
let versionId;
|
||||
|
||||
if (putVersionId) {
|
||||
const decodedVidResult = decodeVID(putVersionId);
|
||||
if (decodedVidResult instanceof Error) {
|
||||
log.trace('invalid x-scal-s3-version-id header', {
|
||||
versionId: putVersionId,
|
||||
error: decodedVidResult,
|
||||
});
|
||||
return process.nextTick(() => callback(decodedVidResult));
|
||||
}
|
||||
versionId = decodedVidResult;
|
||||
}
|
||||
|
||||
const {
|
||||
bucketName,
|
||||
headers,
|
||||
|
@ -69,7 +87,8 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) {
|
|||
const invalidSSEError = errors.InvalidArgument.customizeDescription(
|
||||
'The encryption method specified is not supported');
|
||||
const requestType = 'objectPut';
|
||||
const valParams = { authInfo, bucketName, objectKey, requestType, request };
|
||||
const valParams = { authInfo, bucketName, objectKey, versionId,
|
||||
requestType, request };
|
||||
const canonicalID = authInfo.getCanonicalID();
|
||||
|
||||
if (hasNonPrintables(objectKey)) {
|
||||
|
@ -99,6 +118,12 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) {
|
|||
return callback(errors.NoSuchBucket);
|
||||
}
|
||||
|
||||
if (isPutVersion && !objMD) {
|
||||
const err = putVersionId ? errors.NoSuchVersion : errors.NoSuchKey;
|
||||
log.trace('error no object metadata found', { method: 'objectPut', putVersionId });
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
return async.waterfall([
|
||||
function handleTransientOrDeleteBuckets(next) {
|
||||
if (bucket.hasTransientFlag() || bucket.hasDeletedFlag()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"cloudserver": "S3METADATA=mongodb npm-run-all --parallel start_dataserver start_s3server",
|
||||
"ft_awssdk": "cd tests/functional/aws-node-sdk && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/",
|
||||
"ft_awssdk": "cd tests/functional/aws-node-sdk && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/object/mpuVersion.js",
|
||||
"ft_awssdk_aws": "cd tests/functional/aws-node-sdk && AWS_ON_AIR=true mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/",
|
||||
"ft_awssdk_buckets": "cd tests/functional/aws-node-sdk && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/bucket",
|
||||
"ft_awssdk_objects_misc": "cd tests/functional/aws-node-sdk && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/legacy test/object test/service test/support",
|
||||
|
|
|
@ -0,0 +1,826 @@
|
|||
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 = 'bucket1putversion30';
|
||||
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 putMPUVersion(s3, bucketName, objectName, vId, cb) {
|
||||
async.waterfall([
|
||||
next => {
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
const request = s3.createMultipartUpload(params);
|
||||
if (vId !== undefined) {
|
||||
request.on('build', () => {
|
||||
request.httpRequest.headers['x-scal-s3-version-id'] = vId;
|
||||
});
|
||||
}
|
||||
return request.send(next);
|
||||
},
|
||||
(resCreation, next) => {
|
||||
const uploadId = resCreation.UploadId;
|
||||
const params = {
|
||||
Body: 'okok',
|
||||
Bucket: bucketName,
|
||||
Key: objectName,
|
||||
PartNumber: 1,
|
||||
UploadId: uploadId,
|
||||
};
|
||||
const request = s3.uploadPart(params);
|
||||
if (vId !== undefined) {
|
||||
request.on('build', () => {
|
||||
request.httpRequest.headers['x-scal-s3-version-id'] = vId;
|
||||
});
|
||||
}
|
||||
return request.send((err, res) => next(err, res, uploadId));
|
||||
},
|
||||
(res, uploadId, next) => {
|
||||
const params = {
|
||||
Bucket: bucketName,
|
||||
Key: objectName,
|
||||
MultipartUpload: {
|
||||
Parts: [
|
||||
{
|
||||
ETag: res.ETag,
|
||||
PartNumber: 1
|
||||
},
|
||||
]
|
||||
},
|
||||
UploadId: uploadId,
|
||||
};
|
||||
const request = s3.completeMultipartUpload(params);
|
||||
if (vId !== undefined) {
|
||||
request.on('build', () => {
|
||||
request.httpRequest.headers['x-scal-s3-version-id'] = vId;
|
||||
});
|
||||
}
|
||||
return request.send(err => next(err));
|
||||
},
|
||||
], err => cb(err));
|
||||
}
|
||||
|
||||
function putMPU(s3, bucketName, objectName, cb) {
|
||||
return putMPUVersion(s3, bucketName, objectName, undefined, cb);
|
||||
}
|
||||
|
||||
// function checkVersions(versionsBefore, versionsAfter) {
|
||||
// versionsAfter.forEach((v, i) => {
|
||||
// // assert.notEqual(v.value.Size, versionsBefore[i].value.Size);
|
||||
// assert.notEqual(v.value.ETag, versionsBefore[i].value.ETag);
|
||||
|
||||
// // v.value.Size = versionsBefore[i].value.Size;
|
||||
// v.value.ETag = versionsBefore[i].value.ETag;
|
||||
// });
|
||||
|
||||
// assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
// }
|
||||
|
||||
function checkNotEqualAndUpdate(objMDBefore, objMDAfter, props) {
|
||||
props.forEach(p => {
|
||||
assert.notEqual(objMDAfter[p], objMDBefore[p]);
|
||||
objMDAfter[p] = objMDBefore[p];
|
||||
});
|
||||
}
|
||||
|
||||
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 MPU object', done => {
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
|
||||
async.waterfall([
|
||||
next => putMPU(s3, bucketName, objectName, 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 => putMPUVersion(s3, bucketName, objectName, '', next),
|
||||
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);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'uploadId']);
|
||||
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite an object', done => {
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
let objMDBefore;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
|
||||
async.waterfall([
|
||||
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 => putMPUVersion(s3, bucketName, objectName, '', next),
|
||||
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)}`);
|
||||
|
||||
versionsAfter.forEach((v, i) => {
|
||||
assert.notEqual(v.value.Size, versionsBefore[i].value.Size);
|
||||
assert.notEqual(v.value.ETag, versionsBefore[i].value.ETag);
|
||||
|
||||
v.value.Size = versionsBefore[i].value.Size;
|
||||
v.value.ETag = versionsBefore[i].value.ETag;
|
||||
});
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
|
||||
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, vId, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => putMPUVersion(s3, bucketName, objectName, vId, next),
|
||||
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)}`);
|
||||
|
||||
versionsAfter.forEach((v, i) => {
|
||||
assert.notEqual(v.value.Size, versionsBefore[i].value.Size);
|
||||
assert.notEqual(v.value.ETag, versionsBefore[i].value.ETag);
|
||||
|
||||
v.value.Size = versionsBefore[i].value.Size;
|
||||
v.value.ETag = versionsBefore[i].value.ETag;
|
||||
});
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite the current version if empty version id header', 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, vId, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => putMPUVersion(s3, bucketName, objectName, '', next),
|
||||
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)}`);
|
||||
|
||||
versionsAfter.forEach((v, i) => {
|
||||
assert.notEqual(v.value.Size, versionsBefore[i].value.Size);
|
||||
assert.notEqual(v.value.ETag, versionsBefore[i].value.ETag);
|
||||
|
||||
v.value.Size = versionsBefore[i].value.Size;
|
||||
v.value.ETag = versionsBefore[i].value.ETag;
|
||||
});
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
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 => putMPUVersion(s3, bucketName, objectName, '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 key specified does not exist', done => {
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
|
||||
async.waterfall([
|
||||
next => putMPUVersion(s3, bucketName, objectName, '', err => {
|
||||
checkError(err, 'NoSuchKey', 404);
|
||||
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 => putMPUVersion(s3, bucketName, objectName, '393833343735313131383832343239393939393952473030312020313031', err => {
|
||||
checkError(err, 'NoSuchVersion', 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 => putMPUVersion(s3, bucketName, objectName, 'null', next),
|
||||
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.notEqual(versionsAfter[1].value.Size, versionsBefore[1].value.Size);
|
||||
assert.notEqual(versionsAfter[1].value.ETag, versionsBefore[1].value.ETag);
|
||||
|
||||
versionsAfter[1].value.Size = versionsBefore[1].value.Size;
|
||||
versionsAfter[1].value.ETag = versionsBefore[1].value.ETag;
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
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 => putMPUVersion(s3, bucketName, objectName, vId, next),
|
||||
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.notEqual(versionsAfter[0].value.Size, versionsBefore[0].value.Size);
|
||||
assert.notEqual(versionsAfter[0].value.ETag, versionsBefore[0].value.ETag);
|
||||
|
||||
versionsAfter[0].value.Size = versionsBefore[0].value.Size;
|
||||
versionsAfter[0].value.ETag = versionsBefore[0].value.ETag;
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
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 => putMPUVersion(s3, bucketName, objectName, '', next),
|
||||
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.notEqual(versionsAfter[0].value.Size, versionsBefore[0].value.Size);
|
||||
assert.notEqual(versionsAfter[0].value.ETag, versionsBefore[0].value.ETag);
|
||||
|
||||
versionsAfter[0].value.Size = versionsBefore[0].value.Size;
|
||||
versionsAfter[0].value.ETag = versionsBefore[0].value.ETag;
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
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 => putMPUVersion(s3, bucketName, objectName, vId, next),
|
||||
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.notEqual(versionsAfter[1].value.Size, versionsBefore[1].value.Size);
|
||||
assert.notEqual(versionsAfter[1].value.ETag, versionsBefore[1].value.ETag);
|
||||
|
||||
versionsAfter[1].value.Size = versionsBefore[1].value.Size;
|
||||
versionsAfter[1].value.ETag = versionsBefore[1].value.ETag;
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
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 => putMPUVersion(s3, bucketName, objectName, vId, next),
|
||||
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.notEqual(versionsAfter[0].value.Size, versionsBefore[0].value.Size);
|
||||
assert.notEqual(versionsAfter[0].value.ETag, versionsBefore[0].value.ETag);
|
||||
|
||||
versionsAfter[0].value.Size = versionsBefore[0].value.Size;
|
||||
versionsAfter[0].value.ETag = versionsBefore[0].value.ETag;
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
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 => putMPUVersion(s3, bucketName, objectName, vId, next),
|
||||
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.notEqual(versionsAfter[0].value.Size, versionsBefore[0].value.Size);
|
||||
assert.notEqual(versionsAfter[0].value.ETag, versionsBefore[0].value.ETag);
|
||||
|
||||
versionsAfter[0].value.Size = versionsBefore[0].value.Size;
|
||||
versionsAfter[0].value.ETag = versionsBefore[0].value.ETag;
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should overwrite the current null 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 => putMPUVersion(s3, bucketName, objectName, 'null', next),
|
||||
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.notEqual(versionsAfter[0].value.Size, versionsBefore[0].value.Size);
|
||||
assert.notEqual(versionsAfter[0].value.ETag, versionsBefore[0].value.ETag);
|
||||
|
||||
versionsAfter[0].value.Size = versionsBefore[0].value.Size;
|
||||
versionsAfter[0].value.ETag = versionsBefore[0].value.ETag;
|
||||
assert.deepStrictEqual(versionsAfter, versionsBefore);
|
||||
|
||||
assert.notEqual(objMDAfter.uploadId, objMDBefore.uploadId);
|
||||
delete(objMDAfter.uploadId);
|
||||
|
||||
checkNotEqualAndUpdate(objMDBefore, objMDAfter,
|
||||
['location', 'content-length', 'content-md5', 'originOp']);
|
||||
|
||||
assert.deepStrictEqual(objMDAfter, objMDBefore);
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,599 @@
|
|||
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 = 'bucket1putversion30';
|
||||
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;
|
||||
let objMDAfter;
|
||||
let versionsBefore;
|
||||
let versionsAfter;
|
||||
|
||||
async.waterfall([
|
||||
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 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, 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 version if empty version id header', 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, vId, (err, objMD) => {
|
||||
objMDBefore = objMD;
|
||||
return next(err);
|
||||
}),
|
||||
next => putObjectVersion(s3, params, '', 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 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 key specified does not exist', done => {
|
||||
const params = { Bucket: bucketName, Key: objectName };
|
||||
|
||||
async.waterfall([
|
||||
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 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,
|
||||
'393833343735313131383832343239393939393952473030312020313031', err => {
|
||||
checkError(err, 'NoSuchVersion', 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 null 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue