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)
def test_filters_can_modify_all_apps_from_group_and_subgroups( self, group_dev_namespace_fixture): """ Um fltro deve poder alterar todas as apps de todos os grupos de um response. """ with application.test_request_context("/v2/groups/group-b", method="GET") as ctx: ctx.request.user = self.user ok_response = FlaskResponse( response=json.dumps(group_dev_namespace_fixture["groups"][1]), status=HTTPStatus.OK, headers={}, ) response_wrapper = Response(ctx.request, ok_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline={OperationType.READ: [DummyFilter()]}, filter_method_name_callback=lambda *args: "response_group", ) final_response_data = json.loads(final_response.data) returned_group = MarathonGroup.from_json(final_response_data) self.assertEqual("/dummy/dev/group-b/appb0", returned_group.apps[0].id) self.assertEqual( "/dummy/dev/group-b/group-b0/app0", returned_group.groups[0].apps[0].id, )
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)
def test_response_task_do_not_dispatch_pipeline_if_response_is_deployment( self, tasks_post_fixture): """ Se o request for de escrita em /v2/tasks e foi passado `?scale=true`, não devemos rodar o pipeline, já que nesse response tem apenas um DeploymentId """ with application.test_request_context("/v2/tasks/delete?scale=true", method="POST") as ctx: original_response = FlaskResponse( response=json.dumps(tasks_post_fixture), status=200) response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline=[], filter_method_name_callback=lambda *args: "response_task", ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual( "5ed4c0c5-9ff8-4a6f-a0cd-f57f59a34b43", response_data["deploymentId"], )
def test_call_filter_method_passing_each_group( self, group_dev_namespace_fixture): """ Todos os grupos de um response devem ser passados para os filtros, um de cada vez """ with application.test_request_context("/v2/groups/group-b", method="GET") as ctx: ctx.request.user = self.user ok_response = FlaskResponse( response=json.dumps(group_dev_namespace_fixture["groups"][1]), status=HTTPStatus.OK, headers={}, ) response_wrapper = Response(ctx.request, ok_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline={OperationType.READ: [DummyFilter()]}, filter_method_name_callback=lambda *args: "response_group", ) final_response_data = json.loads(final_response.data) returned_group = MarathonGroup.from_json(final_response_data) self.assertEqual("/dummy/dev/group-b", returned_group.id) self.assertEqual("/dummy/dev/group-b/group-b0", returned_group.groups[0].id)
def test_do_not_call_filter_if_it_doesnt_implement_response_method(self): class DummyRequestFilter: def write(self, user, request_app): return request_app with application.test_request_context("/v2/apps/foo", method="GET") as ctx: single_full_app_one = deepcopy(self.single_full_app_fixture) single_full_app_one['id'] = "/dev/foo" with RequestsMock() as rsps: rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//foo', json={"app": single_full_app_one}, status=200) original_response = FlaskResponse(response=json.dumps({"app": single_full_app_one}), status=200, headers={}) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch(user=self.user, request=response_wrapper, filters_pipeline={OperationType.READ: [DummyRequestFilter()]}, filter_method_name_callback=lambda *args: "response" ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual("/dev/foo", response_data['app']['id'])
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)
def test_response_task_remove_from_response_tasks_outside_same_prefix_namespace( self, tasks_multinamespace_fixure): """ Confirmamos que uma task do namespace "developers" *deve ser removida* quando o usuário faz parte do namespace "dev", mesmo esses dois namespaces começando pelo mesmo prefixo """ with application.test_request_context("/v2/tasks/", method="GET") as ctx: original_response = FlaskResponse( response=json.dumps(tasks_multinamespace_fixure), status=200) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response_task", ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual( [ "waiting.01339ffa-ce9c-11e7-8144-2a27410e5638", "waiting.0432fd4b-ce9c-11e7-8144-2a27410e5638", ], [task["id"] for task in response_data["tasks"]], ) self.assertEqual(2, len(response_data["tasks"]))
def test_response_has_app_modified_by_filter(self): """ Certificamos que um request em uma app, roda o pipeline e essa app pode ser modificada por algum filtro """ with application.test_request_context("/v2/apps/dev/foo", method="GET") as ctx: single_full_app_one = deepcopy(self.single_full_app_fixture) single_full_app_one["id"] = "/dev/foo" _url = conf.MARATHON_ADDRESSES[0] + "/v2/apps//dev/foo" with RequestsMock() as rsps: rsps.add( method="GET", url=_url, json={"app": single_full_app_one}, status=200, ) original_response = FlaskResponse( response=json.dumps({"app": single_full_app_one}), status=200, headers={}, ) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response", ) self.assertEqual(200, final_response.status_code) self.assertEqual("/foo", json.loads(final_response.data)["app"]["id"])
def test_response_task_remove_from_response_tasks_outside_namespace( self, tasks_multinamespace_fixure): class ModifyTaskFilter: def response_task(self, user, response_task): response_task.id = response_task.id.replace( f"{user.current_account.namespace}_", "") return response_task with application.test_request_context("/v2/tasks/", method="GET") as ctx: original_response = FlaskResponse( response=json.dumps(tasks_multinamespace_fixure), status=200) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response_task", ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(2, len(response_data["tasks"])) self.assertEqual( [ "waiting.01339ffa-ce9c-11e7-8144-2a27410e5638", "waiting.0432fd4b-ce9c-11e7-8144-2a27410e5638", ], [task["id"] for task in response_data["tasks"]], )
def test_changes_from_all_filters_are_persisted_after_response_join( self, group_dev_namespace_fixture): """ Certificamos que uma modificação de um filtro não é perdida durante a execução do pipeline. No response final, todas as modificações devem estar disponíveis. """ with application.test_request_context("/v2/groups/group-b", method="GET") as ctx: ctx.request.user = self.user ok_response = FlaskResponse( response=json.dumps(group_dev_namespace_fixture["groups"][1]), status=HTTPStatus.OK, headers={}, ) ctx.request.user = self.user response_wrapper = Response(ctx.request, ok_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline={ OperationType.READ: [DummyFilter(), FooFilter()] }, filter_method_name_callback=lambda *args: "response_group", ) final_response_data = json.loads(final_response.data) returned_group = MarathonGroup.from_json(final_response_data) self.assertEqual("/foo/dummy/dev/group-b/appb0", returned_group.apps[0].id) self.assertEqual( "/foo/dummy/dev/group-b/group-b0/app0", returned_group.groups[0].apps[0].id, )
def test_response_task_filter_modifies_task(self, tasks_get_fixture): class ModifyTaskFilter: def response_task(self, user, response_task, original_task): response_task.id = f"{response_task.id}_bla" return response_task with application.test_request_context("/v2/tasks/", method="GET") as ctx: original_response = FlaskResponse( response=json.dumps(tasks_get_fixture), status=200) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline={OperationType.READ: [ModifyTaskFilter()]}, filter_method_name_callback=lambda *args: "response_task", ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(3, len(response_data["tasks"])) self.assertEqual( [ "dev_waiting.01339ffa-ce9c-11e7-8144-2a27410e5638_bla", "dev_waiting.0432fd4b-ce9c-11e7-8144-2a27410e5638_bla", "dev_waiting.75b2ed9c-ce9c-11e7-8144-2a27410e5638_bla", ], [task["id"] for task in response_data["tasks"]], )
def test_response_apps_remove_outside_current_namespace(self): with application.test_request_context("/v2/apps/", method="GET") as ctx: single_full_app_one = deepcopy(self.single_full_app_fixture) single_full_app_one['id'] = '/dev/foo' single_full_app_two = deepcopy(self.single_full_app_fixture) single_full_app_two['id'] = '/dev/other-app' single_full_app_three = deepcopy(self.single_full_app_fixture) single_full_app_three['id'] = '/othernamespace/other-app' with RequestsMock() as rsps: rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/foo', body=json.dumps({'app': single_full_app_one}), status=200) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/other-app', body=json.dumps({'app': single_full_app_two}), status=200) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//othernamespace/other-app', body=json.dumps({'app': single_full_app_three}), status=200) original_response = FlaskResponse(response=json.dumps({'apps': [single_full_app_one, single_full_app_two, single_full_app_three]}), status=200, headers={}) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch(user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response" ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(2, len(response_data['apps'])) self.assertEqual("/foo", response_data['apps'][0]['id']) self.assertEqual("/other-app", response_data['apps'][1]['id'])
def test_filters_can_modify_all_apps_from_group_and_subgroups(self, group_dev_namespace_fixture): """ Um fltro deve poder alterar todas as apps de todos os grupos de um response. """ with application.test_request_context("/v2/groups/group-b", method="GET") as ctx: ctx.request.user = self.user ok_response = FlaskResponse( response=json.dumps(group_dev_namespace_fixture['groups'][1]), status=HTTPStatus.OK, headers={} ) with RequestsMock() as rsps: rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/groups//dev/group-b', body=json.dumps(deepcopy(group_dev_namespace_fixture['groups'][1])), status=200) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/groups//dev/group-b/group-b0', body=json.dumps(deepcopy(group_dev_namespace_fixture['groups'][1]['groups'][0])), status=200) response_wrapper = Response(ctx.request, ok_response) final_response = dispatch(user=self.user, request=response_wrapper, filters_pipeline={OperationType.READ: [DummyFilter()]}, filter_method_name_callback=lambda *args: "response_group") final_response_data = json.loads(final_response.data) returned_group = MarathonGroup.from_json(final_response_data) self.assertEqual("/dummy/dev/group-b/appb0", returned_group.apps[0].id) self.assertEqual("/dummy/dev/group-b/group-b0/app0", returned_group.groups[0].apps[0].id)
def test_response_has_list_of_apps_modified_by_filters(self): """ Certificamos que uma lista de apps pode ser modificada por algum filtro de response. """ with application.test_request_context("/v2/apps/", method="GET") as ctx: single_full_app_one = deepcopy(self.single_full_app_fixture) single_full_app_one["id"] = "/dev/foo" single_full_app_two = deepcopy(self.single_full_app_fixture) single_full_app_two["id"] = "/dev/other-app" original_response = FlaskResponse( response=json.dumps( {"apps": [single_full_app_one, single_full_app_two]}), status=200, headers={}, ) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response", ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(2, len(response_data["apps"])) self.assertEqual("/foo", response_data["apps"][0]["id"]) self.assertEqual("/other-app", response_data["apps"][1]["id"])
def new(request: http_wrappers.Request) -> Response: filtered_request = dispatch(user=request.request.user, request=request) upstream_response = upstream_request(filtered_request) if upstream_response.status_code == HTTPStatus.OK: response = http_wrappers.Response(request.request, upstream_response) return dispatch( request.request.user, response, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda response, *args: FILTERS_METHOD_NAMES[response.request_resource] ) return upstream_response
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)
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)
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)
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)
def _apply_response_filters(self, response) -> Response: response = http_wrappers.Response(self.wrapped_request.request, response) return dispatch( self.user, response, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda response, *args: FILTERS_METHOD_NAMES[response.request_resource] )
def test_call_write_task_if_is_v2_tasks_request(self): """ Se o request é em PUT /v2/tasks o pipeline deve chamar write_task() """ class DummyFilter: def write_task(self, user, request_task, orignal_tasK): request_task.id = request_task.id + "_suffix" return request_task def write(self, user, request_app, original_app): raise Exception() class DummyFilter2: """ Esse filtro existe por causa de uma regressão, onde o método do filtro era chamado mais de uma vez, quando o filtro seguinte não implementa o mesmo método do filtro anterior. Nesse caso o método do filtro anterior era chamado novamente. """ pass pipeline = { OperationType.WRITE: [ DummyFilter(), DummyFilter2(), ] } 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_suffix", filtered_app.id)
def test_response_task_returns_empty_response_when_all_tasks_are_from_other_namespace(self, tasks_namespace_infra_fixture): with application.test_request_context("/v2/tasks/", method="GET") as ctx: original_response = FlaskResponse(response=json.dumps(tasks_namespace_infra_fixture), status=200) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch(user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response" ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(0, len(response_data['tasks']))
def test_preserve_healthchecks_added_by_filter(self): class AddNewHealthCheckFilter: def write(self, user, request_app, original_app): hc_data = { "command": None, "gracePeriodSeconds": 30, "intervalSeconds": 10, "maxConsecutiveFailures": 3, "path": "/marathon/healthcheck", "portIndex": 0, "protocol": "HTTP", "timeoutSeconds": 5, "ignoreHttp1xx": False } request_app.health_checks.append( MarathonHealthCheck.from_json(hc_data)) return request_app pipeline = { OperationType.WRITE: [ AddNewHealthCheckFilter(), ] } request_data = {"healthChecks": []} request_app = SieveMarathonApp.from_json(request_data) original_app = SieveMarathonApp.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 = SieveMarathonApp.from_json( filtered_request.get_json()) self.assertEqual(1, len(filtered_app.health_checks)) self.assertEqual("/marathon/healthcheck", filtered_app.health_checks[0].json_repr()['path']) self._check_other_fields("healthChecks", filtered_app)
def test_remove_from_response_apps_outside_same_prefix_namespace(self): """ Uma app com namespace `/developers/` deve ser removida quando o usuário faz parte do namespace ´/dev/`, mesmo os namespaces começando pelo mesmo prefixo """ with application.test_request_context("/v2/apps/", method="GET") as ctx: single_full_app_one = deepcopy(self.single_full_app_fixture) single_full_app_one["id"] = "/dev/foo" single_full_app_two = deepcopy(self.single_full_app_fixture) single_full_app_two["id"] = "/dev/other-app" single_full_app_three = deepcopy(self.single_full_app_fixture) single_full_app_three["id"] = "/developers/other-app" original_response = FlaskResponse( response=json.dumps({ "apps": [ single_full_app_one, single_full_app_two, single_full_app_three, ] }), status=200, headers={}, ) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response", ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(2, len(response_data["apps"])) self.assertEqual( ["/foo", "/other-app"], [app["id"] for app in response_data["apps"]], )
def test_remove_from_response_apps_outside_same_prefix_namespace(self): """ Uma app com namespace `/developers/` deve ser removida quando o usuário faz parte do namespace ´/dev/`, mesmo os namespaces começando pelo mesmo prefixo """ with application.test_request_context("/v2/apps/", method="GET") as ctx: single_full_app_one = deepcopy(self.single_full_app_fixture) single_full_app_one['id'] = '/dev/foo' single_full_app_two = deepcopy(self.single_full_app_fixture) single_full_app_two['id'] = '/dev/other-app' single_full_app_three = deepcopy(self.single_full_app_fixture) single_full_app_three['id'] = '/developers/other-app' with RequestsMock() as rsps: rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/foo', body=json.dumps({'app': single_full_app_one}), status=200) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/other-app', body=json.dumps({'app': single_full_app_two}), status=200) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//developers/other-app', body=json.dumps({'app': single_full_app_three}), status=200) original_response = FlaskResponse(response=json.dumps({'apps': [single_full_app_one, single_full_app_two, single_full_app_three]}), status=200, headers={}) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch(user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response" ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(2, len(response_data['apps'])) self.assertEqual(["/foo", "/other-app"], [app['id'] for app in response_data['apps']])
def test_response_apps_remove_outside_current_namespace(self): with application.test_request_context("/v2/apps/", method="GET") as ctx: single_full_app_one = deepcopy(self.single_full_app_fixture) single_full_app_one["id"] = "/dev/foo" single_full_app_two = deepcopy(self.single_full_app_fixture) single_full_app_two["id"] = "/dev/other-app" single_full_app_three = deepcopy(self.single_full_app_fixture) single_full_app_three["id"] = "/othernamespace/other-app" original_response = FlaskResponse( response=json.dumps({ "apps": [ single_full_app_one, single_full_app_two, single_full_app_three, ] }), status=200, headers={}, ) ctx.request.user = self.user response_wrapper = Response(ctx.request, original_response) final_response = dispatch( user=self.user, request=response_wrapper, filters_pipeline=FILTERS_PIPELINE[FilterType.RESPONSE], filter_method_name_callback=lambda *args: "response", ) response_data = json.loads(final_response.data) self.assertEqual(200, final_response.status_code) self.assertEqual(2, len(response_data["apps"])) self.assertEqual("/foo", response_data["apps"][0]["id"]) self.assertEqual("/other-app", response_data["apps"][1]["id"])