train 2.0.2 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/train/platforms/detect/helpers/os_common.rb +1 -2
- data/lib/train/platforms/detect/helpers/os_linux.rb +1 -0
- data/lib/train/plugins/base_connection.rb +13 -4
- data/lib/train/transports/cisco_ios_connection.rb +1 -1
- data/lib/train/transports/docker.rb +1 -1
- data/lib/train/transports/local.rb +1 -1
- data/lib/train/transports/mock.rb +1 -1
- data/lib/train/transports/ssh.rb +2 -1
- data/lib/train/transports/ssh_connection.rb +48 -34
- data/lib/train/transports/vmware.rb +1 -1
- data/lib/train/transports/winrm.rb +4 -0
- data/lib/train/transports/winrm_connection.rb +4 -1
- data/lib/train/version.rb +1 -1
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: fc5c0aaf06370bfbf2ee1308c13dfd87a0da5a736536c4bf3024dd3400a62861
         | 
| 4 | 
            +
              data.tar.gz: 04e7e0b56d0acd587ce5a567e8c81b2a2b701fd87c0165271048158340958d05
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 68a9846a2638f11c3d5d34f340f20cd42748206307f10b930c4967745d6c6db7e803109322c36f9ee15c5b4c7e15c4c05bcbbc58acad15878ca058b2c05e1f34
         | 
| 7 | 
            +
              data.tar.gz: 343a8c70c0e73ff1c3169e28696ad073c5611afa8bcd8425b27b25ff6bd0220084c02139ef96a95c074737df29e8418b03bb91790646c1675b552010b1514f19
         | 
| @@ -14,8 +14,7 @@ module Train::Platforms::Detect::Helpers | |
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 16 | 
             
                def winrm?
         | 
| 17 | 
            -
                   | 
| 18 | 
            -
                    @backend.class == Train::Transports::WinRM::Connection
         | 
| 17 | 
            +
                  @backend.class.to_s == 'Train::Transports::WinRM::Connection'
         | 
| 19 18 | 
             
                end
         | 
| 20 19 |  | 
| 21 20 | 
             
                def unix_file_contents(path)
         | 
| @@ -114,10 +114,14 @@ class Train::Plugins::Transport | |
| 114 114 |  | 
| 115 115 | 
             
                # This is the main command call for all connections. This will call the private
         | 
| 116 116 | 
             
                # run_command_via_connection on the connection with optional caching
         | 
| 117 | 
            -
                 | 
| 118 | 
            -
             | 
| 117 | 
            +
                #
         | 
| 118 | 
            +
                # This command accepts an optional data handler block. When provided,
         | 
| 119 | 
            +
                # inbound data will be published vi `data_handler.call(data)`. This can allow
         | 
| 120 | 
            +
                # callers to receive and render updates from remote command execution.
         | 
| 121 | 
            +
                def run_command(cmd, &data_handler)
         | 
| 122 | 
            +
                  return run_command_via_connection(cmd, &data_handler) unless cache_enabled?(:command)
         | 
| 119 123 |  | 
| 120 | 
            -
                  @cache[:command][cmd] ||= run_command_via_connection(cmd)
         | 
| 124 | 
            +
                  @cache[:command][cmd] ||= run_command_via_connection(cmd, &data_handler)
         | 
| 121 125 | 
             
                end
         | 
| 122 126 |  | 
| 123 127 | 
             
                # This is the main file call for all connections. This will call the private
         | 
| @@ -150,8 +154,13 @@ class Train::Plugins::Transport | |
| 150 154 | 
             
                # Execute a command using this connection.
         | 
| 151 155 | 
             
                #
         | 
| 152 156 | 
             
                # @param command [String] command string to execute
         | 
| 157 | 
            +
                # @param &data_handler(data) [Proc] proc that is called when data arrives from
         | 
| 158 | 
            +
                # the connection.  This block is optional. Individual transports will need
         | 
| 159 | 
            +
                # to explicitly invoke the block in their implementation of run_command_via_connection;
         | 
| 160 | 
            +
                # if they do not, the block is ignored and will not be used to report data back to the caller.
         | 
| 161 | 
            +
                #
         | 
| 153 162 | 
             
                # @return [CommandResult] contains the result of running the command
         | 
| 154 | 
            -
                def run_command_via_connection(_command)
         | 
| 163 | 
            +
                def run_command_via_connection(_command, &_data_handler)
         | 
| 155 164 | 
             
                  fail NotImplementedError, "#{self.class} does not implement #run_command_via_connection()"
         | 
| 156 165 | 
             
                end
         | 
| 157 166 |  | 
    
        data/lib/train/transports/ssh.rb
    CHANGED
    
    | @@ -63,6 +63,7 @@ module Train::Transports | |
| 63 63 | 
             
                option :bastion_user, default: 'root'
         | 
| 64 64 | 
             
                option :bastion_port, default: 22
         | 
| 65 65 | 
             
                option :non_interactive, default: false
         | 
| 66 | 
            +
                option :verify_host_key, default: false
         | 
| 66 67 |  | 
| 67 68 | 
             
                option :compression_level do |opts|
         | 
| 68 69 | 
             
                  # on nil or false: set compression level to 0
         | 
| @@ -168,7 +169,7 @@ module Train::Transports | |
| 168 169 | 
             
                  }
         | 
| 169 170 | 
             
                  # disable host key verification. The hash key to use
         | 
| 170 171 | 
             
                  # depends on the version of net-ssh in use.
         | 
| 171 | 
            -
                  connection_options[verify_host_key_option] = false
         | 
| 172 | 
            +
                  connection_options[verify_host_key_option] = opts[:verify_host_key] || false
         | 
| 172 173 |  | 
| 173 174 | 
             
                  connection_options
         | 
| 174 175 | 
             
                end
         | 
| @@ -207,44 +207,12 @@ class Train::Transports::SSH | |
| 207 207 | 
             
                  end
         | 
| 208 208 | 
             
                end
         | 
| 209 209 |  | 
| 210 | 
            -
                def run_command_via_connection(cmd) | 
| 211 | 
            -
                  stdout = stderr = ''
         | 
| 212 | 
            -
                  exit_status = nil
         | 
| 210 | 
            +
                def run_command_via_connection(cmd, &data_handler)
         | 
| 213 211 | 
             
                  cmd.dup.force_encoding('binary') if cmd.respond_to?(:force_encoding)
         | 
| 214 212 | 
             
                  logger.debug("[SSH] #{self} (#{cmd})")
         | 
| 215 213 |  | 
| 216 214 | 
             
                  reset_session if session.closed?
         | 
| 217 | 
            -
                   | 
| 218 | 
            -
                    # wrap commands if that is configured
         | 
| 219 | 
            -
                    cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
         | 
| 220 | 
            -
             | 
| 221 | 
            -
                    if @transport_options[:pty]
         | 
| 222 | 
            -
                      channel.request_pty do |_ch, success|
         | 
| 223 | 
            -
                        fail Train::Transports::SSHPTYFailed, 'Requesting PTY failed' unless success
         | 
| 224 | 
            -
                      end
         | 
| 225 | 
            -
                    end
         | 
| 226 | 
            -
             | 
| 227 | 
            -
                    channel.exec(cmd) do |_, success|
         | 
| 228 | 
            -
                      abort 'Couldn\'t execute command on SSH.' unless success
         | 
| 229 | 
            -
             | 
| 230 | 
            -
                      channel.on_data do |_, data|
         | 
| 231 | 
            -
                        stdout += data
         | 
| 232 | 
            -
                      end
         | 
| 233 | 
            -
             | 
| 234 | 
            -
                      channel.on_extended_data do |_, _type, data|
         | 
| 235 | 
            -
                        stderr += data
         | 
| 236 | 
            -
                      end
         | 
| 237 | 
            -
             | 
| 238 | 
            -
                      channel.on_request('exit-status') do |_, data|
         | 
| 239 | 
            -
                        exit_status = data.read_long
         | 
| 240 | 
            -
                      end
         | 
| 241 | 
            -
             | 
| 242 | 
            -
                      channel.on_request('exit-signal') do |_, data|
         | 
| 243 | 
            -
                        exit_status = data.read_long
         | 
| 244 | 
            -
                      end
         | 
| 245 | 
            -
                    end
         | 
| 246 | 
            -
                  end
         | 
| 247 | 
            -
                  @session.loop
         | 
| 215 | 
            +
                  exit_status, stdout, stderr = execute_on_channel(cmd, &data_handler)
         | 
| 248 216 |  | 
| 249 217 | 
             
                  # Since `@session.loop` succeeded, reset the IOS command retry counter
         | 
| 250 218 | 
             
                  @ios_cmd_retries = 0
         | 
| @@ -293,5 +261,51 @@ class Train::Transports::SSH | |
| 293 261 | 
             
                  options_to_print[:password] = '<hidden>' if options_to_print.key?(:password)
         | 
| 294 262 | 
             
                  "#{@username}@#{@hostname}<#{options_to_print.inspect}>"
         | 
| 295 263 | 
             
                end
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                # Given a channel and a command string, it will execute the command on the channel
         | 
| 266 | 
            +
                # and accumulate results in  @stdout/@stderr.
         | 
| 267 | 
            +
                #
         | 
| 268 | 
            +
                # @param channel [Net::SSH::Connection::Channel] an open ssh channel
         | 
| 269 | 
            +
                # @param cmd [String] the command to execute
         | 
| 270 | 
            +
                # @return [Integer] exit status or nil if exit-status/exit-signal requests
         | 
| 271 | 
            +
                #         not received.
         | 
| 272 | 
            +
                #
         | 
| 273 | 
            +
                # @api private
         | 
| 274 | 
            +
                def execute_on_channel(cmd, &data_handler)
         | 
| 275 | 
            +
                  stdout = stderr = ''
         | 
| 276 | 
            +
                  exit_status = nil
         | 
| 277 | 
            +
                  session.open_channel do |channel|
         | 
| 278 | 
            +
                    # wrap commands if that is configured
         | 
| 279 | 
            +
                    cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                    if @transport_options[:pty]
         | 
| 282 | 
            +
                      channel.request_pty do |_ch, success|
         | 
| 283 | 
            +
                        fail Train::Transports::SSHPTYFailed, 'Requesting PTY failed' unless success
         | 
| 284 | 
            +
                      end
         | 
| 285 | 
            +
                    end
         | 
| 286 | 
            +
                    channel.exec(cmd) do |_, success|
         | 
| 287 | 
            +
                      abort 'Couldn\'t execute command on SSH.' unless success
         | 
| 288 | 
            +
                      channel.on_data do |_, data|
         | 
| 289 | 
            +
                        yield(data) unless data_handler.nil?
         | 
| 290 | 
            +
                        stdout += data
         | 
| 291 | 
            +
                      end
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                      channel.on_extended_data do |_, _type, data|
         | 
| 294 | 
            +
                        yield(data) unless data_handler.nil?
         | 
| 295 | 
            +
                        stderr += data
         | 
| 296 | 
            +
                      end
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                      channel.on_request('exit-status') do |_, data|
         | 
| 299 | 
            +
                        exit_status = data.read_long
         | 
| 300 | 
            +
                      end
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                      channel.on_request('exit-signal') do |_, data|
         | 
| 303 | 
            +
                        exit_status = data.read_long
         | 
| 304 | 
            +
                      end
         | 
| 305 | 
            +
                    end
         | 
| 306 | 
            +
                  end
         | 
| 307 | 
            +
                  session.loop
         | 
| 308 | 
            +
                  [exit_status, stdout, stderr]
         | 
| 309 | 
            +
                end
         | 
| 296 310 | 
             
              end
         | 
| 297 311 | 
             
            end
         | 
| @@ -64,6 +64,10 @@ module Train::Transports | |
| 64 64 | 
             
                option :kerberos_realm, default: nil
         | 
| 65 65 | 
             
                option :kerberos_service, default: nil
         | 
| 66 66 | 
             
                option :ca_trust_file, default: nil
         | 
| 67 | 
            +
                # The amount of time in SECONDS for which each operation must get an ack
         | 
| 68 | 
            +
                # from the winrm endpoint. Does not mean that the command has
         | 
| 69 | 
            +
                # completed in this time, only that the server has ack'd the request.
         | 
| 70 | 
            +
                option :operation_timeout, default: nil
         | 
| 67 71 |  | 
| 68 72 | 
             
                def initialize(opts)
         | 
| 69 73 | 
             
                  super(opts)
         | 
| @@ -36,6 +36,7 @@ class Train::Transports::WinRM | |
| 36 36 | 
             
                  @connection_retries     = @options.delete(:connection_retries)
         | 
| 37 37 | 
             
                  @connection_retry_sleep = @options.delete(:connection_retry_sleep)
         | 
| 38 38 | 
             
                  @max_wait_until_ready   = @options.delete(:max_wait_until_ready)
         | 
| 39 | 
            +
                  @operation_timeout      = @options.delete(:operation_timeout)
         | 
| 39 40 | 
             
                end
         | 
| 40 41 |  | 
| 41 42 | 
             
                # (see Base::Connection#close)
         | 
| @@ -95,12 +96,13 @@ class Train::Transports::WinRM | |
| 95 96 | 
             
                  Train::File::Remote::Windows.new(self, path)
         | 
| 96 97 | 
             
                end
         | 
| 97 98 |  | 
| 98 | 
            -
                def run_command_via_connection(command)
         | 
| 99 | 
            +
                def run_command_via_connection(command, &data_handler)
         | 
| 99 100 | 
             
                  return if command.nil?
         | 
| 100 101 | 
             
                  logger.debug("[WinRM] #{self} (#{command})")
         | 
| 101 102 | 
             
                  out = ''
         | 
| 102 103 |  | 
| 103 104 | 
             
                  response = session.run(command) do |stdout, _|
         | 
| 105 | 
            +
                    yield(stdout) if data_handler && stdout
         | 
| 104 106 | 
             
                    out << stdout if stdout
         | 
| 105 107 | 
             
                  end
         | 
| 106 108 |  | 
| @@ -178,6 +180,7 @@ class Train::Transports::WinRM | |
| 178 180 | 
             
                      retry_delay: @connection_retry_sleep.to_i,
         | 
| 179 181 | 
             
                    }.merge(retry_options)
         | 
| 180 182 |  | 
| 183 | 
            +
                    opts[:operation_timeout] = @operation_timeout unless @operation_timeout.nil?
         | 
| 181 184 | 
             
                    @service = ::WinRM::Connection.new(options.merge(opts))
         | 
| 182 185 | 
             
                    @service.logger = logger
         | 
| 183 186 | 
             
                    @service.shell(:powershell)
         | 
    
        data/lib/train/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: train
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.0. | 
| 4 | 
            +
              version: 2.0.5
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Dominik Richter
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2019- | 
| 11 | 
            +
            date: 2019-04-10 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: json
         | 
| @@ -308,7 +308,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 308 308 | 
             
                - !ruby/object:Gem::Version
         | 
| 309 309 | 
             
                  version: '0'
         | 
| 310 310 | 
             
            requirements: []
         | 
| 311 | 
            -
            rubygems_version: 3.0. | 
| 311 | 
            +
            rubygems_version: 3.0.3
         | 
| 312 312 | 
             
            signing_key: 
         | 
| 313 313 | 
             
            specification_version: 4
         | 
| 314 314 | 
             
            summary: Transport interface to talk to different backends.
         |