istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/kube/inject/app_probe_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //	http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package inject
    15  
    16  import (
    17  	"reflect"
    18  	"testing"
    19  
    20  	corev1 "k8s.io/api/core/v1"
    21  	"k8s.io/apimachinery/pkg/util/intstr"
    22  
    23  	"istio.io/api/annotation"
    24  	"istio.io/istio/pkg/test"
    25  	"istio.io/istio/pkg/test/util/assert"
    26  )
    27  
    28  func TestFindSidecar(t *testing.T) {
    29  	proxy := corev1.Container{Name: "istio-proxy"}
    30  	app := corev1.Container{Name: "app"}
    31  	for _, tc := range []struct {
    32  		name       string
    33  		containers *corev1.Pod
    34  		want       *corev1.Container
    35  	}{
    36  		{
    37  			name:       "only-sidecar",
    38  			containers: &corev1.Pod{Spec: corev1.PodSpec{Containers: []corev1.Container{proxy}}},
    39  			want:       &proxy,
    40  		},
    41  		{
    42  			name:       "app-and-sidecar",
    43  			containers: &corev1.Pod{Spec: corev1.PodSpec{Containers: []corev1.Container{app, proxy}}},
    44  			want:       &proxy,
    45  		},
    46  		{
    47  			name:       "no-sidecar",
    48  			containers: &corev1.Pod{Spec: corev1.PodSpec{Containers: []corev1.Container{app}}},
    49  			want:       nil,
    50  		},
    51  		{
    52  			name:       "init-sidecar",
    53  			containers: &corev1.Pod{Spec: corev1.PodSpec{InitContainers: []corev1.Container{proxy}, Containers: []corev1.Container{app}}},
    54  			want:       &proxy,
    55  		},
    56  	} {
    57  		t.Run(tc.name, func(t *testing.T) {
    58  			assert.Equal(t, FindSidecar(tc.containers), tc.want)
    59  		})
    60  	}
    61  }
    62  
    63  func TestShouldRewriteAppHTTPProbers(t *testing.T) {
    64  	for _, tc := range []struct {
    65  		name        string
    66  		specSetting bool
    67  		annotations map[string]string
    68  		expected    bool
    69  	}{
    70  		{
    71  			name:        "RewriteAppHTTPProbe-set-in-annotations",
    72  			specSetting: false,
    73  			annotations: nil,
    74  			expected:    false,
    75  		},
    76  		{
    77  			name:        "RewriteAppHTTPProbe-set-in-annotations",
    78  			specSetting: true,
    79  			annotations: nil,
    80  			expected:    true,
    81  		},
    82  		{
    83  			name:        "RewriteAppHTTPProbe-set-in-sidecar-injection-spec",
    84  			specSetting: false,
    85  			annotations: map[string]string{},
    86  			expected:    false,
    87  		},
    88  		{
    89  			name:        "RewriteAppHTTPProbe-set-in-sidecar-injection-spec",
    90  			specSetting: true,
    91  			annotations: map[string]string{},
    92  			expected:    true,
    93  		},
    94  		{
    95  			name:        "RewriteAppHTTPProbe-set-in-annotations",
    96  			specSetting: false,
    97  			annotations: map[string]string{annotation.SidecarRewriteAppHTTPProbers.Name: "true"},
    98  			expected:    true,
    99  		},
   100  		{
   101  			name:        "RewriteAppHTTPProbe-set-in-sidecar-injection-spec-&-annotations",
   102  			specSetting: true,
   103  			annotations: map[string]string{annotation.SidecarRewriteAppHTTPProbers.Name: "true"},
   104  			expected:    true,
   105  		},
   106  		{
   107  			name:        "RewriteAppHTTPProbe-set-in-annotations",
   108  			specSetting: false,
   109  			annotations: map[string]string{annotation.SidecarRewriteAppHTTPProbers.Name: "false"},
   110  			expected:    false,
   111  		},
   112  		{
   113  			name:        "RewriteAppHTTPProbe-set-in-sidecar-injection-spec-&-annotations",
   114  			specSetting: true,
   115  			annotations: map[string]string{annotation.SidecarRewriteAppHTTPProbers.Name: "false"},
   116  			expected:    false,
   117  		},
   118  	} {
   119  		got := ShouldRewriteAppHTTPProbers(tc.annotations, tc.specSetting)
   120  		want := tc.expected
   121  		if got != want {
   122  			t.Errorf("[%v] failed, want %v, got %v", tc.name, want, got)
   123  		}
   124  	}
   125  }
   126  
   127  func TestDumpAppGRPCProbers(t *testing.T) {
   128  	svc := "foo"
   129  	for _, tc := range []struct {
   130  		name     string
   131  		pod      *corev1.Pod
   132  		expected string
   133  	}{
   134  		{
   135  			name: "simple gRPC liveness probe",
   136  			pod: &corev1.Pod{Spec: corev1.PodSpec{
   137  				Containers: []corev1.Container{
   138  					{
   139  						Name: "foo",
   140  						LivenessProbe: &corev1.Probe{
   141  							ProbeHandler: corev1.ProbeHandler{
   142  								GRPC: &corev1.GRPCAction{
   143  									Port: 1234,
   144  								},
   145  							},
   146  						},
   147  					},
   148  				},
   149  			}},
   150  			expected: `
   151  {
   152      "/app-health/foo/livez": {
   153          "grpc": {
   154              "port": 1234,
   155              "service": null
   156          }
   157      }
   158  }`,
   159  		},
   160  		{
   161  			name: "gRPC readiness probe with service",
   162  			pod: &corev1.Pod{Spec: corev1.PodSpec{
   163  				Containers: []corev1.Container{
   164  					{
   165  						Name: "bar",
   166  						ReadinessProbe: &corev1.Probe{
   167  							ProbeHandler: corev1.ProbeHandler{
   168  								GRPC: &corev1.GRPCAction{
   169  									Port:    1234,
   170  									Service: &svc,
   171  								},
   172  							},
   173  						},
   174  					},
   175  				},
   176  			}},
   177  			expected: `
   178  {
   179      "/app-health/bar/readyz": {
   180          "grpc": {
   181              "port": 1234,
   182              "service": "foo"
   183          }
   184      }
   185  }`,
   186  		},
   187  		{
   188  			name: "gRPC startup probe with service and timeout",
   189  			pod: &corev1.Pod{Spec: corev1.PodSpec{
   190  				Containers: []corev1.Container{
   191  					{
   192  						Name: "foo",
   193  						StartupProbe: &corev1.Probe{
   194  							ProbeHandler: corev1.ProbeHandler{
   195  								GRPC: &corev1.GRPCAction{
   196  									Port:    1234,
   197  									Service: &svc,
   198  								},
   199  							},
   200  							TimeoutSeconds: 10,
   201  						},
   202  					},
   203  				},
   204  			}},
   205  			expected: `
   206  {
   207      "/app-health/foo/startupz": {
   208          "grpc": {
   209              "port": 1234,
   210              "service": "foo"
   211          },
   212          "timeoutSeconds": 10
   213      }
   214  }`,
   215  		},
   216  	} {
   217  		got := DumpAppProbers(tc.pod, 15020)
   218  		test.JSONEquals(t, got, tc.expected)
   219  	}
   220  }
   221  
   222  func TestPatchRewriteProbe(t *testing.T) {
   223  	svc := "foo"
   224  	annotations := map[string]string{}
   225  	statusPort := intstr.FromInt32(15020)
   226  	for _, tc := range []struct {
   227  		name        string
   228  		pod         *corev1.Pod
   229  		annotations map[string]string
   230  		expected    *corev1.Pod
   231  	}{
   232  		{
   233  			name: "pod with no probes",
   234  			pod: &corev1.Pod{
   235  				Spec: corev1.PodSpec{
   236  					Containers: []corev1.Container{
   237  						{
   238  							Name: "foo",
   239  						},
   240  					},
   241  				},
   242  			},
   243  			expected: &corev1.Pod{
   244  				Spec: corev1.PodSpec{
   245  					Containers: []corev1.Container{
   246  						{
   247  							Name: "foo",
   248  						},
   249  					},
   250  				},
   251  			},
   252  		},
   253  		{
   254  			name: "pod with a gRPC liveness probe",
   255  			pod: &corev1.Pod{
   256  				Spec: corev1.PodSpec{
   257  					Containers: []corev1.Container{
   258  						{
   259  							Name: "foo",
   260  							LivenessProbe: &corev1.Probe{
   261  								ProbeHandler: corev1.ProbeHandler{
   262  									GRPC: &corev1.GRPCAction{
   263  										Port: 1234,
   264  									},
   265  								},
   266  							},
   267  						},
   268  					},
   269  				},
   270  			},
   271  			expected: &corev1.Pod{
   272  				Spec: corev1.PodSpec{
   273  					Containers: []corev1.Container{
   274  						{
   275  							Name: "foo",
   276  							LivenessProbe: &corev1.Probe{
   277  								ProbeHandler: corev1.ProbeHandler{
   278  									HTTPGet: &corev1.HTTPGetAction{
   279  										Path: "/app-health/foo/livez",
   280  										Port: statusPort,
   281  									},
   282  								},
   283  							},
   284  						},
   285  					},
   286  				},
   287  			},
   288  		},
   289  		{
   290  			name: "pod with gRPC liveness,readiness,startup probes",
   291  			pod: &corev1.Pod{
   292  				Spec: corev1.PodSpec{
   293  					Containers: []corev1.Container{
   294  						{
   295  							Name: "foo",
   296  							LivenessProbe: &corev1.Probe{
   297  								ProbeHandler: corev1.ProbeHandler{
   298  									GRPC: &corev1.GRPCAction{
   299  										Port:    1234,
   300  										Service: &svc,
   301  									},
   302  								},
   303  							},
   304  							ReadinessProbe: &corev1.Probe{
   305  								ProbeHandler: corev1.ProbeHandler{
   306  									GRPC: &corev1.GRPCAction{
   307  										Port:    1235,
   308  										Service: &svc,
   309  									},
   310  								},
   311  								TimeoutSeconds: 10,
   312  							},
   313  						},
   314  						{
   315  							Name: "bar",
   316  							StartupProbe: &corev1.Probe{
   317  								ProbeHandler: corev1.ProbeHandler{
   318  									GRPC: &corev1.GRPCAction{
   319  										Port: 1236,
   320  									},
   321  								},
   322  								TimeoutSeconds:      20,
   323  								PeriodSeconds:       10,
   324  								InitialDelaySeconds: 10,
   325  							},
   326  						},
   327  					},
   328  				},
   329  			},
   330  			expected: &corev1.Pod{
   331  				Spec: corev1.PodSpec{
   332  					Containers: []corev1.Container{
   333  						{
   334  							Name: "foo",
   335  							LivenessProbe: &corev1.Probe{
   336  								ProbeHandler: corev1.ProbeHandler{
   337  									HTTPGet: &corev1.HTTPGetAction{
   338  										Path: "/app-health/foo/livez",
   339  										Port: statusPort,
   340  									},
   341  								},
   342  							},
   343  							ReadinessProbe: &corev1.Probe{
   344  								ProbeHandler: corev1.ProbeHandler{
   345  									HTTPGet: &corev1.HTTPGetAction{
   346  										Path: "/app-health/foo/readyz",
   347  										Port: statusPort,
   348  									},
   349  								},
   350  								TimeoutSeconds: 10,
   351  							},
   352  						},
   353  						{
   354  							Name: "bar",
   355  							StartupProbe: &corev1.Probe{
   356  								ProbeHandler: corev1.ProbeHandler{
   357  									HTTPGet: &corev1.HTTPGetAction{
   358  										Path: "/app-health/bar/startupz",
   359  										Port: statusPort,
   360  									},
   361  								},
   362  								TimeoutSeconds:      20,
   363  								PeriodSeconds:       10,
   364  								InitialDelaySeconds: 10,
   365  							},
   366  						},
   367  					},
   368  				},
   369  			},
   370  		},
   371  	} {
   372  		patchRewriteProbe(annotations, tc.pod, 15020)
   373  		if !reflect.DeepEqual(tc.pod, tc.expected) {
   374  			t.Errorf("[%v] failed, want %v, got %v", tc.name, tc.expected, tc.pod)
   375  		}
   376  	}
   377  }