kitchen-transport-express 1.2.0 → 1.3.1
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 +7 -0
- data/kitchen-transport-express.gemspec +10 -3
- data/lib/kitchen/transport/express/archiver.rb +42 -32
- data/lib/kitchen/transport/express/version.rb +4 -1
- data/lib/kitchen/transport/express_ssh.rb +27 -29
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23840e5574cc8a84acfcb87e24a3a4f6c26ea1174a3c5c2bc8390d3fc23843b6
|
4
|
+
data.tar.gz: eb2165a04339df078065117b00af095b8cba4903d0c5d03233cedfc5b3ac6a8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8257d47351212661fd997b9b3397cdcc63f5f998352fd96362cd6d21092aba753943349db7c31688a705acbbec2582e4754f31b2dc57938b5771c3a726bb95f5
|
7
|
+
data.tar.gz: a3d90892108b59c591f965debb21bb38de8a6eab34f397703660ee5866c7c9a5158bb5a1e90974788d0c41ee8829c95a9457409ab8f4dca62c9b650a17cf2d2a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# kitchen-transport-express CHANGELOG
|
2
2
|
|
3
|
+
## 1.3.1
|
4
|
+
* fix: 🐛 ensure directories that only contain dot files get archived
|
5
|
+
|
6
|
+
## 1.3.0
|
7
|
+
* chore: 📝 minor updates to method documentation
|
8
|
+
* chore: 🔧 add metadata to gemspec
|
9
|
+
|
3
10
|
## 1.2.0
|
4
11
|
* feat: 🥅 add error handling to the thread pool
|
5
12
|
* feat: 📝🎨 add YARD tags and cleaned up class namespaces and private methods
|
@@ -18,12 +18,12 @@ lib = File.expand_path("lib", __dir__)
|
|
18
18
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
19
19
|
require "kitchen/transport/express/version"
|
20
20
|
|
21
|
-
Gem::Specification.new do |spec|
|
21
|
+
Gem::Specification.new do |spec| # rubocop: disable Metrics/BlockLength
|
22
22
|
spec.name = "kitchen-transport-express"
|
23
23
|
spec.version = Kitchen::Transport::Express::VERSION
|
24
24
|
spec.authors = ["Justin Steele"]
|
25
25
|
spec.email = ["justin.steele@oracle.com"]
|
26
|
-
spec.summary = %q{Skip the long lines in
|
26
|
+
spec.summary = %q{Skip the long lines in Kitchen Transport!}
|
27
27
|
spec.description = %q{A Test Kitchen Transport plugin that streamlines the file transfer phase to Linux hosts.}
|
28
28
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
29
29
|
spec.homepage = "https://github.com/justintsteele/kitchen-transport-express.git"
|
@@ -31,6 +31,13 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.license = "Apache-2.0"
|
32
32
|
spec.require_paths = ["lib"]
|
33
33
|
spec.required_ruby_version = ">= 2.4"
|
34
|
+
spec.metadata = {
|
35
|
+
"bug_tracker_uri" => "https://github.com/justintsteele/kitchen-transport-express/issues",
|
36
|
+
"changelog_uri" => "https://github.com/justintsteele/kitchen-transport-express/blob/main/CHANGELOG.md",
|
37
|
+
"documentation_uri" => "https://github.com/justintsteele/kitchen-transport-express/blob/main/README.md",
|
38
|
+
"homepage_uri" => "https://github.com/justintsteele/kitchen-transport-express",
|
39
|
+
"source_code_uri" => "https://github.com/justintsteele/kitchen-transport-express",
|
40
|
+
}
|
34
41
|
spec.add_dependency "test-kitchen"
|
35
42
|
spec.add_dependency "ffi-libarchive"
|
36
43
|
spec.add_dependency "concurrent-ruby"
|
@@ -40,4 +47,4 @@ Gem::Specification.new do |spec|
|
|
40
47
|
spec.add_development_dependency "rake"
|
41
48
|
spec.add_development_dependency "rspec"
|
42
49
|
spec.add_development_dependency "yard"
|
43
|
-
end
|
50
|
+
end # rubocop: enable Metrics/BlockLength
|
@@ -23,24 +23,24 @@ module Kitchen
|
|
23
23
|
#
|
24
24
|
# @author Justin Steele <justin.steele@oracle.com>
|
25
25
|
module Archiver
|
26
|
-
# Creates the archive locally in the Kitchen cache location
|
26
|
+
# Creates the archive locally in the Kitchen cache location.
|
27
27
|
#
|
28
|
-
# @param path [String] the path of the top-level directory to be arvhied
|
29
|
-
# @return [String] the name of the archive
|
28
|
+
# @param path [String] the path of the top-level directory to be arvhied.
|
29
|
+
# @return [String] the name of the archive.
|
30
30
|
def archive(path)
|
31
31
|
archive_basename = ::File.basename(path) + ".tgz"
|
32
32
|
archive_full_name = ::File.join(::File.dirname(path), archive_basename)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
create_archive(path, archive_full_name)
|
33
|
+
files = all_files(path)
|
34
|
+
logger.debug("[#{Express::LOG_PREFIX}] #{path} contains #{files.size} files.")
|
35
|
+
create_archive(path, files, archive_full_name)
|
37
36
|
archive_full_name
|
38
37
|
end
|
39
38
|
|
40
|
-
# Extracts the archive on the remote host
|
39
|
+
# Extracts the archive on the remote host.
|
41
40
|
#
|
42
|
-
# @param session [Net::SSH::Connection::Session]
|
43
|
-
#
|
41
|
+
# @param session [Net::SSH::Connection::Session] the SSH session used to connect to the remote host and execute the extract and cleanup commands.
|
42
|
+
# @param local [String] the directory in the local sandbox that is being processed.
|
43
|
+
# @param remote [String] the remote directory (kitchen_root).
|
44
44
|
def extract(session, local, remote)
|
45
45
|
return unless local.match(/.*\.tgz/)
|
46
46
|
|
@@ -55,26 +55,36 @@ module Kitchen
|
|
55
55
|
|
56
56
|
private
|
57
57
|
|
58
|
-
#
|
58
|
+
# Creates a list of all files that are in the directory to be archived.
|
59
|
+
#
|
60
|
+
# @param path [String] the path to the directory that will be archived.
|
61
|
+
# @return [Array] an array of all files to be archived.
|
62
|
+
# @api private
|
63
|
+
def all_files(path)
|
64
|
+
Dir.glob(File.join(path, "/**/*"), File::FNM_DOTMATCH).reject { |f| %w{. ..}.include? File.basename(f) }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Creats a archive of the directory provided.
|
59
68
|
#
|
60
|
-
# @param path [String] the path to the directory that will be archived
|
61
|
-
# @param
|
69
|
+
# @param path [String] the path to the directory that will be archived.
|
70
|
+
# @param files [Array] the array of all files that will be archived.
|
71
|
+
# @param archive_path [String] the fully qualified path to the archive that will be created.
|
62
72
|
# @api private
|
63
|
-
def create_archive(path, archive_path)
|
73
|
+
def create_archive(path, files, archive_path)
|
64
74
|
Archive.write_open_filename(archive_path, Archive::COMPRESSION_GZIP,
|
65
75
|
Archive::FORMAT_TAR_PAX_RESTRICTED) do |tar|
|
66
|
-
write_content(tar, path)
|
76
|
+
write_content(tar, path, files)
|
67
77
|
end
|
68
78
|
end
|
69
79
|
|
70
|
-
# Appends the content of each item in the expanded directory path
|
80
|
+
# Appends the content of each item in the expanded directory path.
|
71
81
|
#
|
72
|
-
# @param tar [Archive::Writer] the instance of the archive class
|
73
|
-
# @param path [String] the path to the directory that will be archived
|
82
|
+
# @param tar [Archive::Writer] the instance of the archive class.
|
83
|
+
# @param path [String] the path to the directory that will be archived.
|
84
|
+
# @param files [Array] the array of all files that will be archived.
|
74
85
|
# @api private
|
75
|
-
def write_content(tar, path)
|
76
|
-
|
77
|
-
all_files.each do |f|
|
86
|
+
def write_content(tar, path, files)
|
87
|
+
files.each do |f|
|
78
88
|
if File.file? f
|
79
89
|
tar.new_entry do |e|
|
80
90
|
entry(e, f, path)
|
@@ -85,11 +95,11 @@ module Kitchen
|
|
85
95
|
end
|
86
96
|
end
|
87
97
|
|
88
|
-
# Creates the entry in the Archive for each item
|
98
|
+
# Creates the entry in the Archive for each item.
|
89
99
|
#
|
90
|
-
# @param ent [Archive::Entry] the current entry being added to the archive
|
91
|
-
# @param file [String] the current file or directory being added to the archive
|
92
|
-
# @param path [String] the path to the directory being archived
|
100
|
+
# @param ent [Archive::Entry] the current entry being added to the archive.
|
101
|
+
# @param file [String] the current file or directory being added to the archive.
|
102
|
+
# @param path [String] the path to the directory being archived.
|
93
103
|
# @api private
|
94
104
|
def entry(ent, file, path)
|
95
105
|
ent.pathname = file.gsub(%r{#{File.dirname(path)}/}, "")
|
@@ -102,8 +112,8 @@ module Kitchen
|
|
102
112
|
|
103
113
|
# The content of the file in binary format. Directories have no content.
|
104
114
|
#
|
105
|
-
# @param file [String] the path to the file
|
106
|
-
# @return [String] the content of the file
|
115
|
+
# @param file [String] the path to the file.
|
116
|
+
# @return [String] the content of the file.
|
107
117
|
# @api private
|
108
118
|
def content(file)
|
109
119
|
File.read(file, mode: "rb")
|
@@ -111,17 +121,17 @@ module Kitchen
|
|
111
121
|
|
112
122
|
# The size of the file. Directories have no size.
|
113
123
|
#
|
114
|
-
# @param file [String] the path to the file
|
115
|
-
# @return [Integer] the size of the file
|
124
|
+
# @param file [String] the path to the file.
|
125
|
+
# @return [Integer] the size of the file.
|
116
126
|
# @api private
|
117
127
|
def size(file)
|
118
128
|
content(file).size
|
119
129
|
end
|
120
130
|
|
121
|
-
# The file permissions of the file
|
131
|
+
# The file permissions of the file.
|
122
132
|
#
|
123
|
-
# @param file [String] the path to the file or directory
|
124
|
-
# @return [Integer] the mode of the file or directory
|
133
|
+
# @param file [String] the path to the file or directory.
|
134
|
+
# @return [Integer] the mode of the file or directory.
|
125
135
|
# @api private
|
126
136
|
def mode(file)
|
127
137
|
f = File.stat(file)
|
@@ -21,15 +21,15 @@ require_relative "express/archiver"
|
|
21
21
|
|
22
22
|
module Kitchen
|
23
23
|
module Transport
|
24
|
-
# Kitchen Transport Express
|
24
|
+
# Kitchen Transport Express.
|
25
25
|
#
|
26
26
|
# @author Justin Steele <justin.steele@oracle.com>
|
27
27
|
class Express
|
28
|
-
# A constant that gets prepended to debugger messages
|
28
|
+
# A constant that gets prepended to debugger messages.
|
29
29
|
LOG_PREFIX = "EXPRESS"
|
30
30
|
end
|
31
31
|
|
32
|
-
# Express SSH Transport Error class
|
32
|
+
# Express SSH Transport Error class.
|
33
33
|
#
|
34
34
|
# @author Justin Steele <justin.steele@oracle.com>
|
35
35
|
class ExpressFailed < StandardError
|
@@ -38,17 +38,17 @@ module Kitchen
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
# Express SSH Transport plugin for Test Kitchen
|
41
|
+
# Express SSH Transport plugin for Test Kitchen.
|
42
42
|
#
|
43
43
|
# @author Justin Steele <justin.steele@oracle.com>
|
44
44
|
class ExpressSsh < Kitchen::Transport::Ssh
|
45
45
|
kitchen_transport_api_version 1
|
46
46
|
plugin_version Express::VERSION
|
47
47
|
|
48
|
-
# Override the method in the super class to start the connection with our connection class
|
48
|
+
# Override the method in the super class to start the connection with our connection class.
|
49
49
|
#
|
50
|
-
# @param options [Hash] connection options
|
51
|
-
# @return [Ssh::Connection] an instance of Kitchen::Transport::ExpressSsh::Connection
|
50
|
+
# @param options [Hash] connection options.
|
51
|
+
# @return [Ssh::Connection] an instance of Kitchen::Transport::ExpressSsh::Connection.
|
52
52
|
def create_new_connection(options, &block)
|
53
53
|
if @connection
|
54
54
|
logger.debug("[#{Express::LOG_PREFIX}] Shutting previous connection #{@connection}")
|
@@ -59,16 +59,16 @@ module Kitchen
|
|
59
59
|
@connection = self.class::Connection.new(options, &block)
|
60
60
|
end
|
61
61
|
|
62
|
-
# Determines if the Kitchen instance is attempting a Verify stage
|
62
|
+
# Determines if the Kitchen instance is attempting a Verify stage.
|
63
63
|
#
|
64
|
-
# @param instance [Kitchen::Instance] the instance passed in from Kitchen
|
64
|
+
# @param instance [Kitchen::Instance] the instance passed in from Kitchen.
|
65
65
|
# @return [Boolean]
|
66
66
|
def verifier_defined?(instance)
|
67
67
|
defined?(Kitchen::Verifier::Inspec) && instance.verifier.is_a?(Kitchen::Verifier::Inspec)
|
68
68
|
end
|
69
69
|
|
70
|
-
# Finalizes the Kitchen config by executing super and parsing the options provided by the kitchen.yml
|
71
|
-
# The only difference here is we layer in our ssh options so the verifier can use our transport
|
70
|
+
# Finalizes the Kitchen config by executing super and parsing the options provided by the kitchen.yml.
|
71
|
+
# The only difference here is we layer in our ssh options so the verifier can use our transport.
|
72
72
|
# (see Kitchen::Transport::Ssh#finalize_config!)
|
73
73
|
def finalize_config!(instance)
|
74
74
|
super.tap do
|
@@ -88,15 +88,14 @@ module Kitchen
|
|
88
88
|
class Connection < Kitchen::Transport::Ssh::Connection
|
89
89
|
include Express::Archiver
|
90
90
|
|
91
|
+
# Overrides the upload method in Kitchen::Transport::Ssh::Connection.
|
92
|
+
# The special sauce here is that we create threaded uploads of archives of the kitchen files rather than serial file uploads.
|
91
93
|
# (see Kitchen::Transport::Base::Connection#upload)
|
92
|
-
# Overrides the upload method in Kitchen::Transport::Ssh::Connection
|
93
|
-
# The special sauce here is that we create threaded executions of uploading our archives
|
94
94
|
#
|
95
|
-
# @param locals [Array] the top-level list of directories and files to be transfered
|
96
|
-
# @param remote [String] the remote directory
|
97
|
-
# @raise [ExpressFailed] if any of the threads raised an exception
|
98
|
-
# rubocop: disable Metrics/MethodLength
|
99
|
-
def upload(locals, remote)
|
95
|
+
# @param locals [Array] the top-level list of directories and files to be transfered.
|
96
|
+
# @param remote [String] the remote directory (kitchen_root).
|
97
|
+
# @raise [ExpressFailed] if any of the threads raised an exception.
|
98
|
+
def upload(locals, remote) # rubocop: disable Metrics/MethodLength
|
100
99
|
return super unless valid_remote_requirements?(remote)
|
101
100
|
|
102
101
|
processed_locals = process_locals(locals)
|
@@ -112,14 +111,13 @@ module Kitchen
|
|
112
111
|
pool.wait_for_termination
|
113
112
|
|
114
113
|
raise ExpressFailed, exceptions.pop unless exceptions.empty?
|
115
|
-
end
|
116
|
-
# rubocop: enable Metrics/MethodLength
|
114
|
+
end # rubocop: enable Metrics/MethodLength
|
117
115
|
|
118
116
|
private
|
119
117
|
|
120
|
-
# Creates the thread pool and exceptions queue
|
118
|
+
# Creates the thread pool and exceptions queue.
|
121
119
|
#
|
122
|
-
# @param processed_locals [Array] list of files and archives to be uploaded
|
120
|
+
# @param processed_locals [Array] list of files and archives to be uploaded.
|
123
121
|
# @return [Array(Concurrent::FixedThreadPool, Queue)]
|
124
122
|
# @api private
|
125
123
|
def thread_pool(processed_locals)
|
@@ -128,7 +126,7 @@ module Kitchen
|
|
128
126
|
|
129
127
|
# Ensures the remote host has the minimum-required executables to extract the archives.
|
130
128
|
#
|
131
|
-
# @param remote [String] the remote directory
|
129
|
+
# @param remote [String] the remote directory (kitchen_root).
|
132
130
|
# @return [Boolean]
|
133
131
|
# @api private
|
134
132
|
def valid_remote_requirements?(remote)
|
@@ -144,8 +142,8 @@ module Kitchen
|
|
144
142
|
# Builds an array of files we want to ship. If the top-level item is a directory, archive it and
|
145
143
|
# add the archive name to the array.
|
146
144
|
#
|
147
|
-
# @param locals [Array] the top-level list of directories and files to be transfered
|
148
|
-
# @return [Array] the paths to the files and archives that will be transferred
|
145
|
+
# @param locals [Array] the top-level list of directories and files to be transfered.
|
146
|
+
# @return [Array] the paths to the files and archives that will be transferred.
|
149
147
|
# @api private
|
150
148
|
def process_locals(locals)
|
151
149
|
processed_locals = []
|
@@ -162,10 +160,10 @@ module Kitchen
|
|
162
160
|
|
163
161
|
# Uploads the archives or files to the remote host.
|
164
162
|
#
|
165
|
-
# @param local [String] a single top-level item from the upload method
|
166
|
-
# @param remote [String] path to remote destination
|
167
|
-
# @param opts [Hash] the ssh options that came in from the Kitchen instance
|
168
|
-
# @raise [StandardError] if the files could not be uploaded successfully
|
163
|
+
# @param local [String] a single top-level item from the upload method.
|
164
|
+
# @param remote [String] path to remote destination.
|
165
|
+
# @param opts [Hash] the ssh options that came in from the Kitchen instance.
|
166
|
+
# @raise [StandardError] if the files could not be uploaded successfully.
|
169
167
|
# @api private
|
170
168
|
def transfer(local, remote, opts = {})
|
171
169
|
logger.debug("[#{Express::LOG_PREFIX}] Transferring #{local} to #{remote}")
|
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.3.1
|
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-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-kitchen
|
@@ -160,7 +160,11 @@ homepage: https://github.com/justintsteele/kitchen-transport-express.git
|
|
160
160
|
licenses:
|
161
161
|
- Apache-2.0
|
162
162
|
metadata:
|
163
|
-
|
163
|
+
bug_tracker_uri: https://github.com/justintsteele/kitchen-transport-express/issues
|
164
|
+
changelog_uri: https://github.com/justintsteele/kitchen-transport-express/blob/main/CHANGELOG.md
|
165
|
+
documentation_uri: https://github.com/justintsteele/kitchen-transport-express/blob/main/README.md
|
166
|
+
homepage_uri: https://github.com/justintsteele/kitchen-transport-express
|
167
|
+
source_code_uri: https://github.com/justintsteele/kitchen-transport-express
|
164
168
|
post_install_message:
|
165
169
|
rdoc_options: []
|
166
170
|
require_paths:
|
@@ -176,8 +180,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
180
|
- !ruby/object:Gem::Version
|
177
181
|
version: '0'
|
178
182
|
requirements: []
|
179
|
-
rubygems_version: 3.3.
|
183
|
+
rubygems_version: 3.3.27
|
180
184
|
signing_key:
|
181
185
|
specification_version: 4
|
182
|
-
summary: Skip the long lines in
|
186
|
+
summary: Skip the long lines in Kitchen Transport!
|
183
187
|
test_files: []
|