[英]Cloudformation nested stack template ValidationError for child-to-child parameter
I've made a nested cloudformation parent template that then references 4 child templates. 我制作了一个嵌套的cloudformation父模板,然后引用了4个子模板。 When I try to launch the stack via the CLI command
aws cloudformation create-stack...
I get the error: 当我尝试通过CLI命令
aws cloudformation create-stack...
启动堆栈时,出现错误:
An error occurred (ValidationError) when calling the CreateStack
operation: Template error: instance of Fn::GetAtt references undefined
resource BatchScatterGatherSubmissionActivity
This is because I have a child template called StepFunctionResourcesStack that contains the BatchScatterGatherSubmissionActivity
and then another child template EC2InstanceResourcesStack that references it. 这是因为我有一个名为StepFunctionResourcesStack的子模板,其中包含
BatchScatterGatherSubmissionActivity
,然后是另一个引用它的子模板EC2InstanceResourcesStack 。 I made sure to add a DependsOn
clause for the latter child template, but I still get the error. 我确保为后一个子模板添加一个
DependsOn
子句,但是仍然出现错误。
Here is the StepFunctionResourcesStack : 这是StepFunctionResourcesStack :
AWSTemplateFormatVersion: '2010-09-09'
Description: step functions resources stack.
Parameters:
StackUID:
Type: String
Resources:
StatesExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- !Sub states.${AWS::Region}.amazonaws.com
Action: "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: StatesExecutionPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "lambda:InvokeFunction"
Resource: "*"
MyStateMachine:
Type: "AWS::StepFunctions::StateMachine"
Properties:
#
# The StateMachine definition is substituted in with Jinja2
#
DefinitionString: !Sub
- |
{{ machine_json | indent(10) }}
- {% for item in machine_args -%}
{{ item }}
{% endfor %}
RoleArn: !GetAtt [ StatesExecutionRole, Arn ]
# several of these:
BatchScatterGatherSubmissionActivity:
Type: "AWS::StepFunctions::Activity"
Properties:
Name:
Fn::Join: [ "-", [ "BatchScatterGatherSubmissionActivity", Ref: StackUID] ]
BatchScatterGatherPollingActivity:
Type: "AWS::StepFunctions::Activity"
Properties:
Name:
Fn::Join: [ "-", [ "BatchScatterGatherPollingActivity", Ref: StackUID] ]
BatchGatherActivity:
Type: "AWS::StepFunctions::Activity"
Properties:
Name:
Fn::Join: [ "-", [ "BatchGatherActivity", Ref: StackUID] ]
BatchTriodenovoActivity:
Type: "AWS::StepFunctions::Activity"
Properties:
Name:
Fn::Join: [ "-", [ "BatchTriodenovoActivity", Ref: StackUID] ]
BatchHandoffActivity:
Type: "AWS::StepFunctions::Activity"
Properties:
Name:
Fn::Join: [ "-", [ "BatchHandoffActivity", Ref: StackUID] ]
Outputs:
# These get used in the instance_resources child stack.
BatchScatterGatherSubmissionActivity:
Value: !Ref BatchScatterGatherSubmissionActivity
BatchScatterGatherPollingActivity:
Value: !Ref BatchScatterGatherPollingActivity
BatchGatherActivity:
Value: !Ref BatchGatherActivity
BatchTriodenovoActivity:
Value: !Ref BatchTriodenovoActivity
BatchHandoffActivity:
Value: !Ref BatchHandoffActivity
And here is the relevant part of the parent (nested) template where the above outputs are passed into the EC2InstanceResourcesStack: 这是父(嵌套)模板的相关部分,上面的输出将传递到EC2InstanceResourcesStack中:
StepFunctionResourcesStack:
Type: AWS::CloudFormation::Stack
Properties:
Parameters:
StackUID:
Ref: StackUID
TemplateURL: https://s3.amazonaws.com/CFNTemplate/step_functions_resources.stack.yaml
Timeout: "100"
EC2InstanceResourcesStack:
Type: AWS::CloudFormation::Stack
Properties:
Parameters:
BatchScatterGatherSubmissionActivity:
Fn::GetAtt: [ "BatchScatterGatherSubmissionActivity", "Outputs.StepFunctionResourcesStack" ]
BatchScatterGatherPollingActivity:
Fn::GetAtt: [ "BatchScatterGatherPollingActivity", "Outputs.StepFunctionResourcesStack" ]
BatchGatherActivity:
Fn::GetAtt: [ "BatchGatherActivity", "Outputs.StepFunctionResourcesStack" ]
BatchTriodenovoActivity:
Fn::GetAtt: [ "BatchTriodenovoActivity", "Outputs.StepFunctionResourcesStack" ]
BatchHandoffActivity:
Fn::GetAtt: [ "BatchHandoffActivity", "Outputs.StepFunctionResourcesStack" ]
Subnet: !Ref Subnet
GPCESSHKeyPair: !Ref GPCESSHKeyPair
GPCESubnetAZ1: !Ref GPCESubnetAZ1
ActivityAndHandoffAnsibleBucketName: !Ref ActivityAndHandoffAnsibleBucketName
ActivityAndHandoffAnsibleKeyName: !Ref ActivityAndHandoffAnsibleKeyName
ActivityAndHandoffDaemonBucketName: !Ref ActivityAndHandoffDaemonBucketName
ActivityAndHandoffDaemonKeyName: !Ref ActivityAndHandoffDaemonKeyName
ActivityAndHandoffDaemonRequirementsBucketName: !Ref ActivityAndHandoffDaemonRequirementsBucketName
ActivityAndHandoffDaemonRequirementsKeyName: !Ref ActivityAndHandoffDaemonRequirementsKeyName
Rkstr8PkgBucketName: !Ref Rkstr8PkgBucketName
Rkstr8PkgKeyName: !Ref Rkstr8PkgKeyName
TemplateURL: https://s3.amazonaws.com/CFNTemplate/instance_resources.stack.yaml
Timeout: "100"
DependsOn: StepFunctionResourcesStack
For my method of exporting the parameters from the child and passing them to another via the parent template, I followed the approach provided in the answer here: AWS CloudFormation: Passing Values between Nested Stacks 对于从子级导出参数并将其通过父模板传递给另一个参数的方法,我遵循此处答案中提供的方法: AWS CloudFormation:在嵌套堆栈之间传递值
You cannot directly reference resources (via Ref
) from one template in another template, even when they are parent-child or sibling templates. 您不能直接从另一个模板中的一个模板(通过
Ref
)引用资源,即使它们是父子模板或同级模板。 The resources are stack specific unless they are explicitly exported via the Output
section. 资源是特定于堆栈的,除非它们通过“
Output
部分显式导出。
So you have 2 options: 因此,您有2个选择:
Option 1: Export the value(s) you care about for BatchScatterGatherSubmissionActivity
from the child template 1 via the Output
section, then import those values in child template 2. 选项1:通过“
Output
部分从子模板1导出您关心的BatchScatterGatherSubmissionActivity
值,然后将这些值导入子模板2。
For example: 例如:
In the "source" template: 在“源”模板中:
"Outputs" : {
"MyValue" : {
"Value" : {
"Ref" : "BatchScatterGatherSubmissionActivity"
},
"Export" : {
"Name" : "MyExportedValue"
}
}
}
then import the value in your "consuming" template: 然后将值导入“消费”模板中:
{ "Fn::ImportValue" : "MyExportedValue" }
More information: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html 更多信息: https : //docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-stack-exports.html
One drawback is that you cannot "DependsOn". 缺点之一是您不能“ DependsOn”。 Also, quite literally child template 2 depends on child template 1.
而且,从字面上看,子模板2取决于子模板1。
Option 2: Output the value(s) you care about for BatchScatterGatherSubmissionActivity
out from the child template (ie. up to the parent), then pass those values from the parent down to the other child. 选项2:从子模板输出您关心
BatchScatterGatherSubmissionActivity
的值(即,向上传递给父级),然后将这些值从父级传递到另一个子级。
So in child template 1, you would output the value from the child stack: 因此,在子模板1中,您将从子堆栈中输出值:
"Outputs" : {
"MyValue" : {
"Value" : {
"Ref" : "BatchScatterGatherSubmissionActivity"
}
}
}
In child template 2, you would add a parameter to the template via the "Parameters" section, and then reference that parameter. 在子模板2中,您可以通过“参数”部分向模板添加一个参数,然后引用该参数。
"Parameters" : {
"MyParam" : {
"Type" : "String",
"Description" : "The value from elsewhere"
}
}
then 然后
{ "Ref" : "MyParam" }
Finally, hook the 2 child stacks together in the parent by passing the output of child template 1 into the parameter of child template 2: 最后,通过将子模板1的输出传递到子模板2的参数中,将2个子堆栈在父级中挂钩:
"ChildStack2": {
"Type" : "AWS::CloudFormation::Stack",
"Properties" : {
"Parameters" : {
"MyParam" : { "Fn::GetAtt" : "Outputs.MyValue" }
}
}
}
In this case, child stack 2 won't be created until child stack 1 is ready and outputs it's values, so there's an implied "DependsOn". 在这种情况下,直到子堆栈1准备好并输出其值时才创建子堆栈2,因此隐含了“ DependsOn”。 But in this case, child template 2 does not depend on child template 1. Instead, it depends on anything that fulfills it's input parameter (which can be a parent stack, or something else).
但是在这种情况下,子模板2不依赖于子模板1。相反,它取决于满足其输入参数的任何内容(可以是父堆栈,也可以是其他内容)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.