From 03ba8f449c4357f3ecee3d75f84e3b270cae6070 Mon Sep 17 00:00:00 2001 From: Calum Murray Date: Fri, 25 Oct 2024 02:07:03 -0400 Subject: [PATCH] feat: autocreate v1beta3 eventtypes (#8276) * feat: eventtype autocreate creates v1beta3 ets Signed-off-by: Cali0707 * fix(test): et tests pass with v1beta3 autocreate Signed-off-by: Cali0707 * fix(build): components use correct v1beta3 interfaces when making the et autocreate handler Signed-off-by: Cali0707 --------- Signed-off-by: Cali0707 --- cmd/broker/filter/main.go | 4 +- cmd/broker/ingress/main.go | 6 +- pkg/eventtype/eventtypes.go | 25 +-- pkg/eventtype/eventtypes_test.go | 22 +-- .../inmemorychannel/dispatcher/controller.go | 4 +- .../dispatcher/controller_test.go | 2 +- .../dispatcher/inmemorychannel.go | 8 +- pkg/reconciler/testing/v1beta3/eventtype.go | 127 +++++++++++++++ pkg/reconciler/testing/v1beta3/factory.go | 147 ++++++++++++++++++ pkg/reconciler/testing/v1beta3/listers.go | 145 +++++++++++++++++ 10 files changed, 456 insertions(+), 34 deletions(-) create mode 100644 pkg/reconciler/testing/v1beta3/eventtype.go create mode 100644 pkg/reconciler/testing/v1beta3/factory.go create mode 100644 pkg/reconciler/testing/v1beta3/listers.go diff --git a/cmd/broker/filter/main.go b/cmd/broker/filter/main.go index e491670f934..bf6d19cdf89 100644 --- a/cmd/broker/filter/main.go +++ b/cmd/broker/filter/main.go @@ -47,7 +47,7 @@ import ( eventingclient "knative.dev/eventing/pkg/client/injection/client" brokerinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1/broker" triggerinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1/trigger" - eventtypeinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta2/eventtype" + eventtypeinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta3/eventtype" subscriptioninformer "knative.dev/eventing/pkg/client/injection/informers/messaging/v1/subscription" "knative.dev/eventing/pkg/eventingtls" "knative.dev/eventing/pkg/eventtype" @@ -130,7 +130,7 @@ func main() { if featureFlags.IsEnabled(feature.EvenTypeAutoCreate) && featureStore != nil && handler != nil { autoCreate := &eventtype.EventTypeAutoHandler{ EventTypeLister: eventtypeinformer.Get(ctx).Lister(), - EventingClient: eventingclient.Get(ctx).EventingV1beta2(), + EventingClient: eventingclient.Get(ctx).EventingV1beta3(), FeatureStore: featureStore, Logger: logger, } diff --git a/cmd/broker/ingress/main.go b/cmd/broker/ingress/main.go index bd8e76d8fea..ade719ec1af 100644 --- a/cmd/broker/ingress/main.go +++ b/cmd/broker/ingress/main.go @@ -50,7 +50,7 @@ import ( eventingclient "knative.dev/eventing/pkg/client/injection/client" brokerinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1/broker" eventpolicyinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1alpha1/eventpolicy" - eventtypeinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta2/eventtype" + eventtypeinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta3/eventtype" "knative.dev/eventing/pkg/eventingtls" "knative.dev/eventing/pkg/eventtype" "knative.dev/eventing/pkg/reconciler/names" @@ -153,7 +153,7 @@ func main() { if featureFlags.IsEnabled(feature.EvenTypeAutoCreate) && featureStore != nil && handler != nil { autoCreate := &eventtype.EventTypeAutoHandler{ EventTypeLister: eventtypeinformer.Get(ctx).Lister(), - EventingClient: eventingclient.Get(ctx).EventingV1beta2(), + EventingClient: eventingclient.Get(ctx).EventingV1beta3(), FeatureStore: featureStore, Logger: logger, } @@ -190,7 +190,7 @@ func main() { if featureStore.IsEnabled(feature.EvenTypeAutoCreate) { autoCreate := &eventtype.EventTypeAutoHandler{ EventTypeLister: eventtypeinformer.Get(ctx).Lister(), - EventingClient: eventingclient.Get(ctx).EventingV1beta2(), + EventingClient: eventingclient.Get(ctx).EventingV1beta3(), FeatureStore: featureStore, Logger: logger, } diff --git a/pkg/eventtype/eventtypes.go b/pkg/eventtype/eventtypes.go index 178a1a5e1df..1bf7116213c 100644 --- a/pkg/eventtype/eventtypes.go +++ b/pkg/eventtype/eventtypes.go @@ -29,18 +29,18 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "knative.dev/eventing/pkg/apis/eventing/v1beta2" + "knative.dev/eventing/pkg/apis/eventing/v1beta3" "knative.dev/eventing/pkg/apis/feature" - eventingv1beta2 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta2" - v1beta22 "knative.dev/eventing/pkg/client/listers/eventing/v1beta2" + eventingv1beta3 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta3" + v1beta33 "knative.dev/eventing/pkg/client/listers/eventing/v1beta3" "knative.dev/eventing/pkg/utils" "knative.dev/pkg/apis" duckv1 "knative.dev/pkg/apis/duck/v1" ) type EventTypeAutoHandler struct { - EventTypeLister v1beta22.EventTypeLister - EventingClient eventingv1beta2.EventingV1beta2Interface + EventTypeLister v1beta33.EventTypeLister + EventingClient eventingv1beta3.EventingV1beta3Interface FeatureStore *feature.Store Logger *zap.Logger } @@ -80,7 +80,7 @@ func (h *EventTypeAutoHandler) AutoCreateEventType(ctx context.Context, event *e source, _ := apis.ParseURL(event.Source()) schema, _ := apis.ParseURL(event.DataSchema()) - et := &v1beta2.EventType{ + et := &v1beta3.EventType{ ObjectMeta: metav1.ObjectMeta{ Name: eventTypeName, Namespace: addressable.Namespace, @@ -93,11 +93,14 @@ func (h *EventTypeAutoHandler) AutoCreateEventType(ctx context.Context, event *e }, }, }, - Spec: v1beta2.EventTypeSpec{ - Type: event.Type(), - Source: source, - Schema: schema, - SchemaData: event.DataSchema(), + Spec: v1beta3.EventTypeSpec{ + Attributes: []v1beta3.EventAttributeDefinition{ + {Name: "type", Value: event.Type(), Required: true}, + {Name: "source", Value: source.String(), Required: true}, + {Name: "schemadata", Value: schema.String(), Required: true}, + {Name: "specversion", Value: event.SpecVersion(), Required: true}, + {Name: "id", Required: false}, + }, Reference: addressable, Description: "Event Type auto-created by controller", }, diff --git a/pkg/eventtype/eventtypes_test.go b/pkg/eventtype/eventtypes_test.go index 1f72d9886ce..36827290582 100644 --- a/pkg/eventtype/eventtypes_test.go +++ b/pkg/eventtype/eventtypes_test.go @@ -28,10 +28,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "knative.dev/eventing/pkg/apis/eventing/v1beta2" + "knative.dev/eventing/pkg/apis/eventing/v1beta3" "knative.dev/eventing/pkg/apis/feature" fakeeventingclientset "knative.dev/eventing/pkg/client/clientset/versioned/fake" - reconcilertestingv1beta2 "knative.dev/eventing/pkg/reconciler/testing/v1beta2" + reconcilertestingv1beta3 "knative.dev/eventing/pkg/reconciler/testing/v1beta3" "knative.dev/eventing/test/lib/resources" duckv1 "knative.dev/pkg/apis/duck/v1" logtesting "knative.dev/pkg/logging/testing" @@ -43,7 +43,7 @@ func TestEventTypeAutoHandler_AutoCreateEventType(t *testing.T) { featureFlag string addressable *duckv1.KReference events []v2.Event - expectedEventType []v1beta2.EventType + expectedEventType []v1beta3.EventType expectedError error }{ { @@ -55,7 +55,7 @@ func TestEventTypeAutoHandler_AutoCreateEventType(t *testing.T) { Namespace: "default", Name: "broker"}, events: []v2.Event{initEvent("")}, - expectedEventType: []v1beta2.EventType{ + expectedEventType: []v1beta3.EventType{ initEventTypeObject(), initEventTypeObject()}, expectedError: nil, @@ -71,7 +71,7 @@ func TestEventTypeAutoHandler_AutoCreateEventType(t *testing.T) { events: []v2.Event{ initEvent("foo.type"), initEvent("bar.type")}, - expectedEventType: []v1beta2.EventType{ + expectedEventType: []v1beta3.EventType{ initEventTypeObject(), initEventTypeObject()}, expectedError: nil, @@ -80,13 +80,13 @@ func TestEventTypeAutoHandler_AutoCreateEventType(t *testing.T) { for _, tc := range testCases { ctx := context.TODO() eventtypes := make([]runtime.Object, 0, 10) - listers := reconcilertestingv1beta2.NewListers(eventtypes) + listers := reconcilertestingv1beta3.NewListers(eventtypes) eventingClient := fakeeventingclientset.NewSimpleClientset() logger := zap.NewNop() handler := &EventTypeAutoHandler{ EventTypeLister: listers.GetEventTypeLister(), - EventingClient: eventingClient.EventingV1beta2(), + EventingClient: eventingClient.EventingV1beta3(), FeatureStore: initFeatureStore(t, tc.featureFlag), Logger: logger, } @@ -99,7 +99,7 @@ func TestEventTypeAutoHandler_AutoCreateEventType(t *testing.T) { time.Sleep(time.Millisecond * 500) // autocreate runs in a different goroutine, need to wait for it to finish etName := generateEventTypeName(tc.addressable.Name, tc.addressable.Namespace, event.Type(), event.Source()) - et, err := eventingClient.EventingV1beta2().EventTypes(tc.addressable.Namespace).Get(ctx, etName, metav1.GetOptions{}) + et, err := eventingClient.EventingV1beta3().EventTypes(tc.addressable.Namespace).Get(ctx, etName, metav1.GetOptions{}) if err != nil { t.Error(err) } @@ -272,9 +272,9 @@ func initEvent(eventType string) v2.Event { return e } -func initEventTypeObject() v1beta2.EventType { - return v1beta2.EventType{ - Spec: v1beta2.EventTypeSpec{ +func initEventTypeObject() v1beta3.EventType { + return v1beta3.EventType{ + Spec: v1beta3.EventTypeSpec{ Reference: &duckv1.KReference{ APIVersion: "eventing.knative.dev/v1", Kind: "Broker", diff --git a/pkg/reconciler/inmemorychannel/dispatcher/controller.go b/pkg/reconciler/inmemorychannel/dispatcher/controller.go index 2eac2c0771c..77fd0342f62 100644 --- a/pkg/reconciler/inmemorychannel/dispatcher/controller.go +++ b/pkg/reconciler/inmemorychannel/dispatcher/controller.go @@ -55,7 +55,7 @@ import ( "knative.dev/eventing/pkg/channel" eventingclient "knative.dev/eventing/pkg/client/injection/client" eventpolicyinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1alpha1/eventpolicy" - eventtypeinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta2/eventtype" + eventtypeinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta3/eventtype" inmemorychannelinformer "knative.dev/eventing/pkg/client/injection/informers/messaging/v1/inmemorychannel" inmemorychannelreconciler "knative.dev/eventing/pkg/client/injection/reconciler/messaging/v1/inmemorychannel" "knative.dev/eventing/pkg/inmemorychannel" @@ -143,7 +143,7 @@ func NewController( multiChannelEventHandler: sh, reporter: reporter, messagingClientSet: eventingclient.Get(ctx).MessagingV1(), - eventingClient: eventingclient.Get(ctx).EventingV1beta2(), + eventingClient: eventingclient.Get(ctx).EventingV1beta3(), eventTypeLister: eventtypeinformer.Get(ctx).Lister(), eventDispatcher: kncloudevents.NewDispatcher(clientConfig, oidcTokenProvider), authVerifier: auth.NewVerifier(ctx, eventpolicyinformer.Get(ctx).Lister(), trustBundleConfigMapLister, cmw), diff --git a/pkg/reconciler/inmemorychannel/dispatcher/controller_test.go b/pkg/reconciler/inmemorychannel/dispatcher/controller_test.go index ed9994d934c..73d013c26ec 100644 --- a/pkg/reconciler/inmemorychannel/dispatcher/controller_test.go +++ b/pkg/reconciler/inmemorychannel/dispatcher/controller_test.go @@ -41,7 +41,7 @@ import ( _ "knative.dev/pkg/injection/clients/namespacedkube/informers/core/v1/secret/fake" _ "knative.dev/eventing/pkg/client/injection/informers/eventing/v1alpha1/eventpolicy/fake" - _ "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta2/eventtype/fake" + _ "knative.dev/eventing/pkg/client/injection/informers/eventing/v1beta3/eventtype/fake" _ "knative.dev/eventing/pkg/client/injection/informers/messaging/v1/inmemorychannel/fake" ) diff --git a/pkg/reconciler/inmemorychannel/dispatcher/inmemorychannel.go b/pkg/reconciler/inmemorychannel/dispatcher/inmemorychannel.go index 5949f5b1382..8f663491d65 100644 --- a/pkg/reconciler/inmemorychannel/dispatcher/inmemorychannel.go +++ b/pkg/reconciler/inmemorychannel/dispatcher/inmemorychannel.go @@ -42,10 +42,10 @@ import ( "knative.dev/eventing/pkg/channel" "knative.dev/eventing/pkg/channel/fanout" "knative.dev/eventing/pkg/channel/multichannelfanout" - eventingv1beta2 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta2" + eventingv1beta3 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1beta3" messagingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/messaging/v1" reconcilerv1 "knative.dev/eventing/pkg/client/injection/reconciler/messaging/v1/inmemorychannel" - "knative.dev/eventing/pkg/client/listers/eventing/v1beta2" + "knative.dev/eventing/pkg/client/listers/eventing/v1beta3" "knative.dev/eventing/pkg/eventingtls" "knative.dev/eventing/pkg/eventtype" "knative.dev/eventing/pkg/kncloudevents" @@ -56,9 +56,9 @@ type Reconciler struct { multiChannelEventHandler multichannelfanout.MultiChannelEventHandler reporter channel.StatsReporter messagingClientSet messagingv1.MessagingV1Interface - eventTypeLister v1beta2.EventTypeLister + eventTypeLister v1beta3.EventTypeLister inMemoryChannelLister listers.InMemoryChannelLister - eventingClient eventingv1beta2.EventingV1beta2Interface + eventingClient eventingv1beta3.EventingV1beta3Interface featureStore *feature.Store eventDispatcher *kncloudevents.Dispatcher diff --git a/pkg/reconciler/testing/v1beta3/eventtype.go b/pkg/reconciler/testing/v1beta3/eventtype.go new file mode 100644 index 00000000000..3a7aa75430c --- /dev/null +++ b/pkg/reconciler/testing/v1beta3/eventtype.go @@ -0,0 +1,127 @@ +/* +Copyright 2023 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 testing + +import ( + "context" + "time" + + duckv1 "knative.dev/pkg/apis/duck/v1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/eventing/pkg/apis/eventing/v1beta3" + "knative.dev/pkg/apis" +) + +// EventTypeOption enables further configuration of an EventType. +type EventTypeOption func(*v1beta3.EventType) + +// NewEventType creates a EventType with EventTypeOptions. +func NewEventType(name, namespace string, o ...EventTypeOption) *v1beta3.EventType { + et := &v1beta3.EventType{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + } + for _, opt := range o { + opt(et) + } + et.SetDefaults(context.Background()) + return et +} + +// WithInitEventTypeConditions initializes the EventType's conditions. +func WithInitEventTypeConditions(et *v1beta3.EventType) { + et.Status.InitializeConditions() +} + +func WithEventTypeSource(source *apis.URL) EventTypeOption { + return func(et *v1beta3.EventType) { + if et.Spec.Attributes == nil { + et.Spec.Attributes = make([]v1beta3.EventAttributeDefinition, 0) + } + et.Spec.Attributes = append(et.Spec.Attributes, v1beta3.EventAttributeDefinition{Name: "source", Value: source.String(), Required: true}) + } +} + +func WithEventTypeType(t string) EventTypeOption { + return func(et *v1beta3.EventType) { + if et.Spec.Attributes == nil { + et.Spec.Attributes = make([]v1beta3.EventAttributeDefinition, 0) + } + et.Spec.Attributes = append(et.Spec.Attributes, v1beta3.EventAttributeDefinition{Name: "type", Value: t, Required: true}) + } +} + +func WithEventTypeSpecVersion(specVersion string) EventTypeOption { + return func(et *v1beta3.EventType) { + if et.Spec.Attributes == nil { + et.Spec.Attributes = make([]v1beta3.EventAttributeDefinition, 0) + } + et.Spec.Attributes = append(et.Spec.Attributes, v1beta3.EventAttributeDefinition{Name: "specversion", Value: specVersion, Required: true}) + } +} + +func WithEventTypeId() EventTypeOption { + return func(et *v1beta3.EventType) { + if et.Spec.Attributes == nil { + et.Spec.Attributes = make([]v1beta3.EventAttributeDefinition, 0) + } + et.Spec.Attributes = append(et.Spec.Attributes, v1beta3.EventAttributeDefinition{Name: "id", Required: true}) + } +} +func WithEventTypeReference(ref *duckv1.KReference) EventTypeOption { + return func(et *v1beta3.EventType) { + et.Spec.Reference = ref + } +} + +func WithEventTypeDescription(description string) EventTypeOption { + return func(et *v1beta3.EventType) { + et.Spec.Description = description + } +} + +func WithEventTypeLabels(labels map[string]string) EventTypeOption { + return func(et *v1beta3.EventType) { + et.ObjectMeta.Labels = labels + } +} + +func WithEventTypeOwnerReference(ownerRef metav1.OwnerReference) EventTypeOption { + return func(et *v1beta3.EventType) { + et.ObjectMeta.OwnerReferences = []metav1.OwnerReference{ + ownerRef, + } + } +} + +func WithEventTypeDeletionTimestamp(et *v1beta3.EventType) { + t := metav1.NewTime(time.Unix(1e9, 0)) + et.ObjectMeta.SetDeletionTimestamp(&t) +} + +// WithEventTypeResourceDoesNotExist calls .Status.MarkFilterFailed on the EventType. +func WithEventTypeResourceDoesNotExist(et *v1beta3.EventType) { + et.Status.MarkReferenceDoesNotExist() +} + +// WithEventTypeResourceExists calls .Status.MarkReferenceExists on the EventType. +func WithEventTypeResourceExists(et *v1beta3.EventType) { + et.Status.MarkReferenceExists() +} diff --git a/pkg/reconciler/testing/v1beta3/factory.go b/pkg/reconciler/testing/v1beta3/factory.go new file mode 100644 index 00000000000..df5ea0a2dbf --- /dev/null +++ b/pkg/reconciler/testing/v1beta3/factory.go @@ -0,0 +1,147 @@ +/* +Copyright 2023 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 testing + +import ( + "context" + "encoding/json" + "testing" + + "knative.dev/pkg/configmap" + "knative.dev/pkg/logging" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + + "k8s.io/client-go/tools/record" + + "go.uber.org/zap" + ktesting "k8s.io/client-go/testing" + "knative.dev/pkg/controller" + + fakeeventingclient "knative.dev/eventing/pkg/client/injection/client/fake" + fakeapiextensionsclient "knative.dev/pkg/client/injection/apiextensions/client/fake" + fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake" + fakedynamicclient "knative.dev/pkg/injection/clients/dynamicclient/fake" + + "knative.dev/pkg/reconciler" + . "knative.dev/pkg/reconciler/testing" +) + +const ( + // maxEventBufferSize is the estimated max number of event notifications that + // can be buffered during reconciliation. + maxEventBufferSize = 10 +) + +// Ctor functions create a k8s controller with given params. +type Ctor func(context.Context, *Listers, configmap.Watcher) controller.Reconciler + +// MakeFactory creates a reconciler factory with fake clients and controller created by `ctor`. +func MakeFactory(ctor Ctor, unstructured bool, logger *zap.SugaredLogger) Factory { + return func(t *testing.T, r *TableRow) (controller.Reconciler, ActionRecorderList, EventList) { + ls := NewListers(r.Objects) + + ctx := context.Background() + ctx = logging.WithLogger(ctx, logger) + + ctx, kubeClient := fakekubeclient.With(ctx, ls.GetKubeObjects()...) + ctx, client := fakeeventingclient.With(ctx, ls.GetEventingObjects()...) + ctx, extClient := fakeapiextensionsclient.With(ctx, ls.GetAPIExtensionObjects()...) + ctx, dynamicClient := fakedynamicclient.With(ctx, + NewScheme(), ToUnstructured(t, r.Objects)...) + + // The dynamic client's support for patching is BS. Implement it + // here via PrependReactor (this can be overridden below by the + // provided reactors). + dynamicClient.PrependReactor("patch", "*", + func(action ktesting.Action) (bool, runtime.Object, error) { + return true, nil, nil + }) + + eventRecorder := record.NewFakeRecorder(maxEventBufferSize) + ctx = controller.WithEventRecorder(ctx, eventRecorder) + + // Set up our Controller from the fakes. + c := ctor(ctx, &ls, configmap.NewStaticWatcher()) + + // If the reconcilers is leader aware, then promote it. + if la, ok := c.(reconciler.LeaderAware); ok { + la.Promote(reconciler.UniversalBucket(), func(reconciler.Bucket, types.NamespacedName) {}) + } + + for _, reactor := range r.WithReactors { + kubeClient.PrependReactor("*", "*", reactor) + client.PrependReactor("*", "*", reactor) + dynamicClient.PrependReactor("*", "*", reactor) + extClient.PrependReactor("*", "*", reactor) + } + + // Validate all Create operations through the eventing client. + client.PrependReactor("create", "*", func(action ktesting.Action) (handled bool, ret runtime.Object, err error) { + return ValidateCreates(ctx, action) + }) + client.PrependReactor("update", "*", func(action ktesting.Action) (handled bool, ret runtime.Object, err error) { + return ValidateUpdates(ctx, action) + }) + + actionRecorderList := ActionRecorderList{dynamicClient, client, kubeClient} + eventList := EventList{Recorder: eventRecorder} + + return c, actionRecorderList, eventList + } +} + +// ToUnstructured takes a list of k8s resources and converts them to +// Unstructured objects. +// We must pass objects as Unstructured to the dynamic client fake, or it +// won't handle them properly. +func ToUnstructured(t *testing.T, objs []runtime.Object) (us []runtime.Object) { + sch := NewScheme() + for _, obj := range objs { + obj = obj.DeepCopyObject() // Don't mess with the primary copy + + ta, err := meta.TypeAccessor(obj) + if err != nil { + t.Fatal("Unable to create type accessor:", err) + } + + if ta.GetAPIVersion() == "" || ta.GetKind() == "" { + // Determine and set the TypeMeta for this object based on our test scheme. + gvks, _, err := sch.ObjectKinds(obj) + if err != nil { + t.Fatal("Unable to determine kind for type:", err) + } + apiv, k := gvks[0].ToAPIVersionAndKind() + ta.SetAPIVersion(apiv) + ta.SetKind(k) + } + + b, err := json.Marshal(obj) + if err != nil { + t.Fatal("Unable to marshal:", err) + } + u := &unstructured.Unstructured{} + if err := json.Unmarshal(b, u); err != nil { + t.Fatal("Unable to unmarshal:", err) + } + us = append(us, u) + } + return +} diff --git a/pkg/reconciler/testing/v1beta3/listers.go b/pkg/reconciler/testing/v1beta3/listers.go new file mode 100644 index 00000000000..0c451f2db78 --- /dev/null +++ b/pkg/reconciler/testing/v1beta3/listers.go @@ -0,0 +1,145 @@ +/* +Copyright 2023 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 testing + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + fakeapiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" + apiextensionsv1listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1" + "k8s.io/apimachinery/pkg/runtime" + fakekubeclientset "k8s.io/client-go/kubernetes/fake" + appsv1listers "k8s.io/client-go/listers/apps/v1" + corev1listers "k8s.io/client-go/listers/core/v1" + rbacv1listers "k8s.io/client-go/listers/rbac/v1" + "k8s.io/client-go/tools/cache" + eventingv1beta3 "knative.dev/eventing/pkg/apis/eventing/v1beta3" + fakeeventingclientset "knative.dev/eventing/pkg/client/clientset/versioned/fake" + eventingv1beta3listers "knative.dev/eventing/pkg/client/listers/eventing/v1beta3" + testscheme "knative.dev/eventing/pkg/reconciler/testing/scheme" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/reconciler/testing" +) + +var clientSetSchemes = []func(*runtime.Scheme) error{ + fakekubeclientset.AddToScheme, + fakeeventingclientset.AddToScheme, + fakeapiextensionsclientset.AddToScheme, + duckv1.AddToScheme, + testscheme.Eventing.AddToScheme, + testscheme.Serving.AddToScheme, +} + +type Listers struct { + sorter testing.ObjectSorter +} + +func NewScheme() *runtime.Scheme { + scheme := runtime.NewScheme() + + for _, addTo := range clientSetSchemes { + addTo(scheme) + } + return scheme +} + +func NewListers(objs []runtime.Object) Listers { + scheme := runtime.NewScheme() + + for _, addTo := range clientSetSchemes { + addTo(scheme) + } + + ls := Listers{ + sorter: testing.NewObjectSorter(scheme), + } + + ls.sorter.AddObjects(objs...) + + return ls +} + +func (l *Listers) indexerFor(obj runtime.Object) cache.Indexer { + return l.sorter.IndexerForObjectType(obj) +} + +func (l *Listers) GetKubeObjects() []runtime.Object { + return l.sorter.ObjectsForSchemeFunc(fakekubeclientset.AddToScheme) +} + +func (l *Listers) GetAPIExtensionObjects() []runtime.Object { + return l.sorter.ObjectsForSchemeFunc(fakeapiextensionsclientset.AddToScheme) +} + +func (l *Listers) GetEventingObjects() []runtime.Object { + return l.sorter.ObjectsForSchemeFunc(fakeeventingclientset.AddToScheme) +} + +func (l *Listers) GetSubscriberObjects() []runtime.Object { + return l.sorter.ObjectsForSchemeFunc(testscheme.SubscriberToScheme) +} + +func (l *Listers) GetAllObjects() []runtime.Object { + all := l.GetSubscriberObjects() + all = append(all, l.GetEventingObjects()...) + all = append(all, l.GetKubeObjects()...) + all = append(all, l.GetAPIExtensionObjects()...) + + return all +} + +func (l *Listers) GetEventTypeLister() eventingv1beta3listers.EventTypeLister { + return eventingv1beta3listers.NewEventTypeLister(l.indexerFor(&eventingv1beta3.EventType{})) +} + +func (l *Listers) GetDeploymentLister() appsv1listers.DeploymentLister { + return appsv1listers.NewDeploymentLister(l.indexerFor(&appsv1.Deployment{})) +} + +func (l *Listers) GetK8sServiceLister() corev1listers.ServiceLister { + return corev1listers.NewServiceLister(l.indexerFor(&corev1.Service{})) +} + +func (l *Listers) GetNamespaceLister() corev1listers.NamespaceLister { + return corev1listers.NewNamespaceLister(l.indexerFor(&corev1.Namespace{})) +} + +func (l *Listers) GetServiceAccountLister() corev1listers.ServiceAccountLister { + return corev1listers.NewServiceAccountLister(l.indexerFor(&corev1.ServiceAccount{})) +} + +func (l *Listers) GetServiceLister() corev1listers.ServiceLister { + return corev1listers.NewServiceLister(l.indexerFor(&corev1.Service{})) +} + +func (l *Listers) GetRoleBindingLister() rbacv1listers.RoleBindingLister { + return rbacv1listers.NewRoleBindingLister(l.indexerFor(&rbacv1.RoleBinding{})) +} + +func (l *Listers) GetEndpointsLister() corev1listers.EndpointsLister { + return corev1listers.NewEndpointsLister(l.indexerFor(&corev1.Endpoints{})) +} + +func (l *Listers) GetConfigMapLister() corev1listers.ConfigMapLister { + return corev1listers.NewConfigMapLister(l.indexerFor(&corev1.ConfigMap{})) +} + +func (l *Listers) GetCustomResourceDefinitionLister() apiextensionsv1listers.CustomResourceDefinitionLister { + return apiextensionsv1listers.NewCustomResourceDefinitionLister(l.indexerFor(&apiextensionsv1.CustomResourceDefinition{})) +}