This commit is contained in:
Chris Bednarski 2016-06-14 17:35:41 -07:00
commit 9583929e9a
3 changed files with 64 additions and 7 deletions

View File

@ -23,6 +23,7 @@ import (
type guestOSTypeConfig struct { type guestOSTypeConfig struct {
executeCommand string executeCommand string
installCommand string installCommand string
knifeCommand string
stagingDir string stagingDir string
} }
@ -30,11 +31,13 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{
provisioner.UnixOSType: guestOSTypeConfig{ provisioner.UnixOSType: guestOSTypeConfig{
executeCommand: "{{if .Sudo}}sudo {{end}}chef-client --no-color -c {{.ConfigPath}} -j {{.JsonPath}}", executeCommand: "{{if .Sudo}}sudo {{end}}chef-client --no-color -c {{.ConfigPath}} -j {{.JsonPath}}",
installCommand: "curl -L https://www.chef.io/chef/install.sh | {{if .Sudo}}sudo {{end}}bash", installCommand: "curl -L https://www.chef.io/chef/install.sh | {{if .Sudo}}sudo {{end}}bash",
knifeCommand: "{{if .Sudo}}sudo {{end}}knife {{.Args}} {{.Flags}}",
stagingDir: "/tmp/packer-chef-client", stagingDir: "/tmp/packer-chef-client",
}, },
provisioner.WindowsOSType: guestOSTypeConfig{ provisioner.WindowsOSType: guestOSTypeConfig{
executeCommand: "c:/opscode/chef/bin/chef-client.bat --no-color -c {{.ConfigPath}} -j {{.JsonPath}}", executeCommand: "c:/opscode/chef/bin/chef-client.bat --no-color -c {{.ConfigPath}} -j {{.JsonPath}}",
installCommand: "powershell.exe -Command \"(New-Object System.Net.WebClient).DownloadFile('http://chef.io/chef/install.msi', 'C:\\Windows\\Temp\\chef.msi');Start-Process 'msiexec' -ArgumentList '/qb /i C:\\Windows\\Temp\\chef.msi' -NoNewWindow -Wait\"", installCommand: "powershell.exe -Command \"(New-Object System.Net.WebClient).DownloadFile('http://chef.io/chef/install.msi', 'C:\\Windows\\Temp\\chef.msi');Start-Process 'msiexec' -ArgumentList '/qb /i C:\\Windows\\Temp\\chef.msi' -NoNewWindow -Wait\"",
knifeCommand: "c:/opscode/chef/bin/knife.bat {{.Args}} {{.Flags}}",
stagingDir: "C:/Windows/Temp/packer-chef-client", stagingDir: "C:/Windows/Temp/packer-chef-client",
}, },
} }
@ -51,6 +54,7 @@ type Config struct {
ExecuteCommand string `mapstructure:"execute_command"` ExecuteCommand string `mapstructure:"execute_command"`
GuestOSType string `mapstructure:"guest_os_type"` GuestOSType string `mapstructure:"guest_os_type"`
InstallCommand string `mapstructure:"install_command"` InstallCommand string `mapstructure:"install_command"`
KnifeCommand string `mapstructure:"knife_command"`
NodeName string `mapstructure:"node_name"` NodeName string `mapstructure:"node_name"`
PreventSudo bool `mapstructure:"prevent_sudo"` PreventSudo bool `mapstructure:"prevent_sudo"`
RunList []string `mapstructure:"run_list"` RunList []string `mapstructure:"run_list"`
@ -93,6 +97,12 @@ type InstallChefTemplate struct {
Sudo bool Sudo bool
} }
type KnifeTemplate struct {
Sudo bool
Flags string
Args string
}
func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Prepare(raws ...interface{}) error {
err := config.Decode(&p.config, &config.DecodeOpts{ err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true, Interpolate: true,
@ -101,6 +111,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
Exclude: []string{ Exclude: []string{
"execute_command", "execute_command",
"install_command", "install_command",
"knife_command",
}, },
}, },
}, raws...) }, raws...)
@ -140,6 +151,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = p.guestOSTypeConfig.stagingDir p.config.StagingDir = p.guestOSTypeConfig.stagingDir
} }
if p.config.KnifeCommand == "" {
p.config.KnifeCommand = p.guestOSTypeConfig.knifeCommand
}
var errs *packer.MultiError var errs *packer.MultiError
if p.config.ConfigTemplate != "" { if p.config.ConfigTemplate != "" {
fi, err := os.Stat(p.config.ConfigTemplate) fi, err := os.Stat(p.config.ConfigTemplate)
@ -484,13 +499,18 @@ func (p *Provisioner) knifeExec(ui packer.Ui, comm packer.Communicator, node str
"-c", knifeConfigPath, "-c", knifeConfigPath,
} }
cmdText := fmt.Sprintf( p.config.ctx.Data = &KnifeTemplate{
"knife %s %s", strings.Join(args, " "), strings.Join(flags, " ")) Sudo: !p.config.PreventSudo,
if !p.config.PreventSudo { Flags: strings.Join(flags, " "),
cmdText = "sudo " + cmdText Args: strings.Join(args, " "),
} }
cmd := &packer.RemoteCmd{Command: cmdText} command, err := interpolate.Render(p.config.KnifeCommand, &p.config.ctx)
if err != nil {
return err
}
cmd := &packer.RemoteCmd{Command: command}
if err := cmd.StartWithUi(comm, ui); err != nil { if err := cmd.StartWithUi(comm, ui); err != nil {
return err return err
} }
@ -498,7 +518,7 @@ func (p *Provisioner) knifeExec(ui packer.Ui, comm packer.Communicator, node str
return fmt.Errorf( return fmt.Errorf(
"Non-zero exit status. See output above for more info.\n\n"+ "Non-zero exit status. See output above for more info.\n\n"+
"Command: %s", "Command: %s",
cmdText) command)
} }
return nil return nil

View File

@ -87,6 +87,7 @@ func TestProvisionerPrepare_commands(t *testing.T) {
commands := []string{ commands := []string{
"execute_command", "execute_command",
"install_command", "install_command",
"knife_command",
} }
for _, command := range commands { for _, command := range commands {

View File

@ -71,6 +71,11 @@ configuration is actually required.
- `json` (object) - An arbitrary mapping of JSON that will be available as - `json` (object) - An arbitrary mapping of JSON that will be available as
node attributes while running Chef. node attributes while running Chef.
- `knife_command` (string) - The command used to run Knife during node clean-up. This has
various [configuration template
variables](/docs/templates/configuration-templates.html) available. See
below for more information.
- `node_name` (string) - The name of the node to register with the - `node_name` (string) - The name of the node to register with the
Chef Server. This is optional and by default is packer-{{uuid}}. Chef Server. This is optional and by default is packer-{{uuid}}.
@ -194,7 +199,7 @@ This command can be customized using the `execute_command` configuration. As you
can see from the default value above, the value of this configuration can can see from the default value above, the value of this configuration can
contain various template variables, defined below: contain various template variables, defined below:
- `ConfigPath` - The path to the Chef configuration file. file. - `ConfigPath` - The path to the Chef configuration file.
- `JsonPath` - The path to the JSON attributes file for the node. - `JsonPath` - The path to the JSON attributes file for the node.
- `Sudo` - A boolean of whether to `sudo` the command or not, depending on the - `Sudo` - A boolean of whether to `sudo` the command or not, depending on the
value of the `prevent_sudo` configuration. value of the `prevent_sudo` configuration.
@ -219,6 +224,37 @@ powershell.exe -Command "(New-Object System.Net.WebClient).DownloadFile('http://
This command can be customized using the `install_command` configuration. This command can be customized using the `install_command` configuration.
## Knife Command
By default, Packer uses the following command (broken across multiple lines for
readability) to execute Chef:
``` {.liquid}
{{if .Sudo}}sudo {{end}}knife \
{{.Args}} \
{{.Flags}}
```
When guest_os_type is set to "windows", Packer uses the following command to
execute Chef. The full path to Chef is required because the PATH environment
variable changes don't immediately propogate to running processes.
``` {.liquid}
c:/opscode/chef/bin/knife.bat \
{{.Args}} \
{{.Flags}}
```
This command can be customized using the `knife_command` configuration. As you
can see from the default value above, the value of this configuration can
contain various template variables, defined below:
- `Args` - The command arguments that are getting passed to the Knife command.
- `Flags` - The command flags that are getting passed to the Knife command..
- `Sudo` - A boolean of whether to `sudo` the command or not, depending on the
value of the `prevent_sudo` configuration.
## Folder Permissions ## Folder Permissions
!> The `chef-client` provisioner will chmod the directory with your Chef keys !> The `chef-client` provisioner will chmod the directory with your Chef keys