mirror of https://github.com/linkerd/linkerd2.git
426 lines
10 KiB
Go
426 lines
10 KiB
Go
package inject
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
func TestInjectable(t *testing.T) {
|
|
var testCases = []struct {
|
|
podSpec *corev1.PodSpec
|
|
podMeta *metav1.ObjectMeta
|
|
nsAnnotations map[string]string
|
|
unsupportedResource bool
|
|
injectable bool
|
|
reasons []string
|
|
}{
|
|
{
|
|
podSpec: &corev1.PodSpec{
|
|
HostNetwork: false,
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
injectable: true,
|
|
},
|
|
{
|
|
podSpec: &corev1.PodSpec{
|
|
HostNetwork: true,
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
injectable: false,
|
|
reasons: []string{hostNetworkEnabled},
|
|
},
|
|
{
|
|
podSpec: &corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
{
|
|
Name: k8s.ProxyContainerName,
|
|
Image: "cr.l5d.io/linkerd/proxy:",
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
injectable: false,
|
|
reasons: []string{sidecarExists},
|
|
},
|
|
{
|
|
podSpec: &corev1.PodSpec{
|
|
InitContainers: []corev1.Container{
|
|
{
|
|
Name: k8s.InitContainerName,
|
|
Image: "cr.l5d.io/linkerd/proxy-init:",
|
|
},
|
|
},
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
injectable: false,
|
|
reasons: []string{sidecarExists},
|
|
},
|
|
{
|
|
unsupportedResource: true,
|
|
podSpec: &corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
injectable: false,
|
|
reasons: []string{unsupportedResource},
|
|
},
|
|
{
|
|
unsupportedResource: true,
|
|
podSpec: &corev1.PodSpec{
|
|
HostNetwork: true,
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
|
|
injectable: false,
|
|
reasons: []string{hostNetworkEnabled, unsupportedResource},
|
|
},
|
|
{
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
podSpec: &corev1.PodSpec{
|
|
HostNetwork: true,
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
},
|
|
|
|
injectable: false,
|
|
reasons: []string{hostNetworkEnabled, injectDisableAnnotationPresent},
|
|
},
|
|
{
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
unsupportedResource: true,
|
|
podSpec: &corev1.PodSpec{
|
|
HostNetwork: true,
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
},
|
|
|
|
injectable: false,
|
|
reasons: []string{hostNetworkEnabled, unsupportedResource, injectDisableAnnotationPresent},
|
|
},
|
|
{
|
|
unsupportedResource: true,
|
|
podSpec: &corev1.PodSpec{
|
|
HostNetwork: true,
|
|
Containers: []corev1.Container{
|
|
{
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{},
|
|
},
|
|
|
|
injectable: false,
|
|
reasons: []string{hostNetworkEnabled, unsupportedResource, injectEnableAnnotationAbsent},
|
|
},
|
|
{
|
|
podSpec: &corev1.PodSpec{HostNetwork: true,
|
|
Containers: []corev1.Container{
|
|
{
|
|
Name: k8s.ProxyContainerName,
|
|
Image: "cr.l5d.io/linkerd/proxy:",
|
|
VolumeMounts: []corev1.VolumeMount{
|
|
{
|
|
MountPath: k8s.MountPathServiceAccount,
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{},
|
|
},
|
|
|
|
injectable: false,
|
|
reasons: []string{hostNetworkEnabled, sidecarExists, injectEnableAnnotationAbsent},
|
|
},
|
|
}
|
|
|
|
for i, testCase := range testCases {
|
|
testCase := testCase
|
|
t.Run(fmt.Sprintf("test case #%d", i), func(t *testing.T) {
|
|
resourceConfig := &ResourceConfig{}
|
|
resourceConfig.WithNsAnnotations(testCase.nsAnnotations)
|
|
resourceConfig.pod.spec = testCase.podSpec
|
|
resourceConfig.origin = OriginWebhook
|
|
resourceConfig.pod.meta = testCase.podMeta
|
|
|
|
report := newReport(resourceConfig)
|
|
report.UnsupportedResource = testCase.unsupportedResource
|
|
|
|
actual, reasons := report.Injectable()
|
|
if testCase.injectable != actual {
|
|
t.Errorf("Expected %t. Actual %t", testCase.injectable, actual)
|
|
}
|
|
|
|
if len(reasons) != len(testCase.reasons) {
|
|
t.Errorf("Expected %d number of reasons. Actual %d", len(testCase.reasons), len(reasons))
|
|
}
|
|
|
|
for i := range reasons {
|
|
if testCase.reasons[i] != reasons[i] {
|
|
t.Errorf("Expected reason '%s'. Actual reason '%s'", testCase.reasons[i], reasons[i])
|
|
}
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDisableByAnnotation(t *testing.T) {
|
|
t.Run("webhook origin", func(t *testing.T) {
|
|
var testCases = []struct {
|
|
podMeta *metav1.ObjectMeta
|
|
nsAnnotations map[string]string
|
|
expected bool
|
|
}{
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{},
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
},
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
},
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
},
|
|
nsAnnotations: map[string]string{},
|
|
expected: true,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{},
|
|
nsAnnotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
expected: true,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{},
|
|
nsAnnotations: map[string]string{},
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for i, testCase := range testCases {
|
|
testCase := testCase
|
|
t.Run(fmt.Sprintf("test case #%d", i), func(t *testing.T) {
|
|
resourceConfig := &ResourceConfig{origin: OriginWebhook}
|
|
resourceConfig.WithNsAnnotations(testCase.nsAnnotations)
|
|
resourceConfig.pod.meta = testCase.podMeta
|
|
resourceConfig.pod.spec = &corev1.PodSpec{} // initialize empty spec to prevent test from failing
|
|
|
|
report := newReport(resourceConfig)
|
|
if actual, _, _ := report.disabledByAnnotation(resourceConfig); testCase.expected != actual {
|
|
t.Errorf("Expected %t. Actual %t", testCase.expected, actual)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("CLI origin", func(t *testing.T) {
|
|
var testCases = []struct {
|
|
podMeta *metav1.ObjectMeta
|
|
expected bool
|
|
}{
|
|
{
|
|
podMeta: &metav1.ObjectMeta{},
|
|
expected: false,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
|
|
},
|
|
},
|
|
expected: false,
|
|
},
|
|
{
|
|
podMeta: &metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
|
|
},
|
|
},
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for i, testCase := range testCases {
|
|
testCase := testCase
|
|
t.Run(fmt.Sprintf("test case #%d", i), func(t *testing.T) {
|
|
resourceConfig := &ResourceConfig{origin: OriginCLI}
|
|
resourceConfig.pod.meta = testCase.podMeta
|
|
resourceConfig.pod.spec = &corev1.PodSpec{} // initialize empty spec to prevent test from failing
|
|
|
|
report := newReport(resourceConfig)
|
|
if actual, _, _ := report.disabledByAnnotation(resourceConfig); testCase.expected != actual {
|
|
t.Errorf("Expected %t. Actual %t", testCase.expected, actual)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|