linkerd2/controller/proxy-injector/webhook_test.go

182 lines
5.5 KiB
Go

package injector
import (
"fmt"
"io/ioutil"
"reflect"
"testing"
"github.com/linkerd/linkerd2/controller/proxy-injector/fake"
"github.com/linkerd/linkerd2/pkg/k8s"
log "github.com/sirupsen/logrus"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
)
var (
webhook *Webhook
factory *fake.Factory
)
func init() {
// create a webhook which uses its fake client to seed the sidecar configmap
fakeClient, err := fake.NewClient("")
if err != nil {
panic(err)
}
webhook, err = NewWebhook(fakeClient, testWebhookResources, fake.DefaultControllerNamespace)
if err != nil {
panic(err)
}
log.SetOutput(ioutil.Discard)
}
func TestMutate(t *testing.T) {
var testCases = []struct {
title string
requestFile string
responseFile string
}{
{title: "no labels", requestFile: "inject-no-labels-request.json", responseFile: "inject-no-labels-response.yaml"},
{title: "inject enabled", requestFile: "inject-enabled-request.json", responseFile: "inject-enabled-response.yaml"},
{title: "inject disabled", requestFile: "inject-disabled-request.json", responseFile: "inject-disabled-response.yaml"},
{title: "inject completed", requestFile: "inject-completed-request.json", responseFile: "inject-completed-response.yaml"},
}
for _, testCase := range testCases {
t.Run(fmt.Sprintf("%s", testCase.title), func(t *testing.T) {
data, err := factory.HTTPRequestBody(testCase.requestFile)
if err != nil {
t.Fatal("Unexpected error: ", err)
}
expected, err := factory.AdmissionReview(testCase.responseFile)
if err != nil {
t.Fatal("Unexpected error: ", err)
}
actual := webhook.Mutate(data)
assertEqualAdmissionReview(t, expected, actual)
})
}
}
func TestIgnore(t *testing.T) {
t.Run("by checking labels", func(t *testing.T) {
var testCases = []struct {
filename string
expected bool
}{
{filename: "deployment-inject-status-empty.yaml", expected: false},
{filename: "deployment-inject-status-enabled.yaml", expected: false},
{filename: "deployment-inject-status-disabled.yaml", expected: true},
{filename: "deployment-inject-status-completed.yaml", expected: true},
}
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.Fatal("Unexpected error: ", err)
}
if actual := webhook.ignore(deployment); actual != testCase.expected {
t.Errorf("Boolean mismatch. Expected: %t. Actual: %t", testCase.expected, actual)
}
})
}
})
t.Run("by checking container spec", func(t *testing.T) {
deployment, err := factory.Deployment("deployment-with-injected-proxy.yaml")
if err != nil {
t.Fatal("Unexpected error: ", err)
}
if !webhook.ignore(deployment) {
t.Errorf("Expected deployment with injected proxy to be ignored")
}
})
}
func TestContainersSpec(t *testing.T) {
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) {
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)
}
}