blob: eff71b4a4d9f74da7b7f86d89577f5e7ce8d57d0 [file] [log] [blame]
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os.path
import re
import time
import pytest
MYSQL_CONFIG = {
"MYSQL_HOST": "k8sgerrit-mysql",
"MYSQL_PORT": 3306,
"MYSQL_ROOT_PASSWORD": "big_secret",
"REPL_PASSWORD": "test",
}
@pytest.fixture()
def mock_dump():
return (
"CREATE DATABASE `users`;"
"USE `users`;"
"CREATE TABLE `users` ("
"`id` INT(11) NOT NULL,"
"`first_name` VARCHAR(50),"
"`last_name` VARCHAR(50),"
"`password` VARCHAR(100),"
"PRIMARY KEY (`id`))"
)
@pytest.fixture(scope="module")
def mock_sql_script(tmp_path_factory):
tmp_dir = tmp_path_factory.mktemp("mysql_init_script")
with open(os.path.join(tmp_dir, "initialize-slave.sql"), "w") as sql_file:
sql_file.write(
(
"USE `users`;"
"SET @query = CONCAT("
'"INSERT INTO `users` (id, first_name, last_name, password) ",'
"\"VALUES (1, 'John', 'Doe', '\", @replpwd, \"');\");"
"PREPARE stmt FROM @query;"
"EXECUTE stmt;"
)
)
return tmp_dir
@pytest.fixture(scope="module")
def mysql_container(request, docker_client, docker_network, mysql_container_factory):
mysql_container = mysql_container_factory(
docker_client, docker_network, MYSQL_CONFIG
)
mysql_container.start()
request.addfinalizer(mysql_container.stop)
return mysql_container
@pytest.fixture(scope="module")
def init_container(
request,
docker_client,
docker_network,
mysql_replication_init_image,
mock_sql_script,
):
container_run = docker_client.containers.run(
image=mysql_replication_init_image.id,
environment=MYSQL_CONFIG,
volumes={mock_sql_script: {"bind": "/var/sql", "mode": "ro"}},
network=docker_network.name,
name="mysql-replication-init",
detach=True,
)
def stop_container():
container_run.stop(timeout=1)
container_run.remove(v=True, force=True)
request.addfinalizer(stop_container)
return container_run
@pytest.fixture(scope="module")
def containers(mysql_container, init_container):
return mysql_container, init_container
@pytest.mark.slow
@pytest.mark.incremental
class TestMysqlInitScript:
def test_mysql_replication_init_waiting_for_dump(self, containers):
(_, init_container) = containers
timeout = time.time() + 20
while time.time() < timeout:
last_log_line = init_container.logs(tail=1).decode("utf-8").strip()
if (
last_log_line
== "Waiting for database dump file at /var/data/db/master_dump.sql"
):
break
assert timeout > time.time()
def test_mysql_replication_init_accepts_dump(self, containers, mock_dump):
(_, init_container) = containers
cmd = "/bin/bash -c \"echo '%s' > /var/data/db/master_dump.sql\"" % mock_dump
init_container.exec_run(cmd)
timeout = time.time() + 20
while time.time() < timeout:
logs = init_container.logs().decode("utf-8")
if re.search(r"Database dump received", logs):
break
assert timeout > time.time()
def test_mysql_replication_init_finishes(self, containers):
(_, init_container) = containers
timeout = time.time() + 20
while time.time() < timeout:
init_container.reload()
if init_container.status == "exited":
break
assert timeout > time.time()
assert init_container.attrs["State"]["ExitCode"] == 0
def test_mysql_replication_init_applies_dump(self, containers):
(mysql_container, _) = containers
connection = mysql_container.connect()
result = connection.execute("SHOW DATABASES;")
connection.close()
assert "users" in [row[0] for row in result]
def test_mysql_replication_init_runs_slave_init_script(self, containers):
(mysql_container, _) = containers
connection = mysql_container.connect()
result = connection.execute("USE `users`;")
result = connection.execute("SELECT password FROM users WHERE id=1 LIMIT 1;")
connection.close()
for row in result:
assert MYSQL_CONFIG["REPL_PASSWORD"] in row["password"]