From a940aecbd4ac748f86c6676b532a851eeb9ae13b Mon Sep 17 00:00:00 2001 From: KillianG Date: Thu, 22 Jun 2023 12:34:16 +0000 Subject: [PATCH] Fix user MD and tags getting deleted when restoring ISSUE: CLDSRV-408 --- lib/api/apiUtils/object/versioning.js | 7 ++ tests/unit/api/apiUtils/versioning.js | 125 +++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 1 deletion(-) diff --git a/lib/api/apiUtils/object/versioning.js b/lib/api/apiUtils/object/versioning.js index 6dfddc9f82..b183c655d4 100644 --- a/lib/api/apiUtils/object/versioning.js +++ b/lib/api/apiUtils/object/versioning.js @@ -453,6 +453,13 @@ function overwritingVersioning(objMD, metadataStoreParams) { // set correct originOp metadataStoreParams.originOp = 's3:ObjectRestore:Completed'; + // We need to keep user metadata and tags + for (const key of Object.keys(objMD)) { + if (key.startsWith('x-amz-meta-')) { + metadataStoreParams.metaHeaders[key] = objMD[key]; + } + } + metadataStoreParams.taggingCopy = objMD.tags; // update restore const days = objMD.archive?.restoreRequestedDays; const now = Date.now(); diff --git a/tests/unit/api/apiUtils/versioning.js b/tests/unit/api/apiUtils/versioning.js index fca9e06c72..3ff5d9b17a 100644 --- a/tests/unit/api/apiUtils/versioning.js +++ b/tests/unit/api/apiUtils/versioning.js @@ -3,9 +3,12 @@ const assert = require('assert'); const { versioning } = require('arsenal'); const { config } = require('../../../../lib/Config'); const INF_VID = versioning.VersionID.getInfVid(config.replicationGroupId); +const { scaledMsPerDay } = config.getTimeOptions(); +const sinon = require('sinon'); const { processVersioningState, getMasterState, - preprocessingVersioningDelete } = + preprocessingVersioningDelete, + overwritingVersioning } = require('../../../../lib/api/apiUtils/object/versioning'); describe('versioning helpers', () => { @@ -616,4 +619,124 @@ describe('versioning helpers', () => { assert.deepStrictEqual(options, testCase[expectedResAttr]); }))); }); + + describe('overwritingVersioning', () => { + const now = Date.now(); + sinon.useFakeTimers(now); + const days = 3; + 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 = { + '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 + } + }; + const options = overwritingVersioning(objMD, metadataStoreParams); + + const 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)), + } + }; + assert.deepStrictEqual(options.versionId, '2345678'); + assert.deepStrictEqual(metadataStoreParams, expectedRes); + }); + + it('Should return nullVersionId', () => { + const metadataStoreParams = {}; + const objMD = { + 'creation-time': now, + 'last-modified': now, + 'originOp': 's3:PutObject', + 'nullVersionId': 'vnull', + 'isNull': true, + 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, undefined); + assert.deepStrictEqual(options.extraMD.nullVersionId, 'vnull'); + assert.deepStrictEqual(options.isNull, true); + assert.deepStrictEqual(metadataStoreParams, expectedRes); + }); + }); });