...

Source file src/k8s.io/kubernetes/pkg/controller/ttl/ttl_controller_test.go

Documentation: k8s.io/kubernetes/pkg/controller/ttl

     1  /*
     2  Copyright 2017 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 ttl
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"k8s.io/api/core/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/client-go/kubernetes/fake"
    26  	listers "k8s.io/client-go/listers/core/v1"
    27  	core "k8s.io/client-go/testing"
    28  	"k8s.io/client-go/tools/cache"
    29  	"k8s.io/client-go/util/workqueue"
    30  	"k8s.io/klog/v2/ktesting"
    31  
    32  	"github.com/stretchr/testify/assert"
    33  )
    34  
    35  func TestPatchNode(t *testing.T) {
    36  	testCases := []struct {
    37  		node       *v1.Node
    38  		ttlSeconds int
    39  		patch      string
    40  	}{
    41  		{
    42  			node:       &v1.Node{},
    43  			ttlSeconds: 0,
    44  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"0\"}}}",
    45  		},
    46  		{
    47  			node:       &v1.Node{},
    48  			ttlSeconds: 10,
    49  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"10\"}}}",
    50  		},
    51  		{
    52  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "name"}},
    53  			ttlSeconds: 10,
    54  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"10\"}}}",
    55  		},
    56  		{
    57  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{}}},
    58  			ttlSeconds: 10,
    59  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"10\"}}}",
    60  		},
    61  		{
    62  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{"node.alpha.kubernetes.io/ttl": "0"}}},
    63  			ttlSeconds: 10,
    64  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"10\"}}}",
    65  		},
    66  		{
    67  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{"node.alpha.kubernetes.io/ttl": "0", "a": "b"}}},
    68  			ttlSeconds: 10,
    69  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"10\"}}}",
    70  		},
    71  		{
    72  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{"node.alpha.kubernetes.io/ttl": "10", "a": "b"}}},
    73  			ttlSeconds: 10,
    74  			patch:      "{}",
    75  		},
    76  	}
    77  
    78  	for i, testCase := range testCases {
    79  		fakeClient := &fake.Clientset{}
    80  		ttlController := &Controller{
    81  			kubeClient: fakeClient,
    82  		}
    83  		err := ttlController.patchNodeWithAnnotation(context.TODO(), testCase.node, v1.ObjectTTLAnnotationKey, testCase.ttlSeconds)
    84  		if err != nil {
    85  			t.Errorf("%d: unexpected error: %v", i, err)
    86  			continue
    87  		}
    88  		actions := fakeClient.Actions()
    89  		assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions)
    90  		patchAction := actions[0].(core.PatchActionImpl)
    91  		assert.Equal(t, testCase.patch, string(patchAction.Patch), "%d: unexpected patch: %s", i, string(patchAction.Patch))
    92  	}
    93  }
    94  
    95  func TestUpdateNodeIfNeeded(t *testing.T) {
    96  	testCases := []struct {
    97  		node       *v1.Node
    98  		desiredTTL int
    99  		patch      string
   100  	}{
   101  		{
   102  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "name"}},
   103  			desiredTTL: 0,
   104  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"0\"}}}",
   105  		},
   106  		{
   107  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "name"}},
   108  			desiredTTL: 15,
   109  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"15\"}}}",
   110  		},
   111  		{
   112  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "name"}},
   113  			desiredTTL: 30,
   114  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"30\"}}}",
   115  		},
   116  		{
   117  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "name", Annotations: map[string]string{"node.alpha.kubernetes.io/ttl": "0"}}},
   118  			desiredTTL: 60,
   119  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"60\"}}}",
   120  		},
   121  		{
   122  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "name", Annotations: map[string]string{"node.alpha.kubernetes.io/ttl": "60"}}},
   123  			desiredTTL: 60,
   124  			patch:      "",
   125  		},
   126  		{
   127  			node:       &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "name", Annotations: map[string]string{"node.alpha.kubernetes.io/ttl": "60"}}},
   128  			desiredTTL: 30,
   129  			patch:      "{\"metadata\":{\"annotations\":{\"node.alpha.kubernetes.io/ttl\":\"30\"}}}",
   130  		},
   131  	}
   132  
   133  	for i, testCase := range testCases {
   134  		fakeClient := &fake.Clientset{}
   135  		nodeStore := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
   136  		nodeStore.Add(testCase.node)
   137  		ttlController := &Controller{
   138  			kubeClient:        fakeClient,
   139  			nodeStore:         listers.NewNodeLister(nodeStore),
   140  			desiredTTLSeconds: testCase.desiredTTL,
   141  		}
   142  		if err := ttlController.updateNodeIfNeeded(context.TODO(), testCase.node.Name); err != nil {
   143  			t.Errorf("%d: unexpected error: %v", i, err)
   144  			continue
   145  		}
   146  		actions := fakeClient.Actions()
   147  		if testCase.patch == "" {
   148  			assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions)
   149  		} else {
   150  			assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions)
   151  			patchAction := actions[0].(core.PatchActionImpl)
   152  			assert.Equal(t, testCase.patch, string(patchAction.Patch), "%d: unexpected patch: %s", i, string(patchAction.Patch))
   153  		}
   154  	}
   155  }
   156  
   157  func TestDesiredTTL(t *testing.T) {
   158  	testCases := []struct {
   159  		addNode      bool
   160  		deleteNode   bool
   161  		nodeCount    int
   162  		desiredTTL   int
   163  		boundaryStep int
   164  		expectedTTL  int
   165  	}{
   166  		{
   167  			addNode:      true,
   168  			nodeCount:    0,
   169  			desiredTTL:   0,
   170  			boundaryStep: 0,
   171  			expectedTTL:  0,
   172  		},
   173  		{
   174  			addNode:      true,
   175  			nodeCount:    99,
   176  			desiredTTL:   0,
   177  			boundaryStep: 0,
   178  			expectedTTL:  0,
   179  		},
   180  		{
   181  			addNode:      true,
   182  			nodeCount:    100,
   183  			desiredTTL:   0,
   184  			boundaryStep: 0,
   185  			expectedTTL:  15,
   186  		},
   187  		{
   188  			deleteNode:   true,
   189  			nodeCount:    101,
   190  			desiredTTL:   15,
   191  			boundaryStep: 1,
   192  			expectedTTL:  15,
   193  		},
   194  		{
   195  			deleteNode:   true,
   196  			nodeCount:    91,
   197  			desiredTTL:   15,
   198  			boundaryStep: 1,
   199  			expectedTTL:  15,
   200  		},
   201  		{
   202  			addNode:      true,
   203  			nodeCount:    91,
   204  			desiredTTL:   15,
   205  			boundaryStep: 1,
   206  			expectedTTL:  15,
   207  		},
   208  		{
   209  			deleteNode:   true,
   210  			nodeCount:    90,
   211  			desiredTTL:   15,
   212  			boundaryStep: 1,
   213  			expectedTTL:  0,
   214  		},
   215  		{
   216  			deleteNode:   true,
   217  			nodeCount:    1800,
   218  			desiredTTL:   300,
   219  			boundaryStep: 4,
   220  			expectedTTL:  60,
   221  		},
   222  		{
   223  			deleteNode:   true,
   224  			nodeCount:    10000,
   225  			desiredTTL:   300,
   226  			boundaryStep: 4,
   227  			expectedTTL:  300,
   228  		},
   229  	}
   230  
   231  	for i, testCase := range testCases {
   232  		ttlController := &Controller{
   233  			queue:             workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()),
   234  			nodeCount:         testCase.nodeCount,
   235  			desiredTTLSeconds: testCase.desiredTTL,
   236  			boundaryStep:      testCase.boundaryStep,
   237  		}
   238  		if testCase.addNode {
   239  			logger, _ := ktesting.NewTestContext(t)
   240  			ttlController.addNode(logger, &v1.Node{})
   241  		}
   242  		if testCase.deleteNode {
   243  			ttlController.deleteNode(&v1.Node{})
   244  		}
   245  		assert.Equal(t, testCase.expectedTTL, ttlController.getDesiredTTLSeconds(),
   246  			"%d: unexpected ttl: %d", i, ttlController.getDesiredTTLSeconds())
   247  	}
   248  }
   249  

View as plain text