aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM
https://aws.amazon.com/serverless/sam/
Apache License 2.0
6.5k stars 1.17k forks source link

Bug: Fn::If not supported, unsure of a workaround when working with Lambda layers #7509

Open EricXDong opened 1 week ago

EricXDong commented 1 week ago

Description:

In one project, I'm outputting a Lambda layer:

Outputs:
  LayerArn:
    Description: ""
    Value: !Ref LayerResource
    Export:
      Name: LayerArn

In a separate project, I want to import this layer:

Resources:
  LambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Layers:
        - !ImportValue LayerArn

This works in production, but not locally because Fn::ImportValue doesn't work locally. The standard workaround is to use Conditions on a parameter that is overridden on local runs:

Parameters:
  Environment:
    Type: String
    Default: "prod"

Conditions:
  IsLocalRun: !Equals [!Ref Environment, "local"]

Resources:
  LambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Layers:
        - !If
          - IsLocalRun
          - hardcoded ARN value
          - !ImportValue ChatFunctionApiArn-prod

But this doesn't work because Fn::If isn't supported either. Users have run into similar issues where the recommended workaround was to instead define a parameter for the value itself, which is overridden on local runs. Applied to my case, that would be something like:

Parameters:
  LayerArnParam:
    Type: String
    Default: !ImportValue LayerArn

Resources:
  LambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Layers:
        - !Ref LayerArnParam

However, this doesn't work because Every Default member must be a string, so it seems you can't use intrinsic functions in the default values of parameters.

Observed result:

$ sam validate

E2001 Property Parameters/LayerArnParam/Default should be of type String

Expected result:

Expect to be able to !ImportValue a Lambda layer ARN in production, and override it with a hardcoded ARN in local environment.

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Mac
  2. sam --version: SAM CLI, version 1.118.0
  3. AWS region: us-west-1
# Paste the output of `sam --info` here
$ sam --info
{
  "version": "1.118.0",
  "system": {
    "python": "3.8.13",
    "os": "macOS-14.5-x86_64-i386-64bit"
  },
  "additional_dependencies": {
    "docker_engine": "27.2.0",
    "aws_cdk": "Not available",
    "terraform": "Not available"
  },
  "available_beta_feature_env_vars": [
    "SAM_CLI_BETA_FEATURES",
    "SAM_CLI_BETA_BUILD_PERFORMANCE",
    "SAM_CLI_BETA_TERRAFORM_SUPPORT",
    "SAM_CLI_BETA_RUST_CARGO_LAMBDA"
  ]
}
hawflau commented 1 day ago

@EricXDong Thanks for raising the issue.

Every Default member must be a string is a rule that CloudFormation enforces. And SAM CLI does not support Fn::If in local invoke. There is previous feature request for this - https://github.com/aws/aws-sam-cli/issues/6205

There are some alternatives you can try:

EricXDong commented 1 day ago

Thanks for your reply and the alternatives @hawflau, hope I can add my voice to the Fn::If feature request!