# Copyright (C) 2011-2012 RightScale, Inc, All Rights Reserved Worldwide. # # THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE # AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use, # reproduction, modification, or disclosure of this program is # strictly prohibited. Any use of this program by an authorized # licensee is strictly subject to the terms and conditions, # including confidentiality obligations, set forth in the applicable # License Agreement between RightScale.com, Inc. and # the licensee require 'shellwords' module RightConf class Command include Singleton include ProgressReporter # Execute given command with given arguments # # === Parameters # command(String):: Command to run # args(Array):: Command arguments # # === Options # abort_on_failure(bool):: Whether to raise an exception in case command # returns an error (false by default) # env:: Hash of environment variables keyed by name # # === Return # result(CommandResult):: Result of execution (output and exit status) def execute(command, *args) ENV['rvm_is_not_a_shell_function'] = '0' ENV['rvm_ignore_rvmrc'] = '1' ENV['rvm_reload_flag'] = '0' ENV['rvm_project_rvmrc'] = '0' opts = {} if !args.empty? && args[-1].is_a?(Hash) opts = args[-1] args = args[0..-2] end res = Platform.dispatch(command, opts[:env], *args) { :execute } if @verbose msg = ([command] + args).compact.join(' ') + ' => ' + res.status.to_s + ': ' + res.output report(msg) end if !res.success? && msg = opts[:abort_on_failure] report_fatal("#{msg}: '#{command} #{args.join(' ')}' returned\n#{res.output}") end res end # Execute command in context of activated ruby # # === Parameters # command(String):: Command to run # args(Array):: Command arguments # # === Options # abort_on_failure(bool):: Whether to raise an exception in case command # returns an error (false by default) # env:: Hash of environment variables keyed by name # # === Return # result(CommandResult):: Result of execution (output and exit status) # NOTE: This is the result returned by RVM, not the underlying command # and thus could be successful when the command actually failed... def execute_in_ruby(command, *args) report_fatal('Failed to run in ruby context, no ruby specified') unless @rvm_prefix commands = @rvm_prefix + [ 'exec', '--', command ] args = commands + args execute('rvm', *args) end # Execute rvm command # # === Parameters # command(String):: rvm command to run # args(Array):: Command arguments # # === Options # abort_on_failure(bool):: Whether to raise an exception in case command # returns an error (false by default) # env:: Hash of environment variables keyed by name # # === Return # result(CommandResult):: Result of execution (output and exit status) def execute_rvm(command, *args) report_fatal('Failed to run in ruby context, no ruby specified') unless @rvm_prefix commands = @rvm_prefix + [ command ] args = commands + args execute('rvm', *args) end # Execute given command with given arguments using 'sudo' # # === Parameters # command(String):: Command to run # args(Array):: Command arguments # # === Return # result(CommandResult):: Result of execution (output and exit status) def sudo(*args) args = args.unshift('/usr/bin/sudo') Command.execute(*args) end # Execute given command on *nix systems # # === Parameters # command(String):: Command name # env(Hash):: Hash of environment variables keyed by name # params(Array):: List of parameters to pass to command # # === Return # result(CommandResult):: Result of execution (output and exit status) def execute_linux(command, env, *args) env ||= {} old_envs = env.keys.inject({}) { |o, k| o[k] = ENV[k]; o } env.each { |k, v| ENV[k] = v.to_s } out = `#{Shellwords.join([command, *args])} 2>&1` old_envs.each { |k, v| ENV[k] = v } result = CommandResult.new(out, $?.exitstatus) end alias :execute_darwin :execute_linux # Execute given command on Windows systems # # === Parameters # command(String):: Command name # env(Hash):: Hash of environment variables keyed by name # params(Array):: List of parameters to pass to command # # === Return # result(CommandResult):: Result of execution (output and exit status) def execute_windows(command, env, *args) raise 'TBD!' end # Set ruby to be used by 'execute_in_ruby' # # === Parameters # ruby(String):: RVM ruby # gemset(String):: RVM gemset # # === Return # true:: Always return true def set_ruby(ruby, gemset) @rvm_prefix = ["#{ruby}@#{gemset}"] true end # Enable debug output # # === Return # true:: Always return true def set_verbose @verbose = true end end # Command results class CommandResult # Process output attr_reader :output # Process exit status attr_reader :status # Initialize output and exit status # # === Parameters # output(String):: Process output # status(Fixnum):: Process exit status def initialize(output, status) @output = output @status = status end # Whether process exited successfully # # === Return # true:: If process exited with status code 0 # false:: Otherwise def success? @status == 0 end end end