Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 32 additions & 33 deletions test/conformance/helpers/sources/source_status_test_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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
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,
Expand All @@ -18,23 +18,22 @@ package sources

import (
"fmt"
"github.com/pkg/errors"
"knative.dev/eventing/test/lib/duck"
"knative.dev/eventing/test/lib/resources"
"knative.dev/pkg/apis"
duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"
"strings"
"testing"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

testlib "knative.dev/eventing/test/lib"
"knative.dev/eventing/test/lib/duck"
"knative.dev/eventing/test/lib/resources"
"knative.dev/pkg/apis"
duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"
)

// SourceStatusTestHelperWithComponentsTestRunner runs the Source status
// conformance tests for all sources in the ComponentsTestRunner. This test
// needs an instance created of each source which should be initialized via
// ComponentsTestRunner.AddComponentSetupClientOption.
// needs an already created instance of each source which should be initialized
//via ComponentsTestRunner.AddComponentSetupClientOption.
//
// Note: The source object name must be the lower case Kind name (e.g.
// apiserversource for the Kind: ApiServerSource source)
Expand All @@ -43,24 +42,24 @@ func SourceStatusTestHelperWithComponentsTestRunner(
componentsTestRunner testlib.ComponentsTestRunner,
options ...testlib.SetupClientOption,
) {
table := [] struct {
table := []struct {
name string
feature testlib.Feature
// Sources report success via either a Ready condition or a Succeeded condition
want apis.ConditionType
} {
want apis.ConditionType
}{
{
"Long living sources have Ready status condition",
testlib.FeatureLongLiving,
apis.ConditionReady,
name: "Long living sources have Ready status condition",
feature: testlib.FeatureLongLiving,
want: apis.ConditionReady,
},
{
"Batch sources have Succeeded status condition",
testlib.FeatureBatch,
apis.ConditionSucceeded,
name: "Batch sources have Succeeded status condition",
feature: testlib.FeatureBatch,
want: apis.ConditionSucceeded,
},

}

for _, tc := range table {
n := tc.name
f := tc.feature
Expand All @@ -73,27 +72,26 @@ func SourceStatusTestHelperWithComponentsTestRunner(
options = append(options, componentOptions...)
client := testlib.Setup(st, true, options...)
defer testlib.TearDown(client)
validateSourceStatus(st, client, source, w, options...)
})
validateSourceStatus(st, client, source, w)
})
})
}
}

func validateSourceStatus(st *testing.T, client *testlib.Client, source metav1.TypeMeta, successCondition apis.ConditionType, options ...testlib.SetupClientOption) {
const(
sourceName = "source-req-status"
)
func validateSourceStatus(st *testing.T, client *testlib.Client,
source metav1.TypeMeta,
successCondition apis.ConditionType) {

st.Logf("Running source status conformance test with source %q", source)

v1beta1Src, err := getSourceAsV1Beta1Source(client, source)
if err != nil {
st.Fatalf("unable to get source %q with v1beta1 duck type: %v", source, err)
st.Fatalf("Unable to get source %q with v1beta1 duck type: %v", source, err)
}

// SPEC: Sources MUST implement conditions with a Ready condition for long lived sources, and Succeeded for batch style sources.
if ! hasCondition(v1beta1Src, successCondition){
st.Fatalf("%q does not have %q", source, successCondition)
if !hasCondition(v1beta1Src, successCondition) {
st.Fatalf("Source %q does not have condition %q", source, successCondition)
}

// SPEC: Sources MUST propagate the sinkUri to their status to signal to the cluster where their events are being sent.
Expand All @@ -103,25 +101,26 @@ func validateSourceStatus(st *testing.T, client *testlib.Client, source metav1.T
}

func getSourceAsV1Beta1Source(client *testlib.Client,
source metav1.TypeMeta) (*duckv1beta1.Source, error){
source metav1.TypeMeta) (*duckv1beta1.Source, error) {
srcName := strings.ToLower(fmt.Sprintf("%s", source.Kind))
metaResource := resources.NewMetaResource(srcName, client.Namespace,
&source)
obj, err := duck.GetGenericObject(client.Dynamic, metaResource,
&duckv1beta1.Source{})
if err != nil {
return nil, errors.Wrapf(err, "unable to get the source as v1beta1 Source duck type: %q", source)
return nil, fmt.Errorf("unable to get the source as v1beta1 "+
"Source duck type: %q: %w", source, err)
}
srcObj, ok := obj.(*duckv1beta1.Source)
if !ok {
return nil, errors.Errorf("unable to cast source %q to v1beta1 Source" +
" duck type", source)
return nil, fmt.Errorf("unable to cast source %q to v1beta1 "+
"Source duck type", source)
}
return srcObj, nil
}

func hasCondition(src *duckv1beta1.Source, t apis.ConditionType) bool{
if src.Status.GetCondition(t) == nil{
func hasCondition(src *duckv1beta1.Source, t apis.ConditionType) bool {
if src.Status.GetCondition(t) == nil {
return false
}
return true
Expand Down
21 changes: 14 additions & 7 deletions test/conformance/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ import (
"strings"
"testing"

"knative.dev/pkg/test/zipkin"

"knative.dev/eventing/test"
testlib "knative.dev/eventing/test/lib"
"knative.dev/eventing/test/lib/resources"
"knative.dev/eventing/test/lib/setupclientoptions"
"knative.dev/pkg/test/zipkin"
)

const (
roleName = "event-watcher-r"
serviceAccountName = "event-watcher-sa"
recordEventsPodName = "api-server-source-logger-pod"
roleName = "event-watcher-r"
serviceAccountName = "event-watcher-sa"
recordEventsPodName = "api-server-source-logger-pod"
)

var channelTestRunner testlib.ComponentsTestRunner
Expand Down Expand Up @@ -70,12 +70,19 @@ func TestMain(m *testing.M) {
}

func addSourcesInitializers() {
name := strings.ToLower(fmt.Sprintf("%s",
apiSrcName := strings.ToLower(fmt.Sprintf("%s",
testlib.ApiServerSourceTypeMeta.Kind))
pingSrcName := strings.ToLower(fmt.Sprintf("%s",
testlib.PingSourceTypeMeta.Kind))
Comment thread
devguyio marked this conversation as resolved.
sourcesTestRunner.AddComponentSetupClientOption(
testlib.ApiServerSourceTypeMeta,
setupclientoptions.ApiServerSourceClientSetupOption(name,
setupclientoptions.ApiServerSourceClientSetupOption(apiSrcName,
"Reference",
recordEventsPodName, roleName, serviceAccountName),
)
sourcesTestRunner.AddComponentSetupClientOption(
testlib.PingSourceTypeMeta,
setupclientoptions.PingSourceClientSetupOption(pingSrcName,
recordEventsPodName),
)
}
3 changes: 2 additions & 1 deletion test/conformance/source_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ limitations under the License.
package conformance

import (
"testing"

srchelpers "knative.dev/eventing/test/conformance/helpers/sources"
testlib "knative.dev/eventing/test/lib"
"testing"
)

func TestSourceStatus(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions test/lib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ var ChannelFeatureMap = map[metav1.TypeMeta][]Feature{
}

var ApiServerSourceTypeMeta = metav1.TypeMeta{
APIVersion: resources.SourcesAPIVersion,
APIVersion: resources.SourcesV1B1APIVersion,
Kind: resources.ApiServerSourceKind,
}

var PingSourceTypeMeta = metav1.TypeMeta{
APIVersion: resources.SourcesAPIVersion,
APIVersion: resources.SourcesV1A2APIVersion,
Kind: resources.PingSourceKind,
}

Expand Down
13 changes: 7 additions & 6 deletions test/lib/resources/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import (

// API versions for the resources.
const (
CoreAPIVersion = "v1"
EventingAPIVersion = "eventing.knative.dev/v1beta1"
MessagingAPIVersion = "messaging.knative.dev/v1beta1"
FlowsAPIVersion = "flows.knative.dev/v1beta1"
ServingAPIVersion = "serving.knative.dev/v1"
SourcesAPIVersion = "sources.knative.dev/v1beta1"
CoreAPIVersion = "v1"
EventingAPIVersion = "eventing.knative.dev/v1beta1"
MessagingAPIVersion = "messaging.knative.dev/v1beta1"
FlowsAPIVersion = "flows.knative.dev/v1beta1"
ServingAPIVersion = "serving.knative.dev/v1"
SourcesV1A2APIVersion = "sources.knative.dev/v1alpha2"
SourcesV1B1APIVersion = "sources.knative.dev/v1beta1"
)

// Kind for Knative resources.
Expand Down
36 changes: 35 additions & 1 deletion test/lib/setupclientoptions/sources.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ package setupclientoptions

import (
"fmt"

rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/util/uuid"

sourcesv1alpha2 "knative.dev/eventing/pkg/apis/sources/v1alpha2"
sourcesv1beta1 "knative.dev/eventing/pkg/apis/sources/v1beta1"
eventingtesting "knative.dev/eventing/pkg/reconciler/testing"
testlib "knative.dev/eventing/test/lib"
Expand All @@ -32,7 +36,7 @@ import (
// RoleBinding, a RecordEvents pod and an ApiServerSource object with the event
// mode and RecordEvent pod as its sink.
func ApiServerSourceClientSetupOption(name string, mode string, recordEventsPodName string,
roleName string, serviceAccountName string) testlib.SetupClientOption{
roleName string, serviceAccountName string) testlib.SetupClientOption {
return func(client *testlib.Client) {
// create needed RBAC SA, Role & RoleBinding
createRbacObjects(client, roleName, serviceAccountName)
Expand Down Expand Up @@ -64,6 +68,36 @@ func ApiServerSourceClientSetupOption(name string, mode string, recordEventsPodN
}
}

// PingSourceClientSetupOption returns a ClientSetupOption that can be used
// to create a new PingSource. It creates a RecordEvents pod and a
// PingSource object with the RecordEvent pod as its sink.
func PingSourceClientSetupOption(name string, recordEventsPodName string) testlib.SetupClientOption {
return func(client *testlib.Client) {

// create event logger pod and service
recordevents.StartEventRecordOrFail(client, recordEventsPodName)

// create cron job source
data := fmt.Sprintf(`{"msg":"TestPingSource %s"}`, uuid.NewUUID())
source := eventingtesting.NewPingSourceV1Alpha2(
name,
client.Namespace,
eventingtesting.WithPingSourceV1A2Spec(sourcesv1alpha2.PingSourceSpec{
JsonData: data,
SourceSpec: duckv1.SourceSpec{
Sink: duckv1.Destination{
Ref: resources.KnativeRefForService(recordEventsPodName, client.Namespace),
},
},
}),
)
client.CreatePingSourceV1Alpha2OrFail(source)

// wait for all test resources to be ready
client.WaitForAllTestResourcesReadyOrFail()
}
}

func createRbacObjects(client *testlib.Client, roleName string,
serviceAccountName string) {
// creates ServiceAccount and RoleBinding with a role for reading pods
Expand Down
17 changes: 11 additions & 6 deletions test/lib/test_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import (
"testing"
"time"

"knative.dev/eventing/pkg/utils"

corev1 "k8s.io/api/core/v1"
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/storage/names"

"knative.dev/eventing/pkg/utils"
pkgTest "knative.dev/pkg/test"
"knative.dev/pkg/test/helpers"
"knative.dev/pkg/test/prow"
Expand All @@ -49,7 +49,7 @@ const (
type ComponentsTestRunner struct {
ComponentFeatureMap map[metav1.TypeMeta][]Feature
ComponentsToTest []metav1.TypeMeta
componentOptions map[metav1.TypeMeta][]SetupClientOption
componentOptions map[metav1.TypeMeta][]SetupClientOption
}

// RunTests will use all components that support the given feature, to run
Expand Down Expand Up @@ -92,10 +92,15 @@ func (tr *ComponentsTestRunner) RunTestsWithComponentOptions(
// If in strict mode and a component is not present in the map, then
// don't run the tests
features, present := tr.ComponentFeatureMap[component]
if !strict || ( present && contains(features, feature)) {
t.Run(fmt.Sprintf("%s-%s", component.Kind, component.APIVersion), func(st *testing.T) {
subTestName := fmt.Sprintf("%s-%s", component.Kind, component.APIVersion)
if !strict || (present && contains(features, feature)) {
t.Run(subTestName, func(st *testing.T) {
testFunc(st, component, tr.componentOptions[component]...)
})
} else {
t.Skipf("Skipping %s for component %s since it did not "+
"match the feature %s and we are in strict mode", t.Name(),
subTestName, feature)
}
}
}
Expand All @@ -106,7 +111,7 @@ func (tr *ComponentsTestRunner) RunTestsWithComponentOptions(
// of a source or a channel) as opposed to other cheap initialization code that
// is safe to be called in all cases (e.g. installation of a CRD)
func (tr *ComponentsTestRunner) AddComponentSetupClientOption(component metav1.TypeMeta,
options ...SetupClientOption){
options ...SetupClientOption) {
if tr.componentOptions == nil {
tr.componentOptions = make(map[metav1.TypeMeta][]SetupClientOption)
}
Expand Down