I am new to nested stack and i am trying to pass input parameters from parent to child template. My parent stack looks like below:
AWSTemplateFormatVersion: "2010-09-09"
Transform: 'AWS::Serverless-2016-10-31'
Description: "ParentStack with all child stack"
Parameters:
AccountName:
Description: Please Enter valid Account Name.
Type: "CommaDelimitedList"
Default: "citi"
Region:
Description: Enter Region
Type: "CommaDelimitedList"
Default: "us-east-2"
S3BucketName:
Type: "CommaDelimitedList"
Default: ""
S3KeyName:
Type: "CommaDelimitedList"
Default: "Test-LambdaFunction.zip"
Resources:
LambdaStack1:
Type: "AWS::CloudFormation::Stack"
Properties:
Parameters:
TemplateURL: https://test272t3.s3.us-east-2.amazonaws.com/CFTemplates/lambda.yaml
CodeUri:
Bucket: Fn:Join [ ' ', [!Ref S3BucketName] ]
Key: Fn::Join [ ' ', [!Ref S3KeyName] ]
S3Stack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://test272t3.s3.us-east-2.amazonaws.com/CFTemplates/s3child.yaml
Parameters:
BucketName: <<not sure how !sub can be paased in parent stack>>
AccessControl: PublicReadWrite
VersioningConfiguration:
Status: Suspended
And part of child template is as follows:
Parameters:
AccountName:
Description: Please Enter valid Account Name.
Type: String
Default: citi
Region:
Description: Enter Region
Type: String
Default: us-east-2
S3BucketName:
Type: "String"
Default: ""
S3KeyName:
Type: "String"
Default: "MeghFlow-DBConnMgmt-Lambda-DBConnMgmtFunction.zip"
testLambda:
Type: AWS::Serverless::Function
Properties:
CodeUri:
Bucket: !Ref S3BucketName
Key: !Ref S3KeyName
Handler: com.testff.testinghand.dbconnmgmt.lambda.testLambda::handleRequest
Runtime: java8
MemorySize: 1024
Policies: AmazonDynamoDBFullAccess
Environment:
Variables:
REGION: us-east-2
DYNAMODB_NAME: DBConnectionInfo
ArtifactBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
Properties:
BucketName: !Sub ${AccountName}-${Region}-artifacts
AccessControl: PublicReadWrite
VersioningConfiguration:
Status: Suspended
Issue: I am not quite sure how the input parameters can be passed from parent to child. I referred few links like but i was confused even more as to when the input type must be CommaDelimitedList vs string. I even tried keeping the param type to string in both parent and child but still i get below error:
"Value of property Parameters must be an object with String (or simple type) properties"
and on using Fn::join get error as below:
"Fn::Join object requires two parameters, (1) a string delimiter and (2) a list of strings to be joined or a function that returns a list of strings (such as Fn::GetAZs) to be joined."
Have referred link : Trying to pass parameters from Master to child template but no luck .
Can anyone guide me in correct direction please. Thanks in advance.
Thanks #gandaliter for your guidance. As per above marked answer CloudFormation parent stack accepts only strings and not any object level parameters(sub parameters under parameters just like CodeURI in my above code). I did few tweaks and changed all the parent template to below :
Note: All the parameter type are set to String in child and parent template
AWSTemplateFormatVersion: "2010-09-09"
Transform: 'AWS::Serverless-2016-10-31'
Description: "ParentStack with all child stack"
Parameters:
apiGatewayStageName:
Type: String
Default: "dev"
HandlerName:
Type: String
Default: "com.test.tehgsaLambda::handleRequest"
S3BucketName:
Type: String
Default: ""
S3KeyName:
Type: String
Default: "Test-LambdaFunction.zip"
Resources:
LambdaStack1:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL:
Fn::Sub: "https://testyu2y73.s3.us-east-2.amazonaws.com/CFTemplates/lambda.yaml"
Parameters:
S3BucketName: !Ref S3BucketName
S3KeyName: !Ref S3KeyName
HandlerName: !Ref HandlerName
apiGatewayStageName: !Ref apiGatewayStageName
```
I imagine the code you've given above isn't the only combination you've tried, and the parameters don't exactly line up between your parent and child stack, but in any case, the problem is that you're trying to give parameter values of:
CodeUri:
Bucket: Fn:Join [ ' ', [!Ref S3BucketName] ]
Key: Fn::Join [ ' ', [!Ref S3KeyName] ]
and
VersioningConfiguration:
Status: Suspended
Both of these are objects, not 'String (or simple type) properties'. The error is saying that the whole Parameters object must have only simple values.
Incidentally, TemplateURL needs to go outside the Parameters object.
Related
Is there any way to reference parameters in SecretString field in Secrets Manager via CloudFormation?
The way I made the script, the !Ref parameter is a text and not a reference to the parameter.
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Name:
Type: String
myuserparameter:
Type: String
mypasswordparameter:
Type: String
Resources:
SecretsManager:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Ref Name
SecretString: '{"username":"!Ref myuserparameter,"password":"Ref mypasswordparameter"}'
this will work:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Name:
Type: String
myuserparameter:
Type: String
mypasswordparameter:
Type: String
Resources:
SecretsManager:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Ref Name
SecretString: !Sub '{"username": "${myuserparameter}","password": "${mypasswordparameter}"}'
I am trying to pass parameters to one of the nested stacks by populating the values from another nested stacks output.
And i do not want any cross-referencing (unless there is no way around it)
The idea is pretty straight forward.
RootStack
-NstdStackVPC
-NstdStackSG
-NstdStackEC2
The problem is on the last nested stack while creating EC2.
If i created the resource in the root stack directly the EC2 gets created
Description: RootStack
Parameters:
MyKeyName:
Type: AWS::EC2::KeyPair::KeyName
Default: my-test-key
EC2ImageId:
Type: AWS::EC2::Image::Id
Default: ami-0dxxxxa
Resources:
NstdStackVPC ......
NstdStackSG ......
EC2Host:
Type: AWS::EC2::Instance
Properties:
SubnetId: !GetAtt NstdStackVPC.Outputs.VPCPubSubnet
ImageId: !Ref EC2ImageId
InstanceType: t2.micro
KeyName: !Ref MyKeyName
SecurityGroupIds:
- !GetAtt NstdStackSG.Outputs.SecGrp4EC2Host
But if i try to create the EC2 as a nested stack
AWSTemplateFormatVersion: '2010-09-09'
Description: NstdStackEC2.
Parameters:
myNstdKeyName:
Type: AWS::EC2::KeyPair::KeyName
myNstdImageId:
Type: AWS::EC2::Image::Id
myNstdSecGrp:
Type: AWS::EC2::SecurityGroup::Id
myNstdEC2HostSubnet:
Type: AWS::EC2::Subnet::Id
Resources:
EC2Host:
Type: AWS::EC2::Instance
Properties:
SubnetId: !Ref myNstdEC2HostSubnet
ImageId: !Ref myNstdImageId
InstanceType: t2.micro
KeyName: !Ref myNstdKeyName
SecurityGroupIds:
- Ref myNstdSecGrp
By changing the root stack as follows
AWSTemplateFormatVersion: '2010-09-09'
Description: RootStack
Parameters:
MyKeyName:
Type: AWS::EC2::KeyPair::KeyName
Default: my-test-key
EC2ImageId:
Type: AWS::EC2::Image::Id
Default: ami-0dxxxxa
Resources:
NstdStackVPC ......
NstdStackSG ......
NstdStackEC2:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://bkt.s3.eu-central-1.amazonaws.com/NstdEC2Host.yml
Parameters:
myNstdKeyName: !Ref MyKeyName
myNstdImageId: !Ref EC2ImageId
myNstdSecGrp: !GetAtt NstdStackSG.Outputs.SecGrp4BasHost
myNstdEC2HostSubnet: !GetAtt NstdStackVPC.Outputs.VPCPubSubnet
It gives me the following error:
Value of property Parameters must be an object with String (or simple type) properties
tried removing all the parameters to try one by one. But it fails on everything.
Even for the parameters that are being referenced directly from the root stack i.e., MyKeyName, EC2ImageId
I ran into the same exact error message with a similar problem and solution. I came here and since the issue was slightly different, this question helped me get to my solution. So, not trying to hijack this question, simply hoping to provide what I found additionally useful to the next person visiting.
I was nesting a cluster template very similar to this one and OPs example. Passing Subnets as a list of strings (I believe List<AWS::Some::Type> will also work).
Subnets:
Description: Subnets of the of the cluster availaibility zone
Type: CommaDelimitedList
Default: subnet-0d..de,subnet-0e..7a,subnet-0b..24
And I'm using the above parameters to call the partial child template as follows.
ECS:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://xx.amazonaws.com/yy/zz.yaml
Parameters:
SecurityGroups: !Join [",", [!GetAtt SecurityGroups.Outputs.ECSHostSecurityGroup]]
Subnets: !Join [",", !Ref Subnets]
So, In the above example, the SecurityGroups are joined together into a list from the output of the SecurityGroup Nested Template, but the subnets are simply joined together from the comma delimited parameter. There is a knowledge-center article too, if you want more info. TA OP
Ok finally sorted this out myself.
In my NstdStackSG outputs section i was referring to the object itself.
And that is where this goes wrong.
AWSTemplateFormatVersion: 2010-09-09
Description: Security group nested stack
Resources:
MySecGrp
Type: ....
.....
....
Outputs:
MyOtptSecGrp:
#This one is working for me.
Value: !GetAtt MySecGrp.GroupId
#previously i was assigning the following value
#Value: !Re MySecGrp
And now in the RootStack
AWSTemplateFormatVersion: '2010-09-09'
Description: RootStack
Parameters:
MyKeyName:
Type: AWS::EC2::KeyPair::KeyName
Default: my-test-key
EC2ImageId:
Type: AWS::EC2::Image::Id
Default: ami-0dxxxxa
Resources:
NstdStackVPC ......
NstdStackSG ......
NstdStackEC2:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://bkt.s3.eu-central-1.amazonaws.com/NstdEC2Host.yml
Parameters:
myNstdKeyName: !Ref MyKeyName
myNstdImageId: !Ref EC2ImageId
myNstdSecGrp: !GetAtt NstdStackSG.Outputs.SecGrp4BasHost
myNstdEC2HostSubnet: !GetAtt NstdStackVPC.Outputs.VPCPubSubnet
And in my nestedEC2Stack
AWSTemplateFormatVersion: 2010-09-09
Description: NstdStackEC2
Parameters:
myNstdSecGrp:
Type: AWS::EC2::SecurityGroup::Id
myNstdEC2HostSubnet:
Type: AWS::EC2::Subnet::Id
myNstdKeyName:
Type: AWS::EC2::KeyPair::KeyName
myNstdImageId:
Type: AWS::EC2::Image::Id
Resources:
EC2Host:
Type: AWS::EC2::Instance
Properties:
SubnetId: !Ref myNstdEC2HostSubnet
ImageId: !Ref myNstdImageId
InstanceType: t2.micro
KeyName: !Ref myNstdKeyName
SecurityGroupIds:
- !Ref myNstdSecGrp
Hope this helps. (If not in solving then at least in pointing the right direction)
I have a CloudFormation template that looks something like the following:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
env:
Type: String
Default: NONE
Resources:
GraphQLAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
Name: !Sub 'my-api-${env}'
AuthenticationType: AMAZON_COGNITO_USER_POOLS
UserPoolConfig:
UserPoolId: <something>
AwsRegion: !Ref AWS::Region
DefaultAction: ALLOW
Suppose that I already have a SSM parameter named /dev/cognitoUserPoolId. When I create this template, passing env=dev, I want to use the value of that parameter as the UserPoolId. I want to avoid manually passing a new CFN parameter for every SSM parameter, as there may be quite a few in practice.
You should be able to use dynamic references to the SSM parameters in your template.
Something like:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
env:
Type: String
Default: NONE
Resources:
GraphQLAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
Name: !Sub 'my-api-${env}'
AuthenticationType: AMAZON_COGNITO_USER_POOLS
UserPoolConfig:
UserPoolId: !Sub '{{resolve:ssm:/${env}/cognitoUserPoolId:1}}'
AwsRegion: !Ref AWS::Region
DefaultAction: ALLOW
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html
I'm having a strange behavior with cloudformation template. This my template, where I create a bucket and want to notification configuration depending on a condition :
AWSTemplateFormatVersion: '2010-09-09'
Description: "Setup Artifacts Bucket"
Parameters:
BucketName:
Description: Name of the pipeline setup arctifact bucket
Type: String
Default: "s3-pipeline-setup"
NotificationCondition:
Description: Conditionally add Notification configuration to the artifact bucket
Type: String
Default: false
Conditions:
AddNotificationConfiguration: !Equals [ !Ref NotificationCondition, true ]
Resources:
ArtifactBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
Fn::If:
- AddNotificationConfiguration
-
NotificationConfiguration:
LambdaConfigurations:
-
Function: "arn:aws:lambda:eu-west-1:341292222222227:function:lambda-ops-trigger-pipeline-setup"
Event: "s3:ObjectCreated:*"
Filter:
S3Key:
Rules:
-
Name: prefix
Value: "appstackcodes/"
-
Name: suffix
Value: "txt"
- !Ref AWS::NoValue
When I try a deploy it fails with this error :
00:28:10
UTC+0200 CREATE_FAILED AWS::S3::Bucket ArtifactBucket Encountered
unsupported property Fn::If
I don't really understand the matter.. Can someone try and let me know the mistake there please?
Thanks
Unfortunately you can not do what you intended in cloudformation.
The Fn::If can basically just be used as a ternary expression. E.g.
key: Fn::If: [condition_name, value_if_true, value_if_false]
It can't be used as logic flow like you would in a programming language. There are ways around it. You actually already seemed to have discovered the AWS::NoValue, so it's just a matter of moving the NotificationConfiguration assignment to outside the if.
Resources:
ArtifactBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
NotificationConfiguration:
Fn::If:
- AddNotificationConfiguration
- LambdaConfigurations:
-
Function: "arn:aws:lambda:eu-west-1:341294322147:function:lambda-itops-trigger-pipeline-setup"
Event: "s3:ObjectCreated:*"
Filter:
S3Key:
Rules:
-
Name: prefix
Value: "appstackcodes/"
-
Name: suffix
Value: "txt"
- !Ref AWS::NoValue
Effectively you are always assigning something to NotificationConfiguration, but sometimes it's the magic AWS::NoValue. This works in the majority of cases, although there are times when this just isn't sufficient and more creativity is required!
Is there a way to pass every parameter that a root stack receives to its nested stacks? I can pass one parameter at a time just fine, but I'd like to just pass them all at once.
Here is sample template to give you an idea.
Master.yaml:
Resources:
Cloudspan:
Type: "AWS::CloudFormation::Stack"
Properties:
Parameters:
LambdaName: Cloudspan
BucketName: <BucketName>
S3KeyName: <S3KeyName>
FunctionName: <FunctionName>
TemplateURL: <TemplateURL>
Alignment:
Type: "AWS::CloudFormation::Stack"
Properties:
Parameters:
LambdaName: Alignment
BucketName: <BucketName>
S3KeyName: <S3KeyName>
FunctionName: <FunctionName>
TemplateURL: <TemplateURL>
Lambda-child.yaml:
Parameters:
LambdaName:
Type: String
BucketName:
Type: String
S3KeyName:
Type: String
FunctionName:
Type: String
Resources:
LambdaFunction:
Type: "AWS::Lambda::Function"
Properties:
Handler: !Sub '${LambdaName}-{FunctionName}.Handler'
Role:
Fn::GetAtt: ['LambdaExecutionRole', Arn ]
Code:
S3Bucket: !Sub '${LambdaName}{BucketName}'
S3Key: !Sub '${LambdaName}{S3KeyName}'
Runtime: "python3.6"
There is no way (yet) to pass every parameter at once from the root stack to the nested stack. If you want to pass every parameter, you have to do it one by one as the template given in Sudharsan Sivasankaran's answer.
Fn::Import
You can "export" your parameters as outputs from one stack and then any stack will be able to access those values across your entire account. This might be more open than you are looking for but if your end goal is to get stacks to share variables then exporting outputs and referencing them with Fn::Import accomplishes that.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html