diff --git a/cmd/pinniped-supervisor/main.go b/cmd/pinniped-supervisor/main.go index 14d98096..484b4935 100644 --- a/cmd/pinniped-supervisor/main.go +++ b/cmd/pinniped-supervisor/main.go @@ -237,7 +237,9 @@ func startControllers( pinnipedClient, pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(), secretInformer, - klogr.New()), + klogr.New(), + controllerlib.WithInformer, + ), singletonWorker) kubeInformers.Start(ctx.Done()) diff --git a/internal/controller/supervisorconfig/jwks_observer.go b/internal/controller/supervisorconfig/jwks_observer.go index 9f313f38..89f0a3eb 100644 --- a/internal/controller/supervisorconfig/jwks_observer.go +++ b/internal/controller/supervisorconfig/jwks_observer.go @@ -52,7 +52,7 @@ func NewJWKSObserverController( }, withInformer( secretInformer, - pinnipedcontroller.MatchAnySecretOfTypeFilter(jwksSecretTypeValue), + pinnipedcontroller.MatchAnySecretOfTypeFilter(jwksSecretTypeValue, nil), controllerlib.InformerOption{}, ), withInformer( diff --git a/internal/controller/supervisorconfig/tls_cert_observer.go b/internal/controller/supervisorconfig/tls_cert_observer.go index 59635dbc..6071fb4a 100644 --- a/internal/controller/supervisorconfig/tls_cert_observer.go +++ b/internal/controller/supervisorconfig/tls_cert_observer.go @@ -50,7 +50,7 @@ func NewTLSCertObserverController( }, withInformer( secretInformer, - pinnipedcontroller.MatchAnySecretOfTypeFilter(v1.SecretTypeTLS), + pinnipedcontroller.MatchAnySecretOfTypeFilter(v1.SecretTypeTLS, nil), controllerlib.InformerOption{}, ), withInformer( diff --git a/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher.go b/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher.go index df90a5ab..65c55472 100644 --- a/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher.go +++ b/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher.go @@ -117,6 +117,7 @@ func New( oidcIdentityProviderInformer idpinformers.OIDCIdentityProviderInformer, secretInformer corev1informers.SecretInformer, log logr.Logger, + withInformer pinnipedcontroller.WithInformerOptionFunc, ) controllerlib.Controller { c := controller{ cache: idpCache, @@ -126,11 +127,18 @@ func New( secretInformer: secretInformer, validatorCache: &lruValidatorCache{cache: cache.NewExpiring()}, } - filter := pinnipedcontroller.MatchAnythingFilter(pinnipedcontroller.SingletonQueue()) return controllerlib.New( controllerlib.Config{Name: controllerName, Syncer: &c}, - controllerlib.WithInformer(oidcIdentityProviderInformer, filter, controllerlib.InformerOption{}), - controllerlib.WithInformer(secretInformer, filter, controllerlib.InformerOption{}), + withInformer( + oidcIdentityProviderInformer, + pinnipedcontroller.MatchAnythingFilter(pinnipedcontroller.SingletonQueue()), + controllerlib.InformerOption{}, + ), + withInformer( + secretInformer, + pinnipedcontroller.MatchAnySecretOfTypeFilter(oidcClientSecretType, pinnipedcontroller.SingletonQueue()), + controllerlib.InformerOption{}, + ), ) } diff --git a/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher_test.go b/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher_test.go index 4ac03145..f435a200 100644 --- a/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher_test.go +++ b/internal/controller/supervisorconfig/upstreamwatcher/upstreamwatcher_test.go @@ -31,6 +31,76 @@ import ( "go.pinniped.dev/internal/upstreamoidc" ) +func TestControllerFilterSecret(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + secret metav1.Object + wantAdd bool + wantUpdate bool + wantDelete bool + }{ + { + name: "a secret of the right type", + secret: &corev1.Secret{ + Type: "secrets.pinniped.dev/oidc-client", + ObjectMeta: metav1.ObjectMeta{Name: "some-name", Namespace: "some-namespace"}, + }, + wantAdd: true, + wantUpdate: true, + wantDelete: true, + }, + { + name: "a secret of the wrong type", + secret: &corev1.Secret{ + Type: "secrets.pinniped.dev/not-the-oidc-client-type", + ObjectMeta: metav1.ObjectMeta{Name: "some-name", Namespace: "some-namespace"}, + }, + }, + { + name: "resource of wrong data type", + secret: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{Name: "some-name", Namespace: "some-namespace"}, + }, + }, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + fakePinnipedClient := pinnipedfake.NewSimpleClientset() + pinnipedInformers := pinnipedinformers.NewSharedInformerFactory(fakePinnipedClient, 0) + fakeKubeClient := fake.NewSimpleClientset() + kubeInformers := informers.NewSharedInformerFactory(fakeKubeClient, 0) + testLog := testlogger.New(t) + cache := provider.NewDynamicUpstreamIDPProvider() + cache.SetIDPList([]provider.UpstreamOIDCIdentityProviderI{ + &upstreamoidc.ProviderConfig{Name: "initial-entry"}, + }) + secretInformer := kubeInformers.Core().V1().Secrets() + withInformer := testutil.NewObservableWithInformerOption() + + New( + cache, + nil, + pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(), + secretInformer, + testLog, + withInformer.WithInformer, + ) + + unrelated := corev1.Secret{} + filter := withInformer.GetFilterForInformer(secretInformer) + require.Equal(t, test.wantAdd, filter.Add(test.secret)) + require.Equal(t, test.wantUpdate, filter.Update(&unrelated, test.secret)) + require.Equal(t, test.wantUpdate, filter.Update(test.secret, &unrelated)) + require.Equal(t, test.wantDelete, filter.Delete(test.secret)) + }) + } +} + func TestController(t *testing.T) { t.Parallel() now := metav1.NewTime(time.Now().UTC()) @@ -550,7 +620,9 @@ func TestController(t *testing.T) { fakePinnipedClient, pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(), kubeInformers.Core().V1().Secrets(), - testLog) + testLog, + controllerlib.WithInformer, + ) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() diff --git a/internal/controller/utils.go b/internal/controller/utils.go index e4411fab..55e02d45 100644 --- a/internal/controller/utils.go +++ b/internal/controller/utils.go @@ -33,7 +33,7 @@ func SimpleFilter(match func(metav1.Object) bool, parentFunc controllerlib.Paren } } -func MatchAnySecretOfTypeFilter(secretType v1.SecretType) controllerlib.Filter { +func MatchAnySecretOfTypeFilter(secretType v1.SecretType, parentFunc controllerlib.ParentFunc) controllerlib.Filter { isSecretOfType := func(obj metav1.Object) bool { secret, ok := obj.(*v1.Secret) if !ok { @@ -41,7 +41,7 @@ func MatchAnySecretOfTypeFilter(secretType v1.SecretType) controllerlib.Filter { } return secret.Type == secretType } - return SimpleFilter(isSecretOfType, nil) + return SimpleFilter(isSecretOfType, parentFunc) } func SecretIsControlledByParentFunc(matchFunc func(obj metav1.Object) bool) func(obj metav1.Object) controllerlib.Key {