Skip to content
This repository was archived by the owner on Mar 13, 2022. It is now read-only.

Commit 66a45cd

Browse files
committed
Make duck-typing in serialize_body method more restrictive
1 parent dd15ac6 commit 66a45cd

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

Diff for: dynamic/client.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ def ensure_namespace(self, resource, namespace, body):
9898
return namespace
9999

100100
def serialize_body(self, body):
101-
if hasattr(body, 'to_dict'):
101+
"""Serialize body to raw dict so apiserver can handle it
102+
103+
:param body: kubernetes resource body, current support: Union[Dict, ResourceInstance]
104+
"""
105+
# This should match any `ResourceInstance` instances
106+
if callable(getattr(body, 'to_dict', None)):
102107
return body.to_dict()
103108
return body or {}
104109

Diff for: dynamic/test_client.py

+30
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from kubernetes.client import api_client
2121

2222
from . import DynamicClient
23+
from .resource import ResourceInstance, ResourceField
2324
from .exceptions import ResourceNotFoundError
2425

2526

@@ -392,3 +393,32 @@ def test_node_apis_partial_object_metadata(self):
392393
resp = api.get(**params)
393394
self.assertEqual('PartialObjectMetadataList', resp.kind)
394395
self.assertEqual('meta.k8s.io/v1', resp.apiVersion)
396+
397+
398+
class TestDynamicClientSerialization(unittest.TestCase):
399+
400+
@classmethod
401+
def setUpClass(cls):
402+
config = base.get_e2e_configuration()
403+
cls.client = DynamicClient(api_client.ApiClient(configuration=config))
404+
cls.pod_manifest = {
405+
'apiVersion': 'v1',
406+
'kind': 'Pod',
407+
'metadata': {'name': 'foo-pod'},
408+
'spec': {'containers': [{'name': "main", 'image': "busybox"}]},
409+
}
410+
411+
def test_dict_type(self):
412+
self.assertEqual(self.client.serialize_body(self.pod_manifest), self.pod_manifest)
413+
414+
def test_resource_instance_type(self):
415+
inst = ResourceInstance(self.client, self.pod_manifest)
416+
self.assertEqual(self.client.serialize_body(inst), self.pod_manifest)
417+
418+
def test_resource_field(self):
419+
"""`ResourceField` is a special type which overwrites `__getattr__` method to return `None`
420+
when a non-existent attribute was accessed. which means it can pass any `hasattr(...)` tests.
421+
"""
422+
res = ResourceField(foo='bar')
423+
# method will return original object when it doesn't know how to proceed
424+
self.assertEqual(self.client.serialize_body(res), res)

0 commit comments

Comments
 (0)