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

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package command
     5  
     6  import (
     7  	"context"
     8  	"crypto/sha256"
     9  	"fmt"
    10  	"runtime"
    11  	"strings"
    12  
    13  	pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
    14  	plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
    15  	"github.com/mitchellh/cli"
    16  )
    17  
    18  type PluginsRequiredCommand struct {
    19  	Meta
    20  }
    21  
    22  func (c *PluginsRequiredCommand) Synopsis() string {
    23  	return "List plugins required by a config"
    24  }
    25  
    26  func (c *PluginsRequiredCommand) Help() string {
    27  	helpText := `
    28  Usage: packer plugins required <path>
    29  
    30    This command will list every Packer plugin required by a Packer config, in
    31    packer.required_plugins blocks. All binaries matching the required version
    32    constrain and the current OS and Architecture will be listed. The most recent
    33    version (and the first of the list) will be the one picked by Packer during a
    34    build.
    35  
    36    Ex: packer plugins required require.pkr.hcl
    37    Ex: packer plugins required path/to/folder/
    38  `
    39  
    40  	return strings.TrimSpace(helpText)
    41  }
    42  
    43  func (c *PluginsRequiredCommand) Run(args []string) int {
    44  	ctx, cleanup := handleTermInterrupt(c.Ui)
    45  	defer cleanup()
    46  
    47  	cfg, ret := c.ParseArgs(args)
    48  	if ret != 0 {
    49  		return ret
    50  	}
    51  
    52  	return c.RunContext(ctx, cfg)
    53  }
    54  
    55  func (c *PluginsRequiredCommand) ParseArgs(args []string) (*PluginsRequiredArgs, int) {
    56  	var cfg PluginsRequiredArgs
    57  	flags := c.Meta.FlagSet("plugins required")
    58  	flags.Usage = func() { c.Ui.Say(c.Help()) }
    59  	cfg.AddFlagSets(flags)
    60  	if err := flags.Parse(args); err != nil {
    61  		return &cfg, 1
    62  	}
    63  
    64  	args = flags.Args()
    65  	if len(args) != 1 {
    66  		return &cfg, cli.RunResultHelp
    67  	}
    68  	cfg.Path = args[0]
    69  	return &cfg, 0
    70  }
    71  
    72  func (c *PluginsRequiredCommand) RunContext(buildCtx context.Context, cla *PluginsRequiredArgs) int {
    73  
    74  	packerStarter, ret := c.GetConfig(&cla.MetaArgs)
    75  	if ret != 0 {
    76  		return ret
    77  	}
    78  
    79  	// Get plugins requirements
    80  	reqs, diags := packerStarter.PluginRequirements()
    81  	ret = writeDiags(c.Ui, nil, diags)
    82  	if ret != 0 {
    83  		return ret
    84  	}
    85  
    86  	ext := ""
    87  	if runtime.GOOS == "windows" {
    88  		ext = ".exe"
    89  	}
    90  	opts := plugingetter.ListInstallationsOptions{
    91  		PluginDirectory: c.Meta.CoreConfig.Components.PluginConfig.PluginDirectory,
    92  		BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
    93  			OS:              runtime.GOOS,
    94  			ARCH:            runtime.GOARCH,
    95  			Ext:             ext,
    96  			APIVersionMajor: pluginsdk.APIVersionMajor,
    97  			APIVersionMinor: pluginsdk.APIVersionMinor,
    98  			Checksummers: []plugingetter.Checksummer{
    99  				{Type: "sha256", Hash: sha256.New()},
   100  			},
   101  		},
   102  	}
   103  
   104  	for _, pluginRequirement := range reqs {
   105  		s := fmt.Sprintf("%s %s %q", pluginRequirement.Accessor, pluginRequirement.Identifier.String(), pluginRequirement.VersionConstraints.String())
   106  		installs, err := pluginRequirement.ListInstallations(opts)
   107  		if err != nil {
   108  			c.Ui.Error(err.Error())
   109  			return 1
   110  		}
   111  		for _, install := range installs {
   112  			s += fmt.Sprintf(" %s", install.BinaryPath)
   113  		}
   114  		c.Ui.Message(s)
   115  	}
   116  
   117  	if len(reqs) == 0 {
   118  		c.Ui.Message(`
   119  No plugins requirement found, make sure you reference a Packer config
   120  containing a packer.required_plugins block. See
   121  https://www.packer.io/docs/templates/hcl_templates/blocks/packer
   122  for more info.`)
   123  	}
   124  
   125  	return 0
   126  }