Reputation: 378
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
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