hcl2_upgrade update (#10221)
* handle template_dir, pwd funcs, handle min_packer_version * gotpl packer_version becomes hcl2 packer.version * uuid becomes hcl2 uuidv4 * test code with emojis * handle all cases were we cannot guess what the argument was * handle clean_resource_name cases * up docs
This commit is contained in:
parent
2bf912bddf
commit
17ec88246f
|
@ -64,10 +64,19 @@ const (
|
||||||
# once they also need to be in the same folder. 'packer inspect folder/'
|
# once they also need to be in the same folder. 'packer inspect folder/'
|
||||||
# will describe to you what is in that folder.
|
# will describe to you what is in that folder.
|
||||||
|
|
||||||
|
# Avoid mixing go templating calls ( for example ` + "```{{ upper(`string`) }}```" + ` )
|
||||||
|
# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
|
||||||
|
# executed together and the outcome will be unknown.
|
||||||
|
`
|
||||||
|
inputVarHeader = `
|
||||||
# All generated input variables will be of 'string' type as this is how Packer JSON
|
# All generated input variables will be of 'string' type as this is how Packer JSON
|
||||||
# views them; you can change their type later on. Read the variables type
|
# views them; you can change their type later on. Read the variables type
|
||||||
# constraints documentation
|
# constraints documentation
|
||||||
# https://www.packer.io/docs/from-1.5/variables#type-constraints for more info.
|
# https://www.packer.io/docs/from-1.5/variables#type-constraints for more info.
|
||||||
|
`
|
||||||
|
|
||||||
|
packerBlockHeader = `
|
||||||
|
# See https://www.packer.io/docs/from-1.5/blocks/packer for more info
|
||||||
`
|
`
|
||||||
|
|
||||||
sourcesHeader = `
|
sourcesHeader = `
|
||||||
|
@ -112,10 +121,22 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
|
||||||
|
|
||||||
core := hdl.(*CoreWrapper).Core
|
core := hdl.(*CoreWrapper).Core
|
||||||
if err := core.Initialize(); err != nil {
|
if err := core.Initialize(); err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Initialization error, continuing: %v", err))
|
c.Ui.Error(fmt.Sprintf("Ignoring following initialization error: %v", err))
|
||||||
}
|
}
|
||||||
tpl := core.Template
|
tpl := core.Template
|
||||||
|
|
||||||
|
// Packer section
|
||||||
|
if tpl.MinVersion != "" {
|
||||||
|
out.Write([]byte(packerBlockHeader))
|
||||||
|
fileContent := hclwrite.NewEmptyFile()
|
||||||
|
body := fileContent.Body()
|
||||||
|
packerBody := body.AppendNewBlock("packer", nil).Body()
|
||||||
|
packerBody.SetAttributeValue("required_version", cty.StringVal(fmt.Sprintf(">= %s", tpl.MinVersion)))
|
||||||
|
out.Write(fileContent.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Write([]byte(inputVarHeader))
|
||||||
|
|
||||||
// Output variables section
|
// Output variables section
|
||||||
|
|
||||||
variables := []*template.Variable{}
|
variables := []*template.Variable{}
|
||||||
|
@ -266,12 +287,29 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UnhandleableArgumentError struct {
|
||||||
|
Call string
|
||||||
|
Correspondance string
|
||||||
|
Docs string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uc UnhandleableArgumentError) Error() string {
|
||||||
|
return fmt.Sprintf(`unhandled %q call:
|
||||||
|
# there is no way to automatically upgrade the %[1]q call.
|
||||||
|
# Please manually upgrade to %s
|
||||||
|
# Visit %s for more infos.`, uc.Call, uc.Correspondance, uc.Docs)
|
||||||
|
}
|
||||||
|
|
||||||
// transposeTemplatingCalls executes parts of blocks as go template files and replaces
|
// transposeTemplatingCalls executes parts of blocks as go template files and replaces
|
||||||
// their result with their hcl2 variant. If something goes wrong the template
|
// their result with their hcl2 variant. If something goes wrong the template
|
||||||
// containing the go template string is returned.
|
// containing the go template string is returned.
|
||||||
func transposeTemplatingCalls(s []byte) []byte {
|
func transposeTemplatingCalls(s []byte) []byte {
|
||||||
fallbackReturn := func(err error) []byte {
|
fallbackReturn := func(err error) []byte {
|
||||||
return append([]byte(fmt.Sprintf("\n#could not parse template for following block: %q\n", err)), s...)
|
if strings.Contains(err.Error(), "unhandled") {
|
||||||
|
return append([]byte(fmt.Sprintf("\n# %s\n", err)), s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return append([]byte(fmt.Sprintf("\n# could not parse template for following block: %q\n", err)), s...)
|
||||||
}
|
}
|
||||||
funcMap := texttemplate.FuncMap{
|
funcMap := texttemplate.FuncMap{
|
||||||
"timestamp": func() string {
|
"timestamp": func() string {
|
||||||
|
@ -289,9 +327,71 @@ func transposeTemplatingCalls(s []byte) []byte {
|
||||||
"build": func(a string) string {
|
"build": func(a string) string {
|
||||||
return fmt.Sprintf("${build.%s}", a)
|
return fmt.Sprintf("${build.%s}", a)
|
||||||
},
|
},
|
||||||
|
"template_dir": func() string {
|
||||||
|
return fmt.Sprintf("${path.root}")
|
||||||
|
},
|
||||||
|
"pwd": func() string {
|
||||||
|
return fmt.Sprintf("${path.cwd}")
|
||||||
|
},
|
||||||
|
"packer_version": func() string {
|
||||||
|
return fmt.Sprintf("${packer.version}")
|
||||||
|
},
|
||||||
|
"uuid": func() string {
|
||||||
|
return fmt.Sprintf("${uuidv4()}")
|
||||||
|
},
|
||||||
|
"lower": func(_ string) (string, error) {
|
||||||
|
return "", UnhandleableArgumentError{
|
||||||
|
"lower",
|
||||||
|
"`lower(var.example)`",
|
||||||
|
"https://www.packer.io/docs/from-1.5/functions/string/lower",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"upper": func(_ string) (string, error) {
|
||||||
|
return "", UnhandleableArgumentError{
|
||||||
|
"upper",
|
||||||
|
"`upper(var.example)`",
|
||||||
|
"https://www.packer.io/docs/from-1.5/functions/string/upper",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"split": func(_, _ string, _ int) (string, error) {
|
||||||
|
return "", UnhandleableArgumentError{
|
||||||
|
"split",
|
||||||
|
"`split(separator, string)`",
|
||||||
|
"https://www.packer.io/docs/from-1.5/functions/string/split",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"replace": func(_, _, _ string, _ int) (string, error) {
|
||||||
|
return "", UnhandleableArgumentError{
|
||||||
|
"replace",
|
||||||
|
"`replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`",
|
||||||
|
"https://www.packer.io/docs/from-1.5/functions/string/replace or https://www.packer.io/docs/from-1.5/functions/string/regex_replace",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"replace_all": func(_, _, _ string) (string, error) {
|
||||||
|
return "", UnhandleableArgumentError{
|
||||||
|
"replace_all",
|
||||||
|
"`replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`",
|
||||||
|
"https://www.packer.io/docs/from-1.5/functions/string/replace or https://www.packer.io/docs/from-1.5/functions/string/regex_replace",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"clean_resource_name": func(_ string) (string, error) {
|
||||||
|
return "", UnhandleableArgumentError{
|
||||||
|
"clean_resource_name",
|
||||||
|
"use custom validation rules, `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`",
|
||||||
|
"https://packer.io/docs/from-1.5/variables#custom-validation-rules" +
|
||||||
|
" , https://www.packer.io/docs/from-1.5/functions/string/replace" +
|
||||||
|
" or https://www.packer.io/docs/from-1.5/functions/string/regex_replace",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"build_name": func() string {
|
||||||
|
return fmt.Sprintf("${build.name}")
|
||||||
|
},
|
||||||
|
"build_type": func() string {
|
||||||
|
return fmt.Sprintf("${build.type}")
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
tpl, err := texttemplate.New("generated").
|
tpl, err := texttemplate.New("hcl2_upgrade").
|
||||||
Funcs(funcMap).
|
Funcs(funcMap).
|
||||||
Parse(string(s))
|
Parse(string(s))
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,15 @@
|
||||||
# once they also need to be in the same folder. 'packer inspect folder/'
|
# once they also need to be in the same folder. 'packer inspect folder/'
|
||||||
# will describe to you what is in that folder.
|
# will describe to you what is in that folder.
|
||||||
|
|
||||||
|
# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
|
||||||
|
# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
|
||||||
|
# executed together and the outcome will be unknown.
|
||||||
|
|
||||||
|
# See https://www.packer.io/docs/from-1.5/blocks/packer for more info
|
||||||
|
packer {
|
||||||
|
required_version = ">= 1.6.0"
|
||||||
|
}
|
||||||
|
|
||||||
# All generated input variables will be of 'string' type as this is how Packer JSON
|
# All generated input variables will be of 'string' type as this is how Packer JSON
|
||||||
# views them; you can change their type later on. Read the variables type
|
# views them; you can change their type later on. Read the variables type
|
||||||
# constraints documentation
|
# constraints documentation
|
||||||
|
@ -27,6 +36,12 @@ variable "aws_secret_key" {
|
||||||
sensitive = true
|
sensitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "secret_account" {
|
||||||
|
type = string
|
||||||
|
default = "🤷"
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
# "timestamp" template function replacement
|
# "timestamp" template function replacement
|
||||||
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
|
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
|
||||||
|
|
||||||
|
@ -77,14 +92,61 @@ build {
|
||||||
sources = ["source.amazon-ebs.autogenerated_1"]
|
sources = ["source.amazon-ebs.autogenerated_1"]
|
||||||
|
|
||||||
provisioner "shell" {
|
provisioner "shell" {
|
||||||
inline = ["echo ${var.secret_account}", "echo ${build.ID}", "echo ${build.SSHPrivateKey}", "sleep 100000"]
|
except = ["amazon-ebs"]
|
||||||
|
inline = ["echo ${var.secret_account}", "echo ${build.ID}", "echo ${build.SSHPublicKey} | head -c 14", "echo ${path.root} is not ${path.cwd}", "echo ${packer.version}", "echo ${uuidv4()}"]
|
||||||
max_retries = "5"
|
max_retries = "5"
|
||||||
only = ["amazon-ebs"]
|
}
|
||||||
timeout = "5s"
|
|
||||||
|
# template: hcl2_upgrade:2:38: executing "hcl2_upgrade" at <clean_resource_name>: error calling clean_resource_name: unhandled "clean_resource_name" call:
|
||||||
|
# there is no way to automatically upgrade the "clean_resource_name" call.
|
||||||
|
# Please manually upgrade to use custom validation rules, `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
|
||||||
|
# Visit https://packer.io/docs/from-1.5/variables#custom-validation-rules , https://www.packer.io/docs/from-1.5/functions/string/replace or https://www.packer.io/docs/from-1.5/functions/string/regex_replace for more infos.
|
||||||
|
provisioner "shell" {
|
||||||
|
inline = ["echo mybuild-{{isotime | clean_resource_name}}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# template: hcl2_upgrade:2:35: executing "hcl2_upgrade" at <lower>: error calling lower: unhandled "lower" call:
|
||||||
|
# there is no way to automatically upgrade the "lower" call.
|
||||||
|
# Please manually upgrade to `lower(var.example)`
|
||||||
|
# Visit https://www.packer.io/docs/from-1.5/functions/string/lower for more infos.
|
||||||
|
provisioner "shell" {
|
||||||
|
inline = ["echo {{ `SOMETHING` | lower }}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# template: hcl2_upgrade:2:35: executing "hcl2_upgrade" at <upper>: error calling upper: unhandled "upper" call:
|
||||||
|
# there is no way to automatically upgrade the "upper" call.
|
||||||
|
# Please manually upgrade to `upper(var.example)`
|
||||||
|
# Visit https://www.packer.io/docs/from-1.5/functions/string/upper for more infos.
|
||||||
|
provisioner "shell" {
|
||||||
|
inline = ["echo {{ `something` | upper }}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# template: hcl2_upgrade:2:21: executing "hcl2_upgrade" at <split `some-string` `-` 0>: error calling split: unhandled "split" call:
|
||||||
|
# there is no way to automatically upgrade the "split" call.
|
||||||
|
# Please manually upgrade to `split(separator, string)`
|
||||||
|
# Visit https://www.packer.io/docs/from-1.5/functions/string/split for more infos.
|
||||||
|
provisioner "shell" {
|
||||||
|
inline = ["echo {{ split `some-string` `-` 0 }}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# template: hcl2_upgrade:2:21: executing "hcl2_upgrade" at <replace_all `-` `/` build_name>: error calling replace_all: unhandled "replace_all" call:
|
||||||
|
# there is no way to automatically upgrade the "replace_all" call.
|
||||||
|
# Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
|
||||||
|
# Visit https://www.packer.io/docs/from-1.5/functions/string/replace or https://www.packer.io/docs/from-1.5/functions/string/regex_replace for more infos.
|
||||||
|
provisioner "shell" {
|
||||||
|
inline = ["echo {{ replace_all `-` `/` build_name }}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# template: hcl2_upgrade:2:21: executing "hcl2_upgrade" at <replace `some-string` `-` `/` 1>: error calling replace: unhandled "replace" call:
|
||||||
|
# there is no way to automatically upgrade the "replace" call.
|
||||||
|
# Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
|
||||||
|
# Visit https://www.packer.io/docs/from-1.5/functions/string/replace or https://www.packer.io/docs/from-1.5/functions/string/regex_replace for more infos.
|
||||||
|
provisioner "shell" {
|
||||||
|
inline = ["echo {{ replace `some-string` `-` `/` 1 }}"]
|
||||||
}
|
}
|
||||||
provisioner "shell-local" {
|
provisioner "shell-local" {
|
||||||
except = ["amazon-ebs"]
|
|
||||||
inline = ["sleep 100000"]
|
inline = ["sleep 100000"]
|
||||||
|
only = ["amazon-ebs"]
|
||||||
timeout = "5s"
|
timeout = "5s"
|
||||||
}
|
}
|
||||||
post-processor "amazon-import" {
|
post-processor "amazon-import" {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
|
"min_packer_version": "1.6.0",
|
||||||
"variables": {
|
"variables": {
|
||||||
|
"secret_account": "🤷",
|
||||||
"aws_region": null,
|
"aws_region": null,
|
||||||
"aws_secret_key": "",
|
"aws_secret_key": "",
|
||||||
"aws_access_key": ""
|
"aws_access_key": ""
|
||||||
|
@ -7,6 +9,7 @@
|
||||||
"sensitive-variables": [
|
"sensitive-variables": [
|
||||||
"aws_secret_key",
|
"aws_secret_key",
|
||||||
"aws_access_key",
|
"aws_access_key",
|
||||||
|
"secret_account",
|
||||||
"potato"
|
"potato"
|
||||||
],
|
],
|
||||||
"builders": [
|
"builders": [
|
||||||
|
@ -62,21 +65,58 @@
|
||||||
"provisioners": [
|
"provisioners": [
|
||||||
{
|
{
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"only": [
|
"except": [
|
||||||
"amazon-ebs"
|
"amazon-ebs"
|
||||||
],
|
],
|
||||||
"max_retries": 5,
|
"max_retries": 5,
|
||||||
"timeout": "5s",
|
|
||||||
"inline": [
|
"inline": [
|
||||||
"echo {{ user `secret_account` }}",
|
"echo {{ user `secret_account` }}",
|
||||||
"echo {{ build `ID` }}",
|
"echo {{ build `ID` }}",
|
||||||
"echo {{ build `SSHPrivateKey` }}",
|
"echo {{ build `SSHPublicKey` }} | head -c 14",
|
||||||
"sleep 100000"
|
"echo {{ template_dir }} is not {{ pwd }}",
|
||||||
|
"echo {{ packer_version }}",
|
||||||
|
"echo {{ uuid }}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"inline": [
|
||||||
|
"echo mybuild-{{isotime | clean_resource_name}}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"inline": [
|
||||||
|
"echo {{ `SOMETHING` | lower }}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"inline": [
|
||||||
|
"echo {{ `something` | upper }}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"inline": [
|
||||||
|
"echo {{ split `some-string` `-` 0 }}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"inline": [
|
||||||
|
"echo {{ replace_all `-` `/` build_name }}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"inline": [
|
||||||
|
"echo {{ replace `some-string` `-` `/` 1 }}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "shell-local",
|
"type": "shell-local",
|
||||||
"except": [
|
"only": [
|
||||||
"amazon-ebs"
|
"amazon-ebs"
|
||||||
],
|
],
|
||||||
"timeout": "5s",
|
"timeout": "5s",
|
||||||
|
|
Loading…
Reference in New Issue