Module: Minestrone::Configuration::Actions::Invocation
- Included in:
- Minestrone::Configuration
- Defined in:
- lib/minestrone/configuration/actions/invocation.rb
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
-
.included(base) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#add_default_command_options(options) ⇒ Object
Merges the various default command options into the options hash and returns the result.
- #continue_execution(command) ⇒ Object
-
#initialize_invocation ⇒ Object
:nodoc:.
-
#invoke_command(cmd, options = {}, &block) ⇒ Object
Invokes the given command.
-
#run(cmd, options = {}, &block) ⇒ Object
Execute the given command on the configured server.
-
#sudo(*parameters, &block) ⇒ Object
Returns the command string used by minestrone to invoke a comamnd via sudo.
-
#sudo_behavior_callback(fallback) ⇒ Object
Returns a Proc object that defines the behavior of the sudo callback.
-
#sudo_prompt ⇒ Object
Returns the prompt text to use with sudo.
Class Method Details
.included(base) ⇒ Object
:nodoc:
9 10 11 12 13 14 15 16 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 9 def self.included(base) #:nodoc: base.extend(ClassMethods) base.default_io_proc = Proc.new do |ch, stream, out| level = (stream == :err) ? :important : :info ch[:options][:logger].send(level, out, "#{stream} :: #{ch[:server]}") end end |
Instance Method Details
#add_default_command_options(options) ⇒ Object
Merges the various default command options into the options hash and returns the result. The default command options that are understand are:
-
:default_environment: If the :env key already exists, the :env key is merged into default_environment and then added back into options.
-
:default_shell: if the :shell key already exists, it will be used. Otherwise, if the :default_shell key exists in the configuration, it will be used. Otherwise, no :shell key is added.
173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 173 def () defaults = self[:default_run_options] = defaults.merge() env = self[:default_environment] env = env.merge([:env]) if [:env] [:env] = env unless env.empty? shell = [:shell] || self[:default_shell] [:shell] = shell unless shell.nil? end |
#continue_execution(command) ⇒ Object
192 193 194 195 196 197 198 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 192 def continue_execution(command) case Minestrone::CLI.debug_prompt(command.inspect) when "y" then true when "n" then false when "a" then exit(-1) end end |
#initialize_invocation ⇒ Object
:nodoc:
22 23 24 25 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 22 def initialize_invocation #:nodoc: set :default_environment, {} set :default_run_options, {} end |
#invoke_command(cmd, options = {}, &block) ⇒ Object
Invokes the given command. If a via key is given, it will be used to determine what method to use to invoke the command. It defaults to :run, but may be :sudo, or any other method that conforms to the same interface as run and sudo.
32 33 34 35 36 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 32 def invoke_command(cmd, = {}, &block) = .dup via = .delete(:via) || :run send(via, cmd, , &block) end |
#run(cmd, options = {}, &block) ⇒ Object
Execute the given command on the configured server. If a block is given, it is invoked for all output generated by the command, and should accept three parameters: the SSH channel (which may be used to send data back to the remote process), the stream identifier (:err for stderr, and :out for stdout), and the data that was received.
The options hash may include any of the following keys:
-
:shell - says which shell should be used to invoke commands. This defaults to “sh”. Setting this to false causes Minestrone to invoke the commands directly, without wrapping them in a shell invocation.
-
:data - if not nil (the default), this should be a string that will be passed to the command’s stdin stream.
-
:pty - if true, a pseudo-tty will be allocated for each command. The default is false. Note that there are benefits and drawbacks both ways. Empirically, it appears that if a pty is allocated, the SSH server daemon will not read user shell start-up scripts (e.g. bashrc, etc.). However, if a pty is not allocated, some commands will refuse to run in interactive mode and will not prompt for (e.g.) passwords.
-
:env - a hash of environment variable mappings that should be made available to the command. The keys should be environment variable names, and the values should be their corresponding values. The default is empty, but may be modified by changing the
default_environmentMinestrone variable. -
:eof - if true, the standard input stream will be closed after sending any data specified in the :data option. If false, the input stream is left open. The default is to close the input stream only if no block is passed.
Note that if you set these keys in the default_run_options Minestrone variable, they will apply for all invocations of #run and #invoke_command.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 72 def run(cmd, = {}, &block) if [:eof].nil? && !cmd.include?(sudo) = .merge(:eof => !block_given?) end block ||= self.class.default_io_proc = () if cmd.nil? || cmd.empty? raise ArgumentError, "attempt to execute without specifying a command" end logger.debug "executing #{cmd.inspect}" unless [:silent] return if dry_run || (debug && continue_execution(cmd) == false) block = sudo_behavior_callback(block) if cmd.include?(sudo) execute_on_server do Command.process(cmd, session, .merge(:logger => logger, :configuration => self), &block) end end |
#sudo(*parameters, &block) ⇒ Object
Returns the command string used by minestrone to invoke a comamnd via sudo.
run "#{sudo :as => 'bob'} mkdir /path/to/dir"
It can also be invoked like #run, but executing the command via sudo. If sudo requires a password, set the :password variable or pass -p to prompt for it before running.
sudo "mkdir /path/to/dir"
Also, this method understands a :sudo configuration variable, which (if specified) will be used as the full path to the sudo executable on the remote machine:
set :sudo, "/opt/local/bin/sudo"
If you know what you’re doing, you can also set :sudo_prompt, which tells minestrone which prompt sudo should use when asking for a password. (This is so that minestrone knows what prompt to look for in the output.) If you set :sudo_prompt to an empty string, Minestrone will not send a preferred prompt.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 118 def sudo(*parameters, &block) = parameters.last.is_a?(Hash) ? parameters.pop.dup : {} command = parameters.first user = [:as] && "-u #{.delete(:as)}" sudo_prompt_option = "-p '#{sudo_prompt}'" unless sudo_prompt.empty? sudo_command = [fetch(:sudo, "sudo"), sudo_prompt_option, user].compact.join(" ") if command command = sudo_command + " " + command run(command, , &block) else return sudo_command end end |
#sudo_behavior_callback(fallback) ⇒ Object
Returns a Proc object that defines the behavior of the sudo callback. The returned Proc will defer to the fallback argument (which should also be a Proc) for any output it does not explicitly handle.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 139 def sudo_behavior_callback(fallback) #:nodoc: # in order to prevent _each host_ from prompting when the password # was wrong, let's track which host prompted first and only allow # subsequent prompts from that host. prompt_host = nil Proc.new do |ch, stream, out| if out.to_s =~ /^Sorry, try again/ if prompt_host.nil? || prompt_host == ch[:server] prompt_host = ch[:server] logger.important out, "#{stream} :: #{ch[:server]}" reset! :password end end if out.to_s =~ /^#{Regexp.escape(sudo_prompt)}/ ch.send_data "#{self[:password]}\n" elsif fallback fallback.call(ch, stream, out) end end end |
#sudo_prompt ⇒ Object
Returns the prompt text to use with sudo
188 189 190 |
# File 'lib/minestrone/configuration/actions/invocation.rb', line 188 def sudo_prompt fetch(:sudo_prompt, "sudo password: ") end |