Class: CemWinSpec::WinExec::Exec
- Inherits:
-
Object
- Object
- CemWinSpec::WinExec::Exec
- Includes:
- Logging
- Defined in:
- lib/cem_win_spec/win_exec/exec.rb
Overview
Class for executing PowerShell commands over WinRM
Constant Summary collapse
- HALTING_ERRORS =
[ IapTunnelStartError, ].freeze
Constants included from Logging
Instance Attribute Summary collapse
-
#ignore_exitcode ⇒ Object
(also: #ignore_exitcode?)
Returns the value of attribute ignore_exitcode.
-
#result ⇒ Object
readonly
Returns the value of attribute result.
-
#reuse_tunnel ⇒ Object
(also: #reuse_tunnel?)
Returns the value of attribute reuse_tunnel.
-
#title ⇒ Object
readonly
Returns the value of attribute title.
Instance Method Summary collapse
- #add_command_block(&block) ⇒ Object
- #add_iap_tunnel(value) ⇒ Object
- #add_local_cmd(value) ⇒ Object
- #add_ma_builder(value) ⇒ Object
- #add_remote_cmd(value) ⇒ Object
- #add_rspec_test_cmds(value) ⇒ Object
- #add_title(value) ⇒ Object
-
#initialize(title: 'Command', l_cmd: nil, r_cmd: nil, iap_tunnel: nil, ma_builder: nil, r_test_cmds: nil, &block) ⇒ Exec
constructor
A new instance of Exec.
-
#method_missing(method, *args, **kwargs, &block) ⇒ Object
Proxy method calls for methods that don’t exist here to various other objects.
-
#respond_to_missing?(method, include_private = false) ⇒ Boolean
Proxy respond_to? for methods that don’t exist here to various other objects.
- #run(*args, **kwargs) ⇒ Object
- #success? ⇒ Boolean
Methods included from Logging
#current_log_format, current_log_format, current_log_level, #current_log_level, included, log_setup!, #log_setup!, logger, #logger, new_log_formatter, #new_log_formatter, new_log_level, #new_log_level
Constructor Details
#initialize(title: 'Command', l_cmd: nil, r_cmd: nil, iap_tunnel: nil, ma_builder: nil, r_test_cmds: nil, &block) ⇒ Exec
Returns a new instance of Exec.
18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 18 def initialize(title: 'Command', l_cmd: nil, r_cmd: nil, iap_tunnel: nil, ma_builder: nil, r_test_cmds: nil, &block) add_title(title) add_local_cmd(l_cmd) unless l_cmd.nil? add_remote_cmd(r_cmd) unless r_cmd.nil? add_iap_tunnel(iap_tunnel) unless iap_tunnel.nil? add_ma_builder(ma_builder) unless ma_builder.nil? add_rspec_test_cmds(r_test_cmds) unless r_test_cmds.nil? add_command_block(&block) unless block.nil? @reuse_tunnel = true @ignore_exitcode = false @result = nil end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, **kwargs, &block) ⇒ Object
Proxy method calls for methods that don’t exist here to various other objects. This allows doing things like: ‘win_exec.remote_exec(’Get-Process’)‘ and calling the `exec` method on the `winrm_exec` object. This is done by checking method name prefixes and calling the corresponding method on the appropriate object. The prefix is removed from the method name before calling the method on the object. The supported prefixes are:
local_ - calls the method on the @local_cmd object
remote_ - calls the method on the @remote_cmd object
rspec_ - calls the method on the @rspec_test_cmds object
module_archive_ - calls the method on the @ma_builder object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 108 def method_missing(method, *args, **kwargs, &block) if method.to_s.start_with?('local_') # proxy to local_exec method = method.to_s.sub('local_', '').to_sym @local_cmd.send(method, *args, **kwargs, &block) elsif method.to_s.start_with?('remote_') # proxy to remote_exec method = method.to_s.sub('remote_', '').to_sym @remote_cmd.send(method, *args, **kwargs, &block) elsif method.to_s.start_with?('rspec_') # proxy to rspec_test_cmds method = method.to_s.sub('rspec_', '').to_sym @rspec_test_cmds.send(method, *args, **kwargs, &block) elsif method.to_s.start_with?('module_archive_') # proxy to ma_builder method = method.to_s.sub('module_archive_', '').to_sym @ma_builder.send(method, *args, **kwargs, &block) else super end end |
Instance Attribute Details
#ignore_exitcode ⇒ Object Also known as: ignore_exitcode?
Returns the value of attribute ignore_exitcode.
16 17 18 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 16 def ignore_exitcode @ignore_exitcode end |
#result ⇒ Object (readonly)
Returns the value of attribute result.
16 17 18 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 16 def result @result end |
#reuse_tunnel ⇒ Object Also known as: reuse_tunnel?
Returns the value of attribute reuse_tunnel.
16 17 18 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 16 def reuse_tunnel @reuse_tunnel end |
#title ⇒ Object (readonly)
Returns the value of attribute title.
16 17 18 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 16 def title @title end |
Instance Method Details
#add_command_block(&block) ⇒ Object
72 73 74 75 76 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 72 def add_command_block(&block) raise ArgumentError, 'block must be a Proc' unless block.is_a?(Proc) @block = block end |
#add_iap_tunnel(value) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 49 def add_iap_tunnel(value) unless value.respond_to?(:start) && value.respond_to?(:stop) && value.respond_to?(:with) raise ArgumentError, 'iap_tunnel must implement the #start, #stop, and #with methods' end @iap_tunnel = value end |
#add_local_cmd(value) ⇒ Object
37 38 39 40 41 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 37 def add_local_cmd(value) raise ArgumentError, 'local_exec must implement the #run method' unless value.respond_to?(:run) @local_cmd = value end |
#add_ma_builder(value) ⇒ Object
57 58 59 60 61 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 57 def add_ma_builder(value) raise ArgumentError, 'ma_builder must implement the #build method' unless value.respond_to?(:build) @ma_builder = value end |
#add_remote_cmd(value) ⇒ Object
43 44 45 46 47 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 43 def add_remote_cmd(value) raise ArgumentError, 'winrm_exec must implement the #run method' unless value.respond_to?(:run) @remote_cmd = value end |
#add_rspec_test_cmds(value) ⇒ Object
63 64 65 66 67 68 69 70 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 63 def add_rspec_test_cmds(value) unless value.respond_to?(:cmd_standalone) && value.respond_to?(:cmd_parallel) && value.respond_to?(:prep_cmd) && value.respond_to?(:cleanup_cmd) raise ArgumentError, 'rspec_test_cmds must implement the #cmd_standalone, #cmd_parallel, #prep_cmd, and #cleanup_cmd methods' end @rspec_test_cmds = value end |
#add_title(value) ⇒ Object
31 32 33 34 35 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 31 def add_title(value) raise ArgumentError, 'title must be a string' unless value.is_a?(String) @title = value end |
#respond_to_missing?(method, include_private = false) ⇒ Boolean
Proxy respond_to? for methods that don’t exist here to various other objects. This allows doing things like: ‘win_exec.respond_to?(:remote_exec)` and checking if the `exec` method exists on the `winrm_exec` object. This is done by checking method name prefixes and calling the corresponding method on the appropriate object. The prefix is removed from the method name before calling the method on the object. The supported prefixes are:
local_ - calls the method on the @local_cmd object
remote_ - calls the method on the @remote_cmd object
rspec_ - calls the method on the @rspec_test_cmds object
module_archive_ - calls the method on the @ma_builder object
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 136 def respond_to_missing?(method, include_private = false) if method.to_s.start_with?('local_') @local_cmd.respond_to?(method.to_s.sub('local_', '').to_sym, include_private) elsif method.to_s.start_with?('remote_') @remote_cmd.respond_to?(method.to_s.sub('remote_', '').to_sym, include_private) elsif method.to_s.start_with?('rspec_') @rspec_test_cmds.respond_to?(method.to_s.sub('rspec_', '').to_sym, include_private) elsif method.to_s.start_with?('module_archive_') @ma_builder.respond_to?(method.to_s.sub('module_archive_', '').to_sym, include_private) else super end end |
#run(*args, **kwargs) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 150 def run(*args, **kwargs) validate_instance_variables logger.info "Running #{@title}" result = run_with_tunnel { run_in_current_scope(*args, **kwargs) } logger.debug "Command stdout: #{result.stdout}" if result.respond_to?(:stdout) logger.debug "Command stderr: #{result.stderr}" if result.respond_to?(:stderr) @result = Output.new(result) return if @result.pending_threaded? unless @result.success? || ignore_exitcode? raise "Command failed with exit code #{@result.exitcode}: #{@result.stdout}\n#{@result.stderr}" end @result rescue StandardError => e raise if HALTING_ERRORS.include?(e.class) logger.error "Error running #{@title}: #{e.[0..100]}" @result = Output.new(e) @result end |
#success? ⇒ Boolean
92 93 94 95 96 |
# File 'lib/cem_win_spec/win_exec/exec.rb', line 92 def success? @result.success? if @result.is_a?(Output) false end |