Esempio n. 1
0
    def test_retry_on_conflict(self, get_or_create, save, app_spec, signal,
                               signal_name, fail_times):
        def _fail():
            response = mock.MagicMock(spec=Response)
            response.status_code = 409  # Conflict
            raise ClientError("Conflict", response=response)

        configure_mock_fail_then_success(save,
                                         fail=_fail,
                                         fail_times=fail_times)
        application_status = FiaasApplicationStatus(
            metadata=ObjectMeta(name=app_spec.name, namespace="default"))
        get_or_create.return_value = application_status

        status.connect_signals()

        try:
            signal(signal_name).send(app_name=app_spec.name,
                                     namespace=app_spec.namespace,
                                     deployment_id=app_spec.deployment_id)
        except UpsertConflict as e:
            if fail_times < CONFLICT_MAX_RETRIES:
                pytest.fail('Exception {} was raised when signaling {}'.format(
                    e, signal_name))

        save_calls = min(fail_times + 1, CONFLICT_MAX_RETRIES)
        assert save.call_args_list == [mock.call()] * save_calls
    def test_fail_on_error(self, get_or_create, save, app_spec, signal, result):
        response = mock.MagicMock(spec=Response)
        response.status_code = 403

        save.side_effect = ClientError("No", response=response)

        application_status = FiaasApplicationStatus(metadata=ObjectMeta(name=app_spec.name, namespace="default"))
        get_or_create.return_value = application_status

        status.connect_signals()
        lifecycle_subject = _subject_from_app_spec(app_spec)

        with pytest.raises(ClientError):
            signal(DEPLOY_STATUS_CHANGED).send(status=result, subject=lifecycle_subject)
Esempio n. 3
0
    def test_fail_on_error(self, get_or_create, save, app_spec, signal,
                           signal_name):
        response = mock.MagicMock(spec=Response)
        response.status_code = 403

        save.side_effect = ClientError("No", response=response)

        application_status = FiaasApplicationStatus(
            metadata=ObjectMeta(name=app_spec.name, namespace="default"))
        get_or_create.return_value = application_status

        status.connect_signals()

        with pytest.raises(ClientError):
            signal(signal_name).send(app_name=app_spec.name,
                                     namespace=app_spec.namespace,
                                     deployment_id=app_spec.deployment_id)
    def test_action_on_signal(self, request, get, app_spec, test_data, signal):
        app_name = '{}-isb5oqum36ylo'.format(test_data.result)
        expected_logs = [LOG_LINE]
        if not test_data.new:
            get.side_effect = lambda *args, **kwargs: mock.DEFAULT  # disable default behavior of raising NotFound
            get_response = mock.create_autospec(Response)
            get_response.json.return_value = {
                'apiVersion': 'fiaas.schibsted.io/v1',
                'kind': 'ApplicationStatus',
                'metadata': {
                    'labels': {
                        'app': app_spec.name,
                        'fiaas/deployment_id': app_spec.deployment_id,
                        'label/on_existing_resource': 'label_value',
                    },
                    'annotations': {
                        'fiaas/last_updated': LAST_UPDATE,
                        'annotation/on_existing_resource': 'annotation_value',
                    },
                    'namespace': 'default',
                    'name': app_name,
                    },
                'result': 'INITIATED',
                'logs': expected_logs,
            }
            get.return_value = get_response

        # expected data used in expected api response and to configure mocks
        labels = app_spec.labels._replace(status={"status/label": "true"})
        annotations = app_spec.annotations._replace(status={"status/annotations": "true"})
        app_spec = app_spec._replace(name=test_data.result, labels=labels, annotations=annotations)

        # setup status signals
        status.connect_signals()

        # setup expected API call resulting from status update
        expected_call = {
            'apiVersion': 'fiaas.schibsted.io/v1',
            'kind': 'ApplicationStatus',
            'result': test_data.result,
            'logs': expected_logs,
            'metadata': {
                'labels': {
                    'app': app_spec.name,
                    'fiaas/deployment_id': app_spec.deployment_id,
                    'status/label': 'true',
                },
                'annotations': {
                    'fiaas/last_updated': LAST_UPDATE,
                    'status/annotations': 'true',
                },
                'namespace': 'default',
                'name': app_name,
                'ownerReferences': [],
                'finalizers': [],
            }
        }
        # if we have an existing resource, expect that existing labels and annotations are present after update
        if not test_data.new:
            expected_call['metadata']['labels']['label/on_existing_resource'] = 'label_value'
            expected_call['metadata']['annotations']['annotation/on_existing_resource'] = 'annotation_value'

        called_mock = request.getfixturevalue(test_data.called_mock)
        mock_response = mock.create_autospec(Response)
        mock_response.json.return_value = expected_call
        called_mock.return_value = mock_response
        lifecycle_subject = _subject_from_app_spec(app_spec)

        # this triggers the status update
        with mock.patch("fiaas_deploy_daemon.crd.status.now") as mnow:
            mnow.return_value = LAST_UPDATE
            signal(test_data.signal_name).send(status=test_data.status, subject=lifecycle_subject)

        # assert that the api function expected to be called was called, and that the ignored api function was not
        if test_data.action == "create":
            url = '/apis/fiaas.schibsted.io/v1/namespaces/default/application-statuses/'
        else:
            url = '/apis/fiaas.schibsted.io/v1/namespaces/default/application-statuses/{}'.format(app_name)

        called_mock.assert_called_once_with(url, expected_call)
        ignored_mock = request.getfixturevalue(test_data.ignored_mock)
        ignored_mock.assert_not_called()
Esempio n. 5
0
    def test_action_on_signal(self, request, get_or_create, app_spec,
                              test_data, signal):
        app_name = '{}-isb5oqum36ylo'.format(test_data.signal_name)
        labels = app_spec.labels._replace(status={"status/label": "true"})
        annotations = app_spec.annotations._replace(
            status={"status/annotations": "true"})
        app_spec = app_spec._replace(name=test_data.signal_name,
                                     labels=labels,
                                     annotations=annotations)

        expected_labels = merge_dicts(
            app_spec.labels.status, {
                "app": app_spec.name,
                "fiaas/deployment_id": app_spec.deployment_id
            })
        expected_annotations = merge_dicts(app_spec.annotations.status,
                                           {"fiaas/last_updated": LAST_UPDATE})
        expected_metadata = ObjectMeta(name=app_name,
                                       namespace="default",
                                       labels=expected_labels,
                                       annotations=expected_annotations)
        expected_logs = [LOG_LINE]
        get_or_create.return_value = FiaasApplicationStatus(
            new=test_data.new,
            metadata=expected_metadata,
            result=test_data.result,
            logs=expected_logs)
        status.connect_signals()
        expected_call = {
            'apiVersion': 'fiaas.schibsted.io/v1',
            'kind': 'ApplicationStatus',
            'result': test_data.result,
            'logs': expected_logs,
            'metadata': {
                'labels': {
                    'app': app_spec.name,
                    'fiaas/deployment_id': app_spec.deployment_id,
                    'status/label': 'true'
                },
                'annotations': {
                    'fiaas/last_updated': LAST_UPDATE,
                    'status/annotations': 'true'
                },
                'namespace': 'default',
                'name': app_name,
                'ownerReferences': [],
                'finalizers': [],
            }
        }
        called_mock = request.getfixturevalue(test_data.called_mock)
        mock_response = mock.create_autospec(Response)
        mock_response.json.return_value = expected_call
        called_mock.return_value = mock_response

        with mock.patch("fiaas_deploy_daemon.crd.status.now") as mnow:
            mnow.return_value = LAST_UPDATE
            signal(test_data.signal_name).send(
                app_name=app_spec.name,
                namespace=app_spec.namespace,
                deployment_id=app_spec.deployment_id,
                labels=app_spec.labels.status,
                annotations=app_spec.annotations.status)

        get_or_create.assert_called_once_with(metadata=expected_metadata,
                                              result=test_data.result,
                                              logs=expected_logs)
        if test_data.action == "create":
            url = '/apis/fiaas.schibsted.io/v1/namespaces/default/application-statuses/'
        else:
            url = '/apis/fiaas.schibsted.io/v1/namespaces/default/application-statuses/{}'.format(
                app_name)
        ignored_mock = request.getfixturevalue(test_data.ignored_mock)
        called_mock.assert_called_once_with(url, expected_call)
        ignored_mock.assert_not_called()