testcontainers-core 0.1.2 → 0.1.3
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 +24 -3
- data/Gemfile.lock +1 -1
- data/README.md +2 -2
- data/lib/testcontainers/docker_container.rb +167 -7
- data/lib/testcontainers/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd1ecb046574448907ac650c801eda4e7dad34055c6a61fa06a0f066067e2b97
|
4
|
+
data.tar.gz: f9c49b86765f2166cf2460bef0899ba40a1b822bdf23451bbe1a3e68531606e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6dfd296c157b51d3429f0c470e5ee1a46d15de6c47b1d417045260c55fed5482e8562a6bc8ac689254fc80a835dff36a0b2af26d6a5f11e75e162f546d15233
|
7
|
+
data.tar.gz: 77ed8e5fe3cc9df35744fdeccebb9cef54a3a359aa36afe90e0f9dcbd3375a16411db5132590746084c89c3f091b42eb021b033e9d4dce184a12de9499563b4f
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,27 @@
|
|
1
|
+
## [0.1.3] - 2023-06-10
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
- Support for entrypoint customization and the DockerContainer#with_entrypoint method
|
6
|
+
|
7
|
+
- Methods to read/write strings from and to containers: read_file, store_file
|
8
|
+
|
9
|
+
- Methods to copy files from and to containers: copy_file_from_container, copy_file_to_container
|
10
|
+
|
11
|
+
- Support for waiting strategies on start
|
12
|
+
|
13
|
+
- DockerContainer#with_exposed_port (singular) for convenience
|
14
|
+
|
15
|
+
- GenericContainer as alias for DockerContainer
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
- DockerContainer#add_exposed_ports don't override PortBinding settings added by #add_fixed_exposed_port
|
20
|
+
|
21
|
+
|
1
22
|
## [0.1.2] - 2023-05-13
|
2
23
|
|
3
|
-
|
24
|
+
### Added
|
4
25
|
|
5
26
|
- DockerContainer#first_mapped_port method returns the first of the
|
6
27
|
mapped ports for convenience.
|
@@ -13,11 +34,11 @@
|
|
13
34
|
|
14
35
|
redis_container.with_healthcheck(test: ["redis-cli ping"], interval: 30, timeout: 30, retries: 3)
|
15
36
|
|
16
|
-
|
37
|
+
### Changed
|
17
38
|
|
18
39
|
- DockerContainer#mapped_port(port) method now returns an Integer instead of a String.
|
19
40
|
|
20
|
-
|
41
|
+
### Fixed
|
21
42
|
|
22
43
|
- Links to the GitHub project on the README.md file are fixed.
|
23
44
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -28,7 +28,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
28
28
|
|
29
29
|
## Contributing
|
30
30
|
|
31
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
31
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/testcontainers/testcontainers-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/testcontainers/testcontainers-ruby/blob/main/CODE_OF_CONDUCT.md).
|
32
32
|
|
33
33
|
## License
|
34
34
|
|
@@ -36,4 +36,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
36
36
|
|
37
37
|
## Code of Conduct
|
38
38
|
|
39
|
-
Everyone interacting in the Testcontainers project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
39
|
+
Everyone interacting in the Testcontainers project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/testcontainers/testcontainers-ruby/blob/main/CODE_OF_CONDUCT.md).
|
@@ -6,6 +6,7 @@ module Testcontainers
|
|
6
6
|
# @attr name [String] the container's name
|
7
7
|
# @attr image [String] the container's image name
|
8
8
|
# @attr command [Array<String>, nil] the command to run in the container
|
9
|
+
# @attr entrypoint [Array<String>, nil] the entrypoint to run in the container
|
9
10
|
# @attr exposed_ports [Hash, nil] a hash mapping exposed container ports to an empty hash (used for Docker API compatibility)
|
10
11
|
# @attr port_bindings [Hash, nil] a hash mapping container ports to host port bindings (used for Docker API compatibility)
|
11
12
|
# @attr volumes [Hash, nil] a hash mapping volume paths in the container to an empty hash (used for Docker API compatibility)
|
@@ -18,7 +19,8 @@ module Testcontainers
|
|
18
19
|
# @attr_reader _container [Docker::Container, nil] the underlying Docker::Container object
|
19
20
|
# @attr_reader _id [String, nil] the container's ID
|
20
21
|
class DockerContainer
|
21
|
-
attr_accessor :name, :image, :command, :exposed_ports, :port_bindings, :volumes, :filesystem_binds,
|
22
|
+
attr_accessor :name, :image, :command, :entrypoint, :exposed_ports, :port_bindings, :volumes, :filesystem_binds,
|
23
|
+
:env, :labels, :working_dir, :healthcheck, :wait_for
|
22
24
|
attr_accessor :logger
|
23
25
|
attr_reader :_container, :_id
|
24
26
|
|
@@ -35,12 +37,13 @@ module Testcontainers
|
|
35
37
|
# @param labels [Hash, nil] a hash of labels to be applied to the container
|
36
38
|
# @param working_dir [String, nil] the working directory for the container
|
37
39
|
# @param logger [Logger] a logger instance for the container
|
38
|
-
def initialize(image, command: nil,
|
39
|
-
labels: nil, working_dir: nil, healthcheck: nil, logger: Testcontainers.logger)
|
40
|
+
def initialize(image, name: nil, command: nil, entrypoint: nil, exposed_ports: nil, port_bindings: nil, volumes: nil, filesystem_binds: nil,
|
41
|
+
env: nil, labels: nil, working_dir: nil, healthcheck: nil, wait_for: nil, logger: Testcontainers.logger)
|
40
42
|
|
41
43
|
@image = image
|
42
|
-
@command = command
|
43
44
|
@name = name
|
45
|
+
@command = command
|
46
|
+
@entrypoint = entrypoint
|
44
47
|
@exposed_ports = add_exposed_ports(exposed_ports) if exposed_ports
|
45
48
|
@port_bindings = add_fixed_exposed_ports(port_bindings) if port_bindings
|
46
49
|
@volumes = add_volumes(volumes) if volumes
|
@@ -49,6 +52,7 @@ module Testcontainers
|
|
49
52
|
@labels = add_labels(labels) if labels
|
50
53
|
@working_dir = working_dir
|
51
54
|
@healthcheck = add_healthcheck(healthcheck) if healthcheck
|
55
|
+
@wait_for = add_wait_for(wait_for)
|
52
56
|
@logger = logger
|
53
57
|
@_container = nil
|
54
58
|
@_id = nil
|
@@ -78,8 +82,8 @@ module Testcontainers
|
|
78
82
|
port = normalize_port(port)
|
79
83
|
@exposed_ports ||= {}
|
80
84
|
@port_bindings ||= {}
|
81
|
-
@exposed_ports[port]
|
82
|
-
@port_bindings[port]
|
85
|
+
@exposed_ports[port] ||= {}
|
86
|
+
@port_bindings[port] ||= [{"HostPort" => ""}]
|
83
87
|
@exposed_ports
|
84
88
|
end
|
85
89
|
|
@@ -242,6 +246,51 @@ module Testcontainers
|
|
242
246
|
}
|
243
247
|
end
|
244
248
|
|
249
|
+
# Add a wait_for strategy to the container configuration.
|
250
|
+
#
|
251
|
+
# @param method [Symbol, String, Proc, Array] The method to call on the container to wait for it to be ready.
|
252
|
+
# @param args [Array] The arguments to pass to the method if it is a symbol or string.
|
253
|
+
# @param kwargs [Hash] The keyword arguments to pass to the method if it is a symbol or string.
|
254
|
+
# @param block [Proc] The block to call on the container to wait for it to be ready.
|
255
|
+
# @return [Proc] The wait_for strategy.
|
256
|
+
def add_wait_for(method = nil, *args, **kwargs, &block)
|
257
|
+
if method.nil?
|
258
|
+
if block
|
259
|
+
if block.arity == 1
|
260
|
+
@wait_for = block
|
261
|
+
else
|
262
|
+
raise ArgumentError, "Invalid wait_for block: #{block}"
|
263
|
+
end
|
264
|
+
elsif @exposed_ports && !@exposed_ports.empty?
|
265
|
+
port = @exposed_ports.keys.first.split("/").first
|
266
|
+
@wait_for = ->(container) { container.wait_for_tcp_port(port) }
|
267
|
+
end
|
268
|
+
elsif method.is_a?(Proc)
|
269
|
+
if method.arity == 1
|
270
|
+
@wait_for = method
|
271
|
+
else
|
272
|
+
raise ArgumentError, "Invalid wait_for method: #{method}"
|
273
|
+
end
|
274
|
+
elsif method.is_a?(Array)
|
275
|
+
method_name = "wait_for_#{method[0]}".to_sym
|
276
|
+
args = method[1] || []
|
277
|
+
kwargs = method[2] || {}
|
278
|
+
if respond_to?(method_name)
|
279
|
+
@wait_for = ->(container) { container.send(method_name, *args, **kwargs) }
|
280
|
+
else
|
281
|
+
raise ArgumentError, "Invalid wait_for method: #{method_name}"
|
282
|
+
end
|
283
|
+
else
|
284
|
+
method_name = "wait_for_#{method}".to_sym
|
285
|
+
if respond_to?(method_name)
|
286
|
+
@wait_for = ->(container) { container.send(method_name, *args, **kwargs) }
|
287
|
+
else
|
288
|
+
raise ArgumentError, "Invalid wait_for method: #{method_name}"
|
289
|
+
end
|
290
|
+
end
|
291
|
+
@wait_for
|
292
|
+
end
|
293
|
+
|
245
294
|
# Set options for the container configuration using "with_" methods.
|
246
295
|
#
|
247
296
|
# @param options [Hash] A hash of options where keys correspond to "with_" methods and values are the arguments for those methods.
|
@@ -269,6 +318,16 @@ module Testcontainers
|
|
269
318
|
self
|
270
319
|
end
|
271
320
|
|
321
|
+
# Set the entrypoint for the container.
|
322
|
+
#
|
323
|
+
# @param parts [Array<String>] The entry point for the container as an array of strings.
|
324
|
+
# @return [DockerContainer] The updated DockerContainer instance.
|
325
|
+
def with_entrypoint(*parts)
|
326
|
+
@entrypoint = parts.first.is_a?(Array) ? parts.first : parts
|
327
|
+
|
328
|
+
self
|
329
|
+
end
|
330
|
+
|
272
331
|
# Set the name of the container.
|
273
332
|
#
|
274
333
|
# @param name [String] The name of the container.
|
@@ -309,6 +368,15 @@ module Testcontainers
|
|
309
368
|
self
|
310
369
|
end
|
311
370
|
|
371
|
+
# Adds a single exposed port to the container.
|
372
|
+
#
|
373
|
+
# @param port [String, Integer] The port to expose.
|
374
|
+
# @return [DockerContainer] The updated DockerContainer instance.
|
375
|
+
def with_exposed_port(port)
|
376
|
+
add_exposed_ports(port)
|
377
|
+
self
|
378
|
+
end
|
379
|
+
|
312
380
|
# Adds a fixed exposed port to the container.
|
313
381
|
#
|
314
382
|
# @param container_port [String, Integer, Hash] The container port in the format "port/protocol" or as an integer.
|
@@ -373,6 +441,18 @@ module Testcontainers
|
|
373
441
|
self
|
374
442
|
end
|
375
443
|
|
444
|
+
# Add a wait_for strategy to the container configuration.
|
445
|
+
#
|
446
|
+
# @param method [Symbol, String, Proc, Array] The method to call on the container to wait for it to be ready.
|
447
|
+
# @param args [Array] The arguments to pass to the method if it is a symbol or string.
|
448
|
+
# @param kwargs [Hash] The keyword arguments to pass to the method if it is a symbol or string.
|
449
|
+
# @param block [Proc] The block to call on the container to wait for it to be ready.
|
450
|
+
# @return [DockerContainer] The updated DockerContainer instance.
|
451
|
+
def with_wait_for(method = nil, *args, **kwargs, &block)
|
452
|
+
add_wait_for(method, *args, **kwargs, &block)
|
453
|
+
self
|
454
|
+
end
|
455
|
+
|
376
456
|
# Starts the container, yields the container instance to the block, and stops the container.
|
377
457
|
#
|
378
458
|
# @yield [DockerContainer] The container instance.
|
@@ -396,10 +476,11 @@ module Testcontainers
|
|
396
476
|
|
397
477
|
@_id = @_container.id
|
398
478
|
json = @_container.json
|
399
|
-
|
400
479
|
@name = json["Name"]
|
401
480
|
@_created_at = json["Created"]
|
402
481
|
|
482
|
+
@wait_for&.call(self)
|
483
|
+
|
403
484
|
self
|
404
485
|
rescue Excon::Error::Socket => e
|
405
486
|
raise ConnectionError, e.message
|
@@ -810,6 +891,81 @@ module Testcontainers
|
|
810
891
|
File.exist?("/.dockerenv")
|
811
892
|
end
|
812
893
|
|
894
|
+
# Copies a IO object or a file from the host to the container.
|
895
|
+
#
|
896
|
+
# @param container_path [String] The path to the file inside the container.
|
897
|
+
# @param host_path_or_io [String, IO] The path to the file on the host or a IO object.
|
898
|
+
# @raise [ContainerNotStartedError] If the container has not been started.
|
899
|
+
# @raise [ConnectionError] If the connection to the Docker daemon fails.
|
900
|
+
# @return [self]
|
901
|
+
def copy_file_to_container(container_path, host_path_or_io)
|
902
|
+
raise ContainerNotStartedError, "Container has not been started" unless running?
|
903
|
+
raise ArgumentError, "Container path must be a non-empty string" if container_path.to_s.empty?
|
904
|
+
|
905
|
+
begin
|
906
|
+
io = host_path_or_io.is_a?(String) ? File.open(host_path_or_io) : host_path_or_io
|
907
|
+
io.rewind if io.pos != 0
|
908
|
+
store_file(container_path, io.read)
|
909
|
+
io.rewind
|
910
|
+
rescue => e
|
911
|
+
puts "Error while copying file to container: #{e.message}"
|
912
|
+
return false
|
913
|
+
ensure
|
914
|
+
io.close if io.respond_to?(:close)
|
915
|
+
end
|
916
|
+
|
917
|
+
true
|
918
|
+
end
|
919
|
+
|
920
|
+
# Copies a file from the container to the host.
|
921
|
+
#
|
922
|
+
# @param container_path [String] The path to the file inside the container.
|
923
|
+
# @param host_path_or_io [String, IO] The path to the file on the host or a IO object.
|
924
|
+
# @raise [ContainerNotStartedError] If the container has not been started.
|
925
|
+
# @raise [ConnectionError] If the connection to the Docker daemon fails.
|
926
|
+
# @return [String] The contents of the file inside the container.
|
927
|
+
def copy_file_from_container(container_path, host_path_or_io)
|
928
|
+
raise ContainerNotStartedError, "Container has not been started" unless running?
|
929
|
+
raise ArgumentError, "Container path must be a non-empty string" if container_path.to_s.empty?
|
930
|
+
|
931
|
+
begin
|
932
|
+
io = host_path_or_io.is_a?(String) ? File.open(host_path_or_io, "w") : host_path_or_io
|
933
|
+
io.rewind if io.pos != 0
|
934
|
+
content = read_file(container_path)
|
935
|
+
io.write(content)
|
936
|
+
io.rewind
|
937
|
+
rescue => e
|
938
|
+
puts "Error while copying file from container: #{e.message}"
|
939
|
+
raise e # Optionally re-raise the exception or handle it according to your needs
|
940
|
+
ensure
|
941
|
+
io.close if io.respond_to?(:close)
|
942
|
+
end
|
943
|
+
|
944
|
+
content
|
945
|
+
end
|
946
|
+
|
947
|
+
# Reads the contents of a file inside the container.
|
948
|
+
#
|
949
|
+
# @param path [String] The path to the file.
|
950
|
+
# @return [String] The contents of the file.
|
951
|
+
def read_file(path)
|
952
|
+
raise ContainerNotStartedError unless @_container
|
953
|
+
|
954
|
+
@_container.read_file(path)
|
955
|
+
end
|
956
|
+
|
957
|
+
# Writes the contents of a file inside the container.
|
958
|
+
#
|
959
|
+
# @param path [String] The path to the file.
|
960
|
+
# @param contents [String] The contents of the file.
|
961
|
+
# @raise [ContainerNotStartedError] If the container has not been started.
|
962
|
+
# @raise [ConnectionError] If the connection to the Docker daemon fails.
|
963
|
+
def store_file(path, contents)
|
964
|
+
raise ContainerNotStartedError unless @_container
|
965
|
+
|
966
|
+
@_container.store_file(path, contents)
|
967
|
+
end
|
968
|
+
|
813
969
|
private
|
814
970
|
|
815
971
|
def normalize_ports(ports)
|
@@ -937,6 +1093,7 @@ module Testcontainers
|
|
937
1093
|
"name" => @name,
|
938
1094
|
"Image" => @image,
|
939
1095
|
"Cmd" => @command,
|
1096
|
+
"Entrypoint" => @entrypoint,
|
940
1097
|
"ExposedPorts" => @exposed_ports,
|
941
1098
|
"Volumes" => @volumes,
|
942
1099
|
"Env" => @env,
|
@@ -950,4 +1107,7 @@ module Testcontainers
|
|
950
1107
|
}.compact
|
951
1108
|
end
|
952
1109
|
end
|
1110
|
+
|
1111
|
+
# Alias for forward-compatibility
|
1112
|
+
GenericContainer = DockerContainer
|
953
1113
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: testcontainers-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillermo Iguaran
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docker-api
|
@@ -98,13 +98,13 @@ files:
|
|
98
98
|
- lib/testcontainers.rb
|
99
99
|
- lib/testcontainers/docker_container.rb
|
100
100
|
- lib/testcontainers/version.rb
|
101
|
-
homepage: https://github.com/
|
101
|
+
homepage: https://github.com/testcontainers/testcontainers-ruby
|
102
102
|
licenses:
|
103
103
|
- MIT
|
104
104
|
metadata:
|
105
|
-
homepage_uri: https://github.com/
|
106
|
-
source_code_uri: https://github.com/
|
107
|
-
changelog_uri: https://github.com/
|
105
|
+
homepage_uri: https://github.com/testcontainers/testcontainers-ruby
|
106
|
+
source_code_uri: https://github.com/testcontainers/testcontainers-ruby
|
107
|
+
changelog_uri: https://github.com/testcontainers/testcontainers-ruby/blob/main/core/CHANGELOG.md
|
108
108
|
post_install_message:
|
109
109
|
rdoc_options: []
|
110
110
|
require_paths:
|