Files
Packer-Cn/command/validate.go
T
Lucas Bajolet dad07c6097 hcp: keep map of build names for hcp tracking
To be able to track HCP builds during a Packer build, we need to
propagate the name used for registering the build to HCP.

This works out-of-the-box for JSON templates, as the build's name is
always the builder's, so there's no confusion on that.

For HCP templates however, there's a possibility for a template to
define a name for the build, which is returned by a CoreBuild's Name()
function, in addition to the source's Type/Name.
The builds are registered to HCP with the source.String() function
however, which does not contain the build's name. This prevents any
build containing a name to work, as their name/source.String does not
match.

The name we registered the build with is stored in a CoreBuild as the
Type attribute, but cannot be safely accessed, as builds are types
within the command as packersdk.Build, which only exposes Name() for
this purpose.

In order to circumvent this problem, and as a way to present a prototype
of solution that will likely have to be discussed before we merge it,
this commit hotfixes the issue.
2022-11-14 13:31:35 -05:00

127 lines
3.0 KiB
Go

package command
import (
"context"
"strings"
"github.com/hashicorp/packer/packer"
"github.com/posener/complete"
)
type ValidateCommand struct {
Meta
}
func (c *ValidateCommand) Run(args []string) int {
ctx, cleanup := handleTermInterrupt(c.Ui)
defer cleanup()
cfg, ret := c.ParseArgs(args)
if ret != 0 {
return ret
}
return c.RunContext(ctx, cfg)
}
func (c *ValidateCommand) ParseArgs(args []string) (*ValidateArgs, int) {
var cfg ValidateArgs
flags := c.Meta.FlagSet("validate", FlagSetBuildFilter|FlagSetVars)
flags.Usage = func() { c.Ui.Say(c.Help()) }
cfg.AddFlagSets(flags)
if err := flags.Parse(args); err != nil {
return &cfg, 1
}
args = flags.Args()
if len(args) != 1 {
flags.Usage()
return &cfg, 1
}
cfg.Path = args[0]
return &cfg, 0
}
func (c *ValidateCommand) RunContext(ctx context.Context, cla *ValidateArgs) int {
packerStarter, ret := c.GetConfig(&cla.MetaArgs)
if ret != 0 {
return 1
}
// If we're only checking syntax, then we're done already
if cla.SyntaxOnly {
c.Ui.Say("Syntax-only check passed. Everything looks okay.")
return 0
}
diags := packerStarter.Initialize(packer.InitializeOptions{
SkipDatasourcesExecution: true,
})
ret = writeDiags(c.Ui, nil, diags)
if ret != 0 {
return ret
}
_, _, diags = packerStarter.GetBuilds(packer.GetBuildsOptions{
Only: cla.Only,
Except: cla.Except,
})
fixerDiags := packerStarter.FixConfig(packer.FixConfigOptions{
Mode: packer.Diff,
})
diags = append(diags, fixerDiags...)
ret = writeDiags(c.Ui, nil, diags)
if ret == 0 {
c.Ui.Say("The configuration is valid.")
}
return ret
}
func (*ValidateCommand) Help() string {
helpText := `
Usage: packer validate [options] TEMPLATE
Checks the template is valid by parsing the template and also
checking the configuration with the various builders, provisioners, etc.
If it is not valid, the errors will be shown and the command will exit
with a non-zero exit status. If it is valid, it will exit with a zero
exit status.
Options:
-syntax-only Only check syntax. Do not verify config of the template.
-except=foo,bar,baz Validate all builds other than these.
-machine-readable Produce machine-readable output.
-only=foo,bar,baz Validate only these builds.
-var 'key=value' Variable for templates, can be used multiple times.
-var-file=path JSON or HCL2 file containing user variables.
`
return strings.TrimSpace(helpText)
}
func (*ValidateCommand) Synopsis() string {
return "check that a template is valid"
}
func (*ValidateCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}
func (*ValidateCommand) AutocompleteFlags() complete.Flags {
return complete.Flags{
"-syntax-only": complete.PredictNothing,
"-except": complete.PredictNothing,
"-only": complete.PredictNothing,
"-var": complete.PredictNothing,
"-machine-readable": complete.PredictNothing,
"-var-file": complete.PredictNothing,
}
}