-
Notifications
You must be signed in to change notification settings - Fork 249
Improvement/cldsrv 724 sur utapi tests #5950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development/9.1
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,139 +1,146 @@ | ||||||||||||
const AWS = require('aws-sdk'); | ||||||||||||
AWS.config.logger = console; | ||||||||||||
const { S3 } = require('aws-sdk'); | ||||||||||||
const { | ||||||||||||
S3Client, | ||||||||||||
HeadBucketCommand, | ||||||||||||
CreateBucketCommand, | ||||||||||||
DeleteBucketCommand, | ||||||||||||
ListObjectVersionsCommand, | ||||||||||||
DeleteObjectCommand, | ||||||||||||
ListBucketsCommand, | ||||||||||||
} = require('@aws-sdk/client-s3'); | ||||||||||||
const projectFixture = require('../fixtures/project'); | ||||||||||||
const getConfig = require('../../test/support/config'); | ||||||||||||
|
||||||||||||
class BucketUtility { | ||||||||||||
constructor(profile = 'default', config = {}) { | ||||||||||||
constructor(profile = 'default', config = {}, unauthenticated = false) { | ||||||||||||
const s3Config = getConfig(profile, config); | ||||||||||||
|
||||||||||||
this.s3 = new S3(s3Config); | ||||||||||||
this.s3.config.setPromisesDependency(Promise); | ||||||||||||
this.s3.config.update({ | ||||||||||||
maxRetries: 0, | ||||||||||||
}); | ||||||||||||
if (unauthenticated) { | ||||||||||||
this.s3 = new S3Client({ | ||||||||||||
...s3Config, | ||||||||||||
credentials: { accessKeyId: '', secretAccessKey: '' }, | ||||||||||||
forcePathStyle: true, | ||||||||||||
signer: { sign: async request => request }, | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
else { | ||||||||||||
this.s3 = new S3Client({ | ||||||||||||
...s3Config, | ||||||||||||
maxAttempts: 0, | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
bucketExists(bucketName) { | ||||||||||||
return this.s3 | ||||||||||||
.headBucket({ Bucket: bucketName }).promise() | ||||||||||||
return this.s3.send(new HeadBucketCommand({ Bucket: bucketName })) | ||||||||||||
.then(() => true) | ||||||||||||
.catch(err => { | ||||||||||||
if (err.code === 'NotFound') { | ||||||||||||
if (err.name === 'NotFound') { | ||||||||||||
return false; | ||||||||||||
} | ||||||||||||
throw err; | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
|
||||||||||||
createOne(bucketName) { | ||||||||||||
return this.s3 | ||||||||||||
.createBucket({ Bucket: bucketName }).promise() | ||||||||||||
.then(() => bucketName); | ||||||||||||
return this.s3.send(new CreateBucketCommand({ Bucket: bucketName })) | ||||||||||||
.then(() => bucketName) | ||||||||||||
.catch(err => { | ||||||||||||
throw err; | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
|
||||||||||||
createOneWithLock(bucketName) { | ||||||||||||
return this.s3.createBucket({ | ||||||||||||
return this.s3.send(new CreateBucketCommand({ | ||||||||||||
Bucket: bucketName, | ||||||||||||
ObjectLockEnabledForBucket: true, | ||||||||||||
}).promise() | ||||||||||||
.then(() => bucketName); | ||||||||||||
})) | ||||||||||||
.then(() => bucketName) | ||||||||||||
.catch(err => { | ||||||||||||
throw err; | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
|
||||||||||||
createMany(bucketNames) { | ||||||||||||
const promises = bucketNames.map( | ||||||||||||
bucketName => this.createOne(bucketName) | ||||||||||||
); | ||||||||||||
|
||||||||||||
return Promise.all(promises); | ||||||||||||
} | ||||||||||||
|
||||||||||||
createRandom(nBuckets = 1) { | ||||||||||||
if (nBuckets === 1) { | ||||||||||||
const bucketName = projectFixture.generateBucketName(); | ||||||||||||
|
||||||||||||
return this.createOne(bucketName); | ||||||||||||
} | ||||||||||||
|
||||||||||||
const bucketNames = projectFixture | ||||||||||||
.generateManyBucketNames(nBuckets) | ||||||||||||
.sort(() => 0.5 - Math.random()); // Simply shuffle array | ||||||||||||
|
||||||||||||
.sort(() => 0.5 - Math.random()); | ||||||||||||
return this.createMany(bucketNames); | ||||||||||||
} | ||||||||||||
|
||||||||||||
deleteOne(bucketName) { | ||||||||||||
return this.s3 | ||||||||||||
.deleteBucket({ Bucket: bucketName }).promise(); | ||||||||||||
return this.s3.send(new DeleteBucketCommand({ Bucket: bucketName })) | ||||||||||||
.catch(err => { | ||||||||||||
throw err; | ||||||||||||
}); | ||||||||||||
Comment on lines
+80
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
One good practice when working with async/await is to always await with return, this will help to preserve the full stack trace (without the await, the stack trace will start at the caller, if you put the await here, the stack trace will display |
||||||||||||
} | ||||||||||||
|
||||||||||||
deleteMany(bucketNames) { | ||||||||||||
const promises = bucketNames.map( | ||||||||||||
bucketName => this.deleteOne(bucketName) | ||||||||||||
); | ||||||||||||
|
||||||||||||
return Promise.all(promises); | ||||||||||||
} | ||||||||||||
|
||||||||||||
/** | ||||||||||||
* Recursively delete all versions of all objects within the bucket | ||||||||||||
* @param bucketName | ||||||||||||
* @returns {Promise.<T>} | ||||||||||||
*/ | ||||||||||||
|
||||||||||||
empty(bucketName) { | ||||||||||||
const param = { | ||||||||||||
Bucket: bucketName, | ||||||||||||
}; | ||||||||||||
|
||||||||||||
return this.s3 | ||||||||||||
.listObjectVersions(param).promise() | ||||||||||||
.then(data => | ||||||||||||
Promise.all( | ||||||||||||
data.Versions | ||||||||||||
.filter(object => !object.Key.endsWith('/')) | ||||||||||||
// remove all objects | ||||||||||||
return this.s3.send(new ListObjectVersionsCommand(param)) | ||||||||||||
.then(data => Promise.all( | ||||||||||||
(data.Versions || []) | ||||||||||||
.filter(object => !object.Key.endsWith('/')) | ||||||||||||
.map(object => | ||||||||||||
this.s3.send(new DeleteObjectCommand({ | ||||||||||||
Bucket: bucketName, | ||||||||||||
Key: object.Key, | ||||||||||||
VersionId: object.VersionId, | ||||||||||||
})) | ||||||||||||
.then(() => object) | ||||||||||||
) | ||||||||||||
.concat((data.Versions || []) | ||||||||||||
.filter(object => object.Key.endsWith('/')) | ||||||||||||
.map(object => | ||||||||||||
this.s3.deleteObject({ | ||||||||||||
Bucket: bucketName, | ||||||||||||
Key: object.Key, | ||||||||||||
VersionId: object.VersionId, | ||||||||||||
}).promise() | ||||||||||||
.then(() => object) | ||||||||||||
) | ||||||||||||
.concat(data.Versions | ||||||||||||
.filter(object => object.Key.endsWith('/')) | ||||||||||||
// remove all directories | ||||||||||||
.map(object => | ||||||||||||
this.s3.deleteObject({ | ||||||||||||
Bucket: bucketName, | ||||||||||||
Key: object.Key, | ||||||||||||
VersionId: object.VersionId, | ||||||||||||
}).promise() | ||||||||||||
this.s3.send(new DeleteObjectCommand({ | ||||||||||||
Bucket: bucketName, | ||||||||||||
Key: object.Key, | ||||||||||||
VersionId: object.VersionId, | ||||||||||||
})) | ||||||||||||
.then(() => object) | ||||||||||||
) | ||||||||||||
) | ||||||||||||
.concat(data.DeleteMarkers | ||||||||||||
.map(object => | ||||||||||||
this.s3.deleteObject({ | ||||||||||||
Bucket: bucketName, | ||||||||||||
Key: object.Key, | ||||||||||||
VersionId: object.VersionId, | ||||||||||||
}).promise() | ||||||||||||
.then(() => object))) | ||||||||||||
) | ||||||||||||
); | ||||||||||||
) | ||||||||||||
.concat((data.DeleteMarkers || []) | ||||||||||||
.map(object => | ||||||||||||
this.s3.send(new DeleteObjectCommand({ | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This indent is weird ? |
||||||||||||
Bucket: bucketName, | ||||||||||||
Key: object.Key, | ||||||||||||
VersionId: object.VersionId, | ||||||||||||
})) | ||||||||||||
.then(() => object) | ||||||||||||
)) | ||||||||||||
)); | ||||||||||||
} | ||||||||||||
|
||||||||||||
emptyMany(bucketNames) { | ||||||||||||
const promises = bucketNames.map( | ||||||||||||
bucketName => this.empty(bucketName) | ||||||||||||
const promises = bucketNames.map( | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indent issue ? |
||||||||||||
bucketName => this.empty(bucketName) | ||||||||||||
); | ||||||||||||
|
||||||||||||
return Promise.all(promises); | ||||||||||||
} | ||||||||||||
|
||||||||||||
emptyIfExists(bucketName) { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think our guidelines ask us to add a new line between function definition ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch missed it here |
||||||||||||
return this.bucketExists(bucketName) | ||||||||||||
.then(exists => { | ||||||||||||
|
@@ -143,19 +150,19 @@ class BucketUtility { | |||||||||||
return undefined; | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
|
||||||||||||
emptyManyIfExists(bucketNames) { | ||||||||||||
const promises = bucketNames.map( | ||||||||||||
bucketName => this.emptyIfExists(bucketName) | ||||||||||||
); | ||||||||||||
|
||||||||||||
return Promise.all(promises); | ||||||||||||
} | ||||||||||||
|
||||||||||||
getOwner() { | ||||||||||||
return this.s3 | ||||||||||||
.listBuckets().promise() | ||||||||||||
.then(data => data.Owner); | ||||||||||||
return this.s3.send(new ListBucketsCommand({})) | ||||||||||||
.then(data => data.Owner) | ||||||||||||
.catch(err => { | ||||||||||||
throw err; | ||||||||||||
}); | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
const https = require('https'); | ||
const AWS = require('aws-sdk'); | ||
const http = require('http'); | ||
const { NodeHttpHandler } = require('@smithy/node-http-handler'); | ||
|
||
const { getCredentials } = require('./credentials'); | ||
const { getAwsCredentials } = require('./awsConfig'); | ||
|
@@ -19,19 +20,45 @@ if (ssl && ssl.ca) { | |
|
||
const DEFAULT_GLOBAL_OPTIONS = { | ||
httpOptions, | ||
apiVersions: { s3: '2006-03-01' }, | ||
signatureCache: false, | ||
sslEnabled: ssl !== undefined, | ||
}; | ||
|
||
const DEFAULT_MEM_OPTIONS = { | ||
endpoint: `${transport}://127.0.0.1:8000`, | ||
s3ForcePathStyle: true, | ||
port: 8000, | ||
forcePathStyle: true, | ||
region: 'us-east-1', | ||
maxAttempts: 3, | ||
requestHandler: new NodeHttpHandler({ | ||
connectionTimeout: 5000, | ||
socketTimeout: 5000, | ||
httpAgent: new (ssl ? https : http).Agent({ | ||
maxSockets: 200, | ||
keepAlive: true, | ||
keepAliveMsecs: 1000, | ||
}), | ||
}), | ||
}; | ||
|
||
const DEFAULT_AWS_OPTIONS = { | ||
region: 'us-east-1', | ||
maxAttempts: 3, | ||
requestHandler: new NodeHttpHandler({ | ||
connectionTimeout: 5000, | ||
socketTimeout: 5000, | ||
httpAgent: new https.Agent({ | ||
maxSockets: 200, | ||
keepAlive: true, | ||
keepAliveMsecs: 1000, | ||
}), | ||
}), | ||
}; | ||
const DEFAULT_AWS_OPTIONS = {}; | ||
|
||
function _getMemCredentials(profile) { | ||
const { accessKeyId, secretAccessKey } = getCredentials(profile); | ||
return new AWS.Credentials(accessKeyId, secretAccessKey); | ||
return { | ||
accessKeyId, | ||
secretAccessKey, | ||
}; | ||
} | ||
|
||
function _getMemConfig(profile, config) { | ||
|
@@ -58,11 +85,11 @@ function _getAwsConfig(profile, config) { | |
return awsConfig; | ||
} | ||
|
||
function getConfig(profile = 'default', config = {}) { | ||
const fn = process.env.AWS_ON_AIR && process.env.AWS_ON_AIR === 'true' | ||
? _getAwsConfig : _getMemConfig; | ||
|
||
return fn.apply(this, [profile, config]); | ||
function getConfig(profile, config) { | ||
if (process.env.AWS_ON_AIR) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure about that ? This one is essential There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually it's either set or not at all this is the check we have across the whole code base so I'd rather keep it |
||
return _getAwsConfig(profile, config); | ||
} | ||
return _getMemConfig(profile, config); | ||
} | ||
|
||
module.exports = getConfig; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure that
maxAttempts: 0,
is working also for unauthenticated client ?