-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
(Lambda): Lambda environment variables that reference updated "parameters" are not updated when redeploying the stack #30101
Comments
I also deleted ALL env variables in one of my functions, using the console. Then I redeployed the stack, and verified my env variables were not added back. There were a bunch of other env variables there that are just gone. ![img] |
I had to invest around 1 hour to destroy and recreate my stack in order to have env variables updated ![img] |
Please, create a dedicated flag in cdk that "updates env variables only".
Look at this! 28min to deploy + the time to destroy the stack + the time I now have to invest to update the API url in some other stacks ![img] |
@AllanOricil Somehow I'm unable to reproduce the issue with CDK version import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as dotenv from 'dotenv';
export class TypescriptStack extends cdk.Stack {
private readonly allowedOrigins: cdk.CfnParameter;
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
dotenv.config();
console.log("ALLOWED_ORIGINS: " + this.getEnvVar("ALLOWED_ORIGINS"));
this.allowedOrigins = new cdk.CfnParameter(this, "allowedOrigins", {
type: "String",
noEcho: true,
default: this.getEnvVar("ALLOWED_ORIGINS")
});
const lambdaFunction = new lambda.Function(this, 'testLambda', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('lambda'),
handler: 'hello.handler',
environment: {
ALLOWED_ORIGINS: this.getEnvVar("ALLOWED_ORIGINS")
}
});
}
getEnvVar(envVarName: string): string {
return process.env.ALLOWED_ORIGINS ?? "";
}
} lambda\hello.js exports.handler = async function(event) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/plain" },
body: `Hello, CDK! You've hit ${event.path}\n`
};
}; .env (on 1st deploy)
.env (on 2nd deploy)
package.json {
"name": "typescript",
"version": "0.1.0",
"bin": {
"typescript": "bin/typescript.js"
},
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"test": "jest",
"cdk": "cdk"
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "20.12.7",
"aws-cdk": "2.140.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "~5.4.5"
},
"dependencies": {
"aws-cdk-lib": "2.140.0",
"constructs": "^10.0.0",
"dotenv": "^16.4.5",
"source-map-support": "^0.5.21"
}
} Executing
Executing Thanks, |
@ashishdhingra your lambda is not using the value from the parameter. It is using the env variable. Your rendered template must have a Ref pointing to the parameter. |
@AllanOricil Thanks for pointing it out. I modified the code to below and the issue is now reproducible: import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as dotenv from 'dotenv';
export class TypescriptStack extends cdk.Stack {
private readonly allowedOrigins: cdk.CfnParameter;
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
dotenv.config();
console.log("ALLOWED_ORIGINS: " + this.getEnvVar("ALLOWED_ORIGINS"));
this.allowedOrigins = new cdk.CfnParameter(this, "allowedOrigins", {
type: "String",
noEcho: true,
default: this.getEnvVar("ALLOWED_ORIGINS")
});
const lambdaFunction = new lambda.Function(this, 'testLambda', {
runtime: lambda.Runtime.NODEJS_20_X,
code: lambda.Code.fromAsset('lambda'),
handler: 'hello.handler',
environment: {
ALLOWED_ORIGINS: this.allowedOrigins.value.toString()
}
});
}
getEnvVar(envVarName: string): string {
return process.env.ALLOWED_ORIGINS ?? "";
}
} It produces below CloudFormation template (as an example), with environment variable as
Running
I'm unsure though if this is a CDK issue or CloudFormation issue since the synthesized template is handled by CloudFormation, and CloudFormation allows declaring parameters. Need to discuss this with team. Thanks, |
@ashishdhingra keep us updated |
Sorry, I thought I had found another related issue. But I confused an execution record with a config record. |
@AllanOricil why do you need to use a Parameter at all? In general, CloudFormation Parameters are discouraged when using CDK. |
For my use case, I can definitely remove it. Thanks for pointing that out 🤙 However, I did it like that because I wanted to verify if it was possible to override an env variable if necessary using cli parameters. This is useful in complex scenarios (I did not find one yet) which the value of the env variable in the lambda has to be evaluated at deploy time, with information outside of the cdk project. With a parameter like that, I can deploy my stack as so: DYNAMIC_VARIABLE=$(...)
cdk synth stack-name -e --parameters myDynamicVariable $DYNAMIC_VARIABLE If AWS does not recommend it. What about removing this feature? For example, if one tries to do what I did, throw an exception and stop the synthesis. However I do think it could be useful. I just don't know a real use case to show as an example. |
@AllanOricil No worries! A few thoughts:
In general, the results of synthesizing your CDK app should be deterministic, and avoid things like external environment variables as much as possible. Do you need to use environment variables perhaps because you are using the same CDK Let me know if this makes sense! |
For testing purposes, without using CDK:
Parameters:
allowedOrigins:
Type: String
Default: http://localhost:8080,http://testdomain.com
NoEcho: true
BootstrapVersion:
Type: AWS::SSM::Parameter::Value<String>
Default: /cdk-bootstrap/hnb659fds/version
Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
Resources:
testLambdaServiceRole955E2289:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
testLambdaC13632F6:
Type: AWS::Lambda::Function
Properties:
Code:
S3Bucket: testbucket-issue1880
S3Key: b12b4d45960ea908338c4544bcac8039b13736e6d6af9e8a85ef57f538e29706.zip
Environment:
Variables:
ALLOWED_ORIGINS:
Ref: allowedOrigins
Handler: hello.handler
Role:
Fn::GetAtt:
- testLambdaServiceRole955E2289
- Arn
Runtime: nodejs20.x
DependsOn:
- testLambdaServiceRole955E2289 This created Lambda along with environment variable
Parameters:
allowedOrigins:
Type: String
Default: http://localhost:8080,http://testdomain.com,http://makemydomain.com
NoEcho: true
BootstrapVersion:
Type: AWS::SSM::Parameter::Value<String>
Default: /cdk-bootstrap/hnb659fds/version
Description: Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]
Resources:
testLambdaServiceRole955E2289:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
testLambdaC13632F6:
Type: AWS::Lambda::Function
Properties:
Code:
S3Bucket: testbucket-issue1880
S3Key: b12b4d45960ea908338c4544bcac8039b13736e6d6af9e8a85ef57f538e29706.zip
Environment:
Variables:
ALLOWED_ORIGINS:
Ref: allowedOrigins
Handler: hello.handler
Role:
Fn::GetAtt:
- testLambdaServiceRole955E2289
- Arn
Runtime: nodejs20.x
DependsOn:
- testLambdaServiceRole955E2289
So, by default, any changes to CloudFormation parameter are not used (based on observation in AWS console UI). If we look at the CDK guide Deploying with parameters, is explicitly specifies that Going with the above understanding, using @AllanOricil Please use Thanks, |
@ashishdhingra Good job! I didnt know about this flag. Can't it become true by default? Like, it seems a little bit weird for that it isn't true by default in cdk. The only way to know about it is to be aware how this feature works in Cloudformation. It seems counter intuitive based on how many people from CDK team itself, and a former one, couldn't spot the issue right away.
Can you think on a reason for no doing that? |
1 similar comment
@ashishdhingra Good job! I didnt know about this flag. Can't it become true by default? Like, it seems a little bit weird for that it isn't true by default in cdk. The only way to know about it is to be aware how this feature works in Cloudformation. It seems counter intuitive based on how many people from CDK team itself, and a former one, couldn't spot the issue right away.
Can you think on a reason for no doing that? |
@AllanOricil Based on my observation in last #30101 (comment), one possible reasoning is one-to-one parity with CloudFormation UI in AWS console. By default, in AWS console, checkbox |
I will close this. Thank you all for the help. |
|
Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one. |
Describe the bug
I have a lambda full of env variables referencing a "parameter", like the one shown below
![img]
![img]
The above screenshots show a template that was synthesized by CDK after I changed the .env file that provide values to my parameters. However, even after deploying this new stack, CDK did not change my env variable values in my lambda functions. In the image below you can see that "ALLOWED_ORIGINS" was not updated.
![img]
Another weird thing is the CDK doesnt even realize that this change will happen. Below you can see the output of
cdk diff
for the same stack.Expected Behavior
CDK must update Lambda Env Variables values that reference parameters whenever they are changed.
Current Behavior
CDK does not update Lambda Env Variables values when they reference parameters that have changed
Reproduction Steps
create a construct with one lambda
create a cfn parameter that is loaded with values from a .env file. You can use dotenv. like I did.
![img]
![img]
add an env variable to your lambda, and fill its value with the value from the parameter.
![img]
Possible Solution
Couldn't find any woraround
Additional Information/Context
No response
CDK CLI Version
2.138.0
Framework Version
No response
Node.js Version
node 18
OS
macos latest
Language
TypeScript
Language Version
typescript@v5.2.2
Other information
No response
The text was updated successfully, but these errors were encountered: