From 43f4be1cfe206c59abca98d11b5c558617d03bcf Mon Sep 17 00:00:00 2001 From: Chi Zhang Date: Wed, 29 May 2019 22:38:10 -0700 Subject: [PATCH 1/2] add test case for cronjobsource serviceaccount is not required for cronjobsource fix minor commment error make the comment clearer --- test/base/generics.go | 14 +++- test/base/resources.go | 112 +++++++++++++++++++++---------- test/common/creation.go | 38 ++++++++--- test/common/operation.go | 40 +++++++++-- test/common/validation.go | 4 +- test/e2e/source_cron_job_test.go | 59 ++++++++++++++++ 6 files changed, 213 insertions(+), 54 deletions(-) create mode 100644 test/e2e/source_cron_job_test.go diff --git a/test/base/generics.go b/test/base/generics.go index ede044bf141..93fe161fc4d 100644 --- a/test/base/generics.go +++ b/test/base/generics.go @@ -31,8 +31,18 @@ type MetaResource struct { metav1.ObjectMeta `json:"metadata,omitempty"` } +// MetaEventing returns a MetaResource that can represent a Knative Eventing resource. +func MetaEventing(name, namespace, kind string) *MetaResource { + return Meta(name, namespace, kind, eventingAPIVersion) +} + +// MetaSource returns a MetaResource that can represent a Knative Sources resource. +func MetaSource(name, namespace, kind string) *MetaResource { + return Meta(name, namespace, kind, sourcesAPIVersion) +} + // Meta returns a MetaResource built from the given name, namespace and kind. -func Meta(name, namespace, kind string) *MetaResource { +func Meta(name, namespace, kind, apiVersion string) *MetaResource { return &MetaResource{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, @@ -40,7 +50,7 @@ func Meta(name, namespace, kind string) *MetaResource { }, TypeMeta: metav1.TypeMeta{ Kind: kind, - APIVersion: EventingAPIVersion, + APIVersion: apiVersion, }, } } diff --git a/test/base/resources.go b/test/base/resources.go index 5732d7b0cad..88591a805b4 100644 --- a/test/base/resources.go +++ b/test/base/resources.go @@ -21,7 +21,8 @@ package base import ( "fmt" - "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + eventingv1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + sourcesv1alpha1 "github.com/knative/eventing/pkg/apis/sources/v1alpha1" pkgTest "github.com/knative/pkg/test" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -30,38 +31,39 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" ) -const EventingAPIVersion = "eventing.knative.dev/v1alpha1" +const eventingAPIVersion = "eventing.knative.dev/v1alpha1" +const sourcesAPIVersion = "sources.eventing.knative.dev/v1alpha1" // clusterChannelProvisioner returns a ClusterChannelProvisioner for a given name. func clusterChannelProvisioner(name string) *corev1.ObjectReference { if name == "" { return nil } - return pkgTest.CoreV1ObjectReference("ClusterChannelProvisioner", EventingAPIVersion, name) + return pkgTest.CoreV1ObjectReference("ClusterChannelProvisioner", eventingAPIVersion, name) } // channelRef returns an ObjectReference for a given Channel Name. func channelRef(name string) *corev1.ObjectReference { - return pkgTest.CoreV1ObjectReference("Channel", EventingAPIVersion, name) + return pkgTest.CoreV1ObjectReference("Channel", eventingAPIVersion, name) } // Channel returns a Channel with the specified provisioner. -func Channel(name, provisioner string) *v1alpha1.Channel { - return &v1alpha1.Channel{ +func Channel(name, provisioner string) *eventingv1alpha1.Channel { + return &eventingv1alpha1.Channel{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, - Spec: v1alpha1.ChannelSpec{ + Spec: eventingv1alpha1.ChannelSpec{ Provisioner: clusterChannelProvisioner(provisioner), }, } } // WithSubscriberForSubscription returns an option that adds a Subscriber for the given Subscription. -func WithSubscriberForSubscription(name string) func(*v1alpha1.Subscription) { - return func(s *v1alpha1.Subscription) { +func WithSubscriberForSubscription(name string) func(*eventingv1alpha1.Subscription) { + return func(s *eventingv1alpha1.Subscription) { if name != "" { - s.Spec.Subscriber = &v1alpha1.SubscriberSpec{ + s.Spec.Subscriber = &eventingv1alpha1.SubscriberSpec{ Ref: pkgTest.CoreV1ObjectReference("Service", "v1", name), } } @@ -69,23 +71,27 @@ func WithSubscriberForSubscription(name string) func(*v1alpha1.Subscription) { } // WithReply returns an options that adds a ReplyStrategy for the given Subscription. -func WithReply(name string) func(*v1alpha1.Subscription) { - return func(s *v1alpha1.Subscription) { +func WithReply(name string) func(*eventingv1alpha1.Subscription) { + return func(s *eventingv1alpha1.Subscription) { if name != "" { - s.Spec.Reply = &v1alpha1.ReplyStrategy{ - Channel: pkgTest.CoreV1ObjectReference("Channel", EventingAPIVersion, name), + s.Spec.Reply = &eventingv1alpha1.ReplyStrategy{ + Channel: pkgTest.CoreV1ObjectReference("Channel", eventingAPIVersion, name), } } } } // Subscription returns a Subscription. -func Subscription(name, channelName string, options ...func(*v1alpha1.Subscription)) *v1alpha1.Subscription { - subscription := &v1alpha1.Subscription{ +func Subscription( + name, + channelName string, + options ...func(*eventingv1alpha1.Subscription), +) *eventingv1alpha1.Subscription { + subscription := &eventingv1alpha1.Subscription{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, - Spec: v1alpha1.SubscriptionSpec{ + Spec: eventingv1alpha1.SubscriptionSpec{ Channel: *channelRef(channelName), }, } @@ -96,13 +102,13 @@ func Subscription(name, channelName string, options ...func(*v1alpha1.Subscripti } // Broker returns a Broker. -func Broker(name, provisioner string) *v1alpha1.Broker { - return &v1alpha1.Broker{ +func Broker(name, provisioner string) *eventingv1alpha1.Broker { + return &eventingv1alpha1.Broker{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, - Spec: v1alpha1.BrokerSpec{ - ChannelTemplate: &v1alpha1.ChannelSpec{ + Spec: eventingv1alpha1.BrokerSpec{ + ChannelTemplate: &eventingv1alpha1.ChannelSpec{ Provisioner: clusterChannelProvisioner(provisioner), }, }, @@ -110,10 +116,10 @@ func Broker(name, provisioner string) *v1alpha1.Broker { } // WithTriggerFilter returns an option that adds a TriggerFilter for the given Trigger. -func WithTriggerFilter(eventSource, eventType string) func(*v1alpha1.Trigger) { - return func(t *v1alpha1.Trigger) { - triggerFilter := &v1alpha1.TriggerFilter{ - SourceAndType: &v1alpha1.TriggerFilterSourceAndType{ +func WithTriggerFilter(eventSource, eventType string) func(*eventingv1alpha1.Trigger) { + return func(t *eventingv1alpha1.Trigger) { + triggerFilter := &eventingv1alpha1.TriggerFilter{ + SourceAndType: &eventingv1alpha1.TriggerFilterSourceAndType{ Type: eventType, Source: eventSource, }, @@ -123,17 +129,17 @@ func WithTriggerFilter(eventSource, eventType string) func(*v1alpha1.Trigger) { } // WithBroker returns an option that adds a Broker for the given Trigger. -func WithBroker(brokerName string) func(*v1alpha1.Trigger) { - return func(t *v1alpha1.Trigger) { +func WithBroker(brokerName string) func(*eventingv1alpha1.Trigger) { + return func(t *eventingv1alpha1.Trigger) { t.Spec.Broker = brokerName } } // WithSubscriberRefForTrigger returns an option that adds a Subscriber Ref for the given Trigger. -func WithSubscriberRefForTrigger(name string) func(*v1alpha1.Trigger) { - return func(t *v1alpha1.Trigger) { +func WithSubscriberRefForTrigger(name string) func(*eventingv1alpha1.Trigger) { + return func(t *eventingv1alpha1.Trigger) { if name != "" { - t.Spec.Subscriber = &v1alpha1.SubscriberSpec{ + t.Spec.Subscriber = &eventingv1alpha1.SubscriberSpec{ Ref: pkgTest.CoreV1ObjectReference("Service", "v1", name), } } @@ -141,17 +147,17 @@ func WithSubscriberRefForTrigger(name string) func(*v1alpha1.Trigger) { } // WithSubscriberURIForTrigger returns an option that adds a Subscriber URI for the given Trigger. -func WithSubscriberURIForTrigger(uri string) func(*v1alpha1.Trigger) { - return func(t *v1alpha1.Trigger) { - t.Spec.Subscriber = &v1alpha1.SubscriberSpec{ +func WithSubscriberURIForTrigger(uri string) func(*eventingv1alpha1.Trigger) { + return func(t *eventingv1alpha1.Trigger) { + t.Spec.Subscriber = &eventingv1alpha1.SubscriberSpec{ URI: &uri, } } } // Trigger returns a Trigger. -func Trigger(name string, options ...func(*v1alpha1.Trigger)) *v1alpha1.Trigger { - trigger := &v1alpha1.Trigger{ +func Trigger(name string, options ...func(*eventingv1alpha1.Trigger)) *eventingv1alpha1.Trigger { + trigger := &eventingv1alpha1.Trigger{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, @@ -162,6 +168,42 @@ func Trigger(name string, options ...func(*v1alpha1.Trigger)) *v1alpha1.Trigger return trigger } +// WithSinkServiceForCronJobSource returns an option that adds a Kubernetes Service sink for the given CronJobSource. +func WithSinkServiceForCronJobSource(name string) func(*sourcesv1alpha1.CronJobSource) { + return func(cjs *sourcesv1alpha1.CronJobSource) { + cjs.Spec.Sink = pkgTest.CoreV1ObjectReference("Service", "v1", name) + } +} + +// WithServiceAccountForCronJobSource returns an option that adds a ServiceAccount for the given CronJobSource. +func WithServiceAccountForCronJobSource(saName string) func(*sourcesv1alpha1.CronJobSource) { + return func(cjs *sourcesv1alpha1.CronJobSource) { + cjs.Spec.ServiceAccountName = saName + } +} + +// CronJobSource returns a CronJob EventSource. +func CronJobSource( + name, + schedule, + data string, + options ...func(*sourcesv1alpha1.CronJobSource), +) *sourcesv1alpha1.CronJobSource { + cronJobSource := &sourcesv1alpha1.CronJobSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: sourcesv1alpha1.CronJobSourceSpec{ + Schedule: schedule, + Data: data, + }, + } + for _, option := range options { + option(cronJobSource) + } + return cronJobSource +} + // CloudEvent specifies the arguments for a CloudEvent sent by the sendevent // binary. type CloudEvent struct { diff --git a/test/common/creation.go b/test/common/creation.go index 4eca1a06dc5..5cbcdc4b260 100644 --- a/test/common/creation.go +++ b/test/common/creation.go @@ -17,7 +17,8 @@ limitations under the License. package common import ( - "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + eventingv1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + sourcesv1alpha1 "github.com/knative/eventing/pkg/apis/sources/v1alpha1" "github.com/knative/eventing/test/base" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -28,7 +29,7 @@ var coreAPIVersion = corev1.SchemeGroupVersion.Version var rbacAPIGroup = rbacv1.SchemeGroupVersion.Group var rbacAPIVersion = rbacv1.SchemeGroupVersion.Version -// CreateChannelOrFail will create a Channel Resource in Eventing. +// CreateChannelOrFail will create a Channel or fail the test if there is an error. func (client *Client) CreateChannelOrFail(name, provisonerName string) { namespace := client.Namespace channel := base.Channel(name, provisonerName) @@ -49,8 +50,8 @@ func (client *Client) CreateChannelsOrFail(names []string, provisionerName strin } } -// CreateSubscriptionOrFail will create a Subscription. -func (client *Client) CreateSubscriptionOrFail(name, channelName string, options ...func(*v1alpha1.Subscription)) { +// CreateSubscriptionOrFail will create a Subscription or fail the test if there is an error. +func (client *Client) CreateSubscriptionOrFail(name, channelName string, options ...func(*eventingv1alpha1.Subscription)) { namespace := client.Namespace subscription := base.Subscription(name, channelName, options...) @@ -64,13 +65,13 @@ func (client *Client) CreateSubscriptionOrFail(name, channelName string, options } // CreateSubscriptionsOrFail will create a list of Subscriptions with the same configuration except the name. -func (client *Client) CreateSubscriptionsOrFail(names []string, channelName string, options ...func(*v1alpha1.Subscription)) { +func (client *Client) CreateSubscriptionsOrFail(names []string, channelName string, options ...func(*eventingv1alpha1.Subscription)) { for _, name := range names { client.CreateSubscriptionOrFail(name, channelName, options...) } } -// CreateBrokerOrFail will create a Broker. +// CreateBrokerOrFail will create a Broker or fail the test if there is an error. func (client *Client) CreateBrokerOrFail(name, provisionerName string) { namespace := client.Namespace broker := base.Broker(name, provisionerName) @@ -91,8 +92,8 @@ func (client *Client) CreateBrokersOrFail(names []string, provisionerName string } } -// CreateTriggerOrFail will create a Trigger. -func (client *Client) CreateTriggerOrFail(name string, options ...func(*v1alpha1.Trigger)) { +// CreateTriggerOrFail will create a Trigger or fail the test if there is an error. +func (client *Client) CreateTriggerOrFail(name string, options ...func(*eventingv1alpha1.Trigger)) { namespace := client.Namespace trigger := base.Trigger(name, options...) @@ -105,6 +106,25 @@ func (client *Client) CreateTriggerOrFail(name string, options ...func(*v1alpha1 client.Cleaner.AddObj(trigger) } +// CreateCronJobSourceOrFail will create a CronJobSource or fail the test if there is an error. +func (client *Client) CreateCronJobSourceOrFail( + name, + schedule, + data string, + options ...func(*sourcesv1alpha1.CronJobSource), +) { + namespace := client.Namespace + cronJobSource := base.CronJobSource(name, schedule, data, options...) + + cronJobSources := client.Eventing.SourcesV1alpha1().CronJobSources(namespace) + // update cronJobSource with the new reference + cronJobSource, err := cronJobSources.Create(cronJobSource) + if err != nil { + client.T.Fatalf("Failed to create cronjobsource %q: %v", name, err) + } + client.Cleaner.AddObj(cronJobSource) +} + // WithService returns an option that creates a Service binded with the given pod. func WithService(name string) func(*corev1.Pod, *Client) error { return func(pod *corev1.Pod, client *Client) error { @@ -120,7 +140,7 @@ func WithService(name string) func(*corev1.Pod, *Client) error { } } -// CreatePodOrFail will create a Pod. +// CreatePodOrFail will create a Pod or fail the test if there is an error. func (client *Client) CreatePodOrFail(pod *corev1.Pod, options ...func(*corev1.Pod, *Client) error) { // set namespace for the pod in case it's empty namespace := client.Namespace diff --git a/test/common/operation.go b/test/common/operation.go index f8eb07a5bd1..7e8fe951080 100644 --- a/test/common/operation.go +++ b/test/common/operation.go @@ -53,7 +53,7 @@ func (client *Client) SendFakeEventToChannel(senderName, channelName string, eve // GetChannelURL will return the url for the given channel. func (client *Client) GetChannelURL(name string) (string, error) { namespace := client.Namespace - channelMeta := base.Meta(name, namespace, "Channel") + channelMeta := base.MetaEventing(name, namespace, "Channel") return base.GetAddressableURI(client.Dynamic, channelMeta) } @@ -69,7 +69,7 @@ func (client *Client) SendFakeEventToBroker(senderName, brokerName string, event // GetBrokerURL will return the url for the given broker. func (client *Client) GetBrokerURL(name string) (string, error) { namespace := client.Namespace - brokerMeta := base.Meta(name, namespace, "Broker") + brokerMeta := base.MetaEventing(name, namespace, "Broker") return base.GetAddressableURI(client.Dynamic, brokerMeta) } @@ -92,7 +92,7 @@ func (client *Client) sendFakeEventToAddress( // WaitForBrokerReady waits until the broker is Ready. func (client *Client) WaitForBrokerReady(name string) error { namespace := client.Namespace - brokerMeta := base.Meta(name, namespace, "Broker") + brokerMeta := base.MetaEventing(name, namespace, "Broker") if err := base.WaitForResourceReady(client.Dynamic, brokerMeta); err != nil { return err } @@ -117,7 +117,7 @@ func (client *Client) WaitForBrokersReady() error { // WaitForTriggerReady waits until the trigger is Ready. func (client *Client) WaitForTriggerReady(name string) error { namespace := client.Namespace - triggerMeta := base.Meta(name, namespace, "Trigger") + triggerMeta := base.MetaEventing(name, namespace, "Trigger") if err := base.WaitForResourceReady(client.Dynamic, triggerMeta); err != nil { return err } @@ -142,7 +142,7 @@ func (client *Client) WaitForTriggersReady() error { // WaitForChannelReady waits until the channel is Ready. func (client *Client) WaitForChannelReady(name string) error { namespace := client.Namespace - channelMeta := base.Meta(name, namespace, "Channel") + channelMeta := base.MetaEventing(name, namespace, "Channel") if err := base.WaitForResourceReady(client.Dynamic, channelMeta); err != nil { return err } @@ -167,7 +167,7 @@ func (client *Client) WaitForChannelsReady() error { // WaitForSubscriptionReady waits until the subscription is Ready. func (client *Client) WaitForSubscriptionReady(name string) error { namespace := client.Namespace - subscriptionMeta := base.Meta(name, namespace, "Subscription") + subscriptionMeta := base.MetaEventing(name, namespace, "Subscription") if err := base.WaitForResourceReady(client.Dynamic, subscriptionMeta); err != nil { return err } @@ -189,6 +189,31 @@ func (client *Client) WaitForSubscriptionsReady() error { return nil } +// WaitForCronJobSourceReady waits until the cronjobsource is Ready. +func (client *Client) WaitForCronJobSourceReady(name string) error { + namespace := client.Namespace + cronJobSourceMeta := base.MetaSource(name, namespace, "CronJobSource") + if err := base.WaitForResourceReady(client.Dynamic, cronJobSourceMeta); err != nil { + return err + } + return nil +} + +// WaitForCronJobSourcesReady waits until all cronjobsources in the namespace are Ready. +func (client *Client) WaitForCronJobSourcesReady() error { + namespace := client.Namespace + cronJobSources, err := client.Eventing.SourcesV1alpha1().CronJobSources(namespace).List(metav1.ListOptions{}) + if err != nil { + return err + } + for _, cronJobSource := range cronJobSources.Items { + if err := client.WaitForCronJobSourceReady(cronJobSource.Name); err != nil { + return err + } + } + return nil +} + // WaitForAllTestResourcesReady waits until all test resources in the namespace are Ready. // Currently the test resources include Pod, Channel, Subscription, Broker and Trigger. // If there are new resources, this function needs to be changed. @@ -205,6 +230,9 @@ func (client *Client) WaitForAllTestResourcesReady() error { if err := client.WaitForTriggersReady(); err != nil { return err } + if err := client.WaitForCronJobSourcesReady(); err != nil { + return err + } if err := pkgTest.WaitForAllPodsRunning(client.Kube, client.Namespace); err != nil { return err } diff --git a/test/common/validation.go b/test/common/validation.go index 4d2cbaca62c..b46a636973b 100644 --- a/test/common/validation.go +++ b/test/common/validation.go @@ -27,7 +27,7 @@ import ( const ( // The interval and timeout used for polling pod logs. interval = 1 * time.Second - timeout = 2 * time.Minute + timeout = 4 * time.Minute ) // CheckLog waits until logs for the logger Pod satisfy the checker. @@ -66,7 +66,7 @@ func CheckerContainsAll(contents []string) func(string) bool { } } -// CheckerContainsCount returns a checker functions to check if the log contains the count number of given content. +// CheckerContainsCount returns a checker function to check if the log contains the count number of given content. func CheckerContainsCount(content string, count int) func(string) bool { return func(log string) bool { return strings.Count(log, content) == count diff --git a/test/e2e/source_cron_job_test.go b/test/e2e/source_cron_job_test.go new file mode 100644 index 00000000000..70936a93fa8 --- /dev/null +++ b/test/e2e/source_cron_job_test.go @@ -0,0 +1,59 @@ +// +build e2e + +/* +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 e2e + +import ( + "fmt" + "testing" + + "github.com/knative/eventing/test/base" + "github.com/knative/eventing/test/common" + "k8s.io/apimachinery/pkg/util/uuid" +) + +func TestCronJobSource(t *testing.T) { + const ( + cronJobSourceName = "e2e-cron-job-source" + // Every 1 minute starting from now + schedule = "*/1 * * * *" + + loggerPodName = "e2e-cron-job-source-logger-pod" + ) + + client := Setup(t, true) + defer TearDown(client) + + // create event logger pod and service + loggerPod := base.EventLoggerPod(loggerPodName) + client.CreatePodOrFail(loggerPod, common.WithService(loggerPodName)) + + // create cron job source + data := fmt.Sprintf("TestCronJobSource %s", uuid.NewUUID()) + sinkOption := base.WithSinkServiceForCronJobSource(loggerPodName) + client.CreateCronJobSourceOrFail(cronJobSourceName, schedule, data, sinkOption) + + // wait for all test resources to be ready + if err := client.WaitForAllTestResourcesReady(); err != nil { + t.Fatalf("Failed to get all test resources ready: %v", err) + } + + // verify the logger service receives the event + if err := client.CheckLog(loggerPodName, common.CheckerContains(data)); err != nil { + t.Fatalf("String %q not found in logs of logger pod %q: %v", data, loggerPodName, err) + } +} From f7108a70de7abe42fff4af6e493070bb5d2c2528 Mon Sep 17 00:00:00 2001 From: Chi Zhang Date: Tue, 4 Jun 2019 10:04:57 -0700 Subject: [PATCH 2/2] format a couple of long lines --- test/common/creation.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/common/creation.go b/test/common/creation.go index 5cbcdc4b260..ea8bfed5c3c 100644 --- a/test/common/creation.go +++ b/test/common/creation.go @@ -51,7 +51,11 @@ func (client *Client) CreateChannelsOrFail(names []string, provisionerName strin } // CreateSubscriptionOrFail will create a Subscription or fail the test if there is an error. -func (client *Client) CreateSubscriptionOrFail(name, channelName string, options ...func(*eventingv1alpha1.Subscription)) { +func (client *Client) CreateSubscriptionOrFail( + name, + channelName string, + options ...func(*eventingv1alpha1.Subscription), +) { namespace := client.Namespace subscription := base.Subscription(name, channelName, options...) @@ -65,7 +69,11 @@ func (client *Client) CreateSubscriptionOrFail(name, channelName string, options } // CreateSubscriptionsOrFail will create a list of Subscriptions with the same configuration except the name. -func (client *Client) CreateSubscriptionsOrFail(names []string, channelName string, options ...func(*eventingv1alpha1.Subscription)) { +func (client *Client) CreateSubscriptionsOrFail( + names []string, + channelName string, + options ...func(*eventingv1alpha1.Subscription), +) { for _, name := range names { client.CreateSubscriptionOrFail(name, channelName, options...) }