Merge pull request #3554 from mitchellh/chef-provisioner-cleanup
provisioner/chef: Chef provisioner cleanup with Windows
This commit is contained in:
commit
91c7fb7749
|
@ -57,13 +57,23 @@ module VagrantPlugins
|
||||||
return 0 if command.empty?
|
return 0 if command.empty?
|
||||||
|
|
||||||
opts = {
|
opts = {
|
||||||
:error_check => true,
|
error_check: true,
|
||||||
:error_class => Errors::ExecutionError,
|
error_class: Errors::ExecutionError,
|
||||||
:error_key => :execution_error,
|
error_key: :execution_error,
|
||||||
:command => command,
|
command: command,
|
||||||
:shell => :powershell
|
shell: :powershell,
|
||||||
|
elevated: false
|
||||||
}.merge(opts || {})
|
}.merge(opts || {})
|
||||||
|
|
||||||
|
if opts[:elevated]
|
||||||
|
path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__)
|
||||||
|
command = Vagrant::Util::TemplateRenderer.render(path, options: {
|
||||||
|
username: shell.username,
|
||||||
|
password: shell.password,
|
||||||
|
command: command,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
output = shell.send(opts[:shell], command, &block)
|
output = shell.send(opts[:shell], command, &block)
|
||||||
execution_output(output, opts)
|
execution_output(output, opts)
|
||||||
end
|
end
|
||||||
|
@ -121,7 +131,7 @@ module VagrantPlugins
|
||||||
# The error classes expect the translation key to be _key, but that makes for an ugly
|
# The error classes expect the translation key to be _key, but that makes for an ugly
|
||||||
# configuration parameter, so we set it here from `error_key`
|
# configuration parameter, so we set it here from `error_key`
|
||||||
msg = "Command execution failed with an exit code of #{output[:exitcode]}"
|
msg = "Command execution failed with an exit code of #{output[:exitcode]}"
|
||||||
error_opts = opts.merge(:_key => opts[:error_key], :message => msg)
|
error_opts = opts.merge(_key: opts[:error_key], message: msg)
|
||||||
raise opts[:error_class], error_opts
|
raise opts[:error_class], error_opts
|
||||||
end
|
end
|
||||||
end #WinRM class
|
end #WinRM class
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
$command = "<%= options[:command] %>"
|
||||||
|
$user = '<%= options[:username] %>'
|
||||||
|
$password = '<%= options[:password] %>'
|
||||||
|
|
||||||
|
$task_name = "WinRM_Elevated_Shell"
|
||||||
|
$out_file = "$env:SystemRoot\Temp\WinRM_Elevated_Shell.log"
|
||||||
|
|
||||||
|
if (Test-Path $out_file) {
|
||||||
|
del $out_file
|
||||||
|
}
|
||||||
|
|
||||||
|
$task_xml = @'
|
||||||
|
<?xml version="1.0" encoding="UTF-16"?>
|
||||||
|
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
||||||
|
<Principals>
|
||||||
|
<Principal id="Author">
|
||||||
|
<UserId>{user}</UserId>
|
||||||
|
<LogonType>Password</LogonType>
|
||||||
|
<RunLevel>HighestAvailable</RunLevel>
|
||||||
|
</Principal>
|
||||||
|
</Principals>
|
||||||
|
<Settings>
|
||||||
|
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
||||||
|
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
||||||
|
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
||||||
|
<AllowHardTerminate>true</AllowHardTerminate>
|
||||||
|
<StartWhenAvailable>false</StartWhenAvailable>
|
||||||
|
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
||||||
|
<IdleSettings>
|
||||||
|
<StopOnIdleEnd>true</StopOnIdleEnd>
|
||||||
|
<RestartOnIdle>false</RestartOnIdle>
|
||||||
|
</IdleSettings>
|
||||||
|
<AllowStartOnDemand>true</AllowStartOnDemand>
|
||||||
|
<Enabled>true</Enabled>
|
||||||
|
<Hidden>false</Hidden>
|
||||||
|
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
||||||
|
<WakeToRun>false</WakeToRun>
|
||||||
|
<ExecutionTimeLimit>PT2H</ExecutionTimeLimit>
|
||||||
|
<Priority>4</Priority>
|
||||||
|
</Settings>
|
||||||
|
<Actions Context="Author">
|
||||||
|
<Exec>
|
||||||
|
<Command>cmd</Command>
|
||||||
|
<Arguments>{arguments}</Arguments>
|
||||||
|
</Exec>
|
||||||
|
</Actions>
|
||||||
|
</Task>
|
||||||
|
'@
|
||||||
|
|
||||||
|
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
|
||||||
|
$encoded_command = [Convert]::ToBase64String($bytes)
|
||||||
|
$arguments = "/c powershell.exe -EncodedCommand $encoded_command > $out_file 2>&1"
|
||||||
|
|
||||||
|
$task_xml = $task_xml.Replace("{arguments}", $arguments)
|
||||||
|
$task_xml = $task_xml.Replace("{user}", $user)
|
||||||
|
|
||||||
|
$schedule = New-Object -ComObject "Schedule.Service"
|
||||||
|
$schedule.Connect()
|
||||||
|
$task = $schedule.NewTask($null)
|
||||||
|
$task.XmlText = $task_xml
|
||||||
|
$folder = $schedule.GetFolder("\")
|
||||||
|
$folder.RegisterTaskDefinition($task_name, $task, 6, $user, $password, 1, $null) | Out-Null
|
||||||
|
|
||||||
|
$registered_task = $folder.GetTask("\$task_name")
|
||||||
|
$registered_task.Run($null) | Out-Null
|
||||||
|
|
||||||
|
$timeout = 10
|
||||||
|
$sec = 0
|
||||||
|
while ( (!($registered_task.state -eq 4)) -and ($sec -lt $timeout) ) {
|
||||||
|
Start-Sleep -s 1
|
||||||
|
$sec++
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the entire file, but only write out new lines we haven't seen before
|
||||||
|
$numLinesRead = 0
|
||||||
|
do {
|
||||||
|
Start-Sleep -m 100
|
||||||
|
|
||||||
|
if (Test-Path $out_file) {
|
||||||
|
$text = (get-content $out_file)
|
||||||
|
$numLines = ($text | Measure-Object -line).lines
|
||||||
|
$numLinesToRead = $numLines - $numLinesRead
|
||||||
|
|
||||||
|
if ($numLinesToRead -gt 0) {
|
||||||
|
$text | select -first $numLinesToRead -skip $numLinesRead | ForEach {
|
||||||
|
Write-Host "$_"
|
||||||
|
}
|
||||||
|
$numLinesRead += $numLinesToRead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!($registered_task.state -eq 3))
|
||||||
|
|
||||||
|
$exit_code = $registered_task.LastTaskResult
|
||||||
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($schedule) | Out-Null
|
||||||
|
exit $exit_code
|
|
@ -1,15 +1,53 @@
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Chef
|
module Chef
|
||||||
class CommandBuilder
|
class CommandBuilder
|
||||||
def initialize(machine, config, client_type)
|
def initialize(config, client_type, is_windows=false, is_ui_colored=false)
|
||||||
@machine = machine
|
@client_type = client_type
|
||||||
@config = config
|
@config = config
|
||||||
@client_type = client_type
|
@is_windows = is_windows
|
||||||
|
@is_ui_colored = is_ui_colored
|
||||||
|
|
||||||
if client_type != :solo && client_type != :client
|
if client_type != :solo && client_type != :client
|
||||||
raise 'Invalid client_type, expected solo or client'
|
raise 'Invalid client_type, expected solo or client'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_command
|
||||||
|
"#{command_env}#{chef_binary_path} #{chef_arguments}"
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def command_env
|
||||||
|
@config.binary_env ? "#{@config.binary_env} " : ""
|
||||||
|
end
|
||||||
|
|
||||||
|
def chef_binary_path
|
||||||
|
binary_path = "chef-#{@client_type}"
|
||||||
|
if @config.binary_path
|
||||||
|
binary_path = guest_friendly_path(File.join(@config.binary_path, binary_path))
|
||||||
|
end
|
||||||
|
binary_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def chef_arguments
|
||||||
|
chef_arguments = "-c #{provisioning_path("#{@client_type}.rb")}"
|
||||||
|
chef_arguments << " -j #{provisioning_path("dna.json")}"
|
||||||
|
chef_arguments << " #{@config.arguments}" if @config.arguments
|
||||||
|
chef_arguments << " --no-color" unless @is_ui_colored
|
||||||
|
chef_arguments.strip
|
||||||
|
end
|
||||||
|
|
||||||
|
def provisioning_path(file)
|
||||||
|
guest_friendly_path(File.join(@config.provisioning_path, file))
|
||||||
|
end
|
||||||
|
|
||||||
|
def guest_friendly_path(path)
|
||||||
|
return path unless @is_windows
|
||||||
|
path.gsub!("/", "\\")
|
||||||
|
path = "c:#{path}" if path.start_with?("\\")
|
||||||
|
path
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
module VagrantPlugins
|
|
||||||
module Chef
|
|
||||||
class CommandBuilderLinux < CommandBuilder
|
|
||||||
def build_command
|
|
||||||
if @client_type == :solo
|
|
||||||
return build_command_solo
|
|
||||||
else
|
|
||||||
return build_command_client
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def build_command_client
|
|
||||||
command_env = @config.binary_env ? "#{@config.binary_env} " : ""
|
|
||||||
command_args = @config.arguments ? " #{@config.arguments}" : ""
|
|
||||||
|
|
||||||
binary_path = "chef-client"
|
|
||||||
binary_path ||= File.join(@config.binary_path, binary_path)
|
|
||||||
|
|
||||||
return "#{command_env}#{binary_path} " +
|
|
||||||
"-c #{@config.provisioning_path}/client.rb " +
|
|
||||||
"-j #{@config.provisioning_path}/dna.json #{command_args}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_command_solo
|
|
||||||
options = [
|
|
||||||
"-c #{@config.provisioning_path}/solo.rb",
|
|
||||||
"-j #{@config.provisioning_path}/dna.json"
|
|
||||||
]
|
|
||||||
|
|
||||||
if !@machine.env.ui.is_a?(Vagrant::UI::Colored)
|
|
||||||
options << "--no-color"
|
|
||||||
end
|
|
||||||
|
|
||||||
command_env = @config.binary_env ? "#{@config.binary_env} " : ""
|
|
||||||
command_args = @config.arguments ? " #{@config.arguments}" : ""
|
|
||||||
|
|
||||||
binary_path = "chef-solo"
|
|
||||||
binary_path ||= File.join(@config.binary_path, binary_path)
|
|
||||||
|
|
||||||
return "#{command_env}#{binary_path} " +
|
|
||||||
"#{options.join(" ")} #{command_args}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,83 +0,0 @@
|
||||||
require "tempfile"
|
|
||||||
|
|
||||||
require "vagrant/util/template_renderer"
|
|
||||||
|
|
||||||
module VagrantPlugins
|
|
||||||
module Chef
|
|
||||||
class CommandBuilderWindows < CommandBuilder
|
|
||||||
def build_command
|
|
||||||
binary_path = "chef-#{@client_type}"
|
|
||||||
if @config.binary_path
|
|
||||||
binary_path = File.join(@config.binary_path, binary_path)
|
|
||||||
binary_path.gsub!("/", "\\")
|
|
||||||
binary_path = "c:#{binary_path}" if binary_path.start_with?("\\")
|
|
||||||
end
|
|
||||||
|
|
||||||
chef_arguments = "-c #{provisioning_path("#{@client_type}.rb")}"
|
|
||||||
chef_arguments << " -j #{provisioning_path("dna.json")}"
|
|
||||||
chef_arguments << " #{@config.arguments}" if @config.arguments
|
|
||||||
|
|
||||||
command_env = ""
|
|
||||||
command_env = "#{@config.binary_env} " if @config.binary_env
|
|
||||||
|
|
||||||
task_ps1_path = provisioning_path("cheftask.ps1")
|
|
||||||
|
|
||||||
opts = {
|
|
||||||
user: @machine.config.winrm.username,
|
|
||||||
pass: @machine.config.winrm.password,
|
|
||||||
chef_arguments: chef_arguments,
|
|
||||||
chef_binary_path: "#{command_env}#{binary_path}",
|
|
||||||
chef_stdout_log: provisioning_path("chef-#{@client_type}.log"),
|
|
||||||
chef_stderr_log: provisioning_path("chef-#{@client_type}.err.log"),
|
|
||||||
chef_task_exitcode: provisioning_path('cheftask.exitcode'),
|
|
||||||
chef_task_running: provisioning_path('cheftask.running'),
|
|
||||||
chef_task_ps1: task_ps1_path,
|
|
||||||
chef_task_run_ps1: provisioning_path('cheftaskrun.ps1'),
|
|
||||||
chef_task_xml: provisioning_path('cheftask.xml'),
|
|
||||||
}
|
|
||||||
|
|
||||||
# Upload the files we'll need
|
|
||||||
render_and_upload(
|
|
||||||
"cheftaskrun.ps1", opts[:chef_task_run_ps1], opts)
|
|
||||||
render_and_upload(
|
|
||||||
"cheftask.xml", opts[:chef_task_xml], opts)
|
|
||||||
render_and_upload(
|
|
||||||
"cheftask.ps1", opts[:chef_task_ps1], opts)
|
|
||||||
|
|
||||||
return <<-EOH
|
|
||||||
$old = Get-ExecutionPolicy;
|
|
||||||
Set-ExecutionPolicy Unrestricted -force;
|
|
||||||
#{task_ps1_path};
|
|
||||||
Set-ExecutionPolicy $old -force
|
|
||||||
EOH
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def provisioning_path(file)
|
|
||||||
path = "#{@config.provisioning_path}/#{file}"
|
|
||||||
path.gsub!("/", "\\")
|
|
||||||
path = "c:#{path}" if path.start_with?("\\")
|
|
||||||
path
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_and_upload(template, dest, opts)
|
|
||||||
path = File.expand_path("../scripts/#{template}", __FILE__)
|
|
||||||
data = Vagrant::Util::TemplateRenderer.render(path, options)
|
|
||||||
|
|
||||||
file = Tempfile.new("vagrant-chef")
|
|
||||||
file.binmode
|
|
||||||
file.write(data)
|
|
||||||
file.fsync
|
|
||||||
file.close
|
|
||||||
|
|
||||||
@machine.communicate.upload(file.path, dest)
|
|
||||||
ensure
|
|
||||||
if file
|
|
||||||
file.close
|
|
||||||
file.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -6,8 +6,6 @@ module VagrantPlugins
|
||||||
module Chef
|
module Chef
|
||||||
root = Pathname.new(File.expand_path("../", __FILE__))
|
root = Pathname.new(File.expand_path("../", __FILE__))
|
||||||
autoload :CommandBuilder, root.join("command_builder")
|
autoload :CommandBuilder, root.join("command_builder")
|
||||||
autoload :CommandBuilderLinux, root.join("command_builder_linux")
|
|
||||||
autoload :CommandBuilderWindows, root.join("command_builder_windows")
|
|
||||||
|
|
||||||
class Plugin < Vagrant.plugin("2")
|
class Plugin < Vagrant.plugin("2")
|
||||||
name "chef"
|
name "chef"
|
||||||
|
|
|
@ -26,9 +26,7 @@ module VagrantPlugins
|
||||||
# This returns the command to run Chef for the given client
|
# This returns the command to run Chef for the given client
|
||||||
# type.
|
# type.
|
||||||
def build_command(client)
|
def build_command(client)
|
||||||
builder_klass = CommandBuilderLinux
|
builder = CommandBuilder.new(@config, client, windows?, @machine.env.ui.is_a?(Vagrant::UI::Colored))
|
||||||
builder_klass = CommandBuilderWindows if windows?
|
|
||||||
builder = builder_klass.new(@machine, @config, client)
|
|
||||||
return builder.build_command
|
return builder.build_command
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,10 @@ module VagrantPlugins
|
||||||
@machine.ui.warn(I18n.t("vagrant.chef_run_list_empty"))
|
@machine.ui.warn(I18n.t("vagrant.chef_run_list_empty"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @machine.guest.capability?(:wait_for_reboot)
|
||||||
|
@machine.guest.capability(:wait_for_reboot)
|
||||||
|
end
|
||||||
|
|
||||||
if windows?
|
if windows?
|
||||||
# This re-establishes our symbolic links if they were
|
# This re-establishes our symbolic links if they were
|
||||||
# created between now and a reboot
|
# created between now and a reboot
|
||||||
|
@ -75,7 +79,8 @@ module VagrantPlugins
|
||||||
@machine.ui.info I18n.t("vagrant.provisioners.chef.running_client_again")
|
@machine.ui.info I18n.t("vagrant.provisioners.chef.running_client_again")
|
||||||
end
|
end
|
||||||
|
|
||||||
exit_status = @machine.communicate.sudo(command, :error_check => false) do |type, data|
|
opts = { error_check: false, elevated: true }
|
||||||
|
exit_status = @machine.communicate.sudo(command, opts) do |type, data|
|
||||||
# Output the data with the proper color based on the stream.
|
# Output the data with the proper color based on the stream.
|
||||||
color = type == :stdout ? :green : :red
|
color = type == :stdout ? :green : :red
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,10 @@ module VagrantPlugins
|
||||||
@machine.ui.warn(I18n.t("vagrant.chef_run_list_empty"))
|
@machine.ui.warn(I18n.t("vagrant.chef_run_list_empty"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @machine.guest.capability?(:wait_for_reboot)
|
||||||
|
@machine.guest.capability(:wait_for_reboot)
|
||||||
|
end
|
||||||
|
|
||||||
if windows?
|
if windows?
|
||||||
# This re-establishes our symbolic links if they were
|
# This re-establishes our symbolic links if they were
|
||||||
# created between now and a reboot
|
# created between now and a reboot
|
||||||
|
@ -151,7 +155,8 @@ module VagrantPlugins
|
||||||
@machine.ui.info I18n.t("vagrant.provisioners.chef.running_solo_again")
|
@machine.ui.info I18n.t("vagrant.provisioners.chef.running_solo_again")
|
||||||
end
|
end
|
||||||
|
|
||||||
exit_status = @machine.communicate.sudo(command, :error_check => false) do |type, data|
|
opts = { error_check: false, elevated: true }
|
||||||
|
exit_status = @machine.communicate.sudo(command, opts) do |type, data|
|
||||||
# Output the data with the proper color based on the stream.
|
# Output the data with the proper color based on the stream.
|
||||||
color = type == :stdout ? :green : :red
|
color = type == :stdout ? :green : :red
|
||||||
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
# kill the task so we can recreate it
|
|
||||||
schtasks /delete /tn "chef-solo" /f 2>&1 | out-null
|
|
||||||
|
|
||||||
# Ensure the chef task running file doesn't exist from a previous failure
|
|
||||||
if (Test-Path "<%= options[:chef_task_running] %>") {
|
|
||||||
del "<%= options[:chef_task_running] %>"
|
|
||||||
}
|
|
||||||
|
|
||||||
# schedule the task to run once in the far distant future
|
|
||||||
schtasks /create /tn 'chef-solo' /xml '<%= options[:chef_task_xml] %>' /ru '<%= options[:user] %>' /rp '<%= options[:pass] %>' | Out-Null
|
|
||||||
|
|
||||||
# start the scheduled task right now
|
|
||||||
schtasks /run /tn "chef-solo" | Out-Null
|
|
||||||
|
|
||||||
# wait for run_chef.ps1 to start or timeout after 1 minute
|
|
||||||
$timeoutSeconds = 60
|
|
||||||
$elapsedSeconds = 0
|
|
||||||
while ( (!(Test-Path "<%= options[:chef_task_running] %>")) -and ($elapsedSeconds -lt $timeoutSeconds) ) {
|
|
||||||
Start-Sleep -s 1
|
|
||||||
$elapsedSeconds++
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($elapsedSeconds -ge $timeoutSeconds) {
|
|
||||||
Write-Error "Timed out waiting for chef scheduled task to start"
|
|
||||||
exit -2
|
|
||||||
}
|
|
||||||
|
|
||||||
# read the entire file, but only write out new lines we haven't seen before
|
|
||||||
$numLinesRead = 0
|
|
||||||
$success = $TRUE
|
|
||||||
while (Test-Path "<%= options[:chef_task_running] %>") {
|
|
||||||
Start-Sleep -m 100
|
|
||||||
|
|
||||||
if (Test-Path "<%= options[:chef_stdout_log] %>") {
|
|
||||||
$text = (get-content "<%= options[:chef_stdout_log] %>")
|
|
||||||
$numLines = ($text | Measure-Object -line).lines
|
|
||||||
$numLinesToRead = $numLines - $numLinesRead
|
|
||||||
|
|
||||||
if ($numLinesToRead -gt 0) {
|
|
||||||
$text | select -first $numLinesToRead -skip $numLinesRead | ForEach {
|
|
||||||
Write-Host "$_"
|
|
||||||
}
|
|
||||||
$numLinesRead += $numLinesToRead
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit Get-Content "<%= options[:chef_task_exitcode] %>"
|
|
|
@ -1,45 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-16"?>
|
|
||||||
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
||||||
<RegistrationInfo>
|
|
||||||
<Date>2013-06-21T22:41:43</Date>
|
|
||||||
<Author>Administrator</Author>
|
|
||||||
</RegistrationInfo>
|
|
||||||
<Triggers>
|
|
||||||
<TimeTrigger>
|
|
||||||
<StartBoundary>2045-01-01T12:00:00</StartBoundary>
|
|
||||||
<Enabled>true</Enabled>
|
|
||||||
</TimeTrigger>
|
|
||||||
</Triggers>
|
|
||||||
<Principals>
|
|
||||||
<Principal id="Author">
|
|
||||||
<UserId>vagrant</UserId>
|
|
||||||
<LogonType>Password</LogonType>
|
|
||||||
<RunLevel>HighestAvailable</RunLevel>
|
|
||||||
</Principal>
|
|
||||||
</Principals>
|
|
||||||
<Settings>
|
|
||||||
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
||||||
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
||||||
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
||||||
<AllowHardTerminate>true</AllowHardTerminate>
|
|
||||||
<StartWhenAvailable>false</StartWhenAvailable>
|
|
||||||
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
|
||||||
<IdleSettings>
|
|
||||||
<StopOnIdleEnd>true</StopOnIdleEnd>
|
|
||||||
<RestartOnIdle>false</RestartOnIdle>
|
|
||||||
</IdleSettings>
|
|
||||||
<AllowStartOnDemand>true</AllowStartOnDemand>
|
|
||||||
<Enabled>true</Enabled>
|
|
||||||
<Hidden>false</Hidden>
|
|
||||||
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
|
||||||
<WakeToRun>false</WakeToRun>
|
|
||||||
<ExecutionTimeLimit>PT2H</ExecutionTimeLimit>
|
|
||||||
<Priority>4</Priority>
|
|
||||||
</Settings>
|
|
||||||
<Actions Context="Author">
|
|
||||||
<Exec>
|
|
||||||
<Command>powershell</Command>
|
|
||||||
<Arguments>-file <%= options[:chef_task_run_ps1] %></Arguments>
|
|
||||||
</Exec>
|
|
||||||
</Actions>
|
|
||||||
</Task>
|
|
|
@ -1,18 +0,0 @@
|
||||||
$exitCode = -1
|
|
||||||
Set-ExecutionPolicy Unrestricted -force;
|
|
||||||
|
|
||||||
Try
|
|
||||||
{
|
|
||||||
"running" | Out-File "<%= options[:chef_task_running] %>"
|
|
||||||
$process = (Start-Process "<%= options[:chef_binary_path] %>" -ArgumentList "<%= options[:chef_arguments] %>" -NoNewWindow -PassThru -Wait -RedirectStandardOutput "<%= options[:chef_stdout_log] %>" -RedirectStandardError "<%= options[:chef_stderr_log] %>")
|
|
||||||
$exitCode = $process.ExitCode
|
|
||||||
}
|
|
||||||
Finally
|
|
||||||
{
|
|
||||||
$exitCode | Out-File "<%= options[:chef_task_exitcode] %>"
|
|
||||||
if (Test-Path "<%= options[:chef_task_running] %>") {
|
|
||||||
del "<%= options[:chef_task_running] %>"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit $exitCode
|
|
|
@ -17,6 +17,11 @@ describe VagrantPlugins::CommunicatorWinRM::Communicator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(shell).to receive(:username).and_return('vagrant')
|
||||||
|
allow(shell).to receive(:password).and_return('password')
|
||||||
|
end
|
||||||
|
|
||||||
describe ".ready?" do
|
describe ".ready?" do
|
||||||
it "returns true if hostname command executes without error" do
|
it "returns true if hostname command executes without error" do
|
||||||
expect(shell).to receive(:powershell).with("hostname").and_return({ exitcode: 0 })
|
expect(shell).to receive(:powershell).with("hostname").and_return({ exitcode: 0 })
|
||||||
|
@ -42,6 +47,16 @@ describe VagrantPlugins::CommunicatorWinRM::Communicator do
|
||||||
expect(subject.execute("dir")).to eq(0)
|
expect(subject.execute("dir")).to eq(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "wraps command in elevated shell script when elevated is true" do
|
||||||
|
expect(shell).to receive(:powershell) do |cmd|
|
||||||
|
expect(cmd).to include("$command = \"dir\"")
|
||||||
|
expect(cmd).to include("$user = 'vagrant'")
|
||||||
|
expect(cmd).to include("$password = 'password'")
|
||||||
|
expect(cmd).to include("New-Object -ComObject \"Schedule.Service\"")
|
||||||
|
end.and_return({ exitcode: 0 })
|
||||||
|
expect(subject.execute("dir", { elevated: true })).to eq(0)
|
||||||
|
end
|
||||||
|
|
||||||
it "can use cmd shell" do
|
it "can use cmd shell" do
|
||||||
expect(shell).to receive(:cmd).with(kind_of(String)).and_return({ exitcode: 0 })
|
expect(shell).to receive(:cmd).with(kind_of(String)).and_return({ exitcode: 0 })
|
||||||
expect(subject.execute("dir", { :shell => :cmd })).to eq(0)
|
expect(subject.execute("dir", { :shell => :cmd })).to eq(0)
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
require_relative "../../../base"
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/provisioners/chef/command_builder")
|
||||||
|
|
||||||
|
describe VagrantPlugins::Chef::CommandBuilder do
|
||||||
|
|
||||||
|
let(:machine) { double("machine") }
|
||||||
|
let(:chef_config) { double("chef_config") }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
allow(chef_config).to receive(:provisioning_path).and_return('/tmp/vagrant-chef-1')
|
||||||
|
allow(chef_config).to receive(:arguments).and_return(nil)
|
||||||
|
allow(chef_config).to receive(:binary_env).and_return(nil)
|
||||||
|
allow(chef_config).to receive(:binary_path).and_return(nil)
|
||||||
|
allow(chef_config).to receive(:binary_env).and_return(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.initialize' do
|
||||||
|
it 'should raise when chef type is not client or solo' do
|
||||||
|
expect { VagrantPlugins::Chef::CommandBuilder.new(chef_config, :client_bad) }.
|
||||||
|
to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'build_command' do
|
||||||
|
describe 'windows' do
|
||||||
|
subject do
|
||||||
|
VagrantPlugins::Chef::CommandBuilder.new(chef_config, :client, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes the chef-client in PATH by default" do
|
||||||
|
expect(subject.build_command()).to match(/^chef-client/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes the chef-client using full path if binary_path is specified" do
|
||||||
|
allow(chef_config).to receive(:binary_path).and_return(
|
||||||
|
"c:\\opscode\\chef\\bin\\chef-client")
|
||||||
|
expect(subject.build_command()).to match(/^c:\\opscode\\chef\\bin\\chef-client\\chef-client/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "builds a guest friendly client.rb path" do
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
'-c c:\\tmp\\vagrant-chef-1\\client.rb')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "builds a guest friendly solo.json path" do
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
'-j c:\\tmp\\vagrant-chef-1\\dna.json')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes Chef arguments if specified' do
|
||||||
|
allow(chef_config).to receive(:arguments).and_return("-l DEBUG")
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
'-l DEBUG')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes --no-color if UI is not colored' do
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
' --no-color')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'linux' do
|
||||||
|
subject do
|
||||||
|
VagrantPlugins::Chef::CommandBuilder.new(chef_config, :client, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes the chef-client in PATH by default" do
|
||||||
|
expect(subject.build_command()).to match(/^chef-client/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes the chef-client using full path if binary_path is specified" do
|
||||||
|
allow(chef_config).to receive(:binary_path).and_return(
|
||||||
|
"/opt/chef/chef-client")
|
||||||
|
expect(subject.build_command()).to match(/^\/opt\/chef\/chef-client/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "builds a guest friendly client.rb path" do
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
'-c /tmp/vagrant-chef-1/client.rb')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "builds a guest friendly solo.json path" do
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
'-j /tmp/vagrant-chef-1/dna.json')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes Chef arguments if specified' do
|
||||||
|
allow(chef_config).to receive(:arguments).and_return("-l DEBUG")
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
'-l DEBUG')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes --no-color if UI is not colored' do
|
||||||
|
expect(subject.build_command()).to include(
|
||||||
|
' --no-color')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes environment variables if specified' do
|
||||||
|
allow(chef_config).to receive(:binary_env).and_return("ENVVAR=VAL")
|
||||||
|
expect(subject.build_command()).to match(/^ENVVAR=VAL /)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue