Restore finalizer and managedFields (#5808)

Restore finalizer and managedFields of metadata during the restoration

Signed-off-by: Wenkai Yin(尹文开) <yinw@vmware.com>
This commit is contained in:
Wenkai Yin(尹文开)
2023-02-06 13:55:04 +08:00
committed by GitHub
parent dd660882d0
commit 0f063c4dbc
4 changed files with 87 additions and 6 deletions

View File

@@ -0,0 +1 @@
Restore finalizer and managedFields of metadata during the restoration

View File

@@ -146,3 +146,10 @@ func WithGenerateName(val string) func(obj metav1.Object) {
obj.SetGenerateName(val)
}
}
// WithManagedFields is a functional option that applies the specified managed fields to an object.
func WithManagedFields(val []metav1.ManagedFieldsEntry) func(obj metav1.Object) {
return func(obj metav1.Object) {
obj.SetManagedFields(val)
}
}

View File

@@ -1415,6 +1415,24 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso
}
}
// restore the managedFields
withoutManagedFields := createdObj.DeepCopy()
createdObj.SetManagedFields(obj.GetManagedFields())
patchBytes, err := generatePatch(withoutManagedFields, createdObj)
if err != nil {
ctx.log.Errorf("error generating patch for managed fields %s: %v", kube.NamespaceAndName(obj), err)
errs.Add(namespace, err)
return warnings, errs
}
if patchBytes != nil {
if _, err = resourceClient.Patch(name, patchBytes); err != nil {
ctx.log.Errorf("error patch for managed fields %s: %v", kube.NamespaceAndName(obj), err)
errs.Add(namespace, err)
return warnings, errs
}
ctx.log.Infof("the managed fields for %s is patched", kube.NamespaceAndName(obj))
}
if groupResource == kuberesource.Pods {
pod := new(v1.Pod)
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), pod); err != nil {
@@ -1714,8 +1732,8 @@ func resetMetadata(obj *unstructured.Unstructured) (*unstructured.Unstructured,
for k := range metadata {
switch k {
case "name", "namespace", "labels", "annotations":
default:
case "generateName", "selfLink", "uid", "resourceVersion", "generation", "creationTimestamp", "deletionTimestamp",
"deletionGracePeriodSeconds", "ownerReferences":
delete(metadata, k)
}
}

View File

@@ -865,7 +865,7 @@ func TestRestoreItems(t *testing.T) {
want []*test.APIResource
}{
{
name: "metadata other than namespace/name/labels/annotations gets removed",
name: "metadata uid/resourceVersion/etc. gets removed",
restore: defaultRestore().Result(),
backup: defaultBackup().Result(),
tarball: test.NewTarWriter(t).
@@ -875,6 +875,7 @@ func TestRestoreItems(t *testing.T) {
builder.WithLabels("key-1", "val-1"),
builder.WithAnnotations("key-1", "val-1"),
builder.WithFinalizers("finalizer-1"),
builder.WithUID("uid"),
).
Result(),
).
@@ -888,6 +889,7 @@ func TestRestoreItems(t *testing.T) {
ObjectMeta(
builder.WithLabels("key-1", "val-1", "velero.io/backup-name", "backup-1", "velero.io/restore-name", "restore-1"),
builder.WithAnnotations("key-1", "val-1"),
builder.WithFinalizers("finalizer-1"),
).
Result(),
),
@@ -1105,6 +1107,53 @@ func TestRestoreItems(t *testing.T) {
}),
},
},
{
name: "metadata managedFields gets restored",
restore: defaultRestore().Result(),
backup: defaultBackup().Result(),
tarball: test.NewTarWriter(t).
AddItems("pods",
builder.ForPod("ns-1", "pod-1").
ObjectMeta(
builder.WithManagedFields([]metav1.ManagedFieldsEntry{
{
Manager: "kubectl",
Operation: "Apply",
APIVersion: "v1",
FieldsType: "FieldsV1",
FieldsV1: &metav1.FieldsV1{
Raw: []byte(`{"f:data": {"f:key":{}}}`),
},
},
}),
).
Result(),
).
Done(),
apiResources: []*test.APIResource{
test.Pods(),
},
want: []*test.APIResource{
test.Pods(
builder.ForPod("ns-1", "pod-1").
ObjectMeta(
builder.WithLabels("velero.io/backup-name", "backup-1", "velero.io/restore-name", "restore-1"),
builder.WithManagedFields([]metav1.ManagedFieldsEntry{
{
Manager: "kubectl",
Operation: "Apply",
APIVersion: "v1",
FieldsType: "FieldsV1",
FieldsV1: &metav1.FieldsV1{
Raw: []byte(`{"f:data": {"f:key":{}}}`),
},
},
}),
).
Result(),
),
},
},
}
for _, tc := range tests {
@@ -2821,10 +2870,16 @@ func TestResetMetadata(t *testing.T) {
expectedErr: true,
},
{
name: "keep name, namespace, labels, annotations only",
obj: NewTestUnstructured().WithMetadata("name", "blah", "namespace", "labels", "annotations", "foo").Unstructured,
name: "keep name, namespace, labels, annotations, managedFields, finalizers",
obj: NewTestUnstructured().WithMetadata("name", "namespace", "labels", "annotations", "managedFields", "finalizers").Unstructured,
expectedErr: false,
expectedRes: NewTestUnstructured().WithMetadata("name", "namespace", "labels", "annotations").Unstructured,
expectedRes: NewTestUnstructured().WithMetadata("name", "namespace", "labels", "annotations", "managedFields", "finalizers").Unstructured,
},
{
name: "remove uid, ownerReferences",
obj: NewTestUnstructured().WithMetadata("name", "namespace", "uid", "ownerReferences").Unstructured,
expectedErr: false,
expectedRes: NewTestUnstructured().WithMetadata("name", "namespace").Unstructured,
},
{
name: "keep status",