diff --git a/test/proxysql_base_test.py b/test/proxysql_base_test.py index 6d2768c59..4332d3a72 100644 --- a/test/proxysql_base_test.py +++ b/test/proxysql_base_test.py @@ -20,6 +20,12 @@ class ProxySQLBaseTest(TestCase): @classmethod def _startup_docker_services(cls): + """Start up all the docker services necessary to start this test. + + They are specified in the docker compose file specified in the variable + cls.DOCKER_COMPOSE_FILE. + """ + # We have to perform docker-compose build + docker-compose up, # instead of just doing the latter because of a bug which will give a # 500 internal error for the Docker bug. When this is fixed, we should @@ -29,11 +35,24 @@ class ProxySQLBaseTest(TestCase): @classmethod def _shutdown_docker_services(cls): + """Shut down all the docker services necessary to start this test. + + They are specified in the docker compose file specified in the variable + cls.DOCKER_COMPOSE_FILE. + """ + subprocess.call(["docker-compose", "stop"], cwd=cls.DOCKER_COMPOSE_FILE) subprocess.call(["docker-compose", "rm", "--force"], cwd=cls.DOCKER_COMPOSE_FILE) @classmethod def _get_proxysql_container(cls): + """Out of all the started docker containers, select the one which + represents the proxy instance. + + Note that this only supports one proxy instance for now. This method + relies on interogating the Docker daemon via its REST API. + """ + containers = Client(**kwargs_from_env()).containers() for container in containers: if 'proxysql' in container['Image']: @@ -41,6 +60,12 @@ class ProxySQLBaseTest(TestCase): @classmethod def _get_mysql_containers(cls): + """Out of all the started docker containers, select the ones which + represent the MySQL backend instances. + + This method relies on interogating the Docker daemon via its REST API. + """ + result = [] containers = Client(**kwargs_from_env()).containers() for container in containers: @@ -50,6 +75,13 @@ class ProxySQLBaseTest(TestCase): @classmethod def _populate_mysql_containers_with_dump(cls): + """Populates the started MySQL backend containers with the specified + SQL dump file. + + The reason for doing this __after__ the containers are started is + because we want to keep them as generic as possible. + """ + mysql_containers = cls._get_mysql_containers() # We have already added the SQL dump to the container by using # the ADD mysql command in the Dockerfile for mysql -- check it @@ -64,15 +96,33 @@ class ProxySQLBaseTest(TestCase): @classmethod def _extract_hostgroup_from_container_name(cls, container_name): + """MySQL backend containers are named using a naming convention: + backendXhostgroupY, where X and Y can be multi-digit numbers. + This extracts the value of the hostgroup from the container name. + + I made this choice because I wasn't able to find another easy way to + associate arbitrary metadata with a Docker container through the + docker compose file. + """ + service_name = container_name.split('_')[1] return int(re.search(r'BACKEND(\d+)HOSTGROUP(\d+)', service_name).group(2)) @classmethod def _extract_port_number_from_uri(cls, uri): + """Given a Docker container URI (exposed as an environment variable by + the host linking mechanism), extract the TCP port number from it.""" return int(uri.split(':')[2]) @classmethod def _get_environment_variables_from_container(cls, container_name): + """Retrieve the environment variables from the given container. + + This is useful because the host linking mechanism will expose + connectivity information to the linked hosts by the use of environment + variables. + """ + output = Client(**kwargs_from_env()).execute(container_name, 'env') result = {} lines = output.split('\n') @@ -86,6 +136,18 @@ class ProxySQLBaseTest(TestCase): @classmethod def _populate_proxy_configuration_with_backends(cls): + """Populate ProxySQL's admin information with the MySQL backends + and their associated hostgroups. + + This is needed because I do not want to hardcode this into the ProxySQL + config file of the test scenario, as it leaves more room for quick + iteration. + + In order to configure ProxySQL with the correct backends, we are using + the MySQL admin interface of ProxySQL, and inserting rows into the + `mysql_servers` table, which contains a list of which servers go into + which hostgroup. + """ proxysql_container = cls._get_proxysql_container() mysql_containers = cls._get_mysql_containers() environment_variables = cls._get_environment_variables_from_container( @@ -113,12 +175,16 @@ class ProxySQLBaseTest(TestCase): @classmethod def setUpClass(cls): + # Always shutdown docker services because the previous test might have + # left them in limbo. cls._shutdown_docker_services() + cls._startup_docker_services() - # TODO(andrei): figure out a more reliable method to wait for - # MySQL to start up within the container. Otherwise, there will be - # an error when we try to initialize the MySQL instance with the dump. + # Sleep for 30 seconds because we want to populate the MySQL containers + # with SQL dumps, but there is a race condition because we do not know + # when the MySQL daemons inside them have actually started or not. + # TODO(andrei): find a better solution time.sleep(30) cls._populate_mysql_containers_with_dump()