From b522edca36cdbc33c3c24c8659d0b4e69682b4e0 Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Fri, 14 Jul 2023 17:11:54 -0400 Subject: [PATCH] hcl2_upgrade: add required_plugins in out template When a legacy JSON template references built-in plugins, we add them to the resulting template as a `required_plugins' block in HCL2. --- command/hcl2_upgrade.go | 85 ++++++++++++++++++- command/hcl2_upgrade_test.go | 1 + .../hcl2_upgrade/ami_test/expected.pkr.hcl | 8 ++ .../aws-access-config/expected.pkr.hcl | 6 ++ .../hcl2_upgrade/azure_shg/expected.pkr.hcl | 8 ++ .../bundled-plugin-used/expected.pkr.hcl | 29 +++++++ .../bundled-plugin-used/input.json | 11 +++ .../hcl2_upgrade/complete/expected.pkr.hcl | 6 ++ .../hcl2_upgrade/minimal/expected.pkr.hcl | 6 ++ .../hcl2_upgrade/source-name/expected.pkr.hcl | 6 ++ .../expected.pkr.hcl | 8 ++ .../without-annotations/expected.pkr.hcl | 6 ++ 12 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 command/test-fixtures/hcl2_upgrade/bundled-plugin-used/expected.pkr.hcl create mode 100644 command/test-fixtures/hcl2_upgrade/bundled-plugin-used/input.json diff --git a/command/hcl2_upgrade.go b/command/hcl2_upgrade.go index adba96d7f..08b7d2ad7 100644 --- a/command/hcl2_upgrade.go +++ b/command/hcl2_upgrade.go @@ -797,16 +797,93 @@ type PackerParser struct { } func (p *PackerParser) Parse(tpl *template.Template) error { + reqPlugins, err := p.generateRequiredPluginsBlock(tpl) + if err != nil { + return err + } + + if tpl.MinVersion == "" && reqPlugins == nil { + return nil + } + + fileContent := hclwrite.NewEmptyFile() + body := fileContent.Body() + packerBody := body.AppendNewBlock("packer", nil).Body() + if tpl.MinVersion != "" { - fileContent := hclwrite.NewEmptyFile() - body := fileContent.Body() - packerBody := body.AppendNewBlock("packer", nil).Body() packerBody.SetAttributeValue("required_version", cty.StringVal(fmt.Sprintf(">= %s", tpl.MinVersion))) - p.out = fileContent.Bytes() } + + if reqPlugins != nil { + packerBody.AppendBlock(reqPlugins) + } + + p.out = fileContent.Bytes() + return nil } +func gatherPluginsFromTemplate(tpl *template.Template) []string { + plugins := map[string]struct{}{} + + for _, b := range tpl.Builders { + for prefix, plugin := range knownPluginPrefixes { + if strings.HasPrefix(b.Type, prefix) { + plugins[plugin] = struct{}{} + } + } + } + + for _, p := range tpl.Provisioners { + for prefix, plugin := range knownPluginPrefixes { + if strings.HasPrefix(p.Type, prefix) { + plugins[plugin] = struct{}{} + } + } + } + + for _, pps := range tpl.PostProcessors { + for _, pp := range pps { + for prefix, plugin := range knownPluginPrefixes { + if strings.HasPrefix(pp.Type, prefix) { + plugins[plugin] = struct{}{} + } + } + } + } + + if len(plugins) == 0 { + return nil + } + + retPlugins := make([]string, 0, len(plugins)) + for plugin := range plugins { + retPlugins = append(retPlugins, plugin) + } + + sort.Strings(retPlugins) + + return retPlugins +} + +func (p *PackerParser) generateRequiredPluginsBlock(tpl *template.Template) (*hclwrite.Block, error) { + plugins := gatherPluginsFromTemplate(tpl) + if len(plugins) == 0 { + return nil, nil + } + + reqPlugins := hclwrite.NewBlock("required_plugins", nil) + for _, plugin := range plugins { + pluginBlock := cty.ObjectVal(map[string]cty.Value{ + "source": cty.StringVal(plugin), + "version": cty.StringVal("~> 1"), + }) + reqPlugins.Body().SetAttributeValue(strings.Replace(plugin, "github.com/hashicorp/", "", 1), pluginBlock) + } + + return reqPlugins, nil +} + func (p *PackerParser) Write(out *bytes.Buffer) { if len(p.out) > 0 { if p.WithAnnotations { diff --git a/command/hcl2_upgrade_test.go b/command/hcl2_upgrade_test.go index d2f92b6b6..afa8575aa 100644 --- a/command/hcl2_upgrade_test.go +++ b/command/hcl2_upgrade_test.go @@ -38,6 +38,7 @@ func Test_hcl2_upgrade(t *testing.T) { {folder: "complete-variables-with-template-engine", flags: []string{}}, {folder: "undeclared-variables", flags: []string{}, exitCode: 0}, {folder: "varfile-with-no-variables-block", flags: []string{}, exitCode: 0}, + {folder: "bundled-plugin-used", flags: []string{}, exitCode: 0}, } for _, tc := range tc { diff --git a/command/test-fixtures/hcl2_upgrade/ami_test/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/ami_test/expected.pkr.hcl index 72ccb2038..8a72f3551 100644 --- a/command/test-fixtures/hcl2_upgrade/ami_test/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/ami_test/expected.pkr.hcl @@ -1,3 +1,11 @@ +packer { + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + } +} source "amazon-ebs" "autogenerated_1" { run_tags = { diff --git a/command/test-fixtures/hcl2_upgrade/aws-access-config/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/aws-access-config/expected.pkr.hcl index 9ccbe9dc2..8c34e4735 100644 --- a/command/test-fixtures/hcl2_upgrade/aws-access-config/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/aws-access-config/expected.pkr.hcl @@ -1,5 +1,11 @@ packer { required_version = ">= 1.6.0" + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + } } variable "aws_access_key" { diff --git a/command/test-fixtures/hcl2_upgrade/azure_shg/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/azure_shg/expected.pkr.hcl index 089ce80a7..15d5a4ad3 100644 --- a/command/test-fixtures/hcl2_upgrade/azure_shg/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/azure_shg/expected.pkr.hcl @@ -1,3 +1,11 @@ +packer { + required_plugins { + azure = { + source = "github.com/hashicorp/azure" + version = "~> 1" + } + } +} source "azure-arm" "autogenerated_1" { shared_image_gallery { diff --git a/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/expected.pkr.hcl new file mode 100644 index 000000000..cce175b01 --- /dev/null +++ b/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/expected.pkr.hcl @@ -0,0 +1,29 @@ +packer { + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + ansible = { + source = "github.com/hashicorp/ansible" + version = "~> 1" + } + googlecompute = { + source = "github.com/hashicorp/googlecompute" + version = "~> 1" + } + } +} + +source "amazon-ebs" "autogenerated_1" { +} + +build { + sources = ["source.amazon-ebs.autogenerated_1"] + + provisioner "ansible-local" { + } + + post-processor "googlecompute-import" { + } +} diff --git a/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/input.json b/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/input.json new file mode 100644 index 000000000..917c7105e --- /dev/null +++ b/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/input.json @@ -0,0 +1,11 @@ +{ + "builders": [{ + "type": "amazon-ebs" + }], + "provisioners": [{ + "type": "ansible-local" + }], + "post-processors": [{ + "type": "googlecompute-import" + }] +} diff --git a/command/test-fixtures/hcl2_upgrade/complete/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/complete/expected.pkr.hcl index bcc669b64..a6800c672 100644 --- a/command/test-fixtures/hcl2_upgrade/complete/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/complete/expected.pkr.hcl @@ -14,6 +14,12 @@ # See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info packer { required_version = ">= 1.6.0" + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + } } # All generated input variables will be of 'string' type as this is how Packer JSON diff --git a/command/test-fixtures/hcl2_upgrade/minimal/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/minimal/expected.pkr.hcl index 2802e8e18..316293c39 100644 --- a/command/test-fixtures/hcl2_upgrade/minimal/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/minimal/expected.pkr.hcl @@ -14,6 +14,12 @@ # See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info packer { required_version = ">= 1.6.0" + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + } } # All generated input variables will be of 'string' type as this is how Packer JSON diff --git a/command/test-fixtures/hcl2_upgrade/source-name/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/source-name/expected.pkr.hcl index b5adf8ef5..c4145f7d1 100644 --- a/command/test-fixtures/hcl2_upgrade/source-name/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/source-name/expected.pkr.hcl @@ -14,6 +14,12 @@ # See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info packer { required_version = ">= 1.6.0" + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + } } # All generated input variables will be of 'string' type as this is how Packer JSON diff --git a/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/expected.pkr.hcl index a160d0c9e..16c3c21ca 100644 --- a/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/expected.pkr.hcl @@ -1,3 +1,11 @@ +packer { + required_plugins { + vsphere = { + source = "github.com/hashicorp/vsphere" + version = "~> 1" + } + } +} source "vsphere-clone" "autogenerated_1" { RAM_reserve_all = false diff --git a/command/test-fixtures/hcl2_upgrade/without-annotations/expected.pkr.hcl b/command/test-fixtures/hcl2_upgrade/without-annotations/expected.pkr.hcl index e332c21e0..414ebc55a 100644 --- a/command/test-fixtures/hcl2_upgrade/without-annotations/expected.pkr.hcl +++ b/command/test-fixtures/hcl2_upgrade/without-annotations/expected.pkr.hcl @@ -1,5 +1,11 @@ packer { required_version = ">= 1.6.0" + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1" + } + } } variable "aws_access_key" {