Commit 60182afb authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

Automatically discover plugins

parent 7097c756
......@@ -2,67 +2,16 @@ package main
import (
"encoding/json"
"github.com/mitchellh/osext"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/packer/plugin"
"io"
"log"
"os/exec"
"path/filepath"
)
"strings"
// This is the default, built-in configuration that ships with
// Packer.
const defaultConfig = `
{
"plugin_min_port": 10000,
"plugin_max_port": 25000,
"builders": {
"amazon-ebs": "packer-builder-amazon-ebs",
"amazon-chroot": "packer-builder-amazon-chroot",
"amazon-instance": "packer-builder-amazon-instance",
"digitalocean": "packer-builder-digitalocean",
"docker": "packer-builder-docker",
"googlecompute": "packer-builder-googlecompute",
"openstack": "packer-builder-openstack",
"qemu": "packer-builder-qemu",
"virtualbox-iso": "packer-builder-virtualbox-iso",
"virtualbox-ovf": "packer-builder-virtualbox-ovf",
"vmware-iso": "packer-builder-vmware-iso",
"vmware-vmx": "packer-builder-vmware-vmx",
"parallels-iso": "packer-builder-parallels-iso",
"parallels-pvm": "packer-builder-parallels-pvm",
"null": "packer-builder-null"
},
"commands": {
"build": "packer-command-build",
"fix": "packer-command-fix",
"inspect": "packer-command-inspect",
"validate": "packer-command-validate"
},
"post-processors": {
"vagrant": "packer-post-processor-vagrant",
"vsphere": "packer-post-processor-vsphere",
"docker-push": "packer-post-processor-docker-push",
"docker-import": "packer-post-processor-docker-import",
"vagrant-cloud": "packer-post-processor-vagrant-cloud"
},
"provisioners": {
"ansible-local": "packer-provisioner-ansible-local",
"chef-client": "packer-provisioner-chef-client",
"chef-solo": "packer-provisioner-chef-solo",
"file": "packer-provisioner-file",
"puppet-masterless": "packer-provisioner-puppet-masterless",
"puppet-server": "packer-provisioner-puppet-server",
"shell": "packer-provisioner-shell",
"salt-masterless": "packer-provisioner-salt-masterless"
}
}
`
"github.com/mitchellh/osext"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/packer/plugin"
)
type config struct {
PluginMinPort uint
......@@ -81,6 +30,30 @@ func decodeConfig(r io.Reader, c *config) error {
return decoder.Decode(c)
}
// Discover discovers plugins.
//
// This looks in the directory of the executable and the CWD, in that
// order for priority.
func (c *config) Discover() error {
// Look in the cwd.
if err := c.discover("."); err != nil {
return err
}
// Next, look in the same directory as the executable. Any conflicts
// will overwrite those found in our current directory.
exePath, err := osext.Executable()
if err != nil {
log.Printf("[ERR] Error loading exe directory: %s", err)
} else {
if err := c.discover(filepath.Dir(exePath)); err != nil {
return err
}
}
return nil
}
// Returns an array of defined command names.
func (c *config) CommandNames() (result []string) {
result = make([]string, 0, len(c.Commands))
......@@ -149,6 +122,64 @@ func (c *config) LoadProvisioner(name string) (packer.Provisioner, error) {
return c.pluginClient(bin).Provisioner()
}
func (c *config) discover(path string) error {
var err error
err = c.discoverSingle(
filepath.Join(path, "packer-builder-*"), &c.Builders)
if err != nil {
return err
}
err = c.discoverSingle(
filepath.Join(path, "packer-command-*"), &c.Commands)
if err != nil {
return err
}
err = c.discoverSingle(
filepath.Join(path, "packer-post-processor-*"), &c.PostProcessors)
if err != nil {
return err
}
err = c.discoverSingle(
filepath.Join(path, "packer-provisioner-*"), &c.Provisioners)
if err != nil {
return err
}
return nil
}
func (c *config) discoverSingle(glob string, m *map[string]string) error {
matches, err := filepath.Glob(glob)
if err != nil {
return err
}
if *m == nil {
*m = make(map[string]string)
}
prefix := filepath.Base(glob)
prefix = prefix[:strings.Index(prefix, "*")]
for _, match := range matches {
file := filepath.Base(match)
// If the filename has a ".", trim up to there
if idx := strings.Index(file, "."); idx >= 0 {
file = file[:idx]
}
// Look for foo-bar-baz. The plugin name is "baz"
plugin := file[len(prefix):]
log.Printf("[DEBUG] Discoverd plugin: %s = %s", plugin, match)
(*m)[plugin] = match
}
return nil
}
func (c *config) pluginClient(path string) *plugin.Client {
originalPath := path
......
......@@ -2,17 +2,17 @@
package main
import (
"bytes"
"fmt"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/packer/plugin"
"github.com/mitchellh/panicwrap"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/packer/plugin"
"github.com/mitchellh/panicwrap"
)
func main() {
......@@ -173,7 +173,9 @@ func extractMachineReadable(args []string) ([]string, bool) {
func loadConfig() (*config, error) {
var config config
if err := decodeConfig(bytes.NewBufferString(defaultConfig), &config); err != nil {
config.PluginMinPort = 10000
config.PluginMaxPort = 25000
if err := config.Discover(); err != nil {
return nil, err
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment