Search code examples
pythonamazon-web-servicesterraform-provider-aws

Getting attribute from Terrafrom cdk deployed lambda


I'm using Terraform CDK to deploy a lambda function and am trying to set a trigger to it using s3 notifications. I'm sorta new to CDK, so I'm not sure where things might be going wrong here.

Reading this example and based also on what's done using regular CDK, I thought that to access the function arn (so to add it to bucket notification setting), it'd be my_function.arn, but it renders the following string {TfToken[TOKEN.XXX]}.

It seems to me that I'd be able to fetch the arn somewhere with this value, but I couldn't find out where.

I thought of breaking it up into two stacks, but I needed both lambda and its notification trigger to be deployed together.

The code is

#!/usr/bin/env python
from constructs import Construct
from cdktf import App, TerraformStack, TerraformOutput
from imports.aws import AwsProvider
from imports.aws.lambdafunction import LambdaFunction
from imports.aws.s3 import S3BucketNotification, S3BucketNotificationLambdaFunction
import os

class My_Stack(TerraformStack):
  def __init__(self, scope: Construct, ns: str):
    super().__init__(scope, ns)

    AwsProvider(self, 'Aws', region='my-region')

    my_lambda_function = LambdaFunction(
      self, id='id',
      function_name='cdk-deployment-test',
      role='my-role',
      memory_size=128,
      runtime='python3.8',
      timeout=900,
      handler="lambda_handler",
      filename=os.path.join(os.getcwd(), 'deployment_package/package.zip')
    )

    function_to_be_triggered = S3BucketNotificationLambdaFunction(
      lambda_function_arn= my_lambda_function.arn,
      events = ["s3:ObjectCreate:*"],
      filter_prefix = "path"
    )

    payment_recognition_input = S3BucketNotification(
      self, id='s3-bucket-notification',
      bucket = 'my-bucket',
      lambda_function=[function_to_be_triggered]
    )

app = App()
My_Stack(app, "cdktf-poc")

app.synth()


Solution

  • This is the correct way to reference the terraform resource's ARN property, the {TfToken[TOKEN.XXX]} tokens resolve to Terraform language syntax in the synth output. Check out the CDK For Terraform documentation here that discusses tokens:

    https://github.com/hashicorp/terraform-cdk/blob/main/docs/working-with-cdk-for-terraform/tokens.md#tokens

    For example, this CDKTF code:

    const vpc = new Vpc(this, "my-vpc", {
      name: vpcName,
    });
    
    new Eks(this, "EksModule", {
      clusterName: "my-kubernetes-cluster",
      vpcId: vpc.vpcIdOutput,
    });
    

    ultimately generates (using token) this terraform:

    {
      "module": {
        "helloterraEksModule5DDB67AE": {
          "cluster_name": "my-kubernetes-cluster",
          "vpc_id": "${module.helloterraMyVpc62D94C17.vpc_id}"
        }
      }
    }
    

    So that that reference and dependency link still exist at Terraform plan/apply time.

    For your specific use case, have tried out the following, using the pre-built aws provider and S3BucketNotificationLambdaFunction for structuring the lambda function configuration:

    from cdktf_cdktf_provider_aws.s3 import S3BucketNotificationLambdaFunction, S3BucketNotification
    from cdktf_cdktf_provider_aws.lambda_function import LambdaFunction
    
    my_lambda_function = LambdaFunction(
        self, id='id',
        function_name='cdk-deployment-test',
        role='my-role',
        memory_size=128,
        runtime='python3.8',
        timeout=900,
        handler="lambda_handler",
        filename=os.path.join(os.getcwd(), 'deployment_package/package.zip')
    )
    
    S3BucketNotification(
        self,
        id="s3-bucket-notification",
        bucket="my-bucket",
        lambda_function=[
            S3BucketNotificationLambdaFunction(
                lambda_function_arn=my_lambda_function.arn,
                events=["s3:ObjectCreate"],
                filter_prefix="path"
            )
        ]
    )