AWS CDK - update existing lambda environment variables

Viewed 1441

I would love to be able to update an existing lambda function via AWS CDK. I need to update the environment variable configuration. From what I can see this is not possible, is there something workable to make this happen?

I am using code like this to import the lambda:

    const importedLambdaFromArn = lambda.Function.fromFunctionAttributes(
      this,
      'external-lambda-from-arn',
      {
        functionArn: 'my-arn',
        role: importedRole,
      }
    );

For now, I have to manually alter a cloudformation template. Updating directly in cdk would be much nicer.

3 Answers

Yes, it is possible, although you should read @Allan_Chua's answer before actually doing it. Lambda's UpdateFunctionConfiguration API can modify a deployed function's environment variables. The CDK's AwsCustomResource construct lets us call that API during stack deployment.*

Let's say you want to set TABLE_NAME on a previously deployed lambda to the value of a DynamoDB table's name:

// MyStack.ts

const existingFunc = lambda.Function.fromFunctionArn(this, 'ImportedFunction', arn);

const table = new dynamo.Table(this, 'DemoTable', {
  partitionKey: { name: 'id', type: dynamo.AttributeType.STRING },
});

new cr.AwsCustomResource(this, 'UpdateEnvVar', {
  onCreate: {
    service: 'Lambda',
    action: 'updateFunctionConfiguration',
    parameters: {
      FunctionName: existingFunc.functionArn,
      Environment: {
        Variables: {
          TABLE_NAME: table.tableName,
        },
      },
    },
    physicalResourceId: cr.PhysicalResourceId.of('DemoTable'),
  },
  policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
    resources: [existingFunc.functionArn],
  }),
});

Under the hood, the custom resource creates a lambda that makes the UpdateFunctionConfiguration call using the JS SDK when the stack is created. There are also onUpdate and onDelete cases to handle.


* Again, whether this is a good idea or not depends on the use case. You could always call UpdateFunctionConfiguration without the CDK.

The main purpose of CDK is to enable AWS customers to have the capability to automatically provision resources. If we're attempting to update settings of pre-existing resources that were managed by other CloudFormation stacks, it is better to update the variable on its parent CloudFormation template instead of CDK. This provides the following advantages on your side:

  • There's a single source of truth of what the variable should look like
  • There's no tug o war between the CDK and CloudFormation template whenever an update is being pushed from these sources.
  • Otherwise, since this is a compute layer, just get rid of the lambda function from CloudFormation and start full CDK usage altogether bro!

Hope this advise helps

If you are using AWS Amplify, the accepted answer will not work and instead you can do this by exporting a CloudFormation Output from your custom resource stack and then referencing that output using an input parameter in the other stack.

With CDK

new CfnOutput(this, 'MyOutput', { value: 'MyValue' });

With CloudFormation Template

"Outputs": {
  "MyOutput": {
    "Value": "MyValue"
  }
}

Add an input parameter to the cloudformation-template.json of the resource you want to reference your output value in:

"Parameters": {
  "myInput": {
    "Type": "String",
    "Description": "A custom input"
  },
}

Create a parameters.json file that passes the output to the input parameter:

{
  "myInput": {
    "Fn::GetAtt": ["customResource", "Outputs.MyOutput"]
  }
}

Finally, reference that input in your stack:

"Resources": {
  "LambdaFunction": {
    "Type": "AWS::Lambda::Function",
    "Properties": {
      "Environment": {
        "Variables": {
          "myEnvVar": {
            "Ref": "myInput"
          },
        }
      },
    }
  }
}
Related