Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ gem "testcontainers-redpanda", path: "./redpanda"
gem "testcontainers-rabbitmq", path: "./rabbitmq"
gem "testcontainers-selenium", path: "./selenium"
gem "testcontainers-compose", path: "./compose"
gem "testcontainers-clickhouse", path: "./clickhouse"
gem "mysql2", "~> 0.5.3"
gem "pg", "~> 1.5"
gem "redis", "~> 5.0"
Expand Down
7 changes: 7 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ PATH
testcontainers (0.2.0)
testcontainers-core (= 0.2.0)

PATH
remote: clickhouse
specs:
testcontainers-clickhouse (0.1.0)
testcontainers-core (~> 0.1)

PATH
remote: compose
specs:
Expand Down Expand Up @@ -219,6 +225,7 @@ DEPENDENCIES
selenium-webdriver (~> 4.1.0)
standard (~> 1.3)
testcontainers!
testcontainers-clickhouse!
testcontainers-compose!
testcontainers-core!
testcontainers-elasticsearch!
Expand Down
5 changes: 5 additions & 0 deletions clickhouse/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## [0.1.0] - 2026-03-29

### Added

- Initial release of the ClickHouse module
9 changes: 9 additions & 0 deletions clickhouse/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

source "https://rubygems.org"

# Specify your gem's dependencies in testcontainers-clickhouse.gemspec
gemspec

# Use the latest version of testcontainers-core from the local path
gem "testcontainers-core", path: "../core"
129 changes: 129 additions & 0 deletions clickhouse/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
PATH
remote: ../core
specs:
testcontainers-core (0.2.0)
base64 (~> 0.3)
docker-api (~> 2.4)
java-properties (~> 0.3.0)

PATH
remote: .
specs:
testcontainers-clickhouse (0.1.0)
testcontainers-core (~> 0.1)

GEM
remote: https://rubygems.org/
specs:
ast (2.4.3)
base64 (0.3.0)
docker-api (2.4.0)
excon (>= 0.64.0)
multi_json
excon (1.4.2)
logger
java-properties (0.3.0)
json (2.19.3)
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
logger (1.7.0)
minitest (5.27.0)
minitest-hooks (1.5.3)
minitest (> 5.3)
multi_json (1.19.1)
net-http (0.9.1)
uri (>= 0.11.1)
parallel (1.27.0)
parser (3.3.10.2)
ast (~> 2.4.1)
racc
prism (1.9.0)
racc (1.8.1)
rainbow (3.1.1)
rake (13.3.1)
regexp_parser (2.11.3)
rubocop (1.84.2)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.49.1)
parser (>= 3.3.7.2)
prism (~> 1.7)
rubocop-performance (1.26.1)
lint_roller (~> 1.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.47.1, < 2.0)
ruby-progressbar (1.13.0)
standard (1.54.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.0)
rubocop (~> 1.84.0)
standard-custom (~> 1.0.0)
standard-performance (~> 1.8)
standard-custom (1.0.2)
lint_roller (~> 1.0)
rubocop (~> 1.50)
standard-performance (1.9.0)
lint_roller (~> 1.1)
rubocop-performance (~> 1.26.0)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)
uri (1.1.1)

PLATFORMS
arm64-darwin-25
ruby

DEPENDENCIES
minitest (~> 5.0)
minitest-hooks (~> 1.5)
net-http
rake (~> 13.0)
standard (~> 1.3)
testcontainers-clickhouse!
testcontainers-core!

CHECKSUMS
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
docker-api (2.4.0) sha256=824be734f4cc8718189be9c8e795b6414acbbf7e8b082a06f959a27dd8dd63e6
excon (1.4.2) sha256=32d8d8eda619717d9b8043b4675e096fb5c2139b080e2ad3b267f88c545aaa35
java-properties (0.3.0) sha256=0a9fdda90c25ba9ba4de0e242d954a5688629652b592aab66ed54e2b16b93093
json (2.19.3) sha256=289b0bb53052a1fa8c34ab33cc750b659ba14a5c45f3fcf4b18762dc67c78646
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
minitest (5.27.0) sha256=2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5
minitest-hooks (1.5.3) sha256=ef50dd3bf47e6d1646befc358c640c71ca41f5650f0036b4c69929a44d6f32c4
multi_json (1.19.1) sha256=7aefeff8f2c854bf739931a238e4aea64592845e0c0395c8a7d2eea7fdd631b7
net-http (0.9.1) sha256=25ba0b67c63e89df626ed8fac771d0ad24ad151a858af2cc8e6a716ca4336996
parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
parser (3.3.10.2) sha256=6f60c84aa4bdcedb6d1a2434b738fe8a8136807b6adc8f7f53b97da9bc4e9357
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4
rubocop (1.84.2) sha256=5692cea54168f3dc8cb79a6fe95c5424b7ea893c707ad7a4307b0585e88dbf5f
rubocop-ast (1.49.1) sha256=4412f3ee70f6fe4546cc489548e0f6fcf76cafcfa80fa03af67098ffed755035
rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
standard (1.54.0) sha256=7a4b08f83d9893083c8f03bc486f0feeb6a84d48233b40829c03ef4767ea0100
standard-custom (1.0.2) sha256=424adc84179a074f1a2a309bb9cf7cd6bfdb2b6541f20c6bf9436c0ba22a652b
standard-performance (1.9.0) sha256=49483d31be448292951d80e5e67cdcb576c2502103c7b40aec6f1b6e9c88e3f2
testcontainers-clickhouse (0.1.0)
testcontainers-core (0.2.0)
unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6

BUNDLED WITH
4.0.7
21 changes: 21 additions & 0 deletions clickhouse/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2023 Guillermo Iguaran

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
14 changes: 14 additions & 0 deletions clickhouse/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require "bundler/gem_tasks"
require "rake/testtask"

Rake::TestTask.new(:test) do |t|
t.libs << "test"
t.libs << "lib"
t.test_files = FileList["test/**/*_test.rb"]
end

require "standard/rake"

task default: %i[test standard]
146 changes: 146 additions & 0 deletions clickhouse/lib/testcontainers/clickhouse.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# frozen_string_literal: true

require_relative "clickhouse/version"
require "testcontainers"

module Testcontainers
# ClickhouseContainer class is used to manage containers that runs a Clickhouse server
#
# @attr_reader [String] username used by the container
# @attr_reader [String] password used by the container
# @attr_reader [String] database used by the container
class ClickhouseContainer < ::Testcontainers::DockerContainer
# Default ports used by the container
CLICKHOUSE_DEFAULT_PORT = 9000
CLICKHOUSE_DEFAULT_HTTP_PORT = 8123

# Default image used by the container
CLICKHOUSE_DEFAULT_IMAGE = "clickhouse/clickhouse-server:latest"

# Default credentials used by the container
CLICKHOUSE_DEFAULT_USER = "default"
CLICKHOUSE_DEFAULT_PASS = "password"
CLICKHOUSE_DB = "default"

attr_reader :username, :password, :database

# Default "wait for" strategy
WAIT_FOR_PROC = ->(container) {
container.wait_for_http(container_port: 8123, timeout: 30, interval: 1.0, path: "/", status: 200)
}

# Initializes a new instance of ClickhouseContainer
#
# @param image [String] the image to use
# @param username [String] the username to use
# @param password [String] the password to use
# @param database [String]
# @param kwargs [Hash] the options to pass to the container. See {DockerContainer#initialize}
# @return [ClickhouseContainer] a new instance of ClickhouseContainer
def initialize(image = CLICKHOUSE_DEFAULT_IMAGE, username: nil, password: nil, database: nil, **kwargs)
super(image, wait_for: WAIT_FOR_PROC, exposed_ports: [CLICKHOUSE_DEFAULT_PORT, CLICKHOUSE_DEFAULT_HTTP_PORT], **kwargs)
@username = username || ENV.fetch("CLICKHOUSE_USER", CLICKHOUSE_DEFAULT_USER)
@password = password || ENV.fetch("CLICKHOUSE_PASSWORD", CLICKHOUSE_DEFAULT_PASS)
@database = database || ENV.fetch("CLICKHOUSE_DB", CLICKHOUSE_DB)
end

# Starts the container
#
# @return [ClickhouseContainer] self
def start
_configure
super
end

# Returns the native TCP port used to connect to the container
#
# @return [Integer] the port used by the container
def port
CLICKHOUSE_DEFAULT_PORT
end
alias_method :tcp_port, :port

# Returns the HTTP port used to connect to the container via HTTP/HTTPS
#
# @return [Integer] the HTTP/HTTPS port used by the container
def http_port
CLICKHOUSE_DEFAULT_HTTP_PORT
end

# Returns the clickhouse connection url (e.g. clickhouse://user:password@host:port/database)
#
# @param protocol [String] the protocol to use in the string (default: "clickhouse://")
# @param username [String] the username to use in the string (default: @username)
# @param password [String] the password to use in the string (default: @password)
# @param database [String] the database to use in the string (default: @database)
# @return [String] the clickhouse url
# @raise [ConnectionError] If the connection to the Docker daemon fails.
# @raise [ContainerNotStartedError] If the container has not been started.
def clickhouse_url(protocol: "clickhouse://", username: nil, password: nil, database: nil)
username ||= @username
password ||= @password
database ||= @database
database = "/#{database}" unless database.start_with?("/")

# clickhouse://user:pass@host:9000/database
"#{protocol}#{username}:#{password}@#{host}:#{mapped_port(port)}#{database}"
end

alias_method :connection_url, :clickhouse_url

# Returns the clickhouse connection url (e.g. http://user:password@host:port)
#
# @param protocol [String] the protocol to use in the string (default: "http")
# @return [String] the url for the management UI. Returns nil if the management UI is not available.
# @raise [ConnectionError] If the connection to the Docker daemon fails.
# @raise [ContainerNotStartedError] If the container has not been started.
def clickhouse_http_url(protocol: "http")
port = mapped_port(http_port)
port.nil? ? nil : "#{protocol}://#{username}:#{password}@#{host}:#{port}"
end

# Sets the database to use
#
# @param database [String] the database to use
# @return [ClickhouseContainer] self
def with_database(database)
@database = database
self
end

# Sets the username to use
#
# @param username [String] the username to use
# @return [ClickhouseContainer] self
def with_username(username)
@username = username
self
end

# Sets the password to use
#
# @param password [String] the password to use
# @return [ClickhouseContainer] self
def with_password(password)
@password = password
self
end

# Returns the mapped TCP port
#
# @return [Integer] The container's mapped TCP port.
# @raise [ConnectionError] If the connection to the Docker daemon fails.
def first_mapped_port
raise ContainerNotStartedError unless @_container
mapped_port(port)
end

private

def _configure
add_env("CLICKHOUSE_USER", @username)
add_env("CLICKHOUSE_PASSWORD", @password)
add_env("CLICKHOUSE_DB", @database)
end
end
end
7 changes: 7 additions & 0 deletions clickhouse/lib/testcontainers/clickhouse/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

module Testcontainers
module Clickhouse
VERSION = "0.1.0"
end
end
Loading