post-processor/shell-local: run only once for each builder
don't run post-processor for each artifact file, but only for each builder to be consistent with other post-processors Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
This commit is contained in:
parent
0a3b7e1b53
commit
332a208fee
@ -47,9 +47,8 @@ type PostProcessor struct {
|
||||
}
|
||||
|
||||
type ExecuteCommandTemplate struct {
|
||||
Vars string
|
||||
Script string
|
||||
Artifact string
|
||||
Vars string
|
||||
Script string
|
||||
}
|
||||
|
||||
func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||
@ -67,7 +66,7 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||
}
|
||||
|
||||
if p.config.ExecuteCommand == "" {
|
||||
p.config.ExecuteCommand = `chmod +x "{{.Script}}"; {{.Vars}} "{{.Script}}" {{.Artifact}}`
|
||||
p.config.ExecuteCommand = `chmod +x "{{.Script}}"; {{.Vars}} "{{.Script}}"`
|
||||
}
|
||||
|
||||
if p.config.Inline != nil && len(p.config.Inline) == 0 {
|
||||
@ -172,44 +171,41 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
||||
envVars[1] = fmt.Sprintf("PACKER_BUILDER_TYPE='%s'", p.config.PackerBuilderType)
|
||||
copy(envVars[2:], p.config.Vars)
|
||||
|
||||
for _, file := range artifact.Files() {
|
||||
for _, script := range scripts {
|
||||
// Flatten the environment variables
|
||||
flattendVars := strings.Join(envVars, " ")
|
||||
for _, script := range scripts {
|
||||
// Flatten the environment variables
|
||||
flattendVars := strings.Join(envVars, " ")
|
||||
|
||||
p.config.ctx.Data = &ExecuteCommandTemplate{
|
||||
Vars: flattendVars,
|
||||
Script: script,
|
||||
Artifact: file,
|
||||
}
|
||||
p.config.ctx.Data = &ExecuteCommandTemplate{
|
||||
Vars: flattendVars,
|
||||
Script: script,
|
||||
}
|
||||
|
||||
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("Error processing command: %s", err)
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Post processing with local shell script: %s", command))
|
||||
ui.Say(fmt.Sprintf("Post processing with local shell script: %s", command))
|
||||
|
||||
comm := &Communicator{}
|
||||
comm := &Communicator{}
|
||||
|
||||
cmd := &packer.RemoteCmd{Command: command}
|
||||
cmd := &packer.RemoteCmd{Command: command}
|
||||
|
||||
ui.Say(fmt.Sprintf(
|
||||
"Executing local script: %s",
|
||||
script))
|
||||
if err := cmd.StartWithUi(comm, ui); err != nil {
|
||||
return nil, false, fmt.Errorf(
|
||||
"Error executing script: %s\n\n"+
|
||||
"Please see output above for more information.",
|
||||
script)
|
||||
}
|
||||
if cmd.ExitStatus != 0 {
|
||||
return nil, false, fmt.Errorf(
|
||||
"Erroneous exit code %d while executing script: %s\n\n"+
|
||||
"Please see output above for more information.",
|
||||
cmd.ExitStatus,
|
||||
script)
|
||||
}
|
||||
ui.Say(fmt.Sprintf(
|
||||
"Executing local script: %s",
|
||||
script))
|
||||
if err := cmd.StartWithUi(comm, ui); err != nil {
|
||||
return nil, false, fmt.Errorf(
|
||||
"Error executing script: %s\n\n"+
|
||||
"Please see output above for more information.",
|
||||
script)
|
||||
}
|
||||
if cmd.ExitStatus != 0 {
|
||||
return nil, false, fmt.Errorf(
|
||||
"Erroneous exit code %d while executing script: %s\n\n"+
|
||||
"Please see output above for more information.",
|
||||
cmd.ExitStatus,
|
||||
script)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,11 +54,10 @@ Optional parameters:
|
||||
as well, which are covered in the section below.
|
||||
|
||||
- `execute_command` (string) - The command to use to execute the script. By
|
||||
default this is `chmod +x "{{.Script}}"; {{.Vars}} "{{.Script}}" {{.Artifact}}`.
|
||||
default this is `chmod +x "{{.Script}}"; {{.Vars}} "{{.Script}}"`.
|
||||
The value of this is treated as [configuration template](/docs/templates/configuration-templates.html).
|
||||
There are three available variables: `Script`, which is the path to the script
|
||||
to run, `Vars`, which is the list of `environment_vars`, if configured and
|
||||
`Artifact`, which is path to artifact file.
|
||||
There are two available variables: `Script`, which is the path to the script
|
||||
to run, `Vars`, which is the list of `environment_vars`, if configured.
|
||||
|
||||
- `inline_shebang` (string) - The
|
||||
[shebang](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) value to use when
|
||||
@ -101,8 +100,6 @@ For example, the virtualbox builders, when configured to provide an `ovf` output
|
||||
* 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:
|
||||
@ -117,40 +114,11 @@ Your post-processor should look like this:
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
```
|
||||
The result of the above will be an output line for each builder.
|
||||
|
||||
### 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
|
||||
|
||||
````
|
||||
For a shell script, that means the script **must** exit with a zero code. You *must* be extra careful to `exit 0` when necessary.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user