...

Source file src/k8s.io/kubernetes/pkg/kubelet/cloudresource/cloud_request_manager_test.go

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

     1  /*
     2  Copyright 2018 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 cloudresource
    18  
    19  import (
    20  	"errors"
    21  	"reflect"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	v1 "k8s.io/api/core/v1"
    27  	"k8s.io/cloud-provider/fake"
    28  )
    29  
    30  func createNodeInternalIPAddress(address string) []v1.NodeAddress {
    31  	return []v1.NodeAddress{
    32  		{
    33  			Type:    v1.NodeInternalIP,
    34  			Address: address,
    35  		},
    36  	}
    37  }
    38  
    39  func TestNodeAddressesDelay(t *testing.T) {
    40  	syncPeriod := 100 * time.Millisecond
    41  	cloud := &fake.Cloud{
    42  		Addresses: createNodeInternalIPAddress("10.0.1.12"),
    43  		// Set the request delay so the manager timeouts and collects the node addresses later
    44  		RequestDelay: 200 * time.Millisecond,
    45  	}
    46  	stopCh := make(chan struct{})
    47  	defer close(stopCh)
    48  
    49  	manager := NewSyncManager(cloud, "defaultNode", syncPeriod).(*cloudResourceSyncManager)
    50  	go manager.Run(stopCh)
    51  
    52  	nodeAddresses, err := manager.NodeAddresses()
    53  	if err != nil {
    54  		t.Errorf("Unexpected err: %q\n", err)
    55  	}
    56  	if !reflect.DeepEqual(nodeAddresses, cloud.Addresses) {
    57  		t.Errorf("Unexpected diff of node addresses: %v", cmp.Diff(nodeAddresses, cloud.Addresses))
    58  	}
    59  
    60  	// Change the IP address
    61  	cloud.SetNodeAddresses(createNodeInternalIPAddress("10.0.1.13"))
    62  
    63  	// Wait until the IP address changes
    64  	maxRetry := 5
    65  	for i := 0; i < maxRetry; i++ {
    66  		nodeAddresses, err := manager.NodeAddresses()
    67  		t.Logf("nodeAddresses: %#v, err: %v", nodeAddresses, err)
    68  		if err != nil {
    69  			t.Errorf("Unexpected err: %q\n", err)
    70  		}
    71  		// It is safe to read cloud.Addresses since no routine is changing the value at the same time
    72  		if err == nil && nodeAddresses[0].Address != cloud.Addresses[0].Address {
    73  			time.Sleep(syncPeriod)
    74  			continue
    75  		}
    76  		if err != nil {
    77  			t.Errorf("Unexpected err: %q\n", err)
    78  		}
    79  		return
    80  	}
    81  	t.Errorf("Timeout waiting for %q address to appear", cloud.Addresses[0].Address)
    82  }
    83  
    84  func TestNodeAddressesUsesLastSuccess(t *testing.T) {
    85  	cloud := &fake.Cloud{}
    86  	manager := NewSyncManager(cloud, "defaultNode", 0).(*cloudResourceSyncManager)
    87  
    88  	// These tests are stateful and order dependent.
    89  	tests := []struct {
    90  		name                   string
    91  		addrs                  []v1.NodeAddress
    92  		err                    error
    93  		wantAddrs              []v1.NodeAddress
    94  		wantErr                bool
    95  		shouldDisableInstances bool
    96  	}{
    97  		{
    98  			name:    "first sync loop encounters an error",
    99  			err:     errors.New("bad"),
   100  			wantErr: true,
   101  		},
   102  		{
   103  			name:                   "failed to get instances from cloud provider",
   104  			err:                    errors.New("failed to get instances from cloud provider"),
   105  			wantErr:                true,
   106  			shouldDisableInstances: true,
   107  		},
   108  		{
   109  			name:      "subsequent sync loop succeeds",
   110  			addrs:     createNodeInternalIPAddress("10.0.1.12"),
   111  			wantAddrs: createNodeInternalIPAddress("10.0.1.12"),
   112  		},
   113  		{
   114  			name:      "subsequent sync loop encounters an error, last addresses returned",
   115  			err:       errors.New("bad"),
   116  			wantAddrs: createNodeInternalIPAddress("10.0.1.12"),
   117  		},
   118  		{
   119  			name:      "subsequent sync loop succeeds changing addresses",
   120  			addrs:     createNodeInternalIPAddress("10.0.1.13"),
   121  			wantAddrs: createNodeInternalIPAddress("10.0.1.13"),
   122  		},
   123  	}
   124  
   125  	for _, test := range tests {
   126  		t.Run(test.name, func(t *testing.T) {
   127  			cloud.Addresses = test.addrs
   128  			cloud.Err = test.err
   129  
   130  			if test.shouldDisableInstances {
   131  				cloud.DisableInstances = true
   132  				defer func() {
   133  					cloud.DisableInstances = false
   134  				}()
   135  			}
   136  
   137  			manager.syncNodeAddresses()
   138  			nodeAddresses, err := manager.NodeAddresses()
   139  			if (err != nil) != test.wantErr {
   140  				t.Errorf("unexpected err: %v", err)
   141  			}
   142  			if got, want := nodeAddresses, test.wantAddrs; !reflect.DeepEqual(got, want) {
   143  				t.Errorf("Unexpected diff of node addresses: %v", cmp.Diff(got, want))
   144  			}
   145  		})
   146  	}
   147  }
   148  

View as plain text