我正试图通过云初始化将文件复制到Windows EC2实例,方法是通过用户数据传递文件,云初始化模板运行,它创建了一个文件夹,但没有复制文件,你能帮我理解我在代码中做错了什么吗。
该代码通过自动定标组的发射配置传递
data template_cloudinit_config ebs_snapshot_scripts {
gzip = false
base64_encode = false
part {
content_type = "text/cloud-config"
content = <<EOF
<powershell>
$path = "C:aws"
If(!(test-path $path))
{
New-Item -ItemType Directory -Force -Path $path
}
</powershell>
write_files:
- content: |
${file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/1-start-ebs-snapshot.ps1")}
path: C:aws1-start-ebs-snapshot.ps1
permissions: '0744'
- content: |
${file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/2-run-backup.cmd")}
path: C:aws2-run-backup.cmd
permissions: '0744'
- content: |
${file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/3-ebs-snapshot.ps1")}
path: C:aws3-ebs-snapshot.ps1
permissions: '0744'
EOF
}
}
您当前的方法涉及使用Terraform模板语言通过将字符串连接在一起来生成YAML,其中一些字符串是来自外部文件的多行字符串,由于YAML是一种对空格敏感的语言,因此要正确处理这一问题总是非常复杂的。
我有两个想法可以让这件事变得更容易。你可以同时做这两件事,尽管做其中一件也可以。
第一个想法是遵循关于从Terraform的templatefile
函数文档生成JSON和YAML的建议。尽管你的模板是内联的,而不是在一个单独的文件中,但你可以在这里应用类似的原则,让Terraform自己负责生成有效的YAML,然后你就可以担心输入数据结构是正确的形状:
part {
content_type = "text/cloud-config"
# JSON is a subset of YAML, so cloud-init should
# still accept this even though it's jsonencode.
content = jsonencode({
write_files = [
{
content = file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/1-start-ebs-snapshot.ps1")
path = "C:\aws\1-start-ebs-snapshot.ps1"
permissions = "0744"
},
{
content = file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/2-run-backup.cmd")
path = "C:\aws\2-run-backup.cmd"
permissions = "0744"
},
{
content = file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/3-ebs-snapshot.ps1")
path = "C:\aws\3-ebs-snapshot.ps1"
permissions = "0744"
},
]
})
}
jsonencode
和yamlencode
Terraform函数知道如何自动转义换行符和其他特殊字符,因此您只需将文件内容作为属性包含在对象中,Terraform就会自动将其编码为有效的字符串文字。
第二个想法是使用base64编码而不是直接编码。如果将附加属性encoding
设置为b64
,Cloud init允许以base64的形式传递文件内容。然后,您可以使用Terraform的filebase64
函数将文件的内容直接读取到base64字符串中,然后无需任何特殊的引号或转义即可将其包含在YAML中。
使用base64还意味着,放置在远程系统上的文件应该与Terraform模块中磁盘上的文件逐字节相同,而通过在YAML字符串中使用file
,可能会更改行结尾和其他空白。
另一方面,使用base64的一个缺点是文件内容在terraform plan
输出中无法直接读取,因此计划不会像使用纯YAML字符串编码那样清晰。
在第一个示例中,您可以使用filebase64
函数作为jsonencode
参数的一部分,从而有可能将这两种想法结合在一起:
# ...
{
encoding = "b64"
content = filebase64("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/1-start-ebs-snapshot.ps1")
path = "C:\aws\1-start-ebs-snapshot.ps1"
permissions = "0744"
},
# ...
cloud-init
只能可靠地写入文件,因此必须为它们提供内容。我建议将您的文件存储在S3中(例如(,并在引导过程中提取它们。
很抱歉收到MSLinux混合示例。
使用相同的写入文件编写一个简短的脚本,例如
#!/bin/bash
wget something.ps1
wget something-else.ps2
然后使用runcmd/bootcmd运行文件:
bootcmd:
- ./something.ps1
- ./something-else.ps2
工作完成了,没有编码/字符逃避头痛。