I am trying to deep copy items from the official Kubernetes Java V1 API models but there aren’t any copy constructors, Cloneable
, nor Serializable
interface implementations in any of the model objects. Does anyone have any ideas on how one may go about achieving this?
Edit:
Given the confusion of @RoddyoftheFrozenPeas I would like to clarify the situation for those who haven’t used the API.
The V1 Objects have other deeply nested V1 Objects. Take for instance the V1Pod has a V1PodSpec. Merely copying the objects fields at the top level will result in references to the nested objects. Modification of any of the nested objects will be observed in the other objects which retain references to said object.
Edit 2:
A simple self-contained test with results after execution. Perhaps I am doing something incorrectly?
V1Container v1Container = new V1ContainerBuilder() .withName("original container") .addToArgs("original argument 1") .build(); V1Pod original = new V1PodBuilder() .withNewMetadata() .withName("Original Pod") .endMetadata() .withNewSpec() .withContainers(v1Container) .endSpec() .build(); V1Pod copy = new V1Pod(); copy.setMetadata(original.getMetadata()); copy.getMetadata().setName("copy of pod"); copy.setSpec(original.getSpec()); copy.getSpec().getContainers().get(0).setName("copy container");
Original:
class V1Pod { apiVersion: null kind: null metadata: class V1ObjectMeta { annotations: null clusterName: null creationTimestamp: null deletionGracePeriodSeconds: null deletionTimestamp: null finalizers: null generateName: null generation: null labels: null managedFields: null name: copy of pod namespace: null ownerReferences: null resourceVersion: null selfLink: null uid: null } spec: class V1PodSpec { activeDeadlineSeconds: null affinity: null automountServiceAccountToken: null containers: [class V1Container { args: [original argument 1] command: null env: null envFrom: null image: null imagePullPolicy: null lifecycle: null livenessProbe: null name: copy container ports: null readinessProbe: null resources: null securityContext: null startupProbe: null stdin: null stdinOnce: null terminationMessagePath: null terminationMessagePolicy: null tty: null volumeDevices: null volumeMounts: null workingDir: null }] //... } status: null }
Copy:
class V1Pod { apiVersion: null kind: null metadata: class V1ObjectMeta { annotations: null clusterName: null creationTimestamp: null deletionGracePeriodSeconds: null deletionTimestamp: null finalizers: null generateName: null generation: null labels: null managedFields: null name: copy of pod namespace: null ownerReferences: null resourceVersion: null selfLink: null uid: null } spec: class V1PodSpec { activeDeadlineSeconds: null affinity: null automountServiceAccountToken: null containers: [class V1Container { args: [original argument 1] command: null env: null envFrom: null image: null imagePullPolicy: null lifecycle: null livenessProbe: null name: copy container ports: null readinessProbe: null resources: null securityContext: null startupProbe: null stdin: null stdinOnce: null terminationMessagePath: null terminationMessagePolicy: null tty: null volumeDevices: null volumeMounts: null workingDir: null }] /... } status: null }
Advertisement
Answer
The easiest way to copy K8s Java API resources is to utilize the withNew[field name]Like
methods available in the V1 object builder pattern. Here is a simple self-contained example that demonstrates usage for the case above.
Example:
V1Container v1Container = new V1ContainerBuilder() .withName("original container") .addToArgs("original argument 1") .build(); V1Pod original = new V1PodBuilder() .withNewMetadata() .withName("Original Pod") .endMetadata() .withNewSpec() .withContainers(v1Container) .endSpec() .build(); V1Pod copy = new V1PodBuilder() .withNewMetadataLike(original.getMetadata()) .endMetadata() .withNewSpecLike(original.getSpec()) .endSpec() .build(); copy.getMetadata().setName("copy of pod"); copy.getSpec().getContainers().get(0).setName("copy container");
Original:
class V1Pod { apiVersion: null kind: null metadata: class V1ObjectMeta { annotations: null clusterName: null creationTimestamp: null deletionGracePeriodSeconds: null deletionTimestamp: null finalizers: null generateName: null generation: null labels: null managedFields: null name: Original Pod namespace: null ownerReferences: null resourceVersion: null selfLink: null uid: null } spec: class V1PodSpec { activeDeadlineSeconds: null affinity: null automountServiceAccountToken: null containers: [class V1Container { args: [original argument 1] command: null env: null envFrom: null image: null imagePullPolicy: null lifecycle: null livenessProbe: null name: original container ports: null readinessProbe: null resources: null securityContext: null startupProbe: null stdin: null stdinOnce: null terminationMessagePath: null terminationMessagePolicy: null tty: null volumeDevices: null volumeMounts: null workingDir: null }] # ... } status: null }
Copy:
class V1Pod { apiVersion: null kind: null metadata: class V1ObjectMeta { annotations: null clusterName: null creationTimestamp: null deletionGracePeriodSeconds: null deletionTimestamp: null finalizers: null generateName: null generation: null labels: null managedFields: null name: copy of pod namespace: null ownerReferences: null resourceVersion: null selfLink: null uid: null } spec: class V1PodSpec { activeDeadlineSeconds: null affinity: null automountServiceAccountToken: null containers: [class V1Container { args: [original argument 1] command: null env: null envFrom: null image: null imagePullPolicy: null lifecycle: null livenessProbe: null name: copy container ports: null readinessProbe: null resources: null securityContext: null startupProbe: null stdin: null stdinOnce: null terminationMessagePath: null terminationMessagePolicy: null tty: null volumeDevices: null volumeMounts: null workingDir: null }] # ... } status: null }