Beispiel #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)
Beispiel #3
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"]],
                )
    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)
class IncompatibleFieldsFilterTest(unittest.TestCase):
    @with_json_fixture("../fixtures/single_full_app.json")
    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 = AsgardApp.from_json(self.single_full_app_fixture)
        self.original_app = AsgardApp.from_json(self.single_full_app_fixture)

    def test_update_app_remove_ports_fields(self):
        self.original_app.ports = self.single_full_app_fixture['container'][
            'docker']['portMappings'][0]['servicePort']
        merged_app = self.request.merge_marathon_apps(self.original_app,
                                                      self.request_app)
        filtered_app = self.filter.write(None, merged_app, self.original_app)
        self.assertEqual([], filtered_app.ports)

    def test_update_app_remove_port_definitions_fields(self):
        port_definitions = [{
            "port": 10019,
            "protocol": "tcp",
            "name": "http",
            "labels": {
                "vip": "192.168.0.1:80"
            }
        }]
        self.original_app.port_definitions = port_definitions
        merged_app = self.request.merge_marathon_apps(self.original_app,
                                                      self.request_app)
        filtered_app = self.filter.write(None, merged_app, self.original_app)
        self.assertEqual([], filtered_app.port_definitions)
Beispiel #6
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])
 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)
 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)
Beispiel #9
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)
Beispiel #10
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)
 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)
 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)
 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)
 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)
    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)
 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)
    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)
    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))
 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)
    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')
Beispiel #21
0
 def test_it_call_dispatch_using_user_from_request(self):
     """
     Certificamos que o user preenchido no request é repassado para o dispatch
     """
     with application.test_request_context('/v2/apps/foo', method='GET') as ctx:
         with patch('hollowman.request_handlers.upstream_request'), \
             patch('hollowman.request_handlers.dispatch') as dispatch_mock:
             user = MagicMock()
             ctx.request.user = user
             request_parser = Request(ctx.request)
             request_parser.split = MagicMock(return_value=[self.request_apps[0]])
             request_parser.join = MagicMock()
             response = new(request_parser)
             dispatch_mock.assert_called_once_with(user=user, request=ANY)
Beispiel #22
0
    def test_split_groups_write_PUT_on_group(self):
        """
        Atualmente, o único body que chega em um PUT em /v2/groups é:
            {"scaleBy": <N>}
        onde `<N>` é o fator que será multiplicado pelo atual número de TASK_RUNNING de cada app.

        O problema é que o Request.split() retorna uma lista de apps, e o Request.join() potencialmente
        vai reconstruir um body com essa lista de apps. O problema é que isso gera um request body *diferente* do orignal,
        já que agora temos um body contendo um APP_GROUP com todas suas apps (e sub apps).

        E se fazemos apenas isso, a informação do "scaleBy" se perdeu, pois se mandamos um request com o TASK_GROUP inteiro para o
        upstream, nada vai mudar já que as apps não foram modificadas.

        Uma ideia é o Core do hollowman decobrir essa ação de scaleBy e chamar o métoro "scale_by" dos filtros, já com a request_app tendo seu
        atributo "instances" multiplicado pelo fator. Opcionalmente o fator poderia ser passado como parametro para o filtro.

        Isso nos daria a possibilidade de "corrigir" um problema atual do scaleby que é:
            Quando damos scale_by = 2 em um app que está suspended, ela continua suspended já que 2 * 0 = 0. A ideia é que suspended apps também sejam
            ligadas considerando esse fator. O que faríamos no filtro seria, para toda app que instances = 0, consideramos instances = 1 e multiplicamos pelo fator.

        Enfim, apenas uma ideia. Temos que ver o que fazemos com esse teste aqui.
        """

        with application.test_request_context("/v2/groups/group-b",
                                              method="PUT") 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))

                expected_apps = [
                    (
                        MarathonApp(),
                        MarathonApp.from_json({"id": "/dev/group-b/appb0"}),
                    ),
                    (
                        MarathonApp(),
                        MarathonApp.from_json(
                            {"id": "/dev/group-b/group-b0/app0"}),
                    ),
                ]
                self.assertEqual(expected_apps, apps)
Beispiel #23
0
    def test_it_recreates_a_get_request_for_a_single_app(self, fixture):
        with application.test_request_context("/v2/apps//foo",
                                              method="GET",
                                              data=b"") 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, ctx.request)
                self.assertEqual(request.data, b"")
    def test_join_queue_should_return_original_request_if_GET(self):
        """
        Quando fazemos GET em /v2/queue, temos apenas que deixar request passar.
        """
        with application.test_request_context('/v2/queue',
                                              method='GET') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)

            joined_request = request_parser.join([])
            self.assertIsInstance(joined_request, HollowmanRequest)
            self.assertEqual(b'', joined_request.data,
                             "Body deveria estar vazio")
            self.assertEqual("/v2/queue", joined_request.path)
    def test_a_read_single_app_request_returns_a_single_marathonapp_if_app_exists(
            self, fixture):
        with application.test_request_context('/v2/apps//foo',
                                              method='GET',
                                              data=b'') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)

            with patch.object(request_parser, 'marathon_client') as client:
                original_app = MarathonApp.from_json(fixture)
                client.get_app.return_value = original_app
                apps = list(request_parser.split())

            self.assertEqual(apps, [(request_parser.merge_marathon_apps(
                MarathonApp(), original_app), client.get_app.return_value)])
    def test_it_recreates_a_put_request_for_multiple_apps(self, fixture):
        with application.test_request_context('/v2/apps/',
                                              method='PUT',
                                              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())
                         for _ in range(2)]

            request = request_parser.join(mock_apps)
            self.assertIsInstance(request, HollowmanRequest)
            self.assertCountEqual(
                [app['id'] for app in json.loads(request.data)],
                [app.id for app, _ in mock_apps])
Beispiel #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/groups//dev/",
                 status=200,
                 body=json.dumps({"apps": []}),
             )
             apps = list(request.split())
             joined_request = request.join(apps)
             self.assertEqual("/v2/apps", joined_request.path)
             self.assertEqual(b"", joined_request.data)
    def test_join_group_read_root_group(self, group_dev_namespace_fixture):
        with application.test_request_context('/v2/groups',
                                              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/groups//dev/',
                         body=json.dumps(group_dev_namespace_fixture),
                         status=200)

                apps = list(request.split())
                joined_request = request.join(apps)
                self.assertEqual("/v2/groups/dev", joined_request.path)
                self.assertEqual(b"", joined_request.data)
    def test_join_queue_should_return_original_request_with_path_adjusted(
            self):
        """
        No momento d join() devemos ajustar o app_id para adicionar o namespace.
        """
        with application.test_request_context(
                '/v2/queue/myapp/multi/path/delay', method='DELETE') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)

            joined_request = request_parser.join([])
            self.assertIsInstance(joined_request, HollowmanRequest)
            self.assertEqual(b'', joined_request.data,
                             "Body deveria estar vazio")
            self.assertEqual("/v2/queue/dev/myapp/multi/path/delay",
                             joined_request.path)
    def test_join_v2_apps_on_DELETE_method(self):
        """
        O request de DELETE tem o corpo vazio. Isso significa que o split()
        não retornou nada, o que faz o join ser chamado assim: .join([]).
        É isso que esse teste trata.
        """
        with application.test_request_context('/v2/apps/group',
                                              method='DELETE') as ctx:
            ctx.request.user = self.user
            request_parser = Request(ctx.request)

            joined_request = request_parser.join([])
            self.assertIsInstance(joined_request, HollowmanRequest)
            self.assertEqual(b'', joined_request.data,
                             "Body deveria estar vazio")
            self.assertEqual("/v2/apps/dev/group", joined_request.path)