diff --git a/pkg/auth/event_policy.go b/pkg/auth/event_policy.go index 7d4fcb1dbad..d8635167439 100644 --- a/pkg/auth/event_policy.go +++ b/pkg/auth/event_policy.go @@ -18,6 +18,7 @@ package auth import ( "fmt" + "sort" "strings" eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" @@ -93,6 +94,11 @@ func GetEventPoliciesForResource(lister listerseventingv1alpha1.EventPolicyListe } } + // Sort the policies by name to ensure deterministic order + sort.Slice(relevantPolicies, func(i, j int) bool { + return relevantPolicies[i].Name < relevantPolicies[j].Name + }) + return relevantPolicies, nil } diff --git a/pkg/reconciler/sequence/resources/eventpolicy.go b/pkg/reconciler/sequence/resources/eventpolicy.go new file mode 100644 index 00000000000..efe14d3d541 --- /dev/null +++ b/pkg/reconciler/sequence/resources/eventpolicy.go @@ -0,0 +1,118 @@ +/* +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 resources + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" + eventingv1alpha1 "knative.dev/eventing/pkg/apis/eventing/v1alpha1" + flowsv1 "knative.dev/eventing/pkg/apis/flows/v1" + messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" + "knative.dev/pkg/kmeta" +) + +const ( + SequenceChannelEventPolicyLabelPrefix = "flows.knative.dev/" + sequenceKind = "Sequence" + subscriptionKind = "Subscription" + eventPolicyKind = "EventPolicy" +) + +func MakeEventPolicyForSequenceChannel(s *flowsv1.Sequence, channel *eventingduckv1.Channelable, subscription *messagingv1.Subscription) *eventingv1alpha1.EventPolicy { + return &eventingv1alpha1.EventPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: channel.Namespace, + Name: SequenceEventPolicyName(s.Name, channel.Name), + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: flowsv1.SchemeGroupVersion.String(), + Kind: sequenceKind, + Name: s.Name, + UID: s.UID, + }, + }, + Labels: LabelsForSequenceChannelsEventPolicy(s.Name), + }, + Spec: eventingv1alpha1.EventPolicySpec{ + To: []eventingv1alpha1.EventPolicySpecTo{ + { + Ref: &eventingv1alpha1.EventPolicyToReference{ + APIVersion: channel.APIVersion, + Kind: channel.Kind, + Name: channel.Name, + }, + }, + }, + From: []eventingv1alpha1.EventPolicySpecFrom{ + { + Ref: &eventingv1alpha1.EventPolicyFromReference{ + APIVersion: messagingv1.SchemeGroupVersion.String(), + Kind: subscriptionKind, + Name: subscription.Name, + Namespace: subscription.Namespace, + }, + }, + }, + }, + } +} + +func LabelsForSequenceChannelsEventPolicy(sequenceName string) map[string]string { + return map[string]string{ + SequenceChannelEventPolicyLabelPrefix + "sequence-name": sequenceName, + } +} + +func SequenceEventPolicyName(sequenceName, postfix string) string { + + if postfix == "" { + return sequenceName + } + return kmeta.ChildName(sequenceName, "-"+postfix) + +} + +// MakeEventPolicyForSequenceInputChannel creates an EventPolicy for the input channel of a Sequence +func MakeEventPolicyForSequenceInputChannel(s *flowsv1.Sequence, inputChannel *eventingduckv1.Channelable, sequencePolicy *eventingv1alpha1.EventPolicy) *eventingv1alpha1.EventPolicy { + return &eventingv1alpha1.EventPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: inputChannel.Namespace, + Name: SequenceEventPolicyName(s.Name, sequencePolicy.Name), + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: eventingv1alpha1.SchemeGroupVersion.String(), + Kind: eventPolicyKind, + Name: sequencePolicy.Name, + UID: sequencePolicy.UID, + }, + }, + Labels: LabelsForSequenceChannelsEventPolicy(s.Name), + }, + Spec: eventingv1alpha1.EventPolicySpec{ + To: []eventingv1alpha1.EventPolicySpecTo{ + { + Ref: &eventingv1alpha1.EventPolicyToReference{ + APIVersion: inputChannel.APIVersion, + Kind: inputChannel.Kind, + Name: inputChannel.Name, + }, + }, + }, + From: sequencePolicy.Spec.From, + }, + } +} diff --git a/pkg/reconciler/sequence/sequence.go b/pkg/reconciler/sequence/sequence.go index cbb51035197..530d70b7166 100644 --- a/pkg/reconciler/sequence/sequence.go +++ b/pkg/reconciler/sequence/sequence.go @@ -22,6 +22,7 @@ import ( "go.uber.org/zap" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" apierrs "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,6 +38,7 @@ import ( "knative.dev/pkg/kmp" eventingduckv1 "knative.dev/eventing/pkg/apis/duck/v1" + eventingv1alpha1 "knative.dev/eventing/pkg/apis/eventing/v1alpha1" "knative.dev/eventing/pkg/apis/feature" v1 "knative.dev/eventing/pkg/apis/flows/v1" messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" @@ -130,6 +132,10 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, s *v1.Sequence) pkgrecon return err } + if err := r.reconcileEventPolicies(ctx, s, channels, subs, featureFlags); err != nil { + return fmt.Errorf("failed to reconcile EventPolicies: %w", err) + } + err := auth.UpdateStatusWithEventPolicies(featureFlags, &s.Status.AppliedEventPoliciesStatus, &s.Status, r.eventPolicyLister, v1.SchemeGroupVersion.WithKind("Sequence"), s.ObjectMeta) if err != nil { return fmt.Errorf("could not update Sequence status with EventPolicies: %v", err) @@ -333,3 +339,145 @@ func (r *Reconciler) removeUnwantedSubscriptions(ctx context.Context, seq *v1.Se return nil } + +func (r *Reconciler) reconcileEventPolicies(ctx context.Context, s *v1.Sequence, channels []*eventingduckv1.Channelable, subs []*messagingv1.Subscription, featureFlags feature.Flags) error { + if !featureFlags.IsOIDCAuthentication() { + return r.cleanupAllEventPolicies(ctx, s) + } + + existingPolicies, err := r.listEventPoliciesForSequence(s) + if err != nil { + return fmt.Errorf("failed to list existing EventPolicies: %w", err) + } + + // Prepare maps for efficient lookups, updates, and deletions of policies + existingPolicyMap := make(map[string]*eventingv1alpha1.EventPolicy) + for _, policy := range existingPolicies { + existingPolicyMap[policy.Name] = policy + } + + // Prepare lists for different actions so that policies can be categorized + var policiesToUpdate, policiesToCreate []*eventingv1alpha1.EventPolicy + policiesToDelete := make([]*eventingv1alpha1.EventPolicy, 0, len(existingPolicies)) + + // Handle intermediate channel policies (skip the first channel as it's the input channel!) + for i := 1; i < len(channels); i++ { + expectedPolicy := resources.MakeEventPolicyForSequenceChannel(s, channels[i], subs[i-1]) + existingPolicy, exists := existingPolicyMap[expectedPolicy.Name] + + if exists { + if !equality.Semantic.DeepDerivative(expectedPolicy, existingPolicy) { + expectedPolicy.SetResourceVersion(existingPolicy.ResourceVersion) + policiesToUpdate = append(policiesToUpdate, expectedPolicy) + } + delete(existingPolicyMap, expectedPolicy.Name) + } else { + policiesToCreate = append(policiesToCreate, expectedPolicy) + } + } + + // Handle input channel policies + inputPolicies, err := r.prepareInputChannelEventPolicy(s, channels[0]) + if err != nil { + return fmt.Errorf("failed to prepare input channel EventPolicies: %w", err) + } + for _, inputPolicy := range inputPolicies { + existingInputPolicy, exists := existingPolicyMap[inputPolicy.Name] + if exists { + if !equality.Semantic.DeepDerivative(inputPolicy, existingInputPolicy) { + inputPolicy.SetResourceVersion(existingInputPolicy.ResourceVersion) + policiesToUpdate = append(policiesToUpdate, inputPolicy) + } + delete(existingPolicyMap, inputPolicy.Name) + } else { + policiesToCreate = append(policiesToCreate, inputPolicy) + } + } + + // Any remaining policies in the map should be deleted + for _, policy := range existingPolicyMap { + policiesToDelete = append(policiesToDelete, policy) + } + + // Perform the actual CRUD operations + if err := r.createEventPolicies(ctx, policiesToCreate); err != nil { + return fmt.Errorf("failed to create EventPolicies: %w", err) + } + if err := r.updateEventPolicies(ctx, policiesToUpdate); err != nil { + return fmt.Errorf("failed to update EventPolicies: %w", err) + } + if err := r.deleteEventPolicies(ctx, policiesToDelete); err != nil { + return fmt.Errorf("failed to delete EventPolicies: %w", err) + } + + return nil +} + +// listEventPoliciesForSequence lists all EventPolicies (e.g. the policies for the input channel and the intermediate channels) created during reconcileKind that are associated with the given Sequence. +func (r *Reconciler) listEventPoliciesForSequence(s *v1.Sequence) ([]*eventingv1alpha1.EventPolicy, error) { + labelSelector := labels.SelectorFromSet(map[string]string{ + resources.SequenceChannelEventPolicyLabelPrefix + "sequence-name": s.Name, + }) + return r.eventPolicyLister.EventPolicies(s.Namespace).List(labelSelector) +} + +func (r *Reconciler) prepareInputChannelEventPolicy(s *v1.Sequence, inputChannel *eventingduckv1.Channelable) ([]*eventingv1alpha1.EventPolicy, error) { + matchingPolicies, err := auth.GetEventPoliciesForResource( + r.eventPolicyLister, + v1.SchemeGroupVersion.WithKind("Sequence"), + s.ObjectMeta, + ) + if err != nil { + return nil, fmt.Errorf("failed to get matching EventPolicies for Sequence: %w", err) + } + + if len(matchingPolicies) == 0 { + return nil, nil + } + + inputChannelPolicies := make([]*eventingv1alpha1.EventPolicy, 0, len(matchingPolicies)) + for _, policy := range matchingPolicies { + inputChannelPolicy := resources.MakeEventPolicyForSequenceInputChannel(s, inputChannel, policy) + inputChannelPolicies = append(inputChannelPolicies, inputChannelPolicy) + } + + return inputChannelPolicies, nil +} + +func (r *Reconciler) createEventPolicies(ctx context.Context, policies []*eventingv1alpha1.EventPolicy) error { + for _, policy := range policies { + _, err := r.eventingClientSet.EventingV1alpha1().EventPolicies(policy.Namespace).Create(ctx, policy, metav1.CreateOptions{}) + if err != nil { + return err + } + } + return nil +} + +func (r *Reconciler) updateEventPolicies(ctx context.Context, policies []*eventingv1alpha1.EventPolicy) error { + for _, policy := range policies { + _, err := r.eventingClientSet.EventingV1alpha1().EventPolicies(policy.Namespace).Update(ctx, policy, metav1.UpdateOptions{}) + if err != nil { + return err + } + } + return nil +} + +func (r *Reconciler) deleteEventPolicies(ctx context.Context, policies []*eventingv1alpha1.EventPolicy) error { + for _, policy := range policies { + err := r.eventingClientSet.EventingV1alpha1().EventPolicies(policy.Namespace).Delete(ctx, policy.Name, metav1.DeleteOptions{}) + if err != nil && !apierrs.IsNotFound(err) { + return err + } + } + return nil +} + +func (r *Reconciler) cleanupAllEventPolicies(ctx context.Context, s *v1.Sequence) error { + policies, err := r.listEventPoliciesForSequence(s) + if err != nil { + return fmt.Errorf("failed to list EventPolicies for cleanup: %w", err) + } + return r.deleteEventPolicies(ctx, policies) +} diff --git a/pkg/reconciler/sequence/sequence_test.go b/pkg/reconciler/sequence/sequence_test.go index 5232672e4cb..02d59cecc96 100644 --- a/pkg/reconciler/sequence/sequence_test.go +++ b/pkg/reconciler/sequence/sequence_test.go @@ -21,12 +21,15 @@ import ( "fmt" "testing" + "knative.dev/eventing/pkg/apis/feature" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" clientgotesting "k8s.io/client-go/testing" + eventingv1alpha1 "knative.dev/eventing/pkg/apis/eventing/v1alpha1" v1 "knative.dev/eventing/pkg/apis/flows/v1" messagingv1 "knative.dev/eventing/pkg/apis/messaging/v1" @@ -65,7 +68,7 @@ var ( subscriberGVK = metav1.GroupVersionKind{ Group: "messaging.knative.dev", Version: "v1", - Kind: "Subscriber", + Kind: "Subscription", } sequenceGVK = metav1.GroupVersionKind{ @@ -73,6 +76,18 @@ var ( Version: "v1", Kind: "Sequence", } + + channelV1GVK = metav1.GroupVersionKind{ + Group: "messaging.knative.dev", + Version: "v1", + Kind: "InMemoryChannel", + } + + eventPolicyV1Alpha1GVK = metav1.GroupVersionKind{ + Group: "eventing.knative.dev", + Version: "v1alpha1", + Kind: "EventPolicy", + } ) func createReplyChannel(channelName string) *duckv1.Destination { @@ -150,6 +165,7 @@ func TestAllCases(t *testing.T) { }, Spec: &runtime.RawExtension{Raw: []byte("{}")}, } + differentIMC := &messagingv1.ChannelTemplateSpec{ TypeMeta: metav1.TypeMeta{ APIVersion: "messaging.knative.dev/v1", @@ -157,6 +173,7 @@ func TestAllCases(t *testing.T) { }, Spec: &runtime.RawExtension{Raw: []byte("{}")}, } + table := TableTest{{ Name: "bad workqueue key", // Make sure Reconcile handles bad keys. @@ -1561,6 +1578,1990 @@ func TestAllCases(t *testing.T) { ), }}, }, + + { + Name: "threestep with AuthZ enabled, and sequence doesn't have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}}))}, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + createChannel(sequenceName, 2), + resources.NewSubscription(0, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}}))), + resources.NewSubscription(1, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, {Destination: createDestination(1)}, {Destination: createDestination(2)}}))), + resources.NewSubscription(2, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, {Destination: createDestination(1)}, {Destination: createDestination(2)}}))), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 2), 2), + // make the eventpolicy for the sequence + + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceStatusObservedGeneration(sequenceGeneration), + WithSequenceEventPoliciesReady(), + WithSequenceEventPoliciesListed(), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}}), + + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesReadyBecauseNoPolicyAndOIDCEnabled(), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + + { + Name: "threestep with AuthZ enabled, and sequence has event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}})), + makeSequenceEventPolicy(sequenceName), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + createChannel(sequenceName, 2), + resources.NewSubscription(0, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}}))), + resources.NewSubscription(1, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, {Destination: createDestination(1)}, {Destination: createDestination(2)}}))), + resources.NewSubscription(2, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, {Destination: createDestination(1)}, {Destination: createDestination(2)}}))), + + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 2), 2), + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceStatusObservedGeneration(sequenceGeneration), + WithSequenceEventPoliciesReady(), + WithSequenceEventPoliciesListed(), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}}), + + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", "event policies test-sequence are not ready"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + + { + Name: "2 steps with AuthZ enabled, and sequence doesn't have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}))}, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}))), + resources.NewSubscription(1, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, {Destination: createDestination(1)}}))), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + // make the eventpolicy for the sequence + + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceStatusObservedGeneration(sequenceGeneration), + WithSequenceEventPoliciesReady(), + WithSequenceEventPoliciesListed(), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}), + + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesReadyBecauseNoPolicyAndOIDCEnabled(), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "2 steps with AuthZ enabled, and sequence has event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}})), + makeSequenceEventPolicy(sequenceName), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}))), + resources.NewSubscription(1, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, {Destination: createDestination(1)}}))), + + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + + // make the eventpolicy for the sequence + + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceStatusObservedGeneration(sequenceGeneration), + WithSequenceEventPoliciesReady(), + WithSequenceEventPoliciesListed(), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}), + + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", "event policies test-sequence are not ready"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + + { + Name: "1 steps with AuthZ enabled, and sequence doesn't have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}))}, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 0), + resources.NewSubscription(0, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}))), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceStatusObservedGeneration(sequenceGeneration), + WithSequenceEventPoliciesReady(), + WithSequenceEventPoliciesListed(), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}), + + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesReadyBecauseNoPolicyAndOIDCEnabled(), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "1 steps with AuthZ enabled, and sequence has event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}})), + makeSequenceEventPolicy(sequenceName), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 0), + resources.NewSubscription(0, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}))), + + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceGeneration(sequenceGeneration), + WithSequenceStatusObservedGeneration(sequenceGeneration), + WithSequenceEventPoliciesReady(), + WithSequenceEventPoliciesListed(), + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}), + + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", "event policies test-sequence are not ready"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequenceupdate-remove-step with 3 steps with AuthZ enabled, and sequence doesn't have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}})), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + createChannel(sequenceName, 2), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + resources.NewSubscription(2, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + // Making the event policy for the sequence: + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 2), 2), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantDeletes: []clientgotesting.DeleteActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Name: resources.SequenceChannelName(sequenceName, 2), + }, { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("inmemorychannels"), + }, + Name: resources.SequenceChannelName(sequenceName, 2), + }, + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Name: resources.SequenceEventPolicyName(sequenceName, resources.SequenceChannelName(sequenceName, 2)), + }, + }, + WantUpdates: []clientgotesting.UpdateActionImpl{{ + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Object: resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}, + ))), + }}, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesReadyBecauseNoPolicyAndOIDCEnabled(), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequenceupdate-remove-step with 2 steps with AuthZ enabled, and sequence doesn't have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + })), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + // Making the event policy for the sequence: + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantDeletes: []clientgotesting.DeleteActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Name: resources.SequenceChannelName(sequenceName, 1), + }, { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("inmemorychannels"), + }, + Name: resources.SequenceChannelName(sequenceName, 1), + }, + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Name: resources.SequenceEventPolicyName(sequenceName, resources.SequenceChannelName(sequenceName, 1)), + }, + }, + WantUpdates: []clientgotesting.UpdateActionImpl{{ + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Object: resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}, + ))), + }}, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesReadyBecauseNoPolicyAndOIDCEnabled(), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequenceupdate-remove-step with 1 steps with AuthZ enabled, and sequence doesn't have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{})), + createChannel(sequenceName, 0), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + }))), + }, + WantErr: true, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantEvents: []string{ + Eventf(corev1.EventTypeWarning, "UpdateFailed", "Failed to update status for \"test-sequence\": missing field(s): spec.steps"), + }, + + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{}), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{}), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{})), + }}, + }, + { + Name: "sequenceupdate-remove-step with 3 steps with AuthZ enabled, and sequence does have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}})), + makeSequenceEventPolicy(sequenceName), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + createChannel(sequenceName, 2), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + resources.NewSubscription(2, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + // Making the event policy for the sequence: + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 2), 2), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantDeletes: []clientgotesting.DeleteActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Name: resources.SequenceChannelName(sequenceName, 2), + }, { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("inmemorychannels"), + }, + Name: resources.SequenceChannelName(sequenceName, 2), + }, + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Name: resources.SequenceEventPolicyName(sequenceName, resources.SequenceChannelName(sequenceName, 2)), + }, + }, + WantUpdates: []clientgotesting.UpdateActionImpl{{ + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Object: resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}, + ))), + }}, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}}), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", "event policies test-sequence are not ready"), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequenceupdate-remove-step with 2 steps with AuthZ enabled, and sequence does have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + })), + makeSequenceEventPolicy(sequenceName), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + // Making the event policy for the sequence: + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantDeletes: []clientgotesting.DeleteActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Name: resources.SequenceChannelName(sequenceName, 1), + }, { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("inmemorychannels"), + }, + Name: resources.SequenceChannelName(sequenceName, 1), + }, + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Name: resources.SequenceEventPolicyName(sequenceName, resources.SequenceChannelName(sequenceName, 1)), + }, + }, + WantUpdates: []clientgotesting.UpdateActionImpl{{ + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Object: resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}, + ))), + }}, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}}), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", "event policies test-sequence are not ready"), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequenceupdate-remove-step with 1 steps with AuthZ enabled, and sequence does have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{})), + makeSequenceEventPolicy(sequenceName), + createChannel(sequenceName, 0), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + }))), + }, + WantErr: true, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantEvents: []string{ + Eventf(corev1.EventTypeWarning, "UpdateFailed", "Failed to update status for \"test-sequence\": missing field(s): spec.steps"), + }, + + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{}), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{}), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{})), + }}, + }, + { + Name: "sequenceupdate-add-step with 2 steps (3 in total) with AuthZ enabled, and sequence doesn't have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + })), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 2), + resources.NewSubscription(2, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 2), 2), + }, + WantUpdates: []clientgotesting.UpdateActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Object: resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesReadyBecauseNoPolicyAndOIDCEnabled(), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequenceupdate-add-step with 2 steps (3 in total) with AuthZ enabled, and sequence does have event policy", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + })), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + makeSequenceEventPolicy(sequenceName), + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + createChannel(sequenceName, 2), + resources.NewSubscription(2, + NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 2), 2), + }, + WantUpdates: []clientgotesting.UpdateActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("subscriptions"), + }, + Object: resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }))), + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + {Destination: createDestination(2)}, + }), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", fmt.Sprintf("event policies %s are not ready", sequenceName)), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 2), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequence eventpolicy deleted", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + })), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantDeletes: []clientgotesting.DeleteActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: v1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Name: resources.SequenceEventPolicyName(sequenceName, resources.SequenceEventPolicyName(sequenceName, "")), + }, + }, + + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesReadyBecauseNoPolicyAndOIDCEnabled(), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequence with multiple eventpolicies", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + })), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + makeSequenceEventPolicy(sequenceName), + makeSequenceEventPolicy(sequenceName + "-additional-1"), + makeSequenceEventPolicy(sequenceName + "-additional-2"), + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantCreates: []runtime.Object{ + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName+"-additional-1", "")), + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName+"-additional-2", "")), + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", fmt.Sprintf("event policies %s, %s, %s are not ready", sequenceName, sequenceName+"-additional-1", sequenceName+"-additional-2")), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, + { + Name: "sequence with existing intermediate eventpolicies requiring update and cleanup", + Key: pKey, + Objects: []runtime.Object{ + NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + })), + createChannel(sequenceName, 0), + createChannel(sequenceName, 1), + resources.NewSubscription(0, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + resources.NewSubscription(1, NewSequence(sequenceName, testNS, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }))), + makeSequenceEventPolicy(sequenceName), + makeSequenceEventPolicy(sequenceName + "-additional"), + // Existing intermediate policy for input channel (needs update) + makeInputChannelEventPolicyWithWrongSpec(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + // Existing intermediate policy for step 0 (correct, no update needed) + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), 0), + // Existing intermediate policy for step 1 (needs to be deleted) + makeEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 1), 1), + // Obsolete policy that should be deleted + makeObsoleteEventPolicy(sequenceName), + }, + WantErr: false, + Ctx: feature.ToContext(context.Background(), feature.Flags{ + feature.OIDCAuthentication: feature.Enabled, + feature.AuthorizationDefaultMode: feature.AuthorizationAllowSameNamespace, + }), + WantUpdates: []clientgotesting.UpdateActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: eventingv1alpha1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Object: makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName, "")), + }, + }, + WantCreates: []runtime.Object{ + makeInputChannelEventPolicy(sequenceName, resources.SequenceChannelName(sequenceName, 0), resources.SequenceEventPolicyName(sequenceName+"-additional", "")), + }, + WantDeletes: []clientgotesting.DeleteActionImpl{ + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: eventingv1alpha1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Name: resources.SequenceEventPolicyName(sequenceName, resources.SequenceChannelName(sequenceName, 0)), + }, + { + ActionImpl: clientgotesting.ActionImpl{ + Namespace: testNS, + Resource: eventingv1alpha1.SchemeGroupVersion.WithResource("eventpolicies"), + }, + Name: resources.SequenceEventPolicyName(sequenceName, "obsolete"), + }, + }, + WantStatusUpdates: []clientgotesting.UpdateActionImpl{{ + Object: NewSequence(sequenceName, testNS, + WithInitSequenceConditions, + WithSequenceChannelTemplateSpec(imc), + WithSequenceSteps([]v1.SequenceStep{ + {Destination: createDestination(0)}, + {Destination: createDestination(1)}, + }), + WithSequenceChannelsNotReady("ChannelsNotReady", "Channels are not ready yet, or there are none"), + WithSequenceAddressableNotReady("emptyAddress", "addressable is nil"), + WithSequenceSubscriptionsNotReady("SubscriptionsNotReady", "Subscriptions are not ready yet, or there are none"), + WithSequenceEventPoliciesNotReady("EventPoliciesNotReady", fmt.Sprintf("event policies %s, %s are not ready", sequenceName, sequenceName+"-additional")), + WithSequenceChannelStatuses([]v1.SequenceChannelStatus{ + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + { + Channel: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "InMemoryChannel", + Name: resources.SequenceChannelName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Channel does not have Ready condition", + }, + }, + }), + WithSequenceSubscriptionStatuses([]v1.SequenceSubscriptionStatus{ + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 0), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + { + Subscription: corev1.ObjectReference{ + APIVersion: "messaging.knative.dev/v1", + Kind: "Subscription", + Name: resources.SequenceSubscriptionName(sequenceName, 1), + Namespace: testNS, + }, + ReadyCondition: apis.Condition{ + Type: apis.ConditionReady, + Status: corev1.ConditionUnknown, + Reason: "NoReady", + Message: "Subscription does not have Ready condition", + }, + }, + })), + }}, + }, } logger := logtesting.TestLogger(t) @@ -1579,3 +3580,89 @@ func TestAllCases(t *testing.T) { controller.GetEventRecorder(ctx), r) }, false, logger)) } + +func makeEventPolicy(sequenceName, channelName string, step int) *eventingv1alpha1.EventPolicy { + return NewEventPolicy(resources.SequenceEventPolicyName(sequenceName, channelName), testNS, + WithEventPolicyToRef(channelV1GVK, channelName), + // from a subscription + WithEventPolicyFrom(subscriberGVK, resources.SequenceSubscriptionName(sequenceName, step-1), testNS), + WithEventPolicyOwnerReferences([]metav1.OwnerReference{ + { + APIVersion: "flows.knative.dev/v1", + Kind: "Sequence", + Name: sequenceName, + }, + }...), + WithEventPolicyLabels(resources.LabelsForSequenceChannelsEventPolicy(sequenceName)), + ) +} + +// Write a function to make the event policy for the sequence +func makeSequenceEventPolicy(sequenceName string) *eventingv1alpha1.EventPolicy { + return NewEventPolicy(resources.SequenceEventPolicyName(sequenceName, ""), testNS, + // from a subscription + WithEventPolicyOwnerReferences([]metav1.OwnerReference{ + { + APIVersion: "flows.knative.dev/v1", + Kind: "Sequence", + Name: sequenceName, + }, + }...), + ) +} + +func makeInputChannelEventPolicy(sequenceName, channelName string, sequenceEventPolicyName string) *eventingv1alpha1.EventPolicy { + return NewEventPolicy(resources.SequenceEventPolicyName(sequenceName, sequenceEventPolicyName), testNS, + WithEventPolicyToRef(channelV1GVK, channelName), + // from a subscription + WithEventPolicyOwnerReferences([]metav1.OwnerReference{ + { + APIVersion: apiVersion(eventPolicyV1Alpha1GVK), + Kind: eventPolicyV1Alpha1GVK.Kind, + Name: sequenceEventPolicyName, + }, + }...), + WithEventPolicyLabels(resources.LabelsForSequenceChannelsEventPolicy(sequenceName)), + ) +} + +func makeInputChannelEventPolicyWithWrongSpec(sequenceName, channelName, policyName string) *eventingv1alpha1.EventPolicy { + policy := makeInputChannelEventPolicy(sequenceName, channelName, policyName) + // Modify the policy to have an incorrect specification + policy.Spec.From = []eventingv1alpha1.EventPolicySpecFrom{ + { + Ref: &eventingv1alpha1.EventPolicyFromReference{ + APIVersion: apiVersion(subscriberGVK), + Kind: subscriberGVK.Kind, + Name: "wrong-subscription", + Namespace: testNS, + }, + }, + } + + policy.Spec.To = []eventingv1alpha1.EventPolicySpecTo{ + { + Ref: &eventingv1alpha1.EventPolicyToReference{ + APIVersion: apiVersion(channelV1GVK), + Kind: channelV1GVK.Kind, + Name: "wrong-channel", + }, + }, + } + + return policy +} + +func makeObsoleteEventPolicy(sequenceName string) *eventingv1alpha1.EventPolicy { + return NewEventPolicy(resources.SequenceEventPolicyName(sequenceName, "obsolete"), testNS, + WithEventPolicyToRef(channelV1GVK, "obsolete-channel"), + WithEventPolicyOwnerReferences([]metav1.OwnerReference{ + { + APIVersion: apiVersion(sequenceGVK), + Kind: sequenceGVK.Kind, + Name: sequenceName, + }, + }...), + WithEventPolicyLabels(resources.LabelsForSequenceChannelsEventPolicy(sequenceName)), + ) +}