diff --git a/config.go b/config.go index 26a1c19a7..5df96e453 100644 --- a/config.go +++ b/config.go @@ -23,6 +23,19 @@ type config struct { Provisioners map[string]string } +// ConfigFile returns the default path to the configuration file. On +// Unix-like systems this is the ".packerconfig" file in the home directory. +// On Windows, this is the "packer.config" file in the application data +// directory. +func ConfigFile() (string, error) { + return configFile() +} + +// ConfigDir returns the configuration directory for Packer. +func ConfigDir() (string, error) { + return configDir() +} + // Decodes configuration in JSON format from the given io.Reader into // the config object pointed to. func decodeConfig(r io.Reader, c *config) error { @@ -35,11 +48,6 @@ func decodeConfig(r io.Reader, c *config) error { // 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() @@ -51,6 +59,21 @@ func (c *config) Discover() error { } } + // Look in the plugins directory + dir, err := ConfigDir() + if err != nil { + log.Printf("[ERR] Error loading config directory: %s", err) + } else { + if err := c.discover(filepath.Join(dir, "plugins")); err != nil { + return err + } + } + + // Look in the cwd. + if err := c.discover("."); err != nil { + return err + } + return nil } diff --git a/configfile_unix.go b/config_unix.go similarity index 82% rename from configfile_unix.go rename to config_unix.go index b0b28109f..2c8a7a304 100644 --- a/configfile_unix.go +++ b/config_unix.go @@ -13,7 +13,7 @@ import ( ) func configFile() (string, error) { - dir, err := configDir() + dir, err := homeDir() if err != nil { return "", err } @@ -22,6 +22,15 @@ func configFile() (string, error) { } func configDir() (string, error) { + dir, err := homeDir() + if err != nil { + return "", err + } + + return filepath.Join(dir, ".packer.d"), nil +} + +func homeDir() (string, error) { // First prefer the HOME environmental variable if home := os.Getenv("HOME"); home != "" { log.Printf("Detected home directory from env var: %s", home) diff --git a/configfile_windows.go b/config_windows.go similarity index 80% rename from configfile_windows.go rename to config_windows.go index c59359dd9..fa3ab94b7 100644 --- a/configfile_windows.go +++ b/config_windows.go @@ -16,7 +16,7 @@ var ( const CSIDL_APPDATA = 26 func configFile() (string, error) { - dir, err := configDir() + dir, err := homeDir() if err != nil { return "", err } @@ -25,6 +25,15 @@ func configFile() (string, error) { } func configDir() (string, error) { + dir, err := homeDir() + if err != nil { + return "", err + } + + return filepath.Join(dir, "packer.d"), nil +} + +func homeDir() (string, error) { b := make([]uint16, syscall.MAX_PATH) // See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx diff --git a/configfile.go b/configfile.go deleted file mode 100644 index 8b0e8eff1..000000000 --- a/configfile.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -// ConfigFile returns the default path to the configuration file. On -// Unix-like systems this is the ".packerconfig" file in the home directory. -// On Windows, this is the "packer.config" file in the application data -// directory. -func ConfigFile() (string, error) { - return configFile() -} diff --git a/website/source/docs/extend/plugins.html.markdown b/website/source/docs/extend/plugins.html.markdown index fe1dd82e1..5be80be7d 100644 --- a/website/source/docs/extend/plugins.html.markdown +++ b/website/source/docs/extend/plugins.html.markdown @@ -36,43 +36,31 @@ applications running. ## Installing Plugins -Plugins are installed by modifying the [core Packer configuration](/docs/other/core-configuration.html). Within -the core configuration, each component has a key/value mapping of the -plugin name to the actual plugin binary. +The easiest way to install a plugin is to name it correctly, then place +it in the proper directory. To name a plugin correctly, make sure the +binary is named `packer-TYPE-NAME`. For example, `packer-builder-amazon-ebs` +for a "builder" type plugin named "amazon-ebs". Valid types for plugins +are down this page more. -For example, if we're adding a new builder for CustomCloud, the core -Packer configuration may look like this: +Once the plugin is named properly, Packer automatically discovers plugins +in the following directories in the given order. If a conflicting plugin is +found later, it will take precedence over one found earlier. -
-{ - "builders": { - "custom-cloud": "packer-builder-custom-cloud" - } -} -+ 1. The directory where `packer` is, or the executable directory. -In this case, the "custom-cloud" type is the type that is actually used for the value -of the "type" configuration key for the builder definition. + 2. `~/.packer.d/plugins` on Unix systems or `%APPDATA%/packer.d` on + Windows. -The value, "packer-builder-custom-cloud", is the path to the plugin binary. -It can be an absolute or relative path. If it is not an absolute path, then -the binary is searched for on the PATH. In the example above, Packer will -search for `packer-builder-custom-cloud` on the PATH. + 3. The current working directory. -After adding the plugin to the core Packer configuration, it is immediately -available on the next run of Packer. To uninstall a plugin, just remove it -from the core Packer configuration. +The valid types for plugins are: -In addition to builders, other types of plugins can be installed. The full -list is below: +* `builder` - Plugins responsible for building images for a specific platform. -* `builders` - A key/value pair of builder type to the builder plugin - application. +* `command` - A CLI sub-command for `packer`. -* `commands` - A key/value pair of the command name to the command plugin - application. The command name is what is executed on the command line, like - `packer COMMAND`. +* `post-processor` - A post-processor responsible for taking an artifact + from a builder and turning it into something else. -* `provisioners` - A key/value pair of the provisioner type to the - provisioner plugin application. The provisioner type is the value of the - "type" configuration used within templates. +* `provisioner` - A provisioner to install software on images created by + a builder.