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
}
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
}