From 5297b9fe6ac8ad58a09edade480048599abe62eb Mon Sep 17 00:00:00 2001 From: Dharmjit Singh Date: Thu, 20 Jun 2024 02:53:41 +0000 Subject: [PATCH] add eventpolicy reconciler Signed-off-by: Dharmjit Singh --- cmd/controller/main.go | 2 + pkg/reconciler/eventpolicy/controller.go | 49 ++++++ pkg/reconciler/eventpolicy/controller_test.go | 39 +++++ pkg/reconciler/eventpolicy/eventpolicy.go | 54 ++++++ .../eventpolicy/eventpolicy_test.go | 155 ++++++++++++++++++ pkg/reconciler/testing/v1/eventpolicy.go | 7 + pkg/reconciler/testing/v1/listers.go | 8 +- .../ducks/duck/v1/authstatus/fake/fake.go | 30 ++++ vendor/modules.txt | 1 + 9 files changed, 341 insertions(+), 4 deletions(-) create mode 100644 pkg/reconciler/eventpolicy/controller.go create mode 100644 pkg/reconciler/eventpolicy/controller_test.go create mode 100644 pkg/reconciler/eventpolicy/eventpolicy.go create mode 100644 pkg/reconciler/eventpolicy/eventpolicy_test.go create mode 100644 vendor/knative.dev/pkg/client/injection/ducks/duck/v1/authstatus/fake/fake.go diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 79fd5588fed..5b01605a5da 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -34,6 +34,7 @@ import ( "knative.dev/eventing/pkg/apis/sinks" "knative.dev/eventing/pkg/auth" "knative.dev/eventing/pkg/eventingtls" + "knative.dev/eventing/pkg/reconciler/eventpolicy" "knative.dev/eventing/pkg/reconciler/jobsink" "knative.dev/eventing/pkg/reconciler/apiserversource" @@ -93,6 +94,7 @@ func main() { // Eventing eventtype.NewController, + eventpolicy.NewController, // Flows parallel.NewController, diff --git a/pkg/reconciler/eventpolicy/controller.go b/pkg/reconciler/eventpolicy/controller.go new file mode 100644 index 00000000000..44a79f36ba1 --- /dev/null +++ b/pkg/reconciler/eventpolicy/controller.go @@ -0,0 +1,49 @@ +/* +Copyright 2024 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 eventpolicy + +import ( + "context" + + eventpolicyinformer "knative.dev/eventing/pkg/client/injection/informers/eventing/v1alpha1/eventpolicy" + eventpolicyreconciler "knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1alpha1/eventpolicy" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + "knative.dev/pkg/resolver" +) + +// NewController initializes the controller and is called by the generated code +// Registers event handlers to enqueue events +func NewController( + ctx context.Context, + cmw configmap.Watcher, +) *controller.Impl { + // Access informers + eventPolicyInformer := eventpolicyinformer.Get(ctx) + + r := &Reconciler{ + eventPolicyLister: eventPolicyInformer.Lister(), + } + impl := eventpolicyreconciler.NewImpl(ctx, r) + + r.fromRefResolver = resolver.NewAuthenticatableResolverFromTracker(ctx, impl.Tracker) + + // Set up event handlers + eventPolicyInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) + + return impl +} diff --git a/pkg/reconciler/eventpolicy/controller_test.go b/pkg/reconciler/eventpolicy/controller_test.go new file mode 100644 index 00000000000..524f224ecd1 --- /dev/null +++ b/pkg/reconciler/eventpolicy/controller_test.go @@ -0,0 +1,39 @@ +/* +Copyright 2024 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 eventpolicy + +import ( + "testing" + + "knative.dev/pkg/configmap" + + . "knative.dev/pkg/reconciler/testing" + + // Fake injection informers + _ "knative.dev/eventing/pkg/client/injection/informers/eventing/v1alpha1/eventpolicy/fake" + _ "knative.dev/pkg/client/injection/ducks/duck/v1/authstatus/fake" +) + +func TestNew(t *testing.T) { + ctx, _ := SetupFakeContext(t) + + c := NewController(ctx, configmap.NewStaticWatcher()) + + if c == nil { + t.Fatal("Expected NewController to return a non-nil value") + } +} diff --git a/pkg/reconciler/eventpolicy/eventpolicy.go b/pkg/reconciler/eventpolicy/eventpolicy.go new file mode 100644 index 00000000000..3f2d8c1a073 --- /dev/null +++ b/pkg/reconciler/eventpolicy/eventpolicy.go @@ -0,0 +1,54 @@ +/* +Copyright 2024 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 eventpolicy + +import ( + "context" + + "go.uber.org/zap" + "knative.dev/eventing/pkg/apis/eventing/v1alpha1" + "knative.dev/eventing/pkg/auth" + eventinglisters "knative.dev/eventing/pkg/client/listers/eventing/v1alpha1" + "knative.dev/pkg/logging" + pkgreconciler "knative.dev/pkg/reconciler" + "knative.dev/pkg/resolver" +) + +type Reconciler struct { + eventPolicyLister eventinglisters.EventPolicyLister + fromRefResolver *resolver.AuthenticatableResolver +} + +// ReconcileKind implements Interface.ReconcileKind. +// 1. Verify the Reference exists. +func (r *Reconciler) ReconcileKind(ctx context.Context, ep *v1alpha1.EventPolicy) pkgreconciler.Event { + logger := logging.FromContext(ctx) + logger.Infow("Reconciling", zap.Any("EventPolicy", ep)) + // We reconcile the status of the EventPolicy by looking at: + // 1. All from[].refs have subjects + serverAccts, err := auth.ResolveSubjects(r.fromRefResolver, ep) + if err != nil { + logger.Errorw("Error resolving from[].refs", zap.Error(err)) + ep.GetConditionSet().Manage(ep.GetStatus()).MarkFalse(v1alpha1.EventPolicyConditionReady, "Error resolving from[].refs", "") + } else { + logger.Debug("All from[].refs resolved", zap.Error(err)) + ep.GetConditionSet().Manage(ep.GetStatus()).MarkTrue(v1alpha1.EventPolicyConditionReady) + } + ep.Status.From = serverAccts + logger.Debugw("Reconciled EventPolicy", zap.Any("EventPolicy", ep)) + return nil +} diff --git a/pkg/reconciler/eventpolicy/eventpolicy_test.go b/pkg/reconciler/eventpolicy/eventpolicy_test.go new file mode 100644 index 00000000000..d2e4942c82b --- /dev/null +++ b/pkg/reconciler/eventpolicy/eventpolicy_test.go @@ -0,0 +1,155 @@ +/* +Copyright 2024 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 eventpolicy + +import ( + "context" + "fmt" + "testing" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + clientgotesting "k8s.io/client-go/testing" + sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" + fakeeventingclient "knative.dev/eventing/pkg/client/injection/client/fake" + "knative.dev/eventing/pkg/client/injection/reconciler/eventing/v1alpha1/eventpolicy" + . "knative.dev/eventing/pkg/reconciler/testing/v1" + duckv1authstatus "knative.dev/pkg/client/injection/ducks/duck/v1/authstatus" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + logtesting "knative.dev/pkg/logging/testing" + . "knative.dev/pkg/reconciler/testing" + "knative.dev/pkg/resolver" + "knative.dev/pkg/tracker" +) + +const ( + testNS = "test-namespace" + eventPolicyName = "test-eventpolicy" + pingSourceName = "test-pingsource" + apiServerSourceName = "test-apiserversource" + serviceAccountname = "test-sa" +) + +var ( + pingSourceWithServiceAccount = NewPingSource(pingSourceName, testNS, WithPingSourceOIDCServiceAccountName(serviceAccountname)) + apiServerSourceWithServiceAccount = NewApiServerSource(apiServerSourceName, testNS, WithApiServerSourceOIDCServiceAccountName((serviceAccountname))) +) + +func TestReconcile(t *testing.T) { + table := TableTest{ + { + Name: "bad workqueue key", + // Make sure Reconcile handles bad keys. + Key: "too/many/parts", + }, + { + Name: "subject not found, status set to NotReady", + Key: testNS + "/" + eventPolicyName, + Objects: []runtime.Object{ + NewEventPolicy(eventPolicyName, testNS, + WithInitEventPolicyConditions, + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("PingSource")), pingSourceName, testNS), + ), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{ + { + Object: NewEventPolicy(eventPolicyName, testNS, + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("PingSource")), pingSourceName, testNS), + WithUnreadyEventPolicyCondition), + }, + }, + WantErr: false, + }, + { + Name: "subject found for pingsource, status set to Ready", + Key: testNS + "/" + eventPolicyName, + Objects: []runtime.Object{ + pingSourceWithServiceAccount, + NewEventPolicy(eventPolicyName, testNS, + WithInitEventPolicyConditions, + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("PingSource")), pingSourceName, testNS)), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{ + { + Object: NewEventPolicy(eventPolicyName, testNS, + WithInitEventPolicyConditions, + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("PingSource")), pingSourceName, testNS), + WithEventPolicyStatusFromSub([]string{fmt.Sprintf("system:serviceaccount:%s:%s", testNS, serviceAccountname)}), + WithReadyEventPolicyCondition), + }, + }, + WantErr: false, + }, + { + Name: "subject found for apiserversource, status set to Ready", + Key: testNS + "/" + eventPolicyName, + Objects: []runtime.Object{ + apiServerSourceWithServiceAccount, + NewEventPolicy(eventPolicyName, testNS, + WithInitEventPolicyConditions, WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("APIServerSource")), apiServerSourceName, testNS)), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{ + { + Object: NewEventPolicy(eventPolicyName, testNS, + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("APIServerSource")), apiServerSourceName, testNS), + WithEventPolicyStatusFromSub([]string{fmt.Sprintf("system:serviceaccount:%s:%s", testNS, serviceAccountname)}), + WithReadyEventPolicyCondition), + }, + }, + WantErr: false, + }, + { + Name: "Multiple subjects found, status set to Ready", + Key: testNS + "/" + eventPolicyName, + Objects: []runtime.Object{ + apiServerSourceWithServiceAccount, + pingSourceWithServiceAccount, + NewEventPolicy(eventPolicyName, testNS, + WithInitEventPolicyConditions, + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("PingSource")), pingSourceName, testNS), + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("APIServerSource")), apiServerSourceName, testNS)), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{ + { + Object: NewEventPolicy(eventPolicyName, testNS, + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("PingSource")), pingSourceName, testNS), + WithEventPolicyFrom(v1.GroupVersionKind(sourcesv1.SchemeGroupVersion.WithKind("APIServerSource")), apiServerSourceName, testNS), + WithEventPolicyStatusFromSub([]string{ + fmt.Sprintf("system:serviceaccount:%s:%s", testNS, serviceAccountname), + fmt.Sprintf("system:serviceaccount:%s:%s", testNS, serviceAccountname), + }), + WithReadyEventPolicyCondition), + }, + }, + WantErr: false, + }, + } + logger := logtesting.TestLogger(t) + table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler { + ctx = duckv1authstatus.WithDuck(ctx) + r := &Reconciler{ + fromRefResolver: resolver.NewAuthenticatableResolverFromTracker(ctx, tracker.New(func(types.NamespacedName) {}, 0))} + return eventpolicy.NewReconciler(ctx, logger, + fakeeventingclient.Get(ctx), listers.GetEventPolicyLister(), + controller.GetEventRecorder(ctx), r) + }, + false, + logger, + )) +} diff --git a/pkg/reconciler/testing/v1/eventpolicy.go b/pkg/reconciler/testing/v1/eventpolicy.go index 0d2934ac6ce..cc3352aecb9 100644 --- a/pkg/reconciler/testing/v1/eventpolicy.go +++ b/pkg/reconciler/testing/v1/eventpolicy.go @@ -62,6 +62,7 @@ func WithUnreadyEventPolicyCondition(ep *v1alpha1.EventPolicy) { { Type: v1alpha1.EventPolicyConditionReady, Status: corev1.ConditionFalse, + Reason: "Error resolving from[].refs", }, } } @@ -102,3 +103,9 @@ func WithEventPolicyOwnerReferences(ownerRefs ...metav1.OwnerReference) EventPol ep.ObjectMeta.OwnerReferences = append(ep.ObjectMeta.OwnerReferences, ownerRefs...) } } + +func WithEventPolicyStatusFromSub(subs []string) EventPolicyOption { + return func(ep *v1alpha1.EventPolicy) { + ep.Status.From = append(ep.Status.From, subs...) + } +} diff --git a/pkg/reconciler/testing/v1/listers.go b/pkg/reconciler/testing/v1/listers.go index 0c7c3546d2c..b738d212ab6 100644 --- a/pkg/reconciler/testing/v1/listers.go +++ b/pkg/reconciler/testing/v1/listers.go @@ -110,14 +110,14 @@ func (l *Listers) GetAllObjects() []runtime.Object { return all } -func (l *Listers) GetEventTypeLister() eventingv1beta2listers.EventTypeLister { - return eventingv1beta2listers.NewEventTypeLister(l.indexerFor(&eventingv1beta2.EventType{})) -} - func (l *Listers) GetEventPolicyLister() eventingv1alpha1listers.EventPolicyLister { return eventingv1alpha1listers.NewEventPolicyLister(l.indexerFor(&eventingv1alpha1.EventPolicy{})) } +func (l *Listers) GetEventTypeLister() eventingv1beta2listers.EventTypeLister { + return eventingv1beta2listers.NewEventTypeLister(l.indexerFor(&eventingv1beta2.EventType{})) +} + func (l *Listers) GetPingSourceLister() sourcelisters.PingSourceLister { return sourcelisters.NewPingSourceLister(l.indexerFor(&sourcesv1.PingSource{})) } diff --git a/vendor/knative.dev/pkg/client/injection/ducks/duck/v1/authstatus/fake/fake.go b/vendor/knative.dev/pkg/client/injection/ducks/duck/v1/authstatus/fake/fake.go new file mode 100644 index 00000000000..47111b089b7 --- /dev/null +++ b/vendor/knative.dev/pkg/client/injection/ducks/duck/v1/authstatus/fake/fake.go @@ -0,0 +1,30 @@ +/* +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. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fake + +import ( + authstatus "knative.dev/pkg/client/injection/ducks/duck/v1/authstatus" + injection "knative.dev/pkg/injection" +) + +var Get = authstatus.Get + +func init() { + injection.Fake.RegisterDuck(authstatus.WithDuck) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 31702cfc1d7..e5e05d37017 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1081,6 +1081,7 @@ knative.dev/pkg/client/injection/apiextensions/reconciler/apiextensions/v1/custo knative.dev/pkg/client/injection/ducks/duck/v1/addressable knative.dev/pkg/client/injection/ducks/duck/v1/addressable/fake knative.dev/pkg/client/injection/ducks/duck/v1/authstatus +knative.dev/pkg/client/injection/ducks/duck/v1/authstatus/fake knative.dev/pkg/client/injection/ducks/duck/v1/conditions knative.dev/pkg/client/injection/ducks/duck/v1/conditions/fake knative.dev/pkg/client/injection/ducks/duck/v1/kresource