Skip to content

Commit

Permalink
Adding replicationinfo to overwriteVersionning to avoid loosing repli…
Browse files Browse the repository at this point in the history
…cation info in case of a restore

Issue: CLDSRV-408
  • Loading branch information
KillianG authored Jun 28, 2023
1 parent a940aec commit 2e908e3
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 90 deletions.
6 changes: 5 additions & 1 deletion lib/api/apiUtils/object/versioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,12 +453,16 @@ function overwritingVersioning(objMD, metadataStoreParams) {
// set correct originOp
metadataStoreParams.originOp = 's3:ObjectRestore:Completed';

const userMDNotToKeep = ['x-amz-meta-scal-s3-restore-attempt'];
// We need to keep user metadata and tags
for (const key of Object.keys(objMD)) {
if (key.startsWith('x-amz-meta-')) {
if (key.startsWith('x-amz-meta-') && !userMDNotToKeep.includes(key)) {
metadataStoreParams.metaHeaders[key] = objMD[key];
}
}
if (objMD.replicationInfo?.status === 'COMPLETED') {
metadataStoreParams.replicationInfo = objMD.replicationInfo;
}
metadataStoreParams.taggingCopy = objMD.tags;
// update restore
const days = objMD.archive?.restoreRequestedDays;
Expand Down
277 changes: 188 additions & 89 deletions tests/unit/api/apiUtils/versioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -620,123 +620,222 @@ describe('versioning helpers', () => {
})));
});

describe('overwritingVersioning', () => {
const now = Date.now();
sinon.useFakeTimers(now);
describe.only('overwritingVersioning', () => {
sinon.useFakeTimers();
const days = 3;
const now = Date.now();
const archiveInfo = {
'archiveID': '126783123678',
};

it('Should update archive with restore infos', () => {
const metadataStoreParams = {};
const objMD = {
'versionId': '2345678',
'creation-time': now,
'last-modified': now,
'originOp': 's3:PutObject',
archive: {
'restoreRequestedDays': days,
'restoreRequestedAt': now,
archiveInfo
}
};
const options = overwritingVersioning(objMD, metadataStoreParams);

const expectedRes = {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
taggingCopy: undefined,
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
}
};
assert.deepStrictEqual(options.versionId, '2345678');
assert.deepStrictEqual(metadataStoreParams, expectedRes);
});

it('Should keep user mds and tags', () => {
const metadataStoreParams = {
'metaHeaders': {},
};
const objMD = {
const array = [
{
description: 'Should update archive with restore infos',
objMD: {
'versionId': '2345678',
'creation-time': now,
'last-modified': now,
'originOp': 's3:PutObject',
'x-amz-meta-test': 'test',
'x-amz-meta-test2': 'test2',
'tags': { 'testtag': 'testtag', 'testtag2': 'testtag2' },
archive: {
'restoreRequestedDays': days,
'restoreRequestedAt': now,
archiveInfo
}},
expectedRes : {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
taggingCopy: undefined,
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
}
}
};
const options = overwritingVersioning(objMD, metadataStoreParams);

const expectedRes = {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
'metaHeaders': {
},
{
description: 'Should keep user mds and tags',
hasUserMD: true,
objMD: {
'versionId': '2345678',
'creation-time': now,
'last-modified': now,
'originOp': 's3:PutObject',
'x-amz-meta-test': 'test',
'x-amz-meta-test2': 'test2',
'tags': { 'testtag': 'testtag', 'testtag2': 'testtag2' },
archive: {
'restoreRequestedDays': days,
'restoreRequestedAt': now,
archiveInfo
}
},
taggingCopy: { 'testtag': 'testtag', 'testtag2': 'testtag2' },
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
expectedRes: {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
'metaHeaders': {
'x-amz-meta-test': 'test',
'x-amz-meta-test2': 'test2',
},
taggingCopy: { 'testtag': 'testtag', 'testtag2': 'testtag2' },
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
}
},
},
{
description: 'Should return nullVersionId',
objMD: {
'creation-time': now,
'last-modified': now,
'originOp': 's3:PutObject',
'nullVersionId': 'vnull',
'isNull': true,
archive: {
'restoreRequestedDays': days,
'restoreRequestedAt': now,
archiveInfo
}
},
expectedRes: {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
taggingCopy: undefined,
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
}
}
};
assert.deepStrictEqual(options.versionId, '2345678');
assert.deepStrictEqual(metadataStoreParams, expectedRes);
});

it('Should return nullVersionId', () => {
const metadataStoreParams = {};
const objMD = {
},
{
description: 'Should not keep x-amz-meta-scal-s3-restore-attempt user MD',
hasUserMD: true,
objMD: {
'versionId': '2345678',
'creation-time': now,
'last-modified': now,
'originOp': 's3:PutObject',
'x-amz-meta-test': 'test',
'x-amz-meta-scal-s3-restore-attempt': 14,
archive: {
'restoreRequestedDays': days,
'restoreRequestedAt': now,
archiveInfo
}
},
expectedRes: {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
'metaHeaders': {
'x-amz-meta-test': 'test',
},
taggingCopy: undefined,
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
}
}
},
{
description: 'Should not update replication infos if COMPLETED',
objMD: {
'versionId': '2345678',
'creation-time': now,
'last-modified': now,
'originOp': 's3:PutObject',
'nullVersionId': 'vnull',
'isNull': true,
'replicationInfo': {
'status' : 'COMPLETED',
'backends' : [
{
'site' : 'azure-blob',
'status' : 'COMPLETED',
'dataStoreVersionId' : ''
}
],
'content' : [
'DATA',
'METADATA'
],
'destination' : 'arn:aws:s3:::replicate-cold',
'storageClass' : 'azure-blob',
'role' : 'arn:aws:iam::root:role/s3-replication-role',
'storageType' : 'azure',
'dataStoreVersionId' : '',
},
archive: {
'restoreRequestedDays': days,
'restoreRequestedAt': now,
archiveInfo
}
},
expectedRes : {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
'replicationInfo': {
'status' : 'COMPLETED',
'backends' : [
{
'site' : 'azure-blob',
'status' : 'COMPLETED',
'dataStoreVersionId' : ''
}
],
'content' : [
'DATA',
'METADATA'
],
'destination' : 'arn:aws:s3:::replicate-cold',
'storageClass' : 'azure-blob',
'role' : 'arn:aws:iam::root:role/s3-replication-role',
'storageType' : 'azure',
'dataStoreVersionId' : '',
},
taggingCopy: undefined,
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
}
}
},
].forEach(testCase => {
it(testCase.description, () => {
const metadataStoreParams = {};
if (testCase.hasUserMD) {
metadataStoreParams.metaHeaders = {};
}
};
const options = overwritingVersioning(objMD, metadataStoreParams);
const options = overwritingVersioning(testCase.objMD, metadataStoreParams);
assert.deepStrictEqual(options.versionId, testCase.objMD.versionId);
assert.deepStrictEqual(metadataStoreParams, testCase.expectedRes);

const expectedRes = {
'creationTime': now,
'lastModifiedDate': now,
'updateMicroVersionId': true,
'originOp': 's3:ObjectRestore:Completed',
taggingCopy: undefined,
archive: {
archiveInfo,
'restoreRequestedDays': 3,
'restoreRequestedAt': now,
'restoreCompletedAt': new Date(now),
'restoreWillExpireAt': new Date(now + (days * scaledMsPerDay)),
if (testCase.objMD.isNull) {
assert.deepStrictEqual(options.extraMD.nullVersionId, 'vnull');
assert.deepStrictEqual(options.isNull, true);
}
};
assert.deepStrictEqual(options.versionId, undefined);
assert.deepStrictEqual(options.extraMD.nullVersionId, 'vnull');
assert.deepStrictEqual(options.isNull, true);
assert.deepStrictEqual(metadataStoreParams, expectedRes);
});
});
});
});

0 comments on commit 2e908e3

Please sign in to comment.