Excluding nodes and endpoints from restoration

- Introduced a blacklist of resources that are non-restorable.  The
goal being that the backup can still include these resources for
logging/auditing purposes but they are explicitly added to
ExcludedResources in the RestorController's "defaulting" logic
to ensure that if someone were to explicitly ask for nodes
that they would be expressly denied.

Signed-off-by: Justin Nauman <justin.r.nauman@gmail.com>
pull/99/head
Justin Nauman 2017-09-18 22:44:33 -05:00
parent 87f60ed853
commit 1fd1e8deaa
2 changed files with 35 additions and 0 deletions

View File

@ -29,6 +29,7 @@ import (
"github.com/sirupsen/logrus"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
@ -44,6 +45,10 @@ import (
kubeutil "github.com/heptio/ark/pkg/util/kube"
)
// nonRestorableResources is a blacklist for the restoration process. Any resources
// included here are explicitly excluded from the restoration process.
var nonRestorableResources = []string{"nodes"}
type restoreController struct {
restoreClient arkv1client.RestoresGetter
backupClient arkv1client.BackupsGetter
@ -234,6 +239,13 @@ func (controller *restoreController) processRestore(key string) error {
restore.Spec.IncludedResources = []string{"*"}
}
excludedResources := sets.NewString(restore.Spec.ExcludedResources...)
for _, nonrestorable := range nonRestorableResources {
if !excludedResources.Has(nonrestorable) {
restore.Spec.ExcludedResources = append(restore.Spec.ExcludedResources, nonrestorable)
}
}
// validation
if restore.Status.ValidationErrors = controller.getValidationErrors(restore); len(restore.Status.ValidationErrors) > 0 {
restore.Status.Phase = api.RestorePhaseFailedValidation
@ -288,6 +300,13 @@ func (controller *restoreController) getValidationErrors(itm *api.Restore) []str
validationErrors = append(validationErrors, "BackupName must be non-empty and correspond to the name of a backup in object storage.")
}
includedResources := sets.NewString(itm.Spec.IncludedResources...)
for _, nonRestorableResource := range nonRestorableResources {
if includedResources.Has(nonRestorableResource) {
validationErrors = append(validationErrors, fmt.Sprintf("%v are a non-restorable resource", nonRestorableResource))
}
}
for _, err := range collections.ValidateIncludesExcludes(itm.Spec.IncludedNamespaces, itm.Spec.ExcludedNamespaces) {
validationErrors = append(validationErrors, fmt.Sprintf("Invalid included/excluded namespace lists: %v", err))
}

View File

@ -259,6 +259,18 @@ func TestProcessRestore(t *testing.T) {
Restore,
},
},
{
name: "restoration of nodes is not supported",
restore: NewRestore("foo", "bar", "backup-1", "ns-1", "nodes", api.RestorePhaseNew).Restore,
backup: NewTestBackup().WithName("backup-1").Backup,
expectedErr: false,
expectedRestoreUpdates: []*api.Restore{
NewRestore("foo", "bar", "backup-1", "ns-1", "nodes", api.RestorePhaseFailedValidation).
WithValidationError("nodes are a non-restorable resource").
WithValidationError("Invalid included/excluded resource lists: excludes list cannot contain an item in the includes list: nodes").
Restore,
},
},
}
for _, test := range tests {
@ -382,6 +394,10 @@ func NewRestore(ns, name, backup, includeNS, includeResource string, phase api.R
restore = restore.WithIncludedResource(includeResource)
}
for _, n := range nonRestorableResources {
restore.WithExcludedResource(n)
}
return restore
}