linkerd2/controller/proxy-injector/webhook_test.go

200 lines
5.7 KiB
Go

package injector
import (
"fmt"
"reflect"
"testing"
"github.com/linkerd/linkerd2/controller/proxy-injector/fake"
"github.com/linkerd/linkerd2/pkg/k8s"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
corev1 "k8s.io/api/core/v1"
)
var (
factory *fake.Factory
)
func TestShouldInject(t *testing.T) {
nsEnabled, err := factory.Namespace("namespace-inject-enabled.yaml")
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
nsDisabled, err := factory.Namespace("namespace-inject-disabled.yaml")
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
fakeClient := fake.NewClient("", nsEnabled, nsDisabled)
webhook, err := NewWebhook(fakeClient, testWebhookResources, fake.DefaultControllerNamespace, fake.DefaultNoInitContainer, fake.DefaultTLSEnabled)
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
t.Run("by checking annotations", func(t *testing.T) {
var testCases = []struct {
filename string
ns *corev1.Namespace
expected bool
}{
{
filename: "deployment-inject-empty.yaml",
ns: nsEnabled,
expected: true,
},
{
filename: "deployment-inject-enabled.yaml",
ns: nsEnabled,
expected: true,
},
{
filename: "deployment-inject-disabled.yaml",
ns: nsEnabled,
expected: false,
},
{
filename: "deployment-inject-empty.yaml",
ns: nsDisabled,
expected: false,
},
{
filename: "deployment-inject-enabled.yaml",
ns: nsDisabled,
expected: true,
},
{
filename: "deployment-inject-disabled.yaml",
ns: nsDisabled,
expected: false,
},
}
for id, testCase := range testCases {
t.Run(fmt.Sprintf("%d", id), func(t *testing.T) {
deployment, err := factory.Deployment(testCase.filename)
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
inject, err := webhook.shouldInject(testCase.ns.GetName(), deployment)
if err != nil {
t.Fatalf("Unexpected shouldInject error: %s", err)
}
if inject != testCase.expected {
t.Fatalf("Boolean mismatch. Expected: %t. Actual: %t", testCase.expected, inject)
}
})
}
})
t.Run("by checking container spec", func(t *testing.T) {
deployment, err := factory.Deployment("deployment-with-injected-proxy.yaml")
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
inject, err := webhook.shouldInject(nsEnabled.GetName(), deployment)
if err != nil {
t.Fatalf("Unexpected shouldInject error: %s", err)
}
if inject {
t.Fatal("Expected deployment with injected proxy to be skipped")
}
})
}
func TestContainersSpec(t *testing.T) {
fakeClient := fake.NewClient("")
webhook, err := NewWebhook(fakeClient, testWebhookResources, fake.DefaultControllerNamespace, fake.DefaultNoInitContainer, fake.DefaultTLSEnabled)
if err != nil {
t.Fatal("Unexpected error: ", err)
}
expectedSidecar, err := factory.Container("inject-sidecar-container-spec.yaml")
if err != nil {
t.Fatal("Unexpected error: ", err)
}
expectedInit, err := factory.Container("inject-init-container-spec.yaml")
if err != nil {
t.Fatal("Unexpected error: ", err)
}
identity := &k8s.TLSIdentity{
Name: "nginx",
Kind: "deployment",
Namespace: fake.DefaultNamespace,
ControllerNamespace: fake.DefaultControllerNamespace,
}
actualSidecar, actualInit, err := webhook.containersSpec(identity)
if err != nil {
t.Fatal("Unexpected error: ", err)
}
if !reflect.DeepEqual(expectedSidecar, actualSidecar) {
t.Errorf("Content mismatch\nExpected: %+v\nActual: %+v", expectedSidecar, actualSidecar)
}
if !reflect.DeepEqual(expectedInit, actualInit) {
t.Errorf("Content mismatch\nExpected: %+v\nActual: %+v", expectedInit, actualInit)
}
}
func TestVolumesSpec(t *testing.T) {
fakeClient := fake.NewClient("")
webhook, err := NewWebhook(fakeClient, testWebhookResources, fake.DefaultControllerNamespace, fake.DefaultNoInitContainer, fake.DefaultTLSEnabled)
if err != nil {
t.Fatal("Unexpected error: ", err)
}
expectedTrustAnchors, err := factory.Volume("inject-trust-anchors-volume-spec.yaml")
if err != nil {
t.Fatal("Unexpected error: ", err)
}
expectedLinkerdSecrets, err := factory.Volume("inject-linkerd-secrets-volume-spec.yaml")
if err != nil {
t.Fatal("Unexpected error: ", err)
}
identity := &k8s.TLSIdentity{
Name: "nginx",
Kind: "deployment",
Namespace: fake.DefaultNamespace,
ControllerNamespace: fake.DefaultControllerNamespace,
}
actualTrustAnchors, actualLinkerdSecrets, err := webhook.volumesSpec(identity)
if err != nil {
t.Fatal("Unexpected error: ", err)
}
if !reflect.DeepEqual(expectedTrustAnchors, actualTrustAnchors) {
t.Errorf("Content mismatch\nExpected: %+v\nActual: %+v", expectedTrustAnchors, actualTrustAnchors)
}
if !reflect.DeepEqual(expectedLinkerdSecrets, actualLinkerdSecrets) {
t.Errorf("Content mismatch\nExpected: %+v\nActual: %+v", expectedLinkerdSecrets, actualLinkerdSecrets)
}
}
func assertEqualAdmissionReview(t *testing.T, expected, actual *admissionv1beta1.AdmissionReview) {
if !reflect.DeepEqual(expected.Request, actual.Request) {
if !reflect.DeepEqual(expected.Request.Object, actual.Request.Object) {
t.Errorf("Request object mismatch\nExpected: %s\nActual: %s", expected.Request.Object, actual.Request.Object)
} else {
t.Errorf("Request mismatch\nExpected: %+v\nActual: %+v", expected.Request, actual.Request)
}
}
if !reflect.DeepEqual(expected.Response, actual.Response) {
if actual.Response.Result != nil {
t.Errorf("Actual response message: %s", actual.Response.Result.Message)
}
t.Errorf("Response patch mismatch\nExpected: %s\nActual: %s", expected.Response.Patch, actual.Response.Patch)
}
}