def test_configure_mysql_users_fail(self, _run_mysqlcli_script): """Test failure to configure the MySQL users.""" _run_mysqlcli_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLConfigureMySQLUsersError): self.mysql.configure_mysql_users()
def test_remove_primary_instance_error_releasing_lock( self, _release_lock, _run_mysqlsh_script, _get_cluster_member_addresses, _acquire_lock, _get_cluster_primary_address, ): """Test an issue releasing locks while running the remove_instance() method.""" _get_cluster_primary_address.side_effect = ["1.1.1.1", "2.2.2.2"] _acquire_lock.return_value = True _get_cluster_member_addresses.return_value = ("2.2.2.2", True) _release_lock.side_effect = MySQLClientError("Error on subprocess") with self.assertRaises(MySQLRemoveInstanceError): self.mysql.remove_instance("mysql-0") expected_remove_instance_commands = "\n".join([ "shell.connect('clusteradmin:[email protected]')", "cluster = dba.get_cluster('test_cluster')", "number_cluster_members = len(cluster.status()['defaultReplicaSet']['topology'])", 'cluster.remove_instance(\'[email protected]\', {"password": "******", "force": "true"}) if number_cluster_members > 1 else cluster.dissolve({"force": "true"})', ]) self.assertEqual(_get_cluster_primary_address.call_count, 2) _acquire_lock.assert_called_once_with("1.1.1.1", "mysql-0", "unit-teardown") _get_cluster_member_addresses.assert_called_once_with( exclude_unit_labels=["mysql-0"]) _run_mysqlsh_script.assert_called_once_with( expected_remove_instance_commands) _release_lock.assert_called_once_with("2.2.2.2", "mysql-0", "unit-teardown")
def test_is_instance_in_cluster_exception(self, _run_mysqlsh_script): """Test an exception executing is_instance_in_cluster() method.""" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") result = self.mysql.is_instance_in_cluster("mysql-0") self.assertFalse(result)
def test_add_instance_to_cluster_exception(self, _run_mysqlsh_script): """Test exceptions raised while running add_instance_to_cluster.""" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLAddInstanceToClusterError): self.mysql.add_instance_to_cluster("127.0.0.2", "mysql-1")
def test_delete_users_for_unit_failure(self, _run_mysqlcli_script): """Test failure to delete users for a unit.""" _run_mysqlcli_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLDeleteUsersForUnitError): self.mysql.delete_users_for_unit("app/0")
def test_create_cluster_exceptions(self, _run_mysqlsh_script): """Test exceptions raised while running create_cluster.""" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLCreateClusterError): self.mysql.create_cluster("mysql-0")
def test_does_mysql_user_exist_failure(self, _run_mysqlcli_script): """Test failure in execution of does_mysql_user_exist.""" _run_mysqlcli_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLCheckUserExistenceError): self.mysql.does_mysql_user_exist("test_username", "1.1.1.1")
def _run_mysqlcli_script(self, script: str, user: str = "root", password: str = None) -> str: """Execute a MySQL CLI script. Execute SQL script as instance root user. Raises CalledProcessError if the script gets a non-zero return code. Args: script: raw SQL script string user: (optional) user to invoke the mysql cli script with (default is "root") password: (optional) password to invoke the mysql cli script with """ command = [ "mysql", "-u", user, "--protocol=SOCKET", "--socket=/var/run/mysqld/mysqld.sock", "-e", script, ] if password: command.append(f"--password={password}") try: return subprocess.check_output( command, stderr=subprocess.PIPE).decode("utf-8") except subprocess.CalledProcessError as e: raise MySQLClientError(e.stderr)
def _run_mysqlsh_script(self, script: str) -> str: """Execute a MySQL shell script. Raises CalledProcessError if the script gets a non-zero return code. Args: script: Mysqlsh script string Returns: String representing the output of the mysqlsh command """ # Use the self.mysqlsh_common_dir for the confined mysql-shell snap. with tempfile.NamedTemporaryFile( mode="w", dir=MYSQL_SHELL_COMMON_DIRECTORY) as _file: _file.write(script) _file.flush() # Specify python as this is not the default in the deb version # of the mysql-shell snap command = [ MySQL.get_mysqlsh_bin(), "--no-wizard", "--python", "-f", _file.name ] try: return subprocess.check_output( command, stderr=subprocess.PIPE).decode("utf-8") except subprocess.CalledProcessError as e: raise MySQLClientError(e.stderr)
def test_delete_user_for_relation_failure(self, _run_mysqlsh_script, _get_cluster_primary_address): """Test failure to delete users for relation.""" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLDeleteUserForRelationError): self.mysql.delete_user_for_relation(40)
def test_get_cluster_status_failure(self, _run_mysqlsh_script, _json_loads): """Test an exception executing get_cluster_status() method.""" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") self.mysql.get_cluster_status() _json_loads.assert_not_called()
def test_initialize_juju_units_operations_table_exception( self, _run_mysqlcli_script): """Test an exception initialization of the mysql.juju_units_operations table.""" _run_mysqlcli_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLInitializeJujuOperationsTableError): self.mysql.initialize_juju_units_operations_table()
def test_configure_mysqlrouter_user_failure(self, _run_mysqlsh_script, _get_cluster_primary_address): """Test failure to configure the MySQLRouter user.""" _get_cluster_primary_address.return_value = "2.2.2.2" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLConfigureRouterUserError): self.mysql.configure_mysqlrouter_user("test_username", "test_password", "1.1.1.1", "app/0")
def test_create_application_database_and_scoped_user_failure( self, _run_mysqlsh_script, _get_cluster_primary_address): """Test failure to create application database and scoped user.""" _get_cluster_primary_address.return_value = "2.2.2.2" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises( MySQLCreateApplicationDatabaseAndScopedUserError): self.mysql.create_application_database_and_scoped_user( "test_database", "test_username", "test_password", "1.1.1.1", "app/.0")
def test_configure_instance_exceptions(self, _wait_until_mysql_connection, _run_mysqlsh_script): """Test exceptions raise while running configure_instance.""" # Test an issue with _run_mysqlsh_script _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLConfigureInstanceError): self.mysql.configure_instance() _wait_until_mysql_connection.assert_not_called() # Reset mocks _run_mysqlsh_script.reset_mock() _wait_until_mysql_connection.reset_mock() # Test an issue with _wait_until_mysql_connection _wait_until_mysql_connection.side_effect = MySQLClientError( "Error on subprocess") with self.assertRaises(MySQLConfigureInstanceError): self.mysql.configure_instance() _run_mysqlsh_script.assert_called_once()
def test_is_instance_configured_for_innodb_exceptions( self, _run_mysqlsh_script): """Test an exception while calling the is_instance_configured_for_innodb method.""" _run_mysqlsh_script.side_effect = MySQLClientError( "Error on subprocess") check_instance_configuration_commands = ( "shell.connect('clusteradmin:[email protected]')", "instance_configured = dba.check_instance_configuration()['status'] == 'ok'", 'print("INSTANCE_CONFIGURED" if instance_configured else "INSTANCE_NOT_CONFIGURED")', ) is_instance_configured = self.mysql.is_instance_configured_for_innodb( "127.0.0.2", "mysql-1") _run_mysqlsh_script.assert_called_once_with( "\n".join(check_instance_configuration_commands)) self.assertFalse(is_instance_configured)