diff --git a/docker-image-tests/percona-mysql-router/README.md b/docker-image-tests/percona-mysql-router/README.md new file mode 100644 index 000000000..7bd652f9e --- /dev/null +++ b/docker-image-tests/percona-mysql-router/README.md @@ -0,0 +1,7 @@ +Before running set environment variables, eg.: + +export DOCKER_ACC="percona" +export PS_VERSION="8.0.32-24" +export ROUTER_VERSION="8.0.32" +export TESTING_BRANCH="master" +This is based on: https://testinfra.readthedocs.io/en/latest/examples.html#test-docker-images diff --git a/docker-image-tests/percona-mysql-router/cleanup.sh b/docker-image-tests/percona-mysql-router/cleanup.sh new file mode 100755 index 000000000..3cdc4f0ec --- /dev/null +++ b/docker-image-tests/percona-mysql-router/cleanup.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +rm -f report.xml +rm -rf .pytest_cache +rm -rf __pycache__ +rm -rf tests/__pycache__ diff --git a/docker-image-tests/percona-mysql-router/requirements.txt b/docker-image-tests/percona-mysql-router/requirements.txt new file mode 100644 index 000000000..8a28056d0 --- /dev/null +++ b/docker-image-tests/percona-mysql-router/requirements.txt @@ -0,0 +1,15 @@ +atomicwrites==1.3.0 +attrs==19.3.0 +importlib-metadata==0.23 +more-itertools==7.2.0 +packaging==19.2 +pluggy==0.13.0 +py==1.10.0 +pyparsing==2.4.2 +pytest==5.2.1 +six==1.12.0 +testinfra==3.2.0 +wcwidth==0.1.7 +zipp==0.6.0 +requests==2.27.1 +docker==5.0.3 diff --git a/docker-image-tests/percona-mysql-router/run.sh b/docker-image-tests/percona-mysql-router/run.sh new file mode 100755 index 000000000..8ba9b8684 --- /dev/null +++ b/docker-image-tests/percona-mysql-router/run.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +pytest -v --junit-xml report.xml $@ diff --git a/docker-image-tests/percona-mysql-router/settings.py b/docker-image-tests/percona-mysql-router/settings.py new file mode 100644 index 000000000..095ad5237 --- /dev/null +++ b/docker-image-tests/percona-mysql-router/settings.py @@ -0,0 +1,14 @@ +import os + +router_version = os.getenv('ROUTER_VERSION') +docker_tag = os.getenv('ROUTER_VERSION') +docker_acc = os.getenv('DOCKER_ACC') + +docker_product = 'percona-mysql-router' +docker_image = docker_acc + "/" + docker_product + ":" + docker_tag +ps_pwd = 'inno' + +RHEL_DISTS = ["redhat", "centos", "rhel", "oracleserver", "ol", "amzn"] + +DEB_DISTS = ["debian", "ubuntu"] + diff --git a/docker-image-tests/percona-mysql-router/test b/docker-image-tests/percona-mysql-router/test new file mode 100644 index 000000000..29e2c5342 --- /dev/null +++ b/docker-image-tests/percona-mysql-router/test @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +import pytest +import subprocess +import testinfra +import time +from settings import * + +container_name = 'router-docker-test-static' + +@pytest.fixture(scope='module') +def host(): + docker_id = subprocess.check_output( + ['docker', 'run', '--name', container_name, '-d', docker_image ], stderr=subprocess.STDOUT ).decode().strip() + time.sleep(20) + subprocess.check_call(['docker','exec','--user','root',container_name,'microdnf','install', '-y', 'net-tools']) + time.sleep(20) + yield testinfra.get_host("docker://root@" + docker_id) + subprocess.check_call(['docker', 'rm', '-f', docker_id]) + + +class TestRouterEnvironment: + def test_packages(self, host): + pkg = host.package("percona-mysql-router") + dist = host.system_info.distribution + assert pkg.is_installed + if dist.lower() in RHEL_DISTS: + assert router_version in pkg.version+'-'+pkg.release, pkg.version+'-'+pkg.release + else: + assert router_version in pkg.version, pkg.version + + def test_binaries_exist(self, host): + router_binary="/tmp/mysqlrouter" + assert host.file(router_binary).exists + assert oct(host.file(router_binary).mode) == '0o755' + + def test_binaries_version(self, host): + assert router_version in host.check_output("/tmp/mysqlrouter --version") + +# def test_process_running(self, host): +# assert host.process.get(user="mysql", comm="orchestrator") + + def test_http_port_6446(self, host): + assert host.socket('tcp://127.0.0.1:6446').is_listening + + def test_raft_port_6447(self, host): + assert host.socket('tcp://127.0.0.1:6447').is_listening + + def test_mysql_user(self, host): + assert host.user('mysql').exists + assert host.user('mysql').uid == 1001 + assert host.user('mysql').gid == 1001 + assert 'mysql' in host.user('mysql').groups + + def test_mysql_group(self, host): + assert host.group('mysql').exists + assert host.group('mysql').gid == 1001 + + def test_router_permissions(self, host): + assert host.file('/var/lib/mysqlrouter').user == 'mysql' + assert host.file('/var/lib/mysqlrouter').group == 'mysql' + assert oct(host.file('/var/lib/mysqlrouter').mode) == '0o755' + + def test_mysqlrouter_version(self, host): + cmd = host.run("mysqlrouter --version") + assert router_version in cmd.stdout + + + def test_mysqlsh_version(self, host): + cmd = host.run("mysqlsh --version") + assert PS_VERSION in cmd.stdout diff --git a/docker-image-tests/percona-mysql-router/tests/.test_router_attr.py.swp b/docker-image-tests/percona-mysql-router/tests/.test_router_attr.py.swp new file mode 100644 index 000000000..48502ade2 Binary files /dev/null and b/docker-image-tests/percona-mysql-router/tests/.test_router_attr.py.swp differ diff --git a/docker-image-tests/percona-mysql-router/tests/.test_router_static.py.swp b/docker-image-tests/percona-mysql-router/tests/.test_router_static.py.swp new file mode 100644 index 000000000..d76629f6f Binary files /dev/null and b/docker-image-tests/percona-mysql-router/tests/.test_router_static.py.swp differ diff --git a/docker-image-tests/percona-mysql-router/tests/__init__.py b/docker-image-tests/percona-mysql-router/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docker-image-tests/percona-mysql-router/tests/test_router_attr.py b/docker-image-tests/percona-mysql-router/tests/test_router_attr.py new file mode 100644 index 000000000..1499d176c --- /dev/null +++ b/docker-image-tests/percona-mysql-router/tests/test_router_attr.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import pytest +import subprocess +import testinfra +import json +from settings import * + +container_name = 'router-docker-test-inspect' + +@pytest.fixture(scope='module') +def inspect_data(): + docker_id = subprocess.check_output( + ['docker', 'run', '--name', container_name, '-d', docker_image], stderr=subprocess.STDOUT ).decode().strip() + inspect_data = json.loads(subprocess.check_output(['docker','inspect',container_name])) + yield inspect_data[0] + subprocess.check_call(['docker', 'rm', '-f', docker_id]) + + +class TestContainerAttributes: + def test_status(self, inspect_data): + assert inspect_data['State']['Status'] == 'running' + assert inspect_data['State']['Running'] == True + + def test_config(self, inspect_data): + assert len(inspect_data['Config']['Cmd']) == 1 + assert inspect_data['Config']['Cmd'][0] == 'mysqlrouter' + + def test_image_name(self, inspect_data): + assert inspect_data['Config']['Image'] == docker_image + + def test_volumes(self, inspect_data): + assert len(inspect_data['Config']['Volumes']) == 1 + assert '/var/lib/mysqlrouter' in inspect_data['Config']['Volumes'] + + def test_entrypoint(self, inspect_data): + assert len(inspect_data['Config']['Entrypoint']) == 1 + assert inspect_data['Config']['Entrypoint'][0] == '/entrypoint.sh' + diff --git a/docker-image-tests/percona-mysql-router/tests/test_router_static.py b/docker-image-tests/percona-mysql-router/tests/test_router_static.py new file mode 100644 index 000000000..86856d673 --- /dev/null +++ b/docker-image-tests/percona-mysql-router/tests/test_router_static.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +import pytest +import subprocess +import testinfra +import time +from settings import * +import json +import os +import requests +import docker + +container_name = 'mysql-router-test' +network_name = 'innodbnet1' + +@pytest.fixture(scope='module') +def host(): + docker_client = docker.from_env() + docker_client.networks.create(network_name) + docker_id = subprocess.check_output( + ['docker', 'run', '--name', container_name, '-e', '--net', network_name, '-e', 'MYSQL_ROOT_PASSWORD='+ps_pwd, '-e', '--MYSQL_INNODB_CLUSTER_MEMBERS', '4', docker_image ], stderr=subprocess.STDOUT ).decode().strip() + time.sleep(20) + subprocess.check_call(['docker','exec','--user','root',container_name,'microdnf','install', '-y', 'net-tools']) + time.sleep(20) + yield testinfra.get_host("docker://root@" + docker_id) + subprocess.check_call(['docker', 'rm', '-f', docker_id]) + + +class TestRouterEnvironment: + def test_mysqlsh_version(self, host): + assert host.check_output("mysqlsh --version") == 'mysqlsh Ver '+ROUTER_VERSION+' for Linux on x86_64 - for MySQL '+PS_VERSION+' (Source distribution)' + + def test_mysqlrouter_version(self, host): + assert host.check_output("mysqlrouter --version") == 'MySQL Router Ver '+PS_VERSION+' for Linux on x86_64 (Percona Server (GPL), Release 25, Revision '+Revision+')' + + def test_binaries_exist(self, host): + router_binary="/tmp/mysqlrouter" + assert host.file(router_binary).exists + assert oct(host.file(router_binary).mode) == '0o755' + + def test_http_port_6447(self, host): + assert host.socket('tcp://127.0.0.1:6447').is_listening + + def test_raft_port_6446(self, host): + assert host.socket('tcp://127.0.0.1:6446').is_listening + + def test_mysql_user(self, host): + assert host.user('mysql').exists + assert host.user('mysql').uid == 1001 + assert host.user('mysql').gid == 1001 + assert 'mysql' in host.user('mysql').groups + + def test_mysql_group(self, host): + assert host.group('mysql').exists + assert host.group('mysql').gid == 1001 + + def test_router_permissions(self, host): + assert host.file('/var/lib/mysqlrouter').user == 'mysql' + assert host.file('/var/lib/mysqlrouter').group == 'mysql' + assert oct(host.file('/var/lib/mysqlrouter').mode) == '0o755' diff --git a/router-docker_test.sh b/router-docker_test.sh index b453b86ab..9eae67318 100755 --- a/router-docker_test.sh +++ b/router-docker_test.sh @@ -1,31 +1,4 @@ -#!/bin/bash - -if [ $# -eq 0 ]; -then - echo "$0: Missing arguments" - exit 1 -elif [ $# -gt 2 ]; -then - echo "$0: Too many arguments: $@" - exit 1 -else - echo "We got some argument(s)" - - echo "===========================" - - echo "Number of arguments.: $#" - - echo "List of arguments...: $@" - - echo "Arg #1..............: $1" - - echo "Arg #2..............: $2" - - echo "===========================" -fi - - -set -xe +#!/usr/bin/env bash cleanup(){ @@ -78,7 +51,7 @@ start_mysql_containers(){ create_new_user(){ for N in 1 2 3 4 - do sudo docker exec -it mysql$N mysql -uroot -proot \ + do sudo docker exec mysql$N mysql -uroot -proot \ -e "CREATE USER 'inno'@'%' IDENTIFIED BY 'inno';" \ -e "GRANT ALL privileges ON *.* TO 'inno'@'%' with grant option;" \ -e "reset master;" @@ -88,7 +61,7 @@ create_new_user(){ verify_new_user(){ for N in 1 2 3 4 - do sudo docker exec -it mysql$N mysql -uinno -pinno \ + do sudo docker exec mysql$N mysql -uinno -pinno \ -e "SHOW VARIABLES WHERE Variable_name = 'hostname';" \ -e "SELECT user FROM mysql.user where user = 'inno';" done @@ -104,19 +77,19 @@ docker_restart(){ create_cluster(){ - sudo docker exec -it mysql1 mysqlsh -uinno -pinno -- dba create-cluster testCluster + sudo docker exec mysql1 mysqlsh -uinno -pinno -- dba create-cluster testCluster } add_slave(){ - sudo docker exec -it mysql1 mysqlsh -uinno -pinno -- cluster add-instance --uri=inno@mysql2 --recoveryMethod=incremental + sudo docker exec mysql1 mysqlsh -uinno -pinno -- cluster add-instance --uri=inno@mysql2 --recoveryMethod=incremental sleep 10 - sudo docker exec -it mysql1 mysqlsh -uinno -pinno -- cluster add-instance --uri=inno@mysql3 --recoveryMethod=incremental + sudo docker exec mysql1 mysqlsh -uinno -pinno -- cluster add-instance --uri=inno@mysql3 --recoveryMethod=incremental sleep 10 - sudo docker exec -it mysql1 mysqlsh -uinno -pinno -- cluster add-instance --uri=inno@mysql4 --recoveryMethod=incremental + sudo docker exec mysql1 mysqlsh -uinno -pinno -- cluster add-instance --uri=inno@mysql4 --recoveryMethod=incremental sleep 10 } @@ -131,69 +104,24 @@ Router_Bootstrap(){ data_add(){ sudo docker run -d --name=mysql-client --hostname=mysql-client --net=innodbnet -e MYSQL_ROOT_PASSWORD=root $1 - + sleep 10 - + echo "Adding sbtest user" - sudo docker exec -it mysql-client mysql -h mysql-router -P 6446 -uinno -pinno \ + sudo docker exec mysql-client mysql -h mysql-router -P 6446 -uinno -pinno \ -e "CREATE SCHEMA sbtest; CREATE USER sbtest@'%' IDENTIFIED with mysql_native_password by 'password';" \ -e "GRANT ALL PRIVILEGES ON sbtest.* to sbtest@'%';" echo "Verify sbtest user" - - sudo docker exec -it mysql-client mysql -h mysql-router -P 6447 -uinno -pinno -e "select host , user from mysql.user where user='sbtest';" - - sleep 5 - - echo "sysbench run" - - sudo docker run --rm=true --net=innodbnet --name=sb-prepare severalnines/sysbench sysbench --db-driver=mysql --table-size=10000 --tables=1 --threads=1 --mysql-host=mysql-router --mysql-port=6446--mysql-user=sbtest --mysql-password=password /usr/share/sysbench/oltp_insert.lua prepare - - sleep 20 - - echo "verify if data is inserted or not" - - sudo docker exec -it mysql-client mysql -h mysql-router -P 6447 -uinno -pinno -e "SELECT count(*) from sbtest.sbtest1;" -} - -verify_replication(){ - - for N in 1 2 3 4; - do - sudo docker exec -it mysql$N mysql -uinno -pinno -e "SHOW VARIABLES WHERE Variable_name = 'hostname';" -e "SELECT count(*) from sbtest.sbtest1;"; - done -} -Fault_tolerance(){ + sudo docker exec mysql-client mysql -h mysql-router -P 6447 -uinno -pinno -e "select host , user from mysql.user where user='sbtest';" - echo "Stop One node" - - sudo docker stop mysql1 - - sleep 10 - - echo "check status" - - sudo docker exec -it mysql-client mysqlsh -h mysql-router -P 6446 -uinno -pinno -- cluster status >> cluster1.json - - sed '1d' cluster1.json >> cluster.json - - status=$(jq -r '.defaultReplicaSet.status' cluster.json) - - echo $status -} - -verify_status(){ + sleep 5 - if [[ "${status}" = "OK_PARTIAL" ]]; then - echo "Innodb cluster looks good" - exit 0 - else - echo "Issue in Innodb Cluster" - exit 1 - fi + echo "sysbench run" + sudo docker run --rm=true --net=innodbnet --name=sb-prepare severalnines/sysbench sysbench --db-driver=mysql --table-size=10000 --tables=1 --threads=1 --mysql-host=mysql-router --mysql-port=6446--mysql-user=sbtest --mysql-password=password /usr/share/sysbench/oltp_insert.lua prepare } cleanup @@ -206,7 +134,4 @@ docker_restart create_cluster add_slave Router_Bootstrap $2 -data_add $1 -verify_replication -Fault_tolerance -verify_status +data_add $1