From 255a991c6e0e52c4f4af6597a86babd67a9e25b4 Mon Sep 17 00:00:00 2001 From: Andy Goldstein Date: Thu, 28 Jun 2018 10:06:55 -0400 Subject: [PATCH] Stop restoring mirror pods Mirror pods are pods created from static manifest files on a node. They're mirrored to the apiserver so they're visible when querying the apiserver for a list of pods, but it's not possible to send a pod containing the mirror pod annotation to the apiserver and have it be created successfully. Instead of trying to do this, log a message that we're skipping restoring the pod because it's a mirror pod. Signed-off-by: Andy Goldstein --- pkg/restore/restore.go | 6 +++ pkg/restore/restore_test.go | 73 ++++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index 7d6aeeea3..22d404438 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -670,6 +670,12 @@ func (ctx *context) restoreResource(resource, namespace, resourcePath string) (a name := obj.GetName() + // TODO: move to restore item action if/when we add a ShouldRestore() method to the interface + if groupResource == kuberesource.Pods && obj.GetAnnotations()[v1.MirrorPodAnnotationKey] != "" { + ctx.infof("Not restoring pod because it's a mirror pod") + continue + } + if groupResource == kuberesource.PersistentVolumes { _, found := ctx.backup.Status.VolumeBackups[name] reclaimPolicy, err := collections.GetString(obj.Object, "spec.persistentVolumeReclaimPolicy") diff --git a/pkg/restore/restore_test.go b/pkg/restore/restore_test.go index 568bb8fe9..a374888d7 100644 --- a/pkg/restore/restore_test.go +++ b/pkg/restore/restore_test.go @@ -544,6 +544,50 @@ func TestRestoreResourceForNamespace(t *testing.T) { fileSystem: arktest.NewFakeFileSystem().WithFile("serviceaccounts/sa-1.json", newTestServiceAccount().ToJSON()), expectedObjs: toUnstructured(newTestServiceAccount().WithArkLabel("my-restore").ServiceAccount), }, + { + name: "non-mirror pods are restored", + namespace: "ns-1", + resourcePath: "pods", + labelSelector: labels.NewSelector(), + includeClusterResources: nil, + fileSystem: arktest.NewFakeFileSystem(). + WithFile( + "pods/pod.json", + NewTestUnstructured(). + WithAPIVersion("v1"). + WithKind("Pod"). + WithNamespace("ns-1"). + WithName("pod1"). + ToJSON(), + ), + expectedObjs: []unstructured.Unstructured{ + *(NewTestUnstructured(). + WithAPIVersion("v1"). + WithKind("Pod"). + WithNamespace("ns-1"). + WithName("pod1"). + WithArkLabel("my-restore"). + Unstructured), + }, + }, + { + name: "mirror pods are not restored", + namespace: "ns-1", + resourcePath: "pods", + labelSelector: labels.NewSelector(), + includeClusterResources: nil, + fileSystem: arktest.NewFakeFileSystem(). + WithFile( + "pods/pod.json", + NewTestUnstructured(). + WithAPIVersion("v1"). + WithKind("Pod"). + WithNamespace("ns-1"). + WithName("pod1"). + WithAnnotations(v1.MirrorPodAnnotationKey). + ToJSON(), + ), + }, } for _, test := range tests { @@ -556,8 +600,8 @@ func TestRestoreResourceForNamespace(t *testing.T) { dynamicFactory := &arktest.FakeDynamicFactory{} gv := schema.GroupVersion{Group: "", Version: "v1"} - resource := metav1.APIResource{Name: "configmaps", Namespaced: true} - dynamicFactory.On("ClientForGroupVersionResource", gv, resource, test.namespace).Return(resourceClient, nil) + configMapResource := metav1.APIResource{Name: "configmaps", Namespaced: true} + dynamicFactory.On("ClientForGroupVersionResource", gv, configMapResource, test.namespace).Return(resourceClient, nil) pvResource := metav1.APIResource{Name: "persistentvolumes", Namespaced: false} dynamicFactory.On("ClientForGroupVersionResource", gv, pvResource, test.namespace).Return(resourceClient, nil) @@ -566,6 +610,9 @@ func TestRestoreResourceForNamespace(t *testing.T) { saResource := metav1.APIResource{Name: "serviceaccounts", Namespaced: true} dynamicFactory.On("ClientForGroupVersionResource", gv, saResource, test.namespace).Return(resourceClient, nil) + podResource := metav1.APIResource{Name: "pods", Namespaced: true} + dynamicFactory.On("ClientForGroupVersionResource", gv, podResource, test.namespace).Return(resourceClient, nil) + ctx := &context{ dynamicFactory: dynamicFactory, actions: test.actions, @@ -1322,6 +1369,16 @@ func NewTestUnstructured() *testUnstructured { return obj } +func (obj *testUnstructured) WithAPIVersion(v string) *testUnstructured { + obj.Object["apiVersion"] = v + return obj +} + +func (obj *testUnstructured) WithKind(k string) *testUnstructured { + obj.Object["kind"] = k + return obj +} + func (obj *testUnstructured) WithMetadata(fields ...string) *testUnstructured { return obj.withMap("metadata", fields...) } @@ -1357,6 +1414,10 @@ func (obj *testUnstructured) WithAnnotations(fields ...string) *testUnstructured return obj } +func (obj *testUnstructured) WithNamespace(ns string) *testUnstructured { + return obj.WithMetadataField("namespace", ns) +} + func (obj *testUnstructured) WithName(name string) *testUnstructured { return obj.WithMetadataField("name", name) } @@ -1372,6 +1433,14 @@ func (obj *testUnstructured) WithArkLabel(restoreName string) *testUnstructured return obj } +func (obj *testUnstructured) ToJSON() []byte { + bytes, err := json.Marshal(obj.Object) + if err != nil { + panic(err) + } + return bytes +} + func (obj *testUnstructured) withMap(name string, fields ...string) *testUnstructured { m := make(map[string]interface{}) obj.Object[name] = m