mirror of https://github.com/hashicorp/packer
Implicit required_plugin blocks (#10732)
* used components that don't have a required_plugin block will make Packer 'implicitly' require those. These components are manually selected and commented for now. * add tests * docspull/10821/head
parent
70ceed1110
commit
0e3fcb589b
@ -0,0 +1,11 @@
|
||||
package hcl2template
|
||||
|
||||
// ComponentKind helps enumerate what kind of components exist in this Package.
|
||||
type ComponentKind int
|
||||
|
||||
const (
|
||||
Builder ComponentKind = iota
|
||||
Provisioner
|
||||
PostProcessor
|
||||
Datasource
|
||||
)
|
||||
@ -0,0 +1,363 @@
|
||||
package hcl2template
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/packer/hcl2template/addrs"
|
||||
)
|
||||
|
||||
func TestPackerConfig_required_plugin_parse(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg PackerConfig
|
||||
requirePlugins string
|
||||
restOfTemplate string
|
||||
wantDiags bool
|
||||
wantConfig PackerConfig
|
||||
}{
|
||||
{"required_plugin", PackerConfig{parser: getBasicParser()}, `
|
||||
packer {
|
||||
required_plugins {
|
||||
amazon = {
|
||||
source = "github.com/hashicorp/amazon"
|
||||
version = "~> v1.2.3"
|
||||
}
|
||||
}
|
||||
} `, `
|
||||
source "amazon-ebs" "example" {
|
||||
}
|
||||
`, false, PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"amazon": {
|
||||
Name: "amazon",
|
||||
Source: "github.com/hashicorp/amazon",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "hashicorp", Type: "amazon"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: mustVersionConstraints(version.NewConstraint("~> v1.2.3")),
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyExplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
{"required_plugin_forked_no_redirect", PackerConfig{parser: getBasicParser()}, `
|
||||
packer {
|
||||
required_plugins {
|
||||
amazon = {
|
||||
source = "github.com/azr/amazon"
|
||||
version = "~> v1.2.3"
|
||||
}
|
||||
}
|
||||
} `, `
|
||||
source "amazon-chroot" "example" {
|
||||
}
|
||||
`, false, PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"amazon": {
|
||||
Name: "amazon",
|
||||
Source: "github.com/azr/amazon",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "azr", Type: "amazon"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: mustVersionConstraints(version.NewConstraint("~> v1.2.3")),
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyExplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
{"required_plugin_forked", PackerConfig{
|
||||
parser: getBasicParser(func(p *Parser) {
|
||||
p.PluginConfig.BuilderRedirects = map[string]string{
|
||||
"amazon-chroot": "github.com/hashicorp/amazon",
|
||||
}
|
||||
},
|
||||
)}, `
|
||||
packer {
|
||||
required_plugins {
|
||||
amazon = {
|
||||
source = "github.com/azr/amazon"
|
||||
version = "~> v1.2.3"
|
||||
}
|
||||
}
|
||||
} `, `
|
||||
source "amazon-chroot" "example" {
|
||||
}
|
||||
`, false, PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"amazon": {
|
||||
Name: "amazon",
|
||||
Source: "github.com/azr/amazon",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "azr", Type: "amazon"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: mustVersionConstraints(version.NewConstraint("~> v1.2.3")),
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyExplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
{"missing-required-plugin-for-pre-defined-builder", PackerConfig{
|
||||
parser: getBasicParser(func(p *Parser) {
|
||||
p.PluginConfig.BuilderRedirects = map[string]string{
|
||||
"amazon-ebs": "github.com/hashicorp/amazon",
|
||||
}
|
||||
},
|
||||
)},
|
||||
`
|
||||
packer {
|
||||
}`, `
|
||||
# amazon-ebs is mocked in getBasicParser()
|
||||
source "amazon-ebs" "example" {
|
||||
}
|
||||
`,
|
||||
false,
|
||||
PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: nil,
|
||||
},
|
||||
}},
|
||||
{"missing-required-plugin-for-builder", PackerConfig{
|
||||
parser: getBasicParser(func(p *Parser) {
|
||||
p.PluginConfig.BuilderRedirects = map[string]string{
|
||||
"amazon-chroot": "github.com/hashicorp/amazon",
|
||||
}
|
||||
},
|
||||
)},
|
||||
`
|
||||
packer {
|
||||
}`, `
|
||||
source "amazon-chroot" "example" {
|
||||
}
|
||||
`,
|
||||
false,
|
||||
PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"amazon": {
|
||||
Name: "amazon",
|
||||
Source: "github.com/hashicorp/amazon",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "hashicorp", Type: "amazon"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: nil,
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyImplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
{"missing-required-plugin-for-provisioner", PackerConfig{
|
||||
parser: getBasicParser(func(p *Parser) {
|
||||
p.PluginConfig.ProvisionerRedirects = map[string]string{
|
||||
"ansible-local": "github.com/ansible/ansible",
|
||||
}
|
||||
},
|
||||
)},
|
||||
`
|
||||
packer {
|
||||
}`, `
|
||||
build {
|
||||
provisioner "ansible-local" {}
|
||||
}
|
||||
`,
|
||||
false,
|
||||
PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"ansible": {
|
||||
Name: "ansible",
|
||||
Source: "github.com/ansible/ansible",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "ansible", Type: "ansible"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: nil,
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyImplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
{"missing-required-plugin-for-post-processor", PackerConfig{
|
||||
parser: getBasicParser(func(p *Parser) {
|
||||
p.PluginConfig.PostProcessorRedirects = map[string]string{
|
||||
"docker-push": "github.com/hashicorp/docker",
|
||||
}
|
||||
},
|
||||
)},
|
||||
`
|
||||
packer {
|
||||
}`, `
|
||||
build {
|
||||
post-processor "docker-push" {}
|
||||
}
|
||||
`,
|
||||
false,
|
||||
PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"docker": {
|
||||
Name: "docker",
|
||||
Source: "github.com/hashicorp/docker",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "hashicorp", Type: "docker"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: nil,
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyImplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
{"missing-required-plugin-for-nested-post-processor", PackerConfig{
|
||||
parser: getBasicParser(func(p *Parser) {
|
||||
p.PluginConfig.PostProcessorRedirects = map[string]string{
|
||||
"docker-push": "github.com/hashicorp/docker",
|
||||
}
|
||||
},
|
||||
)},
|
||||
`
|
||||
packer {
|
||||
}`, `
|
||||
build {
|
||||
post-processors {
|
||||
post-processor "docker-push" {
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
false,
|
||||
PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"docker": {
|
||||
Name: "docker",
|
||||
Source: "github.com/hashicorp/docker",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "hashicorp", Type: "docker"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: nil,
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyImplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
|
||||
{"required-plugin-renamed", PackerConfig{
|
||||
parser: getBasicParser(func(p *Parser) {
|
||||
p.PluginConfig.BuilderRedirects = map[string]string{
|
||||
"amazon-chroot": "github.com/hashicorp/amazon",
|
||||
}
|
||||
},
|
||||
)},
|
||||
`
|
||||
packer {
|
||||
required_plugins {
|
||||
amazon-v1 = {
|
||||
source = "github.com/hashicorp/amazon"
|
||||
version = "~> v1.0"
|
||||
}
|
||||
}
|
||||
}`, `
|
||||
source "amazon-v1-chroot" "example" {
|
||||
}
|
||||
source "amazon-chroot" "example" {
|
||||
}
|
||||
`,
|
||||
false,
|
||||
PackerConfig{
|
||||
Packer: struct {
|
||||
VersionConstraints []VersionConstraint
|
||||
RequiredPlugins []*RequiredPlugins
|
||||
}{
|
||||
RequiredPlugins: []*RequiredPlugins{
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"amazon-v1": {
|
||||
Name: "amazon-v1",
|
||||
Source: "github.com/hashicorp/amazon",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "hashicorp", Type: "amazon"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: mustVersionConstraints(version.NewConstraint("~> v1.0")),
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyExplicit,
|
||||
},
|
||||
}},
|
||||
{RequiredPlugins: map[string]*RequiredPlugin{
|
||||
"amazon": {
|
||||
Name: "amazon",
|
||||
Source: "github.com/hashicorp/amazon",
|
||||
Type: &addrs.Plugin{Hostname: "github.com", Namespace: "hashicorp", Type: "amazon"},
|
||||
Requirement: VersionConstraint{
|
||||
Required: nil,
|
||||
},
|
||||
PluginDependencyReason: PluginDependencyImplicit,
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cfg := tt.cfg
|
||||
file, diags := cfg.parser.ParseHCL([]byte(tt.requirePlugins), "required_plugins.pkr.hcl")
|
||||
if len(diags) > 0 {
|
||||
t.Fatal(diags)
|
||||
}
|
||||
if diags := cfg.decodeRequiredPluginsBlock(file); len(diags) > 0 {
|
||||
t.Fatal(diags)
|
||||
}
|
||||
|
||||
rest, diags := cfg.parser.ParseHCL([]byte(tt.restOfTemplate), "rest.pkr.hcl")
|
||||
if len(diags) > 0 {
|
||||
t.Fatal(diags)
|
||||
}
|
||||
if gotDiags := cfg.decodeImplicitRequiredPluginsBlocks(rest); (len(gotDiags) > 0) != tt.wantDiags {
|
||||
t.Fatal(gotDiags)
|
||||
}
|
||||
if diff := cmp.Diff(tt.wantConfig, cfg, cmpOpts...); diff != "" {
|
||||
t.Errorf("PackerConfig.inferImplicitRequiredPluginFromBlocks() unexpected PackerConfig: %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue