aboutsummaryrefslogtreecommitdiff
path: root/test/docker/db
diff options
context:
space:
mode:
authorMickael Remond <mremond@process-one.net>2019-05-07 17:59:05 +0200
committerMickael Remond <mremond@process-one.net>2019-05-07 17:59:05 +0200
commite427358e089864955d033305ab1bc0c6baff3c24 (patch)
tree43242b5f15c34b28df4ca17b72dcbc1afd6536fe /test/docker/db
parentFix pubsub compliance XEP-0060 ยง 7.1.3.6 (#2864) (diff)
Initial Docker environment to run ejabberd test suite
Diffstat (limited to 'test/docker/db')
-rw-r--r--test/docker/db/mysql/initdb/mysql.sql465
-rw-r--r--test/docker/db/postgres/initdb/pg.sql470
-rw-r--r--test/docker/db/riak/Dockerfile53
-rw-r--r--test/docker/db/riak/advanced.config27
-rw-r--r--test/docker/db/riak/ejabberd_riak.beambin0 -> 11204 bytes
-rwxr-xr-xtest/docker/db/riak/prestart.d/00-setup-networking.sh9
-rw-r--r--test/docker/db/riak/riak-cluster.sh56
-rw-r--r--test/docker/db/riak/riak.conf682
8 files changed, 1762 insertions, 0 deletions
diff --git a/test/docker/db/mysql/initdb/mysql.sql b/test/docker/db/mysql/initdb/mysql.sql
new file mode 100644
index 000000000..a05f8c86c
--- /dev/null
+++ b/test/docker/db/mysql/initdb/mysql.sql
@@ -0,0 +1,465 @@
+--
+-- ejabberd, Copyright (C) 2002-2019 ProcessOne
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License as
+-- published by the Free Software Foundation; either version 2 of the
+-- License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License along
+-- with this program; if not, write to the Free Software Foundation, Inc.,
+-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+--
+
+CREATE TABLE users (
+ username varchar(191) PRIMARY KEY,
+ password text NOT NULL,
+ serverkey varchar(64) NOT NULL DEFAULT '',
+ salt varchar(64) NOT NULL DEFAULT '',
+ iterationcount integer NOT NULL DEFAULT 0,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+-- Add support for SCRAM auth to a database created before ejabberd 16.03:
+-- ALTER TABLE users ADD COLUMN serverkey varchar(64) NOT NULL DEFAULT '';
+-- ALTER TABLE users ADD COLUMN salt varchar(64) NOT NULL DEFAULT '';
+-- ALTER TABLE users ADD COLUMN iterationcount integer NOT NULL DEFAULT 0;
+
+CREATE TABLE last (
+ username varchar(191) PRIMARY KEY,
+ seconds text NOT NULL,
+ state text NOT NULl
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+
+CREATE TABLE rosterusers (
+ username varchar(191) NOT NULL,
+ jid varchar(191) NOT NULL,
+ nick text NOT NULL,
+ subscription character(1) NOT NULL,
+ ask character(1) NOT NULL,
+ askmessage text NOT NULL,
+ server character(1) NOT NULL,
+ subscribe text NOT NULL,
+ type text,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers(username(75), jid(75));
+CREATE INDEX i_rosteru_username ON rosterusers(username);
+CREATE INDEX i_rosteru_jid ON rosterusers(jid);
+
+CREATE TABLE rostergroups (
+ username varchar(191) NOT NULL,
+ jid varchar(191) NOT NULL,
+ grp text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX pk_rosterg_user_jid ON rostergroups(username(75), jid(75));
+
+CREATE TABLE sr_group (
+ name varchar(191) NOT NULL,
+ opts text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE TABLE sr_user (
+ jid varchar(191) NOT NULL,
+ grp varchar(191) NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_sr_user_jid_group ON sr_user(jid(75), grp(75));
+CREATE INDEX i_sr_user_jid ON sr_user(jid);
+CREATE INDEX i_sr_user_grp ON sr_user(grp);
+
+CREATE TABLE spool (
+ username varchar(191) NOT NULL,
+ xml mediumtext NOT NULL,
+ seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_despool USING BTREE ON spool(username);
+CREATE INDEX i_spool_created_at USING BTREE ON spool(created_at);
+
+CREATE TABLE archive (
+ username varchar(191) NOT NULL,
+ timestamp BIGINT UNSIGNED NOT NULL,
+ peer varchar(191) NOT NULL,
+ bare_peer varchar(191) NOT NULL,
+ xml mediumtext NOT NULL,
+ txt mediumtext,
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
+ kind varchar(10),
+ nick varchar(191),
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE FULLTEXT INDEX i_text ON archive(txt);
+CREATE INDEX i_username_timestamp USING BTREE ON archive(username(191), timestamp);
+CREATE INDEX i_username_peer USING BTREE ON archive(username(191), peer(191));
+CREATE INDEX i_username_bare_peer USING BTREE ON archive(username(191), bare_peer(191));
+CREATE INDEX i_timestamp USING BTREE ON archive(timestamp);
+
+CREATE TABLE archive_prefs (
+ username varchar(191) NOT NULL PRIMARY KEY,
+ def text NOT NULL,
+ always text NOT NULL,
+ never text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE TABLE vcard (
+ username varchar(191) PRIMARY KEY,
+ vcard mediumtext NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE TABLE vcard_search (
+ username varchar(191) NOT NULL,
+ lusername varchar(191) PRIMARY KEY,
+ fn text NOT NULL,
+ lfn varchar(191) NOT NULL,
+ family text NOT NULL,
+ lfamily varchar(191) NOT NULL,
+ given text NOT NULL,
+ lgiven varchar(191) NOT NULL,
+ middle text NOT NULL,
+ lmiddle varchar(191) NOT NULL,
+ nickname text NOT NULL,
+ lnickname varchar(191) NOT NULL,
+ bday text NOT NULL,
+ lbday varchar(191) NOT NULL,
+ ctry text NOT NULL,
+ lctry varchar(191) NOT NULL,
+ locality text NOT NULL,
+ llocality varchar(191) NOT NULL,
+ email text NOT NULL,
+ lemail varchar(191) NOT NULL,
+ orgname text NOT NULL,
+ lorgname varchar(191) NOT NULL,
+ orgunit text NOT NULL,
+ lorgunit varchar(191) NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
+CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily);
+CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven);
+CREATE INDEX i_vcard_search_lmiddle ON vcard_search(lmiddle);
+CREATE INDEX i_vcard_search_lnickname ON vcard_search(lnickname);
+CREATE INDEX i_vcard_search_lbday ON vcard_search(lbday);
+CREATE INDEX i_vcard_search_lctry ON vcard_search(lctry);
+CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality);
+CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
+CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
+CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
+
+CREATE TABLE privacy_default_list (
+ username varchar(191) PRIMARY KEY,
+ name varchar(191) NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE TABLE privacy_list (
+ username varchar(191) NOT NULL,
+ name varchar(191) NOT NULL,
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_privacy_list_username USING BTREE ON privacy_list(username);
+CREATE UNIQUE INDEX i_privacy_list_username_name USING BTREE ON privacy_list (username(75), name(75));
+
+CREATE TABLE privacy_list_data (
+ id bigint,
+ t character(1) NOT NULL,
+ value text NOT NULL,
+ action character(1) NOT NULL,
+ ord NUMERIC NOT NULL,
+ match_all boolean NOT NULL,
+ match_iq boolean NOT NULL,
+ match_message boolean NOT NULL,
+ match_presence_in boolean NOT NULL,
+ match_presence_out boolean NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_privacy_list_data_id ON privacy_list_data(id);
+
+CREATE TABLE private_storage (
+ username varchar(191) NOT NULL,
+ namespace varchar(191) NOT NULL,
+ data text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_private_storage_username USING BTREE ON private_storage(username);
+CREATE UNIQUE INDEX i_private_storage_username_namespace USING BTREE ON private_storage(username(75), namespace(75));
+
+-- Not tested in mysql
+CREATE TABLE roster_version (
+ username varchar(191) PRIMARY KEY,
+ version text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+-- To update from 1.x:
+-- ALTER TABLE rosterusers ADD COLUMN askmessage text AFTER ask;
+-- UPDATE rosterusers SET askmessage = '';
+-- ALTER TABLE rosterusers ALTER COLUMN askmessage SET NOT NULL;
+
+CREATE TABLE pubsub_node (
+ host text NOT NULL,
+ node text NOT NULL,
+ parent VARCHAR(191) NOT NULL DEFAULT '',
+ plugin text NOT NULL,
+ nodeid bigint auto_increment primary key
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE INDEX i_pubsub_node_parent ON pubsub_node(parent(120));
+CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node(host(71), node(120));
+
+CREATE TABLE pubsub_node_option (
+ nodeid bigint,
+ name text NOT NULL,
+ val text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option(nodeid);
+ALTER TABLE `pubsub_node_option` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
+
+CREATE TABLE pubsub_node_owner (
+ nodeid bigint,
+ owner text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner(nodeid);
+ALTER TABLE `pubsub_node_owner` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
+
+CREATE TABLE pubsub_state (
+ nodeid bigint,
+ jid text NOT NULL,
+ affiliation character(1),
+ subscriptions VARCHAR(191) NOT NULL DEFAULT '',
+ stateid bigint auto_increment primary key
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE INDEX i_pubsub_state_jid ON pubsub_state(jid(60));
+CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state(nodeid, jid(60));
+ALTER TABLE `pubsub_state` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
+
+CREATE TABLE pubsub_item (
+ nodeid bigint,
+ itemid text NOT NULL,
+ publisher text NOT NULL,
+ creation varchar(32) NOT NULL,
+ modification varchar(32) NOT NULL,
+ payload mediumtext NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE INDEX i_pubsub_item_itemid ON pubsub_item(itemid(36));
+CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item(nodeid, itemid(36));
+ALTER TABLE `pubsub_item` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
+
+CREATE TABLE pubsub_subscription_opt (
+ subid text NOT NULL,
+ opt_name varchar(32),
+ opt_value text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt(subid(32), opt_name(32));
+
+CREATE TABLE muc_room (
+ name text NOT NULL,
+ host text NOT NULL,
+ opts mediumtext NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_muc_room_name_host USING BTREE ON muc_room(name(75), host(75));
+
+CREATE TABLE muc_registered (
+ jid text NOT NULL,
+ host text NOT NULL,
+ nick text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_muc_registered_nick USING BTREE ON muc_registered(nick(75));
+CREATE UNIQUE INDEX i_muc_registered_jid_host USING BTREE ON muc_registered(jid(75), host(75));
+
+CREATE TABLE muc_online_room (
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_muc_online_room_name_host USING BTREE ON muc_online_room(name(75), host(75));
+
+CREATE TABLE muc_online_users (
+ username text NOT NULL,
+ server text NOT NULL,
+ resource text NOT NULL,
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_muc_online_users USING BTREE ON muc_online_users(username(75), server(75), resource(75), name(75), host(75));
+CREATE INDEX i_muc_online_users_us USING BTREE ON muc_online_users(username(75), server(75));
+
+CREATE TABLE muc_room_subscribers (
+ room varchar(191) NOT NULL,
+ host varchar(191) NOT NULL,
+ jid varchar(191) NOT NULL,
+ nick text NOT NULL,
+ nodes text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE KEY i_muc_room_subscribers_host_room_jid (host, room, jid)
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_muc_room_subscribers_host_jid USING BTREE ON muc_room_subscribers(host, jid);
+
+CREATE TABLE motd (
+ username varchar(191) PRIMARY KEY,
+ xml text,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE TABLE caps_features (
+ node varchar(191) NOT NULL,
+ subnode varchar(191) NOT NULL,
+ feature text,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE INDEX i_caps_features_node_subnode ON caps_features(node(75), subnode(75));
+
+CREATE TABLE sm (
+ usec bigint NOT NULL,
+ pid text NOT NULL,
+ node text NOT NULL,
+ username varchar(191) NOT NULL,
+ resource varchar(191) NOT NULL,
+ priority text NOT NULL,
+ info text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_sid ON sm(usec, pid(75));
+CREATE INDEX i_node ON sm(node(75));
+CREATE INDEX i_username ON sm(username);
+
+CREATE TABLE oauth_token (
+ token varchar(191) NOT NULL PRIMARY KEY,
+ jid text NOT NULL,
+ scope text NOT NULL,
+ expire bigint NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE TABLE route (
+ domain text NOT NULL,
+ server_host text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL,
+ local_hint text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_route ON route(domain(75), server_host(75), node(75), pid(75));
+CREATE INDEX i_route_domain ON route(domain(75));
+
+CREATE TABLE bosh (
+ sid text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_bosh_sid ON bosh(sid(75));
+
+CREATE TABLE proxy65 (
+ sid text NOT NULL,
+ pid_t text NOT NULL,
+ pid_i text NOT NULL,
+ node_t text NOT NULL,
+ node_i text NOT NULL,
+ jid_i text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_proxy65_sid ON proxy65 (sid(191));
+CREATE INDEX i_proxy65_jid ON proxy65 (jid_i(191));
+
+CREATE TABLE push_session (
+ username text NOT NULL,
+ timestamp bigint NOT NULL,
+ service text NOT NULL,
+ node text NOT NULL,
+ xml text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_push_usn ON push_session (username(191), service(191), node(191));
+CREATE UNIQUE INDEX i_push_ut ON push_session (username(191), timestamp);
+
+CREATE TABLE mix_channel (
+ channel text NOT NULL,
+ service text NOT NULL,
+ username text NOT NULL,
+ domain text NOT NULL,
+ jid text NOT NULL,
+ hidden boolean NOT NULL,
+ hmac_key text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_mix_channel ON mix_channel (channel(191), service(191));
+CREATE INDEX i_mix_channel_serv ON mix_channel (service(191));
+
+CREATE TABLE mix_participant (
+ channel text NOT NULL,
+ service text NOT NULL,
+ username text NOT NULL,
+ domain text NOT NULL,
+ jid text NOT NULL,
+ id text NOT NULL,
+ nick text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_mix_participant ON mix_participant (channel(191), service(191), username(191), domain(191));
+CREATE INDEX i_mix_participant_chan_serv ON mix_participant (channel(191), service(191));
+
+CREATE TABLE mix_subscription (
+ channel text NOT NULL,
+ service text NOT NULL,
+ username text NOT NULL,
+ domain text NOT NULL,
+ node text NOT NULL,
+ jid text NOT NULL
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_mix_subscription ON mix_subscription (channel(153), service(153), username(153), domain(153), node(153));
+CREATE INDEX i_mix_subscription_chan_serv_ud ON mix_subscription (channel(191), service(191), username(191), domain(191));
+CREATE INDEX i_mix_subscription_chan_serv_node ON mix_subscription (channel(191), service(191), node(191));
+CREATE INDEX i_mix_subscription_chan_serv ON mix_subscription (channel(191), service(191));
+
+CREATE TABLE mix_pam (
+ username text NOT NULL,
+ channel text NOT NULL,
+ service text NOT NULL,
+ id text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+CREATE UNIQUE INDEX i_mix_pam ON mix_pam (username(191), channel(191), service(191));
+CREATE INDEX i_mix_pam_u ON mix_pam (username(191));
+
+CREATE TABLE mqtt_pub (
+ username varchar(191) NOT NULL,
+ resource varchar(191) NOT NULL,
+ topic text NOT NULL,
+ qos tinyint NOT NULL,
+ payload blob NOT NULL,
+ payload_format tinyint NOT NULL,
+ content_type text NOT NULL,
+ response_topic text NOT NULL,
+ correlation_data blob NOT NULL,
+ user_properties blob NOT NULL,
+ expiry int unsigned NOT NULL,
+ UNIQUE KEY i_mqtt_topic (topic(191))
+);
diff --git a/test/docker/db/postgres/initdb/pg.sql b/test/docker/db/postgres/initdb/pg.sql
new file mode 100644
index 000000000..eae98d3f0
--- /dev/null
+++ b/test/docker/db/postgres/initdb/pg.sql
@@ -0,0 +1,470 @@
+--
+-- ejabberd, Copyright (C) 2002-2019 ProcessOne
+--
+-- This program is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU General Public License as
+-- published by the Free Software Foundation; either version 2 of the
+-- License, or (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License along
+-- with this program; if not, write to the Free Software Foundation, Inc.,
+-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+--
+
+CREATE TABLE users (
+ username text PRIMARY KEY,
+ "password" text NOT NULL,
+ serverkey text NOT NULL DEFAULT '',
+ salt text NOT NULL DEFAULT '',
+ iterationcount integer NOT NULL DEFAULT 0,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+-- Add support for SCRAM auth to a database created before ejabberd 16.03:
+-- ALTER TABLE users ADD COLUMN serverkey text NOT NULL DEFAULT '';
+-- ALTER TABLE users ADD COLUMN salt text NOT NULL DEFAULT '';
+-- ALTER TABLE users ADD COLUMN iterationcount integer NOT NULL DEFAULT 0;
+
+CREATE TABLE last (
+ username text PRIMARY KEY,
+ seconds text NOT NULL,
+ state text NOT NULL
+);
+
+
+CREATE TABLE rosterusers (
+ username text NOT NULL,
+ jid text NOT NULL,
+ nick text NOT NULL,
+ subscription character(1) NOT NULL,
+ ask character(1) NOT NULL,
+ askmessage text NOT NULL,
+ server character(1) NOT NULL,
+ subscribe text NOT NULL,
+ "type" text,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers USING btree (username, jid);
+CREATE INDEX i_rosteru_username ON rosterusers USING btree (username);
+CREATE INDEX i_rosteru_jid ON rosterusers USING btree (jid);
+
+
+CREATE TABLE rostergroups (
+ username text NOT NULL,
+ jid text NOT NULL,
+ grp text NOT NULL
+);
+
+CREATE INDEX pk_rosterg_user_jid ON rostergroups USING btree (username, jid);
+
+CREATE TABLE sr_group (
+ name text NOT NULL,
+ opts text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE TABLE sr_user (
+ jid text NOT NULL,
+ grp text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE UNIQUE INDEX i_sr_user_jid_grp ON sr_user USING btree (jid, grp);
+CREATE INDEX i_sr_user_jid ON sr_user USING btree (jid);
+CREATE INDEX i_sr_user_grp ON sr_user USING btree (grp);
+
+CREATE TABLE spool (
+ username text NOT NULL,
+ xml text NOT NULL,
+ seq SERIAL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_despool ON spool USING btree (username);
+
+CREATE TABLE archive (
+ username text NOT NULL,
+ timestamp BIGINT NOT NULL,
+ peer text NOT NULL,
+ bare_peer text NOT NULL,
+ xml text NOT NULL,
+ txt text,
+ id SERIAL,
+ kind text,
+ nick text,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_username_timestamp ON archive USING btree (username, timestamp);
+CREATE INDEX i_username_peer ON archive USING btree (username, peer);
+CREATE INDEX i_username_bare_peer ON archive USING btree (username, bare_peer);
+CREATE INDEX i_timestamp ON archive USING btree (timestamp);
+
+CREATE TABLE archive_prefs (
+ username text NOT NULL PRIMARY KEY,
+ def text NOT NULL,
+ always text NOT NULL,
+ never text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE TABLE vcard (
+ username text PRIMARY KEY,
+ vcard text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE TABLE vcard_search (
+ username text NOT NULL,
+ lusername text PRIMARY KEY,
+ fn text NOT NULL,
+ lfn text NOT NULL,
+ family text NOT NULL,
+ lfamily text NOT NULL,
+ given text NOT NULL,
+ lgiven text NOT NULL,
+ middle text NOT NULL,
+ lmiddle text NOT NULL,
+ nickname text NOT NULL,
+ lnickname text NOT NULL,
+ bday text NOT NULL,
+ lbday text NOT NULL,
+ ctry text NOT NULL,
+ lctry text NOT NULL,
+ locality text NOT NULL,
+ llocality text NOT NULL,
+ email text NOT NULL,
+ lemail text NOT NULL,
+ orgname text NOT NULL,
+ lorgname text NOT NULL,
+ orgunit text NOT NULL,
+ lorgunit text NOT NULL
+);
+
+CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
+CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily);
+CREATE INDEX i_vcard_search_lgiven ON vcard_search(lgiven);
+CREATE INDEX i_vcard_search_lmiddle ON vcard_search(lmiddle);
+CREATE INDEX i_vcard_search_lnickname ON vcard_search(lnickname);
+CREATE INDEX i_vcard_search_lbday ON vcard_search(lbday);
+CREATE INDEX i_vcard_search_lctry ON vcard_search(lctry);
+CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality);
+CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
+CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
+CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
+
+CREATE TABLE privacy_default_list (
+ username text PRIMARY KEY,
+ name text NOT NULL
+);
+
+CREATE TABLE privacy_list (
+ username text NOT NULL,
+ name text NOT NULL,
+ id SERIAL UNIQUE,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_privacy_list_username ON privacy_list USING btree (username);
+CREATE UNIQUE INDEX i_privacy_list_username_name ON privacy_list USING btree (username, name);
+
+CREATE TABLE privacy_list_data (
+ id bigint REFERENCES privacy_list(id) ON DELETE CASCADE,
+ t character(1) NOT NULL,
+ value text NOT NULL,
+ action character(1) NOT NULL,
+ ord NUMERIC NOT NULL,
+ match_all boolean NOT NULL,
+ match_iq boolean NOT NULL,
+ match_message boolean NOT NULL,
+ match_presence_in boolean NOT NULL,
+ match_presence_out boolean NOT NULL
+);
+
+CREATE INDEX i_privacy_list_data_id ON privacy_list_data USING btree (id);
+
+CREATE TABLE private_storage (
+ username text NOT NULL,
+ namespace text NOT NULL,
+ data text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_private_storage_username ON private_storage USING btree (username);
+CREATE UNIQUE INDEX i_private_storage_username_namespace ON private_storage USING btree (username, namespace);
+
+
+CREATE TABLE roster_version (
+ username text PRIMARY KEY,
+ version text NOT NULL
+);
+
+-- To update from 0.9.8:
+-- CREATE SEQUENCE spool_seq_seq;
+-- ALTER TABLE spool ADD COLUMN seq integer;
+-- ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
+-- UPDATE spool SET seq = DEFAULT;
+-- ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
+
+-- To update from 1.x:
+-- ALTER TABLE rosterusers ADD COLUMN askmessage text;
+-- UPDATE rosterusers SET askmessage = '';
+-- ALTER TABLE rosterusers ALTER COLUMN askmessage SET NOT NULL;
+
+CREATE TABLE pubsub_node (
+ host text NOT NULL,
+ node text NOT NULL,
+ parent text NOT NULL DEFAULT '',
+ plugin text NOT NULL,
+ nodeid SERIAL UNIQUE
+);
+CREATE INDEX i_pubsub_node_parent ON pubsub_node USING btree (parent);
+CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node USING btree (host, node);
+
+CREATE TABLE pubsub_node_option (
+ nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+ name text NOT NULL,
+ val text NOT NULL
+);
+CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option USING btree (nodeid);
+
+CREATE TABLE pubsub_node_owner (
+ nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+ owner text NOT NULL
+);
+CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner USING btree (nodeid);
+
+CREATE TABLE pubsub_state (
+ nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+ jid text NOT NULL,
+ affiliation character(1),
+ subscriptions text NOT NULL DEFAULT '',
+ stateid SERIAL UNIQUE
+);
+CREATE INDEX i_pubsub_state_jid ON pubsub_state USING btree (jid);
+CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state USING btree (nodeid, jid);
+
+CREATE TABLE pubsub_item (
+ nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
+ itemid text NOT NULL,
+ publisher text NOT NULL,
+ creation varchar(32) NOT NULL,
+ modification varchar(32) NOT NULL,
+ payload text NOT NULL DEFAULT ''
+);
+CREATE INDEX i_pubsub_item_itemid ON pubsub_item USING btree (itemid);
+CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item USING btree (nodeid, itemid);
+
+CREATE TABLE pubsub_subscription_opt (
+ subid text NOT NULL,
+ opt_name varchar(32),
+ opt_value text NOT NULL
+);
+CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt USING btree (subid, opt_name);
+
+CREATE TABLE muc_room (
+ name text NOT NULL,
+ host text NOT NULL,
+ opts text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE UNIQUE INDEX i_muc_room_name_host ON muc_room USING btree (name, host);
+
+CREATE TABLE muc_registered (
+ jid text NOT NULL,
+ host text NOT NULL,
+ nick text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_muc_registered_nick ON muc_registered USING btree (nick);
+CREATE UNIQUE INDEX i_muc_registered_jid_host ON muc_registered USING btree (jid, host);
+
+CREATE TABLE muc_online_room (
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_room_name_host ON muc_online_room USING btree (name, host);
+
+CREATE TABLE muc_online_users (
+ username text NOT NULL,
+ server text NOT NULL,
+ resource text NOT NULL,
+ name text NOT NULL,
+ host text NOT NULL,
+ node text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_muc_online_users ON muc_online_users USING btree (username, server, resource, name, host);
+CREATE INDEX i_muc_online_users_us ON muc_online_users USING btree (username, server);
+
+CREATE TABLE muc_room_subscribers (
+ room text NOT NULL,
+ host text NOT NULL,
+ jid text NOT NULL,
+ nick text NOT NULL,
+ nodes text NOT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_muc_room_subscribers_host_jid ON muc_room_subscribers USING btree (host, jid);
+CREATE UNIQUE INDEX i_muc_room_subscribers_host_room_jid ON muc_room_subscribers USING btree (host, room, jid);
+
+CREATE TABLE motd (
+ username text PRIMARY KEY,
+ xml text,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE TABLE caps_features (
+ node text NOT NULL,
+ subnode text NOT NULL,
+ feature text,
+ created_at TIMESTAMP NOT NULL DEFAULT now()
+);
+
+CREATE INDEX i_caps_features_node_subnode ON caps_features USING btree (node, subnode);
+
+CREATE TABLE sm (
+ usec bigint NOT NULL,
+ pid text NOT NULL,
+ node text NOT NULL,
+ username text NOT NULL,
+ resource text NOT NULL,
+ priority text NOT NULL,
+ info text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_sm_sid ON sm USING btree (usec, pid);
+CREATE INDEX i_sm_node ON sm USING btree (node);
+CREATE INDEX i_sm_username ON sm USING btree (username);
+
+CREATE TABLE oauth_token (
+ token text NOT NULL,
+ jid text NOT NULL,
+ scope text NOT NULL,
+ expire bigint NOT NULL
+);
+
+CREATE UNIQUE INDEX i_oauth_token_token ON oauth_token USING btree (token);
+
+CREATE TABLE route (
+ domain text NOT NULL,
+ server_host text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL,
+ local_hint text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_route ON route USING btree (domain, server_host, node, pid);
+CREATE INDEX i_route_domain ON route USING btree (domain);
+
+CREATE TABLE bosh (
+ sid text NOT NULL,
+ node text NOT NULL,
+ pid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_bosh_sid ON bosh USING btree (sid);
+
+CREATE TABLE proxy65 (
+ sid text NOT NULL,
+ pid_t text NOT NULL,
+ pid_i text NOT NULL,
+ node_t text NOT NULL,
+ node_i text NOT NULL,
+ jid_i text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_proxy65_sid ON proxy65 USING btree (sid);
+CREATE INDEX i_proxy65_jid ON proxy65 USING btree (jid_i);
+
+CREATE TABLE push_session (
+ username text NOT NULL,
+ timestamp bigint NOT NULL,
+ service text NOT NULL,
+ node text NOT NULL,
+ xml text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_push_usn ON push_session USING btree (username, service, node);
+CREATE UNIQUE INDEX i_push_ut ON push_session USING btree (username, timestamp);
+
+CREATE TABLE mix_channel (
+ channel text NOT NULL,
+ service text NOT NULL,
+ username text NOT NULL,
+ domain text NOT NULL,
+ jid text NOT NULL,
+ hidden boolean NOT NULL,
+ hmac_key text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE UNIQUE INDEX i_mix_channel ON mix_channel (channel, service);
+CREATE INDEX i_mix_channel_serv ON mix_channel (service);
+
+CREATE TABLE mix_participant (
+ channel text NOT NULL,
+ service text NOT NULL,
+ username text NOT NULL,
+ domain text NOT NULL,
+ jid text NOT NULL,
+ id text NOT NULL,
+ nick text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE UNIQUE INDEX i_mix_participant ON mix_participant (channel, service, username, domain);
+CREATE INDEX i_mix_participant_chan_serv ON mix_participant (channel, service);
+
+CREATE TABLE mix_subscription (
+ channel text NOT NULL,
+ service text NOT NULL,
+ username text NOT NULL,
+ domain text NOT NULL,
+ node text NOT NULL,
+ jid text NOT NULL
+);
+
+CREATE UNIQUE INDEX i_mix_subscription ON mix_subscription (channel, service, username, domain, node);
+CREATE INDEX i_mix_subscription_chan_serv_ud ON mix_subscription (channel, service, username, domain);
+CREATE INDEX i_mix_subscription_chan_serv_node ON mix_subscription (channel, service, node);
+CREATE INDEX i_mix_subscription_chan_serv ON mix_subscription (channel, service);
+
+CREATE TABLE mix_pam (
+ username text NOT NULL,
+ channel text NOT NULL,
+ service text NOT NULL,
+ id text NOT NULL,
+ created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE UNIQUE INDEX i_mix_pam ON mix_pam (username, channel, service);
+CREATE INDEX i_mix_pam_us ON mix_pam (username);
+
+CREATE TABLE mqtt_pub (
+ username text NOT NULL,
+ resource text NOT NULL,
+ topic text NOT NULL,
+ qos smallint NOT NULL,
+ payload bytea NOT NULL,
+ payload_format smallint NOT NULL,
+ content_type text NOT NULL,
+ response_topic text NOT NULL,
+ correlation_data bytea NOT NULL,
+ user_properties bytea NOT NULL,
+ expiry bigint NOT NULL
+);
+
+CREATE UNIQUE INDEX i_mqtt_topic ON mqtt_pub (topic);
diff --git a/test/docker/db/riak/Dockerfile b/test/docker/db/riak/Dockerfile
new file mode 100644
index 000000000..b0f539dc9
--- /dev/null
+++ b/test/docker/db/riak/Dockerfile
@@ -0,0 +1,53 @@
+# docker build -t ejabberd/riak .
+# docker run --rm -it -p 8087:8087 -p 8098:8098 -v "`pwd`/ebin:/usr/lib/ejabberd/ebin" --name ejabberd-riak ejabberd/riak
+# docker exec -it ejabberd-riak /bin/bash
+# docker push ejabberd/riak:latest
+FROM ubuntu:16.04
+
+ENV DEBIAN_FRONTEND noninteractive
+# ENV RIAK_VERSION 2.0.9-1
+# install riak=${RIAK_VERSION} to fallback to an older version
+
+RUN \
+ apt-get update -qq && \
+ apt-get install -y curl apt-utils iputils-ping && \
+ curl -s https://packagecloud.io/install/repositories/basho/riak/script.deb.sh | bash && \
+ apt-get install -y riak && \
+ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+
+# Expose default ports
+EXPOSE 8087
+EXPOSE 8098
+
+# Expose volumes for data and logs
+VOLUME /var/log/riak
+VOLUME /var/lib/riak
+
+# Expose volumes for ejabberd code for map/reduce in Riak.
+# It can be overloaded to provide a new ejabberd_riak.beam file.
+# Note that ejabberd_riak.beam needs to be compiled with Erlang/OTP R16
+# as this is the version of Erlang Basho has packaged with Riak.
+COPY ejabberd_riak.beam /usr/lib/ejabberd/ebin/ejabberd_riak.beam
+VOLUME /usr/lib/ejabberd/ebin
+
+# Install custom start script
+COPY riak-cluster.sh /sbin/riak-cluster.sh
+RUN chmod a+x /sbin/riak-cluster.sh
+
+# Change configuration to make it work with ejabberd
+COPY advanced.config /etc/riak/advanced.config
+COPY riak.conf /etc/riak/riak.conf
+
+# Install custom hooks
+COPY prestart.d /etc/riak/prestart.d
+# COPY poststart.d /etc/riak/poststart.d
+
+# Prepare for bootstrapping schemas
+RUN mkdir -p /etc/riak/schemas
+
+# Clean up APT cache
+RUN rm -rf /var/lib/apt/lists/* /tmp/*
+
+WORKDIR /var/lib/riak
+
+CMD ["/sbin/riak-cluster.sh"]
diff --git a/test/docker/db/riak/advanced.config b/test/docker/db/riak/advanced.config
new file mode 100644
index 000000000..e5d5f8743
--- /dev/null
+++ b/test/docker/db/riak/advanced.config
@@ -0,0 +1,27 @@
+%% Config file used to set advanced configuration options
+
+[{lager,
+ [
+ {extra_sinks,
+ [
+ {object_lager_event,
+ [{handlers,
+ [{lager_file_backend,
+ [{file, "/var/log/riak/object.log"},
+ {level, info},
+ {formatter_config, [date, " ", time," [",severity,"] ",message, "\n"]}
+ ]
+ }]
+ },
+ {async_threshold, 500},
+ {async_threshold_window, 50}]
+ }
+ ]
+ }
+ ]},
+
+ {riak_kv, [
+ %% Other configs
+ {add_paths, ["/usr/lib/ejabberd/ebin"]}
+ ]}
+].
diff --git a/test/docker/db/riak/ejabberd_riak.beam b/test/docker/db/riak/ejabberd_riak.beam
new file mode 100644
index 000000000..3bebb297d
--- /dev/null
+++ b/test/docker/db/riak/ejabberd_riak.beam
Binary files differ
diff --git a/test/docker/db/riak/prestart.d/00-setup-networking.sh b/test/docker/db/riak/prestart.d/00-setup-networking.sh
new file mode 100755
index 000000000..07ca617fb
--- /dev/null
+++ b/test/docker/db/riak/prestart.d/00-setup-networking.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Add standard config items
+cat <<END >>$RIAK_CONF
+nodename = riak@$HOST
+distributed_cookie = $CLUSTER_NAME
+listener.protobuf.internal = $HOST:$PB_PORT
+listener.http.internal = $HOST:$HTTP_PORT
+END
diff --git a/test/docker/db/riak/riak-cluster.sh b/test/docker/db/riak/riak-cluster.sh
new file mode 100644
index 000000000..11f344f0a
--- /dev/null
+++ b/test/docker/db/riak/riak-cluster.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+#
+# Cluster start script to bootstrap a Riak cluster.
+#
+set -ex
+
+if [[ -x /usr/sbin/riak ]]; then
+ export RIAK=/usr/sbin/riak
+else
+ export RIAK=$RIAK_HOME/bin/riak
+fi
+export RIAK_CONF=/etc/riak/riak.conf
+export USER_CONF=/etc/riak/user.conf
+export RIAK_ADVANCED_CONF=/etc/riak/advanced.config
+if [[ -x /usr/sbin/riak-admin ]]; then
+ export RIAK_ADMIN=/usr/sbin/riak-admin
+else
+ export RIAK_ADMIN=$RIAK_HOME/bin/riak-admin
+fi
+export SCHEMAS_DIR=/etc/riak/schemas/
+
+# Set ports for PB and HTTP
+export PB_PORT=${PB_PORT:-8087}
+export HTTP_PORT=${HTTP_PORT:-8098}
+
+# Use ping to discover our HOSTNAME because it's easier and more reliable than other methods
+export HOST=$(ping -c1 $HOSTNAME | awk '/^PING/ {print $3}' | sed 's/[()]//g')||'127.0.0.1'
+
+# CLUSTER_NAME is used to name the nodes and is the value used in the distributed cookie
+export CLUSTER_NAME=${CLUSTER_NAME:-riak}
+
+# The COORDINATOR_NODE is the first node in a cluster to which other nodes will eventually join
+export COORDINATOR_NODE=${COORDINATOR_NODE:-$HOSTNAME}
+export COORDINATOR_NODE_HOST=$(ping -c1 $COORDINATOR_NODE | awk '/^PING/ {print $3}' | sed 's/[()]//g')||'127.0.0.1'
+
+# Run all prestart scripts
+PRESTART=$(find /etc/riak/prestart.d -name *.sh -print | sort)
+for s in $PRESTART; do
+ . $s
+done
+
+# Start the node and wait until fully up
+$RIAK start
+$RIAK_ADMIN wait-for-service riak_kv
+
+# Run all poststart scripts
+POSTSTART=$(find /etc/riak/poststart.d -name *.sh -print | sort)
+for s in $POSTSTART; do
+ . $s
+done
+
+# Trap SIGTERM and SIGINT and tail the log file indefinitely
+tail -n 1024 -f /var/log/riak/console.log &
+PID=$!
+trap "$RIAK stop; kill $PID" SIGTERM SIGINT
+wait $PID
diff --git a/test/docker/db/riak/riak.conf b/test/docker/db/riak/riak.conf
new file mode 100644
index 000000000..3c8c0c09e
--- /dev/null
+++ b/test/docker/db/riak/riak.conf
@@ -0,0 +1,682 @@
+## Where to emit the default log messages (typically at 'info'
+## severity):
+## off: disabled
+## file: the file specified by log.console.file
+## console: to standard output (seen when using `riak attach-direct`)
+## both: log.console.file and standard out.
+##
+## Default: file
+##
+## Acceptable values:
+## - one of: off, file, console, both
+log.console = file
+
+## The severity level of the console log, default is 'info'.
+##
+## Default: info
+##
+## Acceptable values:
+## - one of: debug, info, notice, warning, error, critical, alert, emergency, none
+log.console.level = info
+
+## When 'log.console' is set to 'file' or 'both', the file where
+## console messages will be logged.
+##
+## Default: $(platform_log_dir)/console.log
+##
+## Acceptable values:
+## - the path to a file
+log.console.file = $(platform_log_dir)/console.log
+
+## The file where error messages will be logged.
+##
+## Default: $(platform_log_dir)/error.log
+##
+## Acceptable values:
+## - the path to a file
+log.error.file = $(platform_log_dir)/error.log
+
+## When set to 'on', enables log output to syslog.
+##
+## Default: off
+##
+## Acceptable values:
+## - on or off
+log.syslog = off
+
+## Whether to enable the crash log.
+##
+## Default: on
+##
+## Acceptable values:
+## - on or off
+log.crash = on
+
+## If the crash log is enabled, the file where its messages will
+## be written.
+##
+## Default: $(platform_log_dir)/crash.log
+##
+## Acceptable values:
+## - the path to a file
+log.crash.file = $(platform_log_dir)/crash.log
+
+## Maximum size in bytes of individual messages in the crash log
+##
+## Default: 64KB
+##
+## Acceptable values:
+## - a byte size with units, e.g. 10GB
+log.crash.maximum_message_size = 64KB
+
+## Maximum size of the crash log in bytes, before it is rotated
+##
+## Default: 10MB
+##
+## Acceptable values:
+## - a byte size with units, e.g. 10GB
+log.crash.size = 10MB
+
+## The schedule on which to rotate the crash log. For more
+## information see:
+## https://github.com/basho/lager/blob/master/README.md#internal-log-rotation
+##
+## Default: $D0
+##
+## Acceptable values:
+## - text
+log.crash.rotation = $D0
+
+## The number of rotated crash logs to keep. When set to
+## 'current', only the current open log file is kept.
+##
+## Default: 5
+##
+## Acceptable values:
+## - an integer
+## - the text "current"
+log.crash.rotation.keep = 5
+
+## Name of the Erlang node
+##
+## Default: riak@127.0.0.1
+##
+## Acceptable values:
+## - text
+## nodename = riak@127.0.0.1
+
+## Cookie for distributed node communication. All nodes in the
+## same cluster should use the same cookie or they will not be able to
+## communicate.
+##
+## Default: riak
+##
+## Acceptable values:
+## - text
+distributed_cookie = riak
+
+## Sets the number of threads in async thread pool, valid range
+## is 0-1024. If thread support is available, the default is 64.
+## More information at: http://erlang.org/doc/man/erl.html
+##
+## Default: 64
+##
+## Acceptable values:
+## - an integer
+erlang.async_threads = 64
+
+## The number of concurrent ports/sockets
+## Valid range is 1024-134217727
+##
+## Default: 262144
+##
+## Acceptable values:
+## - an integer
+erlang.max_ports = 262144
+
+## Set scheduler forced wakeup interval. All run queues will be
+## scanned each Interval milliseconds. While there are sleeping
+## schedulers in the system, one scheduler will be woken for each
+## non-empty run queue found. An Interval of zero disables this
+## feature, which also is the default.
+## This feature is a workaround for lengthy executing native code, and
+## native code that do not bump reductions properly.
+## More information: http://www.erlang.org/doc/man/erl.html#+sfwi
+##
+## Default: 500
+##
+## Acceptable values:
+## - an integer
+## erlang.schedulers.force_wakeup_interval = 500
+
+## Enable or disable scheduler compaction of load. By default
+## scheduler compaction of load is enabled. When enabled, load
+## balancing will strive for a load distribution which causes as many
+## scheduler threads as possible to be fully loaded (i.e., not run out
+## of work). This is accomplished by migrating load (e.g. runnable
+## processes) into a smaller set of schedulers when schedulers
+## frequently run out of work. When disabled, the frequency with which
+## schedulers run out of work will not be taken into account by the
+## load balancing logic.
+## More information: http://www.erlang.org/doc/man/erl.html#+scl
+##
+## Default: false
+##
+## Acceptable values:
+## - one of: true, false
+## erlang.schedulers.compaction_of_load = false
+
+## Enable or disable scheduler utilization balancing of load. By
+## default scheduler utilization balancing is disabled and instead
+## scheduler compaction of load is enabled which will strive for a
+## load distribution which causes as many scheduler threads as
+## possible to be fully loaded (i.e., not run out of work). When
+## scheduler utilization balancing is enabled the system will instead
+## try to balance scheduler utilization between schedulers. That is,
+## strive for equal scheduler utilization on all schedulers.
+## More information: http://www.erlang.org/doc/man/erl.html#+sub
+##
+## Acceptable values:
+## - one of: true, false
+## erlang.schedulers.utilization_balancing = true
+
+## Number of partitions in the cluster (only valid when first
+## creating the cluster). Must be a power of 2, minimum 8 and maximum
+## 1024.
+##
+## Default: 64
+##
+## Acceptable values:
+## - an integer
+## ring_size = 64
+
+## Number of concurrent node-to-node transfers allowed.
+##
+## Default: 2
+##
+## Acceptable values:
+## - an integer
+## transfer_limit = 2
+
+## Default cert location for https can be overridden
+## with the ssl config variable, for example:
+##
+## Acceptable values:
+## - the path to a file
+## ssl.certfile = $(platform_etc_dir)/cert.pem
+
+## Default key location for https can be overridden with the ssl
+## config variable, for example:
+##
+## Acceptable values:
+## - the path to a file
+## ssl.keyfile = $(platform_etc_dir)/key.pem
+
+## Default signing authority location for https can be overridden
+## with the ssl config variable, for example:
+##
+## Acceptable values:
+## - the path to a file
+## ssl.cacertfile = $(platform_etc_dir)/cacertfile.pem
+
+## DTrace support Do not enable 'dtrace' unless your Erlang/OTP
+## runtime is compiled to support DTrace. DTrace is available in
+## R15B01 (supported by the Erlang/OTP official source package) and in
+## R14B04 via a custom source repository & branch.
+##
+## Default: off
+##
+## Acceptable values:
+## - on or off
+dtrace = off
+
+## Platform-specific installation paths (substituted by rebar)
+##
+## Default: /usr/sbin
+##
+## Acceptable values:
+## - the path to a directory
+platform_bin_dir = /usr/sbin
+
+##
+## Default: /var/lib/riak
+##
+## Acceptable values:
+## - the path to a directory
+platform_data_dir = /var/lib/riak
+
+##
+## Default: /etc/riak
+##
+## Acceptable values:
+## - the path to a directory
+platform_etc_dir = /etc/riak
+
+##
+## Default: /usr/lib/riak/lib
+##
+## Acceptable values:
+## - the path to a directory
+platform_lib_dir = /usr/lib/riak/lib
+
+##
+## Default: /var/log/riak
+##
+## Acceptable values:
+## - the path to a directory
+platform_log_dir = /var/log/riak
+
+## Enable consensus subsystem. Set to 'on' to enable the
+## consensus subsystem used for strongly consistent Riak operations.
+##
+## Default: off
+##
+## Acceptable values:
+## - on or off
+## strong_consistency = on
+
+## listener.http.<name> is an IP address and TCP port that the Riak
+## HTTP interface will bind.
+##
+## Default: 127.0.0.1:8098
+##
+## Acceptable values:
+## - an IP/port pair, e.g. 127.0.0.1:10011
+## listener.http.internal = 127.0.0.1:8098
+
+## listener.protobuf.<name> is an IP address and TCP port that the Riak
+## Protocol Buffers interface will bind.
+##
+## Default: 127.0.0.1:8087
+##
+## Acceptable values:
+## - an IP/port pair, e.g. 127.0.0.1:10011
+## listener.protobuf.internal = 127.0.0.1:8087
+
+## The maximum length to which the queue of pending connections
+## may grow. If set, it must be an integer > 0. If you anticipate a
+## huge number of connections being initialized *simultaneously*, set
+## this number higher.
+##
+## Default: 128
+##
+## Acceptable values:
+## - an integer
+## protobuf.backlog = 128
+
+## listener.https.<name> is an IP address and TCP port that the Riak
+## HTTPS interface will bind.
+##
+## Acceptable values:
+## - an IP/port pair, e.g. 127.0.0.1:10011
+## listener.https.internal = 127.0.0.1:8098
+
+## How Riak will repair out-of-sync keys. Some features require
+## this to be set to 'active', including search.
+## * active: out-of-sync keys will be repaired in the background
+## * passive: out-of-sync keys are only repaired on read
+## * active-debug: like active, but outputs verbose debugging
+## information
+##
+## Default: active
+##
+## Acceptable values:
+## - one of: active, passive, active-debug
+anti_entropy = active
+
+## Specifies the storage engine used for Riak's key-value data
+## and secondary indexes (if supported).
+##
+## Default: bitcask
+##
+## Acceptable values:
+## - one of: bitcask, leveldb, memory, multi, prefix_multi
+storage_backend = leveldb
+
+## Simplify prefix_multi configuration for Riak CS. Keep this
+## commented out unless Riak is configured for Riak CS.
+##
+## Acceptable values:
+## - an integer
+## cs_version = 20000
+
+## Controls which binary representation of a riak value is stored
+## on disk.
+## * 0: Original erlang:term_to_binary format. Higher space overhead.
+## * 1: New format for more compact storage of small values.
+##
+## Default: 1
+##
+## Acceptable values:
+## - the integer 1
+## - the integer 0
+object.format = 1
+
+## Reading or writing objects bigger than this size will write a
+## warning in the logs.
+##
+## Default: 5MB
+##
+## Acceptable values:
+## - a byte size with units, e.g. 10GB
+object.size.warning_threshold = 5MB
+
+## Writing an object bigger than this will send a failure to the
+## client.
+##
+## Default: 50MB
+##
+## Acceptable values:
+## - a byte size with units, e.g. 10GB
+object.size.maximum = 50MB
+
+## Writing an object with more than this number of siblings will
+## generate a warning in the logs.
+##
+## Default: 25
+##
+## Acceptable values:
+## - an integer
+object.siblings.warning_threshold = 25
+
+## Writing an object with more than this number of siblings will
+## send a failure to the client.
+##
+## Default: 100
+##
+## Acceptable values:
+## - an integer
+object.siblings.maximum = 100
+
+## Whether to allow list buckets.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.list_buckets = enabled
+
+## Whether to allow streaming list buckets.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.stream_list_buckets = enabled
+
+## Whether to allow list keys.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.list_keys = enabled
+
+## Whether to allow streaming list keys.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.stream_list_keys = enabled
+
+## Whether to allow secondary index queries.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.secondary_index = enabled
+
+## Whether to allow streaming secondary index queries.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.stream_secondary_index = enabled
+
+## Whether to allow term-based map-reduce.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.map_reduce = enabled
+
+## Whether to allow JavaScript map-reduce.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_kv.map_reduce_js = enabled
+
+## A path under which bitcask data files will be stored.
+##
+## Default: $(platform_data_dir)/bitcask
+##
+## Acceptable values:
+## - the path to a directory
+bitcask.data_root = $(platform_data_dir)/bitcask
+
+## Configure how Bitcask writes data to disk.
+## erlang: Erlang's built-in file API
+## nif: Direct calls to the POSIX C API
+## The NIF mode provides higher throughput for certain
+## workloads, but has the potential to negatively impact
+## the Erlang VM, leading to higher worst-case latencies
+## and possible throughput collapse.
+##
+## Default: erlang
+##
+## Acceptable values:
+## - one of: erlang, nif
+bitcask.io_mode = erlang
+
+## Set to 'off' to disable the admin panel.
+##
+## Default: off
+##
+## Acceptable values:
+## - on or off
+riak_control = off
+
+## Authentication mode used for access to the admin panel.
+##
+## Default: off
+##
+## Acceptable values:
+## - one of: off, userlist
+riak_control.auth.mode = off
+
+## If riak control's authentication mode (riak_control.auth.mode)
+## is set to 'userlist' then this is the list of usernames and
+## passwords for access to the admin panel.
+## To create users with given names, add entries of the format:
+## riak_control.auth.user.USERNAME.password = PASSWORD
+## replacing USERNAME with the desired username and PASSWORD with the
+## desired password for that user.
+##
+## Acceptable values:
+## - text
+## riak_control.auth.user.admin.password = pass
+
+## This parameter defines the percentage of total server memory
+## to assign to LevelDB. LevelDB will dynamically adjust its internal
+## cache sizes to stay within this size. The memory size can
+## alternately be assigned as a byte count via leveldb.maximum_memory
+## instead.
+##
+## Default: 70
+##
+## Acceptable values:
+## - an integer
+leveldb.maximum_memory.percent = 70
+
+## Enables or disables the compression of data on disk.
+## Enabling (default) saves disk space. Disabling may reduce read
+## latency but increase overall disk activity. Option can be
+## changed at any time, but will not impact data on disk until
+## next time a file requires compaction.
+##
+## Default: on
+##
+## Acceptable values:
+## - on or off
+leveldb.compression = on
+
+## Selection of compression algorithms. snappy is
+## original compression supplied for leveldb. lz4 is new
+## algorithm that compresses to similar volume but averages twice
+## as fast on writes and four times as fast on reads.
+##
+## Acceptable values:
+## - one of: snappy, lz4
+leveldb.compression.algorithm = lz4
+
+##
+## Default: on
+##
+## Acceptable values:
+## - on or off
+## multi_backend.name.leveldb.compression = on
+
+##
+## Acceptable values:
+## - one of: snappy, lz4
+## multi_backend.name.leveldb.compression.algorithm = lz4
+
+## Whether to allow search queries.
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.riak_search.query = enabled
+
+## To enable Search set this 'on'.
+##
+## Default: off
+##
+## Acceptable values:
+## - on or off
+search = off
+
+## How long Riak will wait for Solr to start. The start sequence
+## will be tried twice. If both attempts timeout, then the Riak node
+## will be shutdown. This may need to be increased as more data is
+## indexed and Solr takes longer to start. Values lower than 1s will
+## be rounded up to the minimum 1s.
+##
+## Default: 30s
+##
+## Acceptable values:
+## - a time duration with units, e.g. '10s' for 10 seconds
+search.solr.start_timeout = 30s
+
+## The port number which Solr binds to.
+## NOTE: Binds on every interface.
+##
+## Default: 8093
+##
+## Acceptable values:
+## - an integer
+search.solr.port = 8093
+
+## The port number which Solr JMX binds to.
+## NOTE: Binds on every interface.
+##
+## Default: 8985
+##
+## Acceptable values:
+## - an integer
+search.solr.jmx_port = 8985
+
+## The options to pass to the Solr JVM. Non-standard options,
+## i.e. -XX, may not be portable across JVM implementations.
+## E.g. -XX:+UseCompressedStrings
+##
+## Default: -d64 -Xms1g -Xmx1g -XX:+UseStringCache -XX:+UseCompressedOops
+##
+## Acceptable values:
+## - text
+search.solr.jvm_options = -d64 -Xms1g -Xmx1g -XX:+UseStringCache -XX:+UseCompressedOops
+
+## The minimum batch size, in number of Riak objects. Any batches that
+## are smaller than this amount will not be immediately flushed to Solr,
+## but are guaranteed to be flushed within the
+## "search.queue.batch.flush_interval".
+##
+## Default: 10
+##
+## Acceptable values:
+## - an integer
+## search.queue.batch.minimum = 10
+
+## The maximum batch size, in number of Riak objects. Any batches that are
+## larger than this amount will be split, where the first
+## search.queue.batch.maximum set of objects will be flushed to Solr, and
+## the remaining objects enqueued for that index will be retained until the
+## next batch is delivered. This parameter ensures that at most
+## "search.queue.batch.maximum object" will be delivered into Solr in any
+## given request.
+##
+## Default: 500
+##
+## Acceptable values:
+## - an integer
+## search.queue.batch.maximum = 500
+
+## The maximum delay between notification to flush batches to Solr. This
+## setting is used to increase or decrease the frequency of batch delivery
+## into Solr, specifically for relatively low-volume input into Riak. This
+## setting ensures that data will be delivered into Solr in accordance with
+## the "search.queue.batch.minimum" and "search.queue.batch.maximum"
+## settings within the specified interval. Batches that are smaller than
+## "search.queue.batch.minimum" will be delivered to Solr within this
+## interval. This setting will generally hav no effect on heavily loaded
+## systems.
+##
+## Default: 500ms
+##
+## Acceptable values:
+## - a time duration with units, e.g. '10s' for 10 seconds
+## - the text "infinity"
+## search.queue.batch.flush_interval = 500ms
+
+## The queue high watermark. If the total number of queued messages in a
+## Solr Queue Worker instance exceeds this limit, then the calling vnode
+## will be blocked until the total number falls below this limit. This
+## parameter exercises flow control between Riak and the Riak
+## Search batching subsystem if writes into Solr start to fall behind.
+##
+## Default: 1000
+##
+## Acceptable values:
+## - an integer
+## search.queue.high_watermark = 1000
+
+## The strategy for how we handle purging when we hit the
+## search.queue.high_watermark.
+## - purge_one -> Removes the oldest item on the queue from an
+## erroring (references to fuses blown in the code) index in
+## order to get below the search.queue.high_watermark.
+## - purge_index -> Removes all items associated with one random
+## erroring (references to fuses blown in the code) index in
+## order to get below the search.queue.high_watermark.
+## - off -> purging is disabled
+##
+## Default: purge_one
+##
+## Acceptable values:
+## - one of: purge_one, purge_index, off
+## search.queue.high_watermark.purge_strategy = purge_one
+
+## Whether to allow Yokozuna queries on this node
+##
+## Default: enabled
+##
+## Acceptable values:
+## - enabled or disabled
+## cluster.job.yokozuna.query = enabled