github.com/hashicorp/packer@v1.14.3/command/validate.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package command 5 6 import ( 7 "context" 8 "log" 9 "strings" 10 11 "github.com/hashicorp/packer/packer" 12 13 "github.com/posener/complete" 14 ) 15 16 type ValidateCommand struct { 17 Meta 18 } 19 20 func (c *ValidateCommand) Run(args []string) int { 21 ctx, cleanup := handleTermInterrupt(c.Ui) 22 defer cleanup() 23 24 cfg, ret := c.ParseArgs(args) 25 if ret != 0 { 26 return ret 27 } 28 29 return c.RunContext(ctx, cfg) 30 } 31 32 func (c *ValidateCommand) ParseArgs(args []string) (*ValidateArgs, int) { 33 var cfg ValidateArgs 34 35 flags := c.Meta.FlagSet("validate") 36 flags.Usage = func() { c.Ui.Say(c.Help()) } 37 cfg.AddFlagSets(flags) 38 if err := flags.Parse(args); err != nil { 39 return &cfg, 1 40 } 41 42 args = flags.Args() 43 if len(args) != 1 { 44 flags.Usage() 45 return &cfg, 1 46 } 47 cfg.Path = args[0] 48 return &cfg, 0 49 } 50 51 func (c *ValidateCommand) RunContext(ctx context.Context, cla *ValidateArgs) int { 52 // Set the release only flag if specified as argument 53 // 54 // This deactivates the capacity for Packer to load development binaries. 55 c.CoreConfig.Components.PluginConfig.ReleasesOnly = cla.ReleaseOnly 56 57 // By default we want to inform users of undeclared variables when validating but not during build time. 58 cla.MetaArgs.WarnOnUndeclaredVar = true 59 if cla.NoWarnUndeclaredVar { 60 cla.MetaArgs.WarnOnUndeclaredVar = false 61 } 62 63 packerStarter, ret := c.GetConfig(&cla.MetaArgs) 64 if ret != 0 { 65 return 1 66 } 67 68 // If we're only checking syntax, then we're done already 69 if cla.SyntaxOnly { 70 c.Ui.Say("Syntax-only check passed. Everything looks okay.") 71 return 0 72 } 73 74 diags := packerStarter.DetectPluginBinaries() 75 ret = writeDiags(c.Ui, nil, diags) 76 if ret != 0 { 77 return ret 78 } 79 80 if packer.PackerUseProto { 81 log.Printf("[TRACE] Using protobuf for communication with plugins") 82 } 83 84 diags = packerStarter.Initialize(packer.InitializeOptions{ 85 SkipDatasourcesExecution: !cla.EvaluateDatasources, 86 UseSequential: cla.UseSequential, 87 }) 88 ret = writeDiags(c.Ui, nil, diags) 89 if ret != 0 { 90 return ret 91 } 92 93 _, diags = packerStarter.GetBuilds(packer.GetBuildsOptions{ 94 Only: cla.Only, 95 Except: cla.Except, 96 }) 97 98 fixerDiags := packerStarter.FixConfig(packer.FixConfigOptions{ 99 Mode: packer.Diff, 100 }) 101 diags = append(diags, fixerDiags...) 102 103 ret = writeDiags(c.Ui, nil, diags) 104 if ret == 0 { 105 c.Ui.Say("The configuration is valid.") 106 } 107 108 return ret 109 } 110 111 func (*ValidateCommand) Help() string { 112 helpText := ` 113 Usage: packer validate [options] TEMPLATE 114 115 Checks the template is valid by parsing the template and also 116 checking the configuration with the various builders, provisioners, etc. 117 118 If it is not valid, the errors will be shown and the command will exit 119 with a non-zero exit status. If it is valid, it will exit with a zero 120 exit status. 121 122 Options: 123 124 -syntax-only Only check syntax. Do not verify config of the template. 125 -except=foo,bar,baz Validate all builds other than these. 126 -only=foo,bar,baz Validate only these builds. 127 -machine-readable Produce machine-readable output. 128 -var 'key=value' Variable for templates, can be used multiple times. 129 -var-file=path JSON or HCL2 file containing user variables, can be used multiple times. 130 -no-warn-undeclared-var Disable warnings for user variable files containing undeclared variables. 131 -evaluate-datasources Evaluate data sources during validation (HCL2 only, may incur costs); Defaults to false. 132 -ignore-prerelease-plugins Disable the loading of prerelease plugin binaries (x.y.z-dev). 133 -use-sequential-evaluation Fallback to using a sequential approach for local/datasource evaluation. 134 ` 135 136 return strings.TrimSpace(helpText) 137 } 138 139 func (*ValidateCommand) Synopsis() string { 140 return "check that a template is valid" 141 } 142 143 func (*ValidateCommand) AutocompleteArgs() complete.Predictor { 144 return complete.PredictNothing 145 } 146 147 func (*ValidateCommand) AutocompleteFlags() complete.Flags { 148 return complete.Flags{ 149 "-syntax-only": complete.PredictNothing, 150 "-except": complete.PredictNothing, 151 "-only": complete.PredictNothing, 152 "-var": complete.PredictNothing, 153 "-machine-readable": complete.PredictNothing, 154 "-var-file": complete.PredictNothing, 155 } 156 }