From d5f9c0a00c0d4fd68208650fd84e89c33c1e1aa2 Mon Sep 17 00:00:00 2001 From: Stavros Kontopoulos Date: Fri, 20 May 2022 04:06:58 +0300 Subject: [PATCH] Add filtering support for secret informer in ingress controller (#920) * add filtering support for secret informer * updates * use the new key * revert githubflow * use networking with new key * minor updates * updates * cleanup tests --- cmd/controller/main.go | 5 +- config/500-controller.yaml | 2 + pkg/reconciler/informerfiltering/util.go | 47 ++++++ pkg/reconciler/ingress/controller.go | 11 +- pkg/reconciler/ingress/ingress_test.go | 13 +- pkg/reconciler/ingress/resources/secret.go | 2 + .../ingress/resources/secret_test.go | 7 +- .../core/v1/secret/filtered/fake/fake.go | 52 +++++++ .../core/v1/secret/filtered/secret.go | 136 ++++++++++++++++++ .../filtered/fake/fake_filtered_factory.go | 59 ++++++++ .../factory/filtered/filtered_factory.go | 77 ++++++++++ vendor/modules.txt | 4 + 12 files changed, 405 insertions(+), 10 deletions(-) create mode 100644 pkg/reconciler/informerfiltering/util.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/fake/fake.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/secret.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go create mode 100644 vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go diff --git a/cmd/controller/main.go b/cmd/controller/main.go index c21bb2dba9..d50872813e 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -18,8 +18,10 @@ package main import ( "istio.io/api/networking/v1beta1" + "knative.dev/net-istio/pkg/reconciler/informerfiltering" "knative.dev/net-istio/pkg/reconciler/ingress" "knative.dev/net-istio/pkg/reconciler/serverlessservice" + "knative.dev/pkg/signals" // This defines the shared main for injected controllers. "knative.dev/pkg/injection/sharedmain" @@ -31,5 +33,6 @@ func main() { v1beta1.VirtualServiceUnmarshaler.AllowUnknownFields = true v1beta1.GatewayUnmarshaler.AllowUnknownFields = true - sharedmain.Main("net-istio-controller", ingress.NewController, serverlessservice.NewController) + ctx := informerfiltering.GetContextWithFilteringLabelSelector(signals.NewContext()) + sharedmain.MainWithContext(ctx, "net-istio-controller", ingress.NewController, serverlessservice.NewController) } diff --git a/config/500-controller.yaml b/config/500-controller.yaml index 2cf9b03961..aa8cb52f9e 100644 --- a/config/500-controller.yaml +++ b/config/500-controller.yaml @@ -64,6 +64,8 @@ spec: value: config-logging - name: CONFIG_OBSERVABILITY_NAME value: config-observability + - name: ENABLE_SECRET_INFORMER_FILTERING_BY_CERT_UID + value: "false" # TODO(https://github.com/knative/pkg/pull/953): Remove stackdriver specific config - name: METRICS_DOMAIN diff --git a/pkg/reconciler/informerfiltering/util.go b/pkg/reconciler/informerfiltering/util.go new file mode 100644 index 0000000000..786e205d85 --- /dev/null +++ b/pkg/reconciler/informerfiltering/util.go @@ -0,0 +1,47 @@ +/* +Copyright 2022 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package informerfiltering + +import ( + "context" + "os" + "strconv" + + "knative.dev/networking/pkg/apis/networking" + filteredFactory "knative.dev/pkg/client/injection/kube/informers/factory/filtered" +) + +const EnableSecretInformerFilteringByCertUIDEnv = "ENABLE_SECRET_INFORMER_FILTERING_BY_CERT_UID" + +// ShouldFilterByCertificateUID allows to choose whether to apply filtering on certificate related secrets +// when list by informers in this component. If not set or set to false no filtering is applied and instead informers +// will get any secret available in the cluster which may lead to mem issues in large clusters. +func ShouldFilterByCertificateUID() bool { + if enable := os.Getenv(EnableSecretInformerFilteringByCertUIDEnv); enable != "" { + b, _ := strconv.ParseBool(enable) + return b + } + return false +} + +// GetContextWithFilteringLabelSelector returns the passed context with the proper label key selector added to it. +func GetContextWithFilteringLabelSelector(ctx context.Context) context.Context { + if ShouldFilterByCertificateUID() { + return filteredFactory.WithSelectors(ctx, networking.CertificateUIDLabelKey) + } + return filteredFactory.WithSelectors(ctx, "") // Allow all +} diff --git a/pkg/reconciler/ingress/controller.go b/pkg/reconciler/ingress/controller.go index 24d5701783..1254b633b8 100644 --- a/pkg/reconciler/ingress/controller.go +++ b/pkg/reconciler/ingress/controller.go @@ -20,6 +20,7 @@ import ( "context" "go.uber.org/zap" + v1 "k8s.io/client-go/informers/core/v1" istioclient "knative.dev/net-istio/pkg/client/istio/injection/client" gatewayinformer "knative.dev/net-istio/pkg/client/istio/injection/informers/networking/v1alpha3/gateway" virtualserviceinformer "knative.dev/net-istio/pkg/client/istio/injection/informers/networking/v1alpha3/virtualservice" @@ -33,8 +34,9 @@ import ( kubeclient "knative.dev/pkg/client/injection/kube/client" endpointsinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/endpoints" podinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/pod" - secretinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/secret" + secretfilteredinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered" serviceinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/service" + filteredFactory "knative.dev/pkg/client/injection/kube/informers/factory/filtered" "knative.dev/pkg/configmap" "knative.dev/pkg/controller" "knative.dev/pkg/logging" @@ -81,7 +83,7 @@ func newControllerWithOptions( logger := logging.FromContext(ctx) virtualServiceInformer := virtualserviceinformer.Get(ctx) gatewayInformer := gatewayinformer.Get(ctx) - secretInformer := secretinformer.Get(ctx) + secretInformer := getSecretInformer(ctx) serviceInformer := serviceinformer.Get(ctx) ingressInformer := ingressinformer.Get(ctx) @@ -179,3 +181,8 @@ func combineFunc(functions ...func(interface{})) func(interface{}) { } } } + +func getSecretInformer(ctx context.Context) v1.SecretInformer { + untyped := ctx.Value(filteredFactory.LabelKey{}) // This should always be not nil and have exactly one selector + return secretfilteredinformer.Get(ctx, untyped.([]string)[0]) +} diff --git a/pkg/reconciler/ingress/ingress_test.go b/pkg/reconciler/ingress/ingress_test.go index b8f44e3abc..0a5e94b3da 100644 --- a/pkg/reconciler/ingress/ingress_test.go +++ b/pkg/reconciler/ingress/ingress_test.go @@ -38,8 +38,10 @@ import ( fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake" _ "knative.dev/pkg/client/injection/kube/informers/core/v1/endpoints/fake" _ "knative.dev/pkg/client/injection/kube/informers/core/v1/pod/fake" - _ "knative.dev/pkg/client/injection/kube/informers/core/v1/secret/fake" + _ "knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/fake" _ "knative.dev/pkg/client/injection/kube/informers/core/v1/service/fake" + filteredFactory "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + _ "knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake" proto "github.com/gogo/protobuf/proto" "github.com/google/go-cmp/cmp" @@ -981,8 +983,9 @@ func TestReconcile_EnableAutoTLS(t *testing.T) { // The secret copy under istio-system. targetSecret("istio-system", targetSecretName, map[string]string{ - networking.OriginSecretNameLabelKey: "secret0", - networking.OriginSecretNamespaceLabelKey: "knative-serving", + "networking.internal.knative.dev/certificate-uid": "", + networking.OriginSecretNameLabelKey: "secret0", + networking.OriginSecretNamespaceLabelKey: "knative-serving", }), }, WantPatches: []clientgotesting.PatchActionImpl{ @@ -1573,7 +1576,9 @@ func newTestSetup(t *testing.T, configs ...*corev1.ConfigMap) ( *controller.Impl, *configmap.ManualWatcher) { - ctx, cancel, informers := SetupFakeContextWithCancel(t) + ctx, cancel, informers := SetupFakeContextWithCancel(t, func(ctx context.Context) context.Context { + return filteredFactory.WithSelectors(ctx, networking.CertificateUIDLabelKey) + }) configMapWatcher := &configmap.ManualWatcher{Namespace: system.Namespace()} controller := newControllerWithOptions(ctx, diff --git a/pkg/reconciler/ingress/resources/secret.go b/pkg/reconciler/ingress/resources/secret.go index f7631e255c..4862d0694a 100644 --- a/pkg/reconciler/ingress/resources/secret.go +++ b/pkg/reconciler/ingress/resources/secret.go @@ -97,6 +97,8 @@ func targetWildcardSecretName(originSecretName, originSecretNamespace string) st } func makeSecret(originSecret *corev1.Secret, name, namespace string, labels map[string]string) *corev1.Secret { + labels[networking.CertificateUIDLabelKey] = originSecret.Labels[networking.CertificateUIDLabelKey] // propagate label for informer use + return &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, diff --git a/pkg/reconciler/ingress/resources/secret_test.go b/pkg/reconciler/ingress/resources/secret_test.go index c16b960baa..c3ee0d2bee 100644 --- a/pkg/reconciler/ingress/resources/secret_test.go +++ b/pkg/reconciler/ingress/resources/secret_test.go @@ -159,8 +159,9 @@ func TestMakeSecrets(t *testing.T) { // the ns of Istio gateway service. Namespace: "istio-system", Labels: map[string]string{ - networking.OriginSecretNameLabelKey: "test-secret", - networking.OriginSecretNamespaceLabelKey: "knative-serving", + "networking.internal.knative.dev/certificate-uid": "", + networking.OriginSecretNameLabelKey: "test-secret", + networking.OriginSecretNamespaceLabelKey: "knative-serving", }, }, Data: map[string][]byte{ @@ -230,7 +231,7 @@ func TestMakeWildcardSecrets(t *testing.T) { // Expected secret should be in istio-system which is // the ns of Istio gateway service. Namespace: "istio-system", - Labels: map[string]string{}, + Labels: map[string]string{"networking.internal.knative.dev/certificate-uid": ""}, }, Data: map[string][]byte{ "test-data": []byte("abcd"), diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/fake/fake.go b/vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/fake/fake.go new file mode 100644 index 0000000000..6cd6028b67 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/fake/fake.go @@ -0,0 +1,52 @@ +/* +Copyright 2021 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fake + +import ( + context "context" + + filtered "knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered" + factoryfiltered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +var Get = filtered.Get + +func init() { + injection.Fake.RegisterFilteredInformers(withInformer) +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(factoryfiltered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := factoryfiltered.Get(ctx, selector) + inf := f.Core().V1().Secrets() + ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/secret.go b/vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/secret.go new file mode 100644 index 0000000000..73bd40e1b9 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/secret.go @@ -0,0 +1,136 @@ +/* +Copyright 2021 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package filtered + +import ( + context "context" + + apicorev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + v1 "k8s.io/client-go/informers/core/v1" + kubernetes "k8s.io/client-go/kubernetes" + corev1 "k8s.io/client-go/listers/core/v1" + cache "k8s.io/client-go/tools/cache" + client "knative.dev/pkg/client/injection/kube/client" + filtered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterFilteredInformers(withInformer) + injection.Dynamic.RegisterDynamicInformer(withDynamicInformer) +} + +// Key is used for associating the Informer inside the context.Context. +type Key struct { + Selector string +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := filtered.Get(ctx, selector) + inf := f.Core().V1().Secrets() + ctx = context.WithValue(ctx, Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} + +func withDynamicInformer(ctx context.Context) context.Context { + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + for _, selector := range labelSelectors { + inf := &wrapper{client: client.Get(ctx), selector: selector} + ctx = context.WithValue(ctx, Key{Selector: selector}, inf) + } + return ctx +} + +// Get extracts the typed informer from the context. +func Get(ctx context.Context, selector string) v1.SecretInformer { + untyped := ctx.Value(Key{Selector: selector}) + if untyped == nil { + logging.FromContext(ctx).Panicf( + "Unable to fetch k8s.io/client-go/informers/core/v1.SecretInformer with selector %s from context.", selector) + } + return untyped.(v1.SecretInformer) +} + +type wrapper struct { + client kubernetes.Interface + + namespace string + + selector string +} + +var _ v1.SecretInformer = (*wrapper)(nil) +var _ corev1.SecretLister = (*wrapper)(nil) + +func (w *wrapper) Informer() cache.SharedIndexInformer { + return cache.NewSharedIndexInformer(nil, &apicorev1.Secret{}, 0, nil) +} + +func (w *wrapper) Lister() corev1.SecretLister { + return w +} + +func (w *wrapper) Secrets(namespace string) corev1.SecretNamespaceLister { + return &wrapper{client: w.client, namespace: namespace, selector: w.selector} +} + +func (w *wrapper) List(selector labels.Selector) (ret []*apicorev1.Secret, err error) { + reqs, err := labels.ParseToRequirements(w.selector) + if err != nil { + return nil, err + } + selector = selector.Add(reqs...) + lo, err := w.client.CoreV1().Secrets(w.namespace).List(context.TODO(), metav1.ListOptions{ + LabelSelector: selector.String(), + // TODO(mattmoor): Incorporate resourceVersion bounds based on staleness criteria. + }) + if err != nil { + return nil, err + } + for idx := range lo.Items { + ret = append(ret, &lo.Items[idx]) + } + return ret, nil +} + +func (w *wrapper) Get(name string) (*apicorev1.Secret, error) { + // TODO(mattmoor): Check that the fetched object matches the selector. + return w.client.CoreV1().Secrets(w.namespace).Get(context.TODO(), name, metav1.GetOptions{ + // TODO(mattmoor): Incorporate resourceVersion bounds based on staleness criteria. + }) +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go new file mode 100644 index 0000000000..3e71d49646 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake/fake_filtered_factory.go @@ -0,0 +1,59 @@ +/* +Copyright 2021 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fakeFilteredFactory + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + informers "k8s.io/client-go/informers" + fake "knative.dev/pkg/client/injection/kube/client/fake" + filtered "knative.dev/pkg/client/injection/kube/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +var Get = filtered.Get + +func init() { + injection.Fake.RegisterInformerFactory(withInformerFactory) +} + +func withInformerFactory(ctx context.Context) context.Context { + c := fake.Get(ctx) + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + for _, selector := range labelSelectors { + opts := []informers.SharedInformerOption{} + if injection.HasNamespaceScope(ctx) { + opts = append(opts, informers.WithNamespace(injection.GetNamespaceScope(ctx))) + } + opts = append(opts, informers.WithTweakListOptions(func(l *v1.ListOptions) { + l.LabelSelector = selector + })) + ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, + informers.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), opts...)) + } + return ctx +} diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go new file mode 100644 index 0000000000..fbd00f1bc7 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/kube/informers/factory/filtered/filtered_factory.go @@ -0,0 +1,77 @@ +/* +Copyright 2021 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package filteredFactory + +import ( + context "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + informers "k8s.io/client-go/informers" + client "knative.dev/pkg/client/injection/kube/client" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterInformerFactory(withInformerFactory) +} + +// Key is used as the key for associating information with a context.Context. +type Key struct { + Selector string +} + +type LabelKey struct{} + +func WithSelectors(ctx context.Context, selector ...string) context.Context { + return context.WithValue(ctx, LabelKey{}, selector) +} + +func withInformerFactory(ctx context.Context) context.Context { + c := client.Get(ctx) + untyped := ctx.Value(LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + for _, selector := range labelSelectors { + opts := []informers.SharedInformerOption{} + if injection.HasNamespaceScope(ctx) { + opts = append(opts, informers.WithNamespace(injection.GetNamespaceScope(ctx))) + } + opts = append(opts, informers.WithTweakListOptions(func(l *v1.ListOptions) { + l.LabelSelector = selector + })) + ctx = context.WithValue(ctx, Key{Selector: selector}, + informers.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), opts...)) + } + return ctx +} + +// Get extracts the InformerFactory from the context. +func Get(ctx context.Context, selector string) informers.SharedInformerFactory { + untyped := ctx.Value(Key{Selector: selector}) + if untyped == nil { + logging.FromContext(ctx).Panicf( + "Unable to fetch k8s.io/client-go/informers.SharedInformerFactory with selector %s from context.", selector) + } + return untyped.(informers.SharedInformerFactory) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 64707366aa..9f5f466c14 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -877,10 +877,14 @@ knative.dev/pkg/client/injection/kube/informers/core/v1/pod knative.dev/pkg/client/injection/kube/informers/core/v1/pod/fake knative.dev/pkg/client/injection/kube/informers/core/v1/secret knative.dev/pkg/client/injection/kube/informers/core/v1/secret/fake +knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered +knative.dev/pkg/client/injection/kube/informers/core/v1/secret/filtered/fake knative.dev/pkg/client/injection/kube/informers/core/v1/service knative.dev/pkg/client/injection/kube/informers/core/v1/service/fake knative.dev/pkg/client/injection/kube/informers/factory knative.dev/pkg/client/injection/kube/informers/factory/fake +knative.dev/pkg/client/injection/kube/informers/factory/filtered +knative.dev/pkg/client/injection/kube/informers/factory/filtered/fake knative.dev/pkg/codegen/cmd/injection-gen knative.dev/pkg/codegen/cmd/injection-gen/args knative.dev/pkg/codegen/cmd/injection-gen/generators