我试图了解是否可以在 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, {DeviceName: xvdh, Ebs:{VolumeSize: 150, VolumeType: st1}}, !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, {DeviceName: xvdh, Ebs:{VolumeSize: 150, VolumeType: st1}}, !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 参数中的值创建脚本变量。
关于amazon-web-services - 在 UserData 中实现 If 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67452923/