如何修复/为什么会导致未解决的资源依赖关系

如何修复/为什么会导致未解决的资源依赖关系

编辑

以下是原始详细信息。

在追查过程中,我现在已经将范围缩小到这个安全组

  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:。

相关内容