Skip to content

Commit f8f590a

Browse files
ISSUE #390
1 parent de05f5c commit f8f590a

File tree

3 files changed

+95
-40
lines changed

3 files changed

+95
-40
lines changed

packages/plugins/minos-discovery-kong/minos/plugins/kong/client.py

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,52 @@
11
from __future__ import (
22
annotations,
33
)
4-
from abc import ABC
4+
5+
from abc import (
6+
ABC,
7+
)
8+
from datetime import (
9+
datetime,
10+
timedelta,
11+
)
512
from uuid import (
613
UUID,
714
)
815

916
import httpx as httpx
10-
from datetime import datetime
11-
from datetime import timedelta
12-
1317
import jwt
18+
from pytz import (
19+
utc,
20+
)
21+
1422
from minos.common import (
15-
SetupMixin,
1623
Config,
24+
SetupMixin,
1725
)
18-
from pytz import utc
1926

2027

21-
class KongClient: #(ABC, SetupMixin):
28+
class KongClient(ABC, SetupMixin):
2229
"""Kong Client class."""
2330

24-
def __init__(self, route: str, **kwargs): #def __init__(self, host: str, port: str, token_expiration_minutes: int, **kwargs):
31+
def __init__(self, host: str = None, port: str = None, token_expiration_sec: int = 60 * 5, **kwargs):
2532
super().__init__(**kwargs)
26-
self.route = route #f"http://{host}:{port}"
27-
#self.token_expiration_minutes = token_expiration_minutes
33+
if host is None:
34+
host = "localhost"
35+
if port is None:
36+
port = 8001
37+
38+
self.route = f"http://{host}:{port}"
39+
self.token_expiration_sec = token_expiration_sec
40+
41+
@classmethod
42+
def _from_config(cls, config: Config, **kwargs) -> KongClient:
43+
discovery_config = config.get_discovery()
2844

29-
# @classmethod
30-
# def _from_config(cls, config: Config, **kwargs) -> KongClient:
31-
# discovery_config = config.get_discovery()
32-
#
33-
# token_expiration = discovery_config.get("token-exp-minutes")
34-
# return cls(token_expiration=token_expiration, **kwargs)
45+
token_expiration_sec = discovery_config.get("token-exp-minutes")
46+
host = discovery_config.get("host")
47+
port = discovery_config.get("port")
48+
49+
return cls(host=host, port=port, token_expiration_sec=token_expiration_sec, **kwargs)
3550

3651
@staticmethod
3752
async def register_service(
@@ -152,21 +167,24 @@ async def activate_basic_auth_plugin_on_route(self, route_id: str):
152167
return resp
153168

154169
async def activate_jwt_plugin_on_route(self, route_id: str):
155-
payload = {"name": "jwt",
156-
"config": {"secret_is_base64": False, "run_on_preflight": True, "claims_to_verify": ["exp", "nbf"]}}
170+
payload = {
171+
"name": "jwt",
172+
"config": {"secret_is_base64": False, "run_on_preflight": True, "claims_to_verify": ["exp", "nbf"]},
173+
}
157174

158175
async with httpx.AsyncClient() as client:
159176
resp = await client.post(f"{self.route}/routes/{route_id}/plugins", json=payload)
160177
return resp
161178

162-
async def get_jwt_token(self, key: str, secret: str, algorithm: str = 'HS256', exp: datetime = None, nbf: datetime = None) -> str:
179+
async def get_jwt_token(
180+
self, key: str, secret: str, algorithm: str = "HS256", exp: datetime = None, nbf: datetime = None
181+
) -> str:
163182
payload = {"iss": key, "exp": exp, "nbf": nbf}
164183

165184
current = datetime.now(tz=utc)
166185

167186
if not exp:
168-
#payload["exp"] = current + timedelta(minutes=self.token_expiration_minutes)
169-
payload["exp"] = current + timedelta(minutes=120)
187+
payload["exp"] = current + timedelta(seconds=self.token_expiration_sec)
170188

171189
if not nbf:
172190
payload["nbf"] = current

packages/plugins/minos-discovery-kong/minos/plugins/kong/discovery.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def __init__(
4141
host: Optional[str] = None,
4242
port: Optional[int] = None,
4343
circuit_breaker_exceptions: Iterable[type] = tuple(),
44+
client: KongClient = None,
4445
**kwargs,
4546
):
4647
if host is None:
@@ -50,7 +51,11 @@ def __init__(
5051
super().__init__(
5152
host, port, circuit_breaker_exceptions=(httpx.HTTPStatusError, *circuit_breaker_exceptions), **kwargs
5253
)
53-
self.kong = KongClient(self.route)
54+
55+
if client is None:
56+
client = KongClient()
57+
58+
self.client = client
5459

5560
self.auth_type = None
5661
if "auth_type" in kwargs:
@@ -66,8 +71,9 @@ def _from_config(cls, config: Config, **kwargs) -> KongDiscoveryClient:
6671
auth_type = config.get_by_key("discovery.auth-type")
6772
except Exception:
6873
auth_type = None
74+
client = KongClient.from_config(config)
6975

70-
return super()._from_config(config, auth_type=auth_type, **kwargs)
76+
return super()._from_config(config, auth_type=auth_type, client=client, **kwargs)
7177

7278
async def subscribe(
7379
self, host: str, port: int, name: str, endpoints: list[dict[str, str]], *args, **kwargs
@@ -83,13 +89,13 @@ async def subscribe(
8389
:return: This method does not return anything.
8490
"""
8591

86-
fnsr = partial(self.kong.register_service, self.route, name, host, port)
92+
fnsr = partial(self.client.register_service, self.route, name, host, port)
8793
response_service = await self.with_circuit_breaker(fnsr) # register a service
8894
if response_service.status_code == 409: # service already exist
8995
# if service already exist, delete and add again
90-
fn_delete = partial(self.kong.delete_service, self.route, name)
96+
fn_delete = partial(self.client.delete_service, self.route, name)
9197
await self.with_circuit_breaker(fn_delete) # delete the service
92-
fnsr = partial(self.kong.register_service, self.route, name, host, port)
98+
fnsr = partial(self.client.register_service, self.route, name, host, port)
9399
response_service = await self.with_circuit_breaker(fnsr) # send the servie subscription again
94100

95101
content_service = response_service.json() # get the servie information like the id
@@ -98,7 +104,7 @@ async def subscribe(
98104
endpointClass = Endpoint(endpoint["url"])
99105

100106
fn = partial(
101-
self.kong.create_route,
107+
self.client.create_route,
102108
self.route,
103109
["http"],
104110
[endpoint["method"]],
@@ -111,15 +117,15 @@ async def subscribe(
111117

112118
if "authenticated" in endpoint and self.auth_type:
113119
if self.auth_type == "basic-auth":
114-
fn = partial(self.kong.activate_basic_auth_plugin_on_route, route_id=resp["id"])
120+
fn = partial(self.client.activate_basic_auth_plugin_on_route, route_id=resp["id"])
115121
await self.with_circuit_breaker(fn)
116122
elif self.auth_type == "jwt":
117-
fn = partial(self.kong.activate_jwt_plugin_on_route, route_id=resp["id"])
123+
fn = partial(self.client.activate_jwt_plugin_on_route, route_id=resp["id"])
118124
await self.with_circuit_breaker(fn)
119125

120126
if "authorized_groups" in endpoint:
121127
fn = partial(
122-
self.kong.activate_acl_plugin_on_route, route_id=resp["id"], allow=endpoint["authorized_groups"]
128+
self.client.activate_acl_plugin_on_route, route_id=resp["id"], allow=endpoint["authorized_groups"]
123129
)
124130
await self.with_circuit_breaker(fn)
125131

@@ -133,6 +139,6 @@ async def unsubscribe(self, name: str, *args, **kwargs) -> httpx.Response:
133139
:param kwargs: Additional named arguments.
134140
:return: This method does not return anything.
135141
"""
136-
fn = partial(self.kong.delete_service, self.route, name)
142+
fn = partial(self.client.delete_service, self.route, name)
137143
response = await self.with_circuit_breaker(fn)
138144
return response

packages/plugins/minos-discovery-kong/tests/test_kong/test_client.py

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
import os
22
import unittest
3+
from datetime import (
4+
datetime,
5+
timedelta,
6+
)
37
from uuid import (
48
uuid4,
59
)
610

711
import httpx
12+
from pytz import (
13+
utc,
14+
)
815

16+
from minos.common import (
17+
Config,
18+
)
919
from minos.plugins.kong import (
1020
KongClient,
1121
KongDiscoveryClient,
1222
)
1323
from tests.utils import (
24+
CONFIG_FILE_PATH,
1425
TEST_HOST,
1526
)
16-
from datetime import datetime
17-
from datetime import timedelta
18-
19-
import jwt
20-
from pytz import utc
2127

2228
PROTOCOL = "http"
2329

@@ -28,7 +34,7 @@ class TestKongDiscoveryClient(unittest.IsolatedAsyncioTestCase):
2834

2935
def setUp(self) -> None:
3036
self.client = KongDiscoveryClient(self.KONG_HOST, self.KONG_PORT, circuit_breaker_time=0.1)
31-
self.kong = KongClient(self.client.route)
37+
self.kong = KongClient()
3238

3339
@staticmethod
3440
def generate_underscore_uuid():
@@ -195,7 +201,7 @@ async def test_jwt_token_generation(self):
195201
self.assertTrue(201 == response.status_code)
196202
resp = response.json()
197203

198-
token = await self.kong.get_jwt_token(key=resp['key'], secret=resp['secret'])
204+
token = await self.kong.get_jwt_token(key=resp["key"], secret=resp["secret"])
199205

200206
self.assertGreater(len(token), 50)
201207

@@ -213,11 +219,36 @@ async def test_jwt_token_generation_with_expiration(self):
213219
resp = response.json()
214220

215221
current = datetime.now(tz=utc)
216-
token = await self.kong.get_jwt_token(key=resp['key'], secret=resp['secret'],
217-
exp=current + timedelta(minutes=10), nbf=current + timedelta(minutes=9))
222+
token = await self.kong.get_jwt_token(
223+
key=resp["key"],
224+
secret=resp["secret"],
225+
exp=current + timedelta(minutes=10),
226+
nbf=current + timedelta(minutes=9),
227+
)
218228

219229
self.assertGreater(len(token), 50)
220230

221231

232+
class TestKongClientFromConfig(unittest.IsolatedAsyncioTestCase):
233+
KONG_HOST = os.getenv("KONG_HOST", "localhost")
234+
KONG_PORT = os.getenv("KONG_PORT", 8001)
235+
236+
def setUp(self) -> None:
237+
config = Config(CONFIG_FILE_PATH)
238+
self.kong = KongClient.from_config(config=config)
239+
240+
@staticmethod
241+
def generate_underscore_uuid():
242+
name = str(uuid4())
243+
return name.replace("-", "_")
244+
245+
async def test_create_consumer(self):
246+
user_uuid = uuid4()
247+
user_name = self.generate_underscore_uuid()
248+
response = await self.kong.create_consumer(username=user_name, user=user_uuid, tags=[])
249+
250+
self.assertTrue(201 == response.status_code)
251+
252+
222253
if __name__ == "__main__":
223254
unittest.main()

0 commit comments

Comments
 (0)