Amazon web services 在UserData中实现If函数

Amazon web services 在UserData中实现If函数,amazon-web-services,amazon-cloudformation,Amazon Web Services,Amazon Cloudformation,我试图理解是否可以在UserData中使用if函数。当我使用下面的CloudFormation模板时,一切都按预期执行 Type: 'AWS::EC2::Instance' Properties: <OMIT> BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 50 - !If [Volu

我试图理解是否可以在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>

我在引用时找不到任何语法问题。我的场景的唯一解决方案是将条件应用于此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
查看验证模板时发生的情况:

$ 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参数。

谢谢,这让我走上了正确的方向。我在powershell脚本中使用了定义变量的相同逻辑,并使用powershell语法执行了if语句。它现在工作正常。
$ 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
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
        }
    ]
}