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 }