Commit 4b9a9f59 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

Merge pull request #842 from strcrzy/ansible_config_options

provisioner/ansible: more configuration options
parents 9b23282b 458d90c7
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"os" "os"
"path/filepath" "path/filepath"
"strings"
) )
const DefaultStagingDir = "/tmp/packer-provisioner-ansible-local" const DefaultStagingDir = "/tmp/packer-provisioner-ansible-local"
...@@ -23,9 +24,21 @@ type Config struct { ...@@ -23,9 +24,21 @@ type Config struct {
// An array of local paths of roles to upload. // An array of local paths of roles to upload.
RolePaths []string `mapstructure:"role_paths"` RolePaths []string `mapstructure:"role_paths"`
// Path to group_vars directory
GroupVars string `mapstructure:"group_vars"`
// Path to host_vars directory
HostVars string `mapstructure:"host_vars"`
// The directory where files will be uploaded. Packer requires write // The directory where files will be uploaded. Packer requires write
// permissions in this directory. // permissions in this directory.
StagingDir string `mapstructure:"staging_directory"` StagingDir string `mapstructure:"staging_directory"`
// The command to run ansible
Command string
// Extra options to pass to the ansible command
ExtraArguments []string `mapstructure:"extra_arguments"`
} }
type Provisioner struct { type Provisioner struct {
...@@ -48,14 +61,22 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -48,14 +61,22 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
// Accumulate any errors // Accumulate any errors
errs := common.CheckUnusedConfig(md) errs := common.CheckUnusedConfig(md)
// Defaults
if p.config.StagingDir == "" { if p.config.StagingDir == "" {
p.config.StagingDir = DefaultStagingDir p.config.StagingDir = DefaultStagingDir
} }
if p.config.Command == "" {
p.config.Command = "ansible-playbook"
}
// Templates // Templates
templates := map[string]*string{ templates := map[string]*string{
"playbook_file": &p.config.PlaybookFile, "playbook_file": &p.config.PlaybookFile,
"staging_dir": &p.config.StagingDir, "staging_dir": &p.config.StagingDir,
"command": &p.config.Command,
"group_vars": &p.config.GroupVars,
"host_vars": &p.config.HostVars,
} }
for n, ptr := range templates { for n, ptr := range templates {
...@@ -68,8 +89,9 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -68,8 +89,9 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
} }
sliceTemplates := map[string][]string{ sliceTemplates := map[string][]string{
"playbook_paths": p.config.PlaybookPaths, "playbook_paths": p.config.PlaybookPaths,
"role_paths": p.config.RolePaths, "role_paths": p.config.RolePaths,
"extra_arguments": p.config.ExtraArguments,
} }
for n, slice := range sliceTemplates { for n, slice := range sliceTemplates {
...@@ -99,6 +121,20 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -99,6 +121,20 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
errs = packer.MultiErrorAppend(errs, err) errs = packer.MultiErrorAppend(errs, err)
} }
} }
// Check that the group_vars directory exists, if configured
if len(p.config.GroupVars) > 0 {
if err := validateDirConfig(p.config.GroupVars, "group_vars"); err != nil {
errs = packer.MultiErrorAppend(errs, err)
}
}
// Check that the host_vars directory exists, if configured
if len(p.config.HostVars) > 0 {
if err := validateDirConfig(p.config.HostVars, "host_vars"); err != nil {
errs = packer.MultiErrorAppend(errs, err)
}
}
if errs != nil && len(errs.Errors) > 0 { if errs != nil && len(errs.Errors) > 0 {
return errs return errs
} }
...@@ -120,6 +156,26 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -120,6 +156,26 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
return fmt.Errorf("Error uploading main playbook: %s", err) return fmt.Errorf("Error uploading main playbook: %s", err)
} }
// Upload group_vars
if len(p.config.GroupVars) > 0 {
ui.Message("Uploading group_vars directory...")
src := p.config.GroupVars
dst := filepath.Join(p.config.StagingDir, "group_vars")
if err := p.uploadDir(ui, comm, dst, src); err != nil {
return fmt.Errorf("Error uploading group_vars directory: %s", err)
}
}
// Upload host_vars
if len(p.config.HostVars) > 0 {
ui.Message("Uploading host_vars directory...")
src := p.config.HostVars
dst := filepath.Join(p.config.StagingDir, "host_vars")
if err := p.uploadDir(ui, comm, dst, src); err != nil {
return fmt.Errorf("Error uploading host_vars directory: %s", err)
}
}
if len(p.config.RolePaths) > 0 { if len(p.config.RolePaths) > 0 {
ui.Message("Uploading role directories...") ui.Message("Uploading role directories...")
for _, src := range p.config.RolePaths { for _, src := range p.config.RolePaths {
...@@ -161,7 +217,13 @@ func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator) err ...@@ -161,7 +217,13 @@ func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator) err
// The inventory must be set to "127.0.0.1,". The comma is important // The inventory must be set to "127.0.0.1,". The comma is important
// as its the only way to override the ansible inventory when dealing // as its the only way to override the ansible inventory when dealing
// with a single host. // with a single host.
command := fmt.Sprintf("ansible-playbook %s -c local -i %s", playbook, `"127.0.0.1,"`) var command string
if len(p.config.ExtraArguments) > 0 {
command = fmt.Sprintf("%s %s %s -c local -i \"127.0.0.1,\"", p.config.Command,
playbook, strings.Join(p.config.ExtraArguments, " "))
} else {
command = fmt.Sprintf("%s %s -c local -i \"127.0.0.1,\"", p.config.Command, playbook)
}
ui.Message(fmt.Sprintf("Executing Ansible: %s", command)) ui.Message(fmt.Sprintf("Executing Ansible: %s", command))
cmd := &packer.RemoteCmd{ cmd := &packer.RemoteCmd{
......
...@@ -120,4 +120,28 @@ func TestProvisionerPrepare_Dirs(t *testing.T) { ...@@ -120,4 +120,28 @@ func TestProvisionerPrepare_Dirs(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
config["group_vars"] = playbook_file.Name()
err = p.Prepare(config)
if err == nil {
t.Fatalf("should error if group_vars path is not a dir")
}
config["group_vars"] = os.TempDir()
err = p.Prepare(config)
if err != nil {
t.Fatalf("err: %s", err)
}
config["host_vars"] = playbook_file.Name()
err = p.Prepare(config)
if err == nil {
t.Fatalf("should error if host_vars path is not a dir")
}
config["host_vars"] = os.TempDir()
err = p.Prepare(config)
if err != nil {
t.Fatalf("err: %s", err)
}
} }
...@@ -34,6 +34,11 @@ Required: ...@@ -34,6 +34,11 @@ Required:
Optional: Optional:
* `command` (string) - The command to invoke ansible. Defaults to "ansible-playbook".
* `extra_arguments` (array of strings) - An array of extra arguments to pass to the
ansible command. By default, this is empty.
* `playbook_paths` (array of strings) - An array of paths to playbook files on * `playbook_paths` (array of strings) - An array of paths to playbook files on
your local system. These will be uploaded to the remote machine under your local system. These will be uploaded to the remote machine under
`staging_directory`/playbooks. By default, this is empty. `staging_directory`/playbooks. By default, this is empty.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment