示例#1
0
def run_experiment(
    experiment: Experiment,
    settings: Settings = None,
    experiment_vars: Dict[str, Any] = None,
    strategy: Strategy = Strategy.DEFAULT,
    schedule: Schedule = None,
    event_handlers: List[RunEventHandler] = None,
) -> Journal:
    """
    Run the given `experiment` method step by step, in the following sequence:
    steady probe, action, close probe.

    Activities can be executed in background when they have the
    `"background"` property set to `true`. In that case, the activity is run in
    a thread. By the end of runs, those threads block until they are all
    complete.

    If the experiment has the `"dry"` property set to `False`, the experiment
    runs without actually executing the activities.

    NOTE: Tricky to make a decision whether we should rollback when exiting
    abnormally (Ctrl-C, SIGTERM...). Afterall, there is a chance we actually
    cannot afford to rollback properly. Better bailing to a conservative
    approach. This means we swallow :exc:`KeyboardInterrupt` and
    :exc:`SystemExit` and do not bubble it back up to the caller. We when were
    interrupted, we set the `interrupted` flag of the result accordingly to
    notify the caller this was indeed not terminated properly.
    """
    with Runner(strategy, schedule) as runner:
        if event_handlers:
            for h in event_handlers:
                runner.register_event_handler(h)
        return runner.run(experiment,
                          settings,
                          experiment_vars=experiment_vars)
示例#2
0
def test_play_rollbacks_on_graceful_exit_with_python_action():
    x = deepcopy(experiments.ExperimentGracefulExitLongPythonCall)
    with Runner(Strategy.DEFAULT) as runner:
        journal = runner.run(x, settings={
            "runtime": {"rollbacks": {"strategy": "always"}}})

        assert journal["status"] == "interrupted"
        assert len(journal["rollbacks"]) == 1
示例#3
0
def test_wait_for_background_activity_on_graceful_exit():
    server = threading.Thread(target=run_http_server_in_background)
    server.start()

    x = deepcopy(experiments.ExperimentGracefulExitLongHTTPCall)
    with Runner(Strategy.DEFAULT) as runner:
        journal = runner.run(x)

        assert journal["status"] == "interrupted"
        assert 3.0 < journal["run"][0]["duration"] < 3.2

    server.join()
示例#4
0
def test_wait_for_background_activity_to_finish_on_graceful_exit():
    def _exit_soon():
        time.sleep(1.5)
        exit_gracefully()
    t = threading.Thread(target=_exit_soon)

    x = deepcopy(experiments.SimpleExperimentWithBackgroundActivity)
    with Runner(Strategy.DEFAULT) as runner:
        t.start()
        journal = runner.run(x)
        assert journal["status"] == "interrupted"
        assert journal["run"][0]["status"] == "succeeded"
示例#5
0
def test_do_not_play_rollbacks_on_graceful_exit_with_python_action():
    server = threading.Thread(target=run_http_server_in_background)
    server.start()

    x = deepcopy(experiments.ExperimentUngracefulExitLongHTTPCall)
    with Runner(Strategy.DEFAULT) as runner:
        journal = runner.run(x, settings={
            "runtime": {"rollbacks": {"strategy": "always"}}})

        assert journal["status"] == "interrupted"
        assert len(journal["rollbacks"]) == 0

    server.join()
示例#6
0
def test_do_not_wait_for_background_activity_on_ungraceful_exit():
    def _exit_soon():
        time.sleep(1.5)
        exit_ungracefully()
    t = threading.Thread(target=_exit_soon)

    x = deepcopy(experiments.SimpleExperimentWithBackgroundActivity)
    with Runner(Strategy.DEFAULT) as runner:
        t.start()
        journal = runner.run(x)
        assert journal["status"] == "interrupted"
        assert journal["run"][0]["status"] == "failed"
        assert "ExperimentExitedException" in journal["run"][0]["exception"][-1]
示例#7
0
def run_verification(experiment: Experiment,
                     settings: Settings = None,
                     experiment_vars: Dict[str, Any] = None,
                     strategy: Strategy = CONTINUOUS,
                     schedule: Schedule = None) -> Journal:
    with Runner(strategy, schedule) as runner:
        runner.register_event_handler(RunEventHandler())
        runner.register_event_handler(
            VerificationRunEventHandler(experiment, settings))

        journal = initialize_run_journal(experiment)
        # TODO: remove with https://github.com/chaosiq/chaosiq-cloud/issues/70
        journal["measurements"] = []

        return runner.run(experiment,
                          settings,
                          journal=journal,
                          experiment_vars=experiment_vars)