This adds the v1 lease controller

This refactors the v1 lease controller. It makes two functional differences
to the lease controller:
* It no longer ties lease updates to node pings or node status updates
* There is no fallback mechanism to status updates

This also moves vk_envtest, allowing for future brown-box testing of the
lease controller with envtest
This commit is contained in:
Sargun Dhillon
2020-12-07 10:37:17 -08:00
parent 8affa1c42a
commit 735eb34829
10 changed files with 525 additions and 366 deletions

View File

@@ -21,10 +21,11 @@ import (
"testing"
"time"
coordinationv1 "k8s.io/api/coordination/v1"
"gotest.tools/assert"
"gotest.tools/assert/cmp"
is "gotest.tools/assert/cmp"
coord "k8s.io/api/coordination/v1beta1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -47,7 +48,7 @@ func testNodeRun(t *testing.T, enableLease bool) {
testP := &testNodeProvider{NodeProvider: &NaiveNodeProvider{}}
nodes := c.CoreV1().Nodes()
leases := c.CoordinationV1beta1().Leases(corev1.NamespaceNodeLease)
leases := c.CoordinationV1().Leases(corev1.NamespaceNodeLease)
interval := 1 * time.Millisecond
opts := []NodeControllerOpt{
@@ -55,7 +56,7 @@ func testNodeRun(t *testing.T, enableLease bool) {
WithNodeStatusUpdateInterval(interval),
}
if enableLease {
opts = append(opts, WithNodeEnableLeaseV1Beta1(leases, nil))
opts = append(opts, WithNodeEnableLeaseV1WithRenewInterval(leases, 40, interval))
}
testNode := testNode(t)
// We have to refer to testNodeCopy during the course of the test. testNode is modified by the node controller
@@ -84,7 +85,7 @@ func testNodeRun(t *testing.T, enableLease bool) {
lr := lw.ResultChan()
var (
lBefore *coord.Lease
lBefore *coordinationv1.Lease
nodeUpdates int
leaseUpdates int
@@ -94,7 +95,7 @@ func testNodeRun(t *testing.T, enableLease bool) {
timeout := time.After(30 * time.Second)
for i := 0; i < iters; i++ {
var l *coord.Lease
var l *coordinationv1.Lease
select {
case <-timeout:
@@ -108,7 +109,7 @@ func testNodeRun(t *testing.T, enableLease bool) {
nodeUpdates++
continue
case le := <-lr:
l = le.Object.(*coord.Lease)
l = le.Object.(*coordinationv1.Lease)
leaseUpdates++
assert.Assert(t, cmp.Equal(l.Spec.HolderIdentity != nil, true))
@@ -224,23 +225,6 @@ func TestNodeCustomUpdateStatusErrorHandler(t *testing.T) {
}
}
func TestEnsureLease(t *testing.T) {
c := testclient.NewSimpleClientset().CoordinationV1beta1().Leases(corev1.NamespaceNodeLease)
n := testNode(t)
ctx := context.Background()
lease := newLease(ctx, nil, n, 1*time.Second)
l1, err := ensureLease(ctx, c, lease.DeepCopy())
assert.NilError(t, err)
assert.Check(t, timeEqual(l1.Spec.RenewTime.Time, lease.Spec.RenewTime.Time))
l1.Spec.RenewTime.Time = time.Now().Add(1 * time.Second)
l2, err := ensureLease(ctx, c, l1.DeepCopy())
assert.NilError(t, err)
assert.Check(t, timeEqual(l2.Spec.RenewTime.Time, l1.Spec.RenewTime.Time))
}
func TestUpdateNodeStatus(t *testing.T) {
n := testNode(t)
n.Status.Conditions = append(n.Status.Conditions, corev1.NodeCondition{
@@ -277,53 +261,6 @@ func TestUpdateNodeStatus(t *testing.T) {
assert.Equal(t, errors.IsNotFound(err), true, err)
}
func TestUpdateNodeLease(t *testing.T) {
ctx := context.Background()
leases := testclient.NewSimpleClientset().CoordinationV1beta1().Leases(corev1.NamespaceNodeLease)
n := testNode(t)
lease := newLease(ctx, nil, n, time.Duration(0))
l, err := updateNodeLease(ctx, leases, lease)
assert.NilError(t, err)
assert.Equal(t, l.Name, lease.Name)
assert.Assert(t, cmp.DeepEqual(l.Spec.HolderIdentity, lease.Spec.HolderIdentity))
compare, err := leases.Get(ctx, l.Name, emptyGetOptions)
assert.NilError(t, err)
assert.Equal(t, l.Spec.RenewTime.Time.Unix(), compare.Spec.RenewTime.Time.Unix())
assert.Equal(t, compare.Name, lease.Name)
assert.Assert(t, cmp.DeepEqual(compare.Spec.HolderIdentity, lease.Spec.HolderIdentity))
l.Spec.RenewTime.Time = time.Now().Add(10 * time.Second)
compare, err = updateNodeLease(ctx, leases, l.DeepCopy())
assert.NilError(t, err)
assert.Equal(t, compare.Spec.RenewTime.Time.Unix(), l.Spec.RenewTime.Time.Unix())
assert.Equal(t, compare.Name, lease.Name)
assert.Assert(t, cmp.DeepEqual(compare.Spec.HolderIdentity, lease.Spec.HolderIdentity))
}
func TestFixNodeLeaseReferences(t *testing.T) {
ctx := context.Background()
n := testNode(t)
lease1 := newLease(ctx, nil, n, time.Second)
// Let's break owner references
lease1.OwnerReferences = nil
time.Sleep(2 * time.Nanosecond)
lease2 := newLease(ctx, lease1, n, time.Second)
// Make sure that newLease actually did its jobs
assert.Assert(t, lease2.Spec.RenewTime.Nanosecond() > lease1.Spec.RenewTime.Nanosecond())
// Let's check if owner references got set
assert.Assert(t, is.Len(lease2.OwnerReferences, 1))
assert.Assert(t, is.Equal(lease2.OwnerReferences[0].UID, n.UID))
assert.Assert(t, is.Equal(lease2.OwnerReferences[0].Name, n.Name))
}
// TestPingAfterStatusUpdate checks that Ping continues to be called with the specified interval
// after a node status update occurs, when leases are disabled.
//
@@ -672,7 +609,7 @@ func TestNodePingSingleInflight(t *testing.T) {
assert.NilError(t, err)
start := time.Now()
go node.nodePingController.run(ctx)
go node.nodePingController.Run(ctx)
firstPing, err := node.nodePingController.getResult(ctx)
assert.NilError(t, err)
timeTakenToCompleteFirstPing := time.Since(start)
@@ -773,15 +710,6 @@ func before(x, y time.Time) cmp.Comparison {
}
}
func timeEqual(x, y time.Time) cmp.Comparison {
return func() cmp.Result {
if x.Equal(y) {
return cmp.ResultSuccess
}
return cmp.ResultFailureTemplate(failTemplate("!="), map[string]interface{}{"x": x, "y": y})
}
}
// waitForEvent waits for the `check` function to return true
// `check` is run when an event is received
// Cancelling the context will cancel the wait, with the context error sent on