diff --git a/command/cli.go b/command/cli.go index 826835ef2..e1eb1ffbc 100644 --- a/command/cli.go +++ b/command/cli.go @@ -136,6 +136,7 @@ type FixArgs struct { func (va *ValidateArgs) AddFlagSets(flags *flag.FlagSet) { flags.BoolVar(&va.SyntaxOnly, "syntax-only", false, "check syntax only") flags.BoolVar(&va.NoWarnUndeclaredVar, "no-warn-undeclared-var", false, "Ignore warnings for variable files containing undeclared variables.") + flags.BoolVar(&va.EvaluateDatasources, "evaluate-datasources", false, "evaluate datasources for validation (HCL2 only, may incur costs)") va.MetaArgs.AddFlagSets(flags) } @@ -144,6 +145,7 @@ func (va *ValidateArgs) AddFlagSets(flags *flag.FlagSet) { type ValidateArgs struct { MetaArgs SyntaxOnly, NoWarnUndeclaredVar bool + EvaluateDatasources bool } func (va *InspectArgs) AddFlagSets(flags *flag.FlagSet) { diff --git a/command/test-fixtures/hcl/local-ds-validate.pkr.hcl b/command/test-fixtures/hcl/local-ds-validate.pkr.hcl new file mode 100644 index 000000000..47a2f9fd1 --- /dev/null +++ b/command/test-fixtures/hcl/local-ds-validate.pkr.hcl @@ -0,0 +1,17 @@ +data "null" "dep" { + input = "upload" +} + +source "null" "test" { + communicator = "none" +} + +build { + sources = ["sources.null.test"] + + provisioner "file" { + source = "test-fixtures/hcl/force.pkr.hcl" + destination = "dest" + direction = "${data.null.dep.output}" + } +} diff --git a/command/validate.go b/command/validate.go index 304db1a38..718fcc121 100644 --- a/command/validate.go +++ b/command/validate.go @@ -63,7 +63,7 @@ func (c *ValidateCommand) RunContext(ctx context.Context, cla *ValidateArgs) int } diags := packerStarter.Initialize(packer.InitializeOptions{ - SkipDatasourcesExecution: true, + SkipDatasourcesExecution: !cla.EvaluateDatasources, }) ret = writeDiags(c.Ui, nil, diags) if ret != 0 { diff --git a/command/validate_test.go b/command/validate_test.go index 5b9b346aa..3a2c6b20a 100644 --- a/command/validate_test.go +++ b/command/validate_test.go @@ -11,8 +11,9 @@ import ( func TestValidateCommand(t *testing.T) { tt := []struct { - path string - exitCode int + path string + exitCode int + extraArgs []string }{ {path: filepath.Join(testFixture("validate"), "build.json")}, {path: filepath.Join(testFixture("validate"), "build.pkr.hcl")}, @@ -39,6 +40,11 @@ func TestValidateCommand(t *testing.T) { // datasource could be unknown at that moment {path: filepath.Join(testFixture("hcl", "data-source-validation.pkr.hcl")), exitCode: 0}, + + // datasource unknown at validation-time without datasource evaluation -> fail on provisioner + {path: filepath.Join(testFixture("hcl", "local-ds-validate.pkr.hcl")), exitCode: 1}, + // datasource unknown at validation-time with datasource evaluation -> success + {path: filepath.Join(testFixture("hcl", "local-ds-validate.pkr.hcl")), exitCode: 0, extraArgs: []string{"--evaluate-datasources"}}, } for _, tc := range tt { @@ -47,7 +53,8 @@ func TestValidateCommand(t *testing.T) { Meta: TestMetaFile(t), } tc := tc - args := []string{tc.path} + args := tc.extraArgs + args = append(args, tc.path) if code := c.Run(args); code != tc.exitCode { fatalCommand(t, c.Meta) } diff --git a/website/content/docs/commands/validate.mdx b/website/content/docs/commands/validate.mdx index 57026315e..8b06c274f 100644 --- a/website/content/docs/commands/validate.mdx +++ b/website/content/docs/commands/validate.mdx @@ -31,6 +31,14 @@ Errors validating build 'vmware'. 1 error(s) occurred: - `-syntax-only` - Only the syntax of the template is checked. The configuration is not validated. +- `-evaluate-datasources` - Evaluate all data sources when validating a template. + This is only valid on HCL2 templates, since JSON templates do not feature + datasources, this option will be ignored. + + ~> **Warning:** Data sources may rely on external services for fetching data, + which can incur some costs at validation if the services being contacted are + billing per operation. + - `-except=foo,bar,baz` - Validates all the builds except those with the comma-separated names. In legacy JSON templates, build names default to the types of their builders (e.g. `docker` or