diff --git a/scenarios.py b/scenarios.py new file mode 100755 index 000000000..445eb5575 --- /dev/null +++ b/scenarios.py @@ -0,0 +1,160 @@ +#!/usr/bin/python + +"""scenarios management tool + +Usage: + scenarios.py [...] + scenarios.py start [] + scenarios.py build_image [] + +The most commonly used scenarios.py commands are: + list List the available test scenarios + proxysql_versions List the available ProxySQL versions to be tested + mysql_versions List the available MySQL versions to be paired with ProxySQL for testing + start Start a ProxySQL testing scenario + ps List the running ProxySQL scenarios +""" +import os +import subprocess +import sys + +from docopt import docopt +import nose + +from test.docker_fleet import DockerFleet + +PROXYSQL_SCENARIO_FILE = '/tmp/proxysql-scenario.txt' + +def scenarios_list(): + templates = DockerFleet().get_docker_scenario_templates() + scenario_names = sorted(templates.keys()) + for scenario in scenario_names: + print('%s @ %s' % (scenario, os.path.abspath(templates[scenario]['dir']))) + +def proxysql_images(): + dockerfiles = DockerFleet().get_dockerfiles_for_proxysql() + images = sorted(dockerfiles.keys()) + for image in images: + print('%s @ %s' % (image, os.path.abspath(dockerfiles[image]['dir']))) + +def mysql_images(): + dockerfiles = DockerFleet().get_dockerfiles_for_mysql() + images = sorted(dockerfiles.keys()) + for image in images: + print('%s @ %s' % (image, os.path.abspath(dockerfiles[image]['dir']))) + +def start(scenario, proxysql_image, mysql_image): + docker_fleet = DockerFleet() + scenario_info = docker_fleet.generate_scenarios( + scenarios=[scenario], + proxysql_filters={'names': [proxysql_image]}, + mysql_filters={'names': [mysql_image]} + )[0] + dirname = docker_fleet.start_temp_scenario(scenario_info, copy_folder=True) + with open(PROXYSQL_SCENARIO_FILE, 'wt') as f: + f.write(dirname) + return dirname + +def stop(): + with open(PROXYSQL_SCENARIO_FILE, 'rt') as f: + dirname = ''.join(f.readlines()).strip() + DockerFleet().stop_temp_scenario(dirname, delete_folder=True) + try: + os.remove(PROXYSQL_SCENARIO_FILE) + except: + pass + +def _build_image(image, dir): + subprocess.call(["docker", "rmi", "-f", "proxysql:%s" % image]) + subprocess.call(["docker", "build", "-t", "proxysql:%s" % image, "."], + cwd=dir) + +def build_image(image): + if image != 'all': + # Builds a docker image (either for ProxySQL or for MySQL) and commits it + # to the renecannao dockerhub repository. + dockerfiles = DockerFleet().get_dockerfiles_for_proxysql() + if image in dockerfiles: + _build_image(image, dockerfiles[image]['dir']) + return + + dockerfiles = DockerFleet().get_dockerfiles_for_mysql() + if image in dockerfiles: + _build_image(image, dockerfiles[image]['dir']) + return + + print("Image %s wasn't found in either ProxySQL or MySQL image list.\n" + "Please double-check the name!" % image) + else: + dockerfiles = DockerFleet().get_dockerfiles_for_proxysql() + for image in dockerfiles.iterkeys(): + _build_image(image, dockerfiles[image]['dir']) + + dockerfiles = DockerFleet().get_dockerfiles_for_mysql() + for image in dockerfiles.iterkeys(): + _build_image(image, dockerfiles[image]['dir']) + +def test(argv): + nose.run(argv=argv) + +if __name__ == '__main__': + + args = docopt(__doc__, + version='scenarios.py version 0.0.1', + options_first=True) + + argv = [args['']] + args[''] + if args[''] == 'list': + scenarios_list() + elif args[''] == 'proxysql_images': + proxysql_images() + elif args[''] == 'mysql_images': + mysql_images() + elif args[''] == 'start': + if len(args['']) >= 1: + scenario = args[''][0] + else: + # Default value for the scenario parameter: '1backend' + scenario = '1backend' + + if len(args['']) >= 2: + proxysql_image = args[''][1].split('=')[1] + else: + # Default value for the proxysql_image parameter: 'proxysql' + proxysql_image = 'proxysql' + + if len(args['']) >= 3: + mysql_image = args[''][2].split('=')[1] + else: + # Default value for the mysql_image parameter: 'mysql-simple-dump' + mysql_image = 'mysql-simple-dump' + + if (os.path.exists(PROXYSQL_SCENARIO_FILE)): + print("Is there another scenario running? If not, delete %s" % + PROXYSQL_SCENARIO_FILE) + else: + dirname = start(scenario, proxysql_image, mysql_image) + print("Scenario started successfully at path %s" % dirname) + + elif args[''] == 'stop': + if (not os.path.exists(PROXYSQL_SCENARIO_FILE)): + print("There is no scenario running or file %s has been removed" % + PROXYSQL_SCENARIO_FILE) + else: + stop() + print("Scenario stopped successfully") + + elif args[''] == 'build_image': + if len(args['']) > 0: + build_image(args[''][0]) + else: + build_image('all') + + elif args[''] == 'test': + if (not os.path.exists(PROXYSQL_SCENARIO_FILE)): + print("There doesn't seem to be a running scenario. Aborting.") + else: + if len(args['']) > 0: + test(args['']) + else: + test(['.']) \ No newline at end of file diff --git a/test/admin_tables_test.py b/test/admin_tables_test.py index 47bdf5614..fd1e70a61 100644 --- a/test/admin_tables_test.py +++ b/test/admin_tables_test.py @@ -5,7 +5,7 @@ from proxysql_base_test import ProxySQLBaseTest class AdminTablesTest(ProxySQLBaseTest): - def _test_monitor_tables_locking_errors(self): + def test_monitor_tables_locking_errors(self): """Test that intensive read/write operations to the MySQL Monitor tables do not trigger locking errors. @@ -31,7 +31,4 @@ class AdminTablesTest(ProxySQLBaseTest): # If we reached this point without an error, it means that the test # has passed. - self.assertEqual(1, 1) - - def test_monitor_tables_locking_errors(self): - self.run_in_docker_scenarios(self._test_monitor_tables_locking_errors) \ No newline at end of file + self.assertEqual(1, 1) \ No newline at end of file diff --git a/test/admin_test.py b/test/admin_test.py index 1b7aca353..2fe4e0bdd 100644 --- a/test/admin_test.py +++ b/test/admin_test.py @@ -4,7 +4,7 @@ from MySQLdb import OperationalError class AdminTest(ProxySQLBaseTest): - def _test_stop_main_thread(self): + def test_stop_main_thread(self): try: # This test will just assert that PROXYSQL STOP works correctly # Since September 2015, the behaviour has been changed - PROXYSQL STOP @@ -13,7 +13,4 @@ class AdminTest(ProxySQLBaseTest): self.run_query_proxysql_admin("PROXYSQL STOP") self.assertEqual(0, 1) except OperationalError: - self.assertEqual(1, 1) - - def test_stop_main_thread(self): - self.run_in_docker_scenarios(self._test_stop_main_thread) \ No newline at end of file + self.assertEqual(1, 1) \ No newline at end of file diff --git a/test/authentication_test.py b/test/authentication_test.py index d6ef7c158..4bd747429 100644 --- a/test/authentication_test.py +++ b/test/authentication_test.py @@ -6,7 +6,7 @@ from proxysql_base_test import ProxySQLBaseTest class AuthenticationTest(ProxySQLBaseTest): - def _test_existing_user_with_correct_password_works(self): + def test_existing_user_with_correct_password_works(self): version1 = self.run_query_mysql( "SELECT @@version_comment LIMIT 1", "test", return_result=True, @@ -19,10 +19,7 @@ class AuthenticationTest(ProxySQLBaseTest): self.assertEqual(version1, version2) - def test_existing_user_with_correct_password_works(self): - self.run_in_docker_scenarios(self._test_existing_user_with_correct_password_works) - - def _test_existing_user_with_correct_password_but_not_registerd_within_proxysql_does_not_work(self): + def test_existing_user_with_correct_password_but_not_registerd_within_proxysql_does_not_work(self): try: self.run_query_proxysql("SELECT @@version_comment LIMIT 1", "test", return_result=True, @@ -33,10 +30,7 @@ class AuthenticationTest(ProxySQLBaseTest): except OperationalError: self.assertEqual(1, 1) - def test_existing_user_with_correct_password_but_not_registerd_within_proxysql_does_not_work(self): - self.run_in_docker_scenarios(self._test_existing_user_with_correct_password_works) - - def _test_existing_user_with_incorrect_password_does_not_work(self): + def test_existing_user_with_incorrect_password_does_not_work(self): try: self.run_query_proxysql("SELECT @@version_comment LIMIT 1", "test", return_result=True, @@ -47,17 +41,11 @@ class AuthenticationTest(ProxySQLBaseTest): except OperationalError: self.assertEqual(1, 1) - def test_existing_user_with_incorrect_password_does_not_work(self): - self.run_in_docker_scenarios(self._test_existing_user_with_incorrect_password_does_not_work) - - def _test_inexisting_user_with_random_password_does_not_work(self): + def test_inexisting_user_with_random_password_does_not_work(self): try: self.run_query_proxysql("SELECT @@version_comment LIMIT 1", "test", return_result=True, username="johnny", password="randomdoe") self.assertEqual(1, 0) except OperationalError: - self.assertEqual(1, 1) - - def test_inexisting_user_with_random_password_does_not_work(self): - self.run_in_docker_scenarios(self._test_inexisting_user_with_random_password_does_not_work) \ No newline at end of file + self.assertEqual(1, 1) \ No newline at end of file diff --git a/test/one_backend_test.py b/test/one_backend_test.py index af02d7e25..643a3d016 100644 --- a/test/one_backend_test.py +++ b/test/one_backend_test.py @@ -4,11 +4,8 @@ from proxysql_base_test import ProxySQLBaseTest class OneBackendTest(ProxySQLBaseTest): - def _test_select_strings_returns_correct_result(self): + def test_select_strings_returns_correct_result(self): rows = self.run_query_proxysql("SELECT * FROM strings", "test") self.assertEqual(set([row[0] for row in rows]), - set(['a', 'ab', 'abc', 'abcd'])) - - def test_select_strings_returns_correct_result(self): - self.run_in_docker_scenarios(self._test_select_strings_returns_correct_result) \ No newline at end of file + set(['a', 'ab', 'abc', 'abcd'])) \ No newline at end of file diff --git a/test/replication_topology_awareness_test.py b/test/replication_topology_awareness_test.py index 97134b47a..f7bac7d77 100644 --- a/test/replication_topology_awareness_test.py +++ b/test/replication_topology_awareness_test.py @@ -6,6 +6,7 @@ import time from proxysql_base_test import ProxySQLBaseTest +""" class ReplicationTopologyAwareness(ProxySQLBaseTest): def _test_insert_sent_through_proxysql_is_visible_in_slave_servers(self): @@ -177,4 +178,5 @@ class ReplicationTopologyAwareness(ProxySQLBaseTest): # The old master, and the other slaves should still be in the slave hostgroup for ip in slave_ips: - self.assertEqual(hostgroups[ip], 1) \ No newline at end of file + self.assertEqual(hostgroups[ip], 1) +""" \ No newline at end of file diff --git a/test/sysbench_test.py b/test/sysbench_test.py index 2bef5762b..168576238 100644 --- a/test/sysbench_test.py +++ b/test/sysbench_test.py @@ -2,8 +2,5 @@ from proxysql_base_test import ProxySQLBaseTest class SysBenchTest(ProxySQLBaseTest): - def _test_proxy_doesnt_crash_under_mild_sysbench_load(self): - self.run_sysbench_proxysql() - def test_proxy_doesnt_crash_under_mild_sysbench_load(self): - self.run_in_docker_scenarios(self._test_proxy_doesnt_crash_under_mild_sysbench_load) \ No newline at end of file + self.run_sysbench_proxysql() \ No newline at end of file