-
Notifications
You must be signed in to change notification settings - Fork 45
/
cmd.go
121 lines (100 loc) · 3.11 KB
/
cmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package plugincheck
import (
_ "embed"
"encoding/json"
"fmt"
"log"
"os/exec"
"path/filepath"
"strings"
"github.com/pkg/errors"
)
var (
//go:embed README.md
readme string
)
type Command struct {
}
func (cmd *Command) Help() string {
return "\n" + readme
}
func (cmd *Command) Run(args []string) int {
if err := cmd.run(args); err != nil {
log.Printf("%v", err)
return 1
}
return 0
}
func (cmd *Command) run(args []string) error {
if len(args) != 1 {
cmd.Help()
return errors.New("plugin-check requires a plugin binary name as an argument.\n" +
"ex: 'packer-plugin-happycloud'. Check will be run on the binary.")
}
pluginName := args[0]
if isOldPlugin(pluginName) {
fmt.Printf("\n[WARNING] Plugin is named with old prefix `packer-[builder|provisioner|post-processor]-{name})`. " +
"These will be detected but Packer cannot install them automatically. " +
"The plugin must be a multi-component plugin named packer-plugin-{name} to be installable through the `packer init` command.\n" +
"See docs at: https://www.packer.io/docs/plugins.\n")
return nil
}
if err := checkPluginName(pluginName); err != nil {
return err
}
path, err := filepath.Abs(pluginName)
if err != nil {
return err
}
output, err := exec.Command(path, "describe").Output()
if err != nil {
return errors.Wrap(err, "failed to describe plugin")
}
desc := pluginDescription{}
err = json.Unmarshal(output, &desc)
if err != nil {
return errors.Wrap(err, "failed to json.Unmarshal plugin description")
}
if len(desc.Version) == 0 {
return errors.New("Version needs to be set")
}
if len(desc.SDKVersion) == 0 {
return errors.New("SDKVersion needs to be set")
}
if len(desc.APIVersion) == 0 {
return errors.New("APIVersion needs to be set")
}
if len(desc.Builders) == 0 && len(desc.PostProcessors) == 0 && len(desc.Datasources) == 0 && len(desc.Provisioners) == 0 {
return errors.New("this plugin defines no component.")
}
return nil
}
type pluginDescription struct {
Version string `json:"version"`
SDKVersion string `json:"sdk_version"`
APIVersion string `json:"api_version"`
Builders []string `json:"builders"`
PostProcessors []string `json:"post_processors"`
Datasources []string `json:"datasources"`
Provisioners []string `json:"provisioners"`
}
func isOldPlugin(pluginName string) bool {
return strings.HasPrefix(pluginName, "packer-builder-") ||
strings.HasPrefix(pluginName, "packer-provisioner-") ||
strings.HasPrefix(pluginName, "packer-post-processor-")
}
// checkPluginName checks for the possible valid names for a plugin,
// packer-plugin-* or packer-[builder|provisioner|post-processor]-*. If the name
// is prefixed with `packer-[builder|provisioner|post-processor]-`, packer won't
// be able to install it, therefore a WARNING will be shown.
func checkPluginName(name string) error {
if strings.HasPrefix(name, "packer-plugin-") {
return nil
}
return fmt.Errorf("plugin name is not valid")
}
func (cmd *Command) Synopsis() string {
return "Tell wether a plugin release looks valid for Packer."
}