github.com/hashicorp/packer@v1.14.3/website/content/docs/plugins/creation/plugin-load-spec.mdx (about) 1 --- 2 description: | 3 Packer needs plugins in order to build artifacts from a template. 4 This page explains how plugins are discovered and loaded by Packer. 5 page_title: Plugin Loading - Specification 6 --- 7 8 # Packer plugin loading 9 10 This document aims to document how Packer discovers plugins on the local filesystem. 11 This is not meant for beginners with Packer but instead serves as a technical reference for curiosity and troubleshooting purposes. 12 13 If you are new to Packer, you are advised to start with the [Installing Plugins](/packer/docs/plugins/install) page for details on plugin installation. 14 15 ## Plugin sources 16 17 A source is conceptually the distribution point for a plugin. It is a URL to that location. It is intended to document where to get a plugin binary, and for Packer to remotely install plugins from this source, if compatible. 18 If Packer cannot install from that source remotely, a plugin can still be installed with `packer plugins install --path <path-to-binary> <source>`. 19 20 As of Packer 1.11.0, sources are mandatory to install plugins. 21 A source will also reflect where a plugin is installed on the local filesystem, as a series of directories. 22 23 Example: `github.com/hashicorp/hashicups` will result in the following directory tree `$HOME/.config/packer/plugins/github.com/hashicorp/hashicups`. 24 25 26 There are some conventions to adopt when declaring a source: 27 28 * No schema (e.g. `https://`) 29 * No fragment (e.g. `#section`) 30 * No query (e.g. `?page=1`) 31 * The URL must contain at least a host and two parts to the URL. 32 * The URL must not have over 15 parts, in addition to the host. 33 * `/` is the only separator that can be used for the source. 34 * The full source URL needs to be compatible with the filesystem you are installing the plugin onto. Packer does not check for unsupported characters within the URL, but will error if a valid directory tree can not be created. 35 36 The last part of the source URL is the plugin's name. 37 It must always have the raw name of the plugin, without the `packer` or `packer-plugin` prefix. 38 39 **Note**: If your plugin is on GitHub, the repository's name must look like `packer-plugin-<name>` for Packer to be able to find it. However, the source address specified in your template or on the CLI must exclude `packer-plugin-`. 40 41 Example: `https://github.com/hashicorp/packer-plugin-hashicups` will become `github.com/hashicorp/hashicups` when declaring it as a source. 42 43 ## Root plugin directory 44 45 The plugins need to be installed under a root plugin directory. 46 This will default to either of the following: 47 48 **UNIX**: 49 50 * `$HOME/.packer.d/plugins`: this is the old-style installation directory for plugins. `~/.packer.d` will have precedence over the following if it exists. 51 * `$HOME/.config/packer/plugins`: this replaces `~/.packer.d`, if no existing configuration directory exists, Packer will create this automatically at first use. 52 53 **WINDOWS**: 54 55 * `%APPDATA%/packer.d/plugins`: this is the only default for Windows systems. 56 57 If you want to change that behavior, there are two alternatives: 58 59 * `PACKER_CONFIG_DIR`: this environment variable allows you to customize where the configuration directory is. The plugins are installed in a `plugin` subdirectory of this configuration directory. 60 * `PACKER_PLUGIN_PATH`: this environment variable allows you to customize where plugins are installed. This points to a root plugins directory, under which the normal directory hierarchy will be enforced. 61 62 **Note**: `PACKER_PLUGIN_PATH` has precedence over `PACKER_CONFIG_DIR`, if it is defined, `PACKER_CONFIG_DIR` will be ignored for plugin installation and loading. 63 64 Refer to [Configuring Packer](/packer/docs/configure) for a full list of environment variables. 65 66 ## Plugin installation directories 67 68 All plugins must be installed under a root plugin directory. 69 Under this directory, the plugins are installed under a series of directories that match the source URL. 70 71 Example: `github.com/hashicorp/hashicups` will translate to a hierarchy like the following: 72 73 ```shell-session 74 <plugin-root-dir> 75 └── github.com 76 └── hashicorp 77 └── hashicups 78 ``` 79 80 Plugins are installed in the leaf directory of that example. 81 Each plugin version must have only one binary per version, accompanied by a matching SHA256SUM file for the said version. The SHA256SUM file's contents are the raw hexdigest of the sha256 sum from the contents of the plugin binary. 82 83 ### Plugin binary naming convention 84 85 In order for Packer to discover and load a plugin binary it must conform to the following naming convention : 86 87 `packer-plugin-<name>_<version>_<api_version>_<os>_<arch>[.exe]` 88 89 The sha256sum file must follow the same convention, with a `SHA256SUM` suffix to the name: 90 91 `packer-plugin-<name>_<version>_<api_version>_<os>_<arch>[.exe]_SHA256SUM` 92 93 As for the components of the name, the convention is the following: 94 95 * `name`: the raw name of the plugin, it should match the parent directory's name. Ex: `hashicups`. 96 * `version`: the semver version of the plugin. It must follow the convention `v<major>.<minor>.<patch>[-<prerelease>]`. Metadata information must not be part of the version string. 97 * `api_version`: the plugin API version that the plugin was compiled with. Typically it looks like `x<api_major>.<api_minor>`. 98 * `os`: the OS the plugin was built for. Ex: `darwin` (macOS), `windows`, `linux`, etc. 99 * `arch`: the micro-architecture the plugin was built for. Ex: `arm64`, `amd64`, `386`, etc. 100 101 Note: the `.exe` suffix is only used for Windows plugins. Any other OS must not add the suffix to the plugin name, otherwise Packer will ignore it. 102 103 ## Loading process 104 105 When running either `packer build` or `packer validate`, Packer will attempt to discover and load plugins to execute the command on a template. 106 107 There are two phases to this: 108 109 1. Load explicitly required plugins. 110 2. Discover the remainder of the installed plugins. 111 112 Explicitly required plugins are an HCL2 specificity. 113 They are declared through `required_plugins` blocks. 114 These allow you to specify an exact source and version constraints on that plugin requirement. 115 116 Each of the plugins declared this way will have precedence over what the second phase will gather. 117 118 The second phase is optimistically attempting to discover the remainder of the plugins installed. 119 The name of the plugins will be inferred from the binary's name, without the `packer-plugin-` part. 120 121 Ex: If the `github.com/hashicorp/hashicups` plugin is installed, and discovered during this phase, each of the uses of this plugin's components will have their name start with `hashicups`. 122 123 When discovering a plugin, Packer will execute its `describe` command. 124 The `describe` command showcases the capabilities of a plugin and gives information about its respective version and API version. 125 126 Typically this is what you can see by invoking `describe` on a plugin: 127 128 ```shell-session 129 > $HOME/.packer.d/plugins/github.com/hashicorp/hashicups/packer-plugin-hashicups_v1.0.2_x5.0_linux_amd64 describe 130 {"version":"1.0.2","sdk_version":"0.5.1","api_version":"x5.0","builders":["order"],"post_processors":["receipt"],"provisioners":["toppings"],"datasources":["coffees","ingredients"]} 131 ``` 132 133 **Note**: the information from the plugin's described output must match the version specified within the name of the plugin. 134 135 To summarise, this is a list of the checks Packer performs before deciding if a plugin should be listed as a candidate: 136 137 * The version reported by `describe` must match the version in the plugin name: i.e. if `describe` reports v1.0.2 while the binary is named `v1.0.1`, Packer rejects it. 138 * The version must be canonical (the version must be its simplest expression): i.e. v1.00.01 is non-canonical, v1.0.1 would be. Any plugin with this version mismatch will be rejected. 139 * The API version must match between what the plugin reports, and the name: i.e. if `describe` reports x5.1 and the binary contains `x5.0`, Packer rejects it. 140 * The version may contain a pre-release fragment if this is non-final. It must however be `-dev`, anything else is rejected. 141 142 When multiple plugins are installed, Packer always chooses the one with the highest version that matches a potential constraint. 143 144 Final releases have precedence over pre-releases if the version radical is equivalent: `v1.0.0 < v1.0.1-dev < v1.0.1`. 145 146 ### Known limits 147 148 While explicit discovery ensures you always get what you intend, automatic discovery can lead to cohesion issues. 149 150 For example, if a plugin is installed twice, with a different source, Packer will discover both but the final plugin that will be executed when requesting a component from this plugin is undefined behavior. 151 152 Example: 153 154 ```shell-session 155 <plugin-root-dir> 156 ├── github.com 157 │ └── hashicorp 158 │ └── hashicups 159 │ └── packer-plugin-hashicups_v1.0.2_x5.0_linux_amd64 160 └── gitlab.com 161 └── hashicorp 162 └── hashicups 163 └── packer-plugin-hashicups_v1.0.2_x5.0_linux_amd64 164 ``` 165 166 In this case, there's an ambiguity problem as both plugins are `hashicups`, and they define a series of components that may overlap. 167 Therefore using the `hashicups-coffees` datasource without a `required_plugins` to resolve this ambiguity means one of the two plugins is executed, but there are no guarantees as to which one it will be.