testcontainers-core 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de8f9261b2ba17241f48480e8416830c0a8f26bd5d8d3fe3c7b9651a1f2d21f7
4
- data.tar.gz: 2e0b37028da3f826adbfe57b0003b3ac46b7915bab6b1122bdd1af4693ae7fc3
3
+ metadata.gz: 584f5aabce655fd2f113af37af6ce59cc8b3e0f6aa4b276bff52378e1d3c5e9d
4
+ data.tar.gz: 0a3c73c6a6ba495c61b3ded68092d4a58a06099e1ff543d7ac2a45e9503082a6
5
5
  SHA512:
6
- metadata.gz: 463b57b9a444a3395fe645dfb72937381551c52b26f7f1d19f4228c00f53518b7c05e5a7a0e80956e95dfc16bedb9f69dbb006efe4bf72cf45dc5fe06d77d0d8
7
- data.tar.gz: c9b28c1ee6d6a6a8fd30f7cb334307adbc673efd7554b50c0bd0fe7f1ffd72ff14b0c53ce44407113f5f584ee9e9ebe4ccc532c1a4d67a3f4766efda266a79ce
6
+ metadata.gz: 18f526847480a5cec71aa4abf2b10393fa7a08ccf5c4f70a07c18667624a8fb49ca3f0d9d241f0f5dd9e32404f3e0e06fc2cb67465059703d5e9eec143c04f4e
7
+ data.tar.gz: fcc6793d0bbdf773de7e0cb5933364f45840c034c8821dd12ab99c17d08a05c23967d2b992d4152b2c7298eae12d75d751eaff8e83e21563a060647cdcbd1b67
data/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ ## [0.1.2] - 2023-05-13
2
+
3
+ ## Added
4
+
5
+ - DockerContainer#first_mapped_port method returns the first of the
6
+ mapped ports for convenience.
7
+
8
+ - DockerContainer#get_env(key) method to gets the value of a single
9
+ env variable in the container
10
+
11
+ - Support custom healthchecks set with the new and
12
+ DockerContainer#add_/with_healthcheck methods. Example:
13
+
14
+ redis_container.with_healthcheck(test: ["redis-cli ping"], interval: 30, timeout: 30, retries: 3)
15
+
16
+ ## Changed
17
+
18
+ - DockerContainer#mapped_port(port) method now returns an Integer instead of a String.
19
+
20
+ ## Fixed
21
+
22
+ - Links to the GitHub project on the README.md file are fixed.
23
+
24
+ - Healtchecks handling have been fixed
25
+
26
+ ## [0.1.1] - 2023-05-04
27
+
28
+ ### Added
29
+
30
+ - Add .yardopts file to set the project ready for RubyDoc.info.
31
+
32
+ ## [0.1.0] - 2023-05-04
33
+
34
+ ### Added
35
+
36
+ - Initial release of the project with the Testcontainer::DockerContainer working.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- testcontainers-core (0.1.0)
4
+ testcontainers-core (0.1.1)
5
5
  docker-api (~> 2.2)
6
6
 
7
7
  GEM
@@ -13,11 +13,12 @@ module Testcontainers
13
13
  # @attr env [Array<String>, nil] an array of environment variables for the container in the format KEY=VALUE
14
14
  # @attr labels [Hash, nil] a hash of labels to be applied to the container
15
15
  # @attr working_dir [String, nil] the working directory for the container
16
+ # @attr healthcheck [Hash, nil] a hash of healthcheck options for the container
16
17
  # @attr logger [Logger] a logger instance for the container
17
18
  # @attr_reader _container [Docker::Container, nil] the underlying Docker::Container object
18
19
  # @attr_reader _id [String, nil] the container's ID
19
20
  class DockerContainer
20
- attr_accessor :name, :image, :command, :exposed_ports, :port_bindings, :volumes, :filesystem_binds, :env, :labels, :working_dir
21
+ attr_accessor :name, :image, :command, :exposed_ports, :port_bindings, :volumes, :filesystem_binds, :env, :labels, :working_dir, :healthcheck
21
22
  attr_accessor :logger
22
23
  attr_reader :_container, :_id
23
24
 
@@ -35,7 +36,7 @@ module Testcontainers
35
36
  # @param working_dir [String, nil] the working directory for the container
36
37
  # @param logger [Logger] a logger instance for the container
37
38
  def initialize(image, command: nil, name: nil, exposed_ports: nil, port_bindings: nil, volumes: nil, filesystem_binds: nil, env: nil,
38
- labels: nil, working_dir: nil, logger: Testcontainers.logger)
39
+ labels: nil, working_dir: nil, healthcheck: nil, logger: Testcontainers.logger)
39
40
 
40
41
  @image = image
41
42
  @command = command
@@ -47,6 +48,7 @@ module Testcontainers
47
48
  @filesystem_binds = add_filesystem_binds(filesystem_binds) if filesystem_binds
48
49
  @labels = add_labels(labels) if labels
49
50
  @working_dir = working_dir
51
+ @healthcheck = add_healthcheck(healthcheck) if healthcheck
50
52
  @logger = logger
51
53
  @_container = nil
52
54
  @_id = nil
@@ -206,6 +208,40 @@ module Testcontainers
206
208
  @labels
207
209
  end
208
210
 
211
+ # Adds a healthcheck to the container.
212
+ #
213
+ # @param options [Hash] the healthcheck options.
214
+ # @option options [Array|String] :test the command to run to check the health of the container.
215
+ # @option options [Float] :interval the time in seconds between health checks. (default: 30)
216
+ # @option options [Float] :timeout the time in seconds to wait for a health check to complete. (default: 30)
217
+ # @option options [Integer] :retries the number of times to retry a failed health check before giving up. (default: 3)
218
+ # @option options [Boolean] :shell whether or not to run the health check in a shell. (default: false)
219
+ # @return [Hash] the healthcheck options for Docker.
220
+ def add_healthcheck(options = {})
221
+ test = options[:test]
222
+
223
+ if test.nil?
224
+ @healthcheck = {"Test" => ["NONE"]}
225
+ return @healthcheck
226
+ end
227
+
228
+ interval = options[:interval]&.to_f || 30.0
229
+ timeout = options[:timeout]&.to_f || 30.0
230
+ retries = options[:retries]&.to_i || 3
231
+ shell = options[:shell] || false
232
+
233
+ test = test.split(" ") if test.is_a?(String)
234
+ test = shell ? test.unshift("CMD-SHELL") : test.unshift("CMD")
235
+
236
+ @healthcheck = {
237
+ "Test" => test,
238
+ "Interval" => (interval * 1_000_000_000).to_i,
239
+ "Timeout" => (timeout * 1_000_000_000).to_i,
240
+ "Retries" => retries,
241
+ "StartPeriod" => 0
242
+ }
243
+ end
244
+
209
245
  # Set options for the container configuration using "with_" methods.
210
246
  #
211
247
  # @param options [Hash] A hash of options where keys correspond to "with_" methods and values are the arguments for those methods.
@@ -323,6 +359,20 @@ module Testcontainers
323
359
  self
324
360
  end
325
361
 
362
+ # Adds a healthcheck to the container.
363
+ #
364
+ # @param options [Hash] the healthcheck options.
365
+ # @option options [Array|String] :test the command to run to check the health of the container.
366
+ # @option options [Float] :interval the time in seconds between health checks. (default: 30)
367
+ # @option options [Float] :timeout the time in seconds to wait for a health check to complete. (default: 30)
368
+ # @option options [Integer] :retries the number of times to retry a failed health check before giving up. (default: 3)
369
+ # @option options [Boolean] :shell whether or not to run the health check in a shell. (default: false)
370
+ # @return [DockerContainer] The updated DockerContainer instance.
371
+ def with_healthcheck(options = {})
372
+ add_healthcheck(options)
373
+ self
374
+ end
375
+
326
376
  # Starts the container, yields the container instance to the block, and stops the container.
327
377
  #
328
378
  # @yield [DockerContainer] The container instance.
@@ -492,7 +542,7 @@ module Testcontainers
492
542
  # @raise [ConnectionError] If the connection to the Docker daemon fails.
493
543
  # @raise [HealthcheckNotSupportedError] If the container does not support healthchecks.
494
544
  def healthy?
495
- if supports_healtcheck?
545
+ if supports_healthcheck?
496
546
  @_container&.json&.dig("State", "Health", "Status") == "healthy"
497
547
  else
498
548
  raise HealthcheckNotSupportedError
@@ -508,9 +558,9 @@ module Testcontainers
508
558
  #
509
559
  # @return [Boolean] Whether the container supports healthchecks.
510
560
  # @raise [ContainerNotStartedError] If the container has not been started.
511
- def supports_healtcheck?
561
+ def supports_healthcheck?
512
562
  raise ContainerNotStartedError unless @_container
513
- @_container.json["Config"]["Healthcheck"].present?
563
+ @_container.json["Config"]["Healthcheck"] != nil
514
564
  end
515
565
 
516
566
  # Returns whether the container exists.
@@ -573,8 +623,8 @@ module Testcontainers
573
623
 
574
624
  # Returns the mapped host port for the given container port.
575
625
  #
576
- # @param port [Integer] The container port.
577
- # @return [String] The mapped host port.
626
+ # @param port [Integer | String] The container port.
627
+ # @return [Integer] The mapped host port.
578
628
  # @raise [ConnectionError] If the connection to the Docker daemon fails.
579
629
  # @raise [ContainerNotStartedError] If the container has not been started.
580
630
  def mapped_port(port)
@@ -585,13 +635,32 @@ module Testcontainers
585
635
  gateway_ip = container_gateway_ip
586
636
  host = docker_host
587
637
 
588
- return port if gateway_ip == host
638
+ return port.to_i if gateway_ip == host
589
639
  end
590
- mapped_port
640
+ mapped_port.to_i
591
641
  rescue Excon::Error::Socket => e
592
642
  raise ConnectionError, e.message
593
643
  end
594
644
 
645
+ # Returns the container's first mapped port.
646
+ #
647
+ # @return [Integer] The container's first mapped port.
648
+ # @raise [ConnectionError] If the connection to the Docker daemon fails.
649
+ def first_mapped_port
650
+ raise ContainerNotStartedError unless @_container
651
+ container_ports.map { |port| mapped_port(port) }.first
652
+ end
653
+
654
+ # Returns the value for the given environment variable.
655
+ #
656
+ # @param key [String] The environment variable's key.
657
+ # @return [String] The environment variable's value.
658
+ # @return [nil] If the environment variable does not exist.
659
+ def get_env(key)
660
+ env_entry = env.find { |entry| entry.start_with?("#{key}=") }
661
+ env_entry&.split("=")&.last
662
+ end
663
+
595
664
  # Returns the container's logs.
596
665
  #
597
666
  # @param stdout [Boolean] Whether to return stdout.
@@ -830,6 +899,11 @@ module Testcontainers
830
899
  @_container&.json&.dig("NetworkSettings", "Ports", normalize_port(port))&.first&.dig("HostPort")
831
900
  end
832
901
 
902
+ def container_ports
903
+ ports = @_container&.json&.dig("NetworkSettings", "Ports")&.keys || []
904
+ ports&.map { |port| port.split("/").first }
905
+ end
906
+
833
907
  def default_gateway_ip
834
908
  cmd = "ip route | awk '/default/ { print $3 }'"
835
909
 
@@ -868,6 +942,7 @@ module Testcontainers
868
942
  "Env" => @env,
869
943
  "Labels" => @labels,
870
944
  "WorkingDir" => @working_dir,
945
+ "Healthcheck" => @healthcheck,
871
946
  "HostConfig" => {
872
947
  "PortBindings" => @port_bindings,
873
948
  "Binds" => @filesystem_binds
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Testcontainers
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
@@ -20,6 +20,8 @@ module Testcontainers
20
20
 
21
21
  class PortNotMappedError < Error; end
22
22
 
23
+ class ContainerLaunchException < Error; end
24
+
23
25
  class << self
24
26
  attr_writer :logger
25
27
 
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.1
4
+ version: 0.1.2
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-05-04 00:00:00.000000000 Z
11
+ date: 2023-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api
@@ -88,6 +88,7 @@ executables: []
88
88
  extensions: []
89
89
  extra_rdoc_files: []
90
90
  files:
91
+ - CHANGELOG.md
91
92
  - Gemfile
92
93
  - Gemfile.lock
93
94
  - LICENSE.txt