Skip to content

Commit

Permalink
port reconciler tests to webhook
Browse files Browse the repository at this point in the history
Signed-off-by: Benedikt Bongartz <[email protected]>
  • Loading branch information
frzifus committed Mar 25, 2022
1 parent e093cdc commit f50dddd
Show file tree
Hide file tree
Showing 2 changed files with 339 additions and 0 deletions.
217 changes: 217 additions & 0 deletions controllers/appsv1/deployment_webhook_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
package appsv1

import (
"bytes"
"context"
"encoding/json"
"testing"

"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
jsonpatch "gomodules.xyz/jsonpatch/v2"
admissionv1 "k8s.io/api/admission/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

v1 "github.com/jaegertracing/jaeger-operator/apis/v1"
"github.com/jaegertracing/jaeger-operator/pkg/inject"
)

func TestReconcileConfigMaps(t *testing.T) {
testCases := []struct {
desc string
existing []runtime.Object
}{
{
desc: "all config maps missing",
},
{
desc: "none missing",
existing: []runtime.Object{
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns1",
Name: "my-instance-trusted-ca",
},
},
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns1",
Name: "my-instance-service-ca",
},
},
},
},
}
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
// prepare
jaeger := v1.NewJaeger(types.NamespacedName{
Namespace: "observability",
Name: "my-instance",
})
dep := appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns1",
Name: "my-dep",
},
}

cl := fake.NewFakeClient(tC.existing...)

viper.Set("platform", v1.FlagPlatformOpenShift)
defer viper.Reset()

// test
err := reconcileConfigMaps(context.Background(), cl, jaeger, &dep)

// verify
assert.NoError(t, err)

cms := corev1.ConfigMapList{}
err = cl.List(context.Background(), &cms)
require.NoError(t, err)

assert.Len(t, cms.Items, 2)
})
}
}

func TestReconcilieDeployment(t *testing.T) {
namespacedName := types.NamespacedName{
Name: "jaeger-query",
Namespace: "my-ns",
}

jaeger := v1.NewJaeger(types.NamespacedName{
Namespace: "observability",
Name: "my-instance",
})

s := scheme.Scheme
s.AddKnownTypes(v1.GroupVersion, jaeger)
s.AddKnownTypes(v1.GroupVersion, &v1.JaegerList{})

testCases := []struct {
desc string
dep *appsv1.Deployment
resp admission.Response
}{
{
desc: "Should not remove the instance from a jaeger component",
dep: inject.Sidecar(jaeger, &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
Annotations: map[string]string{},
Labels: map[string]string{
"app": "jaeger",
},
},
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "only_container",
}},
},
},
},
}),
resp: admission.Response{
AdmissionResponse: admissionv1.AdmissionResponse{
Allowed: true,
Result: &metav1.Status{
Reason: "is jeager deployment, we do not touch it",
Code: 200,
},
},
},
},
{
desc: "Should remove the instance",
dep: inject.Sidecar(jaeger, &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
Annotations: map[string]string{},
},
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "only_container",
}},
},
},
},
}),
resp: admission.Response{
Patches: []jsonpatch.JsonPatchOperation{
{
Operation: "remove",
Path: "/metadata/labels",
},
{
Operation: "remove",
Path: "/spec/template/spec/containers/1",
},
},
AdmissionResponse: admissionv1.AdmissionResponse{
Allowed: true,
PatchType: func() *admissionv1.PatchType { str := admissionv1.PatchTypeJSONPatch; return &str }(),
},
},
},
}

for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {

assert.Equal(t, 2, len(tc.dep.Spec.Template.Spec.Containers))
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Namespace,
},
}

cl := fake.NewFakeClient(tc.dep, ns)

r := NewDeploymentInterceptorWebhook(cl)

req := admission.Request{
AdmissionRequest: admissionv1.AdmissionRequest{
Name: tc.dep.Name,
Namespace: tc.dep.Namespace,
Object: runtime.RawExtension{
Raw: func() []byte {
var buf bytes.Buffer
if getErr := json.NewEncoder(&buf).Encode(tc.dep); getErr != nil {
t.Fatal(getErr)
}
return buf.Bytes()
}(),
},
},
}

decoder, err := admission.NewDecoder(s)
require.NoError(t, err)
admission.InjectDecoderInto(decoder, r)
resp := r.Handle(context.Background(), req)

assert.Equal(t, tc.resp, resp)

require.NoError(t, err)
})
}
}
122 changes: 122 additions & 0 deletions controllers/jaegertracing/jaeger_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,141 @@ package jaegertracing_test

import (
"context"
"sort"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
k8sconfig "sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/manager"
k8sreconcile "sigs.k8s.io/controller-runtime/pkg/reconcile"

v1 "github.com/jaegertracing/jaeger-operator/apis/v1"
"github.com/jaegertracing/jaeger-operator/controllers/jaegertracing"
ctljaeger "github.com/jaegertracing/jaeger-operator/pkg/controller/jaeger"
"github.com/jaegertracing/jaeger-operator/pkg/inject"
)

type updateCounter struct {
client.WithWatch

counter int
}

func (u *updateCounter) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
u.counter++
return u.WithWatch.Update(ctx, obj, opts...)
}

func TestSyncOnJaegerChanges(t *testing.T) {
// prepare
jaeger := v1.NewJaeger(types.NamespacedName{
Namespace: "observability",
Name: "my-instance",
})

objs := []runtime.Object{
&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{
Name: "ns-with-annotation",
Annotations: map[string]string{
inject.Annotation: "true",
},
}},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "dep-without-annotation",
Namespace: "ns-with-annotation",
},
},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "dep-with-annotation",
Namespace: "ns-with-annotation",
Annotations: map[string]string{
inject.Annotation: "true",
},
},
},

&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{
Name: "ns-without-annotation",
}},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "dep-without-annotation",
Namespace: "ns-without-annotation",
},
},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "dep-with-annotation",
Namespace: "ns-without-annotation",
Annotations: map[string]string{
inject.Annotation: "true",
},
},
},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "dep-with-another-jaegers-label",
Namespace: "ns-without-annotation",
Annotations: map[string]string{
inject.Annotation: "true",
},
Labels: map[string]string{
inject.Label: "some-other-jaeger",
},
},
},
&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "dep-affected-jaeger-label",
Namespace: "ns-without-annotation",
Annotations: map[string]string{
inject.Annotation: "true",
},
Labels: map[string]string{
inject.Label: jaeger.Name,
},
},
},
}

s := scheme.Scheme
cl := &updateCounter{WithWatch: fake.NewFakeClient(objs...)}
r := ctljaeger.New(cl, cl, s)

// test
requests := r.SyncOnJaegerChanges(jaeger)

// verify
assert.Equal(t, cl.counter, 3)
assert.Len(t, requests, 1)

expected := []k8sreconcile.Request{
{NamespacedName: types.NamespacedName{
Name: "dep-without-annotation",
Namespace: "ns-with-annotation",
}},
}

sort.Slice(requests, func(i, j int) bool {
return requests[i].NamespacedName.String() < requests[j].NamespacedName.String()
})
sort.Slice(expected, func(i, j int) bool {
return expected[i].NamespacedName.String() < expected[j].NamespacedName.String()
})
assert.Equal(t, expected, requests)
}

func TestNewJaegerInstance(t *testing.T) {
// prepare
nsn := types.NamespacedName{Name: "my-instance", Namespace: "default"}
Expand Down

0 comments on commit f50dddd

Please sign in to comment.