diff --git a/tests/functional/aws-node-sdk/test/mdSearch/basicSearch.js b/tests/functional/aws-node-sdk/test/mdSearch/basicSearch.js index 81f5ef02c7..e957e69ee8 100644 --- a/tests/functional/aws-node-sdk/test/mdSearch/basicSearch.js +++ b/tests/functional/aws-node-sdk/test/mdSearch/basicSearch.js @@ -1,4 +1,11 @@ +const { + CreateBucketCommand, + DeleteBucketCommand, + PutObjectCommand, + DeleteObjectsCommand, +} = require('@aws-sdk/client-s3'); const s3Client = require('./utils/s3SDK'); + const { runAndCheckSearch, runIfMongo } = require('./utils/helpers'); const objectKey = 'findMe'; @@ -10,33 +17,35 @@ const updatedUserMetadata = { food: 'cake' }; runIfMongo('Basic search', () => { const bucketName = `basicsearchmebucket${Date.now()}`; + before(done => { - s3Client.createBucket({ Bucket: bucketName }, err => { - if (err) { - return done(err); - } - return s3Client.putObject({ Bucket: bucketName, Key: objectKey, - Metadata: userMetadata, Tagging: objectTagData }, err => { - if (err) { - return done(err); - } - return s3Client.putObject({ Bucket: bucketName, - Key: hiddenKey, Tagging: hiddenTagData }, done); - }); - }); - }); - - after(done => { - s3Client.deleteObjects({ Bucket: bucketName, Delete: { Objects: [ - { Key: objectKey }, - { Key: hiddenKey }], - } }, - err => { - if (err) { - return done(err); - } - return s3Client.deleteBucket({ Bucket: bucketName }, done); - }); + s3Client.send(new CreateBucketCommand({ Bucket: bucketName })) + .then(() => s3Client.send(new PutObjectCommand({ + Bucket: bucketName, + Key: objectKey, + Metadata: userMetadata, + Tagging: objectTagData, + }))) + .then(() => s3Client.send(new PutObjectCommand({ + Bucket: bucketName, + Key: hiddenKey, + Tagging: hiddenTagData, + }))) + .then(() => done()) + .catch(done); + }); + + after(async () => { + await s3Client.send(new DeleteObjectsCommand({ + Bucket: bucketName, + Delete: { + Objects: [ + { Key: objectKey }, + { Key: hiddenKey }, + ], + }, + })); + await s3Client.send(new DeleteBucketCommand({ Bucket: bucketName })); }); it('should list object with searched for system metadata', done => { @@ -87,8 +96,13 @@ runIfMongo('Basic search', () => { describe('search when overwrite object', () => { before(done => { - s3Client.putObject({ Bucket: bucketName, Key: objectKey, - Metadata: updatedUserMetadata }, done); + s3Client.send(new PutObjectCommand({ + Bucket: bucketName, + Key: objectKey, + Metadata: updatedUserMetadata, + })) + .then(() => done()) + .catch(done); }); it('should list object with searched for updated user metadata', @@ -104,12 +118,17 @@ runIfMongo('Basic search', () => { runIfMongo('Search when no objects in bucket', () => { const bucketName = `noobjectbucket${Date.now()}`; + before(done => { - s3Client.createBucket({ Bucket: bucketName }, done); + s3Client.send(new CreateBucketCommand({ Bucket: bucketName })) + .then(() => done()) + .catch(done); }); after(done => { - s3Client.deleteBucket({ Bucket: bucketName }, done); + s3Client.send(new DeleteBucketCommand({ Bucket: bucketName })) + .then(() => done()) + .catch(done); }); it('should return empty listing when no objects in bucket', done => { @@ -121,12 +140,17 @@ runIfMongo('Search when no objects in bucket', () => { runIfMongo('Invalid regular expression searches', () => { const bucketName = `badregex-${Date.now()}`; + before(done => { - s3Client.createBucket({ Bucket: bucketName }, done); + s3Client.send(new CreateBucketCommand({ Bucket: bucketName })) + .then(() => done()) + .catch(done); }); after(done => { - s3Client.deleteBucket({ Bucket: bucketName }, done); + s3Client.send(new DeleteBucketCommand({ Bucket: bucketName })) + .then(() => done()) + .catch(done); }); it('should return error if pattern is invalid', done => { diff --git a/tests/functional/aws-node-sdk/test/mdSearch/utils/helpers.js b/tests/functional/aws-node-sdk/test/mdSearch/utils/helpers.js index 0afdd361fa..39bb29161a 100644 --- a/tests/functional/aws-node-sdk/test/mdSearch/utils/helpers.js +++ b/tests/functional/aws-node-sdk/test/mdSearch/utils/helpers.js @@ -1,17 +1,27 @@ const assert = require('assert'); const async = require('async'); +const { + ListObjectsCommand, + ListObjectVersionsCommand, + DeleteObjectsCommand, +} = require('@aws-sdk/client-s3'); function _deleteVersionList(s3Client, versionList, bucket, callback) { if (versionList === undefined || versionList.length === 0) { return callback(); } - const params = { Bucket: bucket, Delete: { Objects: [] } }; - versionList.forEach(version => { - params.Delete.Objects.push({ - Key: version.Key, VersionId: version.VersionId }); - }); - - return s3Client.deleteObjects(params, callback); + const params = { + Bucket: bucket, + Delete: { + Objects: versionList.map(version => ({ + Key: version.Key, + VersionId: version.VersionId, + })), + }, + }; + return s3Client.send(new DeleteObjectsCommand(params)) + .then(() => callback()) + .catch(callback); } const testUtils = {}; @@ -21,62 +31,94 @@ testUtils.runIfMongo = process.env.S3METADATA === 'mongodb' ? testUtils.runAndCheckSearch = (s3Client, bucketName, encodedSearch, listVersions, testResult, done) => { - let searchRequest; - if (listVersions) { - searchRequest = s3Client.listObjectVersions({ Bucket: bucketName }); - searchRequest.on('build', () => { - searchRequest.httpRequest.path = - `/${bucketName}?search=${encodedSearch}&&versions`; - }); - searchRequest.on('success', res => { - if (testResult) { - assert.notStrictEqual(res.data.Versions[0].VersionId, undefined); - if (Array.isArray(testResult)) { - assert.strictEqual(res.data.Versions.length, testResult.length); - async.forEachOf(testResult, (expected, i, next) => { - assert.strictEqual(res.data.Versions[i].Key, expected); - next(); - }); + const makeRequest = async () => { + try { + const input = { + Bucket: bucketName, + }; + + let command; + if (listVersions) { + command = new ListObjectVersionsCommand(input); + } else { + command = new ListObjectsCommand(input); + } + + // Add middleware to inject the search query parameter + // SDK v3 automatically encodes query parameters, so we decode first to avoid double-encoding + command.middlewareStack.add( + next => async args => { + if (!args.request.query) { + // eslint-disable-next-line no-param-reassign + args.request.query = {}; + } + // Decode the already-encoded search string since SDK v3 will encode it again + // eslint-disable-next-line no-param-reassign + args.request.query.search = decodeURIComponent(encodedSearch); + if (listVersions) { + // eslint-disable-next-line no-param-reassign + args.request.query.versions = ''; + } + + return next(args); + }, + { + step: 'build', + name: 'addSearchQuery', + } + ); + + const res = await s3Client.send(command); + + if (listVersions) { + if (testResult) { + assert.notStrictEqual(res.Versions[0].VersionId, undefined); + if (Array.isArray(testResult)) { + assert.strictEqual(res.Versions.length, testResult.length); + async.forEachOf(testResult, (expected, i, next) => { + assert.strictEqual(res.Versions[i].Key, expected); + next(); + }, done); + return; + } else { + assert(res.Versions[0], 'should be Contents listed'); + assert.strictEqual(res.Versions[0].Key, testResult); + assert.strictEqual(res.Versions.length, 1); + } } else { - assert(res.data.Versions[0], 'should be Contents listed'); - assert.strictEqual(res.data.Versions[0].Key, testResult); - assert.strictEqual(res.data.Versions.length, 1); + assert.strictEqual(res.Versions.length, 0); } } else { - assert.strictEqual(res.data.Versions.length, 0); + if (testResult && typeof testResult === 'object' && testResult.code) { + // This was expected to be an error, but we got success + done(new Error('Expected error but got success')); + } + if (testResult) { + assert(res.Contents[0], 'should be Contents listed'); + assert.strictEqual(res.Contents[0].Key, testResult); + assert.strictEqual(res.Contents.length, 1); + } else { + assert.strictEqual(res.Contents?.length, undefined); + } } - return done(); - }); - } else { - searchRequest = s3Client.listObjects({ Bucket: bucketName }); - searchRequest.on('build', () => { - searchRequest.httpRequest.path = - `/${bucketName}?search=${encodedSearch}`; - }); - searchRequest.on('success', res => { - if (testResult) { - assert(res.data.Contents[0], 'should be Contents listed'); - assert.strictEqual(res.data.Contents[0].Key, testResult); - assert.strictEqual(res.data.Contents.length, 1); - } else { - assert.strictEqual(res.data.Contents.length, 0); + done(); + } catch (err) { + if (testResult && typeof testResult === 'object' && testResult.code) { + assert.strictEqual(err.name, testResult.code); + assert.strictEqual(err.message, testResult.message); + done(); } - return done(); - }); - } - searchRequest.on('error', err => { - if (testResult) { - assert.strictEqual(err.code, testResult.code); - assert.strictEqual(err.message, testResult.message); + done(err); } - return done(); - }); - searchRequest.send(); + }; + makeRequest(); }; testUtils.removeAllVersions = (s3Client, bucket, callback) => { async.waterfall([ - cb => s3Client.listObjectVersions({ Bucket: bucket }, cb), + cb => s3Client.send(new ListObjectVersionsCommand({ Bucket: bucket })) + .then(data => cb(null, data)) + .catch(cb), (data, cb) => _deleteVersionList(s3Client, data.DeleteMarkers, bucket, err => cb(err, data)), (data, cb) => _deleteVersionList(s3Client, data.Versions, bucket, @@ -88,7 +130,7 @@ testUtils.removeAllVersions = (s3Client, bucket, callback) => { KeyMarker: data.NextKeyMarker, VersionIdMarker: data.NextVersionIdMarker, }; - return this.removeAllVersions(params, cb); + return testUtils.removeAllVersions(s3Client, params, cb); } return cb(); }, diff --git a/tests/functional/aws-node-sdk/test/mdSearch/utils/s3SDK.js b/tests/functional/aws-node-sdk/test/mdSearch/utils/s3SDK.js index ec2e234797..a0b52a0cc9 100644 --- a/tests/functional/aws-node-sdk/test/mdSearch/utils/s3SDK.js +++ b/tests/functional/aws-node-sdk/test/mdSearch/utils/s3SDK.js @@ -1,17 +1,4 @@ -const S3 = require('aws-sdk').S3; +const { S3Client } = require('@aws-sdk/client-s3'); +const getConfig = require('../../support/config'); -const config = { - sslEnabled: false, - endpoint: 'http://127.0.0.1:8000', - apiVersions: { s3: '2006-03-01' }, - signatureCache: false, - signatureVersion: 'v4', - region: 'us-east-1', - s3ForcePathStyle: true, - accessKeyId: 'accessKey1', - secretAccessKey: 'verySecretKey1', -}; - -const client = new S3(config); - -module.exports = client; +module.exports = new S3Client(getConfig('default')); diff --git a/tests/functional/aws-node-sdk/test/mdSearch/versionEnabledSearch.js b/tests/functional/aws-node-sdk/test/mdSearch/versionEnabledSearch.js index 82381abf08..904f3b5696 100644 --- a/tests/functional/aws-node-sdk/test/mdSearch/versionEnabledSearch.js +++ b/tests/functional/aws-node-sdk/test/mdSearch/versionEnabledSearch.js @@ -1,7 +1,14 @@ +const { + CreateBucketCommand, + PutBucketVersioningCommand, + PutObjectCommand, + DeleteBucketCommand, +} = require('@aws-sdk/client-s3'); +const { promisify } = require('util'); const s3Client = require('./utils/s3SDK'); const { runAndCheckSearch, removeAllVersions, runIfMongo } = require('./utils/helpers'); - +const removeAllVersionsPromise = promisify(removeAllVersions); const userMetadata = { food: 'pizza' }; const updatedMetadata = { food: 'pineapple' }; const masterKey = 'master'; @@ -12,56 +19,49 @@ runIfMongo('Search in version enabled bucket', () => { MFADelete: 'Disabled', Status: 'Enabled', }; - before(done => { - s3Client.createBucket({ Bucket: bucketName }, err => { - if (err) { - return done(err); - } - return s3Client.putBucketVersioning({ Bucket: bucketName, - VersioningConfiguration }, err => { - if (err) { - return done(err); - } - return s3Client.putObject({ Bucket: bucketName, - Key: masterKey, Metadata: userMetadata }, done); - }); - }); + before(async () => { + await s3Client.send(new CreateBucketCommand({ Bucket: bucketName })); + await s3Client.send(new PutBucketVersioningCommand({ + Bucket: bucketName, + VersioningConfiguration + })); + await s3Client.send(new PutObjectCommand({ + Bucket: bucketName, + Key: masterKey, + Metadata: userMetadata + })); }); - after(done => { - removeAllVersions(s3Client, bucketName, - err => { - if (err) { - return done(err); - } - return s3Client.deleteBucket({ Bucket: bucketName }, done); - }); + after(async () => { + await removeAllVersionsPromise(s3Client, bucketName); + await s3Client.send(new DeleteBucketCommand({ Bucket: bucketName })); }); it('should list just master object with searched for metadata by default', done => { const encodedSearch = encodeURIComponent(`x-amz-meta-food="${userMetadata.food}"`); - return runAndCheckSearch(s3Client, bucketName, - encodedSearch, false, masterKey, done); + runAndCheckSearch(s3Client, bucketName, encodedSearch, false, masterKey, done); }); describe('New version overwrite', () => { - before(done => { - s3Client.putObject({ Bucket: bucketName, - Key: masterKey, Metadata: updatedMetadata }, done); + before(async () => { + await s3Client.send(new PutObjectCommand({ + Bucket: bucketName, + Key: masterKey, + Metadata: updatedMetadata + })); }); it('should list just master object with updated metadata by default', done => { const encodedSearch = encodeURIComponent(`x-amz-meta-food="${updatedMetadata.food}"`); - return runAndCheckSearch(s3Client, bucketName, - encodedSearch, false, masterKey, done); + runAndCheckSearch(s3Client, bucketName, encodedSearch, false, masterKey, done); }); it('should list all object versions that met search query while specifying versions param', done => { const encodedSearch = encodeURIComponent('x-amz-meta-food LIKE "pi.*"'); - return runAndCheckSearch(s3Client, bucketName, + runAndCheckSearch(s3Client, bucketName, encodedSearch, true, [masterKey, masterKey], done); }); });