Implemented internal plugins
- Internal plugins are compiled into the same packer binary and invoked through the plugin command - Search paths allow disk-based plugins to override and should function as normal - This should allow for a 94% space savings vs statically compiling all the plugins as separate binaries.. approximately 24mb vs 431mb
This commit is contained in:
parent
f197cf76a7
commit
d09a9ab0c7
|
@ -0,0 +1,147 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mitchellh/packer/builder/amazon/chroot"
|
||||||
|
"github.com/mitchellh/packer/builder/amazon/ebs"
|
||||||
|
"github.com/mitchellh/packer/builder/amazon/instance"
|
||||||
|
"github.com/mitchellh/packer/builder/digitalocean"
|
||||||
|
"github.com/mitchellh/packer/builder/docker"
|
||||||
|
filebuilder "github.com/mitchellh/packer/builder/file"
|
||||||
|
"github.com/mitchellh/packer/builder/googlecompute"
|
||||||
|
"github.com/mitchellh/packer/builder/null"
|
||||||
|
"github.com/mitchellh/packer/builder/openstack"
|
||||||
|
parallelsiso "github.com/mitchellh/packer/builder/parallels/iso"
|
||||||
|
parallelspvm "github.com/mitchellh/packer/builder/parallels/pvm"
|
||||||
|
"github.com/mitchellh/packer/builder/qemu"
|
||||||
|
virtualboxiso "github.com/mitchellh/packer/builder/virtualbox/iso"
|
||||||
|
virtualboxovf "github.com/mitchellh/packer/builder/virtualbox/ovf"
|
||||||
|
vmwareiso "github.com/mitchellh/packer/builder/vmware/iso"
|
||||||
|
vmwarevmx "github.com/mitchellh/packer/builder/vmware/vmx"
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"github.com/mitchellh/packer/packer/plugin"
|
||||||
|
"github.com/mitchellh/packer/provisioner/ansible-local"
|
||||||
|
"github.com/mitchellh/packer/provisioner/chef-client"
|
||||||
|
"github.com/mitchellh/packer/provisioner/chef-solo"
|
||||||
|
fileprovisioner "github.com/mitchellh/packer/provisioner/file"
|
||||||
|
"github.com/mitchellh/packer/provisioner/powershell"
|
||||||
|
"github.com/mitchellh/packer/provisioner/puppet-masterless"
|
||||||
|
"github.com/mitchellh/packer/provisioner/puppet-server"
|
||||||
|
"github.com/mitchellh/packer/provisioner/salt-masterless"
|
||||||
|
"github.com/mitchellh/packer/provisioner/shell"
|
||||||
|
shelllocal "github.com/mitchellh/packer/provisioner/shell-local"
|
||||||
|
"github.com/mitchellh/packer/provisioner/windows-restart"
|
||||||
|
windowsshell "github.com/mitchellh/packer/provisioner/windows-shell"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PluginCommand struct {
|
||||||
|
Meta
|
||||||
|
}
|
||||||
|
|
||||||
|
var Builders = map[string]packer.Builder{
|
||||||
|
"amazon-chroot": new(chroot.Builder),
|
||||||
|
"amazon-ebs": new(ebs.Builder),
|
||||||
|
"amazon-instance": new(instance.Builder),
|
||||||
|
"digitalocean": new(digitalocean.Builder),
|
||||||
|
"docker": new(docker.Builder),
|
||||||
|
"file": new(filebuilder.Builder),
|
||||||
|
"googlecompute": new(googlecompute.Builder),
|
||||||
|
"null": new(null.Builder),
|
||||||
|
"openstack": new(openstack.Builder),
|
||||||
|
"parallels-iso": new(parallelsiso.Builder),
|
||||||
|
"parallels-pvm": new(parallelspvm.Builder),
|
||||||
|
"qemu": new(qemu.Builder),
|
||||||
|
"virtualbox-iso": new(virtualboxiso.Builder),
|
||||||
|
"virtualbox-ovf": new(virtualboxovf.Builder),
|
||||||
|
"vmware-iso": new(vmwareiso.Builder),
|
||||||
|
"vmware-vmx": new(vmwarevmx.Builder),
|
||||||
|
}
|
||||||
|
|
||||||
|
var Provisioners = map[string]packer.Provisioner{
|
||||||
|
"ansible-local": new(ansiblelocal.Provisioner),
|
||||||
|
"chef-client": new(chefclient.Provisioner),
|
||||||
|
"chef-solo": new(chefsolo.Provisioner),
|
||||||
|
"file": new(fileprovisioner.Provisioner),
|
||||||
|
"powershell": new(powershell.Provisioner),
|
||||||
|
"puppet-masterless": new(puppetmasterless.Provisioner),
|
||||||
|
"puppet-server": new(puppetserver.Provisioner),
|
||||||
|
"salt-masterless": new(saltmasterless.Provisioner),
|
||||||
|
"shell": new(shell.Provisioner),
|
||||||
|
"shell-local": new(shelllocal.Provisioner),
|
||||||
|
"windows-restart": new(restart.Provisioner),
|
||||||
|
"windows-shell": new(windowsshell.Provisioner),
|
||||||
|
}
|
||||||
|
|
||||||
|
var PostProcessors = map[string]packer.PostProcessor{}
|
||||||
|
|
||||||
|
func (c *PluginCommand) Run(args []string) int {
|
||||||
|
// This is an internal call so we're not going to do much error checking.
|
||||||
|
// If there's a problem we'll usually just crash.
|
||||||
|
log.Printf("args: %#v", args)
|
||||||
|
if len(args) != 1 {
|
||||||
|
c.Ui.Error("Wrong number of args")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin should be called like "packer-builder-amazon-ebs" so we'll take it
|
||||||
|
// apart.
|
||||||
|
parts := strings.Split(args[0], "-")
|
||||||
|
pluginType := parts[1]
|
||||||
|
pluginName := ""
|
||||||
|
// Post-processor is split so we'll so some magic here. We could use a
|
||||||
|
// regexp but this is simpler.
|
||||||
|
if pluginType == "post" {
|
||||||
|
pluginType = strings.Join(parts[1:2], "-")
|
||||||
|
pluginName = strings.Join(parts[3:], "-")
|
||||||
|
} else {
|
||||||
|
pluginName = strings.Join(parts[2:], "-")
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err := plugin.Server()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pluginType == "builder" {
|
||||||
|
builder, found := Builders[pluginName]
|
||||||
|
if !found {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Could not load builder: %s", pluginName))
|
||||||
|
}
|
||||||
|
server.RegisterBuilder(builder)
|
||||||
|
} else if pluginType == "provisioner" {
|
||||||
|
provisioner, found := Provisioners[pluginName]
|
||||||
|
if !found {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Could not load provisioner: %s", pluginName))
|
||||||
|
}
|
||||||
|
server.RegisterProvisioner(provisioner)
|
||||||
|
} else if pluginType == "post-processor" {
|
||||||
|
postProcessor, found := PostProcessors[pluginName]
|
||||||
|
if !found {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Could not load post-processor: %s", pluginName))
|
||||||
|
}
|
||||||
|
server.RegisterPostProcessor(postProcessor)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.Serve()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*PluginCommand) Help() string {
|
||||||
|
helpText := `
|
||||||
|
Usage: packer plugin PLUGIN
|
||||||
|
|
||||||
|
Runs an internally-compiled version of a plugin from the packer binary. Note
|
||||||
|
that this is an internal command and you should not call it yourself.
|
||||||
|
`
|
||||||
|
|
||||||
|
return strings.TrimSpace(helpText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PluginCommand) Synopsis() string {
|
||||||
|
return "call an internal plugin"
|
||||||
|
}
|
|
@ -59,6 +59,12 @@ func init() {
|
||||||
CheckFunc: commandVersionCheck,
|
CheckFunc: commandVersionCheck,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"plugin": func() (cli.Command, error) {
|
||||||
|
return &command.PluginCommand{
|
||||||
|
Meta: *CommandMeta,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
55
config.go
55
config.go
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mitchellh/osext"
|
"github.com/mitchellh/osext"
|
||||||
|
"github.com/mitchellh/packer/command"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"github.com/mitchellh/packer/packer/plugin"
|
"github.com/mitchellh/packer/packer/plugin"
|
||||||
)
|
)
|
||||||
|
@ -73,11 +75,17 @@ func (c *config) Discover() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last, look in the CWD.
|
// Next, look in the CWD.
|
||||||
if err := c.discover("."); err != nil {
|
if err := c.discover("."); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, try to use an internal plugin. Note that this will not Override
|
||||||
|
// any previously-loaded plugins.
|
||||||
|
if err := c.discoverInternal(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +204,41 @@ func (c *config) discoverSingle(glob string, m *map[string]string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *config) discoverInternal() error {
|
||||||
|
// Get the packer binary path
|
||||||
|
packerPath, err := osext.Executable()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERR] Error loading exe directory: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for builder := range command.Builders {
|
||||||
|
_, found := (c.Builders)[builder]
|
||||||
|
if !found {
|
||||||
|
log.Printf("Using internal plugin for %s", builder)
|
||||||
|
(c.Builders)[builder] = fmt.Sprintf("%s-PACKERSPACE-plugin-PACKERSPACE-packer-builder-%s", packerPath, builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for provisioner := range command.Provisioners {
|
||||||
|
_, found := (c.Provisioners)[provisioner]
|
||||||
|
if !found {
|
||||||
|
log.Printf("Using internal plugin for %s", provisioner)
|
||||||
|
(c.Provisioners)[provisioner] = fmt.Sprintf("%s-PACKERSPACE-plugin-PACKERSPACE-packer-provisioner-%s", packerPath, provisioner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for postProcessor := range command.PostProcessors {
|
||||||
|
_, found := (c.PostProcessors)[postProcessor]
|
||||||
|
if !found {
|
||||||
|
log.Printf("Using internal plugin for %s", postProcessor)
|
||||||
|
(c.PostProcessors)[postProcessor] = fmt.Sprintf("%s-PACKERSPACE-plugin-PACKERSPACE-packer-post-processor-%s", packerPath, postProcessor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *config) pluginClient(path string) *plugin.Client {
|
func (c *config) pluginClient(path string) *plugin.Client {
|
||||||
originalPath := path
|
originalPath := path
|
||||||
|
|
||||||
|
@ -214,6 +257,14 @@ func (c *config) pluginClient(path string) *plugin.Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for special case using `packer plugin PLUGIN`
|
||||||
|
args := []string{}
|
||||||
|
if strings.Contains(path, "-PACKERSPACE-") {
|
||||||
|
parts := strings.Split(path, "-PACKERSPACE-")
|
||||||
|
path = parts[0]
|
||||||
|
args = parts[1:]
|
||||||
|
}
|
||||||
|
|
||||||
// If everything failed, just use the original path and let the error
|
// If everything failed, just use the original path and let the error
|
||||||
// bubble through.
|
// bubble through.
|
||||||
if path == "" {
|
if path == "" {
|
||||||
|
@ -222,7 +273,7 @@ func (c *config) pluginClient(path string) *plugin.Client {
|
||||||
|
|
||||||
log.Printf("Creating plugin client for path: %s", path)
|
log.Printf("Creating plugin client for path: %s", path)
|
||||||
var config plugin.ClientConfig
|
var config plugin.ClientConfig
|
||||||
config.Cmd = exec.Command(path)
|
config.Cmd = exec.Command(path, args...)
|
||||||
config.Managed = true
|
config.Managed = true
|
||||||
config.MinPort = c.PluginMinPort
|
config.MinPort = c.PluginMinPort
|
||||||
config.MaxPort = c.PluginMaxPort
|
config.MaxPort = c.PluginMaxPort
|
||||||
|
|
Loading…
Reference in New Issue