Skip to content

Commit 3bee512

Browse files
committed
Add ClickHouse module
1 parent 602f58b commit 3bee512

13 files changed

Lines changed: 528 additions & 0 deletions

File tree

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ gem "testcontainers-redpanda", path: "./redpanda"
1919
gem "testcontainers-rabbitmq", path: "./rabbitmq"
2020
gem "testcontainers-selenium", path: "./selenium"
2121
gem "testcontainers-compose", path: "./compose"
22+
gem "testcontainers-clickhouse", path: "./clickhouse"
2223
gem "mysql2", "~> 0.5.3"
2324
gem "pg", "~> 1.5"
2425
gem "redis", "~> 5.0"

Gemfile.lock

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ PATH
44
testcontainers (0.2.0)
55
testcontainers-core (= 0.2.0)
66

7+
PATH
8+
remote: clickhouse
9+
specs:
10+
testcontainers-clickhouse (0.1.0)
11+
testcontainers-core (~> 0.1)
12+
713
PATH
814
remote: compose
915
specs:
@@ -219,6 +225,7 @@ DEPENDENCIES
219225
selenium-webdriver (~> 4.1.0)
220226
standard (~> 1.3)
221227
testcontainers!
228+
testcontainers-clickhouse!
222229
testcontainers-compose!
223230
testcontainers-core!
224231
testcontainers-elasticsearch!

clickhouse/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## [0.1.0] - 2026-03-29
2+
3+
### Added
4+
5+
- Initial release of the ClickHouse module

clickhouse/Gemfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# frozen_string_literal: true
2+
3+
source "https://rubygems.org"
4+
5+
# Specify your gem's dependencies in testcontainers-clickhouse.gemspec
6+
gemspec
7+
8+
# Use the latest version of testcontainers-core from the local path
9+
gem "testcontainers-core", path: "../core"

clickhouse/Gemfile.lock

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
PATH
2+
remote: ../core
3+
specs:
4+
testcontainers-core (0.2.0)
5+
base64 (~> 0.3)
6+
docker-api (~> 2.4)
7+
java-properties (~> 0.3.0)
8+
9+
PATH
10+
remote: .
11+
specs:
12+
testcontainers-clickhouse (0.1.0)
13+
testcontainers-core (~> 0.1)
14+
15+
GEM
16+
remote: https://rubygems.org/
17+
specs:
18+
ast (2.4.3)
19+
base64 (0.3.0)
20+
docker-api (2.4.0)
21+
excon (>= 0.64.0)
22+
multi_json
23+
excon (1.4.2)
24+
logger
25+
java-properties (0.3.0)
26+
json (2.19.3)
27+
language_server-protocol (3.17.0.5)
28+
lint_roller (1.1.0)
29+
logger (1.7.0)
30+
minitest (5.27.0)
31+
minitest-hooks (1.5.3)
32+
minitest (> 5.3)
33+
multi_json (1.19.1)
34+
net-http (0.9.1)
35+
uri (>= 0.11.1)
36+
parallel (1.27.0)
37+
parser (3.3.10.2)
38+
ast (~> 2.4.1)
39+
racc
40+
prism (1.9.0)
41+
racc (1.8.1)
42+
rainbow (3.1.1)
43+
rake (13.3.1)
44+
regexp_parser (2.11.3)
45+
rubocop (1.84.2)
46+
json (~> 2.3)
47+
language_server-protocol (~> 3.17.0.2)
48+
lint_roller (~> 1.1.0)
49+
parallel (~> 1.10)
50+
parser (>= 3.3.0.2)
51+
rainbow (>= 2.2.2, < 4.0)
52+
regexp_parser (>= 2.9.3, < 3.0)
53+
rubocop-ast (>= 1.49.0, < 2.0)
54+
ruby-progressbar (~> 1.7)
55+
unicode-display_width (>= 2.4.0, < 4.0)
56+
rubocop-ast (1.49.1)
57+
parser (>= 3.3.7.2)
58+
prism (~> 1.7)
59+
rubocop-performance (1.26.1)
60+
lint_roller (~> 1.1)
61+
rubocop (>= 1.75.0, < 2.0)
62+
rubocop-ast (>= 1.47.1, < 2.0)
63+
ruby-progressbar (1.13.0)
64+
standard (1.54.0)
65+
language_server-protocol (~> 3.17.0.2)
66+
lint_roller (~> 1.0)
67+
rubocop (~> 1.84.0)
68+
standard-custom (~> 1.0.0)
69+
standard-performance (~> 1.8)
70+
standard-custom (1.0.2)
71+
lint_roller (~> 1.0)
72+
rubocop (~> 1.50)
73+
standard-performance (1.9.0)
74+
lint_roller (~> 1.1)
75+
rubocop-performance (~> 1.26.0)
76+
unicode-display_width (3.2.0)
77+
unicode-emoji (~> 4.1)
78+
unicode-emoji (4.2.0)
79+
uri (1.1.1)
80+
81+
PLATFORMS
82+
arm64-darwin-25
83+
ruby
84+
85+
DEPENDENCIES
86+
minitest (~> 5.0)
87+
minitest-hooks (~> 1.5)
88+
net-http
89+
rake (~> 13.0)
90+
standard (~> 1.3)
91+
testcontainers-clickhouse!
92+
testcontainers-core!
93+
94+
CHECKSUMS
95+
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
96+
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
97+
docker-api (2.4.0) sha256=824be734f4cc8718189be9c8e795b6414acbbf7e8b082a06f959a27dd8dd63e6
98+
excon (1.4.2) sha256=32d8d8eda619717d9b8043b4675e096fb5c2139b080e2ad3b267f88c545aaa35
99+
java-properties (0.3.0) sha256=0a9fdda90c25ba9ba4de0e242d954a5688629652b592aab66ed54e2b16b93093
100+
json (2.19.3) sha256=289b0bb53052a1fa8c34ab33cc750b659ba14a5c45f3fcf4b18762dc67c78646
101+
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
102+
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
103+
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
104+
minitest (5.27.0) sha256=2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5
105+
minitest-hooks (1.5.3) sha256=ef50dd3bf47e6d1646befc358c640c71ca41f5650f0036b4c69929a44d6f32c4
106+
multi_json (1.19.1) sha256=7aefeff8f2c854bf739931a238e4aea64592845e0c0395c8a7d2eea7fdd631b7
107+
net-http (0.9.1) sha256=25ba0b67c63e89df626ed8fac771d0ad24ad151a858af2cc8e6a716ca4336996
108+
parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
109+
parser (3.3.10.2) sha256=6f60c84aa4bdcedb6d1a2434b738fe8a8136807b6adc8f7f53b97da9bc4e9357
110+
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
111+
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
112+
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
113+
rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
114+
regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4
115+
rubocop (1.84.2) sha256=5692cea54168f3dc8cb79a6fe95c5424b7ea893c707ad7a4307b0585e88dbf5f
116+
rubocop-ast (1.49.1) sha256=4412f3ee70f6fe4546cc489548e0f6fcf76cafcfa80fa03af67098ffed755035
117+
rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834
118+
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
119+
standard (1.54.0) sha256=7a4b08f83d9893083c8f03bc486f0feeb6a84d48233b40829c03ef4767ea0100
120+
standard-custom (1.0.2) sha256=424adc84179a074f1a2a309bb9cf7cd6bfdb2b6541f20c6bf9436c0ba22a652b
121+
standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2
122+
testcontainers-clickhouse (0.1.0)
123+
testcontainers-core (0.2.0)
124+
unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
125+
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
126+
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
127+
128+
BUNDLED WITH
129+
4.0.7

clickhouse/LICENSE.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2023 Guillermo Iguaran
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

clickhouse/Rakefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# frozen_string_literal: true
2+
3+
require "bundler/gem_tasks"
4+
require "rake/testtask"
5+
6+
Rake::TestTask.new(:test) do |t|
7+
t.libs << "test"
8+
t.libs << "lib"
9+
t.test_files = FileList["test/**/*_test.rb"]
10+
end
11+
12+
require "standard/rake"
13+
14+
task default: %i[test standard]
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "clickhouse/version"
4+
require "testcontainers"
5+
6+
module Testcontainers
7+
# ClickhouseContainer class is used to manage containers that runs a Clickhouse server
8+
#
9+
# @attr_reader [String] username used by the container
10+
# @attr_reader [String] password used by the container
11+
# @attr_reader [String] database used by the container
12+
class ClickhouseContainer < ::Testcontainers::DockerContainer
13+
# Default ports used by the container
14+
CLICKHOUSE_DEFAULT_PORT = 9000
15+
CLICKHOUSE_DEFAULT_HTTP_PORT = 8123
16+
17+
# Default image used by the container
18+
CLICKHOUSE_DEFAULT_IMAGE = "clickhouse/clickhouse-server:latest"
19+
20+
# Default credentials used by the container
21+
CLICKHOUSE_DEFAULT_USER = "default"
22+
CLICKHOUSE_DEFAULT_PASS = "password"
23+
CLICKHOUSE_DB = "default"
24+
25+
attr_reader :username, :password, :database
26+
27+
# Default "wait for" strategy
28+
WAIT_FOR_PROC = ->(container) {
29+
container.wait_for_http(container_port: 8123, timeout: 30, interval: 1.0, path: "/", status: 200)
30+
}
31+
32+
# Initializes a new instance of ClickhouseContainer
33+
#
34+
# @param image [String] the image to use
35+
# @param username [String] the username to use
36+
# @param password [String] the password to use
37+
# @param database [String]
38+
# @param kwargs [Hash] the options to pass to the container. See {DockerContainer#initialize}
39+
# @return [ClickhouseContainer] a new instance of ClickhouseContainer
40+
def initialize(image = CLICKHOUSE_DEFAULT_IMAGE, username: nil, password: nil, database: nil, **kwargs)
41+
super(image, wait_for: WAIT_FOR_PROC, exposed_ports: [CLICKHOUSE_DEFAULT_PORT, CLICKHOUSE_DEFAULT_HTTP_PORT], **kwargs)
42+
@username = username || ENV.fetch("CLICKHOUSE_USER", CLICKHOUSE_DEFAULT_USER)
43+
@password = password || ENV.fetch("CLICKHOUSE_PASSWORD", CLICKHOUSE_DEFAULT_PASS)
44+
@database = database || ENV.fetch("CLICKHOUSE_DB", CLICKHOUSE_DB)
45+
end
46+
47+
# Starts the container
48+
#
49+
# @return [ClickhouseContainer] self
50+
def start
51+
_configure
52+
super
53+
end
54+
55+
# Returns the native TCP port used to connect to the container
56+
#
57+
# @return [Integer] the port used by the container
58+
def port
59+
CLICKHOUSE_DEFAULT_PORT
60+
end
61+
alias_method :tcp_port, :port
62+
63+
# Returns the HTTP port used to connect to the container via HTTP/HTTPS
64+
#
65+
# @return [Integer] the HTTP/HTTPS port used by the container
66+
def http_port
67+
CLICKHOUSE_DEFAULT_HTTP_PORT
68+
end
69+
70+
# Returns the clickhouse connection url (e.g. clickhouse://user:password@host:port/database)
71+
#
72+
# @param protocol [String] the protocol to use in the string (default: "clickhouse://")
73+
# @param username [String] the username to use in the string (default: @username)
74+
# @param password [String] the password to use in the string (default: @password)
75+
# @param database [String] the database to use in the string (default: @database)
76+
# @return [String] the clickhouse url
77+
# @raise [ConnectionError] If the connection to the Docker daemon fails.
78+
# @raise [ContainerNotStartedError] If the container has not been started.
79+
def clickhouse_url(protocol: "clickhouse://", username: nil, password: nil, database: nil)
80+
username ||= @username
81+
password ||= @password
82+
database ||= @database
83+
database = "/#{database}" unless database.start_with?("/")
84+
85+
# clickhouse://user:pass@host:9000/database
86+
"#{protocol}#{username}:#{password}@#{host}:#{mapped_port(port)}#{database}"
87+
end
88+
89+
alias_method :connection_url, :clickhouse_url
90+
91+
# Returns the clickhouse connection url (e.g. http://user:password@host:port)
92+
#
93+
# @param protocol [String] the protocol to use in the string (default: "http")
94+
# @return [String] the url for the management UI. Returns nil if the management UI is not available.
95+
# @raise [ConnectionError] If the connection to the Docker daemon fails.
96+
# @raise [ContainerNotStartedError] If the container has not been started.
97+
def clickhouse_http_url(protocol: "http")
98+
port = mapped_port(http_port)
99+
port.nil? ? nil : "#{protocol}://#{username}:#{password}@#{host}:#{port}"
100+
end
101+
102+
# Sets the database to use
103+
#
104+
# @param database [String] the database to use
105+
# @return [ClickhouseContainer] self
106+
def with_database(database)
107+
@database = database
108+
self
109+
end
110+
111+
# Sets the username to use
112+
#
113+
# @param username [String] the username to use
114+
# @return [ClickhouseContainer] self
115+
def with_username(username)
116+
@username = username
117+
self
118+
end
119+
120+
# Sets the password to use
121+
#
122+
# @param password [String] the password to use
123+
# @return [ClickhouseContainer] self
124+
def with_password(password)
125+
@password = password
126+
self
127+
end
128+
129+
# Returns the mapped TCP port
130+
#
131+
# @return [Integer] The container's mapped TCP port.
132+
# @raise [ConnectionError] If the connection to the Docker daemon fails.
133+
def first_mapped_port
134+
raise ContainerNotStartedError unless @_container
135+
mapped_port(port)
136+
end
137+
138+
private
139+
140+
def _configure
141+
add_env("CLICKHOUSE_USER", @username)
142+
add_env("CLICKHOUSE_PASSWORD", @password)
143+
add_env("CLICKHOUSE_DB", @database)
144+
end
145+
end
146+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
module Testcontainers
4+
module Clickhouse
5+
VERSION = "0.1.0"
6+
end
7+
end

0 commit comments

Comments
 (0)