Skip to content

Commit

Permalink
Merge branches 'w/8.7/bugfix/CLDSRV-458-fixBucketdParamsUpdatingLegac…
Browse files Browse the repository at this point in the history
…yNullVersion' and 'q/5384/8.6/bugfix/CLDSRV-458-fixBucketdParamsUpdatingLegacyNullVersion' into tmp/octopus/q/8.7
  • Loading branch information
bert-e committed Oct 24, 2023
3 parents 5f82ee2 + 114b885 + 4ebb5d4 commit 41d6365
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 76 deletions.
99 changes: 63 additions & 36 deletions lib/api/apiUtils/object/versioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,60 +377,86 @@ function versioningPreprocessing(bucketName, bucketMD, objectKey, objMD,
});
}

/** Return options to pass to Metadata layer for version-specific
* operations with the given requested version ID
*
* @param {object} objectMD - object metadata
* @param {boolean} nullVersionCompatMode - if true, behaves in null
* version compatibility mode
* @return {object} options object with params:
* {string} [options.versionId] - specific versionId to update
* {boolean} [options.isNull=true|false|undefined] - if set, tells the
* Metadata backend if we're updating or deleting a new-style null
* version (stored in master or null key), or not a null version.
*/
function getVersionSpecificMetadataOptions(objectMD, nullVersionCompatMode) {
// Use the internal versionId if it is a "real" null version (not
// non-versioned)
//
// If the target object is non-versioned: do not specify a
// "versionId" attribute nor "isNull"
//
// If the target version is a null version, i.e. has the "isNull"
// attribute:
//
// - send the "isNull=true" param to Metadata if the version is
// already a null key put by a non-compat mode Cloudserver, to
// let Metadata know that the null key is to be updated or
// deleted. This is the case if the "isNull2" metadata attribute
// exists
//
// - otherwise, do not send the "isNull" parameter to hint
// Metadata that it is a legacy null version
//
// If the target version is not a null version and is versioned:
//
// - send the "isNull=false" param to Metadata in non-compat
// mode (mandatory for v1 format)
//
// - otherwise, do not send the "isNull" parameter to hint
// Metadata that an existing null version may not be stored in a
// null key
//
//
if (objectMD.versionId === undefined) {
return {};
}
const options = { versionId: objectMD.versionId };
if (objectMD.isNull) {
if (objectMD.isNull2) {
options.isNull = true;
}
} else if (!nullVersionCompatMode) {
options.isNull = false;
}
return options;
}

/** preprocessingVersioningDelete - return versioning information for S3 to
* manage deletion of objects and versions, including creation of delete markers
* @param {string} bucketName - name of bucket
* @param {object} bucketMD - bucket metadata
* @param {object} objectMD - obj metadata
* @param {string} [reqVersionId] - specific version ID sent as part of request
* @param {boolean} nullVersionCompatMode - if true, behaves in null
* version compatibility mode and return appropriate values:
* - in normal mode, returns an 'isNull' boolean sent to Metadata (true or false)
* - in compatibility mode, does not return an 'isNull' property
* @param {boolean} nullVersionCompatMode - if true, behaves in null version compatibility mode
* @return {object} options object with params:
* {boolean} [options.deleteData=true|undefined] - whether to delete data (if undefined
* means creating a delete marker instead)
* {string} [options.versionId] - specific versionId to delete
* {boolean} [options.isNull=true|false|undefined] - if set, tells the
* Metadata backend if we're deleting a null version or not a null
* version. Not set if `nullVersionCompatMode` is true.
* Metadata backend if we're deleting a new-style null version (stored
* in master or null key), or not a null version.
*/
function preprocessingVersioningDelete(bucketName, bucketMD, objectMD, reqVersionId, nullVersionCompatMode) {
const options = {};
let options = {};
if (bucketMD.getVersioningConfiguration() && reqVersionId) {
options = getVersionSpecificMetadataOptions(objectMD, nullVersionCompatMode);
}
if (!bucketMD.getVersioningConfiguration() || reqVersionId) {
// delete data if bucket is non-versioned or the request
// deletes a specific version
options.deleteData = true;
}
if (bucketMD.getVersioningConfiguration() && reqVersionId) {
if (reqVersionId === 'null') {
// deleting the 'null' version if it exists:
//
// - use its internal versionId if it is a "real" null
// version (not non-versioned)
//
// - send the "isNull" param to Metadata if:
//
// - in non-compat mode (mandatory for v1 format)
//
// - OR if the version is already a null key put by a
// non-compat mode Cloudserver, to let Metadata know that
// the null key is to be deleted. This is the case if the
// "isNull2" param is set.
if (objectMD.versionId !== undefined) {
options.versionId = objectMD.versionId;
if (objectMD.isNull2) {
options.isNull = true;
}
}
} else {
// deleting a specific version
options.versionId = reqVersionId;
if (!nullVersionCompatMode) {
options.isNull = false;
}
}
}
return options;
}

Expand Down Expand Up @@ -528,6 +554,7 @@ module.exports = {
processVersioningState,
getMasterState,
versioningPreprocessing,
getVersionSpecificMetadataOptions,
preprocessingVersioningDelete,
overwritingVersioning,
decodeVID,
Expand Down
10 changes: 2 additions & 8 deletions lib/api/objectDeleteTagging.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const async = require('async');
const { errors } = require('arsenal');

const { decodeVersionId, getVersionIdResHeader }
const { decodeVersionId, getVersionIdResHeader, getVersionSpecificMetadataOptions }
= require('./apiUtils/object/versioning');

const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
Expand Down Expand Up @@ -75,13 +75,7 @@ function objectDeleteTagging(authInfo, request, log, callback) {
(bucket, objectMD, next) => {
// eslint-disable-next-line no-param-reassign
objectMD.tags = {};
const params = {};
if (objectMD.versionId) {
params.versionId = objectMD.versionId;
if (!config.nullVersionCompatMode) {
params.isNull = objectMD.isNull || false;
}
}
const params = getVersionSpecificMetadataOptions(objectMD, config.nullVersionCompatMode);
const replicationInfo = getReplicationInfo(objectKey, bucket, true,
0, REPLICATION_ACTION, objectMD);
if (replicationInfo) {
Expand Down
10 changes: 2 additions & 8 deletions lib/api/objectPutACL.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { pushMetric } = require('../utapi/utilities');
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
const constants = require('../../constants');
const vault = require('../auth/vault');
const { decodeVersionId, getVersionIdResHeader }
const { decodeVersionId, getVersionIdResHeader, getVersionSpecificMetadataOptions }
= require('./apiUtils/object/versioning');
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
const monitoring = require('../utilities/monitoringHandler');
Expand Down Expand Up @@ -281,13 +281,7 @@ function objectPutACL(authInfo, request, log, cb) {
},
function addAclsToObjMD(bucket, objectMD, ACLParams, next) {
// Add acl's to object metadata
const params = {};
if (objectMD.versionId) {
params.versionId = objectMD.versionId;
if (!config.nullVersionCompatMode) {
params.isNull = objectMD.isNull || false;
}
}
const params = getVersionSpecificMetadataOptions(objectMD, config.nullVersionCompatMode);
acl.addObjectACL(bucket, objectKey, objectMD,
ACLParams, params, log, err => next(err, bucket, objectMD));
},
Expand Down
10 changes: 2 additions & 8 deletions lib/api/objectPutLegalHold.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const async = require('async');
const { errors, s3middleware } = require('arsenal');

const collectCorsHeaders = require('../utilities/collectCorsHeaders');
const { decodeVersionId, getVersionIdResHeader } =
const { decodeVersionId, getVersionIdResHeader, getVersionSpecificMetadataOptions } =
require('./apiUtils/object/versioning');
const getReplicationInfo = require('./apiUtils/object/getReplicationInfo');
const metadata = require('../metadata/wrapper');
Expand Down Expand Up @@ -86,13 +86,7 @@ function objectPutLegalHold(authInfo, request, log, callback) {
(bucket, legalHold, objectMD, next) => {
// eslint-disable-next-line no-param-reassign
objectMD.legalHold = legalHold;
const params = {};
if (objectMD.versionId) {
params.versionId = objectMD.versionId;
if (!config.nullVersionCompatMode) {
params.isNull = objectMD.isNull || false;
}
}
const params = getVersionSpecificMetadataOptions(objectMD, config.nullVersionCompatMode);
const replicationInfo = getReplicationInfo(objectKey, bucket, true,
0, REPLICATION_ACTION, objectMD);
if (replicationInfo) {
Expand Down
10 changes: 2 additions & 8 deletions lib/api/objectPutRetention.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const async = require('async');
const { errors, s3middleware } = require('arsenal');

const { decodeVersionId, getVersionIdResHeader } =
const { decodeVersionId, getVersionIdResHeader, getVersionSpecificMetadataOptions } =
require('./apiUtils/object/versioning');
const { ObjectLockInfo, checkUserGovernanceBypass, hasGovernanceBypassHeader } =
require('./apiUtils/object/objectLockHelpers');
Expand Down Expand Up @@ -117,13 +117,7 @@ function objectPutRetention(authInfo, request, log, callback) {
/* eslint-disable no-param-reassign */
objectMD.retentionMode = retentionInfo.mode;
objectMD.retentionDate = retentionInfo.date;
const params = {};
if (objectMD.versionId) {
params.versionId = objectMD.versionId;
if (!config.nullVersionCompatMode) {
params.isNull = objectMD.isNull || false;
}
}
const params = getVersionSpecificMetadataOptions(objectMD, config.nullVersionCompatMode);
const replicationInfo = getReplicationInfo(objectKey, bucket, true,
0, REPLICATION_ACTION, objectMD);
if (replicationInfo) {
Expand Down
10 changes: 2 additions & 8 deletions lib/api/objectPutTagging.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const async = require('async');
const { errors, s3middleware } = require('arsenal');

const { decodeVersionId, getVersionIdResHeader } =
const { decodeVersionId, getVersionIdResHeader, getVersionSpecificMetadataOptions } =
require('./apiUtils/object/versioning');

const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
Expand Down Expand Up @@ -81,13 +81,7 @@ function objectPutTagging(authInfo, request, log, callback) {
(bucket, tags, objectMD, next) => {
// eslint-disable-next-line no-param-reassign
objectMD.tags = tags;
const params = {};
if (objectMD.versionId) {
params.versionId = objectMD.versionId;
if (!config.nullVersionCompatMode) {
params.isNull = objectMD.isNull || false;
}
}
const params = getVersionSpecificMetadataOptions(objectMD, config.nullVersionCompatMode);
const replicationInfo = getReplicationInfo(objectKey, bucket, true,
0, REPLICATION_ACTION, objectMD);
if (replicationInfo) {
Expand Down
Loading

0 comments on commit 41d6365

Please sign in to comment.