diff --git a/provisioner/ansible/provisioner.go b/provisioner/ansible/provisioner.go index 4b9df4e7f..9979fbd2a 100644 --- a/provisioner/ansible/provisioner.go +++ b/provisioner/ansible/provisioner.go @@ -51,7 +51,7 @@ type Config struct { EmptyGroups []string `mapstructure:"empty_groups"` HostAlias string `mapstructure:"host_alias"` User string `mapstructure:"user"` - LocalPort string `mapstructure:"local_port"` + LocalPort uint `mapstructure:"local_port"` SSHHostKeyFile string `mapstructure:"ssh_host_key_file"` SSHAuthorizedKeyFile string `mapstructure:"ssh_authorized_key_file"` SFTPCmd string `mapstructure:"sftp_command"` @@ -130,12 +130,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.AnsibleEnvVars = append(p.config.AnsibleEnvVars, "ANSIBLE_SCP_IF_SSH=True") } - if len(p.config.LocalPort) > 0 { - if _, err := strconv.ParseUint(p.config.LocalPort, 10, 16); err != nil { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("local_port: %s must be a valid port", p.config.LocalPort)) - } - } else { - p.config.LocalPort = "0" + if p.config.LocalPort > 65535 { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("local_port: %d must be a valid port", p.config.LocalPort)) } if len(p.config.InventoryDirectory) > 0 { @@ -256,11 +252,8 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { config.AddHostKey(hostSigner) localListener, err := func() (net.Listener, error) { - port, err := strconv.ParseUint(p.config.LocalPort, 10, 16) - if err != nil { - return nil, err - } + port := p.config.LocalPort tries := 1 if port != 0 { tries = 10 @@ -272,11 +265,17 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ui.Say(err.Error()) continue } - _, p.config.LocalPort, err = net.SplitHostPort(l.Addr().String()) + _, portStr, err := net.SplitHostPort(l.Addr().String()) if err != nil { ui.Say(err.Error()) continue } + portUint64, err := strconv.ParseUint(portStr, 10, 0) + if err != nil { + ui.Say(err.Error()) + continue + } + p.config.LocalPort = uint(portUint64) return l, nil } return nil, errors.New("Error setting up SSH proxy connection") @@ -304,10 +303,10 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { } defer os.Remove(tf.Name()) - host := fmt.Sprintf("%s ansible_host=127.0.0.1 ansible_user=%s ansible_port=%s\n", + host := fmt.Sprintf("%s ansible_host=127.0.0.1 ansible_user=%s ansible_port=%d\n", p.config.HostAlias, p.config.User, p.config.LocalPort) if p.ansibleMajVersion < 2 { - host = fmt.Sprintf("%s ansible_ssh_host=127.0.0.1 ansible_ssh_user=%s ansible_ssh_port=%s\n", + host = fmt.Sprintf("%s ansible_ssh_host=127.0.0.1 ansible_ssh_user=%s ansible_ssh_port=%d\n", p.config.HostAlias, p.config.User, p.config.LocalPort) } diff --git a/provisioner/ansible/provisioner_test.go b/provisioner/ansible/provisioner_test.go index 3386b74cb..099f72bcc 100644 --- a/provisioner/ansible/provisioner_test.go +++ b/provisioner/ansible/provisioner_test.go @@ -245,13 +245,13 @@ func TestProvisionerPrepare_LocalPort(t *testing.T) { config["ssh_authorized_key_file"] = publickey_file.Name() config["playbook_file"] = playbook_file.Name() - config["local_port"] = "65537" + config["local_port"] = uint(65537) err = p.Prepare(config) if err == nil { t.Fatal("should have error") } - config["local_port"] = "22222" + config["local_port"] = uint(22222) err = p.Prepare(config) if err != nil { t.Fatalf("err: %s", err) diff --git a/website/source/docs/provisioners/ansible.html.md b/website/source/docs/provisioners/ansible.html.md index 440215b8a..7ec4941c9 100644 --- a/website/source/docs/provisioners/ansible.html.md +++ b/website/source/docs/provisioners/ansible.html.md @@ -49,7 +49,7 @@ DigitalOcean. Replace the mock `api_token` value with your own. Required Parameters: -- `playbook_file` - The playbook to be run by Ansible. +- `playbook_file` (string) - The playbook to be run by Ansible. Optional Parameters: @@ -57,9 +57,7 @@ Optional Parameters: running Ansible. Usage example: ``` json - { "ansible_env_vars": [ "ANSIBLE_HOST_KEY_CHECKING=False", "ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s'", "ANSIBLE_NOCOLOR=True" ] - } ``` If you are running a Windows build on AWS, Azure or Google Compute and @@ -82,9 +80,7 @@ Optional Parameters: not be quoted. Usage example: ``` json - { "extra_arguments": [ "--extra-vars", "Region={{user `Region`}} Stage={{user `Stage`}}" ] - } ``` If you are running a Windows build on AWS, Azure or Google Compute and @@ -117,7 +113,7 @@ Optional Parameters: inventory directory with `host_vars` `group_vars` that you would like to use in the playbook that this provisioner will run. -- `local_port` (string) - The port on which to attempt to listen for SSH +- `local_port` (uint) - The port on which to attempt to listen for SSH connections. This value is a starting point. The provisioner will attempt listen for SSH connections on the first available of ten ports, starting at `local_port`. A system-chosen port is used when `local_port` is missing or @@ -175,9 +171,7 @@ To debug underlying issues with Ansible, add `"-vvvv"` to `"extra_arguments"` to enable verbose logging. ``` json -{ "extra_arguments": [ "-vvvv" ] -} ``` ## Limitations diff --git a/website/source/layouts/docs.erb b/website/source/layouts/docs.erb index e0cf12c86..63f65f109 100644 --- a/website/source/layouts/docs.erb +++ b/website/source/layouts/docs.erb @@ -202,7 +202,7 @@ Ansible Local > - Ansible Remote + Ansible (Remote) > Breakpoint