github.com/hashicorp/packer@v1.14.3/command/cli.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package command
     5  
     6  import (
     7  	"flag"
     8  	"strings"
     9  
    10  	"github.com/hashicorp/packer/command/enumflag"
    11  	kvflag "github.com/hashicorp/packer/command/flag-kv"
    12  	sliceflag "github.com/hashicorp/packer/command/flag-slice"
    13  )
    14  
    15  //go:generate enumer -type configType -trimprefix ConfigType -transform snake
    16  type configType int
    17  
    18  const (
    19  	ConfigTypeJSON configType = iota // default config type
    20  	ConfigTypeHCL2
    21  )
    22  
    23  func (c *configType) Set(value string) error {
    24  	v, err := configTypeString(value)
    25  	if err == nil {
    26  		*c = v
    27  	}
    28  	return err
    29  }
    30  
    31  // ConfigType tells what type of config we should use, it can return values
    32  // like "hcl" or "json".
    33  // Make sure Args was correctly set before.
    34  func (ma *MetaArgs) GetConfigType() (configType, error) {
    35  	if ma.Path == "" {
    36  		return ma.ConfigType, nil
    37  	}
    38  	name := ma.Path
    39  	if name == "-" {
    40  		// TODO(azr): To allow piping HCL2 confs (when args is "-"), we probably
    41  		// will need to add a setting that says "this is an HCL config".
    42  		return ma.ConfigType, nil
    43  	}
    44  	if strings.HasSuffix(name, ".pkr.hcl") ||
    45  		strings.HasSuffix(name, ".pkr.json") {
    46  		return ConfigTypeHCL2, nil
    47  	}
    48  	isDir, err := isDir(name)
    49  	if isDir {
    50  		return ConfigTypeHCL2, err
    51  	}
    52  	return ma.ConfigType, err
    53  }
    54  
    55  // NewMetaArgs parses cli args and put possible values
    56  func (ma *MetaArgs) AddFlagSets(fs *flag.FlagSet) {
    57  	fs.Var((*sliceflag.StringFlag)(&ma.Only), "only", "")
    58  	fs.Var((*sliceflag.StringFlag)(&ma.Except), "except", "")
    59  	fs.Var((*kvflag.Flag)(&ma.Vars), "var", "")
    60  	fs.Var((*kvflag.StringSlice)(&ma.VarFiles), "var-file", "")
    61  	fs.Var(&ma.ConfigType, "config-type", "set to 'hcl2' to run in hcl2 mode when no file is passed.")
    62  }
    63  
    64  // MetaArgs defines commonalities between all commands
    65  type MetaArgs struct {
    66  	// TODO(azr): in the future, I want to allow passing multiple path to
    67  	// merge HCL confs together; but this will probably need an RFC first.
    68  	Path         string
    69  	Paths        []string
    70  	Only, Except []string
    71  	Vars         map[string]string
    72  	VarFiles     []string
    73  	// set to "hcl2" to force hcl2 mode
    74  	ConfigType configType
    75  
    76  	// WarnOnUndeclared does not have a common default, as the default varies per sub-command usage.
    77  	// Refer to individual command FlagSets for usage.
    78  	WarnOnUndeclaredVar bool
    79  	// UseSequential specifies to use a sequential/phased approach for
    80  	// evaluating datasources/locals instead of a DAG.
    81  	//
    82  	// This allows users to fall-back to using the approach used by Packer
    83  	// before the introduction of a DAG in case they run in an impasse/bug.
    84  	UseSequential bool
    85  }
    86  
    87  func (ba *BuildArgs) AddFlagSets(flags *flag.FlagSet) {
    88  	flags.BoolVar(&ba.Color, "color", true, "")
    89  	flags.BoolVar(&ba.Debug, "debug", false, "")
    90  	flags.BoolVar(&ba.Force, "force", false, "")
    91  	flags.BoolVar(&ba.TimestampUi, "timestamp-ui", false, "")
    92  	flags.BoolVar(&ba.MachineReadable, "machine-readable", false, "")
    93  
    94  	flags.Int64Var(&ba.ParallelBuilds, "parallel-builds", 0, "")
    95  
    96  	flagOnError := enumflag.New(&ba.OnError, "cleanup", "abort", "ask", "run-cleanup-provisioner")
    97  	flags.Var(flagOnError, "on-error", "")
    98  
    99  	flags.BoolVar(&ba.MetaArgs.WarnOnUndeclaredVar, "warn-on-undeclared-var", false, "Show warnings for variable files containing undeclared variables.")
   100  	flags.BoolVar(&ba.MetaArgs.UseSequential, "use-sequential-evaluation", false, "Fallback to using a sequential approach for local/datasource evaluation.")
   101  
   102  	flags.BoolVar(&ba.ReleaseOnly, "ignore-prerelease-plugins", false, "Disable the loading of prerelease plugin binaries (x.y.z-dev).")
   103  
   104  	ba.MetaArgs.AddFlagSets(flags)
   105  }
   106  
   107  // GetCleanedBuildArgs returns a map containing build flags specified to build for tracking within
   108  // the HCP Packer registry.
   109  //
   110  // Most of the arguments are kept as-is, except for the -var args, where only
   111  // the keys are kept to avoid leaking potential secrets.
   112  func GetCleanedBuildArgs(ba *BuildArgs) map[string]interface{} {
   113  	cleanedArgs := map[string]interface{}{
   114  		"debug":     ba.Debug,
   115  		"force":     ba.Force,
   116  		"only":      ba.Only,
   117  		"except":    ba.Except,
   118  		"var-files": ba.VarFiles,
   119  		"path":      ba.Path,
   120  	}
   121  
   122  	var varNames []string
   123  	for k := range ba.Vars {
   124  		varNames = append(varNames, k)
   125  	}
   126  	cleanedArgs["vars"] = varNames
   127  
   128  	return cleanedArgs
   129  }
   130  
   131  // BuildArgs represents a parsed cli line for a `packer build`
   132  type BuildArgs struct {
   133  	MetaArgs
   134  	Debug, Force                        bool
   135  	Color, TimestampUi, MachineReadable bool
   136  	ParallelBuilds                      int64
   137  	OnError                             string
   138  	ReleaseOnly                         bool
   139  }
   140  
   141  func (ia *InitArgs) AddFlagSets(flags *flag.FlagSet) {
   142  	flags.BoolVar(&ia.Upgrade, "upgrade", false, "upgrade any present plugin to the highest allowed version.")
   143  	flags.BoolVar(&ia.Force, "force", false, "force installation of a plugin, even if already installed")
   144  
   145  	ia.MetaArgs.AddFlagSets(flags)
   146  }
   147  
   148  // InitArgs represents a parsed cli line for a `packer init <path>`
   149  type InitArgs struct {
   150  	MetaArgs
   151  	Upgrade bool
   152  	Force   bool
   153  }
   154  
   155  // PluginsRequiredArgs represents a parsed cli line for a `packer plugins required <path>`
   156  type PluginsRequiredArgs struct {
   157  	MetaArgs
   158  }
   159  
   160  func (ca *ConsoleArgs) AddFlagSets(flags *flag.FlagSet) {
   161  	flags.BoolVar(&ca.MetaArgs.UseSequential, "use-sequential-evaluation", false, "Fallback to using a sequential approach for local/datasource evaluation.")
   162  }
   163  
   164  // ConsoleArgs represents a parsed cli line for a `packer console`
   165  type ConsoleArgs struct {
   166  	MetaArgs
   167  }
   168  
   169  func (fa *FixArgs) AddFlagSets(flags *flag.FlagSet) {
   170  	flags.BoolVar(&fa.Validate, "validate", true, "")
   171  
   172  	fa.MetaArgs.AddFlagSets(flags)
   173  }
   174  
   175  // FixArgs represents a parsed cli line for a `packer fix`
   176  type FixArgs struct {
   177  	MetaArgs
   178  	Validate bool
   179  }
   180  
   181  func (va *ValidateArgs) AddFlagSets(flags *flag.FlagSet) {
   182  	flags.BoolVar(&va.SyntaxOnly, "syntax-only", false, "check syntax only")
   183  	flags.BoolVar(&va.NoWarnUndeclaredVar, "no-warn-undeclared-var", false, "Ignore warnings for variable files containing undeclared variables.")
   184  	flags.BoolVar(&va.EvaluateDatasources, "evaluate-datasources", false, "evaluate datasources for validation (HCL2 only, may incur costs)")
   185  	flags.BoolVar(&va.ReleaseOnly, "ignore-prerelease-plugins", false, "Disable the loading of prerelease plugin binaries (x.y.z-dev).")
   186  	flags.BoolVar(&va.MetaArgs.UseSequential, "use-sequential-evaluation", false, "Fallback to using a sequential approach for local/datasource evaluation.")
   187  
   188  	va.MetaArgs.AddFlagSets(flags)
   189  }
   190  
   191  // ValidateArgs represents a parsed cli line for a `packer validate`
   192  type ValidateArgs struct {
   193  	MetaArgs
   194  	SyntaxOnly, NoWarnUndeclaredVar bool
   195  	EvaluateDatasources             bool
   196  	ReleaseOnly                     bool
   197  }
   198  
   199  func (va *InspectArgs) AddFlagSets(flags *flag.FlagSet) {
   200  	flags.BoolVar(&va.MetaArgs.UseSequential, "use-sequential-evaluation", false, "Fallback to using a sequential approach for local/datasource evaluation.")
   201  	va.MetaArgs.AddFlagSets(flags)
   202  }
   203  
   204  // InspectArgs represents a parsed cli line for a `packer inspect`
   205  type InspectArgs struct {
   206  	MetaArgs
   207  }
   208  
   209  func (va *HCL2UpgradeArgs) AddFlagSets(flags *flag.FlagSet) {
   210  	flags.StringVar(&va.OutputFile, "output-file", "", "File where to put the hcl2 generated config. Defaults to JSON_TEMPLATE.pkr.hcl")
   211  	flags.BoolVar(&va.WithAnnotations, "with-annotations", false, "Adds helper annotations with information about the generated HCL2 blocks.")
   212  
   213  	va.MetaArgs.AddFlagSets(flags)
   214  }
   215  
   216  // HCL2UpgradeArgs represents a parsed cli line for a `packer hcl2_upgrade`
   217  type HCL2UpgradeArgs struct {
   218  	MetaArgs
   219  	OutputFile      string
   220  	WithAnnotations bool
   221  }
   222  
   223  func (va *FormatArgs) AddFlagSets(flags *flag.FlagSet) {
   224  	flags.BoolVar(&va.Check, "check", false, "check if the input is formatted")
   225  	flags.BoolVar(&va.Diff, "diff", false, "display the diff of formatting changes")
   226  	flags.BoolVar(&va.Write, "write", true, "overwrite source files instead of writing to stdout")
   227  	flags.BoolVar(&va.Recursive, "recursive", false, "Also process files in subdirectories")
   228  	va.MetaArgs.AddFlagSets(flags)
   229  }
   230  
   231  // FormatArgs represents a parsed cli line for `packer fmt`
   232  type FormatArgs struct {
   233  	MetaArgs
   234  	Check, Diff, Write, Recursive bool
   235  }