...

Source file src/k8s.io/kubernetes/pkg/kubelet/pleg/evented_test.go

Documentation: k8s.io/kubernetes/pkg/kubelet/pleg

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package pleg
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  
    29  	"k8s.io/apimachinery/pkg/types"
    30  	"k8s.io/component-base/metrics/testutil"
    31  	v1 "k8s.io/cri-api/pkg/apis/runtime/v1"
    32  	critest "k8s.io/cri-api/pkg/apis/testing"
    33  	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
    34  	containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
    35  	"k8s.io/kubernetes/pkg/kubelet/metrics"
    36  	testingclock "k8s.io/utils/clock/testing"
    37  )
    38  
    39  func newTestEventedPLEG() *EventedPLEG {
    40  	return &EventedPLEG{
    41  		runtime:        &containertest.FakeRuntime{},
    42  		clock:          testingclock.NewFakeClock(time.Time{}),
    43  		cache:          kubecontainer.NewCache(),
    44  		runtimeService: critest.NewFakeRuntimeService(),
    45  		eventChannel:   make(chan *PodLifecycleEvent, 100),
    46  	}
    47  }
    48  
    49  func TestHealthyEventedPLEG(t *testing.T) {
    50  	metrics.Register()
    51  	pleg := newTestEventedPLEG()
    52  
    53  	_, _, events := createTestPodsStatusesAndEvents(100)
    54  	for _, event := range events[:5] {
    55  		pleg.eventChannel <- event
    56  	}
    57  
    58  	// test if healthy when event channel has 5 events
    59  	isHealthy, err := pleg.Healthy()
    60  	require.NoError(t, err)
    61  	assert.Equal(t, true, isHealthy)
    62  
    63  	// send remaining 95 events and make channel out of capacity
    64  	for _, event := range events[5:] {
    65  		pleg.eventChannel <- event
    66  	}
    67  	// pleg is unhealthy when channel is out of capacity
    68  	isHealthy, err = pleg.Healthy()
    69  	require.Error(t, err)
    70  	assert.Equal(t, false, isHealthy)
    71  }
    72  
    73  func TestUpdateRunningPodMetric(t *testing.T) {
    74  	metrics.Register()
    75  	pleg := newTestEventedPLEG()
    76  
    77  	podStatuses := make([]*kubecontainer.PodStatus, 5)
    78  	for i := range podStatuses {
    79  		id := fmt.Sprintf("test-pod-%d", i)
    80  		podStatuses[i] = &kubecontainer.PodStatus{
    81  			ID: types.UID(id),
    82  			SandboxStatuses: []*v1.PodSandboxStatus{
    83  				{Id: id},
    84  			},
    85  			ContainerStatuses: []*kubecontainer.Status{
    86  				{ID: kubecontainer.ContainerID{ID: id}, State: kubecontainer.ContainerStateRunning},
    87  			},
    88  		}
    89  
    90  		pleg.updateRunningPodMetric(podStatuses[i])
    91  		pleg.cache.Set(podStatuses[i].ID, podStatuses[i], nil, time.Now())
    92  
    93  	}
    94  	pleg.cache.UpdateTime(time.Now())
    95  
    96  	expectedMetric := `
    97  # HELP kubelet_running_pods [ALPHA] Number of pods that have a running pod sandbox
    98  # TYPE kubelet_running_pods gauge
    99  kubelet_running_pods 5
   100  `
   101  	testMetric(t, expectedMetric, metrics.RunningPodCount.FQName())
   102  
   103  	// stop sandbox containers for first 2 pods
   104  	for _, podStatus := range podStatuses[:2] {
   105  		podId := string(podStatus.ID)
   106  		newPodStatus := kubecontainer.PodStatus{
   107  			ID: podStatus.ID,
   108  			SandboxStatuses: []*v1.PodSandboxStatus{
   109  				{Id: podId},
   110  			},
   111  			ContainerStatuses: []*kubecontainer.Status{
   112  				// update state to container exited
   113  				{ID: kubecontainer.ContainerID{ID: podId}, State: kubecontainer.ContainerStateExited},
   114  			},
   115  		}
   116  
   117  		pleg.updateRunningPodMetric(&newPodStatus)
   118  		pleg.cache.Set(newPodStatus.ID, &newPodStatus, nil, time.Now())
   119  	}
   120  	pleg.cache.UpdateTime(time.Now())
   121  
   122  	expectedMetric = `
   123  # HELP kubelet_running_pods [ALPHA] Number of pods that have a running pod sandbox
   124  # TYPE kubelet_running_pods gauge
   125  kubelet_running_pods 3
   126  `
   127  	testMetric(t, expectedMetric, metrics.RunningPodCount.FQName())
   128  }
   129  
   130  func testMetric(t *testing.T, expectedMetric string, metricName string) {
   131  	err := testutil.GatherAndCompare(metrics.GetGather(), strings.NewReader(expectedMetric), metricName)
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  }
   136  
   137  func TestEventedPLEG_getPodIPs(t *testing.T) {
   138  	cache := kubecontainer.NewCache()
   139  	type args struct {
   140  		pid    types.UID
   141  		status *kubecontainer.PodStatus
   142  	}
   143  	tests := []struct {
   144  		name      string
   145  		args      args
   146  		oldstatus *kubecontainer.PodStatus
   147  		expected  []string
   148  	}{
   149  		{
   150  			name: "status ips is not empty",
   151  			args: args{
   152  				pid: "62212",
   153  				status: &kubecontainer.PodStatus{
   154  					IPs: []string{"10.0.0.10", "10.23.0.1"},
   155  				},
   156  			},
   157  			oldstatus: &kubecontainer.PodStatus{
   158  				IPs: []string{"192.168.0.10", "192.168.0.1"},
   159  			},
   160  			expected: []string{"10.0.0.10", "10.23.0.1"},
   161  		},
   162  		{
   163  			name: "status ips is empty and SandboxStatuses has PodSandboxState_SANDBOX_READY state",
   164  			args: args{
   165  				pid: "62212",
   166  				status: &kubecontainer.PodStatus{
   167  					SandboxStatuses: []*v1.PodSandboxStatus{
   168  						{
   169  							Id:       "sandboxID2",
   170  							Metadata: &v1.PodSandboxMetadata{Attempt: uint32(1)},
   171  							State:    v1.PodSandboxState_SANDBOX_READY,
   172  						},
   173  						{
   174  							Id:       "sandboxID1",
   175  							Metadata: &v1.PodSandboxMetadata{Attempt: uint32(0)},
   176  							State:    v1.PodSandboxState_SANDBOX_NOTREADY,
   177  						},
   178  					},
   179  				},
   180  			},
   181  			oldstatus: &kubecontainer.PodStatus{
   182  				IPs: []string{"192.168.0.10", "192.168.0.1"},
   183  			},
   184  			expected: nil,
   185  		},
   186  		{
   187  			name: "status and cache ips are empty",
   188  			args: args{
   189  				pid:    "62212",
   190  				status: &kubecontainer.PodStatus{},
   191  			},
   192  			oldstatus: &kubecontainer.PodStatus{
   193  				IPs: []string{},
   194  			},
   195  			expected: nil,
   196  		},
   197  		{
   198  			name: "sandbox state is no PodSandboxState_SANDBOX_READY",
   199  			args: args{
   200  				pid: "62212",
   201  				status: &kubecontainer.PodStatus{
   202  					SandboxStatuses: []*v1.PodSandboxStatus{
   203  						{
   204  							Id:       "sandboxID2",
   205  							Metadata: &v1.PodSandboxMetadata{Attempt: uint32(1)},
   206  							State:    v1.PodSandboxState_SANDBOX_NOTREADY,
   207  						},
   208  						{
   209  							Id:       "sandboxID1",
   210  							Metadata: &v1.PodSandboxMetadata{Attempt: uint32(0)},
   211  							State:    v1.PodSandboxState_SANDBOX_NOTREADY,
   212  						},
   213  					},
   214  				},
   215  			},
   216  			oldstatus: &kubecontainer.PodStatus{
   217  				IPs: []string{"192.168.0.10", "192.168.0.1"},
   218  			},
   219  			expected: []string{"192.168.0.10", "192.168.0.1"},
   220  		},
   221  	}
   222  	for _, test := range tests {
   223  		cache.Set(test.args.pid, test.oldstatus, nil, time.Time{})
   224  		e := &EventedPLEG{
   225  			cache: cache,
   226  		}
   227  		t.Run(test.name, func(t *testing.T) {
   228  			if got := e.getPodIPs(test.args.pid, test.args.status); !reflect.DeepEqual(got, test.expected) {
   229  				t.Errorf("EventedPLEG.getPodIPs() = %v, expected %v", got, test.expected)
   230  			}
   231  		})
   232  	}
   233  }
   234  

View as plain text