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. - -For example, if we're adding a new builder for CustomCloud, the core -Packer configuration may look like this: - -
-{
- "builders": {
- "custom-cloud": "packer-builder-custom-cloud"
- }
-}
-
-
-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.
-
-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.
-
-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.
-
-In addition to builders, other types of plugins can be installed. The full
-list is below:
-
-* `builders` - A key/value pair of builder type to the builder plugin
- application.
-
-* `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`.
-
-* `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.
+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.
+
+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.
+
+ 1. The directory where `packer` is, or the executable directory.
+
+ 2. `~/.packer.d/plugins` on Unix systems or `%APPDATA%/packer.d` on
+ Windows.
+
+ 3. The current working directory.
+
+The valid types for plugins are:
+
+* `builder` - Plugins responsible for building images for a specific platform.
+
+* `command` - A CLI sub-command for `packer`.
+
+* `post-processor` - A post-processor responsible for taking an artifact
+ from a builder and turning it into something else.
+
+* `provisioner` - A provisioner to install software on images created by
+ a builder.