def update_job()

in dyno/app/api/control.py [0:0]


def update_job() -> dict:
    """
    Updates a job with a new configuration.

    We try to reconstruct the existing job by querying
    the status dictionary and then we update as necessary.
    Then we kill the job and start it again with the new
    values.

    Exposed via HTTP at /api/update

    Supported HTTP methods: POST

    Parameters
    ----------
    job : str
        The name of the job to modify. (Required)

    workers : str
        The number of workers the load generator should use. (Optional)

    error_weight : str
        The relative "weight" of errors. Higher number result in the load
        generator choosing to hit pages known to produce errors a higher
        percentage of the time.

        This number is entirely arbitrary and is only relative to statically
        configured weights in the scenario file itself. (Optional)

    app_latency_weight : str
        In the case of the `dyno` scenario, an `app_latency_weight`
        parameter can be passed which increases the rate at which a given
        label is accessed.

        Does NOT work with scenarios other than `dyno`! (Optional)

    app_latency_label : str
        Used in conjunction with `app_latency_eight` to specify a label which
        should be hit at a higher or lower rate, which is controlled by
        the `app_latency_weight` parameter.

    app_latency_lower_bound : int
        The lower bound of latency which should be applied to requests which
        hit the delayed endpoint

    app_latency_upper_bound : int
        The upper bound of latency which should be applied to requests which
        hit the delayed endpoint

    Returns
    -------
    An empty dictionary on success

    Examples
    --------
    Sample JSON payload to send to this endpoint:
    > {"job":"python","workers":2.1}

    Note
    ----
    Paramaters are received via JSON in a Flask request object. They
    may not be passed directly to this function.
    """
    r = request.get_json() or {}
    job = r.get('job')

    if job is None:
        return "Must supply job", 400
    if job not in JOB_STATUS:
        # TODO refactor to single source of truth
        JOB_STATUS[job] = {
                'duration': "31536000",
                'delay': "0.600",
                "scenario": "molotov_scenarios",
                "workers": r.get('workers', "3"),
                "error_weight": r.get('error_weight', "0"),
                "app_latency_weight": r.get('app_latency_weight', 0),
                "app_latency_label": r.get("app_latency_label", "dyno_app_latency"),  # noqa
                "app_latency_lower_bound": r.get("app_latency_lower_bound", 1),
                "app_latency_upper_bound": r.get("app_latency_upper_bound", 1000)  # noqa
                }
        return {}

    config = JOB_STATUS[job]

    if 'workers' in r:
        config['workers'] = r['workers']
    if 'error_weight' in r:
        config['error_weight'] = r['error_weight']
    if 'app_latency_weight' in r:
        config['app_latency_weight'] = r['app_latency_weight']
    if 'app_latency_label' in r:
        config['app_latency_label'] = r['app_latency_label']
    if 'app_latency_lower_bound' in r:
        config['app_latency_lower_bound'] = r['app_latency_lower_bound']
    if 'app_latency_upper_bound' in r:
        config['app_latency_upper_bound'] = r['app_latency_upper_bound']
    _stop_job(job)

    if DEBUG:
        print('Relaunching job: ', config)
    _launch_job(job, config)
    _update_status(job, config)
    return {}