AWS CDK如何获取伪参数用户数据?
How to obtain pseudo-parameters user data with AWS CDK?
我想将此有效的 CloudFormation 代码转换为适当的 Python AWS CDK 版本。 EC2 应在 VPC 内启动。用户数据用于安装应用程序。完成后,我需要回调 Cloudformation。
UserData:
Fn::Base64: !Sub |
<script>
cfn-signal.exe --exit-code 0 --stack ${AWS::StackId} --resource EC2Instance --region ${AWS::Region}
</script>
我尝试使用 aws_cdk.core.Fn.base64
的直接方式,这对于 EC2 用户数据中的伪参数声明不起作用。
这是我目前的状态:
EC2InstanceUserData = aws_ec2.UserData.for_windows()
EC2InstanceUserData.add_commands(
"cfn-signal.exe --exit-code 0 ",
"--stack ",
VpcStack.stack_id(XXX, e.g. self?), # not working
" --resource ",
VpcStack.get_logical_id(XXX, e.g. self?), # not working
" --region ",
VpcStack.region(XXX, e.g. self?) # not working
)
您可以使用核心模块访问这些伪参数:
from aws_cdk import core
# other code...
EC2InstanceUserData = aws_ec2.UserData.for_windows()
EC2InstanceUserData.add_commands(
"cfn-signal.exe --exit-code 0 ",
f"--stack {core.Aws.STACK_ID}",
f" --resource {EC2Instance}", # Without more context, I'm not sure if this is exactly what you're wanting
f" --region {core.Aws.REGION}",
)
# other code ...
方法一:
优点:
- 可以接受任意数量的变量,例如上下文中定义的变量,而不仅仅是
core.Aws
对象中的变量,例如区域或帐户 ID。
缺点:
- 您需要在
user_data.sh
脚本中为所有常规变量的引用加上前缀 $!{
而不仅仅是 ${
.
步骤
使用映射字典并将其解析为 Fn.sub 函数。就我个人而言,我喜欢在 user_data.sh
脚本的顶部声明这些,而不是在整个脚本中进行替换,因此使用双下划线作为前缀和后缀。请注意,您仍然需要将映射视为变量而不是字符串。
即
$cat user_data.sh
ACCOUNT_ID="${__ACCOUNT_ID__}"
REGION="${__REGION__}"
## Updates
yum update -y
## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime
## ECR Repo
ECR_REPO="${!ACCOUNT_ID}.dkr.ecr.${!REGION}.amazonaws.com/"
...
然后在我的堆栈声明中放置以下字典:
mappings = {"__ACCOUNT_ID__": self.account,
"__REGION__": self.region}
并将user_data.sh
读入子函数,映射字典作为第二个参数
with open("user_data/user_data.sh", 'r') as user_data_h:
# Use a substitution
user_data_sub = core.Fn.sub(user_data_h.read(), mappings)
然后使用 UserData 模块中的 custom attribute。
# Import substitution object into user_data set
user_data = ec2.UserData.custom(user_data_sub)
方法二
优点:
- 无需更改 bash 语法
缺点:
- 令牌变量难以读取,并且仅限于
core.Aws
对象的属性。比如AccountID和Region。
步骤
您可以 运行 在 cdk 工作流程中打印语句,以帮助您确定 core.Aws.ACCOUNT_ID
和 core.Aws.REGION
等变量的计算结果,并在 [=84] 中使用这些语句=] 脚本。 (我正在 python 中编写我的部署,并基于来自 aws official examples repo 的现有 VPC 的 ec2。
即:
host = ec2.Instance(...)
print(core.aws.ACCOUNT_ID)
print(core.Aws.REGION)
然后我 运行 cdk synth
产生:
${Token[AWS::AccountId.0]}
${Token[AWS::Region.4]}
Resources:...
从这里我可以在我的 user_data 脚本中使用它们:即
#!/bin/bash
ACCOUNT_ID="${Token[AWS::AccountId.0]}"
REGION="${Token[AWS::Region.4]}"
## Updates
yum update -y
## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime
现在请注意,当重新运行宁cdk synth
时,这些被yaml构造函数识别为特殊的(yaml双间距是一个已知的cdk错误):
...
UserData:
Fn::Base64:
Fn::Join:
- ""
- - >-
#!/bin/bash
# AWS vars:
ACCOUNT_ID="
- Ref: AWS::AccountId
- >-
"
REGION="
- Ref: AWS::Region
- >-
"
## Updates
yum update -y
## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime
## ECR Repo
EC2_REPO="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/"
...
我发现以下内容适用于 python
from aws_cdk import (
aws_ec2,
core
)
host = aws_ec2.Instance(...)
host.add_user_data('', join([
'yum install -y aws-cfn-bootstrap\n',
f'/opt/aws/bin/cfn-init -v -s {core.Aws.STACK_NAME} -r {host.node.default_child.logical_id}\n'
])
meta_data = {
'config': {
'packages': {...},
'files': {...},
...
}
}
# for adding the meta data in a way that gets synth
host.node.default_child.add_overide('Metadata.AWS::CloudFormation::Init', meta_data)
这是使用从 host.node.default_child
获得的 CfnInstance
对象
我想将此有效的 CloudFormation 代码转换为适当的 Python AWS CDK 版本。 EC2 应在 VPC 内启动。用户数据用于安装应用程序。完成后,我需要回调 Cloudformation。
UserData:
Fn::Base64: !Sub |
<script>
cfn-signal.exe --exit-code 0 --stack ${AWS::StackId} --resource EC2Instance --region ${AWS::Region}
</script>
我尝试使用 aws_cdk.core.Fn.base64
的直接方式,这对于 EC2 用户数据中的伪参数声明不起作用。
这是我目前的状态:
EC2InstanceUserData = aws_ec2.UserData.for_windows()
EC2InstanceUserData.add_commands(
"cfn-signal.exe --exit-code 0 ",
"--stack ",
VpcStack.stack_id(XXX, e.g. self?), # not working
" --resource ",
VpcStack.get_logical_id(XXX, e.g. self?), # not working
" --region ",
VpcStack.region(XXX, e.g. self?) # not working
)
您可以使用核心模块访问这些伪参数:
from aws_cdk import core
# other code...
EC2InstanceUserData = aws_ec2.UserData.for_windows()
EC2InstanceUserData.add_commands(
"cfn-signal.exe --exit-code 0 ",
f"--stack {core.Aws.STACK_ID}",
f" --resource {EC2Instance}", # Without more context, I'm not sure if this is exactly what you're wanting
f" --region {core.Aws.REGION}",
)
# other code ...
方法一:
优点:
- 可以接受任意数量的变量,例如上下文中定义的变量,而不仅仅是
core.Aws
对象中的变量,例如区域或帐户 ID。
缺点:
- 您需要在
user_data.sh
脚本中为所有常规变量的引用加上前缀$!{
而不仅仅是${
.
步骤
使用映射字典并将其解析为 Fn.sub 函数。就我个人而言,我喜欢在 user_data.sh
脚本的顶部声明这些,而不是在整个脚本中进行替换,因此使用双下划线作为前缀和后缀。请注意,您仍然需要将映射视为变量而不是字符串。
即
$cat user_data.sh
ACCOUNT_ID="${__ACCOUNT_ID__}"
REGION="${__REGION__}"
## Updates
yum update -y
## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime
## ECR Repo
ECR_REPO="${!ACCOUNT_ID}.dkr.ecr.${!REGION}.amazonaws.com/"
...
然后在我的堆栈声明中放置以下字典:
mappings = {"__ACCOUNT_ID__": self.account,
"__REGION__": self.region}
并将user_data.sh
读入子函数,映射字典作为第二个参数
with open("user_data/user_data.sh", 'r') as user_data_h:
# Use a substitution
user_data_sub = core.Fn.sub(user_data_h.read(), mappings)
然后使用 UserData 模块中的 custom attribute。
# Import substitution object into user_data set
user_data = ec2.UserData.custom(user_data_sub)
方法二
优点:
- 无需更改 bash 语法
缺点:
- 令牌变量难以读取,并且仅限于
core.Aws
对象的属性。比如AccountID和Region。
步骤
您可以 运行 在 cdk 工作流程中打印语句,以帮助您确定 core.Aws.ACCOUNT_ID
和 core.Aws.REGION
等变量的计算结果,并在 [=84] 中使用这些语句=] 脚本。 (我正在 python 中编写我的部署,并基于来自 aws official examples repo 的现有 VPC 的 ec2。
即:
host = ec2.Instance(...)
print(core.aws.ACCOUNT_ID)
print(core.Aws.REGION)
然后我 运行 cdk synth
产生:
${Token[AWS::AccountId.0]}
${Token[AWS::Region.4]}
Resources:...
从这里我可以在我的 user_data 脚本中使用它们:即
#!/bin/bash
ACCOUNT_ID="${Token[AWS::AccountId.0]}"
REGION="${Token[AWS::Region.4]}"
## Updates
yum update -y
## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime
现在请注意,当重新运行宁cdk synth
时,这些被yaml构造函数识别为特殊的(yaml双间距是一个已知的cdk错误):
...
UserData:
Fn::Base64:
Fn::Join:
- ""
- - >-
#!/bin/bash
# AWS vars:
ACCOUNT_ID="
- Ref: AWS::AccountId
- >-
"
REGION="
- Ref: AWS::Region
- >-
"
## Updates
yum update -y
## Fix time
ln -sf /usr/share/zoneinfo/Australia/Melbourne /etc/localtime
## ECR Repo
EC2_REPO="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/"
...
我发现以下内容适用于 python
from aws_cdk import (
aws_ec2,
core
)
host = aws_ec2.Instance(...)
host.add_user_data('', join([
'yum install -y aws-cfn-bootstrap\n',
f'/opt/aws/bin/cfn-init -v -s {core.Aws.STACK_NAME} -r {host.node.default_child.logical_id}\n'
])
meta_data = {
'config': {
'packages': {...},
'files': {...},
...
}
}
# for adding the meta data in a way that gets synth
host.node.default_child.add_overide('Metadata.AWS::CloudFormation::Init', meta_data)
这是使用从 host.node.default_child
CfnInstance
对象