diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 6bfdee9c3619..4de915a2570a 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -306,7 +306,7 @@ in
cinnamon-wayland = runTest ./cinnamon-wayland.nix;
cjdns = runTest ./cjdns.nix;
clatd = runTest ./clatd.nix;
- clickhouse = runTest ./clickhouse.nix;
+ clickhouse = import ./clickhouse { inherit runTest; };
cloud-init = handleTest ./cloud-init.nix { };
cloud-init-hostname = handleTest ./cloud-init-hostname.nix { };
cloudlog = runTest ./cloudlog.nix;
diff --git a/nixos/tests/clickhouse.nix b/nixos/tests/clickhouse/base.nix
similarity index 94%
rename from nixos/tests/clickhouse.nix
rename to nixos/tests/clickhouse/base.nix
index 165f00a1ec4e..cbeb5b64699a 100644
--- a/nixos/tests/clickhouse.nix
+++ b/nixos/tests/clickhouse/base.nix
@@ -1,7 +1,7 @@
{ pkgs, ... }:
{
name = "clickhouse";
- meta.maintainers = with pkgs.lib.maintainers; [ ];
+ meta.maintainers = with pkgs.lib.maintainers; [ jpds ];
nodes.machine = {
services.clickhouse.enable = true;
diff --git a/nixos/tests/clickhouse/default.nix b/nixos/tests/clickhouse/default.nix
new file mode 100644
index 000000000000..e6568010eb66
--- /dev/null
+++ b/nixos/tests/clickhouse/default.nix
@@ -0,0 +1,8 @@
+{ runTest }:
+
+{
+ base = runTest ./base.nix;
+ kafka = runTest ./kafka.nix;
+ keeper = runTest ./keeper.nix;
+ s3 = runTest ./s3.nix;
+}
diff --git a/nixos/tests/clickhouse/kafka.nix b/nixos/tests/clickhouse/kafka.nix
new file mode 100644
index 000000000000..29e4f839d07f
--- /dev/null
+++ b/nixos/tests/clickhouse/kafka.nix
@@ -0,0 +1,172 @@
+{ pkgs, ... }:
+
+let
+ kafkaNamedCollectionConfig = ''
+
+
+
+
+ kafka:9092
+ test_topic
+ clickhouse
+ JSONEachRow
+ 0
+ 1
+ 1
+
+
+
+ all
+ earliest
+
+
+
+
+ '';
+
+ kafkaNamedCollection = pkgs.writeText "kafka.xml" kafkaNamedCollectionConfig;
+in
+{
+ name = "clickhouse-kafka";
+ meta.maintainers = with pkgs.lib.maintainers; [ jpds ];
+
+ nodes = {
+ clickhouse = {
+ environment.etc = {
+ "clickhouse-server/config.d/kafka.xml" = {
+ source = "${kafkaNamedCollection}";
+ };
+ };
+
+ services.clickhouse.enable = true;
+ virtualisation.memorySize = 4096;
+ };
+
+ kafka = {
+ networking.firewall.allowedTCPPorts = [
+ 9092
+ 9093
+ ];
+
+ environment.systemPackages = [
+ pkgs.apacheKafka
+ pkgs.jq
+ ];
+
+ services.apache-kafka = {
+ enable = true;
+
+ # Randomly generated uuid. You can get one by running:
+ # kafka-storage.sh random-uuid
+ clusterId = "b81s-MuGSwyt_B9_h37wtQ";
+
+ formatLogDirs = true;
+
+ settings = {
+ listeners = [
+ "PLAINTEXT://:9092"
+ "CONTROLLER://:9093"
+ ];
+ "listener.security.protocol.map" = [
+ "PLAINTEXT:PLAINTEXT"
+ "CONTROLLER:PLAINTEXT"
+ ];
+ "controller.quorum.voters" = [
+ "1@kafka:9093"
+ ];
+ "controller.listener.names" = [ "CONTROLLER" ];
+
+ "node.id" = 1;
+ "broker.rack" = 1;
+
+ "process.roles" = [
+ "broker"
+ "controller"
+ ];
+
+ "log.dirs" = [ "/var/lib/apache-kafka" ];
+ "num.partitions" = 1;
+ "offsets.topic.replication.factor" = 1;
+ "transaction.state.log.replication.factor" = 1;
+ "transaction.state.log.min.isr" = 1;
+ };
+ };
+
+ systemd.services.apache-kafka.serviceConfig.StateDirectory = "apache-kafka";
+ };
+ };
+
+ testScript =
+ let
+ jsonTestMessage = pkgs.writeText "kafka-test-data.json" ''
+ { "id": 1, "first_name": "Fred", "age": 32 }
+ { "id": 2, "first_name": "Barbara", "age": 30 }
+ { "id": 3, "first_name": "Nicola", "age": 12 }
+ '';
+ # work around quote/substitution complexity by Nix, Perl, bash and SQL.
+ tableKafkaDDL = pkgs.writeText "ddl-kafka.sql" ''
+ CREATE TABLE `test_kafka_topic` (
+ `id` UInt32,
+ `first_name` String,
+ `age` UInt32
+ ) ENGINE = Kafka(cluster_1);
+ '';
+
+ tableDDL = pkgs.writeText "ddl.sql" ''
+ CREATE TABLE `test_topic` (
+ `id` UInt32,
+ `first_name` String,
+ `age` UInt32
+ ) ENGINE = MergeTree ORDER BY id;
+ '';
+
+ viewDDL = pkgs.writeText "view.sql" ''
+ CREATE MATERIALIZED VIEW kafka_view TO test_topic AS
+ SELECT
+ id,
+ first_name,
+ age,
+ FROM test_kafka_topic;
+ '';
+ selectQuery = pkgs.writeText "select.sql" "SELECT sum(age) from `test_topic`";
+ in
+ ''
+ kafka.start()
+ kafka.wait_for_unit("apache-kafka")
+ kafka.wait_for_open_port(9092)
+
+ clickhouse.start()
+ clickhouse.wait_for_unit("clickhouse")
+ clickhouse.wait_for_open_port(9000)
+
+ clickhouse.wait_until_succeeds(
+ """
+ journalctl -o cat -u clickhouse.service | grep "Merging configuration file '/etc/clickhouse-server/config.d/kafka.xml'"
+ """
+ )
+
+ clickhouse.succeed(
+ "cat ${tableKafkaDDL} | clickhouse-client"
+ )
+
+ clickhouse.succeed(
+ "cat ${tableDDL} | clickhouse-client"
+ )
+
+ clickhouse.succeed(
+ "cat ${viewDDL} | clickhouse-client"
+ )
+
+ kafka.succeed(
+ "jq -rc . ${jsonTestMessage} | kafka-console-producer.sh --topic test_topic --bootstrap-server kafka:9092"
+ )
+
+ kafka.wait_until_succeeds(
+ "journalctl -o cat -u apache-kafka.service | grep 'Created a new member id ClickHouse-clickhouse-default-test_kafka_topic'"
+ )
+
+ clickhouse.wait_until_succeeds(
+ "cat ${selectQuery} | clickhouse-client | grep 74"
+ )
+ '';
+}
diff --git a/nixos/tests/clickhouse/keeper.nix b/nixos/tests/clickhouse/keeper.nix
new file mode 100644
index 000000000000..40be4c19f2cf
--- /dev/null
+++ b/nixos/tests/clickhouse/keeper.nix
@@ -0,0 +1,183 @@
+{ lib, pkgs, ... }:
+rec {
+ name = "clickhouse-keeper";
+ meta.maintainers = with pkgs.lib.maintainers; [ jpds ];
+
+ nodes =
+ let
+ node = i: {
+
+ environment.etc = {
+ "clickhouse-server/config.d/cluster.xml".text = ''
+
+
+
+ ${lib.concatStrings (
+ lib.imap0 (j: name: ''
+
+
+ ${name}
+ 9000
+
+
+ '') (builtins.attrNames nodes)
+ )}
+
+
+
+ '';
+
+ "clickhouse-server/config.d/keeper.xml".text = ''
+
+
+ ${toString i}
+ 9181
+ /var/lib/clickhouse/coordination/log
+ /var/lib/clickhouse/coordination/snapshots
+
+
+ 10000
+ 30000
+ trace
+ 10000
+
+
+
+ ${lib.concatStrings (
+ lib.imap1 (j: name: ''
+
+ ${toString j}
+ ${name}
+ 9444
+
+ '') (builtins.attrNames nodes)
+ )}
+
+
+
+
+ ${lib.concatStrings (
+ lib.imap0 (j: name: ''
+
+ ${name}
+ 9181
+
+ '') (builtins.attrNames nodes)
+ )}
+
+
+
+ /clickhouse/testcluster/task_queue/ddl
+
+
+ '';
+
+ "clickhouse-server/config.d/listen.xml".text = ''
+
+ ::
+
+ '';
+
+ "clickhouse-server/config.d/macros.xml".text = ''
+
+
+ ${toString i}
+ perftest_2shards_1replicas
+
+
+ '';
+ };
+
+ networking.firewall.allowedTCPPorts = [
+ 9009
+ 9181
+ 9444
+ ];
+
+ services.clickhouse.enable = true;
+
+ systemd.services.clickhouse = {
+ after = [ "network-online.target" ];
+ requires = [ "network-online.target" ];
+ };
+
+ virtualisation.memorySize = 1024 * 4;
+ virtualisation.diskSize = 1024 * 10;
+ };
+ in
+ {
+ clickhouse1 = node 1;
+ clickhouse2 = node 2;
+ };
+
+ testScript =
+ let
+ # work around quote/substitution complexity by Nix, Perl, bash and SQL.
+ clustersQuery = pkgs.writeText "clusters.sql" "SHOW clusters";
+ keeperQuery = pkgs.writeText "keeper.sql" "SELECT * FROM system.zookeeper WHERE path IN ('/', '/clickhouse') FORMAT VERTICAL";
+ systemClustersQuery = pkgs.writeText "system-clusters.sql" "SELECT host_name, host_address, replica_num FROM system.clusters WHERE cluster = 'perftest_2shards_1replicas'";
+
+ tableDDL = pkgs.writeText "table.sql" ''
+ CREATE TABLE test ON cluster 'perftest_2shards_1replicas' ( A Int64, S String)
+ Engine = ReplicatedMergeTree('/clickhouse/{cluster}/tables/{database}/{table}', '{replica}')
+ ORDER BY A;
+ '';
+
+ insertDDL = pkgs.writeText "insert.sql" "
+ INSERT INTO test SELECT number, '' FROM numbers(100000000);
+ ";
+
+ selectCountQuery = pkgs.writeText "select-count.sql" "
+ select count() from test;
+ ";
+ in
+ ''
+ clickhouse1.start()
+ clickhouse2.start()
+
+ for machine in clickhouse1, clickhouse2:
+ machine.wait_for_unit("clickhouse.service")
+ machine.wait_for_open_port(9000)
+ machine.wait_for_open_port(9009)
+ machine.wait_for_open_port(9181)
+ machine.wait_for_open_port(9444)
+
+ machine.wait_until_succeeds(
+ """
+ journalctl -o cat -u clickhouse.service | grep "Merging configuration file '/etc/clickhouse-server/config.d/keeper.xml'"
+ """
+ )
+
+ machine.log(machine.succeed(
+ "cat ${clustersQuery} | clickhouse-client | grep perftest_2shards_1replicas"
+ ))
+
+ machine.log(machine.succeed(
+ "cat ${keeperQuery} | clickhouse-client"
+ ))
+
+ machine.succeed(
+ "cat ${systemClustersQuery} | clickhouse-client | grep clickhouse1"
+ )
+ machine.succeed(
+ "cat ${systemClustersQuery} | clickhouse-client | grep clickhouse2"
+ )
+
+ machine.succeed(
+ "ls /var/lib/clickhouse/coordination/log | grep changelog"
+ )
+
+ clickhouse2.succeed(
+ "cat ${tableDDL} | clickhouse-client"
+ )
+
+ clickhouse2.succeed(
+ "cat ${insertDDL} | clickhouse-client"
+ )
+
+ for machine in clickhouse1, clickhouse2:
+ machine.wait_until_succeeds(
+ "cat ${selectCountQuery} | clickhouse-client | grep 100000000"
+ )
+ '';
+}
diff --git a/nixos/tests/clickhouse/s3.nix b/nixos/tests/clickhouse/s3.nix
new file mode 100644
index 000000000000..2268b6128fe6
--- /dev/null
+++ b/nixos/tests/clickhouse/s3.nix
@@ -0,0 +1,121 @@
+{ pkgs, ... }:
+
+let
+ s3 = {
+ bucket = "clickhouse-bucket";
+ accessKey = "BKIKJAA5BMMU2RHO6IBB";
+ secretKey = "V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12";
+ };
+
+ clickhouseS3StorageConfig = ''
+
+
+
+
+ s3
+ http://minio:9000/${s3.bucket}/
+ ${s3.accessKey}
+ ${s3.secretKey}
+ /var/lib/clickhouse/disks/s3_disk/
+
+
+ cache
+ s3_disk
+ /var/lib/clickhouse/disks/s3_cache/
+ 10Gi
+
+
+
+
+
+
+ s3_disk
+
+
+
+
+
+
+ '';
+in
+{
+ name = "clickhouse-s3";
+ meta.maintainers = with pkgs.lib.maintainers; [ jpds ];
+
+ nodes = {
+ clickhouse = {
+ environment.etc = {
+ "clickhouse-server/config.d/s3.xml" = {
+ text = "${clickhouseS3StorageConfig}";
+ };
+ };
+
+ services.clickhouse.enable = true;
+ virtualisation.diskSize = 15 * 1024;
+ virtualisation.memorySize = 4 * 1024;
+ };
+
+ minio =
+ { pkgs, ... }:
+ {
+ virtualisation.diskSize = 2 * 1024;
+ networking.firewall.allowedTCPPorts = [ 9000 ];
+
+ services.minio = {
+ enable = true;
+ inherit (s3) accessKey secretKey;
+ };
+
+ environment.systemPackages = [ pkgs.minio-client ];
+ };
+ };
+
+ testScript =
+ let
+ # work around quote/substitution complexity by Nix, Perl, bash and SQL.
+ tableDDL = pkgs.writeText "ddl.sql" ''
+ CREATE TABLE `demo` (
+ `value` String
+ )
+ ENGINE = MergeTree
+ ORDER BY value
+ SETTINGS storage_policy = 's3_main';
+ '';
+ insertQuery = pkgs.writeText "insert.sql" "INSERT INTO `demo` (`value`) VALUES ('foo');";
+ selectQuery = pkgs.writeText "select.sql" "SELECT * from `demo`";
+ in
+ ''
+ minio.wait_for_unit("minio")
+ minio.wait_for_open_port(9000)
+ minio.succeed(
+ "mc alias set minio "
+ + "http://localhost:9000 "
+ + "${s3.accessKey} ${s3.secretKey} --api s3v4",
+ "mc mb minio/${s3.bucket}",
+ )
+
+ clickhouse.start()
+ clickhouse.wait_for_unit("clickhouse.service")
+ clickhouse.wait_for_open_port(9000)
+
+ clickhouse.wait_until_succeeds(
+ """
+ journalctl -o cat -u clickhouse.service | grep "Merging configuration file '/etc/clickhouse-server/config.d/s3.xml'"
+ """
+ )
+
+ clickhouse.succeed(
+ "cat ${tableDDL} | clickhouse-client"
+ )
+ clickhouse.succeed(
+ "cat ${insertQuery} | clickhouse-client"
+ )
+ clickhouse.succeed(
+ "cat ${selectQuery} | clickhouse-client | grep foo"
+ )
+
+ minio.log(minio.succeed(
+ "mc ls minio/${s3.bucket}",
+ ))
+ '';
+}