Packer构建Proxmox模板时多行字符串验证错误求助
问题:Packer templatefile 多行字符串格式错误修复
我使用Packer 1.9.4结合proxmox-iso构建Proxmox模板,构建文件中定义了如下本地变量:
locals { </snip> data_source_content = { "/meta-data" = file("${abspath(path.root)}/data/meta-data") "/user-data" = templatefile("${abspath(path.root)}/data/user-data.pkrtpl.hcl", { build_username = "${var.build_username}" build_password = "${var.build_password}" build_password_encrypted = "${var.build_password_encrypted}" vm_os_language = "${var.vm_os_language}" vm_os_keyboard = "${var.vm_os_keyboard}" vm_os_timezone = "${var.vm_os_timezone}" }) } }
验证模板时出现以下错误:
Error: Error in function call on builds/linux/<sensitive>/22-04-lts/linux-<sensitive>-proxmox.pkr.hcl line 38: (source code not available) with path.root as "builds/linux/<sensitive>/22-04-lts/", var.build_password as "<sensitive>", var.build_password_encrypted as "<sensitive>", var.build_username as "<sensitive>", var.vm_os_keyboard as "us", var.vm_os_language as "en_US", var.vm_os_timezone as "UTC". Call to function "templatefile" failed: /home/ubuntu/proxmox-devops/builds/linux/<sensitive>/22-04-lts/data/user-data.pkrtpl.hcl:16,35-17,1: Invalid multi-line string; Quoted strings may not be split over multiple lines. To produce a multi-line string, either use the \n escape to represent a newline character or use the "heredoc" multi-line template syntax., and 249 other diagnostic(s).
我尝试过用heredoc但仍报错,不确定该语法是否适用于当前变量类型。试过多种变量格式化方式,移除部分变量的sensitive参数后能看到变量正常传递,因此判断是格式化问题。请问应如何正确格式化上述data_source_content变量?
附user-data.pkrtpl.hcl内容:
#cloud-config autoinstall: version: 1 early-commands: - sudo systemctl stop ssh locale: ${vm_os_language} keyboard: layout: ${vm_os_keyboard} storage: config: %{ if "${vm_firmware} == "ovmf" ~} - ptable: gpt path: /dev/sda wipe: superblock preserve: false grub_device: true type: disk id: disk-sda - device: disk-sda size: 1M flag: bios_grub number: 1 preserve: false type: partition id: partition-grub %{ else ~} - ptable: gpt path: /dev/sda wipe: superblock preserve: false type: disk id: disk-sda - device: disk-sda size: 768M wipe: superblock flag: boot number: 1 preserve: false grub_device: true type: partition id: partition-efi - fstype: fat32 volume: partition-efi preserve: false type: format id: fs-efi label: EFI - path: /boot/efi device: fs-efi type: mount id: mount-efi %{ endif ~} <bunch of partitions and lvols> identity: hostname: ubuntu-server username: ${build_username} password: ${build_password_encrypted} ssh: install-server: true allow-pw: true packages: - openssh-server - qemu-guest-agent - cloud-init user-data: disable_root: false timezone: ${vm_os_timezone} late-commands: - sed -i -e 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g' /target/etc/ssh/sshd_config - echo '${build_username} ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/${build_username} - curtin in-target --target=/target -- chmod 440 /etc/sudoers.d/${build_username}
解决方案
1. 修复模板条件判断语法错误
你的user-data.pkrtpl.hcl中条件判断存在引号嵌套错误,且HCL模板引用变量无需额外加引号,正确写法应为:
%{ if vm_firmware == "ovmf" ~}
2. 用YAML Heredoc处理多行配置
错误核心是storage.config的多行列表结构被HCL解析为非法字符串,需用YAML的|符号开启Heredoc模式保留格式:
#cloud-config autoinstall: version: 1 early-commands: - sudo systemctl stop ssh locale: ${vm_os_language} keyboard: layout: ${vm_os_keyboard} storage: config: | %{ if vm_firmware == "ovmf" ~} - ptable: gpt path: /dev/sda wipe: superblock preserve: false grub_device: true type: disk id: disk-sda - device: disk-sda size: 1M flag: bios_grub number: 1 preserve: false type: partition id: partition-grub %{ else ~} - ptable: gpt path: /dev/sda wipe: superblock preserve: false type: disk id: disk-sda - device: disk-sda size: 768M wipe: superblock flag: boot number: 1 preserve: false grub_device: true type: partition id: partition-efi - fstype: fat32 volume: partition-efi preserve: false type: format id: fs-efi label: EFI - path: /boot/efi device: fs-efi type: mount id: mount-efi %{ endif ~} # 补充剩余分区与逻辑卷配置 identity: hostname: ubuntu-server username: ${build_username} password: ${build_password_encrypted} ssh: install-server: true allow-pw: true packages: - openssh-server - qemu-guest-agent - cloud-init user-data: disable_root: false timezone: ${vm_os_timezone} late-commands: - sed -i -e 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g' /target/etc/ssh/sshd_config - echo '${build_username} ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/${build_username} - curtin in-target --target=/target -- chmod 440 /etc/sudoers.d/${build_username}
3. 简化模板变量传递
locals定义中无需给变量加引号,直接传递即可,同时补上模板中用到但遗漏的vm_firmware变量:
locals { </snip> data_source_content = { "/meta-data" = file("${abspath(path.root)}/data/meta-data") "/user-data" = templatefile("${abspath(path.root)}/data/user-data.pkrtpl.hcl", { build_username = var.build_username build_password = var.build_password build_password_encrypted = var.build_password_encrypted vm_os_language = var.vm_os_language vm_os_keyboard = var.vm_os_keyboard vm_os_timezone = var.vm_os_timezone vm_firmware = var.vm_firmware # 补充缺失的变量传递 }) } }
4. 敏感变量处理
sensitive类型变量无需额外格式化,Packer会自动处理,确保模板引用方式正确即可。
内容的提问来源于stack exchange,提问作者AJ Schroeder
相关产品推荐
相关产品推荐

