testcontainers-core 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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