Merge pull request #6450 from shadycuz/ansible_winrm

Feature: Add randomly generated win_rm password to the ansible provisioner
This commit is contained in:
Megan Marsh 2018-07-18 09:49:48 -07:00 committed by GitHub
commit fe15bc53a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 5 deletions

View File

@ -26,6 +26,7 @@ import (
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common"
commonhelper "github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
@ -67,9 +68,19 @@ type Provisioner struct {
ansibleMajVersion uint ansibleMajVersion uint
} }
type PassthroughTemplate struct {
WinRMPassword string
}
func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Prepare(raws ...interface{}) error {
p.done = make(chan struct{}) p.done = make(chan struct{})
// Create passthrough for winrm password so we can fill it in once we know
// it
p.config.ctx.Data = &PassthroughTemplate{
WinRMPassword: `{{.WinRMPassword}}`,
}
err := config.Decode(&p.config, &config.DecodeOpts{ err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true, Interpolate: true,
InterpolateContext: &p.config.ctx, InterpolateContext: &p.config.ctx,
@ -188,6 +199,25 @@ func (p *Provisioner) getVersion() error {
func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
ui.Say("Provisioning with Ansible...") ui.Say("Provisioning with Ansible...")
// Interpolate env vars to check for .WinRMPassword
p.config.ctx.Data = &PassthroughTemplate{
WinRMPassword: getWinRMPassword(p.config.PackerBuildName),
}
for i, envVar := range p.config.AnsibleEnvVars {
envVar, err := interpolate.Render(envVar, &p.config.ctx)
if err != nil {
return fmt.Errorf("Could not interpolate ansible env vars: %s", err)
}
p.config.AnsibleEnvVars[i] = envVar
}
// Interpolate extra vars to check for .WinRMPassword
for i, arg := range p.config.ExtraArguments {
arg, err := interpolate.Render(arg, &p.config.ctx)
if err != nil {
return fmt.Errorf("Could not interpolate ansible env vars: %s", err)
}
p.config.ExtraArguments[i] = arg
}
k, err := newUserKey(p.config.SSHAuthorizedKeyFile) k, err := newUserKey(p.config.SSHAuthorizedKeyFile)
if err != nil { if err != nil {
@ -381,7 +411,15 @@ func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator, pri
go repeat(stdout) go repeat(stdout)
go repeat(stderr) go repeat(stderr)
ui.Say(fmt.Sprintf("Executing Ansible: %s", strings.Join(cmd.Args, " "))) // remove winrm password from command, if it's been added
flattenedCmd := strings.Join(cmd.Args, " ")
sanitized := flattenedCmd
if len(getWinRMPassword(p.config.PackerBuildName)) > 0 {
sanitized = strings.Replace(sanitized,
getWinRMPassword(p.config.PackerBuildName), "*****", -1)
}
ui.Say(fmt.Sprintf("Executing Ansible: %s", sanitized))
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
return err return err
} }
@ -508,6 +546,11 @@ func newSigner(privKeyFile string) (*signer, error) {
return signer, nil return signer, nil
} }
func getWinRMPassword(buildName string) string {
winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName)
return winRMPass
}
// Ui provides concurrency-safe access to packer.Ui. // Ui provides concurrency-safe access to packer.Ui.
type Ui struct { type Ui struct {
sem chan int sem chan int

View File

@ -14,7 +14,7 @@ Type: `ansible`
The `ansible` Packer provisioner runs Ansible playbooks. It dynamically creates The `ansible` Packer provisioner runs Ansible playbooks. It dynamically creates
an Ansible inventory file configured to use SSH, runs an SSH server, executes an Ansible inventory file configured to use SSH, runs an SSH server, executes
`ansible-playbook`, and marshals Ansible plays through the SSH server to the `ansible-playbook`, and marshals Ansible plays through the SSH server to the
machine being provisioned by Packer. machine being provisioned by Packer.
-> **Note:**: Any `remote_user` defined in tasks will be ignored. Packer will -> **Note:**: Any `remote_user` defined in tasks will be ignored. Packer will
always connect with the user given in the json config for this provisioner. always connect with the user given in the json config for this provisioner.
@ -61,6 +61,15 @@ Optional Parameters:
"ansible_env_vars": [ "ANSIBLE_HOST_KEY_CHECKING=False", "ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s'", "ANSIBLE_NOCOLOR=True" ] "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 would
like to access the auto-generated password that Packer uses to connect to a
Windows instance via WinRM, you can use the template variable
{{.WinRMPassword}} in this option.
For example:
```json
"ansible_env_vars": [ "WINRM_PASSWORD={{.WinRMPassword}}" ],
```
- `command` (string) - The command to invoke ansible. - `command` (string) - The command to invoke ansible.
Defaults to `ansible-playbook`. Defaults to `ansible-playbook`.
@ -72,12 +81,24 @@ Optional Parameters:
These arguments *will not* be passed through a shell and arguments should These arguments *will not* be passed through a shell and arguments should
not be quoted. Usage example: not be quoted. Usage example:
``` json ```json
{ {
"extra_arguments": [ "--extra-vars", "Region={{user `Region`}} Stage={{user `Stage`}}" ] "extra_arguments": [ "--extra-vars", "Region={{user `Region`}} Stage={{user `Stage`}}" ]
} }
``` ```
If you are running a Windows build on AWS, Azure or Google Compute and would
like to access the auto-generated password that Packer uses to connect to a
Windows instance via WinRM, you can use the template variable
{{.WinRMPassword}} in this option.
For example:
```json
"extra_arguments": [
"--extra-vars", "winrm_password={{ .WinRMPassword }}"
]
```
- `groups` (array of strings) - The groups into which the Ansible host - `groups` (array of strings) - The groups into which the Ansible host
should be placed. When unspecified, the host is not associated with any should be placed. When unspecified, the host is not associated with any
groups. groups.
@ -146,7 +167,7 @@ commonly useful Ansible variables:
To debug underlying issues with Ansible, add `"-vvvv"` to `"extra_arguments"` to enable verbose logging. To debug underlying issues with Ansible, add `"-vvvv"` to `"extra_arguments"` to enable verbose logging.
``` json ```json
{ {
"extra_arguments": [ "-vvvv" ] "extra_arguments": [ "-vvvv" ]
} }
@ -167,7 +188,7 @@ Redhat / CentOS builds have been known to fail with the following error due to `
Building within a chroot (e.g. `amazon-chroot`) requires changing the Ansible connection to chroot. Building within a chroot (e.g. `amazon-chroot`) requires changing the Ansible connection to chroot.
``` json ```json
{ {
"builders": [ "builders": [
{ {