From d5730f40cd12c415607e18ff5b497df08c9940df Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Tue, 4 Jul 2017 18:14:41 -0500 Subject: [PATCH] Ensure namespace exists as part of RBAC reconciliation --- pkg/registry/rbac/reconciliation/BUILD | 1 + pkg/registry/rbac/reconciliation/role_interfaces.go | 11 ++++++++++- .../rbac/reconciliation/rolebinding_interfaces.go | 11 ++++++++++- pkg/registry/rbac/rest/BUILD | 1 + pkg/registry/rbac/rest/storage_rbac.go | 12 ++++++++++-- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/pkg/registry/rbac/reconciliation/BUILD b/pkg/registry/rbac/reconciliation/BUILD index 36a5cc05d9..7ffc2828e0 100644 --- a/pkg/registry/rbac/reconciliation/BUILD +++ b/pkg/registry/rbac/reconciliation/BUILD @@ -37,6 +37,7 @@ go_library( deps = [ "//pkg/api:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/registry/rbac/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/pkg/registry/rbac/reconciliation/role_interfaces.go b/pkg/registry/rbac/reconciliation/role_interfaces.go index b3bc3c882b..9cabec6231 100644 --- a/pkg/registry/rbac/reconciliation/role_interfaces.go +++ b/pkg/registry/rbac/reconciliation/role_interfaces.go @@ -17,8 +17,11 @@ limitations under the License. package reconciliation import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/rbac" + core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" ) @@ -59,7 +62,8 @@ func (o RoleRuleOwner) SetRules(in []rbac.PolicyRule) { } type RoleModifier struct { - Client internalversion.RolesGetter + Client internalversion.RolesGetter + NamespaceClient core.NamespaceInterface } func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) { @@ -71,6 +75,11 @@ func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) { } func (c RoleModifier) Create(in RuleOwner) (RuleOwner, error) { + ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} + if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) { + return nil, err + } + ret, err := c.Client.Roles(in.GetNamespace()).Create(in.(RoleRuleOwner).Role) if err != nil { return nil, err diff --git a/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go b/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go index 6ec14ab2db..fde4b1e67b 100644 --- a/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go +++ b/pkg/registry/rbac/reconciliation/rolebinding_interfaces.go @@ -17,9 +17,12 @@ limitations under the License. package reconciliation import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/rbac" + core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" ) @@ -68,7 +71,8 @@ func (o RoleBindingAdapter) SetSubjects(in []rbac.Subject) { } type RoleBindingClientAdapter struct { - Client internalversion.RoleBindingsGetter + Client internalversion.RoleBindingsGetter + NamespaceClient core.NamespaceInterface } func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) { @@ -80,6 +84,11 @@ func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, erro } func (c RoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) { + ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}} + if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) { + return nil, err + } + ret, err := c.Client.RoleBindings(in.GetNamespace()).Create(in.(RoleBindingAdapter).RoleBinding) if err != nil { return nil, err diff --git a/pkg/registry/rbac/rest/BUILD b/pkg/registry/rbac/rest/BUILD index 05f9b470f7..38d373335f 100644 --- a/pkg/registry/rbac/rest/BUILD +++ b/pkg/registry/rbac/rest/BUILD @@ -14,6 +14,7 @@ go_library( deps = [ "//pkg/api:go_default_library", "//pkg/apis/rbac:go_default_library", + "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/client/retry:go_default_library", "//pkg/registry/rbac/clusterrole:go_default_library", diff --git a/pkg/registry/rbac/rest/storage_rbac.go b/pkg/registry/rbac/rest/storage_rbac.go index 76cf37a135..cdb38b5328 100644 --- a/pkg/registry/rbac/rest/storage_rbac.go +++ b/pkg/registry/rbac/rest/storage_rbac.go @@ -36,6 +36,7 @@ import ( serverstorage "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/rbac" + coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" "k8s.io/kubernetes/pkg/client/retry" "k8s.io/kubernetes/pkg/registry/rbac/clusterrole" @@ -134,6 +135,13 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error { // intializing roles is really important. On some e2e runs, we've seen cases where etcd is down when the server // starts, the roles don't initialize, and nothing works. err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) { + + coreclientset, err := coreclient.NewForConfig(hookContext.LoopbackClientConfig) + if err != nil { + utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) + return false, nil + } + clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) @@ -212,7 +220,7 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error { for _, role := range roles { opts := reconciliation.ReconcileRoleOptions{ Role: reconciliation.RoleRuleOwner{Role: &role}, - Client: reconciliation.RoleModifier{Client: clientset}, + Client: reconciliation.RoleModifier{Client: clientset, NamespaceClient: coreclientset.Namespaces()}, Confirm: true, } err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { @@ -242,7 +250,7 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error { for _, roleBinding := range roleBindings { opts := reconciliation.ReconcileRoleBindingOptions{ RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: &roleBinding}, - Client: reconciliation.RoleBindingClientAdapter{Client: clientset}, + Client: reconciliation.RoleBindingClientAdapter{Client: clientset, NamespaceClient: coreclientset.Namespaces()}, Confirm: true, } err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {