Skip to content
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

feat: Support kmsKeyArn for deploy function #8697

Merged

Conversation

ifitzsimmons
Copy link
Contributor

Closes: #8692: provider.kmsKeyArn and functions[].kmsKeyArn are not supported with single function deployment}

@codecov
Copy link

codecov bot commented Dec 31, 2020

Codecov Report

Merging #8697 (88a85e9) into master (dc9f180) will decrease coverage by 0.02%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #8697      +/-   ##
==========================================
- Coverage   87.73%   87.70%   -0.03%     
==========================================
  Files         264      264              
  Lines        9851     9852       +1     
==========================================
- Hits         8643     8641       -2     
- Misses       1208     1211       +3     
Impacted Files Coverage Δ
lib/plugins/aws/deployFunction.js 95.53% <100.00%> (+0.67%) ⬆️
lib/Serverless.js 92.24% <0.00%> (-3.11%) ⬇️
lib/utils/createFromTemplate.js 84.84% <0.00%> (-2.00%) ⬇️
lib/plugins/interactiveCli/initializeService.js 100.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dc9f180...88a85e9. Read the comment docs.

Copy link
Contributor

@pgrzesik pgrzesik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @ifitzsimmons, thanks for submitting your PR 🙇 There are a few remarks that I believe should be addressed before finalizing this PR, if anything is not clear please let me know 💯

kmsKeyArn = !kmsKeyArn ? functionObj.awsKmsKeyArn : kmsKeyArn;

this.serverless._logDeprecation(
'FUNCTION_DEPRECATED_PROPERTY_AWS_KMS_KEY_ARN',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we should use AWS_KMS_KEY_ARN code so it constructs a proper link to deprecation documentation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could also stick to the exact same deprecation message as we have during sls deploy: Starting with next major version, "awsKmsKeyArn" function property will be replaced by "kmsKeyArn"

kmsKeyArn = !kmsKeyArn ? serviceObj.awsKmsKeyArn : kmsKeyArn;

this.serverless._logDeprecation(
'SERVICE_DEPRECATED_PROPERTY_AWS_KMS_KEY_ARN',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we should use AWS_KMS_KEY_ARN code so it constructs a proper link to deprecation documentation

} else if (serviceObj && 'awsKmsKeyArn' in serviceObj && !_.isObject(serviceObj.awsKmsKeyArn)) {
params.KMSKeyArn = serviceObj.awsKmsKeyArn;
let kmsKeyArn = functionObj.kmsKeyArn || providerObj.kmsKeyArn;
if (functionObj.awsKmsKeyArn) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is your opinion on moving the deprecation checks to deploy:function:initialize hook? We use similar approach in https://github.com/serverless/serverless/blob/master/lib/plugins/aws/package/compile/functions.js#L33-L63 which I believe helps with readability and nicely separates deprecation checks with the actual logic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good. A couple of questions:

Can I modify the if checks?

- if (_.get(this.serverless.service.serviceObject, 'awsKmsKeyArn'))
+ if (this.serverless.service.serviceObject.awsKmsKeyArn)
 
- if (Object.values(this.serverless.service.functions).some(({ awsKmsKeyArn }) => awsKmsKeyArn))
+ if (this.options.functionObj.awsKmsKeyArn)

Will the awsKmsKeyArn property ever exist on anything other than the functionObj? If so, I understand the use of the .some() method. Otherwise, we can probably just check functionObj for that property directly. I guess unless functionObj is not guaranteed to exist. Also, why is that function checking the serverless.service.functions object? It looks like the deployFunction class has a functions object on the class's options attribute.

And then just a general question -- when does the hook run?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for when do hooks run - they're invoked as a part of deploy command, you can see the logic here:

function: {

As for checks:

  • the use of some is there due to the fact that in functions.js we're considering all functions - here it will be enough if we check only on the one that is considered for deploy
  • the check for awsKmsKeyArn on serviceObject - here I'm not 100% if there's a use case where where the serviceObject could be empty (I'm not aware of it), but for now I would stick to _.get use - we have a separate issue where we migrate lodash use and we would be able to address it at a later point in time

awsDeployFunction.options = options;

await awsDeployFunction.updateFunctionConfiguration();

expect(normalizeArnRoleStub.calledOnce).to.be.equal(true);
expect(normalizeArnRoleStub.calledWithExactly('arn:aws:iam::123456789012:role/Admin'));
expect(updateFunctionConfigurationStub.calledOnce).to.be.equal(true);
expect(
updateFunctionConfigurationStub.calledWithExactly('Lambda', 'updateFunctionConfiguration', {
sinon.assert.calledWith(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could skip these assertions on deprecations - we usually don't do them and it's also expanding a test that is written in "old-way"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that we still have that test expanded, is there a reason for that?

@@ -421,6 +430,218 @@ describe('AwsDeployFunction', () => {
})
).to.be.equal(true);
});

describe('#KMSKeyArn should be set by "kmsKeyArn" or "awsKmsKeyArn"', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if all newly introduced tests will be configured with runServerless util as described: https://github.com/serverless/serverless/blob/master/test/README.md#unit-tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been going through the documentation for a little while now and I'm a little embarrassed but I just don't get it. Do you think you could provide me an example for one of these tests and I can take that and run with it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries 🙌 You can find some examples here: https://github.com/serverless/serverless/blob/master/test/unit/lib/plugins/aws/package/compile/functions.test.js#L1444

The general idea behind runServerless is to test outputs/results of certain functionalities instead of testing internal implementation, as it often makes it harder to refactor at later point in time. In case of deployFunction use of runServerless might be a bit tricky, as you'll most likely have to mock AWS calls. You can see an example of how single function deploy can be tested with runServerless - https://github.com/serverless/serverless/pull/8315/files

Please let me know if I can help more here 💯

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move them to a top-level describe block in this test file as is suggested in https://github.com/serverless/serverless/blob/master/test/README.md#unit-tests

You might also want to rebase on top of master, because I believe we gained a few tests that rely on runServerless in this module in the meantime

@ifitzsimmons
Copy link
Contributor Author

@pgrzesik Are you waiting on me for anything regarding this PR?

Copy link
Contributor

@pgrzesik pgrzesik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @ifitzsimmons and sorry about the delay - I explained the reasons in another PR, please request for re-review after submitting changes and I'll make sure to review as soon as possible. Overall it looks good, I only have a few minor comments, please let me know what do you think 🙇

awsDeployFunction.options = options;

await awsDeployFunction.updateFunctionConfiguration();

expect(normalizeArnRoleStub.calledOnce).to.be.equal(true);
expect(normalizeArnRoleStub.calledWithExactly('arn:aws:iam::123456789012:role/Admin'));
expect(updateFunctionConfigurationStub.calledOnce).to.be.equal(true);
expect(
updateFunctionConfigurationStub.calledWithExactly('Lambda', 'updateFunctionConfiguration', {
sinon.assert.calledWith(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that we still have that test expanded, is there a reason for that?

@@ -421,6 +430,218 @@ describe('AwsDeployFunction', () => {
})
).to.be.equal(true);
});

describe('#KMSKeyArn should be set by "kmsKeyArn" or "awsKmsKeyArn"', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move them to a top-level describe block in this test file as is suggested in https://github.com/serverless/serverless/blob/master/test/README.md#unit-tests

You might also want to rebase on top of master, because I believe we gained a few tests that rely on runServerless in this module in the meantime

},
},
provider: {
vpc: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these extra vpc, environment, memorySize and timeout variables needed here? I think if not, let's leave them out as they're not important in this particular test case

Copy link
Contributor

@pgrzesik pgrzesik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good, unfortunatelly there's a conflicting file that should be resolved before merging + I added a minor suggestion for simplification.
Thanks for being patient and sorry for so many conflicts along the way 😬

params.KMSKeyArn = functionObj.awsKmsKeyArn;
} else if (serviceObj && 'awsKmsKeyArn' in serviceObj && !_.isObject(serviceObj.awsKmsKeyArn)) {
params.KMSKeyArn = serviceObj.awsKmsKeyArn;
let kmsKeyArn = functionObj.kmsKeyArn || providerObj.kmsKeyArn;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be simplified even further with `kmsKeyArn = functionObj.kmsKeyArn || providerObjkmsKeyArn || functionObj.awsKmsKeyArn || serviceObj.awsKmsKeyArn;

Copy link
Contributor

@pgrzesik pgrzesik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing and we're be ready to merge, thank you @ifitzsimmons

@@ -183,6 +184,138 @@ describe('AwsDeployFunction', () => {
});
});

describe('#KMSKeyArn should be set by "kmsKeyArn" or "awsKmsKeyArn"', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing - let's move that describe into describe from https://github.com/serverless/serverless/pull/8697/files#diff-79623f798e186957caf38cdf7b770ba812c6a8bf7034dc4cb39abb234974e0aeR445 - we try to keep all runServerless based tests separately from the ones written the old way

`function[]` objects for single function deployment
Copy link
Contributor

@pgrzesik pgrzesik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ifitzsimmons - I believe schema needs to be cleaned up a little bit and we are ready to merge 👍

@@ -419,6 +419,10 @@ class AwsProvider {
],
},
},
awsKmsArn: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it a duplicate of definiton from lib/configSchema.js?

@@ -619,6 +623,7 @@ class AwsProvider {
},
additionalProperties: false,
},
awsKmsKeyArn: { $ref: '#/definitions/awsKmsArn' },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to add this? I think it's invalid property on provider and we already have kmsKeyArn defined for provider as available

Copy link
Contributor

@pgrzesik pgrzesik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your patience, well done 🙇

@pgrzesik pgrzesik changed the title #8692: Add kmsKeyArn property to provider and function[] objects for single function deployment feat: Support kmsKeyArn for deploy function Jan 24, 2021
@pgrzesik pgrzesik merged commit 8a92be9 into serverless:master Jan 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants