def split(self) -> Apps: if self.is_read_request(): response_content = json.loads(self.response.data) if self.is_list_apps_request(): for app in response_content['apps']: response_app = SieveMarathonApp.from_json(app) app = self.marathon_client.get_app(self.object_id or response_app.id) yield response_app, app return elif self.is_group_request(): response_group = SieveAppGroup( MarathonGroup.from_json(response_content)) for current_group in response_group.iterate_groups(): group_id = current_group.id group_id_without_namespace = self._remove_namespace_if_exists( self.request.user.current_account.namespace, group_id) original_group = self._get_original_group( self.request.user, group_id_without_namespace) yield current_group, original_group return elif self.is_tasks_request(): for task in response_content['tasks']: response_task = MarathonTask.from_json(task) yield response_task, response_task return elif self.is_deployment(): content = response_content deployments = (MarathonDeployment.from_json(deploy) for deploy in content) for deployment in deployments: yield deployment, deployment return elif self.is_queue_request(): queue_data = response_content queued_apps = (MarathonQueueItem.from_json(queue_item) for queue_item in queue_data['queue']) for queued_app in queued_apps: yield queued_app, queued_app return else: response_app = SieveMarathonApp.from_json( response_content.get('app') or response_content) app = self.marathon_client.get_app(self.object_id) yield response_app, app return if self.is_write_request(): response_content = json.loads(self.response.data) if 'tasks' in response_content: for task in response_content['tasks']: response_task = MarathonTask.from_json(task) yield response_task, response_task return return yield SieveMarathonApp(), self.marathon_client.get_app(self.app_id)
def split(self) -> Apps: if self.is_read_request(): response_content = json.loads(self.response.data) if self.is_list_apps_request(): all_apps = list( AsgardAppGroup.from_json(response_content).iterate_apps() ) for response_app in all_apps: yield response_app, response_app return elif self.is_group_request(): response_group = AsgardAppGroup( MarathonGroup.from_json(response_content) ) for current_group in response_group.iterate_groups(): yield current_group, current_group return elif self.is_tasks_request(): for task in response_content["tasks"]: response_task = MarathonTask.from_json(task) yield response_task, response_task return elif self.is_deployment(): content = response_content deployments = ( MarathonDeployment.from_json(deploy) for deploy in content ) for deployment in deployments: yield deployment, deployment return elif self.is_queue_request(): queue_data = response_content queued_apps = ( MarathonQueueItem.from_json(queue_item) for queue_item in queue_data["queue"] ) for queued_app in queued_apps: yield queued_app, queued_app return else: response_app = AsgardApp.from_json( response_content.get("app") or response_content ) app = self.marathon_client.get_app(self.object_id) yield response_app, app return if self.is_write_request(): response_content = json.loads(self.response.data) if "tasks" in response_content: for task in response_content["tasks"]: response_task = MarathonTask.from_json(task) yield response_task, response_task return return yield AsgardApp(), self.marathon_client.get_app(self.app_id)
def split(self) -> Apps: if self.is_read_request(): if self.is_list_apps_request(): apps = self.marathon_client.list_apps() for app in apps: yield self.merge_marathon_apps(MarathonApp(), app), app elif self.is_app_request(): app = self._get_original_app(self.request.user, self.object_id) yield self.merge_marathon_apps(MarathonApp(), app), app elif self.is_group_request(): self.group = self._get_original_group(self.request.user, self.object_id) for app in self.group.iterate_apps(): yield self.merge_marathon_apps(MarathonApp(), app), app return # Request is a WRITE if self.is_app_request(): for app in self.get_request_data(): request_app = MarathonApp.from_json(app) app = self._get_original_app(self.request.user, self.object_id or request_app.id) yield self.merge_marathon_apps(request_app, app), app elif self.is_tasks_request(): request_data = self.request.get_json() for task_id in request_data['ids']: request_task = MarathonTask.from_json({"id": task_id}) yield request_task, request_task return
def merge_marathon_apps(self, modified_app, base_app): """ A junção das duas apps (request_app (aqui modified_app) e original_app (aqui base_app)) é sempre feita pegando todos os dados da original_app e jogando os dados da requst_app "em cima". Não podemos usar o `minimal=Fase` na request_app pois para requests que estão *incompletos*, ou seja, sem alguns vampos (já veremos exemplo) se esássemos minimal=False, iríramos apagar esses "campos faltantes" da original_app. Exemplos: request_app = {"instances": 10} original_app está completa, com envs, constraints e tudo mais. se usamos `minimal=False` na request_app, teremos um JSON com *todos* os campos em branco, menos o "instances". Então quando fizermos `merged.update(modified_app.json_repr(minimal=False))`, vamos no final ter um JSON apenas com o campo "instances" perrnchido e todo o restante vazio. """ merged = base_app.json_repr(minimal=False) merged.update(modified_app.json_repr(minimal=True)) try: raw_request_data = json.loads(self.request.data) for key in REMOVABLE_KEYS: if key in raw_request_data: merged[key] = raw_request_data[key] except Exception as e: pass if isinstance(base_app, MarathonTask): return MarathonTask.from_json(merged) return SieveMarathonApp.from_json(merged)
def test_response_tasks_remove_namespace_from_all_tasks(self, tasks_get_fixture): task = MarathonTask.from_json(tasks_get_fixture['tasks'][0]) task.id = "dev_" + task.id task.app_id = "/dev" + task.app_id filtered_task = self.filter.response_task(self.user, task, task) self.assertEqual("waiting.01339ffa-ce9c-11e7-8144-2a27410e5638", filtered_task.id) self.assertEqual("/waiting", filtered_task.app_id)
def test_request_add_namespace_to_all_tasks(self, tasks_get_fixture): """ Um POST em /v2/tasks/delete deve ajustar o ID de todas as tasks envolvidas """ task = MarathonTask.from_json(tasks_get_fixture['tasks'][0]) filtered_task = self.filter.write_task(self.user, task, task) self.assertEqual("dev_waiting.01339ffa-ce9c-11e7-8144-2a27410e5638", filtered_task.id) self.assertEqual("/dev/waiting", filtered_task.app_id)
def test_remove_namespace_from_task(self): """ Certifica que o namespace é removido corretamente, ou seja, apenas a primeira ocorrência deve ser removida """ tasks = [MarathonTask.from_json({"id": "dev_app_my_other_dev_path", "app_id": "/dev/app/my/other/dev/path"})] expected_task_ids = ["app_my_other_dev_path"] self.filter._remove_namespace_from_tasks(tasks, "dev") self.assertEqual(expected_task_ids, [task.id for task in tasks])
def test_split_tasks_GET(self, tasks_get_fixture): """ No cado de um GET, o retorno sempre é uma lista de apps. """ with application.test_request_context('/v2/tasks/', method='GET') as ctx: response = FlaskResponse( response=json.dumps(tasks_get_fixture), status=HTTPStatus.OK ) ctx.request.user = self.user response = Response(ctx.request, response) tasks_tuple = list(response.split()) self.assertEqual([MarathonTask.from_json(task) for task in tasks_get_fixture['tasks']], [task[0] for task in tasks_tuple])
def test_split_staks_POST_scale_false(self, tasks_get_fixture): """ No caso do POST com `?scale=false` o retorno é: - Lista de apps que foram killed Por isso usamos a fixture de tasks/get.json aqui """ with application.test_request_context('/v2/tasks/delete?scale=false', method='POST') as ctx: response = FlaskResponse( response=json.dumps(tasks_get_fixture), status=HTTPStatus.OK ) ctx.request.user = self.user response = Response(ctx.request, response) tasks_tuple = list(response.split()) self.assertEqual([MarathonTask.from_json(task) for task in tasks_get_fixture['tasks']], [task[0] for task in tasks_tuple])
def test_response_tasks_returns_none_if_group_outside_current_namespace( self, tasks_get_fixture): task = MarathonTask.from_json(tasks_get_fixture["tasks"][0]) task.id = "othernamespace_" + task.id task.app_id = "/othernamespace" + task.app_id self.assertIsNone(self.filter.response_task(self.user, task, task))