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

Make duck-typing checking in serialize_body method more restrictive #241

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion dynamic/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,12 @@ def ensure_namespace(self, resource, namespace, body):
return namespace

def serialize_body(self, body):
if hasattr(body, 'to_dict'):
"""Serialize body to raw dict so apiserver can handle it

:param body: kubernetes resource body, current support: Union[Dict, ResourceInstance]
"""
# This should match any `ResourceInstance` instances
if callable(getattr(body, 'to_dict', None)):
return body.to_dict()
return body or {}

Expand Down
30 changes: 30 additions & 0 deletions dynamic/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from kubernetes.client import api_client

from . import DynamicClient
from .resource import ResourceInstance, ResourceField
from .exceptions import ResourceNotFoundError


Expand Down Expand Up @@ -392,3 +393,32 @@ def test_node_apis_partial_object_metadata(self):
resp = api.get(**params)
self.assertEqual('PartialObjectMetadataList', resp.kind)
self.assertEqual('meta.k8s.io/v1', resp.apiVersion)


class TestDynamicClientSerialization(unittest.TestCase):

@classmethod
def setUpClass(cls):
config = base.get_e2e_configuration()
cls.client = DynamicClient(api_client.ApiClient(configuration=config))
cls.pod_manifest = {
'apiVersion': 'v1',
'kind': 'Pod',
'metadata': {'name': 'foo-pod'},
'spec': {'containers': [{'name': "main", 'image': "busybox"}]},
}

def test_dict_type(self):
self.assertEqual(self.client.serialize_body(self.pod_manifest), self.pod_manifest)

def test_resource_instance_type(self):
inst = ResourceInstance(self.client, self.pod_manifest)
self.assertEqual(self.client.serialize_body(inst), self.pod_manifest)

def test_resource_field(self):
"""`ResourceField` is a special type which overwrites `__getattr__` method to return `None`
when a non-existent attribute was accessed. which means it can pass any `hasattr(...)` tests.
"""
res = ResourceField(foo='bar')
# method will return original object when it doesn't know how to proceed
self.assertEqual(self.client.serialize_body(res), res)