From d0441a9fba69a7d1a6d27f7d9c24b84dea2fdee8 Mon Sep 17 00:00:00 2001 From: derekwaynecarr Date: Fri, 19 Jun 2015 12:24:54 -0400 Subject: [PATCH] Prevent deletion of default namespace --- .../namespace/lifecycle/admission.go | 23 +++++++++++++++---- .../namespace/lifecycle/admission_test.go | 13 +++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/plugin/pkg/admission/namespace/lifecycle/admission.go b/plugin/pkg/admission/namespace/lifecycle/admission.go index 71c1e8bdd8d..16b70bebf09 100644 --- a/plugin/pkg/admission/namespace/lifecycle/admission.go +++ b/plugin/pkg/admission/namespace/lifecycle/admission.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/admission" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" @@ -29,6 +30,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" ) @@ -42,11 +44,21 @@ func init() { // It enforces life-cycle constraints around a Namespace depending on its Phase type lifecycle struct { *admission.Handler - client client.Interface - store cache.Store + client client.Interface + store cache.Store + immortalNamespaces util.StringSet } func (l *lifecycle) Admit(a admission.Attributes) (err error) { + + // prevent deletion of immortal namespaces + if a.GetOperation() == admission.Delete { + if a.GetKind() == "Namespace" && l.immortalNamespaces.Has(a.GetName()) { + return errors.NewForbidden(a.GetKind(), a.GetName(), fmt.Errorf("namespace can never be deleted")) + } + return nil + } + defaultVersion, kind, err := latest.RESTMapper.VersionAndKindForResource(a.GetResource()) if err != nil { return admission.NewForbidden(a, err) @@ -96,8 +108,9 @@ func NewLifecycle(c client.Interface) admission.Interface { ) reflector.Run() return &lifecycle{ - Handler: admission.NewHandler(admission.Create), - client: c, - store: store, + Handler: admission.NewHandler(admission.Create, admission.Delete), + client: c, + store: store, + immortalNamespaces: util.NewStringSet(api.NamespaceDefault), } } diff --git a/plugin/pkg/admission/namespace/lifecycle/admission_test.go b/plugin/pkg/admission/namespace/lifecycle/admission_test.go index 092910020c2..7e8bde7756f 100644 --- a/plugin/pkg/admission/namespace/lifecycle/admission_test.go +++ b/plugin/pkg/admission/namespace/lifecycle/admission_test.go @@ -75,4 +75,17 @@ func TestAdmission(t *testing.T) { if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } + + // verify delete of namespace default can never proceed + err = handler.Admit(admission.NewAttributesRecord(nil, "Namespace", "", api.NamespaceDefault, "namespaces", "", admission.Delete, nil)) + if err == nil { + t.Errorf("Expected an error that this namespace can never be deleted") + } + + // verify delete of namespace other than default can proceed + err = handler.Admit(admission.NewAttributesRecord(nil, "Namespace", "", "other", "namespaces", "", admission.Delete, nil)) + if err != nil { + t.Errorf("Did not expect an error %v", err) + } + }