vagrant/plugins/provisioners/shell/provisioner.rb

129 lines
4.0 KiB
Ruby
Raw Normal View History

2012-04-19 04:53:19 +00:00
require "pathname"
require "tempfile"
2012-01-07 01:36:51 +00:00
require "vagrant/util/downloader"
2012-04-19 04:53:19 +00:00
module VagrantPlugins
module Shell
2012-11-07 05:21:36 +00:00
class Provisioner < Vagrant.plugin("2", :provisioner)
def provision
if @config.vm.communicator == :winrm
provision_winrm
else
provision_ssh
end
end
protected
# This is the provision method called if SSH is what is running
# on the remote end, which assumes a POSIX-style host.
def provision_ssh
args = ""
if config.args.is_a?(String)
args = " #{config.args.to_s}"
elsif config.args.is_a?(Array)
args = config.args.map { |a| quote_and_escape(a) }
args = " #{args.join(" ")}"
2013-07-19 01:35:37 +00:00
end
command = "chmod +x #{config.upload_path} && #{config.upload_path}#{args}"
with_script_file do |path|
# Upload the script to the machine
@machine.communicate.tap do |comm|
# Reset upload path permissions for the current ssh user
user = @machine.ssh_info[:username]
comm.sudo("chown -R #{user} #{config.upload_path}",
:error_check => false)
comm.upload(path.to_s, config.upload_path)
if config.path
@machine.ui.detail(I18n.t("vagrant.provisioners.shell.running",
script: path.to_s))
else
@machine.ui.detail(I18n.t("vagrant.provisioners.shell.running",
script: "inline script"))
end
# Execute it with sudo
comm.execute(command, sudo: config.privileged) do |type, data|
if [:stderr, :stdout].include?(type)
# Output the data with the proper color based on the stream.
color = type == :stdout ? :green : :red
2013-11-24 00:05:44 +00:00
options = {
new_line: false,
prefix: false,
}
options[:color] = color if !config.keep_color
@machine.env.ui.info(data, options)
end
2011-12-15 03:02:10 +00:00
end
end
end
end
# This provisions using WinRM, which assumes a PowerShell
# console on the other side.
def provision_winrm
# TODO
end
# Quote and escape strings for shell execution, thanks to Capistrano.
2013-07-19 01:35:37 +00:00
def quote_and_escape(text, quote = '"')
"#{quote}#{text.gsub(/#{quote}/) { |m| "#{m}\\#{m}#{m}" }}#{quote}"
end
# This method yields the path to a script to upload and execute
# on the remote server. This method will properly clean up the
# script file if needed.
def with_script_file
script = nil
if config.remote?
download_path = @machine.env.tmp_path.join(
"#{@machine.id}-remote-script")
download_path.delete if download_path.file?
Vagrant::Util::Downloader.new(config.path, download_path).download!
script = download_path.read
download_path.delete
elsif config.path
# Just yield the path to that file...
root_path = @machine.env.root_path
script = Pathname.new(config.path).expand_path(root_path).read
else
# The script is just the inline code...
script = config.inline
end
# Replace Windows line endings with Unix ones unless binary file
2013-09-21 00:24:59 +00:00
script.gsub!(/\r\n?$/, "\n") if !config.binary
# Otherwise we have an inline script, we need to Tempfile it,
# and handle it specially...
file = Tempfile.new('vagrant-shell')
2012-10-13 02:51:25 +00:00
# Unless you set binmode, on a Windows host the shell script will
# have CRLF line endings instead of LF line endings, causing havoc
# when the guest executes it. This fixes [GH-1181].
file.binmode
2012-10-13 02:51:25 +00:00
begin
file.write(script)
file.fsync
file.close
yield file.path
ensure
file.close
file.unlink
end
end
end
end
end