Skip to content

Commit

Permalink
feat: added more robust init of tests
Browse files Browse the repository at this point in the history
Signed-off-by: RealAnna <[email protected]>
  • Loading branch information
RealAnna committed Oct 28, 2022
1 parent f1d4d4b commit 2c650fe
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 54 deletions.
7 changes: 7 additions & 0 deletions operator/controllers/common/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package common

import ctrl "sigs.k8s.io/controller-runtime"

type Controller interface {
SetupWithManager(mgr ctrl.Manager) error
}
80 changes: 63 additions & 17 deletions operator/test/appcontroller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,69 @@ package test
import (
klcv1alpha1 "github.com/keptn/lifecycle-controller/operator/api/v1alpha1"
"github.com/keptn/lifecycle-controller/operator/api/v1alpha1/common"
keptncontroller "github.com/keptn/lifecycle-controller/operator/controllers/common"
"github.com/keptn/lifecycle-controller/operator/controllers/keptnapp"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"go.opentelemetry.io/otel/sdk/trace"
otelsdk "go.opentelemetry.io/otel/sdk/trace"
sdktest "go.opentelemetry.io/otel/sdk/trace/tracetest"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)

// clean example of E2E test/ integration test --
// App controller creates AppVersion when a new App CRD is added
// span for creation and reconcile are correct
var _ = Describe("KeptnAppController", func() {
// container must be ordered to have the before all setup
// this way the container spec check is not randomized, so we can make
// assertions on spans number and traces
var _ = Describe("KeptnAppController", Ordered, func() {
var (
name string
namespace string
version string
name string
namespace string
version string
spanRecorder *sdktest.SpanRecorder
tracer *otelsdk.TracerProvider
)
BeforeEach(func() { // list var here

BeforeAll(func() {
//setup once
By("Waiting for Manager")
Eventually(func() bool {
return k8sManager != nil
}).Should(Equal(true))

By("Creating the Controller")

spanRecorder = sdktest.NewSpanRecorder()
tracer = otelsdk.NewTracerProvider(otelsdk.WithSpanProcessor(spanRecorder))

////setup controllers here
controllers := []keptncontroller.Controller{&keptnapp.KeptnAppReconciler{
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
Recorder: k8sManager.GetEventRecorderFor("test-app-controller"),
Log: GinkgoLogr,
Tracer: tracer.Tracer("test-app-tracer"),
}}
setupManager(controllers) // we can register multiple time the same controller
// so that they have a different span/trace

//for a fake controller you can also use
//controller, err := controller.New("app-controller", cm, controller.Options{
// Reconciler: reconcile.Func(
// func(_ context.Context, request reconcile.Request) (reconcile.Result, error) {
// reconciled <- request
// return reconcile.Result{}, nil
// }),
//})
//Expect(err).NotTo(HaveOccurred())
})

BeforeEach(func() { // list var here they will be copied for every spec
name = "test-app"
namespace = "default" // namespaces are not deleted in the api so be careful when creating new ones
namespace = "default" // namespaces are not deleted in the api so be careful
// when creating you can use ignoreAlreadyExists(err error)
version = "1.0.0"
})
Describe("Creation of AppVersion from a new App", func() {
Expand All @@ -30,25 +74,27 @@ var _ = Describe("KeptnAppController", func() {
appVersion *klcv1alpha1.KeptnAppVersion
)
Context("with a new App CRD", func() {

BeforeEach(func() {
instance = createInstanceInCluster(name, namespace, version, instance)
})
AfterEach(func() {
// Remember to clean up the cluster after each test
deleteAppInCluster(instance)
deleteAppVersionInCluster(appVersion)
})

It("should update the status of the CR ", func() {
appVersion = assertResourceUpdated(instance)
})
It("should update the spans", func() {
assertAppSpan(instance)
//ResetSpanRecords() // clean up span every time you read them
assertAppSpan(instance, spanRecorder)
})

})
AfterEach(func() {
// Remember to clean up the cluster after each test
deleteAppInCluster(instance)
deleteAppVersionInCluster(appVersion)
// Reset span recorder after each spec
resetSpanRecords(tracer, spanRecorder)
})
})

})

func deleteAppVersionInCluster(version *klcv1alpha1.KeptnAppVersion) {
Expand Down Expand Up @@ -82,9 +128,9 @@ func assertResourceUpdated(instance *klcv1alpha1.KeptnApp) *klcv1alpha1.KeptnApp
return appVersion
}

func assertAppSpan(instance *klcv1alpha1.KeptnApp) {
func assertAppSpan(instance *klcv1alpha1.KeptnApp, spanRecorder *sdktest.SpanRecorder) {
By("Comparing spans")
var spans []trace.ReadOnlySpan
var spans []otelsdk.ReadOnlySpan
Eventually(func() int {
spans = spanRecorder.Ended()
return len(spans)
Expand Down
36 changes: 32 additions & 4 deletions operator/test/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package test
import (
"fmt"
klcv1alpha1 "github.com/keptn/lifecycle-controller/operator/api/v1alpha1"
keptncontroller "github.com/keptn/lifecycle-controller/operator/controllers/common"
"github.com/keptn/lifecycle-controller/operator/controllers/keptnapp"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
otelsdk "go.opentelemetry.io/otel/sdk/trace"
sdktest "go.opentelemetry.io/otel/sdk/trace/tracetest"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -230,9 +234,33 @@ import (

const LOAD = 100

var _ = Describe("[Feature:Performance] Load KeptnAppController", func() {
var apps []*klcv1alpha1.KeptnApp //Shelf is declared here
var appVersions []*klcv1alpha1.KeptnAppVersion
var _ = Describe("[Feature:Performance] Load KeptnAppController", Ordered, func() {
var (
apps []*klcv1alpha1.KeptnApp //Shelf is declared here
appVersions []*klcv1alpha1.KeptnAppVersion
spanRecorder *sdktest.SpanRecorder
tracer *otelsdk.TracerProvider
)
BeforeAll(func() {
//setup once
By("Waiting for Manager")
Eventually(func() bool {
return k8sManager != nil
}).Should(Equal(true))

spanRecorder = sdktest.NewSpanRecorder()
tracer = otelsdk.NewTracerProvider(otelsdk.WithSpanProcessor(spanRecorder))

controllers := []keptncontroller.Controller{&keptnapp.KeptnAppReconciler{
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
Recorder: k8sManager.GetEventRecorderFor("test-app-controller"),
Log: GinkgoLogr,
Tracer: tracer.Tracer("test-app-tracer"),
}}
setupManager(controllers)
})

BeforeEach(func() {

for i := 0; i < LOAD; i++ {
Expand Down Expand Up @@ -267,7 +295,7 @@ var _ = Describe("[Feature:Performance] Load KeptnAppController", func() {
It("should create the app version CR", func() {
for _, app := range apps {
appVersions = append(appVersions, assertResourceUpdated(app))
ResetSpanRecords()
//ResetSpanRecords()
}
})
})
65 changes: 32 additions & 33 deletions operator/test/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,38 @@ package test
import (
"context"
"fmt"
"github.com/keptn/lifecycle-controller/operator/controllers/keptnapp"
lifecyclev1alpha1 "github.com/keptn/lifecycle-controller/operator/api/v1alpha1"
keptncontroller "github.com/keptn/lifecycle-controller/operator/controllers/common"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
otelsdk "go.opentelemetry.io/otel/sdk/trace"
sdktest "go.opentelemetry.io/otel/sdk/trace/tracetest"
"path/filepath"
ctrl "sigs.k8s.io/controller-runtime"
"testing"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"path/filepath"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"

lifecyclev1alpha1 "github.com/keptn/lifecycle-controller/operator/api/v1alpha1"
"testing"
"time"
//+kubebuilder:scaffold:imports
)

// These tests use Ginkgo (BDD-style Go testing framework). Refer to
// http://onsi.github.io/ginkgo/v2 to learn more about Ginkgo.
var (
cfg *rest.Config
k8sClient client.Client
testEnv *envtest.Environment
ctx context.Context
cancel context.CancelFunc
spanRecorder *sdktest.SpanRecorder
tp otelsdk.TracerProvider
cfg *rest.Config
k8sClient client.Client
testEnv *envtest.Environment
ctx context.Context
cancel context.CancelFunc
k8sManager ctrl.Manager
//spanRecorder *sdktest.SpanRecorder
//tp otelsdk.TracerProvider
)

func TestAPIs(t *testing.T) {
Expand Down Expand Up @@ -103,23 +102,11 @@ var _ = BeforeSuite(func() {
available when talking directly to the API server.
*/

k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
k8sManager, err = ctrl.NewManager(cfg, ctrl.Options{
Scheme: scheme.Scheme,
})
Expect(err).ToNot(HaveOccurred())
spanRecorder = sdktest.NewSpanRecorder()
tr := otelsdk.NewTracerProvider(otelsdk.WithSpanProcessor(spanRecorder))

//setup controllers here
err = (&keptnapp.KeptnAppReconciler{
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
Recorder: k8sManager.GetEventRecorderFor("test-app-controller"),
Log: GinkgoLogr,
Tracer: tr.Tracer("test-app-tracer"),
}).SetupWithManager(k8sManager)

Expect(err).ToNot(HaveOccurred())
go func() {
defer GinkgoRecover()
err = k8sManager.Start(ctx)
Expand All @@ -135,9 +122,21 @@ var _ = BeforeSuite(func() {

})

var _ = AfterSuite(ResetSpanRecords)
func ignoreAlreadyExists(err error) error {
if apierrors.IsAlreadyExists(err) {
return nil
}
return err
}

func setupManager(rec []keptncontroller.Controller) {
for _, r := range rec {
r.SetupWithManager(k8sManager)
}

}

func ResetSpanRecords() {
func resetSpanRecords(tp *otelsdk.TracerProvider, spanRecorder *sdktest.SpanRecorder) {
GinkgoLogr.Info("Removing ", fmt.Sprint(len(spanRecorder.Ended())), " spans")
tp.UnregisterSpanProcessor(spanRecorder)
spanRecorder = sdktest.NewSpanRecorder()
Expand Down

0 comments on commit 2c650fe

Please sign in to comment.