def test_change_log_messages(
    containers,
    rbrsource,
    create_table_query,
    schematizer,
    namespace,
    source,
    rbr_source_session,
    gtid_enabled
):

    if not gtid_enabled:
        increment_heartbeat(containers, rbrsource)

    execute_query_get_one_row(
        containers,
        rbrsource,
        create_table_query.format(table_name=source)
    )

    BasicModel = _generate_basic_model(source)
    model_1 = BasicModel(id=1, name='insert')
    model_2 = BasicModel(id=2, name='insert')
    rbr_source_session.add(model_1)
    rbr_source_session.add(model_2)
    rbr_source_session.commit()
    model_1.name = 'update'
    rbr_source_session.delete(model_2)
    rbr_source_session.commit()

    messages = _fetch_messages(
        containers,
        schematizer,
        namespace,
        source,
        4
    )

    expected_messages = [
        {
            'message_type': MessageType.create,
            'payload_data': {'id': 1, 'table_name': source, 'table_schema': 'yelp'}
        },
        {
            'message_type': MessageType.create,
            'payload_data': {'id': 2, 'table_name': source, 'table_schema': 'yelp'}
        },
        {
            'message_type': MessageType.update,
            'payload_data': {'id': 1, 'table_name': source, 'table_schema': 'yelp'},
            'previous_payload_data': {'id': 1, 'table_name': source, 'table_schema': 'yelp'}
        },
        {
            'message_type': MessageType.delete,
            'payload_data': {'id': 2, 'table_name': source, 'table_schema': 'yelp'}
        },
    ]
    _verify_messages(messages, expected_messages)
    def test_basic_table(self, containers, replhandler, rbrsource,
                         create_table_query, namespace, schematizer,
                         rbr_source_session, gtid_enabled):
        if not gtid_enabled:
            increment_heartbeat(containers, rbrsource)

        source = "{0}_basic_table".format(replhandler)
        execute_query_get_one_row(containers, rbrsource,
                                  create_table_query.format(table_name=source))

        BasicModel = _generate_basic_model(source)
        model_1 = BasicModel(id=1, name='insert')
        model_2 = BasicModel(id=2, name='insert')
        rbr_source_session.add(model_1)
        rbr_source_session.add(model_2)
        rbr_source_session.commit()
        model_1.name = 'update'
        rbr_source_session.delete(model_2)
        rbr_source_session.commit()

        messages = _fetch_messages(containers, schematizer, namespace, source,
                                   4)
        expected_messages = [
            {
                'message_type': MessageType.create,
                'payload_data': {
                    'id': 1,
                    'name': 'insert'
                }
            },
            {
                'message_type': MessageType.create,
                'payload_data': {
                    'id': 2,
                    'name': 'insert'
                }
            },
            {
                'message_type': MessageType.update,
                'payload_data': {
                    'id': 1,
                    'name': 'update'
                },
                'previous_payload_data': {
                    'id': 1,
                    'name': 'insert'
                }
            },
            {
                'message_type': MessageType.delete,
                'payload_data': {
                    'id': 2,
                    'name': 'insert'
                }
            },
        ]
        _verify_messages(messages, expected_messages)
    def test_complex_table(self, containers, rbrsource, complex_table_name,
                           ComplexModel, actual_complex_data,
                           expected_complex_data, schematizer, namespace,
                           rbr_source_session, gtid_enabled):
        if not gtid_enabled:
            increment_heartbeat(containers, rbrsource)

        complex_instance = ComplexModel(**actual_complex_data)
        rbr_source_session.add(complex_instance)
        rbr_source_session.commit()
        messages = _fetch_messages(containers, schematizer, namespace,
                                   complex_table_name, 1)
        expected_messages = [
            {
                'message_type': MessageType.create,
                'payload_data': expected_complex_data
            },
        ]

        _verify_messages(messages, expected_messages)
    def test_table_with_contains_pii(self, containers, replhandler, rbrsource,
                                     create_table_query, namespace,
                                     schematizer, rbr_source_session,
                                     gtid_enabled):
        with reconfigure(encryption_type='AES_MODE_CBC-1',
                         key_location='acceptance/configs/data_pipeline/'):
            if not gtid_enabled:
                increment_heartbeat(containers, rbrsource)

            source = "{}_secret_table".format(replhandler)
            execute_query_get_one_row(
                containers, rbrsource,
                create_table_query.format(table_name=source))

            BasicModel = _generate_basic_model(source)
            model_1 = BasicModel(id=1, name='insert')
            model_2 = BasicModel(id=2, name='insert')
            rbr_source_session.add(model_1)
            rbr_source_session.add(model_2)
            rbr_source_session.commit()

            messages = _fetch_messages(containers, schematizer, namespace,
                                       source, 2)
            expected_messages = [{
                'message_type': MessageType.create,
                'payload_data': {
                    'id': 1,
                    'name': 'insert'
                }
            }, {
                'message_type': MessageType.create,
                'payload_data': {
                    'id': 2,
                    'name': 'insert'
                }
            }]
            _verify_messages(messages, expected_messages)
Example #5
0
    def test_processing_table_rename(
        self,
        containers_without_repl_handler,
        rbrsource,
        schematizer,
        schematracker,
        namespace,
        start_service,
        gtid_enabled
    ):
        """
        This test verifies that the service handles table renames.
        """
        table_name_one = "hogwarts_{r}".format(r=self.get_random_string())
        table_name_two = "durmstrang_{r}".format(r=self.get_random_string())
        create_table_query = """
        CREATE TABLE {table_name}
        (
            `name` VARCHAR(255) NOT NULL PRIMARY KEY,
            `house` VARCHAR(255) NOT NULL
        )"""
        insert_query = """
        INSERT INTO {table} VALUES ( "{one}", "{two}" )
        """
        change_table_name_query = """
        RENAME TABLE {old} TO {new}
        """
        if not gtid_enabled:
            increment_heartbeat(containers_without_repl_handler, rbrsource)
        create_query = create_table_query.format(table_name=table_name_one)
        rename_query = change_table_name_query.format(
            old=table_name_one,
            new=table_name_two
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            create_query
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            insert_query.format(
                table=table_name_one,
                one='Cedric Diggory',
                two='Hufflepuff'
            )
        )

        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            insert_query.format(
                table=table_name_one,
                one='Hannah Abbott',
                two='Hufflepuff'
            )
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            rename_query
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            insert_query.format(
                table=table_name_two,
                one='Viktor Krum',
                two='Durmstrang'
            )
        )

        start_service(
            resume_stream=True,
            num_of_queries_to_process=5,
            end_time=30,
            is_schema_event_helper_enabled=False,
            num_of_schema_events=100,
        )
        show_query = "SHOW CREATE TABLE {name}"
        source_schema = execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            show_query.format(name=table_name_two)
        )
        tracker_schema = execute_query_get_one_row(
            containers_without_repl_handler,
            schematracker,
            show_query.format(name=table_name_two)
        )
        assert source_schema == tracker_schema

        messages_two = _fetch_messages(
            containers_without_repl_handler,
            schematizer,
            namespace,
            table_name_two,
            1
        )

        messages_one = _fetch_messages(
            containers_without_repl_handler,
            schematizer,
            namespace,
            table_name_one,
            2
        )

        expected_messages_one = [
            {
                'message_type': MessageType.create,
                'payload_data': {'name': 'Cedric Diggory',
                                 'house': 'Hufflepuff'}
            },
            {
                'message_type': MessageType.create,
                'payload_data': {'name': 'Hannah Abbott', 'house': 'Hufflepuff'}
            }
        ]
        _verify_messages(messages_one, expected_messages_one)

        expected_messages_two = [
            {
                'message_type': MessageType.create,
                'payload_data': {'name': 'Viktor Krum', 'house': 'Durmstrang'}
            }
        ]
        _verify_messages(messages_two, expected_messages_two)
Example #6
0
    def test_unclean_shutdown_schema_event(
        self,
        containers_without_repl_handler,
        rbrsource,
        schematracker,
        schematizer,
        namespace,
        start_service,
        gtid_enabled
    ):
        """This tests the recovery of the service if it fails when executing an
        schema event.
        A failure is triggered intentionally when an alter table to add column
        event is being handled. The test asserts that after the service restarts
        it processes that event again and processes the schema event. It also
        asserts that it doesn't miss out on any event and doesn't process an
        event more than once.
        """
        table_name = "ministry_of_magic_{r}".format(r=self.get_random_string())
        create_query = """
        CREATE TABLE {table}
        (name VARCHAR(255) PRIMARY KEY, dept VARCHAR(255))
        """
        insert_query_one = """
        INSERT INTO {table} VALUES
        ("{one}", "{two}")
        """
        add_col_query = """
        ALTER TABLE {table}
        ADD floor INT(11)
        """
        insert_query_two = """
        INSERT INTO {table} VALUES
        ("{one}", "{two}", "{three}")
        """

        if not gtid_enabled:
            increment_heartbeat(containers_without_repl_handler, rbrsource)
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            create_query.format(table=table_name)
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            insert_query_one.format(
                table=table_name,
                one='Rufus Scrimgeour',
                two='Minister'
            )
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            add_col_query.format(
                table=table_name
            )
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            insert_query_two.format(
                table=table_name,
                one='Kingsley Shacklebolt',
                two='Auror',
                three=2
            )
        )

        start_service(
            resume_stream=True,
            num_of_queries_to_process=3,
            end_time=30,
            is_schema_event_helper_enabled=True,
            num_of_schema_events=0,
        )

        execute_query_get_one_row(
            containers_without_repl_handler,
            schematracker,
            "DROP TABLE {table}".format(table=table_name)
        )

        execute_query_get_one_row(
            containers_without_repl_handler,
            schematracker,
            create_query.format(table=table_name)
        )

        tracker_create_table = execute_query_get_all_rows(
            containers_without_repl_handler,
            schematracker,
            "SHOW CREATE TABLE {table}".format(table=table_name)
        )[0]['Create Table']

        source_create_table = execute_query_get_all_rows(
            containers_without_repl_handler,
            rbrsource,
            "SHOW CREATE TABLE {table}".format(table=table_name)
        )[0]['Create Table']

        assert source_create_table != tracker_create_table

        start_service(
            resume_stream=True,
            num_of_queries_to_process=2,
            end_time=30,
            is_schema_event_helper_enabled=False,
            num_of_schema_events=100,
        )

        tracker_create_table = execute_query_get_all_rows(
            containers_without_repl_handler,
            schematracker,
            "SHOW CREATE TABLE {table}".format(table=table_name)
        )[0]['Create Table']

        assert source_create_table == tracker_create_table

        _fetch_messages(
            containers_without_repl_handler,
            schematizer,
            namespace,
            table_name,
            2
        )
Example #7
0
    def test_shutdown_processing_events_publishes_events_only_once(
        self,
        containers_without_repl_handler,
        rbrsource,
        schematizer,
        namespace,
        start_service,
        gtid_enabled
    ):
        """Tests the guarantee that the service provides about publishing every
        MySQL change only once. A few queries are executed on the source
        database and the service is started. The service is asked to halt after
        processing a subset of events and then restart and pick up from where it
        left off.
        """
        table_name = "coursework_{r}".format(r=self.get_random_string())
        create_query = """
        CREATE TABLE {table}
        (name VARCHAR(255) PRIMARY KEY, teacher VARCHAR(255))
        """
        insert_query_one = """
        INSERT INTO {table} VALUES
        ("{one}", "{two}")
        """
        update_query = """
        UPDATE {table}
        SET teacher="{one}"
        WHERE name="{two}"
        """
        if not gtid_enabled:
            increment_heartbeat(containers_without_repl_handler, rbrsource)
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            create_query.format(table=table_name)
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            insert_query_one.format(
                table=table_name,
                one='potions',
                two='Severus Snape'
            )
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            insert_query_one.format(
                table=table_name,
                one='care of magical creatures',
                two='Rubeus Hagrid'
            )
        )
        execute_query_get_one_row(
            containers_without_repl_handler,
            rbrsource,
            update_query.format(
                table=table_name,
                one='Grubbly Plank',
                two='care of magical creatures'
            )
        )

        start_service(
            resume_stream=False,
            num_of_queries_to_process=2,
            end_time=30,
            is_schema_event_helper_enabled=False,
            num_of_schema_events=100,
        )

        messages_one = _fetch_messages(
            containers_without_repl_handler,
            schematizer,
            namespace,
            table_name,
            1
        )

        expected_messages_one = [
            {
                'message_type': MessageType.create,
                'payload_data': {'name': 'potions', 'teacher': 'Severus Snape'}
            },
        ]
        _verify_messages(messages_one, expected_messages_one)

        start_service(
            resume_stream=True,
            num_of_queries_to_process=2,
            end_time=30,
            is_schema_event_helper_enabled=False,
            num_of_schema_events=100,
        )

        messages_two = _fetch_messages(
            containers_without_repl_handler,
            schematizer,
            namespace,
            table_name,
            3
        )
        messages_two = messages_two[1:]

        expected_messages_two = [
            {
                'message_type': MessageType.create,
                'payload_data': {'name': 'care of magical creatures',
                                 'teacher': 'Rubeus Hagrid'}
            },
            {
                'message_type': MessageType.update,
                'payload_data': {'name': 'care of magical creatures',
                                 'teacher': 'Grubbly Plank'},
                'previous_payload_data': {'name': 'care of magical creatures',
                                          'teacher': 'Rubeus Hagrid'}
            }
        ]

        _verify_messages(messages_two, expected_messages_two)