module Sprinkle module Actors # = Psexec Delivery Method # # Windows specific remote delivery method, using the psexec.exe tool # (which must be on the path of your local machine): # http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx. # # A minimal configuration for this delivery method would specify the # role to be applied to some host: # # deployment do # delivery :psexec do # role :app, 'app.example.com' # end # end # # A more complex example could define multiple roles and a specific user: # # deployment do # delivery :psexec do # role :app, 'app.example.com' # role :web, 'web.example.com' # # you can also specify a password, but if # # not provided you will be prompted for it # user 'domain\\administrator', 'opensesame' # end # end class Psexec attr_accessor :options def initialize(options = {}, &block) #:nodoc: @options = {:roles => {}}.merge options self.instance_eval &block if block end def role(name, *host) @options[:roles][name] = host end def roles(roles) @options[:roles] = roles end def user(name, pass = nil) @options[:user], @options[:password] = name, pass end def process(name, commands, roles, suppress_and_return_failures = false) Array(roles).each do |role| Array(@options[:roles][role]).each do |host| Array(commands).each do |command| begin psexec(host, command) rescue RuntimeError => e return false if suppress_and_return_failures raise end end end end return true end protected # execute a command against a remote windows machine using psexec def psexec(host, command) exec = "psexec \\\\#{Array(host).join ','}" if @options[:user] exec << " -u \"#{@options[:user]}\"" @options[:password] = ask("--> Enter password for #{@options[:user]}@#{host}: ") {|q| q.echo = '*'} unless @options[:password] exec << " -p \"#{@options[:password]}\"" end exec << " /accepteula" exec << " cmd /c \"#{command}\"" exec << ' > NUL 2>&1' unless logger.debug? logger.debug "--> #{exec}" system exec raise "Failed to execute command \"#{command}\" on host: #{host}" if $?.to_i != 0 end end end end