github.com/phobos182/packer@v0.2.3-0.20130819023704-c84d2aeffc68/config.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "github.com/mitchellh/osext" 6 "github.com/mitchellh/packer/packer" 7 "github.com/mitchellh/packer/packer/plugin" 8 "io" 9 "log" 10 "os/exec" 11 "path/filepath" 12 ) 13 14 // This is the default, built-in configuration that ships with 15 // Packer. 16 const defaultConfig = ` 17 { 18 "plugin_min_port": 10000, 19 "plugin_max_port": 25000, 20 21 "builders": { 22 "amazon-ebs": "packer-builder-amazon-ebs", 23 "amazon-chroot": "packer-builder-amazon-chroot", 24 "amazon-instance": "packer-builder-amazon-instance", 25 "digitalocean": "packer-builder-digitalocean", 26 "virtualbox": "packer-builder-virtualbox", 27 "vmware": "packer-builder-vmware" 28 }, 29 30 "commands": { 31 "build": "packer-command-build", 32 "fix": "packer-command-fix", 33 "inspect": "packer-command-inspect", 34 "validate": "packer-command-validate" 35 }, 36 37 "post-processors": { 38 "vagrant": "packer-post-processor-vagrant" 39 }, 40 41 "provisioners": { 42 "file": "packer-provisioner-file", 43 "shell": "packer-provisioner-shell", 44 "salt-masterless": "packer-provisioner-salt-masterless" 45 } 46 } 47 ` 48 49 type config struct { 50 PluginMinPort uint 51 PluginMaxPort uint 52 53 Builders map[string]string 54 Commands map[string]string 55 PostProcessors map[string]string `json:"post-processors"` 56 Provisioners map[string]string 57 } 58 59 // Decodes configuration in JSON format from the given io.Reader into 60 // the config object pointed to. 61 func decodeConfig(r io.Reader, c *config) error { 62 decoder := json.NewDecoder(r) 63 return decoder.Decode(c) 64 } 65 66 // Returns an array of defined command names. 67 func (c *config) CommandNames() (result []string) { 68 result = make([]string, 0, len(c.Commands)) 69 for name := range c.Commands { 70 result = append(result, name) 71 } 72 return 73 } 74 75 // This is a proper packer.BuilderFunc that can be used to load packer.Builder 76 // implementations from the defined plugins. 77 func (c *config) LoadBuilder(name string) (packer.Builder, error) { 78 log.Printf("Loading builder: %s\n", name) 79 bin, ok := c.Builders[name] 80 if !ok { 81 log.Printf("Builder not found: %s\n", name) 82 return nil, nil 83 } 84 85 return c.pluginClient(bin).Builder() 86 } 87 88 // This is a proper packer.CommandFunc that can be used to load packer.Command 89 // implementations from the defined plugins. 90 func (c *config) LoadCommand(name string) (packer.Command, error) { 91 log.Printf("Loading command: %s\n", name) 92 bin, ok := c.Commands[name] 93 if !ok { 94 log.Printf("Command not found: %s\n", name) 95 return nil, nil 96 } 97 98 return c.pluginClient(bin).Command() 99 } 100 101 // This is a proper implementation of packer.HookFunc that can be used 102 // to load packer.Hook implementations from the defined plugins. 103 func (c *config) LoadHook(name string) (packer.Hook, error) { 104 log.Printf("Loading hook: %s\n", name) 105 return c.pluginClient(name).Hook() 106 } 107 108 // This is a proper packer.PostProcessorFunc that can be used to load 109 // packer.PostProcessor implementations from defined plugins. 110 func (c *config) LoadPostProcessor(name string) (packer.PostProcessor, error) { 111 log.Printf("Loading post-processor: %s", name) 112 bin, ok := c.PostProcessors[name] 113 if !ok { 114 log.Printf("Post-processor not found: %s", name) 115 return nil, nil 116 } 117 118 return c.pluginClient(bin).PostProcessor() 119 } 120 121 // This is a proper packer.ProvisionerFunc that can be used to load 122 // packer.Provisioner implementations from defined plugins. 123 func (c *config) LoadProvisioner(name string) (packer.Provisioner, error) { 124 log.Printf("Loading provisioner: %s\n", name) 125 bin, ok := c.Provisioners[name] 126 if !ok { 127 log.Printf("Provisioner not found: %s\n", name) 128 return nil, nil 129 } 130 131 return c.pluginClient(bin).Provisioner() 132 } 133 134 func (c *config) pluginClient(path string) *plugin.Client { 135 originalPath := path 136 137 // First attempt to find the executable by consulting the PATH. 138 path, err := exec.LookPath(path) 139 if err != nil { 140 // If that doesn't work, look for it in the same directory 141 // as the `packer` executable (us). 142 log.Printf("Plugin could not be found. Checking same directory as executable.") 143 exePath, err := osext.Executable() 144 if err != nil { 145 log.Printf("Couldn't get current exe path: %s", err) 146 } else { 147 log.Printf("Current exe path: %s", exePath) 148 path = filepath.Join(filepath.Dir(exePath), filepath.Base(originalPath)) 149 } 150 } 151 152 // If everything failed, just use the original path and let the error 153 // bubble through. 154 if path == "" { 155 path = originalPath 156 } 157 158 log.Printf("Creating plugin client for path: %s", path) 159 var config plugin.ClientConfig 160 config.Cmd = exec.Command(path) 161 config.Managed = true 162 config.MinPort = c.PluginMinPort 163 config.MaxPort = c.PluginMaxPort 164 return plugin.NewClient(&config) 165 }