-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add pkr plugin check cmd from packer core (#85)
This is simplified to not pull in core as a dep. The drawback is that we don't actually start plugins to verify that it works with Packer and has a ConfigSpec func. We do start a binary, though. But, I think this is fine since if a plugin implements describe then we can be pretty sure it uses the SDK's function and interfaces. Related to hashicorp/packer#11317 closes hashicorp/packer#11309
- Loading branch information
Showing
3 changed files
with
126 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## `plugin-check` | ||
|
||
`plugin-check` will check wether a plugin binary seems to work with packer. | ||
|
||
Use: `packer-sdc plugin-check packer-plugin-happy-cloud` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
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 { | ||
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"` | ||
} | ||
|
||
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." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters