def test_return_401_if_key_not_found(self): with application.test_client() as client: r = client.get("/v2/apps", headers={"Authorization": "Token token-not-found"}) self.assertEqual(401, r.status_code) self.assertEqual("Authorization token is invalid", json.loads(r.data)['msg'])
def test_groups_endpoint_returns_group_on_root_json( self, group_dev_namespace_fixture): auth_header = { "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" } with application.test_client() as client: 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', 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 = client.get("/v2/groups/group-b", headers=auth_header) self.assertEqual(200, response.status_code) self.assertEqual("/group-b", json.loads(response.data)['id'])
def test_it_creates_a_response_using_a_dict_of_headers(self, fixture): """ O atributo headers de um objeto `request.models.Response` é utilizado para gerar o response do hollowman. Por ser do tipo `CaseInsentiveDict`, quebra a implementação do flask e faz com que seja necessário o typecast para `dict`. """ test_client = application.test_client() with application.app_context(): auth_header = self.make_auth_header(self.normal_user, self.account) with RequestsMock() as rsps: rsps.add( method="GET", url=conf.MARATHON_ADDRESSES[0] + "/v2/apps", body=json.dumps({"apps": [fixture]}), status=200, ) rsps.add( method="GET", url=conf.MARATHON_ADDRESSES[0] + f"/v2/groups//{self.account.namespace}/", body=json.dumps({"apps": [fixture]}), status=200, ) r = test_client.get("/v2/apps", headers=auth_header) self.assertEqual(200, r.status_code)
def test_return_401_if_jwt_token_not_present(self): test_client = application.test_client() with application.app_context(): r = test_client.get("/v2/apps") self.assertEqual(401, r.status_code) self.assertEqual("Authorization token is invalid", json.loads(r.data)['msg'])
def test_queue_removes_queued_appps_from_other_namespaces( self, queue_get_fixture): """ Removemos todas as apps que não sejam do namespace atual. Esse teste tambéem confirma que o namespace é removido dos elementos que voltam no response. """ auth_header = { "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" } with application.test_client() as client: with RequestsMock() as rsps: rsps.add( method="GET", url=conf.MARATHON_ADDRESSES[0] + "/v2/queue", status=200, json=queue_get_fixture, ) response = client.get("/v2/queue", headers=auth_header) self.assertEqual(200, response.status_code) response_data = json.loads(response.data) self.assertEqual(1, len(response_data["queue"])) self.assertEqual("/waiting", response_data["queue"][0]["app"]["id"])
def test_disables_http_when_suspending_app(self, single_full_app_fixture): auth_header = { "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" } app_id = "/dev/my-app" single_full_app_fixture["id"] = app_id single_full_app_fixture["instances"] = 0 # Suspend app expected_labels = single_full_app_fixture["labels"].copy() expected_labels["traefik.enable"] = False with application.test_client() as client: with RequestsMock() as rsps: rsps.add( method="GET", url=conf.MARATHON_ADDRESSES[0] + f"/v2/apps//dev{app_id}", body=json.dumps({"app": single_full_app_fixture}), status=200, ) rsps.add( method="POST", url=conf.MARATHON_ADDRESSES[0] + f"/v2/apps{app_id}", body=json.dumps({ **single_full_app_fixture, "labels": expected_labels }), status=200, ) response = client.post( f"/v2/apps{app_id}", headers=auth_header, json=single_full_app_fixture, ) self.assertEqual(200, response.status_code)
def test_test_change_to_next_account_no_account_left(self): """ User tem duas accounts e já está usando a segunda, quando pedir a próxima retornamos a primeira account """ with application.app_context(), application.test_client() as client: jwt_token = self.generate_jwt_token_for_user( self.user, self.account_infra) response = client.post( "/hollow/account/next", headers={ "Authorization": "JWT {}".format(jwt_token.decode("utf8")) }, ) self.assertEqual(200, response.status_code) response_data = json.loads(response.data) self.assertEqual(self.user.email, response_data["user"]["email"]) self.assertEqual(self.user.name, response_data["user"]["name"]) self.assertEqual(self.account_dev.id, response_data["current_account"]["id"]) self.assertEqual(self.account_dev.name, response_data["current_account"]["name"]) jwt_response_header = response_data["jwt_token"] self.assertTrue(jwt_response_header) returned_token = jwt.decode(jwt_response_header, key=SECRET_KEY) self.assertEqual(self.user.email, returned_token["user"]["email"]) self.assertEqual(self.user.name, returned_token["user"]["name"]) self.assertEqual(self.account_dev.id, returned_token["current_account"]["id"]) self.assertEqual(self.account_dev.name, returned_token["current_account"]["name"])
def test_apps_endpoint_accepts_app_with_versions_in_the_name( self, single_full_app_fixture): """ Regressão: Commit 0068801288b33a407676a6aa9b521881854de2f7 Devemos aceitar uma app que possui a string "versions" em um lugar no nome, especialmente no fim de uma parte do path, ex: "/workers/conversions/splitter" """ auth_header = { "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" } single_full_app_fixture['id'] = "/dev/workers/conversions/splitter" with application.test_client() as client: with RequestsMock() as rsps: rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps/dev/workers/conversions/splitter', body=json.dumps({"app": single_full_app_fixture}), status=200) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/workers/conversions/splitter', body=json.dumps({"app": single_full_app_fixture}), status=200) response = client.get("/v2/apps/workers/conversions/splitter", headers=auth_header) self.assertEqual(200, response.status_code) self.assertTrue('app' in json.loads(response.data)) self.assertEqual("/workers/conversions/splitter", json.loads(response.data)['app']['id'])
def test_change_account_has_permmission(self): """ Troca para uma conta que o user atual está vinculado. """ with application.app_context(), \ application.test_client() as client: jwt_token = self.generate_jwt_token_for_user( self.user, self.user.accounts[0]) response = client.post( "/hollow/account/change/{}".format(self.user.accounts[1].id), headers={ "Authorization": "JWT {}".format(jwt_token.decode("utf8")) }) self.assertEqual(200, response.status_code) response_data = json.loads(response.data) self.assertEqual(self.user.tx_email, response_data["user"]["email"]) self.assertEqual(self.user.tx_name, response_data["user"]["name"]) self.assertEqual(self.user.accounts[1].id, response_data["current_account"]["id"]) self.assertEqual(self.user.accounts[1].name, response_data["current_account"]["name"]) jwt_response_token = response_data["jwt_token"] self.assertTrue(jwt_response_token) returned_token = jwt.decode(jwt_response_token, key=SECRET_KEY) self.assertEqual(self.user.tx_email, returned_token["user"]["email"]) self.assertEqual(self.user.tx_name, returned_token["user"]["name"]) self.assertEqual(self.user.accounts[1].id, returned_token["current_account"]["id"]) self.assertEqual(self.user.accounts[1].name, returned_token["current_account"]["name"])
def test_jwt_add_redirect_with_account_id_on_token_after_login(self): """ Depois do processo de login, o token JWT conterá o account_id da conta padrão do usuário. """ test_client = application.test_client() with application.app_context(), \ patch.object(routes, "check_authentication_successful", return_value={"email": self.user.tx_email}),\ patch.object(routes, "redirect") as redirect_mock: response = test_client.get("/authenticate/google") jwt_token = redirect_mock.call_args_list[0][0][0].split("=")[1] token_content = jwt.decode(jwt_token, conf.SECRET_KEY) self.assertEqual(self.user.tx_email, token_content["user"]["email"]) self.assertEqual(self.user.tx_name, token_content["user"]["name"]) self.assertEqual(self.user.accounts[0].id, token_content["current_account"]["id"]) self.assertEqual(self.user.accounts[0].name, token_content["current_account"]["name"]) self.assertEqual(self.user.accounts[0].namespace, token_content["current_account"]["namespace"])
def test_versions_endpoint_returns_app_on_root_json( self, single_full_app_fixture): """ Apesar de um GET /v2/apps/<app-id> retornat a app em: {"app": <app-definition} um GET /v2/apps/<app-id>/versions/<version-id> retorna em: {<app-definition>} Aqui conferimos que nosso pipeline retorna um response consistente com essa regra """ auth_header = { "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" } single_full_app_fixture['id'] = "/dev/foo" with application.test_client() as client: with RequestsMock() as rsps: rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps/dev/foo/versions/2017-10-31T13:01:07.768Z', body=json.dumps(single_full_app_fixture), status=200) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/foo', body=json.dumps({"app": single_full_app_fixture}), status=200) response = client.get( "/v2/apps/foo/versions/2017-10-31T13:01:07.768Z", headers=auth_header) self.assertEqual(200, response.status_code) self.assertEqual("/foo", json.loads(response.data)['id'])
def test_v2_deployments_get(self, fixture): with application.test_client() as client, RequestsMock() as rsps: rsps.add(url=f'{conf.MARATHON_ADDRESSES[0]}/v2/deployments', body=json.dumps(fixture), method='GET', status=200) response = client.get("/v2/deployments", headers=self.auth_header) self.assertEqual(json.loads(response.data), [{ 'affectedApps': ['/foo'], 'currentActions': [{ 'action': 'ScaleApplication', 'app': '/foo', 'apps': None, 'pod': None, 'type': None, 'readinessCheckResults': [{ 'taskId': 'foo.c9de6033', 'lastResponse': { 'body': '{}', 'contentType': 'application/json', 'status': 500 }, 'name': 'myReadyCheck', 'ready': False }] }], 'currentStep': 2, 'id': '97c136bf-5a28-4821-9d94-480d9fbb01c8', 'steps': [{ 'actions': [{ 'action': 'StartApplication', 'app': '/foo', 'apps': None, 'pod': None, 'type': None, 'readinessCheckResults': None }] }, { 'actions': [{ 'action': 'ScaleApplication', 'app': '/foo', 'apps': None, 'pod': None, 'type': None, 'readinessCheckResults': None }] }], 'totalSteps': 2, 'version': '2015-09-30T09:09:17.614Z', }])
def test_v2_artifacts(self): with application.test_client() as client: client.get( "/v2/artifacts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.get( "/v2/artifacts/etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.put( "/v2/artifacts/etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.post( "/v2/artifacts/etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.delete( "/v2/artifacts/etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.get( "/v2/artifacts//etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.put( "/v2/artifacts//etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.post( "/v2/artifacts//etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) client.delete( "/v2/artifacts//etc/hosts", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }, ) self.assertEqual(9, self.proxy_mock.call_count)
def test_return_200_if_key_found(self): with application.test_client() as client: r = client.get("/v2/apps", headers={ "Authorization": " Token 69ed620926be4067a36402c3f7e9ddf0" }) self.assertEqual(200, r.status_code)
def test_v2_info(self): with application.test_client() as client: client.get("/v2/info", headers={ "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0" }) self.assertEqual(1, self.proxy_mock.call_count)
def test_download_by_id_expired(self): """ Se o ID não existir mais no cache, retornamos 404 """ download_id = "7094c8e5b131416a87ccdc3e7d3131a6" with application.test_client() as client: resp = client.get(f"/tasks/downloads/{download_id}") self.assertEquals(404, resp.status_code)
def test_redirect_to_right_main_js(self): response = application.test_client().get( "/v2/plugins/some-plugin/main.js") self.assertEqual(302, response.status_code) self.assertEqual( "http://localhost/static/plugins/some-plugin/main.js", response.headers["Location"], )
def test_zk_metrics_server_found(self): with application.test_client() as client: with patch.dict(os.environ, HOLLOWMAN_METRICS_ZK_ID_0="127.0.0.1"): expected_return = {"connections": 10, "is_leader": 0} self.parse_stat_output_mock.return_value = expected_return res = client.get("/_cat/metrics/zk/1") self.assertEqual(200, res.status_code) self.assertEqual(expected_return, json.loads(res.data.decode("utf8")))
def test_index_path(self): response = application.test_client().get("/") self.assertEqual(response.status_code, 302) self.assertTrue("Location" in response.headers) self.assertEqual( "http://localhost/v2/apps", response.headers["Location"] ) redirect_value = "https://marathon.sieve.com.br" with patch.object( conf, "REDIRECT_ROOTPATH_TO", new=redirect_value ) as redirect_mock: response = application.test_client().open("/") self.assertEqual(response.status_code, 302) self.assertTrue("Location" in response.headers) self.assertEqual(redirect_value, response.headers["Location"])
def test_token_return_401_if_when_account_does_not_exist(self): with application.test_client() as client: r = client.get("/v2/apps?account_id=1024", headers={ "Authorization": " Token 69ed620926be4067a36402c3f7e9ddf0" }) self.assertEqual(401, r.status_code) self.assertEqual("Account does not exist", json.loads(r.data)['msg'])
def test_do_not_dispatch_response_pipeline_if_upstream_returns_404(self): auth_header = {"Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0"} with application.test_client() as client: with RequestsMock() as rsps: rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/foo', body=json.dumps({'message': "App /foo not found"}), status=404) rsps.add(method='GET', url=conf.MARATHON_ADDRESSES[0] + '/v2/apps/dev/foo', body=json.dumps({'message': "App /foo not found"}), status=404) response = client.get("/v2/apps/foo", headers=auth_header) self.assertEqual(404, response.status_code)
def test_login_failed_user_not_found(self): test_client = application.test_client() with application.app_context(), \ patch.object(routes, "check_authentication_successful", return_value={"email": "*****@*****.**"}), \ patch.object(routes, "render_template") as render_mock: response = test_client.get("/authenticate/google") render_mock.assert_called_once_with("login-failed.html", reason="User not found")
def test_token_return_401_if_user_has_no_associated_account(self): with application.test_client() as client: r = client.get("/v2/apps", headers={ "Authorization": " Token 7b4184bfe7d2349eb56bcfb9dc246cf8" }) self.assertEqual(401, r.status_code) self.assertEqual("No associated account", json.loads(r.data)['msg'])
def test_login_failed_user_does_not_have_any_account(self): test_client = application.test_client() with application.app_context(), \ patch.object(routes, "check_authentication_successful", return_value={"email": self.user_with_no_accounts.tx_email}), \ patch.object(routes, "render_template") as render_mock: response = test_client.get("/authenticate/google") render_mock.assert_called_once_with( "login-failed.html", reason="No associated accounts")
def test_login_failed_invalid_oauth2(self): test_client = application.test_client() with application.app_context(), \ patch.object(routes, "check_authentication_successful", return_value={}), \ patch.object(routes, "render_template") as render_mock: response = test_client.get("/authenticate/google") render_mock.assert_called_once_with("login-failed.html", reason="Invalid OAuth2 code")
def test_return_200_if_jwt_token_valid(self): test_client = application.test_client() with application.app_context(): jwt_token = jwt_auth.jwt_encode_callback( jwt_generate_user_info(self.user, self.account_dev)) auth_header = { "Authorization": "JWT {}".format(jwt_token.decode('utf-8')) } r = test_client.get("/v2/apps", headers=auth_header) self.assertEqual(200, r.status_code)
def test_jwt_do_not_trigger_token_auth_if_jwt_token_is_present(self): """ Both auth uses the same header: Authorization. Token Auth should *not* be called if current token is JWT """ with application.test_client() as test_client, \ application.app_context(), \ patch.object(decorators, "HollowmanSession") as session_mock: r = test_client.get("/v2/apps", headers={"Authorization": "JWT Token"}) self.assertEqual(0, session_mock.call_count)
def test_tasks_browse_files( self, task_browse_file_fixture, one_task_json_fixture, one_slave_json_fixture, slave_state_fixture, ): task_id = "infra_mysql.b331f6c9-fb9e-11e7-ab4b-faf0633ea91f" sandbox_directory = "/tmp/mesos/slaves/2084863b-12d1-4319-b515-992eab91a53d-S1/frameworks/27b52920-3899-4b90-a1d6-bf83a87f3612-0000/executors/dev_infra_mysql.b331f6c9-fb9e-11e7-ab4b-faf0633ea91f/runs/e14d7537-c1d0-4846-a076-25d623d6a70f" with application.test_client() as client: with RequestsMock() as rsps: rsps.add( method="GET", url= f"{DEFAULT_MESOS_ADDRESS}/tasks?task_id={self.user.current_account.namespace}_{task_id}", body=json.dumps(one_task_json_fixture), status=200, match_querystring=True, ) rsps.add( method="GET", url= f"{DEFAULT_MESOS_ADDRESS}/slaves?slave_id=2084863b-12d1-4319-b515-992eab91a53d-S1", body=json.dumps(one_slave_json_fixture), status=200, match_querystring=True, ) rsps.add( method="GET", url="http://127.0.0.1:5051/state", body=json.dumps(slave_state_fixture), status=200, ) rsps.add( method="GET", url= f"http://127.0.0.1:5051/files/browse?path={sandbox_directory}", body=json.dumps(task_browse_file_fixture), status=200, match_querystring=True, ) resp = client.get(f"/tasks/{task_id}/files", headers=self.auth_header) resp_data = json.loads(resp.data) self.assertEquals(200, resp.status_code) self.assertEqual(4, len(resp_data)) self.assertEqual( sorted([ "/stdout", "/stdout.logrotate.conf", "/stderr", "/stderr.logrotate.conf", ]), sorted([u["path"] for u in resp_data]), )
def test_v2_queue_get(self, fixture): with application.test_client() as client, RequestsMock() as rsps: rsps.add(url=f'{conf.MARATHON_ADDRESSES[0]}/v2/queue', body=json.dumps(fixture), method='GET', status=200) response = client.get("/v2/queue", headers=self.auth_header) response_data = json.loads(response.data) self.assertEqual(1, len(response_data['queue'])) self.assertEqual("/waiting", response_data['queue'][0]['app']['id'])
def test_healthcheck_return_500_if_all_servers_down(self): marathon_addresses = [ "http://invalid-host:8080", "http://172.30.0.1:8080", "http://172.31.0.1:8080" ] with application.test_client() as client, RequestsMock() as rsps,\ patch.multiple(conf, MARATHON_ADDRESSES=marathon_addresses), \ patch.multiple(conf, MARATHON_LEADER=marathon_addresses[1]): response = client.get("/healthcheck") self.assertEqual(500, response.status_code)