class ApiAdminClientTest(unittest.TestCase): def setUp(self): self.faker = Faker() self.faker.add_provider(ApiDataProvider) self.api_name = self.faker.api_name() self.api_upstream_url = self.faker.url() self.api_uris = self.faker.api_uris() self.api_kong_id = self.faker.kong_id() hosts = [ self.faker.domain_name() for _ in range(self.faker.random_int(0, 10)) ] methods = ["GET", "POST"] strip_uri = self.faker.boolean() preserve_host = self.faker.boolean() retries = self.faker.random_int() https_only = self.faker.boolean() http_if_terminated = self.faker.boolean() upstream_connect_timeout = self.faker.random_int() upstream_send_timeout = self.faker.random_int() upstream_read_timeout = self.faker.random_int() self.api_data = ApiData( name=self.api_name, upstream_url=self.api_upstream_url, uris=self.api_uris, hosts=hosts, methods=methods, strip_uri=strip_uri, preserve_host=preserve_host, retries=retries, https_only=https_only, http_if_terminated=http_if_terminated, upstream_connect_timeout=upstream_connect_timeout, upstream_send_timeout=upstream_send_timeout, upstream_read_timeout=upstream_read_timeout) self.requests_mock = MagicMock() self.session_mock = MagicMock() self.requests_mock.session.return_value = self.session_mock data_w_id = {**self.api_data, **{'id': self.api_kong_id}} self.session_mock.post.return_value.json.return_value = data_w_id self.session_mock.put.return_value.json.return_value = data_w_id self.session_mock.patch.return_value.json.return_value = data_w_id self.session_mock.get.return_value.status_code = 200 self.session_mock.post.return_value.status_code = 201 self.session_mock.patch.return_value.status_code = 200 self.session_mock.delete.return_value.status_code = 204 self.kong_admin_url = self.faker.url() self.apis_endpoint = self.kong_admin_url + 'apis/' self.api_admin_client = ApiAdminClient( self.kong_admin_url, _session=self.requests_mock.session()) def test_api_admin_create(self): """ Test: ApiAdminClient.create() creates a api data dictionary instance with given api's data. """ # Exercise api_data = self.api_admin_client.create(self.api_name, self.api_upstream_url, uris=self.api_uris) # Verify self.assertEqual(api_data['name'], self.api_name) self.assertEqual(api_data['upstream_url'], self.api_upstream_url) self.assertEqual(api_data['uris'], self.api_uris) def test_api_admin_create_triggers_http_request_to_kong_server(self): """ Test: ApiAdminClient.create() triggers an http request to kong server to create the api in the server. """ # Exercise self.api_admin_client.create(self.api_name, self.api_upstream_url, uris=self.api_uris) # Verify expected_api_data = ApiData(name=self.api_name, upstream_url=self.api_upstream_url, uris=self.api_uris) self.session_mock.post.assert_called_once_with(self.apis_endpoint, data=expected_api_data) def test_api_admin_create_using_api_data(self): """ Test: passing a ApiData instance results in the same behaviour as normal create """ # Setup orig_data = ApiData(name=self.api_name, upstream_url=self.api_upstream_url, uris=self.api_uris) # Exercise self.api_admin_client.create(orig_data) # Verify self.session_mock.post.assert_called_once_with(self.apis_endpoint, data=orig_data) def test_api_admin_delete_by_name(self): """ Test: ApiAdmin.delete(api_name) deletes it from kong server """ # Setup self.api_admin_client.create(self.api_name, self.api_upstream_url, uris=self.api_uris) # Exercise self.api_admin_client.delete(self.api_name) # Verify api_endpoint = self.apis_endpoint + self.api_name self.session_mock.delete.assert_called_once_with(api_endpoint) def test_api_admin_delete_by_kong_id(self): """ Test: ApiAdmin.delete(api_kong_id) deletes it from kong server """ # Setup self.api_admin_client.create(self.api_name, self.api_upstream_url, uris=self.api_uris) # Exercise self.api_admin_client.delete(self.api_kong_id) # Verify api_endpoint = self.apis_endpoint + self.api_kong_id self.session_mock.delete.assert_called_once_with(api_endpoint) def test_api_admin_update(self): # Setup api_data = self.api_admin_client.create(self.api_name, self.api_upstream_url, uris=self.api_uris) new_uri = self.faker.api_path() # Exercise api_data.add_uri(new_uri) response = self.api_admin_client.update(api_data['name'], **api_data) # Verify self.assertTrue(isinstance(response, ApiData)) self.assertEqual(response, api_data) expected_data = {} for k, v in api_data.items(): expected_data[k] = self.api_admin_client._stringify_if_list(v) api_endpoint = self.apis_endpoint + self.api_name self.session_mock.patch.assert_called_once_with(api_endpoint, data=expected_data) def test_api_admin_list(self): """ Test: ApiAdmin.list() returns a generator ApiData instances of all apis in kong server """ # Setup amount = self.faker.random_int(1, 50) apis = [] for _ in range(amount): api_data = self.api_admin_client.create(self.faker.api_name(), self.faker.url(), uris=self.faker.api_uris()) apis.append(api_data) self.session_mock.get.return_value.json.return_value = { 'total': amount, 'data': apis } # Exercise apis_retrieved = list(self.api_admin_client.list()) actual_amount = len(apis_retrieved) # Verify for api in apis_retrieved: self.assertTrue(isinstance(api, ApiData)) self.assertEqual(amount, actual_amount) def test_api_admin_list_w_parameters(self): # Setup self.session_mock.get.return_value.json.return_value = { 'data': [self.api_data], 'total': 1 } # Exercise generator = self.api_admin_client.list( id=self.api_kong_id, name=self.api_name, upstream_url=self.api_upstream_url) generator.__next__() # Verify expected_data = { 'offset': None, 'size': 10, 'id': self.api_kong_id, 'name': self.api_name, 'upstream_url': self.api_upstream_url } self.session_mock.get.assert_called_once_with(self.apis_endpoint, data=expected_data) def test_api_admin_list_w_invalid_params(self): # Setup invalid_query = {'invalid_field': 'invalid_value'} # Verify self.assertRaisesRegex( KeyError, 'invalid_field', lambda: self.api_admin_client.list(**invalid_query)) def test_api_admin_count(self): """ Test: ApiAdmin.count() returns the number of created apis """ # Setup amount = self.faker.random_int(1, 50) apis = [] for _ in range(amount): api_data = self.api_admin_client.create(self.faker.api_name(), self.faker.url(), uris=self.faker.api_uris()) apis.append(api_data) self.session_mock.get.return_value.json.return_value = { 'total': amount, 'data': apis } # Exercise actual_amount = self.api_admin_client.count() # Verify self.assertEqual(amount, actual_amount) def test_create_bad_request(self): # Setup self.session_mock.post.return_value.status_code = 409 self.session_mock.post.return_value.content = 'bad request' # Verify self.assertRaisesRegex( NameError, r'bad request', lambda: self.api_admin_client.create( self.api_name, self.api_upstream_url, uris=self.api_uris)) def test_create_internal_server_error(self): # Setup self.session_mock.post.return_value.status_code = 500 self.session_mock.post.return_value.content = 'internal server error' # Verify self.assertRaisesRegex( Exception, r'internal server error', lambda: self.api_admin_client. create(self.api_name, self.api_upstream_url, uris=self.api_uris)) def test_delete_not_existing_api(self): # Setup self.session_mock.delete.return_value.status_code = 404 self.session_mock.delete.return_value.content = { "message": "not found" } # Verify self.assertRaisesRegex( NameError, r"not found", lambda: self.api_admin_client.delete(self.api_name)) def test_delete_internal_server_error(self): # Setup self.session_mock.delete.return_value.status_code = 500 self.session_mock.delete.return_value.content = 'internal server error' # Verify self.assertRaisesRegex( Exception, r'internal server error', lambda: self.api_admin_client.delete(self.api_name)) def test_update_w_invalid_parameters(self): # Setup self.session_mock.patch.return_value.status_code = 400 self.session_mock.patch.return_value.content = { "strip": "strip is an unknown field" } # Verify self.assertRaisesRegex( KeyError, r"unknown field", lambda: self.api_admin_client.update( self.api_data['name'], **self.api_data)) def test_update_not_existing_api(self): # Setup self.session_mock.patch.return_value.status_code = 404 self.session_mock.patch.return_value.content = {"message": "not found"} # Verify self.assertRaisesRegex( NameError, r"not found", lambda: self.api_admin_client.update( self.api_data['name'], **self.api_data)) def test_update_internal_server_error(self): # Setup self.session_mock.patch.return_value.status_code = 500 self.session_mock.patch.return_value.content = 'internal server error' # Verify self.assertRaisesRegex( Exception, r'internal server error', lambda: self.api_admin_client.update( self.api_data['name'], **self.api_data)) def test_list_internal_server_error(self): # Setup self.session_mock.get.return_value.status_code = 500 self.session_mock.get.return_value.content = 'internal server error' generator = self.api_admin_client.list() def boom(): for _ in generator: pass # Verify self.assertRaisesRegex(Exception, r'internal server error', boom) def test_retrieve_api(self): # Setup self.session_mock.get.return_value.status_code = 200 self.session_mock.get.return_value.json.return_value = dict( self.api_data) # Exercise retrieved = self.api_admin_client.retrieve(self.api_name) # Verify self.assertTrue(isinstance(retrieved, ApiData)) self.assertEqual(self.api_data, retrieved) def test_retrieve_non_created_api(self): # Setup self.session_mock.get.return_value.status_code = 404 self.session_mock.get.return_value.content = {"message": "Not found"} # Verify self.assertRaisesRegex( NameError, r'Not found', lambda: self.api_admin_client.retrieve(self.api_name)) def test_update_api_w_multiple_hosts(self): # Exercise self.api_admin_client.update(self.api_name, hosts=['host1', 'host2']) # Verify self.session_mock.patch.assert_called_once_with( self.apis_endpoint + self.api_name, data={'hosts': 'host1, host2'})