...

Source file src/github.com/linkerd/linkerd2/pkg/inject/report_test.go

Documentation: github.com/linkerd/linkerd2/pkg/inject

     1  package inject
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/linkerd/linkerd2/pkg/k8s"
     8  	corev1 "k8s.io/api/core/v1"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  )
    11  
    12  func TestInjectable(t *testing.T) {
    13  	var testCases = []struct {
    14  		podSpec             *corev1.PodSpec
    15  		podMeta             *metav1.ObjectMeta
    16  		nsAnnotations       map[string]string
    17  		unsupportedResource bool
    18  		injectable          bool
    19  		reasons             []string
    20  	}{
    21  		{
    22  			podSpec: &corev1.PodSpec{
    23  				HostNetwork: false,
    24  				Containers: []corev1.Container{
    25  					{
    26  						VolumeMounts: []corev1.VolumeMount{
    27  							{
    28  								MountPath: k8s.MountPathServiceAccount,
    29  							},
    30  						},
    31  					},
    32  				},
    33  			},
    34  			podMeta: &metav1.ObjectMeta{
    35  				Annotations: map[string]string{
    36  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
    37  				},
    38  			},
    39  			injectable: true,
    40  		},
    41  		{
    42  			podSpec: &corev1.PodSpec{
    43  				HostNetwork: true,
    44  				Containers: []corev1.Container{
    45  					{
    46  						VolumeMounts: []corev1.VolumeMount{
    47  							{
    48  								MountPath: k8s.MountPathServiceAccount,
    49  							},
    50  						},
    51  					},
    52  				},
    53  			},
    54  			podMeta: &metav1.ObjectMeta{
    55  				Annotations: map[string]string{
    56  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
    57  				},
    58  			},
    59  			injectable: false,
    60  			reasons:    []string{hostNetworkEnabled},
    61  		},
    62  		{
    63  			podSpec: &corev1.PodSpec{
    64  				Containers: []corev1.Container{
    65  					{
    66  						Name:  k8s.ProxyContainerName,
    67  						Image: "cr.l5d.io/linkerd/proxy:",
    68  						VolumeMounts: []corev1.VolumeMount{
    69  							{
    70  								MountPath: k8s.MountPathServiceAccount,
    71  							},
    72  						},
    73  					},
    74  				},
    75  			},
    76  			podMeta: &metav1.ObjectMeta{
    77  				Annotations: map[string]string{
    78  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
    79  				},
    80  			},
    81  			injectable: false,
    82  			reasons:    []string{sidecarExists},
    83  		},
    84  		{
    85  			podSpec: &corev1.PodSpec{
    86  				InitContainers: []corev1.Container{
    87  					{
    88  						Name:  k8s.InitContainerName,
    89  						Image: "cr.l5d.io/linkerd/proxy-init:",
    90  					},
    91  				},
    92  				Containers: []corev1.Container{
    93  					{
    94  						VolumeMounts: []corev1.VolumeMount{
    95  							{
    96  								MountPath: k8s.MountPathServiceAccount,
    97  							},
    98  						},
    99  					},
   100  				},
   101  			},
   102  			podMeta: &metav1.ObjectMeta{
   103  				Annotations: map[string]string{
   104  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   105  				},
   106  			},
   107  			injectable: false,
   108  			reasons:    []string{sidecarExists},
   109  		},
   110  		{
   111  			unsupportedResource: true,
   112  			podSpec: &corev1.PodSpec{
   113  				Containers: []corev1.Container{
   114  					{
   115  						VolumeMounts: []corev1.VolumeMount{
   116  							{
   117  								MountPath: k8s.MountPathServiceAccount,
   118  							},
   119  						},
   120  					},
   121  				},
   122  			},
   123  			podMeta: &metav1.ObjectMeta{
   124  				Annotations: map[string]string{
   125  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   126  				},
   127  			},
   128  			injectable: false,
   129  			reasons:    []string{unsupportedResource},
   130  		},
   131  		{
   132  			unsupportedResource: true,
   133  			podSpec: &corev1.PodSpec{
   134  				HostNetwork: true,
   135  				Containers: []corev1.Container{
   136  					{
   137  						VolumeMounts: []corev1.VolumeMount{
   138  							{
   139  								MountPath: k8s.MountPathServiceAccount,
   140  							},
   141  						},
   142  					},
   143  				},
   144  			},
   145  			podMeta: &metav1.ObjectMeta{
   146  				Annotations: map[string]string{
   147  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   148  				},
   149  			},
   150  
   151  			injectable: false,
   152  			reasons:    []string{hostNetworkEnabled, unsupportedResource},
   153  		},
   154  		{
   155  			nsAnnotations: map[string]string{
   156  				k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   157  			},
   158  			podSpec: &corev1.PodSpec{
   159  				HostNetwork: true,
   160  				Containers: []corev1.Container{
   161  					{
   162  						VolumeMounts: []corev1.VolumeMount{
   163  							{
   164  								MountPath: k8s.MountPathServiceAccount,
   165  							},
   166  						},
   167  					},
   168  				},
   169  			},
   170  			podMeta: &metav1.ObjectMeta{
   171  				Annotations: map[string]string{
   172  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   173  				},
   174  			},
   175  
   176  			injectable: false,
   177  			reasons:    []string{hostNetworkEnabled, injectDisableAnnotationPresent},
   178  		},
   179  		{
   180  			nsAnnotations: map[string]string{
   181  				k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   182  			},
   183  			unsupportedResource: true,
   184  			podSpec: &corev1.PodSpec{
   185  				HostNetwork: true,
   186  				Containers: []corev1.Container{
   187  					{
   188  						VolumeMounts: []corev1.VolumeMount{
   189  							{
   190  								MountPath: k8s.MountPathServiceAccount,
   191  							},
   192  						},
   193  					},
   194  				},
   195  			},
   196  			podMeta: &metav1.ObjectMeta{
   197  				Annotations: map[string]string{
   198  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   199  				},
   200  			},
   201  
   202  			injectable: false,
   203  			reasons:    []string{hostNetworkEnabled, unsupportedResource, injectDisableAnnotationPresent},
   204  		},
   205  		{
   206  			unsupportedResource: true,
   207  			podSpec: &corev1.PodSpec{
   208  				HostNetwork: true,
   209  				Containers: []corev1.Container{
   210  					{
   211  						VolumeMounts: []corev1.VolumeMount{
   212  							{
   213  								MountPath: k8s.MountPathServiceAccount,
   214  							},
   215  						},
   216  					},
   217  				},
   218  			},
   219  			podMeta: &metav1.ObjectMeta{
   220  				Annotations: map[string]string{},
   221  			},
   222  
   223  			injectable: false,
   224  			reasons:    []string{hostNetworkEnabled, unsupportedResource, injectEnableAnnotationAbsent},
   225  		},
   226  		{
   227  			podSpec: &corev1.PodSpec{HostNetwork: true,
   228  				Containers: []corev1.Container{
   229  					{
   230  						Name:  k8s.ProxyContainerName,
   231  						Image: "cr.l5d.io/linkerd/proxy:",
   232  						VolumeMounts: []corev1.VolumeMount{
   233  							{
   234  								MountPath: k8s.MountPathServiceAccount,
   235  							},
   236  						},
   237  					},
   238  				}},
   239  			podMeta: &metav1.ObjectMeta{
   240  				Annotations: map[string]string{},
   241  			},
   242  
   243  			injectable: false,
   244  			reasons:    []string{hostNetworkEnabled, sidecarExists, injectEnableAnnotationAbsent},
   245  		},
   246  	}
   247  
   248  	for i, testCase := range testCases {
   249  		testCase := testCase
   250  		t.Run(fmt.Sprintf("test case #%d", i), func(t *testing.T) {
   251  			resourceConfig := &ResourceConfig{}
   252  			resourceConfig.WithNsAnnotations(testCase.nsAnnotations)
   253  			resourceConfig.pod.spec = testCase.podSpec
   254  			resourceConfig.origin = OriginWebhook
   255  			resourceConfig.pod.meta = testCase.podMeta
   256  
   257  			report := newReport(resourceConfig)
   258  			report.UnsupportedResource = testCase.unsupportedResource
   259  
   260  			actual, reasons := report.Injectable()
   261  			if testCase.injectable != actual {
   262  				t.Errorf("Expected %t. Actual %t", testCase.injectable, actual)
   263  			}
   264  
   265  			if len(reasons) != len(testCase.reasons) {
   266  				t.Errorf("Expected %d number of reasons. Actual %d", len(testCase.reasons), len(reasons))
   267  			}
   268  
   269  			for i := range reasons {
   270  				if testCase.reasons[i] != reasons[i] {
   271  					t.Errorf("Expected reason '%s'. Actual reason '%s'", testCase.reasons[i], reasons[i])
   272  				}
   273  			}
   274  
   275  		})
   276  	}
   277  }
   278  
   279  func TestDisableByAnnotation(t *testing.T) {
   280  	t.Run("webhook origin", func(t *testing.T) {
   281  		var testCases = []struct {
   282  			podMeta       *metav1.ObjectMeta
   283  			nsAnnotations map[string]string
   284  			expected      bool
   285  		}{
   286  			{
   287  				podMeta: &metav1.ObjectMeta{
   288  					Annotations: map[string]string{
   289  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   290  					},
   291  				},
   292  				expected: false,
   293  			},
   294  			{
   295  				podMeta: &metav1.ObjectMeta{
   296  					Annotations: map[string]string{
   297  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   298  					},
   299  				},
   300  				nsAnnotations: map[string]string{
   301  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   302  				},
   303  				expected: false,
   304  			},
   305  			{
   306  				podMeta: &metav1.ObjectMeta{
   307  					Annotations: map[string]string{
   308  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   309  					},
   310  				},
   311  				nsAnnotations: map[string]string{
   312  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   313  				},
   314  				expected: false,
   315  			},
   316  			{
   317  				podMeta: &metav1.ObjectMeta{},
   318  				nsAnnotations: map[string]string{
   319  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   320  				},
   321  				expected: false,
   322  			},
   323  			{
   324  				podMeta: &metav1.ObjectMeta{
   325  					Annotations: map[string]string{
   326  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   327  					},
   328  				},
   329  				nsAnnotations: map[string]string{
   330  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   331  				},
   332  				expected: true,
   333  			},
   334  			{
   335  				podMeta: &metav1.ObjectMeta{
   336  					Annotations: map[string]string{
   337  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   338  					},
   339  				},
   340  				nsAnnotations: map[string]string{
   341  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   342  				},
   343  				expected: true,
   344  			},
   345  			{
   346  				podMeta: &metav1.ObjectMeta{
   347  					Annotations: map[string]string{
   348  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   349  					},
   350  				},
   351  				nsAnnotations: map[string]string{},
   352  				expected:      true,
   353  			},
   354  			{
   355  				podMeta: &metav1.ObjectMeta{},
   356  				nsAnnotations: map[string]string{
   357  					k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   358  				},
   359  				expected: true,
   360  			},
   361  			{
   362  				podMeta:       &metav1.ObjectMeta{},
   363  				nsAnnotations: map[string]string{},
   364  				expected:      true,
   365  			},
   366  		}
   367  
   368  		for i, testCase := range testCases {
   369  			testCase := testCase
   370  			t.Run(fmt.Sprintf("test case #%d", i), func(t *testing.T) {
   371  				resourceConfig := &ResourceConfig{origin: OriginWebhook}
   372  				resourceConfig.WithNsAnnotations(testCase.nsAnnotations)
   373  				resourceConfig.pod.meta = testCase.podMeta
   374  				resourceConfig.pod.spec = &corev1.PodSpec{} // initialize empty spec to prevent test from failing
   375  
   376  				report := newReport(resourceConfig)
   377  				if actual, _, _ := report.disabledByAnnotation(resourceConfig); testCase.expected != actual {
   378  					t.Errorf("Expected %t. Actual %t", testCase.expected, actual)
   379  				}
   380  			})
   381  		}
   382  	})
   383  
   384  	t.Run("CLI origin", func(t *testing.T) {
   385  		var testCases = []struct {
   386  			podMeta  *metav1.ObjectMeta
   387  			expected bool
   388  		}{
   389  			{
   390  				podMeta:  &metav1.ObjectMeta{},
   391  				expected: false,
   392  			},
   393  			{
   394  				podMeta: &metav1.ObjectMeta{
   395  					Annotations: map[string]string{
   396  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
   397  					},
   398  				},
   399  				expected: false,
   400  			},
   401  			{
   402  				podMeta: &metav1.ObjectMeta{
   403  					Annotations: map[string]string{
   404  						k8s.ProxyInjectAnnotation: k8s.ProxyInjectDisabled,
   405  					},
   406  				},
   407  				expected: true,
   408  			},
   409  		}
   410  
   411  		for i, testCase := range testCases {
   412  			testCase := testCase
   413  			t.Run(fmt.Sprintf("test case #%d", i), func(t *testing.T) {
   414  				resourceConfig := &ResourceConfig{origin: OriginCLI}
   415  				resourceConfig.pod.meta = testCase.podMeta
   416  				resourceConfig.pod.spec = &corev1.PodSpec{} // initialize empty spec to prevent test from failing
   417  
   418  				report := newReport(resourceConfig)
   419  				if actual, _, _ := report.disabledByAnnotation(resourceConfig); testCase.expected != actual {
   420  					t.Errorf("Expected %t. Actual %t", testCase.expected, actual)
   421  				}
   422  			})
   423  		}
   424  	})
   425  }
   426  

View as plain text