Skip to content

Commit

Permalink
Compare backup and cluster objects before logging
Browse files Browse the repository at this point in the history
When restoring resources that raise an already exists error, check their
equality before logging a message on the restore. If they're the same
except for some metadata, don't generate a message.

The restore process was modified so that if an object had an empty
namespace string, no namespace key is created on the object. This was to
avoid manipulating the copy of the current cluster's object by adding
the target namespace.

There are some cases right now that are known to not be equal via this
method:

- The `default` ServiceAccount in a namespace will not match, primarily
because of differing default tokens. These will be handled in their own
patch
- IP addresses for Services are recorded in the backup object, but are
either not present on the cluster object, or different. An issue for
this already exists at vmware-tanzu#354
- Endpoints have differing values for `renewTime`. This may be
insubstantial, but isn't currently handled by the resetMetadataAndStatus
function.
- PersistentVolume objects in the backup have a `claimRef` section,
while those in cluster do not.

Signed-off-by: Nolan Brubaker <[email protected]>
  • Loading branch information
Nolan Brubaker committed Apr 2, 2018
1 parent 68e2178 commit b16e2cf
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 12 deletions.
44 changes: 36 additions & 8 deletions pkg/restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/sirupsen/logrus"

"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -634,20 +635,47 @@ func (ctx *context) restoreResource(resource, namespace, resourcePath string) (a
}

// necessary because we may have remapped the namespace
obj.SetNamespace(namespace)
// if the namespace is blank, don't create the key
if namespace != "" {
obj.SetNamespace(namespace)
}

// add an ark-restore label to each resource for easy ID
addLabel(obj, api.RestoreLabelKey, ctx.restore.Name)

ctx.infof("Restoring %s: %v", obj.GroupVersionKind().Kind, obj.GetName())
_, err = resourceClient.Create(obj)
if apierrors.IsAlreadyExists(err) {
addToResult(&warnings, namespace, err)
continue
// Use a special error since we need to retain that information through a couple checks.
_, restoreErr := resourceClient.Create(obj)
if apierrors.IsAlreadyExists(restoreErr) {
fromCluster, err := resourceClient.Get(obj.GetName(), metav1.GetOptions{})
if err != nil {
fmt.Println("First part")
addToResult(&warnings, namespace, err)
continue
}
// Remove insubstantial metadata
fromCluster, err = resetMetadataAndStatus(fromCluster)
if err != nil {
fmt.Println("Second part")
addToResult(&warnings, namespace, err)
continue
}
// Add the restore's label to the in-cluster object since we know that's different
addLabel(fromCluster, api.RestoreLabelKey, ctx.restore.Name)

if equality.Semantic.DeepEqual(obj, fromCluster) {
continue
ctx.infof("Backup for %s matches cluster version, skipping restore.", obj.GetName())
} else {
es := fmt.Sprintf("%s and backup does not match.", restoreErr.Error())
err = errors.New(es)
addToResult(&warnings, namespace, err)
continue
}
}
if err != nil {
ctx.infof("error restoring %s: %v", obj.GetName(), err)
addToResult(&errs, namespace, fmt.Errorf("error restoring %s: %v", fullPath, err))
if restoreErr != nil {
ctx.infof("error restoring %s: %v", obj.GetName(), restoreErr)
addToResult(&errs, namespace, fmt.Errorf("error restoring %s: %v", fullPath, restoreErr))
continue
}

Expand Down
4 changes: 0 additions & 4 deletions pkg/restore/restore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -942,10 +942,6 @@ func toUnstructured(objs ...runtime.Object) []unstructured.Unstructured {

delete(metadata, "creationTimestamp")

if _, exists := metadata["namespace"]; !exists {
metadata["namespace"] = ""
}

delete(unstructuredObj.Object, "status")

res = append(res, unstructuredObj)
Expand Down

0 comments on commit b16e2cf

Please sign in to comment.