Exemple #1
0
    def register(anarchy_run, runtime):
        runner_value = anarchy_run.metadata['labels'].get(runtime.runner_label, None)
        anarchy_subject_name = anarchy_run.subject_name
        anarchy_subject = AnarchySubject.get(anarchy_subject_name, runtime)

        if not anarchy_subject:
            operator_logger.warn(
                'Unable to find AnarchySubject %s for AnarchyRun %s',
                anarchy_subject_name, anarchy_run.name
            )
            return

        if not runner_value or runner_value == 'successful':
            return
        elif runner_value == 'failed':
            anarchy_subject.anarchy_run_update(anarchy_run, runtime)
            last_attempt = anarchy_run.run_post_datetime
            if last_attempt:
                if anarchy_run.failures > 9:
                    retry_delay = timedelta(hours=1)
                else:
                    retry_delay = timedelta(seconds=5 * 2**anarchy_run.failures)
                next_attempt = last_attempt + retry_delay
            else:
                next_attempt = datetime.utcnow()
            anarchy_subject.retry_after = next_attempt
        elif runner_value == 'lost':
            anarchy_subject.anarchy_run_update(anarchy_run, runtime)
            anarchy_subject.put_in_job_queue(runtime)
        elif runner_value == 'pending':
            anarchy_subject.enqueue_anarchy_run(anarchy_run, runtime)
        else:
            anarchy_subject.anarchy_run_update(anarchy_run, runtime)
Exemple #2
0
def patch_or_delete_subject(subject_name):
    anarchy_runner, runner_pod = check_runner_auth(
        flask.request.headers.get('Authorization', ''))
    if not anarchy_runner:
        flask.abort(400)
        return

    if subject_name != runner_pod.metadata.labels.get(runtime.subject_label):
        operator_logger.warning(
            'AnarchyRunner %s Pod %s cannot update AnarchySubject %s!',
            anarchy_runner.name, runner_pod.metadata.name, subject_name)
        flask.abort(400)
        return

    anarchy_subject = AnarchySubject.get(subject_name, runtime)
    if not anarchy_subject:
        operator_logger.warning(
            'AnarchyRunner %s Pod %s attempted %s on deleted AnarchySubject %s!',
            anarchy_runner.name, runner_pod.metadata.name,
            flask.request.method, subject_name)
        flask.abort(400)
        return

    if flask.request.method == 'PATCH':
        if not 'patch' in flask.request.json:
            operator_logger.warning('No patch in AnarchySubject %s post',
                                    subject_name)
            flask.abort(400)
            return
        result = anarchy_subject.patch(flask.request.json['patch'], runtime)
    elif flask.request.method == 'DELETE':
        result = anarchy_subject.delete(
            flask.request.json.get('remove_finalizers', False), runtime)

    return flask.jsonify({'success': True, 'result': result})
Exemple #3
0
def run_subject_action_patch(subject_name, action_name):
    """
    Callback from runner to update AnarchyAction associated with AnarchySubject assigned to runner.

    The only function of this method currently is to pass JSON, `{"successful": true}` or
    `{"failed": true}` to mark the action as finished.
    """
    anarchy_runner, runner_pod = check_runner_auth(
        flask.request.headers.get('Authorization', ''))
    if not anarchy_runner:
        flask.abort(400)

    if not runtime.running_all_in_one \
    and subject_name != runner_pod.metadata.labels.get(runtime.subject_label):
        operator_logger.warning(
            'AnarchyRunner %s Pod %s cannot update actions for AnarchySubject %s!',
            anarchy_runner.name, runner_pod.metadata.name, subject_name)
        flask.abort(400)

    anarchy_action = AnarchyAction.get(action_name, runtime)
    if not anarchy_action:
        operator_logger.warning(
            'AnarchyRunner %s Pod %s attempted to update action on deleted AnarchyAction %s!',
            anarchy_runner.name, runner_pod.metadata.name, action_name)
        flask.abort(400)

    anarchy_subject = AnarchySubject.get(subject_name, runtime)
    if not anarchy_subject:
        operator_logger.warning(
            'AnarchyRunner %s Pod %s attempted to update action on deleted AnarchySubject %s!',
            anarchy_runner.name, runner_pod.metadata.name, subject_name)
        flask.abort(400)

    anarchy_governor = anarchy_subject.get_governor(runtime)
    if not anarchy_governor:
        operator_logger.warning(
            'AnarchyRunner %s Pod %s cannot post action to AnarchySubject %s, unable to find AnarchyGovernor %s!',
            anarchy_runner.name, runner_pod, subject_name,
            anarchy_subject.governor_name)
        flask.abort(400)

    finished_state = None
    if flask.request.json.get('successful', False):
        finished_state = 'successful'
    elif flask.request.json.get('failed', False):
        finished_state = 'failed'

    if finished_state != None:
        anarchy_subject.remove_active_action(anarchy_action, runtime)
        anarchy_action.set_finished(finished_state, runtime)

    return flask.jsonify({
        'success': True,
        'result': anarchy_action.to_dict(runtime)
    })
Exemple #4
0
 def get_subject(self, runtime):
     return AnarchySubject.get(self.subject_name, runtime)
Exemple #5
0
def post_subject_action(subject_name):
    anarchy_runner, runner_pod = check_runner_auth(
        flask.request.headers.get('Authorization', ''))
    if not anarchy_runner:
        flask.abort(400)
        return

    if subject_name != runner_pod.metadata.labels.get(runtime.subject_label):
        operator_logger.warning(
            'AnarchyRunner %s Pod %s cannot update AnarchySubject %s!',
            anarchy_runner.name, runner_pod.metadata.name, subject_name)
        flask.abort(400)
        return

    anarchy_subject = AnarchySubject.get(subject_name, runtime)
    if not anarchy_subject:
        operator_logger.warning(
            'AnarchyRunner %s Pod %s attempted to create action on deleted AnarchySubject %s!',
            anarchy_runner.name, runner_pod.metadata.name, subject_name)
        flask.abort(400)
        return

    anarchy_governor = anarchy_subject.get_governor(runtime)
    if not anarchy_governor:
        operator_logger.warning(
            'AnarchyRunner %s Pod %s cannot post action to AnarchySubject %s, unable to find AnarchyGovernor %s!',
            anarchy_runner.name, runner_pod, subject_name,
            anarchy_subject.governor_name)
        flask.abort(400)
        return

    action_name = flask.request.json.get('action', None)
    after_timestamp = flask.request.json.get('after', None)
    cancel_actions = flask.request.json.get('cancel', None)
    if not action_name and not cancel_actions:
        operator_logger.warning(
            'No action or cancel given for scheduling action')
        flask.abort(400)
        return
    if after_timestamp and not re.match(r'\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ',
                                        after_timestamp):
        operator_logger.warning(
            'Invalide datetime format "%s" given for action after value',
            after_timestamp)
        flask.abort(400)
        return

    if action_name not in cancel_actions:
        cancel_actions.append(action_name)

    for action_resource in runtime.custom_objects_api.list_namespaced_custom_object(
            runtime.operator_domain,
            runtime.api_version,
            runtime.operator_namespace,
            'anarchyactions',
            label_selector='{}/subject={}'.format(runtime.operator_domain,
                                                  anarchy_subject.name)).get(
                                                      'items', []):
        if action_resource['spec']['action'] in cancel_actions \
        and 'status' not in action_resource:
            runtime.custom_objects_api.delete_namespaced_custom_object(
                runtime.operator_domain, runtime.api_version,
                runtime.operator_namespace, 'anarchyactions',
                action_resource['metadata']['name'])

    if action_name:
        result = runtime.custom_objects_api.create_namespaced_custom_object(
            runtime.operator_domain, runtime.api_version,
            runtime.operator_namespace, 'anarchyactions', {
                "apiVersion": runtime.api_group_version,
                "kind": "AnarchyAction",
                "metadata": {
                    "generateName":
                    "%s-%s-" % (anarchy_subject.name, action_name),
                    "labels": {
                        runtime.action_label: action_name,
                        runtime.subject_label: anarchy_subject.name,
                        runtime.governor_label: anarchy_governor.name
                    },
                    "ownerReferences": [{
                        "apiVersion": runtime.api_group_version,
                        "controller": True,
                        "kind": "AnarchySubject",
                        "name": anarchy_subject.name,
                        "uid": anarchy_subject.uid
                    }]
                },
                "spec": {
                    "action": action_name,
                    "after": after_timestamp,
                    "callbackToken": uuid.uuid4().hex,
                    "governorRef": {
                        "apiVersion": runtime.api_group_version,
                        "kind": "AnarchyGovernor",
                        "name": anarchy_governor.name,
                        "namespace": runtime.operator_namespace,
                        "uid": anarchy_governor.uid
                    },
                    "subjectRef": {
                        "apiVersion": runtime.api_group_version,
                        "kind": "AnarchySubject",
                        "name": anarchy_subject.name,
                        "namespace": runtime.operator_namespace,
                        "uid": anarchy_subject.uid
                    }
                }
            })
    else:
        result = None

    return flask.jsonify({'success': True, 'result': result})