Clarify how shell-local post-processor gets called and when, with an example (#3511)
This commit is contained in:
parent
3728e076fe
commit
e9a9219725
|
@ -87,3 +87,70 @@ commonly useful environmental variables:
|
|||
- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create the
|
||||
machine that the script is running on. This is useful if you want to run
|
||||
only certain parts of the script on systems built with certain builders.
|
||||
|
||||
## Safely Writing A Script
|
||||
|
||||
Whether you use the `inline` option, or pass it a direct `script` or `scripts`, it is important to understand a few things about how the shell-local post-processor works to run it safely and easily. This understanding will save you much time in the process.
|
||||
|
||||
### Once Per Artifact
|
||||
|
||||
The `shell-local` script(s) you pass are run once per artifact output file. That means that if your builder results in 1 output file, your script will be run once. If it results in 3 output files, it will run 3 times, once for each file.
|
||||
|
||||
For example, the virtualbox builders, when configured to provide an `ovf` output format (the default), will provide **two** output files:
|
||||
|
||||
* The actual disk itself, in `.vmdk` format
|
||||
* The appliance description file, in `.ovf` format
|
||||
|
||||
Each time each shell-local script is run, it is passed the path to the artifact file, relative to the directory in which packer is run, as the first argument to the script.
|
||||
|
||||
Let's take a simple example. You want to run a post-processor that records the name of every artifact created to `/tmp/artifacts`. (Why? I don't know. For fun.)
|
||||
|
||||
Your post-processor should look like this:
|
||||
|
||||
|
||||
``` {.javascript}
|
||||
{
|
||||
"type": "shell-local",
|
||||
"inline": [
|
||||
"echo \$1 >> /tmp/artifacts"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The result of the above will be an output line for each artifact.
|
||||
|
||||
The net effect of this is that if you want to post-process only some files, **you must test** `$1` to see if it is the file you want.
|
||||
|
||||
Here is an example script that converts the `.vmdk` artifact of a virtualbox build to a raw img, suitable for converting to a USB.
|
||||
|
||||
|
||||
``` {.bash}
|
||||
#!/bin/bash -e
|
||||
|
||||
[[ "$1" == *.vmdk ]] && vboxmanage clonemedium disk $1 --format raw output_file.img
|
||||
|
||||
```
|
||||
|
||||
### Always Exit Intentionally
|
||||
|
||||
If any post-processor fails, the `packer build` stops and all interim artifacts are cleaned up.
|
||||
|
||||
For a shell script, that means the script **must** exit with a zero code. You *must* be extra careful to `exit 0` when necessary. Using our above conversion script example, if the current artifact is *not* a `.vmdk` file, the test `[[ "$1" == *.vmdk ]]` will fail. Since that is the last command in the script, the script will exit with a non-zero code, the post-processor will fail, the build will fail, and you will have to start over.
|
||||
|
||||
Of course, we didn't mean that! We just meant:
|
||||
|
||||
* If a `.vmdk` file, convert, and that is OK
|
||||
* If not a `.vmdk` file, ignore, and that is OK
|
||||
|
||||
To make it work correctly, use the following instead:
|
||||
|
||||
``` {.bash}
|
||||
#!/bin/bash -e
|
||||
|
||||
[[ "$1" == *.vmdk ]] && vboxmanage clonemedium disk $1 --format raw output_file.img
|
||||
|
||||
# always exit 0 unless a command actually fails
|
||||
exit 0
|
||||
|
||||
````
|
||||
|
||||
|
|
Loading…
Reference in New Issue