def _assert_status():
     status = FiaasApplicationStatus.get(
         create_name(name, DEPLOYMENT_ID1))
     assert status.result == u"RUNNING"
     assert len(status.logs) > 0
     assert any("Saving result RUNNING for default/{}".format(name) in l
                for l in status.logs)
Esempio n. 2
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_deploy_based_on_status_result(self, crd_watcher, deploy_queue,
                                           watcher, status_get, result, count):
        watcher.watch.return_value = [WatchEvent(ADD_EVENT, FiaasApplication)]
        status_get.side_effect = lambda *args, **kwargs: mock.DEFAULT  # disable default behavior of raising NotFound
        status_get.return_value = FiaasApplicationStatus(new=False,
                                                         result=result)

        assert deploy_queue.qsize() == 0
        crd_watcher._watch(None)
        assert deploy_queue.qsize() == count
Esempio n. 4
0
def _create_status(i, annotate=True):
    annotations = {
        LAST_UPDATED_KEY: "2020-12-12T23.59.{:02}".format(i)
    } if annotate else None
    metadata = ObjectMeta(name="name-{}".format(i),
                          namespace="test",
                          annotations=annotations)
    return FiaasApplicationStatus(new=False,
                                  metadata=metadata,
                                  result=u"SUCCESS")
Esempio n. 5
0
    def test_custom_resource_definition_deploy(self, custom_resource_definition, service_type, kind_logger):
        with kind_logger():
            name, fiaas_application, expected = custom_resource_definition

            # check that k8s objects for name doesn't already exist
            kinds = self._select_kinds(expected)
            for kind in kinds:
                with pytest.raises(NotFound):
                    kind.get(name)

            # First deploy
            fiaas_application.save()
            app_uid = fiaas_application.metadata.uid

            # Check that deployment status is RUNNING
            def _assert_status():
                status = FiaasApplicationStatus.get(create_name(name, DEPLOYMENT_ID1))
                assert status.result == u"RUNNING"
                assert len(status.logs) > 0
                assert any("Saving result RUNNING for default/{}".format(name) in line for line in status.logs)

            wait_until(_assert_status, patience=PATIENCE)

            # Check that annotations and labels are applied to status object
            status_labels = fiaas_application.spec.additional_labels.status
            if status_labels:
                status = FiaasApplicationStatus.get(create_name(name, DEPLOYMENT_ID1))
                label_difference = status_labels.viewitems() - status.metadata.labels.viewitems()
                assert label_difference == set()

            # Check deploy success
            wait_until(_deploy_success(name, kinds, service_type, IMAGE1, expected, DEPLOYMENT_ID1, app_uid=app_uid), patience=PATIENCE)

            # Redeploy, new image, possibly new init-container
            fiaas_application.spec.image = IMAGE2
            fiaas_application.metadata.labels["fiaas/deployment_id"] = DEPLOYMENT_ID2
            strongbox_groups = []
            if "strongbox" in name:
                strongbox_groups = ["foo", "bar"]
                fiaas_application.spec.config["extensions"]["strongbox"]["groups"] = strongbox_groups
            fiaas_application.save()
            app_uid = fiaas_application.metadata.uid
            # Check success
            wait_until(_deploy_success(name, kinds, service_type, IMAGE2, expected, DEPLOYMENT_ID2, strongbox_groups, app_uid=app_uid),
                       patience=PATIENCE)

            # Cleanup
            FiaasApplication.delete(name)

            def cleanup_complete():
                for kind in kinds:
                    with pytest.raises(NotFound):
                        kind.get(name)

            wait_until(cleanup_complete, patience=PATIENCE)
    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. 7
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)
Esempio n. 8
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()