编辑
以下是原始详细信息。
在追查过程中,我现在已经将范围缩小到这个安全组
DatabaseSecurityGroup:
Type: AWS::EC2::SecurityGroup
Condition: WantsMail
Properties:
GroupDescription: Security group for RDS Databases
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref MailSecurityGroup
VpcId:
!Ref Vpc
虽然WantsMail
正在评估为,但并未创建true
。我知道WantsMail
正在评估为,true
因为我更改了“输出”部分:
Outputs:
...
DatabaseSecurityGroup:
Condition: WantsMail
Description: Security group for RDS database access
Value: Foo
Export:
Name: FooName
这不仅可以正确输出,还可以创建 MailSecurityGroup(也是以 为条件WantsMail
)。但是,这个安全组却没有。没有显示任何 YAML 错误。我在 AWS CloudFormation UI 中找不到任何错误。关于哪里出了问题,或者如何追踪可能发生的任何错误,您有什么想法吗?
附言:这种编辑在这里是正确的做法吗?或者我应该放弃原来的问题并提出这个更具体的问题,或者......?
原始细节
我正在努力将 CloudFormation 模板拆分为功能堆栈。尚未达到进行任何嵌套的程度,只是独立完成所有工作。对于我的安全组模板,我有一些非常简单的工作,但是当我开始添加条件时,我开始在模板的输出块中收到“未解析的资源依赖关系...”。我不知道思考有任何拼写错误,并且与嵌套有关的问题似乎是我在其他类似问题中看到的最常见的问题。
基本的工作模板如下所示:
---
AWSTemplateFormatVersion: 2010-09-09
Description: 'Create Security Groups'
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: AWS Parameters
Parameters:
- SshAccessCidr
- Vpc
ParameterLabels:
SshAccessCidr:
default: SSH Access From
Vpc:
default: Vpc Id
Parameters:
SshAccessCidr:
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
Description: The CIDR IP range that is permitted to SSH to bastion instance. Note - a value of 0.0.0.0/0 will allow access from ANY IP address.
Type: String
Default: 0.0.0.0/0
Vpc:
AllowedPattern: ^(vpc-)([a-z0-9]{8}|[a-z0-9]{17})$
Description: The Vpc Id of an existing Vpc.
Type: AWS::EC2::VPC::Id
Resources:
BastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Bastion instances
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SshAccessCidr
VpcId:
!Ref Vpc
DatabaseSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for RDS Databases
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 10.0.0.0/20
VpcId:
!Ref Vpc
Outputs:
BastionSecurityGroup:
Value: !Ref BastionSecurityGroup
Export:
Name: !Join [ ":", [ !Ref "AWS::StackName", BastionSecurityGroup ] ]
DatabaseSecurityGroup:
Value: !Ref DatabaseSecurityGroup
Export:
Name: !Join [ ":", [ !Ref "AWS::StackName", DatabaseSecurityGroup ] ]
就像我说的,效果很好!
但是,当我开始添加条件时,它就开始失控了:
AWS::CloudFormation::Interface:
ParameterGroups:
...
- Label:
default: Optional security groups to create
Parameters:
- CreateMailSecGroup
ParameterLabels:
...
CreateMailSecGroup:
default: Create a security group for mail servers
Parameters:
...
CreateMailSecGroup:
AllowedValues:
- 'True'
- 'False'
Default: 'False'
Description: Create a security group for use by mail servers
Type: String
Conditions:
WantsMail: !Equals ['True', !Ref CreateMailSecGroup]
WantsNothing: !Not [ !Equals ['True', !Ref CreateMailSecGroup] ]
Resources:
DatabaseSecurityGroup:
Type: AWS::EC2::SecurityGroup
Condition: WantsMail
Properties:
GroupDescription: Security group for RDS Databases
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref MailSecurityGroup
VpcId:
!Ref Vpc
DatabaseSecurityGroup:
Type: AWS::EC2::SecurityGroup
Condition: WantsNothing
Properties:
GroupDescription: Security group for RDS Databases
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 10.0.0.0/20
VpcId:
!Ref Vpc
MailSecurityGroup:
Type: AWS::EC2::SecurityGroup
Condition: WantsMail
Properties:
GroupDescription: Security group for MX Servers
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref BastionSecurityGroup
- IpProtocol: tcp
FromPort: 25
ToPort: 25
CidrIp: 0.0.0.0/0
...
VpcId:
!Ref Vpc
Outputs:
...
DatabaseSecurityGroup:
Description: Security group for RDS database access
Value: !Ref DatabaseSecurityGroup
Export:
Name: !Join [ ":", [ !Ref "AWS::StackName", DatabaseSecurityGroup ] ]
MailSecurityGroup:
Condition: WantsMail
Description: Security group for MX servers
Value: !Ref MailSecurityGroup
Export:
Name: !Join [ ":", [ !Ref "AWS::StackName", MailSecurityGroup ] ]
现在,如果我进行这些更改,并在当前(运行)堆栈上执行更新堆栈,并将新参数保留CreateMailSecGroup
为其默认值False
,它会做正确的事情,并在解析模板后说“无需更改”。但是如果我将其更改为True
,它会抱怨
模板的 Outputs 块中未解析的资源依赖项 [DatabaseSecurityGroup]
在变更集预览中。
我最初的怀疑是,既然 DatabaseSecurityGroup 是有条件的,它肯定需要在 Outputs 块中有一个匹配的条件,所以我尝试了
Conditions:
WantsMail: !Equals ['True', !Ref CreateMailSecGroup]
WantsNothing: !Not [ !Equals ['True', !Ref CreateMailSecGroup] ]
OutputDatabase: !Or [ Condition: WantsMail, Condition: WantsNothing ]
...
Outputs:
DatabaseSecurityGroup:
Condition: OutputDatabase
Description: Security group for RDS database access
Value: !Ref DatabaseSecurityGroup
Export:
Name: !Join [ ":", [ !Ref "AWS::StackName", DatabaseSecurityGroup ] ]
没有骰子。 同样的错误。
True
我的最后一个猜测是,也许由于某些奇怪的排序现象,DatabaseSecurityGroup 实际上并没有按照条件进行处理,所以我尝试添加DependsOn: MailSecurityGroup
,但这也没有解决问题。
我真的希望这不是一个愚蠢的打字错误。有人知道我做错了什么吗?MailSecurityGroup 的条件内容似乎没有引发任何错误,但我不确定这是因为没有错误,还是因为它在 DatabaseSecurityGroup 的输出部分停止并且从未到达最后一个部分。
谢谢!
答案1
哼。根据文档:
逻辑 ID 必须是字母数字(A-Za-z0-9)并且在模板内是唯一的。
既简单又烦人。因此,不能有两个名为“DatabaseSecurityGroup”的不同资源,并根据条件在它们之间切换。需要为它们赋予不同的名称(然后在输出中为不同的名称创建多个输出部分,这些输出部分也是根据条件选择的)。
答案2
您不能在创建的条件中使用引用。我可以看到
WantsMail: !Equals ['True', !Ref CreateMailSecGroup]
WantsNothing: !Not [ !Equals ['True', !Ref CreateMailSecGroup]
这两个条件都使用了 Fn::Ref:。