2019-12-17 05:25:56 -05:00
|
|
|
package hcl2template
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
|
|
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
|
|
"github.com/hashicorp/hcl/v2/hclparse"
|
Hcl2 input variables, local variables and functions (#8588)
Mainly redefine or reused what Terraform did.
* allow to used `variables`, `variable` and `local` blocks
* import the following functions and their docs from Terraform: abs, abspath, basename, base64decode, base64encode, bcrypt, can, ceil, chomp, chunklist, cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, coalesce, coalescelist, compact, concat, contains, convert, csvdecode, dirname, distinct, element, file, fileexists, fileset, flatten, floor, format, formatdate, formatlist, indent, index, join, jsondecode, jsonencode, keys, length, log, lookup, lower, max, md5, merge, min, parseint, pathexpand, pow, range, reverse, rsadecrypt, setintersection, setproduct, setunion, sha1, sha256, sha512, signum, slice, sort, split, strrev, substr, timestamp, timeadd, title, trim, trimprefix, trimspace, trimsuffix, try, upper, urlencode, uuidv4, uuidv5, values, yamldecode, yamlencode, zipmap.
2020-02-06 05:49:21 -05:00
|
|
|
. "github.com/hashicorp/packer/hcl2template/internal"
|
2019-12-17 05:25:56 -05:00
|
|
|
"github.com/hashicorp/packer/helper/config"
|
|
|
|
"github.com/hashicorp/packer/packer"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
)
|
|
|
|
|
|
|
|
func getBasicParser() *Parser {
|
|
|
|
return &Parser{
|
|
|
|
Parser: hclparse.NewParser(),
|
Hcl2 input variables, local variables and functions (#8588)
Mainly redefine or reused what Terraform did.
* allow to used `variables`, `variable` and `local` blocks
* import the following functions and their docs from Terraform: abs, abspath, basename, base64decode, base64encode, bcrypt, can, ceil, chomp, chunklist, cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, coalesce, coalescelist, compact, concat, contains, convert, csvdecode, dirname, distinct, element, file, fileexists, fileset, flatten, floor, format, formatdate, formatlist, indent, index, join, jsondecode, jsonencode, keys, length, log, lookup, lower, max, md5, merge, min, parseint, pathexpand, pow, range, reverse, rsadecrypt, setintersection, setproduct, setunion, sha1, sha256, sha512, signum, slice, sort, split, strrev, substr, timestamp, timeadd, title, trim, trimprefix, trimspace, trimsuffix, try, upper, urlencode, uuidv4, uuidv5, values, yamldecode, yamlencode, zipmap.
2020-02-06 05:49:21 -05:00
|
|
|
BuilderSchemas: packer.MapOfBuilder{
|
|
|
|
"amazon-ebs": func() (packer.Builder, error) { return &MockBuilder{}, nil },
|
|
|
|
"virtualbox-iso": func() (packer.Builder, error) { return &MockBuilder{}, nil },
|
|
|
|
},
|
|
|
|
ProvisionersSchemas: packer.MapOfProvisioner{
|
|
|
|
"shell": func() (packer.Provisioner, error) { return &MockProvisioner{}, nil },
|
|
|
|
"file": func() (packer.Provisioner, error) { return &MockProvisioner{}, nil },
|
|
|
|
},
|
|
|
|
PostProcessorsSchemas: packer.MapOfPostProcessor{
|
|
|
|
"amazon-import": func() (packer.PostProcessor, error) { return &MockPostProcessor{}, nil },
|
|
|
|
},
|
2019-12-17 05:25:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type parseTestArgs struct {
|
|
|
|
filename string
|
Hcl2 input variables, local variables and functions (#8588)
Mainly redefine or reused what Terraform did.
* allow to used `variables`, `variable` and `local` blocks
* import the following functions and their docs from Terraform: abs, abspath, basename, base64decode, base64encode, bcrypt, can, ceil, chomp, chunklist, cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, coalesce, coalescelist, compact, concat, contains, convert, csvdecode, dirname, distinct, element, file, fileexists, fileset, flatten, floor, format, formatdate, formatlist, indent, index, join, jsondecode, jsonencode, keys, length, log, lookup, lower, max, md5, merge, min, parseint, pathexpand, pow, range, reverse, rsadecrypt, setintersection, setproduct, setunion, sha1, sha256, sha512, signum, slice, sort, split, strrev, substr, timestamp, timeadd, title, trim, trimprefix, trimspace, trimsuffix, try, upper, urlencode, uuidv4, uuidv5, values, yamldecode, yamlencode, zipmap.
2020-02-06 05:49:21 -05:00
|
|
|
vars map[string]string
|
2019-12-17 05:25:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
type parseTest struct {
|
|
|
|
name string
|
|
|
|
parser *Parser
|
|
|
|
args parseTestArgs
|
|
|
|
|
|
|
|
parseWantCfg *PackerConfig
|
|
|
|
parseWantDiags bool
|
|
|
|
parseWantDiagHasErrors bool
|
|
|
|
|
|
|
|
getBuildsWantBuilds []packer.Build
|
|
|
|
getBuildsWantDiags bool
|
|
|
|
// getBuildsWantDiagHasErrors bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func testParse(t *testing.T, tests []parseTest) {
|
2019-12-17 10:46:36 -05:00
|
|
|
t.Helper()
|
2019-12-17 05:25:56 -05:00
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
Hcl2 input variables, local variables and functions (#8588)
Mainly redefine or reused what Terraform did.
* allow to used `variables`, `variable` and `local` blocks
* import the following functions and their docs from Terraform: abs, abspath, basename, base64decode, base64encode, bcrypt, can, ceil, chomp, chunklist, cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, coalesce, coalescelist, compact, concat, contains, convert, csvdecode, dirname, distinct, element, file, fileexists, fileset, flatten, floor, format, formatdate, formatlist, indent, index, join, jsondecode, jsonencode, keys, length, log, lookup, lower, max, md5, merge, min, parseint, pathexpand, pow, range, reverse, rsadecrypt, setintersection, setproduct, setunion, sha1, sha256, sha512, signum, slice, sort, split, strrev, substr, timestamp, timeadd, title, trim, trimprefix, trimspace, trimsuffix, try, upper, urlencode, uuidv4, uuidv5, values, yamldecode, yamlencode, zipmap.
2020-02-06 05:49:21 -05:00
|
|
|
gotCfg, gotDiags := tt.parser.parse(tt.args.filename, tt.args.vars)
|
2019-12-17 05:25:56 -05:00
|
|
|
if tt.parseWantDiags == (gotDiags == nil) {
|
|
|
|
t.Fatalf("Parser.parse() unexpected diagnostics. %s", gotDiags)
|
|
|
|
}
|
|
|
|
if tt.parseWantDiagHasErrors != gotDiags.HasErrors() {
|
|
|
|
t.Fatalf("Parser.parse() unexpected diagnostics HasErrors. %s", gotDiags)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(tt.parseWantCfg, gotCfg,
|
Hcl2 input variables, local variables and functions (#8588)
Mainly redefine or reused what Terraform did.
* allow to used `variables`, `variable` and `local` blocks
* import the following functions and their docs from Terraform: abs, abspath, basename, base64decode, base64encode, bcrypt, can, ceil, chomp, chunklist, cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, coalesce, coalescelist, compact, concat, contains, convert, csvdecode, dirname, distinct, element, file, fileexists, fileset, flatten, floor, format, formatdate, formatlist, indent, index, join, jsondecode, jsonencode, keys, length, log, lookup, lower, max, md5, merge, min, parseint, pathexpand, pow, range, reverse, rsadecrypt, setintersection, setproduct, setunion, sha1, sha256, sha512, signum, slice, sort, split, strrev, substr, timestamp, timeadd, title, trim, trimprefix, trimspace, trimsuffix, try, upper, urlencode, uuidv4, uuidv5, values, yamldecode, yamlencode, zipmap.
2020-02-06 05:49:21 -05:00
|
|
|
cmpopts.IgnoreUnexported(
|
|
|
|
cty.Value{},
|
|
|
|
cty.Type{},
|
|
|
|
Variable{},
|
|
|
|
SourceBlock{},
|
|
|
|
ProvisionerBlock{},
|
|
|
|
PostProcessorBlock{},
|
|
|
|
),
|
2019-12-17 05:25:56 -05:00
|
|
|
cmpopts.IgnoreTypes(HCL2Ref{}),
|
|
|
|
cmpopts.IgnoreTypes([]hcl.Range{}),
|
|
|
|
cmpopts.IgnoreTypes(hcl.Range{}),
|
|
|
|
cmpopts.IgnoreInterfaces(struct{ hcl.Expression }{}),
|
|
|
|
cmpopts.IgnoreInterfaces(struct{ hcl.Body }{}),
|
|
|
|
); diff != "" {
|
|
|
|
t.Fatalf("Parser.parse() wrong packer config. %s", diff)
|
|
|
|
}
|
2020-02-21 06:12:30 -05:00
|
|
|
|
|
|
|
if gotCfg != nil && !tt.parseWantDiagHasErrors {
|
|
|
|
gotInputVar := gotCfg.InputVariables
|
|
|
|
for name, value := range tt.parseWantCfg.InputVariables {
|
|
|
|
if variable, ok := gotInputVar[name]; ok {
|
|
|
|
if variable.DefaultValue.GoString() != value.DefaultValue.GoString() {
|
|
|
|
t.Fatalf("Parser.parse() input variable %s expected '%s' but was '%s'", name, value.DefaultValue.GoString(), variable.DefaultValue.GoString())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Fatalf("Parser.parse() missing input variable. %s", name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gotLocalVar := gotCfg.LocalVariables
|
|
|
|
for name, value := range tt.parseWantCfg.LocalVariables {
|
|
|
|
if variable, ok := gotLocalVar[name]; ok {
|
|
|
|
if variable.DefaultValue.GoString() != value.DefaultValue.GoString() {
|
|
|
|
t.Fatalf("Parser.parse() local variable %s expected '%s' but was '%s'", name, value.DefaultValue.GoString(), variable.DefaultValue.GoString())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Fatalf("Parser.parse() missing local variable. %s", name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-17 05:25:56 -05:00
|
|
|
if gotDiags.HasErrors() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
gotBuilds, gotDiags := tt.parser.getBuilds(gotCfg)
|
|
|
|
if tt.getBuildsWantDiags == (gotDiags == nil) {
|
|
|
|
t.Fatalf("Parser.getBuilds() unexpected diagnostics. %s", gotDiags)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(tt.getBuildsWantBuilds, gotBuilds,
|
Hcl2 input variables, local variables and functions (#8588)
Mainly redefine or reused what Terraform did.
* allow to used `variables`, `variable` and `local` blocks
* import the following functions and their docs from Terraform: abs, abspath, basename, base64decode, base64encode, bcrypt, can, ceil, chomp, chunklist, cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, coalesce, coalescelist, compact, concat, contains, convert, csvdecode, dirname, distinct, element, file, fileexists, fileset, flatten, floor, format, formatdate, formatlist, indent, index, join, jsondecode, jsonencode, keys, length, log, lookup, lower, max, md5, merge, min, parseint, pathexpand, pow, range, reverse, rsadecrypt, setintersection, setproduct, setunion, sha1, sha256, sha512, signum, slice, sort, split, strrev, substr, timestamp, timeadd, title, trim, trimprefix, trimspace, trimsuffix, try, upper, urlencode, uuidv4, uuidv5, values, yamldecode, yamlencode, zipmap.
2020-02-06 05:49:21 -05:00
|
|
|
cmpopts.IgnoreUnexported(
|
|
|
|
cty.Value{},
|
|
|
|
cty.Type{},
|
|
|
|
packer.CoreBuild{},
|
2019-12-17 05:25:56 -05:00
|
|
|
packer.CoreBuildProvisioner{},
|
|
|
|
packer.CoreBuildPostProcessor{},
|
|
|
|
),
|
|
|
|
); diff != "" {
|
|
|
|
t.Fatalf("Parser.getBuilds() wrong packer builds. %s", diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
// everything in the tests is a basicNestedMockConfig this allow to test
|
|
|
|
// each known type to packer ( and embedding ) in one go.
|
|
|
|
basicNestedMockConfig = NestedMockConfig{
|
|
|
|
String: "string",
|
|
|
|
Int: 42,
|
|
|
|
Int64: 43,
|
|
|
|
Bool: true,
|
|
|
|
Trilean: config.TriTrue,
|
|
|
|
Duration: 10 * time.Second,
|
|
|
|
MapStringString: map[string]string{
|
|
|
|
"a": "b",
|
|
|
|
"c": "d",
|
|
|
|
},
|
|
|
|
SliceString: []string{
|
|
|
|
"a",
|
|
|
|
"b",
|
|
|
|
"c",
|
|
|
|
},
|
2020-02-03 11:03:28 -05:00
|
|
|
SliceSliceString: [][]string{
|
|
|
|
{"a", "b"},
|
|
|
|
{"c", "d"},
|
|
|
|
},
|
2020-02-20 04:51:34 -05:00
|
|
|
Tags: []MockTag{},
|
2019-12-17 05:25:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
basicMockBuilder = &MockBuilder{
|
|
|
|
Config: MockConfig{
|
|
|
|
NestedMockConfig: basicNestedMockConfig,
|
|
|
|
Nested: basicNestedMockConfig,
|
|
|
|
NestedSlice: []NestedMockConfig{
|
|
|
|
basicNestedMockConfig,
|
|
|
|
basicNestedMockConfig,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
basicMockProvisioner = &MockProvisioner{
|
|
|
|
Config: MockConfig{
|
Hcl2 input variables, local variables and functions (#8588)
Mainly redefine or reused what Terraform did.
* allow to used `variables`, `variable` and `local` blocks
* import the following functions and their docs from Terraform: abs, abspath, basename, base64decode, base64encode, bcrypt, can, ceil, chomp, chunklist, cidrhost, cidrnetmask, cidrsubnet, cidrsubnets, coalesce, coalescelist, compact, concat, contains, convert, csvdecode, dirname, distinct, element, file, fileexists, fileset, flatten, floor, format, formatdate, formatlist, indent, index, join, jsondecode, jsonencode, keys, length, log, lookup, lower, max, md5, merge, min, parseint, pathexpand, pow, range, reverse, rsadecrypt, setintersection, setproduct, setunion, sha1, sha256, sha512, signum, slice, sort, split, strrev, substr, timestamp, timeadd, title, trim, trimprefix, trimspace, trimsuffix, try, upper, urlencode, uuidv4, uuidv5, values, yamldecode, yamlencode, zipmap.
2020-02-06 05:49:21 -05:00
|
|
|
NotSquashed: "value",
|
2019-12-17 05:25:56 -05:00
|
|
|
NestedMockConfig: basicNestedMockConfig,
|
|
|
|
Nested: basicNestedMockConfig,
|
|
|
|
NestedSlice: []NestedMockConfig{
|
2020-02-20 04:51:34 -05:00
|
|
|
{
|
|
|
|
Tags: dynamicTagList,
|
|
|
|
},
|
2019-12-17 05:25:56 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
basicMockPostProcessor = &MockPostProcessor{
|
|
|
|
Config: MockConfig{
|
|
|
|
NestedMockConfig: basicNestedMockConfig,
|
|
|
|
Nested: basicNestedMockConfig,
|
|
|
|
NestedSlice: []NestedMockConfig{
|
2020-02-20 04:51:34 -05:00
|
|
|
{
|
|
|
|
Tags: []MockTag{},
|
|
|
|
},
|
2019-12-17 05:25:56 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
basicMockCommunicator = &MockCommunicator{
|
|
|
|
Config: MockConfig{
|
|
|
|
NestedMockConfig: basicNestedMockConfig,
|
|
|
|
Nested: basicNestedMockConfig,
|
|
|
|
NestedSlice: []NestedMockConfig{
|
2020-02-20 04:51:34 -05:00
|
|
|
{
|
|
|
|
Tags: []MockTag{},
|
|
|
|
},
|
2019-12-17 05:25:56 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2020-02-20 04:51:34 -05:00
|
|
|
|
|
|
|
dynamicTagList = []MockTag{
|
|
|
|
{
|
|
|
|
Key: "first_tag_key",
|
|
|
|
Value: "first_tag_value",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "Component",
|
|
|
|
Value: "user-service",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "Environment",
|
|
|
|
Value: "production",
|
|
|
|
},
|
|
|
|
}
|
2019-12-17 05:25:56 -05:00
|
|
|
)
|