kitchen-transport-express 1.3.1 → 1.4.0
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/CHANGELOG.md +4 -0
 - data/lib/kitchen/transport/express/archiver.rb +16 -2
 - data/lib/kitchen/transport/express/version.rb +1 -1
 - data/lib/kitchen/transport/express_ssh.rb +36 -27
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: e7399b24ea4426dcb6ea891466818b0a3471b24a6a67eb2163727afb8f9d7e35
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: fa22be3398901120654fe61679e913f3b714eaaa59f4c0c68bcd44bde1651410
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 7b3e1b72d7b6f5117e286166e07092c83606965115650f6cf18949300280b1761e57ff78f43e375ce5785e317803c043b788b13167e6ea210ffec9c13294624c
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 76f54ae47956867487ed15bea11dd1b114c5b92c6776da7efc9e44e4f2843837606c6fbf782ca3988fba4d62ffd3f2b5cf68ff74572e1ae0dbac9f8b35f2460e
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    
| 
         @@ -31,11 +31,24 @@ module Kitchen 
     | 
|
| 
       31 
31 
     | 
    
         
             
                      archive_basename = ::File.basename(path) + ".tgz"
         
     | 
| 
       32 
32 
     | 
    
         
             
                      archive_full_name = ::File.join(::File.dirname(path), archive_basename)
         
     | 
| 
       33 
33 
     | 
    
         
             
                      files = all_files(path)
         
     | 
| 
       34 
     | 
    
         
            -
                       
     | 
| 
      
 34 
     | 
    
         
            +
                      start_time = Time.now
         
     | 
| 
       35 
35 
     | 
    
         
             
                      create_archive(path, files, archive_full_name)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      Express.log(logger, "create archive #{File.basename(archive_full_name)} (#{files.size} files)", start_time)
         
     | 
| 
       36 
37 
     | 
    
         
             
                      archive_full_name
         
     | 
| 
       37 
38 
     | 
    
         
             
                    end
         
     | 
| 
       38 
39 
     | 
    
         | 
| 
      
 40 
     | 
    
         
            +
                    # Transfers the archive to the remote host.
         
     | 
| 
      
 41 
     | 
    
         
            +
                    #
         
     | 
| 
      
 42 
     | 
    
         
            +
                    # @param session [Net::SSH::Connection::Session] the SSH session used to connect to the remote host and execute the extract and cleanup commands.
         
     | 
| 
      
 43 
     | 
    
         
            +
                    # @param local [String] the directory in the local sandbox that is being processed.
         
     | 
| 
      
 44 
     | 
    
         
            +
                    # @param remote [String] the remote directory (kitchen_root).
         
     | 
| 
      
 45 
     | 
    
         
            +
                    # @param opts [Hash] the ssh options that came in from the Kitchen instance.
         
     | 
| 
      
 46 
     | 
    
         
            +
                    def scp(session, local, remote, opts = {})
         
     | 
| 
      
 47 
     | 
    
         
            +
                      start_time = Time.now
         
     | 
| 
      
 48 
     | 
    
         
            +
                      session.scp.upload!(local, remote, opts)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      Express.log(logger, "upload #{File.basename(local)} (Thread ID: #{Thread.current.object_id})", start_time)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
       39 
52 
     | 
    
         
             
                    # Extracts the archive on the remote host.
         
     | 
| 
       40 
53 
     | 
    
         
             
                    #
         
     | 
| 
       41 
54 
     | 
    
         
             
                    # @param session [Net::SSH::Connection::Session] the SSH session used to connect to the remote host and execute the extract and cleanup commands.
         
     | 
| 
         @@ -44,13 +57,14 @@ module Kitchen 
     | 
|
| 
       44 
57 
     | 
    
         
             
                    def extract(session, local, remote)
         
     | 
| 
       45 
58 
     | 
    
         
             
                      return unless local.match(/.*\.tgz/)
         
     | 
| 
       46 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
                      start_time = Time.now
         
     | 
| 
       47 
61 
     | 
    
         
             
                      archive_basename = File.basename(local)
         
     | 
| 
       48 
     | 
    
         
            -
                      logger.debug("[#{Express::LOG_PREFIX}] Extracting #{::File.join(remote, archive_basename)}")
         
     | 
| 
       49 
62 
     | 
    
         
             
                      session.open_channel do |channel|
         
     | 
| 
       50 
63 
     | 
    
         
             
                        channel.request_pty
         
     | 
| 
       51 
64 
     | 
    
         
             
                        channel.exec("tar -xzf #{::File.join(remote, archive_basename)} -C #{remote} && rm -f #{File.join(remote, archive_basename)}")
         
     | 
| 
       52 
65 
     | 
    
         
             
                      end
         
     | 
| 
       53 
66 
     | 
    
         
             
                      session.loop
         
     | 
| 
      
 67 
     | 
    
         
            +
                      Express.log(logger, "extract #{File.basename(local)} (Thread ID: #{Thread.current.object_id})", start_time)
         
     | 
| 
       54 
68 
     | 
    
         
             
                    end
         
     | 
| 
       55 
69 
     | 
    
         | 
| 
       56 
70 
     | 
    
         
             
                    private
         
     | 
| 
         @@ -27,6 +27,16 @@ module Kitchen 
     | 
|
| 
       27 
27 
     | 
    
         
             
                class Express
         
     | 
| 
       28 
28 
     | 
    
         
             
                  # A constant that gets prepended to debugger messages.
         
     | 
| 
       29 
29 
     | 
    
         
             
                  LOG_PREFIX = "EXPRESS"
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  # Logger class method to unify logging.
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #
         
     | 
| 
      
 33 
     | 
    
         
            +
                  # @param logger [Kitchen::Logger] the logger that was created by the kitchen instance.
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # @param message [String] the message to output.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # @param start_time [Time] the start time of the process if duration is desired to be part of the message.
         
     | 
| 
      
 36 
     | 
    
         
            +
                  def self.log(logger, message = nil, start_time = nil)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    message = "#{message} (#{Time.now - start_time}s)" if start_time
         
     | 
| 
      
 38 
     | 
    
         
            +
                    logger.debug "[#{Express::LOG_PREFIX}] [#{Time.now.getutc.strftime("%Y-%m-%dT%H:%M:%S%:z")}] #{message}"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
       30 
40 
     | 
    
         
             
                end
         
     | 
| 
       31 
41 
     | 
    
         | 
| 
       32 
42 
     | 
    
         
             
                # Express SSH Transport Error class.
         
     | 
| 
         @@ -51,7 +61,7 @@ module Kitchen 
     | 
|
| 
       51 
61 
     | 
    
         
             
                  # @return [Ssh::Connection] an instance of Kitchen::Transport::ExpressSsh::Connection.
         
     | 
| 
       52 
62 
     | 
    
         
             
                  def create_new_connection(options, &block)
         
     | 
| 
       53 
63 
     | 
    
         
             
                    if @connection
         
     | 
| 
       54 
     | 
    
         
            -
                       
     | 
| 
      
 64 
     | 
    
         
            +
                      Express.log(logger, "shutting previous connection #{@connection}")
         
     | 
| 
       55 
65 
     | 
    
         
             
                      @connection.close
         
     | 
| 
       56 
66 
     | 
    
         
             
                    end
         
     | 
| 
       57 
67 
     | 
    
         | 
| 
         @@ -95,33 +105,35 @@ module Kitchen 
     | 
|
| 
       95 
105 
     | 
    
         
             
                    # @param locals [Array] the top-level list of directories and files to be transfered.
         
     | 
| 
       96 
106 
     | 
    
         
             
                    # @param remote [String] the remote directory (kitchen_root).
         
     | 
| 
       97 
107 
     | 
    
         
             
                    # @raise [ExpressFailed] if any of the threads raised an exception.
         
     | 
| 
       98 
     | 
    
         
            -
                    def upload(locals, remote) 
     | 
| 
      
 108 
     | 
    
         
            +
                    def upload(locals, remote)
         
     | 
| 
       99 
109 
     | 
    
         
             
                      return super unless valid_remote_requirements?(remote)
         
     | 
| 
       100 
110 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
                       
     | 
| 
       102 
     | 
    
         
            -
                       
     | 
| 
       103 
     | 
    
         
            -
                       
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                       
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
                      pool.wait_for_termination
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
                      raise ExpressFailed, exceptions.pop unless exceptions.empty?
         
     | 
| 
       114 
     | 
    
         
            -
                    end # rubocop: enable Metrics/MethodLength
         
     | 
| 
      
 111 
     | 
    
         
            +
                      start_time = Time.now
         
     | 
| 
      
 112 
     | 
    
         
            +
                      processed_local = process_locals(locals)
         
     | 
| 
      
 113 
     | 
    
         
            +
                      futures = create_futures(processed_local, remote)
         
     | 
| 
      
 114 
     | 
    
         
            +
                      all_done = Concurrent::Promise.zip(*futures).execute
         
     | 
| 
      
 115 
     | 
    
         
            +
                      all_done.value!
         
     | 
| 
      
 116 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 117 
     | 
    
         
            +
                      raise ExpressFailed, e.cause.to_s
         
     | 
| 
      
 118 
     | 
    
         
            +
                    ensure
         
     | 
| 
      
 119 
     | 
    
         
            +
                      Express.log(logger, "transport express complete", start_time)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
       115 
121 
     | 
    
         | 
| 
       116 
122 
     | 
    
         
             
                    private
         
     | 
| 
       117 
123 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
                    # Creates the  
     | 
| 
      
 124 
     | 
    
         
            +
                    # Creates the concurrent futures.
         
     | 
| 
       119 
125 
     | 
    
         
             
                    #
         
     | 
| 
       120 
     | 
    
         
            -
                    # @param  
     | 
| 
       121 
     | 
    
         
            -
                    # @return [Array(Concurrent:: 
     | 
| 
      
 126 
     | 
    
         
            +
                    # @param locals [Array] list of files and archives to be uploaded.
         
     | 
| 
      
 127 
     | 
    
         
            +
                    # @return [Array(Concurrent::Promise)]
         
     | 
| 
       122 
128 
     | 
    
         
             
                    # @api private
         
     | 
| 
       123 
     | 
    
         
            -
                    def  
     | 
| 
       124 
     | 
    
         
            -
                       
     | 
| 
      
 129 
     | 
    
         
            +
                    def create_futures(locals, remote)
         
     | 
| 
      
 130 
     | 
    
         
            +
                      # Start upload futures
         
     | 
| 
      
 131 
     | 
    
         
            +
                      executor = Concurrent::FixedThreadPool.new([locals.length, 10].min)
         
     | 
| 
      
 132 
     | 
    
         
            +
                      locals.map do |local|
         
     | 
| 
      
 133 
     | 
    
         
            +
                        Concurrent::Promise.execute(executor: executor) do
         
     | 
| 
      
 134 
     | 
    
         
            +
                          transfer(local, remote, session.options)
         
     | 
| 
      
 135 
     | 
    
         
            +
                        end
         
     | 
| 
      
 136 
     | 
    
         
            +
                      end
         
     | 
| 
       125 
137 
     | 
    
         
             
                    end
         
     | 
| 
       126 
138 
     | 
    
         | 
| 
       127 
139 
     | 
    
         
             
                    # Ensures the remote host has the minimum-required executables to extract the archives.
         
     | 
| 
         @@ -134,8 +146,7 @@ module Kitchen 
     | 
|
| 
       134 
146 
     | 
    
         
             
                      execute("mkdir -p #{remote}")
         
     | 
| 
       135 
147 
     | 
    
         
             
                      true
         
     | 
| 
       136 
148 
     | 
    
         
             
                    rescue => e
         
     | 
| 
       137 
     | 
    
         
            -
                       
     | 
| 
       138 
     | 
    
         
            -
                      logger.debug("[#{Express::LOG_PREFIX}] #{e}")
         
     | 
| 
      
 149 
     | 
    
         
            +
                      Express.log(logger, "Requirements not met on remote host for Express transport.\n#{e}")
         
     | 
| 
       139 
150 
     | 
    
         
             
                      false
         
     | 
| 
       140 
151 
     | 
    
         
             
                    end
         
     | 
| 
       141 
152 
     | 
    
         | 
| 
         @@ -166,13 +177,11 @@ module Kitchen 
     | 
|
| 
       166 
177 
     | 
    
         
             
                    # @raise [StandardError] if the files could not be uploaded successfully.
         
     | 
| 
       167 
178 
     | 
    
         
             
                    # @api private
         
     | 
| 
       168 
179 
     | 
    
         
             
                    def transfer(local, remote, opts = {})
         
     | 
| 
       169 
     | 
    
         
            -
                      logger.debug("[#{Express::LOG_PREFIX}] Transferring #{local} to #{remote}")
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
180 
     | 
    
         
             
                      Net::SSH.start(session.host, opts[:user], **opts) do |ssh|
         
     | 
| 
       172 
     | 
    
         
            -
                         
     | 
| 
      
 181 
     | 
    
         
            +
                        scp(ssh, local, remote, opts)
         
     | 
| 
       173 
182 
     | 
    
         
             
                        extract(ssh, local, remote)
         
     | 
| 
       174 
183 
     | 
    
         
             
                      rescue Net::SCP::Error => ex
         
     | 
| 
       175 
     | 
    
         
            -
                         
     | 
| 
      
 184 
     | 
    
         
            +
                        Express.log(logger, "upload failed with #{ex.message.strip}")
         
     | 
| 
       176 
185 
     | 
    
         
             
                        raise "(#{ex.message.strip})"
         
     | 
| 
       177 
186 
     | 
    
         
             
                      end
         
     | 
| 
       178 
187 
     | 
    
         
             
                    end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: kitchen-transport-express
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.4.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Justin Steele
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2025- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2025-08-28 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: test-kitchen
         
     |