-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
hcl2_upgrade: change handling of Go template escaping sequences #12068
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this approach. I left a nit pick and a question out of curiosity. That said, my concern about allowing unknown template variables is that users may have some invalid fields and Packer does not know they are invalid. Which can be confusing to the user when they validate or try to execute. I do wonder if there should be some sort of warning when executing with the with-annotations
flag?
I changed your input template to use {{ .Else }}
as the communicator type and then executed validate on it. You can see it is reporting for the type, when it is set to {{ .Else }}
.
~> go run . validate /tmp/input.json.pkr.hcl
Error: 4 error(s) occurred:
* Communicator type <no value> is invalid
* a Host must be specified, please reference your communicator documentation
* a Username must be specified, please reference your communicator documentation
* one authentication method must be specified, please reference your communicator documentation
on /tmp/input.json.pkr.hcl line 13:
(source code not available)
exit status 1
variable "envtest" {
type = string
default = "${env("Something")}"
}
variable "test" {
type = string
default = "{{ .Something }}"
}
# The "legacy_isotime" function has been provided for backwards compatability, but we recommend switching to the timestamp and formatdate functions.
source "null" "autogenerated_1" {
communicator = "{{ .Else }}"
}
build {
sources = ["source.null.autogenerated_1"]
provisioner "shell-local" {
inline = ["packer-${legacy_isotime("2006-01-02 03:04:05")}", "echo {{ .Vars }} sudo -E -S bash '{{ .Path }}'", "echo '${build.SSHPrivateKey}' > /tmp/packer-session.pem"]
}
}
Hey @nywilken, thanks for the review. To your point: I agree that this approach trades correctness for flexibility. |
Thinking about this a little more the majority of these go template variables that are being escaped are the builders specific, right? So to actually use them in HCL should they not be build.VariableName? thinking of https://developer.hashicorp.com/packer/docs/templates/hcl_templates/contextual-variables |
Very true, but from inside a source/build block, we can't use the HCL2 On another note, I can confirm this isn't accepted right now, trying to get the variable from within a source returns an error:
|
36c3116
to
5b5d80f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the original PR where the PASSTHROUGH logic was implemented and seeing how it fails. This change makes sense to me, and offers more flexibility than the current implementation.
In previous versions of hcl2_upgrade, we referenced a list of passthrough statements from the original JSON template to be replaced by their equivalent Go-template in HCL2. This works but requires us to explicitely accept every possible templated variable in order to not ever encounter <no value> in our generated HCL2 templates. This is suboptimal, hence this commit changes approach by pre-visting the AST from the original Go Template, escaping every sequence that is not covered by the list of functions we can migrate. Pipes are also excluded from this function.
Some literal strings without format-string directives nor arguments were littered around the hcl2_upgrade command's code, which is pointed out by the linters. Since they serve no purpose, we remove them.
5b5d80f
to
125e601
Compare
I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. |
Legacy JSON templates are essentially Go templates with extra limitations.
Leveraging this fact, we wrote the hcl2_upgrade command to migrate from JSON to HCL2 templates, and doing so, we interpret the template with a couple of fallbacks for things we don't want/can't replace.
This list being explicit, it means that whenever one's missing, it gets replaced by go template's default behaviour:
<no value>
.As pointed out in issue #11920, this is surprising for users. Also, this is a pretty rigid approach, as we must change the code and release a new version of Packer every time there's something else that pops up that wasn't already known and handled.
There's also the problem of nested values, due to the type of
PASSTHROUGH
, there can only be direct replacements from string to string. This falls through in cases like{{ .SourceAMITags.TagName }}
.This PR is an attempt at a more general fix: rather than relying on a manually populated list of strings to replace by themselves, we go for a two-pass approach, where we escape the go-template sequences
{{
and}}
so their contents are not interpreted afterwards, leaving out those we can handle.Closes #11920