...

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

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

     1  package inject
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/go-test/deep"
     7  	l5dcharts "github.com/linkerd/linkerd2/pkg/charts/linkerd2"
     8  	"github.com/linkerd/linkerd2/pkg/k8s"
     9  	"github.com/linkerd/linkerd2/pkg/util"
    10  	"github.com/linkerd/linkerd2/pkg/version"
    11  	appsv1 "k8s.io/api/apps/v1"
    12  	corev1 "k8s.io/api/core/v1"
    13  	k8sResource "k8s.io/apimachinery/pkg/api/resource"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"sigs.k8s.io/yaml"
    16  )
    17  
    18  func TestGetOverriddenValues(t *testing.T) {
    19  	// this test uses an annotated deployment and a expected Values object to verify
    20  	// the GetOverriddenValues function.
    21  
    22  	var (
    23  		proxyVersionOverride = "proxy-version-override"
    24  		pullPolicy           = "Always"
    25  	)
    26  
    27  	testConfig, err := l5dcharts.NewValues()
    28  	if err != nil {
    29  		t.Fatalf("Unexpected error: %v", err)
    30  	}
    31  
    32  	var testCases = []struct {
    33  		id            string
    34  		nsAnnotations map[string]string
    35  		spec          appsv1.DeploymentSpec
    36  		expected      func() *l5dcharts.Values
    37  	}{
    38  		{id: "use overrides",
    39  			nsAnnotations: make(map[string]string),
    40  			spec: appsv1.DeploymentSpec{
    41  				Template: corev1.PodTemplateSpec{
    42  					ObjectMeta: metav1.ObjectMeta{
    43  						Annotations: map[string]string{
    44  							k8s.ProxyImageAnnotation:                         "cr.l5d.io/linkerd/proxy",
    45  							k8s.ProxyImagePullPolicyAnnotation:               pullPolicy,
    46  							k8s.ProxyInitImageAnnotation:                     "cr.l5d.io/linkerd/proxy-init",
    47  							k8s.ProxyControlPortAnnotation:                   "4000",
    48  							k8s.ProxyInboundPortAnnotation:                   "5000",
    49  							k8s.ProxyAdminPortAnnotation:                     "5001",
    50  							k8s.ProxyOutboundPortAnnotation:                  "5002",
    51  							k8s.ProxyPodInboundPortsAnnotation:               "1234,5678",
    52  							k8s.ProxyIgnoreInboundPortsAnnotation:            "4222,6222",
    53  							k8s.ProxyIgnoreOutboundPortsAnnotation:           "8079,8080",
    54  							k8s.ProxyCPURequestAnnotation:                    "0.15",
    55  							k8s.ProxyMemoryRequestAnnotation:                 "120",
    56  							k8s.ProxyEphemeralStorageRequestAnnotation:       "10",
    57  							k8s.ProxyCPULimitAnnotation:                      "1.5",
    58  							k8s.ProxyMemoryLimitAnnotation:                   "256",
    59  							k8s.ProxyEphemeralStorageLimitAnnotation:         "50",
    60  							k8s.ProxyUIDAnnotation:                           "8500",
    61  							k8s.ProxyGIDAnnotation:                           "8500",
    62  							k8s.ProxyLogLevelAnnotation:                      "debug,linkerd=debug",
    63  							k8s.ProxyLogFormatAnnotation:                     "json",
    64  							k8s.ProxyEnableExternalProfilesAnnotation:        "false",
    65  							k8s.ProxyVersionOverrideAnnotation:               proxyVersionOverride,
    66  							k8s.ProxyWaitBeforeExitSecondsAnnotation:         "123",
    67  							k8s.ProxyRequireIdentityOnInboundPortsAnnotation: "8888,9999",
    68  							k8s.ProxyOutboundConnectTimeout:                  "6000ms",
    69  							k8s.ProxyInboundConnectTimeout:                   "600ms",
    70  							k8s.ProxyOpaquePortsAnnotation:                   "4320-4325,3306",
    71  							k8s.ProxyAwait:                                   "enabled",
    72  							k8s.ProxySkipSubnetsAnnotation:                   "172.17.0.0/16",
    73  							k8s.ProxyAccessLogAnnotation:                     "apache",
    74  							k8s.ProxyShutdownGracePeriodAnnotation:           "30s",
    75  							k8s.ProxyOutboundDiscoveryCacheUnusedTimeout:     "50000ms",
    76  							k8s.ProxyInboundDiscoveryCacheUnusedTimeout:      "900s",
    77  							k8s.ProxyDisableOutboundProtocolDetectTimeout:    "true",
    78  							k8s.ProxyDisableInboundProtocolDetectTimeout:     "true",
    79  							k8s.ProxyEnableNativeSidecarAnnotation:           "true",
    80  						},
    81  					},
    82  					Spec: corev1.PodSpec{},
    83  				},
    84  			},
    85  			expected: func() *l5dcharts.Values {
    86  				values, _ := l5dcharts.NewValues()
    87  
    88  				values.Proxy.Cores = 2
    89  				values.Proxy.Image.Name = "cr.l5d.io/linkerd/proxy"
    90  				values.Proxy.Image.PullPolicy = pullPolicy
    91  				values.Proxy.Image.Version = proxyVersionOverride
    92  				values.Proxy.PodInboundPorts = "1234,5678"
    93  				values.Proxy.Ports.Control = 4000
    94  				values.Proxy.Ports.Inbound = 5000
    95  				values.Proxy.Ports.Admin = 5001
    96  				values.Proxy.Ports.Outbound = 5002
    97  				values.Proxy.WaitBeforeExitSeconds = 123
    98  				values.Proxy.LogLevel = "debug,linkerd=debug"
    99  				values.Proxy.LogFormat = "json"
   100  				values.Proxy.Resources = &l5dcharts.Resources{
   101  					CPU: l5dcharts.Constraints{
   102  						Limit:   "1.5",
   103  						Request: "0.15",
   104  					},
   105  					Memory: l5dcharts.Constraints{
   106  						Limit:   "256",
   107  						Request: "120",
   108  					},
   109  					EphemeralStorage: l5dcharts.Constraints{
   110  						Limit:   "50",
   111  						Request: "10",
   112  					},
   113  				}
   114  				values.Proxy.UID = 8500
   115  				values.Proxy.GID = 8500
   116  				values.ProxyInit.Image.Name = "cr.l5d.io/linkerd/proxy-init"
   117  				values.ProxyInit.Image.PullPolicy = pullPolicy
   118  				values.ProxyInit.Image.Version = version.ProxyInitVersion
   119  				values.ProxyInit.IgnoreInboundPorts = "4222,6222"
   120  				values.ProxyInit.IgnoreOutboundPorts = "8079,8080"
   121  				values.ProxyInit.SkipSubnets = "172.17.0.0/16"
   122  				values.Proxy.RequireIdentityOnInboundPorts = "8888,9999"
   123  				values.Proxy.OutboundConnectTimeout = "6000ms"
   124  				values.Proxy.InboundConnectTimeout = "600ms"
   125  				values.Proxy.OpaquePorts = "4320-4325,3306"
   126  				values.Proxy.Await = true
   127  				values.Proxy.AccessLog = "apache"
   128  				values.Proxy.ShutdownGracePeriod = "30000ms"
   129  				values.Proxy.OutboundDiscoveryCacheUnusedTimeout = "50s"
   130  				values.Proxy.InboundDiscoveryCacheUnusedTimeout = "900s"
   131  				values.Proxy.DisableOutboundProtocolDetectTimeout = true
   132  				values.Proxy.DisableInboundProtocolDetectTimeout = true
   133  				values.Proxy.NativeSidecar = true
   134  				return values
   135  			},
   136  		},
   137  		{id: "use defaults",
   138  			nsAnnotations: make(map[string]string),
   139  			spec: appsv1.DeploymentSpec{
   140  				Template: corev1.PodTemplateSpec{
   141  					ObjectMeta: metav1.ObjectMeta{},
   142  					Spec:       corev1.PodSpec{},
   143  				},
   144  			},
   145  			expected: func() *l5dcharts.Values {
   146  				values, _ := l5dcharts.NewValues()
   147  				return values
   148  			},
   149  		},
   150  		{id: "use namespace overrides",
   151  			nsAnnotations: map[string]string{
   152  				k8s.ProxyImageAnnotation:                      "cr.l5d.io/linkerd/proxy",
   153  				k8s.ProxyImagePullPolicyAnnotation:            pullPolicy,
   154  				k8s.ProxyInitImageAnnotation:                  "cr.l5d.io/linkerd/proxy-init",
   155  				k8s.ProxyControlPortAnnotation:                "4000",
   156  				k8s.ProxyInboundPortAnnotation:                "5000",
   157  				k8s.ProxyAdminPortAnnotation:                  "5001",
   158  				k8s.ProxyOutboundPortAnnotation:               "5002",
   159  				k8s.ProxyPodInboundPortsAnnotation:            "1234,5678",
   160  				k8s.ProxyIgnoreInboundPortsAnnotation:         "4222,6222",
   161  				k8s.ProxyIgnoreOutboundPortsAnnotation:        "8079,8080",
   162  				k8s.ProxyCPURequestAnnotation:                 "0.15",
   163  				k8s.ProxyMemoryRequestAnnotation:              "120",
   164  				k8s.ProxyCPULimitAnnotation:                   "1.5",
   165  				k8s.ProxyMemoryLimitAnnotation:                "256",
   166  				k8s.ProxyUIDAnnotation:                        "8500",
   167  				k8s.ProxyGIDAnnotation:                        "8500",
   168  				k8s.ProxyLogLevelAnnotation:                   "debug,linkerd=debug",
   169  				k8s.ProxyLogFormatAnnotation:                  "json",
   170  				k8s.ProxyEnableExternalProfilesAnnotation:     "false",
   171  				k8s.ProxyVersionOverrideAnnotation:            proxyVersionOverride,
   172  				k8s.ProxyWaitBeforeExitSecondsAnnotation:      "123",
   173  				k8s.ProxyOutboundConnectTimeout:               "6000ms",
   174  				k8s.ProxyInboundConnectTimeout:                "600ms",
   175  				k8s.ProxyOpaquePortsAnnotation:                "4320-4325,3306",
   176  				k8s.ProxyAwait:                                "enabled",
   177  				k8s.ProxyAccessLogAnnotation:                  "apache",
   178  				k8s.ProxyInjectAnnotation:                     "ingress",
   179  				k8s.ProxyOutboundDiscoveryCacheUnusedTimeout:  "50s",
   180  				k8s.ProxyInboundDiscoveryCacheUnusedTimeout:   "6000ms",
   181  				k8s.ProxyDisableOutboundProtocolDetectTimeout: "true",
   182  				k8s.ProxyDisableInboundProtocolDetectTimeout:  "false",
   183  				k8s.ProxyEnableNativeSidecarAnnotation:        "true",
   184  			},
   185  			spec: appsv1.DeploymentSpec{
   186  				Template: corev1.PodTemplateSpec{
   187  					Spec: corev1.PodSpec{},
   188  				},
   189  			},
   190  			expected: func() *l5dcharts.Values {
   191  				values, _ := l5dcharts.NewValues()
   192  
   193  				values.Proxy.Cores = 2
   194  				values.Proxy.Image.Name = "cr.l5d.io/linkerd/proxy"
   195  				values.Proxy.Image.PullPolicy = pullPolicy
   196  				values.Proxy.Image.Version = proxyVersionOverride
   197  				values.Proxy.PodInboundPorts = "1234,5678"
   198  				values.Proxy.Ports.Control = 4000
   199  				values.Proxy.Ports.Inbound = 5000
   200  				values.Proxy.Ports.Admin = 5001
   201  				values.Proxy.Ports.Outbound = 5002
   202  				values.Proxy.WaitBeforeExitSeconds = 123
   203  				values.Proxy.LogLevel = "debug,linkerd=debug"
   204  				values.Proxy.LogFormat = "json"
   205  				values.Proxy.Resources = &l5dcharts.Resources{
   206  					CPU: l5dcharts.Constraints{
   207  						Limit:   "1.5",
   208  						Request: "0.15",
   209  					},
   210  					Memory: l5dcharts.Constraints{
   211  						Limit:   "256",
   212  						Request: "120",
   213  					},
   214  				}
   215  				values.Proxy.UID = 8500
   216  				values.Proxy.GID = 8500
   217  				values.ProxyInit.Image.Name = "cr.l5d.io/linkerd/proxy-init"
   218  				values.ProxyInit.Image.PullPolicy = pullPolicy
   219  				values.ProxyInit.Image.Version = version.ProxyInitVersion
   220  				values.ProxyInit.IgnoreInboundPorts = "4222,6222"
   221  				values.ProxyInit.IgnoreOutboundPorts = "8079,8080"
   222  				values.Proxy.OutboundConnectTimeout = "6000ms"
   223  				values.Proxy.InboundConnectTimeout = "600ms"
   224  				values.Proxy.OpaquePorts = "4320-4325,3306"
   225  				values.Proxy.Await = true
   226  				values.Proxy.AccessLog = "apache"
   227  				values.Proxy.IsIngress = true
   228  				values.Proxy.OutboundDiscoveryCacheUnusedTimeout = "50s"
   229  				values.Proxy.InboundDiscoveryCacheUnusedTimeout = "6s"
   230  				values.Proxy.DisableOutboundProtocolDetectTimeout = true
   231  				values.Proxy.DisableInboundProtocolDetectTimeout = false
   232  				values.Proxy.NativeSidecar = true
   233  				return values
   234  			},
   235  		},
   236  		{id: "use invalid duration for proxy timeouts",
   237  			nsAnnotations: map[string]string{
   238  				k8s.ProxyOutboundConnectTimeout:               "6000",
   239  				k8s.ProxyInboundConnectTimeout:                "600",
   240  				k8s.ProxyOutboundDiscoveryCacheUnusedTimeout:  "50",
   241  				k8s.ProxyInboundDiscoveryCacheUnusedTimeout:   "5000",
   242  				k8s.ProxyDisableOutboundProtocolDetectTimeout: "9000",
   243  				k8s.ProxyDisableInboundProtocolDetectTimeout:  "9",
   244  			},
   245  			spec: appsv1.DeploymentSpec{
   246  				Template: corev1.PodTemplateSpec{
   247  					ObjectMeta: metav1.ObjectMeta{},
   248  					Spec:       corev1.PodSpec{},
   249  				},
   250  			},
   251  			expected: func() *l5dcharts.Values {
   252  				values, _ := l5dcharts.NewValues()
   253  				return values
   254  			},
   255  		},
   256  		{id: "use valid duration for proxy timeouts",
   257  			nsAnnotations: map[string]string{
   258  				// Validate we're converting time values into ms for the proxy to parse correctly.
   259  				k8s.ProxyOutboundConnectTimeout:               "6s5ms",
   260  				k8s.ProxyInboundConnectTimeout:                "2s5ms",
   261  				k8s.ProxyOutboundDiscoveryCacheUnusedTimeout:  "6s5000ms",
   262  				k8s.ProxyInboundDiscoveryCacheUnusedTimeout:   "6s5000ms",
   263  				k8s.ProxyDisableOutboundProtocolDetectTimeout: "false",
   264  				k8s.ProxyDisableInboundProtocolDetectTimeout:  "true",
   265  			},
   266  			spec: appsv1.DeploymentSpec{
   267  				Template: corev1.PodTemplateSpec{
   268  					ObjectMeta: metav1.ObjectMeta{},
   269  					Spec:       corev1.PodSpec{},
   270  				},
   271  			},
   272  			expected: func() *l5dcharts.Values {
   273  				values, _ := l5dcharts.NewValues()
   274  				values.Proxy.OutboundConnectTimeout = "6005ms"
   275  				values.Proxy.InboundConnectTimeout = "2005ms"
   276  				values.Proxy.OutboundDiscoveryCacheUnusedTimeout = "11s"
   277  				values.Proxy.InboundDiscoveryCacheUnusedTimeout = "11s"
   278  				values.Proxy.DisableOutboundProtocolDetectTimeout = false
   279  				values.Proxy.DisableInboundProtocolDetectTimeout = true
   280  				return values
   281  			},
   282  		},
   283  		{id: "use named port for opaque ports",
   284  			nsAnnotations: make(map[string]string),
   285  			spec: appsv1.DeploymentSpec{
   286  				Template: corev1.PodTemplateSpec{
   287  					ObjectMeta: metav1.ObjectMeta{
   288  						Annotations: map[string]string{
   289  							k8s.ProxyOpaquePortsAnnotation: "mysql",
   290  						},
   291  					},
   292  					Spec: corev1.PodSpec{
   293  						Containers: []corev1.Container{
   294  							{
   295  								Ports: []corev1.ContainerPort{
   296  									{
   297  										Name:          "mysql",
   298  										ContainerPort: 3306,
   299  									},
   300  								},
   301  							},
   302  						},
   303  					},
   304  				},
   305  			},
   306  			expected: func() *l5dcharts.Values {
   307  				values, _ := l5dcharts.NewValues()
   308  				values.Proxy.OpaquePorts = "3306"
   309  				return values
   310  			},
   311  		},
   312  	}
   313  
   314  	for _, tc := range testCases {
   315  		testCase := tc
   316  		t.Run(testCase.id, func(t *testing.T) {
   317  			data, err := yaml.Marshal(&appsv1.Deployment{Spec: testCase.spec})
   318  			if err != nil {
   319  				t.Fatal(err)
   320  			}
   321  
   322  			resourceConfig := NewResourceConfig(testConfig, OriginUnknown, "linkerd").
   323  				WithKind("Deployment").WithNsAnnotations(testCase.nsAnnotations)
   324  			if err := resourceConfig.parse(data); err != nil {
   325  				t.Fatal(err)
   326  			}
   327  
   328  			AppendNamespaceAnnotations(resourceConfig.GetOverrideAnnotations(), resourceConfig.GetNsAnnotations(), resourceConfig.GetWorkloadAnnotations())
   329  			actual, err := GetOverriddenValues(
   330  				resourceConfig.values,
   331  				resourceConfig.getAnnotationOverrides(),
   332  				util.GetNamedPorts(resourceConfig.pod.spec.Containers),
   333  			)
   334  			if err != nil {
   335  				t.Fatal(err)
   336  			}
   337  			expected := testCase.expected()
   338  			if diff := deep.Equal(actual, expected); diff != nil {
   339  				t.Errorf("%+v", diff)
   340  			}
   341  		})
   342  	}
   343  }
   344  
   345  func TestWholeCPUCores(t *testing.T) {
   346  	for _, c := range []struct {
   347  		v string
   348  		n int
   349  	}{
   350  		{v: "1", n: 1},
   351  		{v: "1m", n: 1},
   352  		{v: "1000m", n: 1},
   353  		{v: "1001m", n: 2},
   354  	} {
   355  		q, err := k8sResource.ParseQuantity(c.v)
   356  		if err != nil {
   357  			t.Fatal(err)
   358  		}
   359  		n, err := ToWholeCPUCores(q)
   360  		if err != nil {
   361  			t.Fatal(err)
   362  		}
   363  		if n != int64(c.n) {
   364  			t.Fatalf("Unexpected value: %v != %v", n, c.n)
   365  		}
   366  	}
   367  }
   368  

View as plain text