-
Notifications
You must be signed in to change notification settings - Fork 20
AWS-SDK Migration #2482
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/8.3
Are you sure you want to change the base?
AWS-SDK Migration #2482
Conversation
Hello benzekrimaha,My role is to assist you with the merge of this Available options
Available commands
Status report is not available. |
ad7e01e to
2f3ed00
Compare
Waiting for approvalThe following approvals are needed before I can proceed with the merge:
|
f8e5940 to
942aa25
Compare
942aa25 to
f9f96ce
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## development/8.3 #2482 +/- ##
===================================================
- Coverage 71.35% 70.54% -0.82%
===================================================
Files 221 219 -2
Lines 17817 17919 +102
Branches 3712 3724 +12
===================================================
- Hits 12714 12641 -73
- Misses 5099 5273 +174
- Partials 4 5 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Wait, you say you've got two Jira ticket 514/524, but they both point to this same PR 🤔 |
| if (keyContext.isDeleteMarker) { | ||
| return this._client.deleteObject(params, putCb); | ||
| return this._client.send(new DeleteObjectCommand(params)).then(res => putCb(null, res)) | ||
| .catch(err => putCb(err)); |
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.
| .catch(err => putCb(err)); | |
| .catch(putCb); |
Can double check other occurrences in this file & elsewhere
| }; | ||
| return callback(null, response); | ||
| }).catch(err => { | ||
| if (err.code === 'NoSuchKey' || err.code === 'NotFound') { |
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.
I don't wanna leave the same comment on all occurence of this err.code vs err.name situation, but make sure this is ok. Because in the Zenko migration, I just checked and when I used getObjectCommand, i checked the err with err.name : https://github.com/scality/Zenko/blob/improvement/ZENKO-5054/tests/zenko_tests/node_tests/cloudserver/keyFormatVersion/tests/versionedBucket.js#L232
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.
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.
That's a limitation of the lack of TS support. Maybe we can have some quick wins here. ANyway there is two kind of errors today: errors coming from drivers/sdk that are usually native JS errors objects or enriched like in aws sdk. And there are the Arsenal errors that are not very standard, where the code would typically have the error string...
Maybe we can type partially at first this file, so we ensure we are working with the right types of errors, and don't miss anything?
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.
@benzekrimaha double checking after your changes :
I see you used xxxException, but I can't import them, instead I can import xxx without the 'Exception' as you can see for example in the screenshot : NoSuchKey exists, but NoSuchKeyException doesn't exists.
Not too sure if it's me who has a messed up IDE or something, but worth double checking
| }); | ||
| }); | ||
|
|
||
| it('should create a new master encryption key', done => { |
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.
Looks like a duplicate of the first test "should support default encryption key per account" 🤔
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.
Up, still here
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.
This completes Sylvain's review. I think I covered everything that makes sense given what should probably change, so I'll come back once it's adressed
| listObjects(params, callback) { | ||
| return this.send(new ListObjectsCommand(params)) | ||
| .then(data => callback && callback(null, data)) | ||
| .catch(err => callback && callback(err)); | ||
| } |
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.
It could make sense to switch this file to ts, but the callback should be required?
If no you can do that
| listObjects(params, callback) { | |
| return this.send(new ListObjectsCommand(params)) | |
| .then(data => callback && callback(null, data)) | |
| .catch(err => callback && callback(err)); | |
| } | |
| listObjects(params, callback) { | |
| return this.send(new ListObjectsCommand(params)) | |
| .then(data => callback?.(null, data)) | |
| .catch(err => callback?.(err)); | |
| } |
But better to always call it?
| }; | ||
| return callback(null, response); | ||
| }).catch(err => { | ||
| if (err.code === 'NoSuchKey' || err.code === 'NotFound') { |
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.
That's a limitation of the lack of TS support. Maybe we can have some quick wins here. ANyway there is two kind of errors today: errors coming from drivers/sdk that are usually native JS errors objects or enriched like in aws sdk. And there are the Arsenal errors that are not very standard, where the code would typically have the error string...
Maybe we can type partially at first this file, so we ensure we are working with the right types of errors, and don't miss anything?
| // Prefer ARN, but fall back to KeyId if ARN is missing | ||
| // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain | ||
| keyId = keyMetadata?.Arn ?? keyMetadata?.KeyId!; | ||
| keyId = keyMetadata?.Arn ?? (keyMetadata?.KeyId || ''); |
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.
I think this is important top keep the comment about double arn prefix just below.
This one:
// May produce double arn prefix: scality arn + aws arn
// arn:scality:kms:external:aws_kms:custom:key/arn:aws:kms:region:accountId:key/cbd69d33-ba8e-4b56-8cfe
// If this is a problem, a config flag should be used to hide the scality arn when returning the KMS KeyId
// or aws arn when creating the KMS Key
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.
(sill applicable)
| maxAttempts: 1, | ||
| requestHandler: undefined, // v3 handles agents differently | ||
| // v3 does not use signatureVersion or sslEnabled directly | ||
| // v3 does not use customUserAgent directly |
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.
Can we maybe point to where the logic now is? In the sdk, or elsewhere in the code, so we can know where to look later?
lib/network/kmsAWS/Client.ts
Outdated
| const params = { | ||
| KeyId: masterKeyId, | ||
| KeySpec: 'AES_256', | ||
| KeySpec: "AES_256" as const, |
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.
| KeySpec: "AES_256" as const, | |
| KeySpec: 'AES_256' as const, |
Or you can also create the variable as a const once and reuse it here
| /** | ||
| * List objects in a bucket. | ||
| * @param {object} params - S3 listObjects params | ||
| * @param {function} callback | ||
| */ | ||
| listObjects(params, callback) { |
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.
Can we maybe deprecate the callback approach, as we currently support both?
Also what is returned is actually not a function but a promise, so doing an await listObjects(...) here will work, even if we don't provide any callback.
Or, if we want to only support callback, better not to return the promise at all, to avoid mixed ways of calling this function?
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.
I think this is still relevant; a way to incrementally switch to async/await is to start enforcing this pattern. Caller can then "callbackify" temporarily if using promises is not possible, what do you think?
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.
mostly code style, so approving, could be nice to test if we can use S3ServiceException, it would allow better error handling logic I think
| const temp = justDataChunk instanceof Buffer | ||
| ? hash.update(justDataChunk) | ||
| : hash.update(justDataChunk, 'binary'); | ||
| const temp = hash.update(justDataChunk); |
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.
| const temp = hash.update(justDataChunk); | |
| const temp = justDataChunk instanceof Buffer | |
| ? hash.update(justDataChunk) | |
| : hash.update(justDataChunk, 'binary'); |
If we are sure this is a buffer, we should update the function from
justDataChunk?: Buffer | string,to
justDataChunk?: Buffer,| logger.info('AWS KMS: key does not exist or is already pending deletion', { masterKeyId, error: err }); | ||
| return cb(null); |
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.
If we return no error we want at least to have a warning log I think?
| logger.info('AWS KMS: key does not exist or is already pending deletion', { masterKeyId, error: err }); | |
| return cb(null); | |
| logger.warn('AWS KMS: key does not exist or is already pending deletion', { masterKeyId, error: err }); | |
| return cb(null); |
| const params = { | ||
| KeyId: masterKeyId, | ||
| KeySpec: 'AES_256', | ||
| KeySpec: 'AES_256' as const, |
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.
| KeySpec: 'AES_256' as const, | |
| KeySpec: 'AES_256', |
| const allowedKmsErrorCodes = Object.keys(allowedKmsErrors) as unknown as (keyof typeof allowedKmsErrors)[]; | ||
|
|
||
| // Local AWSError type for compatibility with v3 error handling | ||
| export type AWSError = Error & { |
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.
I'm pretty sure you can remove this and use the S3ServiceException type, this is exposed by the @aws-sdk/client-s3 module and all exceptions related to S3 are extending this base type, it has all the fields you have here, with the advantage of being typed & documented
| const uploadId = 'externalBackendTestUploadId'; | ||
| testClient.completeMPU(jsonList, null, key, | ||
| uploadId, bucketName, log, (err, res) => { | ||
| if (err) return done(err); |
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.
| if (err) return done(err); | |
| if (err) { | |
| return done(err); | |
| } |
| .then(data => callback && callback(null, data)) | ||
| .catch(err => callback?.(err)); |
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.
| .then(data => callback && callback(null, data)) | |
| .catch(err => callback?.(err)); | |
| .then(data => callback?.(null, data)) | |
| .catch(err => callback?.(err)); |
| /** | ||
| * List objects in a bucket. | ||
| * @param {object} params - S3 listObjects params | ||
| * @param {function} callback | ||
| */ | ||
| listObjects(params, callback) { |
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.
I think this is still relevant; a way to incrementally switch to async/await is to start enforcing this pattern. Caller can then "callbackify" temporarily if using promises is not possible, what do you think?
| const logger = { trace: () => {} }; | ||
| const stringToSign = constructStringToSignV2(fakeRequest, data, logger, 'GCP'); |
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.
up on this, just so we don't forget about the ticket
| }).then(() => { | ||
| return callback(); |
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.
| }).then(() => { | |
| return callback(); | |
| }).then(() => callback()); |
|
|
||
| listObjects(params, callback) { | ||
| return this.send(new ListObjectsCommand(params)) | ||
| .then(data => callback && callback(null, data)) |
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.
| .then(data => callback && callback(null, data)) | |
| .then(data => callback?.(null, data)) |
With the migration we can no longer use the serviceDefine property available with aws-sdk v2. This commit aims to extend the s3Client class to override the methods that are not compatible with GCP. Issue: ARSN-514
Bumps [@eslint/plugin-kit](https://github.com/eslint/rewrite/tree/HEAD/packages/plugin-kit) from 0.3.5 to 0.4.0. - [Release notes](https://github.com/eslint/rewrite/releases) - [Changelog](https://github.com/eslint/rewrite/blob/main/packages/plugin-kit/CHANGELOG.md) - [Commits](https://github.com/eslint/rewrite/commits/core-v0.4.0/packages/plugin-kit) --- updated-dependencies: - dependency-name: "@eslint/plugin-kit" dependency-version: 0.4.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
d61de14 to
30a9a72
Compare
|
|
||
| constructor(options: ClientOptions) { | ||
| this._supportsDefaultKeyPerAccount = true; | ||
| const { providerName, tls, ak, sk, region, endpoint, noAwsArn } = options.kmsAWS; |
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.
lint : nit

Issue: ARSN-514
Please note that a ticket has been creaed to add coverage not to make this PR more extended : https://scality.atlassian.net/browse/ARSN-524