]> git.feebdaed.xyz Git - 0xmirror/kubernetes.git/commitdiff
Fallback to live ns lookup on admission if lister cannot find namespace
authorJordan Liggitt <liggitt@google.com>
Wed, 19 Nov 2025 22:39:14 +0000 (17:39 -0500)
committerJordan Liggitt <liggitt@google.com>
Thu, 20 Nov 2025 17:16:21 +0000 (12:16 -0500)
staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/generic/policy_matcher.go
staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/matching/matching.go
staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/mutating/dispatcher.go
staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/validating/admission_test.go
staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/validating/dispatcher.go
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/namespace/matcher.go

index df21466cbe4124fb129d4df6c1f521c642180ece..782b6f1f483bf6800a2d6f7f8ca4aa2515c95f54 100644 (file)
@@ -17,6 +17,7 @@ limitations under the License.
 package generic
 
 import (
+       "context"
        "fmt"
 
        admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
@@ -41,8 +42,8 @@ type PolicyMatcher interface {
        BindingMatches(a admission.Attributes, o admission.ObjectInterfaces, binding BindingAccessor) (bool, error)
 
        // GetNamespace retrieves the Namespace resource by the given name. The name may be empty, in which case
-       // GetNamespace must return nil, nil
-       GetNamespace(name string) (*corev1.Namespace, error)
+       // GetNamespace must return nil, NotFound
+       GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error)
 }
 
 var errNilSelector = "a nil %s selector was passed, please ensure selectors are initialized properly"
@@ -97,8 +98,8 @@ func (c *matcher) BindingMatches(a admission.Attributes, o admission.ObjectInter
        return isMatch, err
 }
 
-func (c *matcher) GetNamespace(name string) (*corev1.Namespace, error) {
-       return c.Matcher.GetNamespace(name)
+func (c *matcher) GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error) {
+       return c.Matcher.GetNamespace(ctx, name)
 }
 
 var _ matching.MatchCriteria = &matchCriteria{}
index eebe7694340d4d0fd69786dfe0ff152fdd56bb91..30a6cbebe9793f6ef199fd0db7b20b93a227f14c 100644 (file)
@@ -17,6 +17,7 @@ limitations under the License.
 package matching
 
 import (
+       "context"
        "fmt"
 
        v1 "k8s.io/api/admissionregistration/v1"
@@ -44,8 +45,8 @@ type Matcher struct {
        objectMatcher    *object.Matcher
 }
 
-func (m *Matcher) GetNamespace(name string) (*corev1.Namespace, error) {
-       return m.namespaceMatcher.GetNamespace(name)
+func (m *Matcher) GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error) {
+       return m.namespaceMatcher.GetNamespace(ctx, name)
 }
 
 // NewMatcher initialize the matcher with dependencies requires
index 153b268d6718b29b0689e0f2e0c722a8a5c79159..53dbd6486f08a7f7d66e2713a1419bec442baa2f 100644 (file)
@@ -122,8 +122,12 @@ func (d *dispatcher) dispatchInvocations(
        // if it is cluster scoped, namespaceName will be empty
        // Otherwise, get the Namespace resource.
        if namespaceName != "" {
-               namespace, err = d.matcher.GetNamespace(namespaceName)
+               namespace, err = d.matcher.GetNamespace(ctx, namespaceName)
                if err != nil {
+                       var statusError *k8serrors.StatusError
+                       if errors.As(err, &statusError) {
+                               return nil, statusError
+                       }
                        return nil, k8serrors.NewNotFound(schema.GroupResource{Group: "", Resource: "namespaces"}, namespaceName)
                }
        }
index 4309e717fd53586aa4bb73fa51516b4afd321dc3..baad6a9d9f204b993deae4357d6a1c9cff7ee63e 100644 (file)
@@ -269,7 +269,7 @@ func (f *fakeMatcher) ValidateInitialization() error {
        return nil
 }
 
-func (f *fakeMatcher) GetNamespace(name string) (*v1.Namespace, error) {
+func (f *fakeMatcher) GetNamespace(ctx context.Context, name string) (*v1.Namespace, error) {
        return nil, nil
 }
 
index 8f3e22f64dc28ae873f1fd09c2754a8f4a8e0f8a..0b5474b7564221508d3b8f4574e23e561a95fb25 100644 (file)
@@ -189,7 +189,7 @@ func (c *dispatcher) Dispatch(ctx context.Context, a admission.Attributes, o adm
                        // if it is cluster scoped, namespaceName will be empty
                        // Otherwise, get the Namespace resource.
                        if namespaceName != "" {
-                               namespace, err = c.matcher.GetNamespace(namespaceName)
+                               namespace, err = c.matcher.GetNamespace(ctx, namespaceName)
                                if err != nil {
                                        return err
                                }
index 7817cb17725c274b1d7f52889ed95057498d9054..d73c69bbab1503f2979212fa74671c90c6c260ca 100644 (file)
@@ -44,8 +44,13 @@ type Matcher struct {
        Client          clientset.Interface
 }
 
-func (m *Matcher) GetNamespace(name string) (*v1.Namespace, error) {
-       return m.NamespaceLister.Get(name)
+func (m *Matcher) GetNamespace(ctx context.Context, name string) (*v1.Namespace, error) {
+       ns, err := m.NamespaceLister.Get(name)
+       if apierrors.IsNotFound(err) && len(name) > 0 {
+               // in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
+               ns, err = m.Client.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{})
+       }
+       return ns, err
 }
 
 // Validate checks if the Matcher has a NamespaceLister and Client.