DanSchneiderNA
DanSchneiderNA

Reputation: 378

Importing s3 Bucket in Cloudformation template

In a Cloudformation template, I define two S3 Buckets.

 Bucket1:
  Type: AWS::S3::Bucket
  Properties:
   ...
 Bucket2:
  Type: AWS::S3::Bucket
  Properties:
   ...

Outputs:
 Bucket1:
  Description: S3 Bucket
  Value: !Ref Bucket1
  Export:
   Name: !Sub "${AWS::StackName}:Bucket1"
 Bucket2:
  Description: S3 Bucket
  Value: !Ref Bucket2
  Export:
   Name: !Sub "${AWS::StackName}:Bucket2"

I use these exported buckets in two different cloudformation templates.

Template 1

Parameters:
 LoaderCodeBucket:
  Type: String

Resources:
 MyLambdaFunction:
  Type: AWS::Lambda::Function
  Properties:
   Code:
    S3Bucket:
     Fn::ImportValue:
      !Sub "${LoaderCodeBucket}:Bucket1"

Template 2

Parameters:
 ProcessorCodeBucket:
  Type: String

Resources:
 MyOtherLambdaFunction:
  Type: AWS::Lambda::Function
  Properties:
   Code:
    S3Bucket:
     Fn::ImportValue:
      !Sub "${ProcessorCodeBucket}:Bucket2"

Template 1 passes aws cloudformation validate-template --template-body ... while Template 2 fails due to

Template error: the attribute in Fn::ImportValue must not depend on any resources, imported values, or Fn::GetAZs.

The only difference is the lambda function in template 2 is used in an aws analytics application that is also defined in template 2.

I know for sure it's the S3 Bucket causing issues because when I remove that section of code, it passes the validation check.

I have been using this site to try to debug this issue, but none of the questions seem to answer this particular issue.

This is in same region/same account.

My question is: Why is this particular section of code (template 2) throwing a template error when template 1 passes with no error?

Upvotes: 1

Views: 2859

Answers (1)

Balu Vyamajala
Balu Vyamajala

Reputation: 10333

This is a working example.

Template 1:

AWSTemplateFormatVersion: "2010-09-09"
Description: "Test"
Resources:
  MyBucketOne:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: bucket-one-12341234
  MyBucketTwo:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: bucket-two-12341234
Outputs:
  MyBucketOneOutput:
    Description: "Bucket Name of BucketOne"
    Value: !Ref MyBucketOne
    Export:
      Name: !Sub "${AWS::StackName}-BucketOne"
  MyBucketTwoOutput:
    Description: "Bucket Name of BucketTwo"
    Value: !Ref MyBucketTwo
    Export:
      Name: !Sub "${AWS::StackName}-BucketTwo"

Template 2: we can import it as !ImportValue my-s3-BucketOne

AWSTemplateFormatVersion: "2010-09-09"
Description: "Test"
Resources:
  MyLambda:
    Type: "AWS::Lambda::Function"
    Properties:
      Handler: index.handler
      Runtime: nodejs12.x
      FunctionName: "test-s3-import"
      Code:
        S3Bucket: !ImportValue my-s3-BucketOne
        S3Key: "index.zip"
      Description: "Test Lambda"
      MemorySize: 128
      Timeout: 60
      Role: test-role-arn

If you do want to use from Parameter, it will be Fn::ImportValue: !Sub ${BucketExportNamePrefix}-BucketOne

AWSTemplateFormatVersion: "2010-09-09"
Description: "Test"
Parameters:
  BucketExportNamePrefix:
    Type: String
    Default: "my-s3"

Resources:
  MyLambda:
    Type: "AWS::Lambda::Function"
    Properties:
      Handler: index.handler
      Runtime: nodejs12.x
      FunctionName: "test-s3-import"
      Code:
        S3Bucket:
          Fn::ImportValue: !Sub ${BucketExportNamePrefix}-BucketOne
        S3Key: "index.zip"
      Description: "Test Lambda"
      MemorySize: 128
      Timeout: 60
      Role: test-role-arn

Upvotes: 1

Related Questions