微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 UserData 中实现 If 函数

如何解决在 UserData 中实现 If 函数

我想了解是否可以在 UserData 中使用 If 函数。当我使用下面的 CloudFormation 模板时,一切都按预期执行。

    Type: 'AWS::EC2::Instance'
    Properties:
        <OMIT>
        BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeSize: 50
        - !If [VolumeCreationCondition,{DeviceName: xvdh,Ebs:{VolumeSize: 150,VolumeType: st1}},!Ref AWS::Novalue]
        UserData:
          !Base64 |
            <powershell>
            Install-WindowsFeature Net-Framework-Core;
            Initialize-disk 1;
            New-Partition -diskNumber 1 -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel Video;
            & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -s -c ssm:WindowsAgentConfig
            </powershell>

但是,当我引入 2 个新的 If 条件时,不会执行单个 PowerShell 命令。

    Type: 'AWS::EC2::Instance'
    Properties:
        <OMIT>
        BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeSize: 50
        - !If [VolumeCreationCondition,!Ref AWS::Novalue]
        UserData:
          !Base64 |
            <powershell>
            Install-WindowsFeature Net-Framework-Core;
            !If [VolumeCreationCondition,Initialize-disk 1;,!Ref AWS::Novalue]
            !If [VolumeCreationCondition,New-Partition -diskNumber 1 -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel Video;,!Ref AWS::Novalue]
            & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -s -c ssm:WindowsAgentConfig
            </powershell>

VolumeCreationCondition 没有问题,因为它在这里工作正常。

!If [VolumeCreationCondition,!Ref AWS::Novalue]

我在引用 AWS Condition functions 时找不到任何语法问题。将条件应用于此 EC2 资源是我的方案的唯一解决方案吗?这并不理想,因为我还有其他几个资源引用了这个 EC2,这意味着我也必须对所有这些资源实施条件。

解决方法

您不能在 PowerShell 脚本中使用 CloudFormation IF 语句。
实际上在任何 userdata 脚本中。

我不了解 PowerShell,但我会告诉你如何用 Bash 做你想做的事。只需遵循相同的方法即可。

Type: 'AWS::EC2::Instance'
    Properties:
        <OMIT>
        BlockDeviceMappings:
        - DeviceName: /dev/sda1
            Ebs:
            VolumeSize: 50
        - !If [VolumeCreationCondition,{DeviceName: xvdh,Ebs:{VolumeSize: 150,VolumeType: st1}},!Ref AWS::NoValue]
        UserData:
            Fn::Base64: !Sub |
            #!/bin/bash
            
            export need_to_init="${VolumeCreationCondition}"
            if [[ "${need_to_init}" != "" ]]
            then
                # "Run your command to init disk here"
            fi

您不能直接在用户数据脚本中使用 CloudFormation 条件。
请参阅下面尝试使用它的示例。

Parameters:
  Production:
    Type: String
    Default: ''

Conditions:
  CreateProdResources: !Not [!Equals [!Ref Production,'']]

Resources:
  CloudNetPingTargetInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: amzn2-ami-hvm-2.0.20210427.0-x86_64-gp2
      NetworkInterfaces:
        - DeviceIndex: '0'
          DeleteOnTermination: true
          SubnetId: subnet-11111c86
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash

          export PRODUCTION="${CreateProdResources}"
          if [[ "$PRODUCTION" != "" ]]
          then
            echo "##### IS PRODUCTION"
          fi

看看当我们验证模板时会发生什么:

$ aws cloudformation validate-template --template-body file://test.yaml

An error occurred (ValidationError) when calling the ValidateTemplate operation: Template format error: Unresolved resource dependencies [CreateProdResources] in the Resources block of the template

但是您可以在脚本中执行与 CloudFormation 条件相同的逻辑。见下文。

Parameters:
  Production:
    Type: String
    Default: ''

Conditions:
  CreateProdResources: !Not [!Equals [!Ref Production,'']]

Resources:
  CloudNetPingTargetInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: amzn2-ami-hvm-2.0.20210427.0-x86_64-gp2
      NetworkInterfaces:
        - DeviceIndex: '0'
          DeleteOnTermination: true
          SubnetId: subnet-11111c86
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash

          export PRODUCTION="${Production}"
          if [[ "$PRODUCTION" != "" ]]
          then
            echo "##### IS PRODUCTION"
          fi
      

现在当我验证时,它起作用了。

$ aws cloudformation validate-template --template-body file://test.yaml
{
    "Parameters": [
        {
            "ParameterKey": "Production","DefaultValue": "","NoEcho": false
        }
    ]
}

诀窍是使用 CloudFormation Sub 函数创建一个带有 CloudFormation 参数值的脚本变量。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。