Пример #1
0
def create_label(state_machine_name, label_name):
    """
    Create a label with a given metadata, and start it in the state machine.

    Returns:
    - 201 Created: if the label is successfully created and started.
    - 409 Conflict: if the label already exists in the state machine.
    - 404 Not Found: if the state machine does not exist.
    - 400 Bad Request: if the request body is not a valid metadata.

    Successful return codes return the full created metadata for the label.
    """
    app = server.config.app
    label = LabelRef(label_name, state_machine_name)
    data = request.get_json()

    try:
        initial_metadata = data['metadata']
    except KeyError:
        abort(400, "No metadata given")

    try:
        initial_state_name = \
            app.config.state_machines[state_machine_name].states[0].name
        metadata = state_machine.create_label(app, label, initial_metadata)
        return jsonify(metadata=metadata, state=initial_state_name), 201
    except LookupError:
        msg = f"State machine '{state_machine_name}' does not exist"
        abort(404, msg)
    except LabelAlreadyExists:
        msg = f"Label {label_name} already exists in '{state_machine_name}'"
        abort(409, msg)
Пример #2
0
def test_continues_after_time_since_entering_gate(app, current_state):
    label = LabelRef('foo', 'test_machine_timing')
    gate = app.config.state_machines['test_machine_timing'].states[0]

    with freeze_time('2018-01-24 12:00:00'), app.new_session():
        state_machine.create_label(
            app,
            label,
            {},
        )

    # 1 day later, not enough to progress
    with freeze_time('2018-01-25 12:00:00'), app.new_session():
        process_gate(
            app=app,
            state=gate,
            state_machine=state_machine,
            label=label,
        )

    assert current_state(label) == 'start'

    # 2 days later
    with freeze_time('2018-01-26 12:00:00'), app.new_session():
        process_gate(
            app=app,
            state=gate,
            state_machine=state_machine,
            label=label,
        )

    assert current_state(label) == 'end'
Пример #3
0
def get_label(state_machine_name, label_name):
    """
    Get a label within a given state machine.

    Returns:
    - 200 Ok: if the label is exists.
    - 404 Not Found: if the state machine or label does not exist.
    - 410 Gone: if the label once existed but has since been deleted.

    Successful return codes return the full metadata for the label.
    """
    app = server.config.app
    label = LabelRef(label_name, state_machine_name)

    try:
        metadata = state_machine.get_label_metadata(app, label)
    except UnknownLabel as e:
        abort(
            410 if e.deleted else 404,
            f"Label {label.name} in state machine '{label.state_machine}' "
            f"does not exist.",
        )
    except UnknownStateMachine:
        abort(404, f"State machine '{label.state_machine}' does not exist.")

    state = state_machine.get_label_state(app, label)
    return jsonify(metadata=metadata, state=state.name)
Пример #4
0
def test_maintains_updated_field_on_label(app, mock_test_feed):
    label = LabelRef('foo', 'test_machine')

    with mock_test_feed(), app.new_session():
        state_machine.create_label(
            app,
            label,
            {},
        )

        first_updated = app.session.query(Label.updated, ).filter_by(
            name=label.name,
            state_machine=label.state_machine,
        ).scalar()

    with mock_test_feed(), app.new_session():
        state_machine.update_metadata_for_label(
            app,
            label,
            {'foo': 'bar'},
        )

        second_updated = app.session.query(Label.updated, ).filter_by(
            name=label.name,
            state_machine=label.state_machine,
        ).scalar()

    assert second_updated > first_updated
Пример #5
0
def test_stays_in_gate_if_gate_processing_fails(app, mock_test_feed,
                                                current_state):
    label = LabelRef('foo', 'test_machine')

    with mock_test_feed(), app.new_session():
        state_machine.create_label(
            app,
            label,
            {},
        )

    assert current_state(label) == 'start'

    with mock_test_feed(), mock.patch(
            'routemaster.context.Context._pre_warm_feeds',
            side_effect=RequestException,
    ), app.new_session():
        state_machine.update_metadata_for_label(
            app,
            label,
            {'should_progress': True},
        )

    assert metadata_triggers_processed(app, label) is False
    assert current_state(label) == 'start'
Пример #6
0
def test_label_get_state(app, mock_test_feed):
    label = LabelRef('foo', 'test_machine')
    with mock_test_feed(), app.new_session():
        state_machine.create_label(
            app,
            label,
            {'foo': 'bar'},
        )

    with app.new_session():
        assert state_machine.get_label_state(app, label).name == 'start'
Пример #7
0
def test_delete_label_only_deletes_target_label(app, assert_history,
                                                mock_test_feed):
    label_foo = LabelRef('foo', 'test_machine')
    label_bar = LabelRef('bar', 'test_machine')

    with mock_test_feed(), app.new_session():
        state_machine.create_label(app, label_foo, {})
        state_machine.create_label(app, label_bar, {})
        state_machine.delete_label(app, label_foo)

    with app.new_session():
        with pytest.raises(DeletedLabel):
            state_machine.get_label_metadata(
                app,
                label_foo,
            )

        state_machine.get_label_metadata(
            app,
            label_bar,
        )
Пример #8
0
def test_state_machine_progresses_automatically(app, mock_webhook,
                                                mock_test_feed, current_state):
    label = LabelRef('foo', 'test_machine')

    with mock_webhook() as webhook, mock_test_feed(), app.new_session():
        state_machine.create_label(
            app,
            label,
            {'should_progress': True},
        )
        webhook.assert_called_once()

    assert current_state(label) == 'end'
Пример #9
0
def test_state_machine_simple(app, mock_test_feed):
    label = LabelRef('foo', 'test_machine')

    with mock_test_feed(), app.new_session():
        state_machine.create_label(
            app,
            label,
            {},
        )
        state_machine.update_metadata_for_label(
            app,
            label,
            {'foo': 'bar'},
        )

    with app.new_session():
        assert state_machine.get_label_metadata(app, label) == {'foo': 'bar'}
Пример #10
0
def test_delete_label(app, assert_history, mock_test_feed):
    label_foo = LabelRef('foo', 'test_machine')

    with mock_test_feed(), app.new_session():
        state_machine.create_label(app, label_foo, {})
        state_machine.delete_label(app, label_foo)

    with app.new_session():
        with pytest.raises(DeletedLabel):
            state_machine.get_label_metadata(
                app,
                label_foo,
            )

    assert_history([
        (None, 'start'),
        ('start', None),
    ])
Пример #11
0
def delete_label(state_machine_name, label_name):
    """
    Delete a label in a state machine.

    Marks a label as deleted, but does not remove it from the database.
    Deleted labels cannot be updated and will not move state.

    Returns:
    - 204 No content: if the label is successfully deleted (or did not exist).
    - 404 Not Found: if the state machine does not exist.
    """
    app = server.config.app
    label = LabelRef(label_name, state_machine_name)

    try:
        state_machine.delete_label(app, label)
    except UnknownStateMachine:
        msg = f"State machine '{state_machine_name}' does not exist"
        abort(404, msg)

    return '', 204
Пример #12
0
def test_state_machine_does_not_progress_when_not_eligible(
        app, mock_test_feed, current_state):
    label = LabelRef('foo', 'test_machine')

    with mock_test_feed(), app.new_session():
        state_machine.create_label(
            app,
            label,
            {},
        )

    assert current_state(label) == 'start'

    with mock_test_feed(), app.new_session():
        state_machine.update_metadata_for_label(
            app,
            label,
            {'should_progress': False},
        )

    assert current_state(label) == 'start'
Пример #13
0
def update_label(state_machine_name, label_name):
    """
    Update a label in a state machine.

    Triggering progression if necessary according to the state machine
    configuration. Updates are _merged_ with existing metadata.

    Returns:
    - 200 Ok: if the label is successfully updated.
    - 400 Bad Request: if the request body is not a valid metadata.
    - 404 Not Found: if the state machine or label does not exist.
    - 410 Gone: if the label once existed but has since been deleted.

    Successful return codes return the full new metadata for a label.
    """
    app = server.config.app
    label = LabelRef(label_name, state_machine_name)

    try:
        patch_metadata = request.get_json()['metadata']
    except KeyError:
        abort(400, "No new metadata")

    try:
        new_metadata = state_machine.update_metadata_for_label(
            app,
            label,
            patch_metadata,
        )
        state = state_machine.get_label_state(app, label)
        return jsonify(metadata=new_metadata, state=state.name)
    except UnknownStateMachine:
        msg = f"State machine '{state_machine_name}' does not exist"
        abort(404, msg)
    except UnknownLabel as e:
        abort(
            410 if e.deleted else 404,
            f"Label {label_name} does not exist in state machine "
            f"'{state_machine_name}'.",
        )
Пример #14
0
def test_state_machine_progresses_on_update(app, mock_webhook, mock_test_feed,
                                            current_state):
    label = LabelRef('foo', 'test_machine')

    with mock_test_feed(), app.new_session():
        state_machine.create_label(
            app,
            label,
            {},
        )

    assert current_state(label) == 'start'

    with mock_webhook() as webhook, mock_test_feed(), app.new_session():
        state_machine.update_metadata_for_label(
            app,
            label,
            {'should_progress': True},
        )
        webhook.assert_called_once()

    assert metadata_triggers_processed(app, label) is True
    assert current_state(label) == 'end'
Пример #15
0
def test_update_metadata_for_label_raises_for_unknown_state_machine(app):
    label = LabelRef('foo', 'nonexistent_machine')
    with pytest.raises(UnknownStateMachine), app.new_session():
        state_machine.update_metadata_for_label(app, label, {})
Пример #16
0
def test_label_get_state_raises_for_unknown_state_machine(app):
    label = LabelRef('foo', 'unknown_machine')
    with pytest.raises(UnknownStateMachine), app.new_session():
        assert state_machine.get_label_state(app, label)