Environment Variables using ExecInstance go API

I am using the LXD api to write a Hashicorp Packer plugin (https://github.com/deepankarsharma/packer-plugin-lxdapi). The lxc Go api has been pleasant to use and I have been able to get things to a point where I can write things like the following and have packer generate a valid LXD container or VM image.

source "lxdapi" "instance" {
  unix_socket_path = "/var/snap/lxd/common/lxd/unix.socket"
  source_image     = "jammy-amd64"
  output_image = "jammy-output"
  output_image_description = "Jammy container image"
  publish_properties = {
    description = "Jammy container image"
  }
  config = {
    "security.secureboot": "false"
  }
  virtual_machine = false
  compression_algorithm = "zstd"
}

build {
  sources = [
    "source.lxdapi.instance",
  ]

  provisioner "lxdapi-shell" {
    environment = {
      "HELLO": "WORLD"
    }

    inline = [
      "env",
      "echo $HELLO",
    ]
  }
}

I am now trying to add support for environment variables in the call to ExecInstance (https://github.com/deepankarsharma/packer-plugin-lxdapi/blob/main/utils/lxd_utils.go#L272).
Am using the following simple use case to test environment variables. The underlying code adds HELLO=WORLD to the environment. And later I try to first print the whole env and then echo value of $HELLO.

Following snippet is from https://github.com/deepankarsharma/packer-plugin-lxdapi/blob/main/example/build.pkr.hcl#L32

environment = {
      "HELLO": "WORLD"
    }

    inline = [
      "env",
      "echo $HELLO",
    ]

I can see that the HELLO variable does indeed show up in the env.

==> lxdapi.instance: stdout: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
==> lxdapi.instance: container=lxc
==> lxdapi.instance: HELLO=WORLD
==> lxdapi.instance: HOME=/root
==> lxdapi.instance: USER=root
==> lxdapi.instance: LANG=C.UTF-8

However I do not see any variable substitution taking place in the commands themselves as shown by the following output

==> lxdapi.instance: shell_exec: echo $HELLO
==> lxdapi.instance: rcode: 0
==> lxdapi.instance: stdout: $HELLO
==> lxdapi.instance:
==> lxdapi.instance: stderr:

Instead of the value of HELLO being substituted for $HELLO, I see an output of $HELLO in stdout.

Would appreciate any pointers on what I need to do to have variable substitution in commands passed in to the ExecInstance api.

lxc exec does not invoke a shell by default.

But you can do so by doing something like this:

lxc exec c1 -- /bin/bash -c "echo \$HOME"

Thanks, this is exactly what I was looking for!

1 Like