Skip to content

Commit

Permalink
fix(cli): Lambda hotswap fails if environment contains tokens (aws#22099
Browse files Browse the repository at this point in the history
)

closes aws#22088 

We always need to use `evaluateCfnTemplate.evaluateCfnExpression` when a variable to be used in hotswap may contain tokens.

----

### All Submissions:

* [X] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)?
	* [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
tmokmss authored and madeline-k committed Oct 10, 2022
1 parent 9c2f779 commit ce13e30
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 4 deletions.
9 changes: 5 additions & 4 deletions packages/aws-cdk/lib/api/hotswap/lambda-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,10 @@ async function isLambdaFunctionCodeOnlyChange(
*/
const tagUpdates: { [tag: string]: string | TagDeletion } = {};
if (updatedProp?.isDifferent) {
updatedProp.newValue.forEach((tag: CfnDiffTagValue) => {
tagUpdates[tag.Key] = tag.Value;
const tasks = updatedProp.newValue.map(async (tag: CfnDiffTagValue) => {
tagUpdates[tag.Key] = await evaluateCfnTemplate.evaluateCfnExpression(tag.Value);
});
await Promise.all(tasks);

updatedProp.oldValue.forEach((tag: CfnDiffTagValue) => {
if (tagUpdates[tag.Key] === undefined) {
Expand All @@ -178,10 +179,10 @@ async function isLambdaFunctionCodeOnlyChange(
}
break;
case 'Description':
description = updatedProp.newValue;
description = await evaluateCfnTemplate.evaluateCfnExpression(updatedProp.newValue);
break;
case 'Environment':
environment = updatedProp.newValue;
environment = await evaluateCfnTemplate.evaluateCfnExpression(updatedProp.newValue);
break;
default:
return ChangeHotswapImpact.REQUIRES_FULL_DEPLOYMENT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -905,3 +905,127 @@ test('calls both updateLambdaCode() and updateLambdaConfiguration() API when it
S3Key: 'new-key',
});
});

test('Lambda hotswap works properly with changes of environment variables, description, tags with tokens', async () => {
// GIVEN
setup.setCurrentCfnStackTemplate({
Resources: {
EventBus: {
Type: 'AWS::Events::EventBus',
Properties: {
Name: 'my-event-bus',
},
},
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 's3-bucket',
S3Key: 's3-key',
},
FunctionName: 'my-function',
Environment: {
Variables: {
token: { 'Fn::GetAtt': ['EventBus', 'Arn'] },
literal: 'oldValue',
},
},
Description: {
'Fn::Join': ['', [
'oldValue',
{ 'Fn::GetAtt': ['EventBus', 'Arn'] },
]],
},
Tags: [
{
Key: 'token',
Value: { 'Fn::GetAtt': ['EventBus', 'Arn'] },
},
{
Key: 'literal',
Value: 'oldValue',
},
],
},
Metadata: {
'aws:asset:path': 'asset-path',
},
},
},
});

setup.pushStackResourceSummaries(
setup.stackSummaryOf('EventBus', 'AWS::Events::EventBus', 'my-event-bus'),
);

const cdkStackArtifact = setup.cdkStackArtifactOf({
template: {
Resources: {
EventBus: {
Type: 'AWS::Events::EventBus',
Properties: {
Name: 'my-event-bus',
},
},
Func: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: {
S3Bucket: 's3-bucket',
S3Key: 's3-key',
},
FunctionName: 'my-function',
Environment: {
Variables: {
token: { 'Fn::GetAtt': ['EventBus', 'Arn'] },
literal: 'newValue',
},
},
Description: {
'Fn::Join': ['', [
'newValue',
{ 'Fn::GetAtt': ['EventBus', 'Arn'] },
]],
},
Tags: [
{
Key: 'token',
Value: { 'Fn::GetAtt': ['EventBus', 'Arn'] },
},
{
Key: 'literal',
Value: 'newValue',
},
],
},
Metadata: {
'aws:asset:path': 'asset-path',
},
},
},
},
});

// WHEN
const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact);

// THEN
expect(deployStackResult).not.toBeUndefined();
expect(mockUpdateLambdaConfiguration).toHaveBeenCalledWith({
FunctionName: 'my-function',
Environment: {
Variables: {
token: 'arn:aws:events:here:123456789012:event-bus/my-event-bus',
literal: 'newValue',
},
},
Description: 'newValuearn:aws:events:here:123456789012:event-bus/my-event-bus',
});
expect(mockTagResource).toHaveBeenCalledWith({
Resource: 'arn:aws:lambda:here:123456789012:function:my-function',
Tags: {
token: 'arn:aws:events:here:123456789012:event-bus/my-event-bus',
literal: 'newValue',
},
});
});

0 comments on commit ce13e30

Please sign in to comment.