...

Source file src/k8s.io/client-go/tools/leaderelection/healthzadaptor_test.go

Documentation: k8s.io/client-go/tools/leaderelection

     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 leaderelection
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  	"time"
    24  
    25  	"net/http"
    26  
    27  	rl "k8s.io/client-go/tools/leaderelection/resourcelock"
    28  	testingclock "k8s.io/utils/clock/testing"
    29  )
    30  
    31  type fakeLock struct {
    32  	identity string
    33  }
    34  
    35  // Get is a dummy to allow us to have a fakeLock for testing.
    36  func (fl *fakeLock) Get(ctx context.Context) (ler *rl.LeaderElectionRecord, rawRecord []byte, err error) {
    37  	return nil, nil, nil
    38  }
    39  
    40  // Create is a dummy to allow us to have a fakeLock for testing.
    41  func (fl *fakeLock) Create(ctx context.Context, ler rl.LeaderElectionRecord) error {
    42  	return nil
    43  }
    44  
    45  // Update is a dummy to allow us to have a fakeLock for testing.
    46  func (fl *fakeLock) Update(ctx context.Context, ler rl.LeaderElectionRecord) error {
    47  	return nil
    48  }
    49  
    50  // RecordEvent is a dummy to allow us to have a fakeLock for testing.
    51  func (fl *fakeLock) RecordEvent(string) {}
    52  
    53  // Identity is a dummy to allow us to have a fakeLock for testing.
    54  func (fl *fakeLock) Identity() string {
    55  	return fl.identity
    56  }
    57  
    58  // Describe is a dummy to allow us to have a fakeLock for testing.
    59  func (fl *fakeLock) Describe() string {
    60  	return "Dummy implementation of lock for testing"
    61  }
    62  
    63  // TestLeaderElectionHealthChecker tests that the healthcheck for leader election handles its edge cases.
    64  func TestLeaderElectionHealthChecker(t *testing.T) {
    65  	current := time.Now()
    66  	req := &http.Request{}
    67  
    68  	tests := []struct {
    69  		description    string
    70  		expected       error
    71  		adaptorTimeout time.Duration
    72  		elector        *LeaderElector
    73  	}{
    74  		{
    75  			description:    "call check before leader elector initialized",
    76  			expected:       nil,
    77  			adaptorTimeout: time.Second * 20,
    78  			elector:        nil,
    79  		},
    80  		{
    81  			description:    "call check when the lease is far expired",
    82  			expected:       fmt.Errorf("failed election to renew leadership on lease %s", "foo"),
    83  			adaptorTimeout: time.Second * 20,
    84  			elector: &LeaderElector{
    85  				config: LeaderElectionConfig{
    86  					Lock:          &fakeLock{identity: "healthTest"},
    87  					LeaseDuration: time.Minute,
    88  					Name:          "foo",
    89  				},
    90  				observedRecord: rl.LeaderElectionRecord{
    91  					HolderIdentity: "healthTest",
    92  				},
    93  				observedTime: current,
    94  				clock:        testingclock.NewFakeClock(current.Add(time.Hour)),
    95  			},
    96  		},
    97  		{
    98  			description:    "call check when the lease is far expired but held by another server",
    99  			expected:       nil,
   100  			adaptorTimeout: time.Second * 20,
   101  			elector: &LeaderElector{
   102  				config: LeaderElectionConfig{
   103  					Lock:          &fakeLock{identity: "healthTest"},
   104  					LeaseDuration: time.Minute,
   105  					Name:          "foo",
   106  				},
   107  				observedRecord: rl.LeaderElectionRecord{
   108  					HolderIdentity: "otherServer",
   109  				},
   110  				observedTime: current,
   111  				clock:        testingclock.NewFakeClock(current.Add(time.Hour)),
   112  			},
   113  		},
   114  		{
   115  			description:    "call check when the lease is not expired",
   116  			expected:       nil,
   117  			adaptorTimeout: time.Second * 20,
   118  			elector: &LeaderElector{
   119  				config: LeaderElectionConfig{
   120  					Lock:          &fakeLock{identity: "healthTest"},
   121  					LeaseDuration: time.Minute,
   122  					Name:          "foo",
   123  				},
   124  				observedRecord: rl.LeaderElectionRecord{
   125  					HolderIdentity: "healthTest",
   126  				},
   127  				observedTime: current,
   128  				clock:        testingclock.NewFakeClock(current),
   129  			},
   130  		},
   131  		{
   132  			description:    "call check when the lease is expired but inside the timeout",
   133  			expected:       nil,
   134  			adaptorTimeout: time.Second * 20,
   135  			elector: &LeaderElector{
   136  				config: LeaderElectionConfig{
   137  					Lock:          &fakeLock{identity: "healthTest"},
   138  					LeaseDuration: time.Minute,
   139  					Name:          "foo",
   140  				},
   141  				observedRecord: rl.LeaderElectionRecord{
   142  					HolderIdentity: "healthTest",
   143  				},
   144  				observedTime: current,
   145  				clock:        testingclock.NewFakeClock(current.Add(time.Minute).Add(time.Second)),
   146  			},
   147  		},
   148  	}
   149  
   150  	for _, test := range tests {
   151  		adaptor := NewLeaderHealthzAdaptor(test.adaptorTimeout)
   152  		if adaptor.le != nil {
   153  			t.Errorf("[%s] leaderChecker started with a LeaderElector %v", test.description, adaptor.le)
   154  		}
   155  		if test.elector != nil {
   156  			test.elector.config.WatchDog = adaptor
   157  			adaptor.SetLeaderElection(test.elector)
   158  			if adaptor.le == nil {
   159  				t.Errorf("[%s] adaptor failed to set the LeaderElector", test.description)
   160  			}
   161  		}
   162  		err := adaptor.Check(req)
   163  		if test.expected == nil {
   164  			if err == nil {
   165  				continue
   166  			}
   167  			t.Errorf("[%s] called check, expected no error but received \"%v\"", test.description, err)
   168  		} else {
   169  			if err == nil {
   170  				t.Errorf("[%s] called check and failed to received the expected error \"%v\"", test.description, test.expected)
   171  			}
   172  			if err.Error() != test.expected.Error() {
   173  				t.Errorf("[%s] called check, expected %v, received %v", test.description, test.expected, err)
   174  			}
   175  		}
   176  	}
   177  }
   178  

View as plain text