...

Source file src/k8s.io/kubernetes/pkg/controlplane/reconcilers/instancecount_test.go

Documentation: k8s.io/kubernetes/pkg/controlplane/reconcilers

     1  /*
     2  Copyright 2014 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 reconcilers
    18  
    19  import (
    20  	"testing"
    21  
    22  	corev1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/runtime"
    24  	"k8s.io/client-go/kubernetes/fake"
    25  	netutils "k8s.io/utils/net"
    26  )
    27  
    28  func TestMasterCountEndpointReconciler(t *testing.T) {
    29  	reconcileTests := []struct {
    30  		testName          string
    31  		serviceName       string
    32  		ip                string
    33  		endpointPorts     []corev1.EndpointPort
    34  		additionalMasters int
    35  		initialState      []runtime.Object
    36  		expectUpdate      []runtime.Object
    37  		expectCreate      []runtime.Object
    38  	}{
    39  		{
    40  			testName:      "no existing endpoints",
    41  			serviceName:   "foo",
    42  			ip:            "1.2.3.4",
    43  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
    44  			initialState:  nil,
    45  			expectCreate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    46  		},
    47  		{
    48  			testName:      "existing endpoints satisfy",
    49  			serviceName:   "foo",
    50  			ip:            "1.2.3.4",
    51  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
    52  			initialState:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    53  		},
    54  		{
    55  			testName:      "existing endpoints satisfy, no endpointslice",
    56  			serviceName:   "foo",
    57  			ip:            "1.2.3.4",
    58  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
    59  			initialState: []runtime.Object{
    60  				makeEndpoints("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    61  			},
    62  			expectCreate: []runtime.Object{
    63  				makeEndpointSlice("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    64  			},
    65  		},
    66  		{
    67  			testName:      "existing endpointslice satisfies, no endpoints",
    68  			serviceName:   "foo",
    69  			ip:            "1.2.3.4",
    70  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
    71  			initialState: []runtime.Object{
    72  				makeEndpointSlice("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    73  			},
    74  			expectCreate: []runtime.Object{
    75  				makeEndpoints("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    76  			},
    77  		},
    78  		{
    79  			testName:      "existing endpoints satisfy, endpointslice is wrong",
    80  			serviceName:   "foo",
    81  			ip:            "1.2.3.4",
    82  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
    83  			initialState: []runtime.Object{
    84  				makeEndpoints("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    85  				makeEndpointSlice("foo", []string{"4.3.2.1"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    86  			},
    87  			expectUpdate: []runtime.Object{
    88  				makeEndpointSlice("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    89  			},
    90  		},
    91  		{
    92  			testName:      "existing endpointslice satisfies, endpoints is wrong",
    93  			serviceName:   "foo",
    94  			ip:            "1.2.3.4",
    95  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
    96  			initialState: []runtime.Object{
    97  				makeEndpoints("foo", []string{"4.3.2.1"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    98  				makeEndpointSlice("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
    99  			},
   100  			expectUpdate: []runtime.Object{
   101  				makeEndpoints("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   102  			},
   103  		},
   104  		{
   105  			testName:      "existing endpoints satisfy but too many",
   106  			serviceName:   "foo",
   107  			ip:            "1.2.3.4",
   108  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   109  			initialState:  makeEndpointsArray("foo", []string{"1.2.3.4", "4.3.2.1"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   110  			expectUpdate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   111  		},
   112  		{
   113  			testName:          "existing endpoints satisfy but too many + extra masters",
   114  			serviceName:       "foo",
   115  			ip:                "1.2.3.4",
   116  			endpointPorts:     []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   117  			additionalMasters: 3,
   118  			initialState:      makeEndpointsArray("foo", []string{"1.2.3.4", "4.3.2.1", "4.3.2.2", "4.3.2.3", "4.3.2.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   119  			expectUpdate:      makeEndpointsArray("foo", []string{"1.2.3.4", "4.3.2.2", "4.3.2.3", "4.3.2.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   120  		},
   121  		{
   122  			testName:          "existing endpoints satisfy but too many + extra masters + delete first",
   123  			serviceName:       "foo",
   124  			ip:                "4.3.2.4",
   125  			endpointPorts:     []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   126  			additionalMasters: 3,
   127  			initialState:      makeEndpointsArray("foo", []string{"1.2.3.4", "4.3.2.1", "4.3.2.2", "4.3.2.3", "4.3.2.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   128  			expectUpdate:      makeEndpointsArray("foo", []string{"4.3.2.1", "4.3.2.2", "4.3.2.3", "4.3.2.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   129  		},
   130  		{
   131  			testName:          "existing endpoints satisfy and endpoint addresses length less than master count",
   132  			serviceName:       "foo",
   133  			ip:                "4.3.2.2",
   134  			endpointPorts:     []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   135  			additionalMasters: 3,
   136  			initialState:      makeEndpointsArray("foo", []string{"4.3.2.1", "4.3.2.2"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   137  			expectUpdate:      nil,
   138  		},
   139  		{
   140  			testName:          "existing endpoints current IP missing and address length less than master count",
   141  			serviceName:       "foo",
   142  			ip:                "4.3.2.2",
   143  			endpointPorts:     []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   144  			additionalMasters: 3,
   145  			initialState:      makeEndpointsArray("foo", []string{"4.3.2.1"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   146  			expectUpdate:      makeEndpointsArray("foo", []string{"4.3.2.1", "4.3.2.2"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   147  		},
   148  		{
   149  			testName:      "existing endpoints wrong name",
   150  			serviceName:   "foo",
   151  			ip:            "1.2.3.4",
   152  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   153  			initialState:  makeEndpointsArray("bar", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   154  			expectCreate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   155  		},
   156  		{
   157  			testName:      "existing endpoints wrong IP",
   158  			serviceName:   "foo",
   159  			ip:            "1.2.3.4",
   160  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   161  			initialState:  makeEndpointsArray("foo", []string{"4.3.2.1"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   162  			expectUpdate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   163  		},
   164  		{
   165  			testName:      "existing endpoints wrong port",
   166  			serviceName:   "foo",
   167  			ip:            "1.2.3.4",
   168  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   169  			initialState:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 9090, Protocol: "TCP"}}),
   170  			expectUpdate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   171  		},
   172  		{
   173  			testName:      "existing endpoints wrong protocol",
   174  			serviceName:   "foo",
   175  			ip:            "1.2.3.4",
   176  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   177  			initialState:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "UDP"}}),
   178  			expectUpdate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   179  		},
   180  		{
   181  			testName:      "existing endpoints wrong port name",
   182  			serviceName:   "foo",
   183  			ip:            "1.2.3.4",
   184  			endpointPorts: []corev1.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}},
   185  			initialState:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   186  			expectUpdate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}}),
   187  		},
   188  		{
   189  			testName:    "existing endpoints extra service ports satisfy",
   190  			serviceName: "foo",
   191  			ip:          "1.2.3.4",
   192  			endpointPorts: []corev1.EndpointPort{
   193  				{Name: "foo", Port: 8080, Protocol: "TCP"},
   194  				{Name: "bar", Port: 1000, Protocol: "TCP"},
   195  				{Name: "baz", Port: 1010, Protocol: "TCP"},
   196  			},
   197  			initialState: makeEndpointsArray("foo", []string{"1.2.3.4"},
   198  				[]corev1.EndpointPort{
   199  					{Name: "foo", Port: 8080, Protocol: "TCP"},
   200  					{Name: "bar", Port: 1000, Protocol: "TCP"},
   201  					{Name: "baz", Port: 1010, Protocol: "TCP"},
   202  				},
   203  			),
   204  		},
   205  		{
   206  			testName:    "existing endpoints extra service ports missing port",
   207  			serviceName: "foo",
   208  			ip:          "1.2.3.4",
   209  			endpointPorts: []corev1.EndpointPort{
   210  				{Name: "foo", Port: 8080, Protocol: "TCP"},
   211  				{Name: "bar", Port: 1000, Protocol: "TCP"},
   212  			},
   213  			initialState: makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   214  			expectUpdate: makeEndpointsArray("foo", []string{"1.2.3.4"},
   215  				[]corev1.EndpointPort{
   216  					{Name: "foo", Port: 8080, Protocol: "TCP"},
   217  					{Name: "bar", Port: 1000, Protocol: "TCP"},
   218  				},
   219  			),
   220  		},
   221  		{
   222  			testName:      "no existing sctp endpoints",
   223  			serviceName:   "boo",
   224  			ip:            "1.2.3.4",
   225  			endpointPorts: []corev1.EndpointPort{{Name: "boo", Port: 7777, Protocol: "SCTP"}},
   226  			initialState:  nil,
   227  			expectCreate:  makeEndpointsArray("boo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "boo", Port: 7777, Protocol: "SCTP"}}),
   228  		},
   229  	}
   230  	for _, test := range reconcileTests {
   231  		t.Run(test.testName, func(t *testing.T) {
   232  			fakeClient := fake.NewSimpleClientset(test.initialState...)
   233  			epAdapter := NewEndpointsAdapter(fakeClient.CoreV1(), fakeClient.DiscoveryV1())
   234  			reconciler := NewMasterCountEndpointReconciler(test.additionalMasters+1, epAdapter)
   235  			err := reconciler.ReconcileEndpoints(test.serviceName, netutils.ParseIPSloppy(test.ip), test.endpointPorts, true)
   236  			if err != nil {
   237  				t.Errorf("unexpected error reconciling: %v", err)
   238  			}
   239  
   240  			err = verifyCreatesAndUpdates(fakeClient, test.expectCreate, test.expectUpdate)
   241  			if err != nil {
   242  				t.Errorf("unexpected error in side effects: %v", err)
   243  			}
   244  		})
   245  	}
   246  
   247  	nonReconcileTests := []struct {
   248  		testName          string
   249  		serviceName       string
   250  		ip                string
   251  		endpointPorts     []corev1.EndpointPort
   252  		additionalMasters int
   253  		initialState      []runtime.Object
   254  		expectUpdate      []runtime.Object
   255  		expectCreate      []runtime.Object
   256  	}{
   257  		{
   258  			testName:    "existing endpoints extra service ports missing port no update",
   259  			serviceName: "foo",
   260  			ip:          "1.2.3.4",
   261  			endpointPorts: []corev1.EndpointPort{
   262  				{Name: "foo", Port: 8080, Protocol: "TCP"},
   263  				{Name: "bar", Port: 1000, Protocol: "TCP"},
   264  			},
   265  			initialState: makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   266  			expectUpdate: nil,
   267  		},
   268  		{
   269  			testName:    "existing endpoints extra service ports, wrong ports, wrong IP",
   270  			serviceName: "foo",
   271  			ip:          "1.2.3.4",
   272  			endpointPorts: []corev1.EndpointPort{
   273  				{Name: "foo", Port: 8080, Protocol: "TCP"},
   274  				{Name: "bar", Port: 1000, Protocol: "TCP"},
   275  			},
   276  			initialState: makeEndpointsArray("foo", []string{"4.3.2.1"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   277  			expectUpdate: makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   278  		},
   279  		{
   280  			testName:      "no existing endpoints",
   281  			serviceName:   "foo",
   282  			ip:            "1.2.3.4",
   283  			endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
   284  			initialState:  nil,
   285  			expectCreate:  makeEndpointsArray("foo", []string{"1.2.3.4"}, []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}}),
   286  		},
   287  	}
   288  	for _, test := range nonReconcileTests {
   289  		t.Run(test.testName, func(t *testing.T) {
   290  			fakeClient := fake.NewSimpleClientset(test.initialState...)
   291  			epAdapter := NewEndpointsAdapter(fakeClient.CoreV1(), fakeClient.DiscoveryV1())
   292  			reconciler := NewMasterCountEndpointReconciler(test.additionalMasters+1, epAdapter)
   293  			err := reconciler.ReconcileEndpoints(test.serviceName, netutils.ParseIPSloppy(test.ip), test.endpointPorts, false)
   294  			if err != nil {
   295  				t.Errorf("unexpected error reconciling: %v", err)
   296  			}
   297  
   298  			err = verifyCreatesAndUpdates(fakeClient, test.expectCreate, test.expectUpdate)
   299  			if err != nil {
   300  				t.Errorf("unexpected error in side effects: %v", err)
   301  			}
   302  		})
   303  	}
   304  }
   305  
   306  func TestEmptySubsets(t *testing.T) {
   307  	endpoints := makeEndpointsArray("foo", nil, nil)
   308  	fakeClient := fake.NewSimpleClientset(endpoints...)
   309  	epAdapter := NewEndpointsAdapter(fakeClient.CoreV1(), fakeClient.DiscoveryV1())
   310  	reconciler := NewMasterCountEndpointReconciler(1, epAdapter)
   311  	endpointPorts := []corev1.EndpointPort{
   312  		{Name: "foo", Port: 8080, Protocol: "TCP"},
   313  	}
   314  	err := reconciler.RemoveEndpoints("foo", netutils.ParseIPSloppy("1.2.3.4"), endpointPorts)
   315  	if err != nil {
   316  		t.Errorf("unexpected error: %v", err)
   317  	}
   318  }
   319  

View as plain text