Skip to content

Commit 3193f6e

Browse files
committed
fix: KubernetesObjectSerializer::deserialize() should support list api
1 parent 15c6ef8 commit 3193f6e

File tree

2 files changed

+113
-4
lines changed

2 files changed

+113
-4
lines changed

src/serializer.ts

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ObjectSerializer } from './api';
1+
import { ObjectSerializer, V1ListMeta } from './api';
22
import { V1ObjectMeta } from './gen/model/v1ObjectMeta';
33

44
type AttributeType = {
@@ -37,9 +37,52 @@ class KubernetesObject {
3737
];
3838
}
3939

40+
class KubernetesObjectList {
41+
/**
42+
* APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
43+
*/
44+
'apiVersion'?: string;
45+
/**
46+
* Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
47+
*/
48+
'kind'?: string;
49+
'metadata'?: V1ListMeta;
50+
'items'?: KubernetesObject[];
51+
52+
static attributeTypeMap: AttributeType[] = [
53+
{
54+
name: 'apiVersion',
55+
baseName: 'apiVersion',
56+
type: 'string',
57+
},
58+
{
59+
name: 'kind',
60+
baseName: 'kind',
61+
type: 'string',
62+
},
63+
{
64+
name: 'metadata',
65+
baseName: 'metadata',
66+
type: 'V1ListMeta',
67+
},
68+
];
69+
}
70+
4071
const isKubernetesObject = (data: unknown): boolean =>
4172
!!data && typeof data === 'object' && 'apiVersion' in data && 'kind' in data;
4273

74+
const isKubernetesObjectList = (data: any): boolean => isKubernetesObject(data) && 'items' in data;
75+
76+
const getClassOfKubernetesInstance = (data: any): any => {
77+
if (!isKubernetesObject(data)) {
78+
return null;
79+
}
80+
if (isKubernetesObjectList(data)) {
81+
return KubernetesObjectList;
82+
}
83+
return KubernetesObject;
84+
};
85+
4386
/**
4487
* Wraps the ObjectSerializer to support custom resources and generic Kubernetes objects.
4588
*/
@@ -90,12 +133,13 @@ class KubernetesObjectSerializer {
90133
return obj;
91134
}
92135

93-
if (!isKubernetesObject(data)) {
136+
const kubernetesClass = getClassOfKubernetesInstance(data);
137+
if (!kubernetesClass) {
94138
return obj;
95139
}
96140

97-
const instance = new KubernetesObject();
98-
for (const attributeType of KubernetesObject.attributeTypeMap) {
141+
const instance = new kubernetesClass();
142+
for (const attributeType of kubernetesClass.attributeTypeMap) {
99143
instance[attributeType.name] = ObjectSerializer.deserialize(
100144
data[attributeType.baseName],
101145
attributeType.type,
@@ -108,6 +152,10 @@ class KubernetesObjectSerializer {
108152
}
109153
instance[key] = value;
110154
}
155+
if (instance.items) {
156+
instance.items = instance.items.map((item: any) => this.deserialize(item, ''));
157+
}
158+
111159
return instance;
112160
}
113161
}

src/serializer_test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,66 @@ describe('KubernetesObjectSerializer', () => {
186186
const res = KubernetesObjectSerializer.serialize(s, 'unknown');
187187
expect(res).to.deep.equal(s);
188188
});
189+
190+
it('should deserialize a list of unknown objects', () => {
191+
const s = {
192+
apiVersion: 'v1alpha1',
193+
kind: 'MyCustomResourceList',
194+
metadata: {
195+
resourceVersion: '1',
196+
},
197+
items: [
198+
{
199+
apiVersion: 'v1alpha1',
200+
kind: 'MyCustomResource',
201+
metadata: {
202+
name: 'k8s-js-client-test',
203+
namespace: 'default',
204+
creationTimestamp: '2022-01-01T00:00:00.000Z',
205+
},
206+
data: {
207+
key: 'value',
208+
},
209+
},
210+
],
211+
};
212+
const res = KubernetesObjectSerializer.deserialize(s, 'v1alpha1MyCustomResource');
213+
expect(res).to.deep.equal({
214+
apiVersion: 'v1alpha1',
215+
kind: 'MyCustomResourceList',
216+
metadata: {
217+
_continue: undefined,
218+
remainingItemCount: undefined,
219+
resourceVersion: '1',
220+
selfLink: undefined,
221+
},
222+
items: [
223+
{
224+
apiVersion: 'v1alpha1',
225+
kind: 'MyCustomResource',
226+
metadata: {
227+
name: 'k8s-js-client-test',
228+
namespace: 'default',
229+
creationTimestamp: new Date('2022-01-01T00:00:00.000Z'),
230+
uid: undefined,
231+
annotations: undefined,
232+
labels: undefined,
233+
finalizers: undefined,
234+
generateName: undefined,
235+
selfLink: undefined,
236+
resourceVersion: undefined,
237+
generation: undefined,
238+
ownerReferences: undefined,
239+
deletionTimestamp: undefined,
240+
deletionGracePeriodSeconds: undefined,
241+
managedFields: undefined,
242+
},
243+
data: {
244+
key: 'value',
245+
},
246+
},
247+
],
248+
});
249+
});
189250
});
190251
});

0 commit comments

Comments
 (0)