You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 08:10:35