diff --git a/plugins/provisioners/salt/bootstrap-salt.ps1 b/plugins/provisioners/salt/bootstrap-salt.ps1 new file mode 100644 index 000000000..10138281f --- /dev/null +++ b/plugins/provisioners/salt/bootstrap-salt.ps1 @@ -0,0 +1,60 @@ +# Copy minion keys & config to correct location +New-Item c:\salt\conf\pki\minion\ -ItemType directory | out-null + +# Check if minion keys have been uploaded +if (Test-Path C:\tmp\minion.pem) { + cp C:\tmp\minion.pem C:\salt\conf\pki\minion\ + cp C:\tmp\minion.pub C:\salt\conf\pki\minion\ +} + +# Check if minion config has been uploaded +if (Test-Path C:\tmp\minion) { + cp C:\tmp\minion C:\salt\conf\ +} + +# Detect architecture +if ([IntPtr]::Size -eq 4) { + $arch = "win32" +} else { + $arch = "AMD64" +} + +# Download minion setup file +Write-Host "Downloading Salt minion installer ($arch)..." +$webclient = New-Object System.Net.WebClient +$url = "https://docs.saltstack.com/downloads/Salt-Minion-2014.1.3-1-$arch-Setup.exe" +$file = "C:\tmp\salt.exe" +$webclient.DownloadFile($url, $file) + +# Install minion silently +Write-Host "Installing Salt minion..." +C:\tmp\salt.exe /S + +# Wait for salt-minion service to be registered before trying to start it +$service = Get-Service salt-minion -ErrorAction SilentlyContinue +While (!$service) { + Start-Sleep -s 2 + $service = Get-Service salt-minion -ErrorAction SilentlyContinue +} + +# Start service +Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue + +# Check if service is started, otherwise retry starting the +# service 4 times. +$try = 0 +While (($service.Status -ne "Running") -and ($try -ne 4)) { + Start-Service -Name "salt-minion" -ErrorAction SilentlyContinue + $service = Get-Service salt-minion -ErrorAction SilentlyContinue + Start-Sleep -s 2 + $try += 1 +} + +# If the salt-minion service is still not running, something probably +# went wrong and user intervention is required - report failure. +if ($service.Status -eq "Stopped") { + Write-Host "Failed to start Salt minion" + exit 1 +} + +Write-Host "Salt minion successfully installed" diff --git a/plugins/provisioners/salt/provisioner.rb b/plugins/provisioners/salt/provisioner.rb index 4946cbc7f..a330edfdd 100644 --- a/plugins/provisioners/salt/provisioner.rb +++ b/plugins/provisioners/salt/provisioner.rb @@ -4,11 +4,6 @@ module VagrantPlugins module Salt class Provisioner < Vagrant.plugin("2", :provisioner) def provision - if @machine.config.vm.communicator == :winrm - raise Vagrant::Errors::ProvisionerWinRMUnsupported, - name: "salt" - end - upload_configs upload_keys run_bootstrap_script @@ -38,16 +33,31 @@ module VagrantPlugins ## Determine States, ie: install vs configure desired_binaries = [] if !@config.no_minion - desired_binaries.push('salt-minion') - desired_binaries.push('salt-call') + if @machine.config.vm.communicator == :winrm + desired_binaries.push('C:\\salt\\salt-minion.exe') + desired_binaries.push('C:\\salt\\salt-call.exe') + else + desired_binaries.push('salt-minion') + desired_binaries.push('salt-call') + end end if @config.install_master - desired_binaries.push('salt-master') + if @machine.config.vm.communicator == :winrm + raise Vagrant::Errors::ProvisionerWinRMUnsupported, + name: "salt.install_master" + else + desired_binaries.push('salt-master') + end end if @config.install_syndic - desired_binaries.push('salt-syndic') + if @machine.config.vm.communicator == :winrm + raise Vagrant::Errors::ProvisionerWinRMUnsupported, + name: "salt.install_syndic" + else + desired_binaries.push('salt-syndic') + end end found = true @@ -77,7 +87,11 @@ module VagrantPlugins end def temp_config_dir - return @config.temp_config_dir || "/tmp" + if @machine.config.vm.communicator == :winrm + return @config.temp_config_dir || "C:\\tmp" + else + return @config.temp_config_dir || "/tmp" + end end # Generates option string for bootstrap script @@ -191,7 +205,11 @@ module VagrantPlugins if @config.bootstrap_script bootstrap_abs_path = expanded_path(@config.bootstrap_script) else - bootstrap_abs_path = Pathname.new("../bootstrap-salt.sh").expand_path(__FILE__) + if @machine.config.vm.communicator == :winrm + bootstrap_abs_path = Pathname.new("../bootstrap-salt.ps1").expand_path(__FILE__) + else + bootstrap_abs_path = Pathname.new("../bootstrap-salt.sh").expand_path(__FILE__) + end end return bootstrap_abs_path @@ -212,25 +230,43 @@ module VagrantPlugins end bootstrap_path = get_bootstrap - bootstrap_destination = File.join(config_dir, "bootstrap_salt.sh") + if @machine.config.vm.communicator == :winrm + bootstrap_destination = File.join(config_dir, "bootstrap_salt.ps1") + else + bootstrap_destination = File.join(config_dir, "bootstrap_salt.sh") + end + @machine.communicate.sudo("rm -f %s" % bootstrap_destination) @machine.communicate.upload(bootstrap_path.to_s, bootstrap_destination) @machine.communicate.sudo("chmod +x %s" % bootstrap_destination) - bootstrap = @machine.communicate.sudo("%s %s" % [bootstrap_destination, options]) do |type, data| - if data[0] == "\n" - # Remove any leading newline but not whitespace. If we wanted to - # remove newlines and whitespace we would have used data.lstrip - data = data[1..-1] + if @machine.config.vm.communicator == :winrm + bootstrap = @machine.communicate.sudo("powershell.exe -executionpolicy bypass -file %s" % [bootstrap_destination]) do |type, data| + if data[0] == "\n" + # Remove any leading newline but not whitespace. If we wanted to + # remove newlines and whitespace we would have used data.lstrip + data = data[1..-1] + end + if @config.verbose + @machine.env.ui.info(data.rstrip) + end end - if @config.verbose - @machine.env.ui.info(data.rstrip) + else + bootstrap = @machine.communicate.sudo("%s %s" % [bootstrap_destination, options]) do |type, data| + if data[0] == "\n" + # Remove any leading newline but not whitespace. If we wanted to + # remove newlines and whitespace we would have used data.lstrip + data = data[1..-1] + end + if @config.verbose + @machine.env.ui.info(data.rstrip) + end end end if !bootstrap raise Salt::Errors::SaltError, :bootstrap_failed end - + if configure and !install @machine.env.ui.info "Salt successfully configured!" elsif configure and install @@ -242,19 +278,20 @@ module VagrantPlugins @machine.env.ui.info "Salt did not need installing or configuring." end end + def call_overstate if @config.run_overstate - if @config.install_master - @machine.env.ui.info "Calling state.overstate... (this may take a while)" - @machine.communicate.sudo("salt '*' saltutil.sync_all") - @machine.communicate.sudo("salt-run state.over") do |type, data| - if @config.verbose - @machine.env.ui.info(data) - end + if @config.install_master + @machine.env.ui.info "Calling state.overstate... (this may take a while)" + @machine.communicate.sudo("salt '*' saltutil.sync_all") + @machine.communicate.sudo("salt-run state.over") do |type, data| + if @config.verbose + @machine.env.ui.info(data) end - else - @machine.env.ui.info "run_overstate does not make sense on a minion. Not running state.overstate." end + else + @machine.env.ui.info "run_overstate does not make sense on a minion. Not running state.overstate." + end else @machine.env.ui.info "run_overstate set to false. Not running state.overstate." end @@ -271,10 +308,20 @@ module VagrantPlugins end end else - @machine.communicate.sudo("salt-call saltutil.sync_all") - @machine.communicate.sudo("salt-call state.highstate #{get_loglevel}#{get_colorize}#{get_pillar}") do |type, data| - if @config.verbose - @machine.env.ui.info(data) + if @machine.config.vm.communicator == :winrm + opts = { elevated: true } + @machine.communicate.execute("C:\\salt\\salt-call.exe saltutil.sync_all", opts) + @machine.communicate.execute("C:\\salt\\salt-call.exe state.highstate #{get_loglevel}#{get_colorize}#{get_pillar}", opts) do |type, data| + if @config.verbose + @machine.env.ui.info(data) + end + end + else + @machine.communicate.sudo("salt-call saltutil.sync_all") + @machine.communicate.sudo("salt-call state.highstate #{get_loglevel}#{get_colorize}#{get_pillar}") do |type, data| + if @config.verbose + @machine.env.ui.info(data) + end end end end diff --git a/website/docs/source/v2/provisioning/salt.html.md b/website/docs/source/v2/provisioning/salt.html.md index 2f2f3fe4f..f66ac7c60 100644 --- a/website/docs/source/v2/provisioning/salt.html.md +++ b/website/docs/source/v2/provisioning/salt.html.md @@ -48,18 +48,19 @@ masterless setup. * `install_master` (boolean) - Should vagrant install the salt-master -on this machine +on this machine. Not supported on Windows. * `no_minion` (boolean) - Don't install the minion, default `false` * `install_syndic` (boolean) - Install the salt-syndic, default -`false` +`false`. Not supported on Windows. * `install_type` (stable | git | daily | testing) - Whether to install from a -distribution's stable package manager, git tree-ish, daily ppa, or testing repository. +distribution's stable package manager, git tree-ish, daily ppa, or testing repository. +Not supported on Windows. * `install_args` (develop) - When performing a git install, -you can specify a branch, tag, or any treeish. +you can specify a branch, tag, or any treeish. Not supported on Windows. * `always_install` (boolean) - Installs salt binaries even if they are already detected, default `false`