Skip to content
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
55 changes: 52 additions & 3 deletions src/serializer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ObjectSerializer } from './api';
import { V1ObjectMeta } from './gen/model/v1ObjectMeta';
import { V1ListMeta } from './gen/model/v1ListMeta';

type AttributeType = {
name: string;
Expand Down Expand Up @@ -37,9 +38,52 @@ class KubernetesObject {
];
}

class KubernetesObjectList {
/**
* 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
*/
'apiVersion'?: string;
/**
* 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
*/
'kind'?: string;
'metadata'?: V1ListMeta;
'items'?: KubernetesObject[];

static attributeTypeMap: AttributeType[] = [
{
name: 'apiVersion',
baseName: 'apiVersion',
type: 'string',
},
{
name: 'kind',
baseName: 'kind',
type: 'string',
},
{
name: 'metadata',
baseName: 'metadata',
type: 'V1ListMeta',
},
];
}

const isKubernetesObject = (data: unknown): boolean =>
!!data && typeof data === 'object' && 'apiVersion' in data && 'kind' in data;

const isKubernetesObjectList = (data: any): boolean => isKubernetesObject(data) && 'items' in data;

const getClassOfKubernetesInstance = (data: any): any => {
if (!isKubernetesObject(data)) {
return null;
}
if (isKubernetesObjectList(data)) {
return KubernetesObjectList;
}
return KubernetesObject;
};

/**
* Wraps the ObjectSerializer to support custom resources and generic Kubernetes objects.
*/
Expand Down Expand Up @@ -90,12 +134,13 @@ class KubernetesObjectSerializer {
return obj;
}

if (!isKubernetesObject(data)) {
const kubernetesClass = getClassOfKubernetesInstance(data);
if (!kubernetesClass) {
return obj;
}

const instance = new KubernetesObject();
for (const attributeType of KubernetesObject.attributeTypeMap) {
const instance = new kubernetesClass();
for (const attributeType of kubernetesClass.attributeTypeMap) {
instance[attributeType.name] = ObjectSerializer.deserialize(
data[attributeType.baseName],
attributeType.type,
Expand All @@ -108,6 +153,10 @@ class KubernetesObjectSerializer {
}
instance[key] = value;
}
if (instance.items) {
instance.items = instance.items.map((item: any) => this.deserialize(item, ''));
}

return instance;
}
}
Expand Down
61 changes: 61 additions & 0 deletions src/serializer_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,66 @@ describe('KubernetesObjectSerializer', () => {
const res = KubernetesObjectSerializer.serialize(s, 'unknown');
expect(res).to.deep.equal(s);
});

it('should deserialize a list of unknown objects', () => {
const s = {
apiVersion: 'v1alpha1',
kind: 'MyCustomResourceList',
metadata: {
resourceVersion: '1',
},
items: [
{
apiVersion: 'v1alpha1',
kind: 'MyCustomResource',
metadata: {
name: 'k8s-js-client-test',
namespace: 'default',
creationTimestamp: '2022-01-01T00:00:00.000Z',
},
data: {
key: 'value',
},
},
],
};
const res = KubernetesObjectSerializer.deserialize(s, 'v1alpha1MyCustomResource');
expect(res).to.deep.equal({
apiVersion: 'v1alpha1',
kind: 'MyCustomResourceList',
metadata: {
_continue: undefined,
remainingItemCount: undefined,
resourceVersion: '1',
selfLink: undefined,
},
items: [
{
apiVersion: 'v1alpha1',
kind: 'MyCustomResource',
metadata: {
name: 'k8s-js-client-test',
namespace: 'default',
creationTimestamp: new Date('2022-01-01T00:00:00.000Z'),
uid: undefined,
annotations: undefined,
labels: undefined,
finalizers: undefined,
generateName: undefined,
selfLink: undefined,
resourceVersion: undefined,
generation: undefined,
ownerReferences: undefined,
deletionTimestamp: undefined,
deletionGracePeriodSeconds: undefined,
managedFields: undefined,
},
data: {
key: 'value',
},
},
],
});
});
});
});
Loading