示例#1
0
    def test_join_one_app_should_produce_one_app_not_a_list(self, fixture):
        """
        Um POST em /v2/apps, apesar de receber no body apens uma app ({...}),
        após o request.join(), restá produzindo um request com uma lista de apps:
            [{...}], e a API do marathon não aceita lista no POST apenas no PUT.

            O problema parece ser no request.join():89, onde fazemos if self.is_list_app_request().
            Precisamos olhar se é PUT ou POST e gerar list() ou dict() apropriadamente.
        """
        with application.test_request_context("/v2/apps/",
                                              method="POST",
                                              data=json.dumps(fixture)) as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)
            mock_app = get_fixture("single_full_app.json")
            mock_apps = [(MarathonApp.from_json(mock_app), Mock())]

            joined_request = request_parser.join(mock_apps)
            self.assertIsInstance(joined_request, HollowmanRequest)
            joined_request_data = json.loads(joined_request.data)
            self.assertFalse(
                isinstance(joined_request_data, list),
                "Body não deveria ser uma lista",
            )
            self.assertEqual("/foo", joined_request_data["id"])
    def test_split_groups_read_on_specific_group(self, group_b_fixture):

        with application.test_request_context('/v2/groups/group-b',
                                              method='GET') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] +
                         '/v2/groups//dev/group-b',
                         body=json.dumps(group_b_fixture),
                         status=200)

                apps = list(request_parser.split())
                self.assertEqual(2, len(apps))

                original_app_one = MarathonApp.from_json(
                    {"id": "/dev/group-b/appb0"})
                original_app_two = MarathonApp.from_json(
                    {"id": "/dev/group-b/group-b0/app0"})
                expected_apps = [
                    (request_parser.merge_marathon_apps(
                        MarathonApp(), original_app_one), original_app_one),
                    (request_parser.merge_marathon_apps(
                        MarathonApp(), original_app_two), original_app_two),
                ]
                self.assertEqual(expected_apps, apps)
示例#3
0
    def test_can_read_app_if_already_migrated(self, single_full_app_fixture):
        """
        Conferimos que é possível fazer um GET em
        /v2/apps/<app-id> para uma app que já está migrada.
        O <app-id> usado é sempre *sem* namespace
        """
        request_data = deepcopy(single_full_app_fixture)
        single_full_app_fixture["id"] = "/dev/foo"
        with application.test_request_context("/v2/apps/foo",
                                              method="GET") as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)
            with RequestsMock() as rsps:
                rsps.add(
                    method="GET",
                    url=conf.MARATHON_ADDRESSES[0] + "/v2/apps//dev/foo",
                    body=json.dumps({"app": single_full_app_fixture}),
                    status=200,
                )

                apps = list(request_parser.split())

                original_app = MarathonApp.from_json(single_full_app_fixture)
                expected_app = (
                    request_parser.merge_marathon_apps(MarathonApp(),
                                                       original_app),
                    original_app,
                )
                self.assertEqual(apps, [expected_app])
示例#4
0
    def test_do_not_call_task_method_if_filter_does_not_implement(self):
        """
        Caso um filtro não implemente write_task, apenas não chamamos esse filtro
        durante o pipeline
        """
        class DummyFilter:
            def write(self, user, request_app, original_app):
                raise Exception()

        pipeline = {
                OperationType.WRITE: [DummyFilter(), ]
        }

        request_data = {"ids": ["task_0"]}
        request_app = MarathonTask.from_json({'id': request_data['ids'][0]})
        original_app = request_app # Por enquanto não temos como passar a original task

        with application.test_request_context("/v2/tasks/delete",
                                              method="POST",
                                              data=json.dumps(request_data),
                                              headers={"Content-type": "application/json"}) as ctx:
            ctx.request.user = self.user
            request = Request(ctx.request)
            with patch.object(request, "split", return_value=[(request_app, original_app)]):
                filtered_request = dispatch(self.user, request, filters_pipeline=pipeline)
                filtered_app = MarathonTask.from_json({"id": filtered_request.get_json()['ids'][0]})
                self.assertEqual("task_0", filtered_app.id)
示例#5
0
    def test_a_request_with_n_apps_returns_n_marathonapps(self, fixture):
        with application.test_request_context("/v2/apps/",
                                              method="GET") as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)
            with RequestsMock() as rsps:
                rsps.add(
                    method="GET",
                    url=conf.MARATHON_ADDRESSES[0] + "/v2/groups//dev/",
                    body=json.dumps(fixture),
                    status=200,
                )
                apps = list(request_parser.split())

                self.assertEqual(
                    [request_app for request_app, _ in apps],
                    [
                        request_parser.merge_marathon_apps(
                            request_app, original_app)
                        for request_app, original_app in apps
                    ],
                )

                self.assertEqual(
                    [app.id for app, _ in apps],
                    [app["id"] for app in fixture["apps"]],
                )
示例#6
0
    def test_preserve_upgrade_strategy_added_by_filter(self):
        class AddNewUpgradeStrategyFilter:
            def write(self, user, request_app, original_app):
                us_data = {
                    "maximumOverCapacity": 1,
                    "minimumHealthCapacity": 0.75
                }
                request_app.upgrade_strategy = MarathonUpgradeStrategy.from_json(us_data)
                return request_app

        pipeline = {
                OperationType.WRITE: [AddNewUpgradeStrategyFilter(), ]
        }
        # Simulando uma app que veio sem o campo "upgradeStrategy"
        request_data = {}

        request_app = AsgardApp.from_json(request_data)
        original_app = AsgardApp.from_json(deepcopy(self.single_full_app_fixture))

        with application.test_request_context("/v2/apps/foo",
                                              method="PUT",
                                              headers={"Content-type": "application/json"},
                                              data=json.dumps(request_data)) as ctx:

            ctx.request.user = self.user
            request = Request(ctx.request)
            filtered_request = dispatch(self.user, request, filters_pipeline=pipeline)
            filtered_app = AsgardApp.from_json(filtered_request.get_json())
            self.assertEqual(1, filtered_app.upgrade_strategy.maximum_over_capacity)
            self.assertEqual(0.75, filtered_app.upgrade_strategy.minimum_health_capacity)
            self._check_other_fields("upgradeStrategy", filtered_app)
示例#7
0
    def test_preserve_envs_added_by_filter(self):
        class AddNewEnvFilter:
            def write(self, user, request_app, original_app):
                request_app.env["env1"] = "env-value1"
                return request_app

        pipeline = {
                OperationType.WRITE: [AddNewEnvFilter(), ]
        }
        request_data = {"env": []}

        request_app = AsgardApp.from_json(request_data)
        original_app = AsgardApp.from_json(deepcopy(self.single_full_app_fixture))

        with application.test_request_context("/v2/apps/foo",
                                              method="PUT",
                                              headers={"Content-type": "application/json"},
                                              data=json.dumps(request_data)) as ctx:

            ctx.request.user = self.user
            request = Request(ctx.request)
            filtered_request = dispatch(self.user, request, filters_pipeline=pipeline)
            filtered_app = AsgardApp.from_json(filtered_request.get_json())
            self.assertEqual(1, len(filtered_app.env.keys()))
            self.assertEqual({"env1": "env-value1"}, filtered_app.env)
            self._check_other_fields("env", filtered_app)
示例#8
0
    def test_update_app_change_all_constraints(self):
        """
        Devemos respeitar as constraints quem estão da request,
        elas devem substituir as constrains da app original
        """
        class DummyFilter:
            def write(self, user, request_app, original_app):
                return request_app

        pipeline = {
                OperationType.WRITE: [DummyFilter(), ]
        }

        request_data = {"constraints": [["hostname", "LIKE", "myhost"]]}
        request_app = AsgardApp.from_json(request_data)
        original_app = AsgardApp.from_json(deepcopy(self.single_full_app_fixture))

        with application.test_request_context("/v2/apps/foo",
                                              method="PUT",
                                              data=json.dumps(request_data),
                                              headers={"Content-type": "application/json"}) as ctx:

            ctx.request.user = self.user
            request = Request(ctx.request)
            filtered_request = dispatch(self.user, request, filters_pipeline=pipeline)
            filtered_app = AsgardApp.from_json(filtered_request.get_json())
            self.assertEqual(1, len(filtered_app.constraints))
            self.assertEqual(["hostname", "LIKE", "myhost"], filtered_app.constraints[0].json_repr())
            self._check_other_fields("constraints", filtered_app)
示例#9
0
    def test_preserve_constraints_added_by_filter(self):
        """
        Certifica que quando um request remove todas as constraints e algum filtro adiciona novas
        constraints, essas constraints adicionadas pelo filtro são preservadas
        """
        class AddNewConstraintFilter:
            def write(self, user, request_app, original_app):
                request_app.constraints.append(MarathonConstraint.from_json("key:LIKE:value".split(":")))
                return request_app

        pipeline = {
                OperationType.WRITE: [AddNewConstraintFilter(), ]
        }

        request_data = {"constraints": []}
        request_app = AsgardApp.from_json(request_data)
        original_app = AsgardApp.from_json(deepcopy(self.single_full_app_fixture))

        with application.test_request_context("/v2/apps/foo",
                                              method="PUT",
                                              headers={"Content-type": "application/json"},
                                              data=json.dumps(request_data)) as ctx:

            ctx.request.user = self.user
            request = Request(ctx.request)
            filtered_request = dispatch(self.user, request, filters_pipeline=pipeline)
            filtered_request_app = AsgardApp.from_json(filtered_request.get_json())
            self.assertEqual(1, len(filtered_request_app.constraints))
            self._check_other_fields("constraints", filtered_request_app)
示例#10
0
    def test_update_app_remove_all_constraints(self):
        """
        Certifica que um request que remove todas as constraints,
        remove essas constraints na app original
        """
        class DummyFilter:
            def write(self, user, request_app, original_app):
                return request_app

        pipeline = {
                OperationType.WRITE: [DummyFilter(), ]
        }

        request_data = {"constraints": []}
        request_app = AsgardApp.from_json(request_data)
        original_app = AsgardApp.from_json(deepcopy(self.single_full_app_fixture))

        with application.test_request_context("/v2/apps/foo",
                                              method="PUT",
                                              data=json.dumps(request_data),
                                              headers={"Content-type": "application/json"}) as ctx:
            ctx.request.user = self.user
            request = Request(ctx.request)
            filtered_request = dispatch(self.user, request, filters_pipeline=pipeline)
            filtered_app = AsgardApp.from_json(filtered_request.get_json())
            self.assertEqual(0, len(filtered_app.constraints))
            self._check_other_fields("constraints", filtered_app)
示例#11
0
    def test_dispatch_should_pass_an_instance_if_SieveMarathonApp_to_filters(self):
        """
        Certifica que quando um request remove todas as constraints e algum filtro adiciona novas
        constraints, essas constraints adicionadas pelo filtro são preservadas
        """
        class AddNewConstraintFilter:
            def write(self, user, request_app, original_app):
                assert isinstance(request_app, AsgardApp)
                return request_app

        pipeline = {
                OperationType.WRITE: [AddNewConstraintFilter(), ]
        }

        request_data = {"constraints": []}
        request_app = AsgardApp.from_json(request_data)
        original_app = AsgardApp.from_json(deepcopy(self.single_full_app_fixture))

        with application.test_request_context("/v2/apps/foo",
                                              method="PUT",
                                              headers={"Content-type": "application/json"},
                                              data=json.dumps(request_data)) as ctx:

            ctx.request.user = self.user
            request = Request(ctx.request)
            filtered_request = dispatch(self.user, request, filters_pipeline=pipeline)
示例#12
0
    def test_return_correct_request_resource(self):
        expected_request_resources = {
            "/v2/apps": RequestResource.APPS,
            "/v2/apps/": RequestResource.APPS,
            "/v2/groups": RequestResource.GROUPS,
            "/v2/groups/": RequestResource.GROUPS,
            "/v2/deployments": RequestResource.DEPLOYMENTS,
            "/v2/deployments/": RequestResource.DEPLOYMENTS,
            "/v2/tasks": RequestResource.TASKS,
            "/v2/tasks/": RequestResource.TASKS,
            "/v2/queue": RequestResource.QUEUE,
            "/v2/queue/": RequestResource.QUEUE,
        }

        for (
                request_path,
                expected_request_resource,
        ) in expected_request_resources.items():
            # noinspection PyTypeChecker
            request_mock = Mock(path=request_path)
            request_wrapper = Request(request_mock)
            response_wrapper = Response(request_mock, Mock())
            self.assertEqual(request_wrapper.request_resource,
                             expected_request_resource)
            self.assertEqual(response_wrapper.request_resource,
                             expected_request_resource)
示例#13
0
    def test_change_request_path_if_is_write_on_one_app(self, fixture):
        """
        Quando fazemos WRITE em cima de uma app específica, devemos
        ajustar o request.path para que o `upstream_request` seja feito
        no endpoint correto.
        """
        user = User(tx_name="User One", tx_email="*****@*****.**")
        user.current_account = Account(name="Dev",
                                       namespace="dev",
                                       owner="company")

        full_app_with_name_space = deepcopy(fixture)
        full_app_with_name_space['id'] = "/dev/foo"
        with application.test_request_context('/v2/apps//foo',
                                              method='PUT',
                                              data=json.dumps(fixture)) as ctx:
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/foo',
                         body=json.dumps({'app': full_app_with_name_space}),
                         status=200)
                ctx.request.user = user
                request_parser = Request(ctx.request)

                apps = list(request_parser.split())

                request = request_parser.join(apps)
                self.assertIsInstance(request, HollowmanRequest)
                self.assertEqual("/v2/apps/dev/foo", request.path)
示例#14
0
 def test_adjust_groups_root_request_path(self):
     with application.test_request_context('/v2/groups/',
                                           method='GET') as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonGroup(id="/dev/")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual("/v2/groups/dev", request_wrapper.request.path)
 def setUp(self, single_full_app_fixture):
     self.request = Request(None)
     self.single_full_app_fixture = single_full_app_fixture
     self.filter = IncompatibleFieldsFilter()
     self.request_app = SieveMarathonApp.from_json(
         self.single_full_app_fixture)
     self.original_app = SieveMarathonApp.from_json(
         self.single_full_app_fixture)
示例#16
0
 def test_adjust_apps_versions_request_path(self):
     with application.test_request_context("/v2/apps/my-app/versions",
                                           method="GET") as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonApp(id="/dev/my-app")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual("/v2/apps/dev/my-app/versions",
                          request_wrapper.request.path)
示例#17
0
    def test_split_queue_should_return_empty_iterator(self):
        with application.test_request_context('/v2/queue',
                                              method='GET') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)

            apps = list(request_parser.split())
            self.assertEqual(0, len(apps))
            self.assertEqual([], apps)
示例#18
0
 def test_adjust_groups_DELETE_request_path(self):
     with application.test_request_context("/v2/groups/my-group/",
                                           method="DELETE") as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonGroup(id="/dev/my-group")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual("/v2/groups/dev/my-group",
                          request_wrapper.request.path)
示例#19
0
 def test_adjust_apps_request_path_repeating_non_final_path(self):
     with application.test_request_context('/v2/apps/app0/app0/app1',
                                           method='GET') as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonApp(id="/dev/app0/app0/app1")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual("/v2/apps/dev/app0/app0/app1",
                          request_wrapper.request.path)
示例#20
0
 def test_adjust_groups_request_path_repeating_final_part(self):
     with application.test_request_context(
             '/v2/groups/grp0/other/parts/grp0/', method='GET') as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonGroup(id="/dev/grp0/grp0")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual("/v2/groups/dev/grp0/grp0",
                          request_wrapper.request.path)
示例#21
0
 def test_adjust_apps_request_path_no_aaditional_paths(self):
     with application.test_request_context('/v2/apps/my-app',
                                           method='GET') as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonApp(id="/dev/my-app")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual("/v2/apps/dev/my-app",
                          request_wrapper.request.path)
示例#22
0
 def test_adjust_apps_tasks_task_id_DELETE_request_path(self):
     with application.test_request_context('/v2/apps/my-app/tasks/task_id',
                                           method='DELETE') as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonApp(id="/dev/my-app")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual("/v2/apps/dev/my-app/tasks/task_id",
                          request_wrapper.request.path)
示例#23
0
    def test_it_parses_task_id(self):
        expected_paths = {
            '/v2/tasks': None,
            '/v2/tasks/': None,
            '/v2/tasks/delete': None,
        }

        for request_path, expected_marathon_path in expected_paths.items():
            # noinspection PyTypeChecker
            request_wrapper = Request(Mock(path=request_path))
            self.assertEqual(request_wrapper.object_id, expected_marathon_path)
示例#24
0
    def test_it_recognizes_apps_requests(self):
        with application.test_request_context('/v2/apps//foo',
                                              method='GET',
                                              data=b'') as ctx:
            request_parser = Request(ctx.request)
            self.assertTrue(request_parser.is_app_request())
            self.assertFalse(request_parser.is_group_request())

        with application.test_request_context('/v2/apps/',
                                              method='PUT',
                                              data=b'') as ctx:
            request_parser = Request(ctx.request)
            self.assertTrue(request_parser.is_app_request())
            self.assertFalse(request_parser.is_group_request())

        with application.test_request_context('/v2/apps//',
                                              method='DELETE',
                                              data=b'') as ctx:
            request_parser = Request(ctx.request)
            self.assertTrue(request_parser.is_app_request())
            self.assertFalse(request_parser.is_group_request())
示例#25
0
 def test_adjust_apps_request_path_keep_additional_paths_multiple_paths(
         self):
     with application.test_request_context(
             '/v2/apps/my-app/versions/2017-10-31T13:01:07.768Z',
             method='GET') as ctx:
         request_wrapper = Request(ctx.request)
         original_app = MarathonApp(id="/dev/my-app")
         request_wrapper._adjust_request_path_if_needed(
             request_wrapper.request, original_app)
         self.assertEqual(
             "/v2/apps/dev/my-app/versions/2017-10-31T13:01:07.768Z",
             request_wrapper.request.path)
示例#26
0
    def test_it_recognizes_apps_requests(self):
        with application.test_request_context("/v2/apps//foo",
                                              method="GET",
                                              data=b"") as ctx:
            request_parser = Request(ctx.request)
            self.assertTrue(request_parser.is_app_request())
            self.assertFalse(request_parser.is_group_request())

        with application.test_request_context("/v2/apps/",
                                              method="PUT",
                                              data=b"") as ctx:
            request_parser = Request(ctx.request)
            self.assertTrue(request_parser.is_app_request())
            self.assertFalse(request_parser.is_group_request())

        with application.test_request_context("/v2/apps//",
                                              method="DELETE",
                                              data=b"") as ctx:
            request_parser = Request(ctx.request)
            self.assertTrue(request_parser.is_app_request())
            self.assertFalse(request_parser.is_group_request())
示例#27
0
 def test_join_apps_read_empty_list(self):
     with application.test_request_context('/v2/apps', method='GET') as ctx:
         ctx.request.user = self.user
         request = Request(ctx.request)
         with RequestsMock() as rsps:
             rsps.add(method='GET',
                      url=conf.MARATHON_ADDRESSES[0] + '/v2/apps',
                      status=200,
                      body='''{"apps":[]}''')
             apps = list(request.split())
             joined_request = request.join(apps)
             self.assertEqual("/v2/apps", joined_request.path)
             self.assertEqual(b"", joined_request.data)
示例#28
0
    def test_split_tasks_GET(self):
        """
        Quadno recebemos um GET em /v2/tasks/delete,
        não temos o que fazer, entãoo request pode passar direto.
        Isso significa que o spit retorna []
        """
        with application.test_request_context('/v2/tasks/delete',
                                              method='GET') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)

            tasks = list(request_parser.split())
            self.assertEqual(0, len(tasks))
示例#29
0
    def test_change_request_path_if_is_read_single_app(
            self, single_full_app_fixture):
        with application.test_request_context('/v2/apps/foo',
                                              method='GET') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)
            single_full_app_fixture['id'] = "/dev/foo"
            apps = [(MarathonApp.from_json(single_full_app_fixture),
                     MarathonApp.from_json(single_full_app_fixture))]

            request = request_parser.join(apps)
            self.assertIsInstance(request, HollowmanRequest)
            self.assertEqual("/v2/apps/dev/foo", request.path)
示例#30
0
    def test_it_recreates_a_post_request_for_a_single_app(self, fixture):
        with application.test_request_context('/v2/apps//foo',
                                              method='POST',
                                              data=json.dumps(fixture)) as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)
            with patch.object(request_parser, 'marathon_client') as client:
                client.get_app.return_value = MarathonApp.from_json(fixture)
                apps = list(request_parser.split())

                request = request_parser.join(apps)
                self.assertIsInstance(request, HollowmanRequest)
                self.assertEqual(request.get_json()['id'], '/foo')