# 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) 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("[rconf] " + 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) def execute_in_ruby(command, *args) report_fatal('Failed to run in ruby context, no ruby specified') unless @ruby_version opts = {}; env = {} if args[-1].is_a?(Hash) opts = args.pop env = opts[:env] || {} end env.merge!({ 'RBENV_VERSION' => @ruby_version }) opts.merge!({ :env => env }) args.push(opts) execute(command, *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 # version(String):: rbenv ruby version # # === Return # true:: Always return true def set_ruby(version) @ruby_version = version 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