diff --git a/pkg/apis/messaging/v1alpha1/sequence_defaults.go b/pkg/apis/messaging/v1alpha1/sequence_defaults.go index 79c0cbe4f4a..a33cfde938e 100644 --- a/pkg/apis/messaging/v1alpha1/sequence_defaults.go +++ b/pkg/apis/messaging/v1alpha1/sequence_defaults.go @@ -16,12 +16,21 @@ limitations under the License. package v1alpha1 -import "context" +import ( + "context" + eventingduckv1alpha1 "github.com/knative/eventing/pkg/apis/duck/v1alpha1" +) func (s *Sequence) SetDefaults(ctx context.Context) { + if s != nil && s.Spec.ChannelTemplate == nil { + // The singleton may not have been set, if so ignore it and validation will reject the + // Channel. + if cd := eventingduckv1alpha1.ChannelDefaulterSingleton; cd != nil { + channelTemplate := cd.GetDefault(s.Namespace) + s.Spec.ChannelTemplate = channelTemplate + } + } s.Spec.SetDefaults(ctx) } -func (ss *SequenceSpec) SetDefaults(ctx context.Context) { - // TODO anything? -} +func (ss *SequenceSpec) SetDefaults(ctx context.Context) {} diff --git a/pkg/apis/messaging/v1alpha1/sequence_defaults_test.go b/pkg/apis/messaging/v1alpha1/sequence_defaults_test.go new file mode 100644 index 00000000000..1eb820252e3 --- /dev/null +++ b/pkg/apis/messaging/v1alpha1/sequence_defaults_test.go @@ -0,0 +1,105 @@ +/* +Copyright 2019 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 v1alpha1 + +import ( + "context" + "k8s.io/apimachinery/pkg/apis/meta/v1" + "testing" + + "github.com/google/go-cmp/cmp" + eventingduckv1alpha1 "github.com/knative/eventing/pkg/apis/duck/v1alpha1" +) + +var ( + defaultTemplate = &eventingduckv1alpha1.ChannelTemplateSpec{ + TypeMeta: v1.TypeMeta{ + APIVersion: SchemeGroupVersion.String(), + Kind: "InMemoryChannel", + }, + } +) + +func TestSequenceSetDefaults(t *testing.T) { + testCases := map[string]struct { + nilChannelDefaulter bool + channelTemplate *eventingduckv1alpha1.ChannelTemplateSpec + initial Sequence + expected Sequence + }{ + "nil ChannelDefaulter": { + nilChannelDefaulter: true, + expected: Sequence{}, + }, + "unset ChannelDefaulter": { + expected: Sequence{}, + }, + "set ChannelDefaulter": { + channelTemplate: defaultChannelTemplate, + expected: Sequence{ + Spec: SequenceSpec{ + ChannelTemplate: defaultChannelTemplate, + }, + }, + }, + "template already specified": { + channelTemplate: defaultChannelTemplate, + initial: Sequence{ + Spec: SequenceSpec{ + ChannelTemplate: &eventingduckv1alpha1.ChannelTemplateSpec{ + TypeMeta: v1.TypeMeta{ + APIVersion: SchemeGroupVersion.String(), + Kind: "OtherChannel", + }, + }, + }, + }, + expected: Sequence{ + Spec: SequenceSpec{ + ChannelTemplate: &eventingduckv1alpha1.ChannelTemplateSpec{ + TypeMeta: v1.TypeMeta{ + APIVersion: SchemeGroupVersion.String(), + Kind: "OtherChannel", + }, + }, + }, + }, + }, + } + for n, tc := range testCases { + t.Run(n, func(t *testing.T) { + if !tc.nilChannelDefaulter { + eventingduckv1alpha1.ChannelDefaulterSingleton = &sequenceChannelDefaulter{ + channelTemplate: tc.channelTemplate, + } + defer func() { eventingduckv1alpha1.ChannelDefaulterSingleton = nil }() + } + tc.initial.SetDefaults(context.TODO()) + if diff := cmp.Diff(tc.expected, tc.initial); diff != "" { + t.Fatalf("Unexpected defaults (-want, +got): %s", diff) + } + }) + } +} + +type sequenceChannelDefaulter struct { + channelTemplate *eventingduckv1alpha1.ChannelTemplateSpec +} + +func (cd *sequenceChannelDefaulter) GetDefault(_ string) *eventingduckv1alpha1.ChannelTemplateSpec { + return cd.channelTemplate +} diff --git a/pkg/apis/messaging/v1alpha1/sequence_types.go b/pkg/apis/messaging/v1alpha1/sequence_types.go index 6899e9d9a59..a0c193d91fa 100644 --- a/pkg/apis/messaging/v1alpha1/sequence_types.go +++ b/pkg/apis/messaging/v1alpha1/sequence_types.go @@ -61,8 +61,10 @@ type SequenceSpec struct { // provided. Steps []eventingv1alpha1.SubscriberSpec `json:"steps"` - // ChannelTemplate specifies which Channel CRD to use - ChannelTemplate eventingduckv1alpha1.ChannelTemplateSpec `json:"channelTemplate"` + // ChannelTemplate specifies which Channel CRD to use. If left unspecified, it is set to the default Channel CRD + // for the namespace (or cluster, in case there are no defaults for the namespace). + // +optional + ChannelTemplate *eventingduckv1alpha1.ChannelTemplateSpec `json:"channelTemplate,omitempty"` // Reply is a Reference to where the result of the last Subscriber gets sent to. // diff --git a/pkg/apis/messaging/v1alpha1/sequence_validation.go b/pkg/apis/messaging/v1alpha1/sequence_validation.go index 80095758113..a260300996f 100644 --- a/pkg/apis/messaging/v1alpha1/sequence_validation.go +++ b/pkg/apis/messaging/v1alpha1/sequence_validation.go @@ -18,9 +18,7 @@ package v1alpha1 import ( "context" - eventingduck "github.com/knative/eventing/pkg/apis/duck/v1alpha1" eventingv1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" - "k8s.io/apimachinery/pkg/api/equality" "knative.dev/pkg/apis" ) @@ -41,7 +39,7 @@ func (ps *SequenceSpec) Validate(ctx context.Context) *apis.FieldError { } } - if equality.Semantic.DeepEqual(ps.ChannelTemplate, eventingduck.ChannelTemplateSpec{}) { + if ps.ChannelTemplate == nil { errs = errs.Also(apis.ErrMissingField("channelTemplate")) return errs } diff --git a/pkg/apis/messaging/v1alpha1/sequence_validation_test.go b/pkg/apis/messaging/v1alpha1/sequence_validation_test.go index 49fb630710e..f624f4bc0ef 100644 --- a/pkg/apis/messaging/v1alpha1/sequence_validation_test.go +++ b/pkg/apis/messaging/v1alpha1/sequence_validation_test.go @@ -65,7 +65,7 @@ func makeInvalidReply(channelName string) *corev1.ObjectReference { func TestSequenceSpecValidation(t *testing.T) { subscriberURI := "http://example.com" - validChannelTemplate := eventingduck.ChannelTemplateSpec{ + validChannelTemplate := &eventingduck.ChannelTemplateSpec{ TypeMeta: metav1.TypeMeta{ Kind: "mykind", APIVersion: "myapiversion", @@ -104,7 +104,7 @@ func TestSequenceSpecValidation(t *testing.T) { }, { name: "invalid channeltemplatespec missing APIVersion", ts: &SequenceSpec{ - ChannelTemplate: eventingduck.ChannelTemplateSpec{TypeMeta: metav1.TypeMeta{Kind: "mykind"}, Spec: &runtime.RawExtension{}}, + ChannelTemplate: &eventingduck.ChannelTemplateSpec{TypeMeta: metav1.TypeMeta{Kind: "mykind"}, Spec: &runtime.RawExtension{}}, Steps: []eventingv1alpha1.SubscriberSpec{{URI: &subscriberURI}}, }, want: func() *apis.FieldError { @@ -114,7 +114,7 @@ func TestSequenceSpecValidation(t *testing.T) { }, { name: "invalid channeltemplatespec missing Kind", ts: &SequenceSpec{ - ChannelTemplate: eventingduck.ChannelTemplateSpec{TypeMeta: metav1.TypeMeta{APIVersion: "myapiversion"}, Spec: &runtime.RawExtension{}}, + ChannelTemplate: &eventingduck.ChannelTemplateSpec{TypeMeta: metav1.TypeMeta{APIVersion: "myapiversion"}, Spec: &runtime.RawExtension{}}, Steps: []eventingv1alpha1.SubscriberSpec{{URI: &subscriberURI}}, }, want: func() *apis.FieldError { diff --git a/pkg/apis/messaging/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/messaging/v1alpha1/zz_generated.deepcopy.go index 876ea568f7c..5b9d0c92e26 100644 --- a/pkg/apis/messaging/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/messaging/v1alpha1/zz_generated.deepcopy.go @@ -328,7 +328,11 @@ func (in *SequenceSpec) DeepCopyInto(out *SequenceSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - in.ChannelTemplate.DeepCopyInto(&out.ChannelTemplate) + if in.ChannelTemplate != nil { + in, out := &in.ChannelTemplate, &out.ChannelTemplate + *out = new(duckv1alpha1.ChannelTemplateSpec) + (*in).DeepCopyInto(*out) + } if in.Reply != nil { in, out := &in.Reply, &out.Reply *out = new(v1.ObjectReference) diff --git a/pkg/reconciler/sequence/sequence_test.go b/pkg/reconciler/sequence/sequence_test.go index a6790872f89..62c7a223bb6 100644 --- a/pkg/reconciler/sequence/sequence_test.go +++ b/pkg/reconciler/sequence/sequence_test.go @@ -106,7 +106,7 @@ func createSubscriber(stepNumber int) eventingv1alpha1.SubscriberSpec { func TestAllCases(t *testing.T) { pKey := testNS + "/" + sequenceName - imc := eventingduckv1alpha1.ChannelTemplateSpec{ + imc := &eventingduckv1alpha1.ChannelTemplateSpec{ TypeMeta: metav1.TypeMeta{ APIVersion: "messaging.knative.dev/v1alpha1", Kind: "inmemorychannel", diff --git a/pkg/reconciler/testing/sequence.go b/pkg/reconciler/testing/sequence.go index b8efa0f3aef..b9c33334a01 100644 --- a/pkg/reconciler/testing/sequence.go +++ b/pkg/reconciler/testing/sequence.go @@ -55,7 +55,7 @@ func WithSequenceDeleted(p *v1alpha1.Sequence) { p.ObjectMeta.SetDeletionTimestamp(&deleteTime) } -func WithSequenceChannelTemplateSpec(cts eventingduckv1alpha1.ChannelTemplateSpec) SequenceOption { +func WithSequenceChannelTemplateSpec(cts *eventingduckv1alpha1.ChannelTemplateSpec) SequenceOption { return func(p *v1alpha1.Sequence) { p.Spec.ChannelTemplate = cts } diff --git a/test/base/resources/messaging.go b/test/base/resources/messaging.go index 2f8dfaa87d5..d48ae948637 100644 --- a/test/base/resources/messaging.go +++ b/test/base/resources/messaging.go @@ -71,7 +71,7 @@ func WithReplyForSequence(name string, typemeta *metav1.TypeMeta) SequenceOption func Sequence( name string, steps []eventingv1alpha1.SubscriberSpec, - channelTemplate eventingduckv1alpha1.ChannelTemplateSpec, + channelTemplate *eventingduckv1alpha1.ChannelTemplateSpec, options ...SequenceOption, ) *messagingv1alpha1.Sequence { sequence := &messagingv1alpha1.Sequence{ diff --git a/test/common/creation.go b/test/common/creation.go index b7080b97dd6..85799ad9e34 100644 --- a/test/common/creation.go +++ b/test/common/creation.go @@ -153,7 +153,7 @@ func (client *Client) CreateTriggerOrFail(name string, options ...resources.Trig func (client *Client) CreateSequenceOrFail( name string, steps []eventingv1alpha1.SubscriberSpec, - channelTemplate eventingduckv1alpha1.ChannelTemplateSpec, + channelTemplate *eventingduckv1alpha1.ChannelTemplateSpec, options ...resources.SequenceOption, ) { namespace := client.Namespace diff --git a/test/e2e/sequence_test.go b/test/e2e/sequence_test.go index c3bc4e5fc7c..d6ba5269ce4 100644 --- a/test/e2e/sequence_test.go +++ b/test/e2e/sequence_test.go @@ -74,7 +74,7 @@ func TestSequence(t *testing.T) { } // create channelTemplate for the Sequence - channelTemplate := eventingduckv1alpha1.ChannelTemplateSpec{ + channelTemplate := &eventingduckv1alpha1.ChannelTemplateSpec{ TypeMeta: *(channelTypeMeta), }