Packer: How do I add the literal braces {{}} in a string without calling a function?

Created on 27 Apr 2020  ยท  13Comments  ยท  Source: hashicorp/packer

Ansible supports a {{CWD}} macro.

Packer uses {{}} for functions and variables.

I don't see any way to escape the {{function_name}} syntax so that I can put in a literal {{CWD}}. I've tried a bunch of different things including using unicode braces (did not work), but they always end up being invalid or trying to call a non-existent CWD function which obviously breaks packer.

docs provisioneansible-remote question

Most helpful comment

Maybe I'm mistaken but I don't think this has anything to do with the provider? This is all Packer templating that's happening before the provider is even handed the string.

I got it working by using the ${PWD} environmental variable in bash and passing it into the script, but I think there's a deficiency in Packer's templating if you can't escape the {{'s required for an action.

All 13 comments

Hi @Jazzepi thanks for reaching out and sorry that you are running into trouble. If you share a sample build configuration we might be able to better help out here. Are you running into issues escaping the curly braces within the Packer build JSON file?

If you are trying to escape curly braces within the initial build configuration they will need to be doubly escaped \\{\\{CWD\\}\\}. Below is an example using the shell-local provisioner

{                                                                                                                                                  
  "builders": [{"type": "null", "communicator": "none"}],                                                                                                    
  "provisioners": [{"type": "shell-local", "inline": ["echo doubly escaped \\{\\{CWD\\}\\}"]}] 
}                                                

โ‡ถ  packer build build.json
null: output will be in this color.

==> null: Running local shell script: /tmp/packer-shell183239578
    null: doubly escaped {{CWD}}
Build 'null' finished.

==> Builds finished. The artifacts of successful builds are:
--> null: Did not export anything. This is the null builder

If this issue is occurring during the build, let's say within Ansible, then you may want to reach out to the mailing list or community for help. Issues opened here on the Packer issue tracker are only viewed by a small handful of developers who work on the tool, and we don't always have the most depth or experience when it comes to custom issues with particular build configurations.

@nywilken that's what I needed! {{CWD}} is a special macro for Ansible, but I couldn't get it past the templating engine in Packer. I didn't know that \\{\\{CWD\\}\\} was an option was available.

I think the documentation should be updated here (https://www.packer.io/docs/configuration/from-1.5/expressions.html#string-literals) with a mention of \\{ as that seems to be a specific exception to the rule that \\ = \. Without you posting this I would expect \\{ to resolve to \{ but instead it appears to resolve to {

@nywilken I was a little hasty. The snippet you provided doesn't work the way I'm looking for.

"extra_arguments": [ "--extra-vars", "roles_path=\\{\\{CWD\\}\\}/roles" ],
expands to
--extra-vars roles_path=\{\{CWD\}\}/roles
Which still has \'s in it

I need {{CWD}} in the resolved string

Hi @Jazzepi thanks for the update. I don't know enough about what the Ansible provisioner is doing here to say why the braces are being escaped. But seeing as you are trying to set the roles_path - unless this is just an example - you might want to checkout https://www.packer.io/docs/provisioners/ansible.html#roles_path which may be an option.

Maybe I'm mistaken but I don't think this has anything to do with the provider? This is all Packer templating that's happening before the provider is even handed the string.

I got it working by using the ${PWD} environmental variable in bash and passing it into the script, but I think there's a deficiency in Packer's templating if you can't escape the {{'s required for an action.

Is there any fix for this? It's extremely concerning for me that it looks like the templating library for packer does not have an escape mechanism for literal {{}}. This seems like a huge deficiency.

This is caused by a combination of two things:

  • Packer uses the golang text/template library as our templating engine, and there's not a really great way of escaping double brackets in the text library apart from putting them inside a string literal backtick. Golang doesn't allow you to escape those backticks, so that trick only works for one interpolation pass.
  • The values being passed into get extra_arguments get interpolated twice (once when the template is loaded and prepared, and once at provisioner runtime), so the escaping would have to be resilient to two different interpolation passes.

Sure, I guess this should be closed then. Maybe something should be noted in the documentation.

Sure, we can add a note to the docs that says you can't use jinja2 templating in the interpolated fields.

Is there a reason you aren't able to define the variables in the playbook itself? or in an inventory file that you pass into packer via the inventory_file or inventory_file_template options?

I was trying to pass the string {{CWD}} to ansible's command line roles_path argument. Now I'm not actually 100% sure that would work, but I think ansible would expand the {{CWD}} passed to roles_path to help it locate the roles in a specific directory. I believe that is not settable from a playbook, but I could be wrong.

Since bash exposes pwd as an environment variable I was able to dereference that in the variables block, but that was just lucky.

  "variables": {
    "pwd": "{{env `PWD`}}",
  }

https://docs.ansible.com/ansible/latest/reference_appendices/config.html#relative-paths-for-configuration

  "provisioners": [
    {
      "type": "ansible",
      "playbook_file": "./candidate-vm-playbook.yml",
      "extra_arguments": [ "--extra-vars", "roles_path={{user `pwd`}}/roles/" ],
    }
  ],

Got it. The Packer template engine has a pwd function built in so you don't even need to do the env var workaround to get the pwd that Packer is running from:

"extra_arguments": ["--extra-vars", "roles_path={{ pwd }}/roles"]

expands how you need too, I think: docs: https://www.packer.io/docs/templates/engine.html#pwd

@SwampDragons Thanks!

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings