Skip to content

Commit

Permalink
Ensure apiVersion and kind are set for 'list' requests
Browse files Browse the repository at this point in the history
  • Loading branch information
benfiola authored and gtsystem committed Jul 1, 2024
1 parent e77c6bb commit 1f05156
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 6 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ build/
dist/
*.egg-info
site/
htmlcov/
htmlcov/
.vscode
.devcontainer

13 changes: 11 additions & 2 deletions lightkube/core/generic_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import httpx

from . import dataclasses_dict as dc_d
from . import resource as r
from ..config.kubeconfig import KubeConfig, SingleConfig, DEFAULT_KUBECONFIG
from ..config import client_adapter
Expand Down Expand Up @@ -192,6 +193,14 @@ def raise_for_status(resp):
def build_adapter_request(self, br: BasicRequest):
return self._client.build_request(br.method, br.url, params=br.params, json=br.data, headers=br.headers)

def convert_to_resource(self, res: Type[r.Resource], item: dict) -> r.Resource:
resource_def = r.api_info(res).resource
if not issubclass(res, dc_d.DataclassDictMixIn):
raise NotImplementedError(res)
item.setdefault("apiVersion", resource_def.api_version)
item.setdefault("kind", resource_def.kind)
return res.from_dict(item, lazy=self._lazy)

def handle_response(self, method, resp, br):
self.raise_for_status(resp)
res = br.response_type
Expand All @@ -205,10 +214,10 @@ def handle_response(self, method, resp, br):
br.params['continue'] = data['metadata']['continue']
else:
cont = False
return cont, (res.from_dict(obj, lazy=self._lazy) for obj in data['items'])
return cont, (self.convert_to_resource(res, obj) for obj in data['items'])
else:
if res is not None:
return res.from_dict(data, lazy=self._lazy)
return self.convert_to_resource(res, data)


class GenericSyncClient(GenericClient):
Expand Down
4 changes: 2 additions & 2 deletions lightkube/core/resource.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import NamedTuple, List, Optional
from typing import NamedTuple, List, Optional, Type, Union
from dataclasses import dataclass


Expand All @@ -25,7 +25,7 @@ class Resource:
_api_info: ApiInfo


def api_info(res: Resource):
def api_info(res: Union[Resource, Type[Resource]]):
return res._api_info


Expand Down
4 changes: 4 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[pytest]
minversion = 6.0
testpaths =
tests
7 changes: 7 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
'httpx >= 0.24.0',
'PyYAML'
],
extras_require={
"dev": [
"pytest",
"pytest-asyncio<0.17.0",
"respx"
]
},
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
Expand Down
18 changes: 18 additions & 0 deletions tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ async def test_list_global(client: lightkube.AsyncClient):
client.list(Binding, namespace=lightkube.ALL_NS)
await client.close()


@respx.mock
@pytest.mark.asyncio
async def test_list_namespaced(client: lightkube.AsyncClient):
resp = {'items':[{'metadata': {'name': 'xx'}}, {'metadata': {'name': 'yy'}}]}
respx.get("https://localhost:9443/api/v1/namespaces/default/pods").respond(json=resp)
pods = [pod async for pod in client.list(Pod)]
for pod, expected in zip(pods, resp["items"]):
assert pod.metadata is not None
assert pod.metadata.name == expected["metadata"]["name"]
assert pod.apiVersion is not None
assert pod.kind is not None

respx.get("https://localhost:9443/api/v1/namespaces/other/pods?labelSelector=k%3Dv").respond(json=resp)
pods = client.list(Pod, namespace="other", labels={'k': 'v'})
assert [pod.metadata.name async for pod in pods] == ['xx', 'yy']


@respx.mock
@pytest.mark.asyncio
async def test_list_chunk_size(client: lightkube.AsyncClient):
Expand Down
6 changes: 5 additions & 1 deletion tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,11 @@ def test_list_namespaced(client: lightkube.Client):
resp = {'items':[{'metadata': {'name': 'xx'}}, {'metadata': {'name': 'yy'}}]}
respx.get("https://localhost:9443/api/v1/namespaces/default/pods").respond(json=resp)
pods = client.list(Pod)
assert [pod.metadata.name for pod in pods] == ['xx', 'yy']
for pod, expected in zip(pods, resp["items"]):
assert pod.metadata is not None
assert pod.metadata.name == expected["metadata"]["name"]
assert pod.apiVersion is not None
assert pod.kind is not None

respx.get("https://localhost:9443/api/v1/namespaces/other/pods?labelSelector=k%3Dv").respond(json=resp)
pods = client.list(Pod, namespace="other", labels={'k': 'v'})
Expand Down

0 comments on commit 1f05156

Please sign in to comment.