go.etcd.io/etcd@v3.3.27+incompatible/integration/v3_lease_test.go (about) 1 // Copyright 2016 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package integration 16 17 import ( 18 "context" 19 "fmt" 20 "testing" 21 "time" 22 23 "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" 24 pb "github.com/coreos/etcd/etcdserver/etcdserverpb" 25 "github.com/coreos/etcd/mvcc/mvccpb" 26 "github.com/coreos/etcd/pkg/testutil" 27 28 "google.golang.org/grpc/metadata" 29 ) 30 31 // TestV3LeasePrmote ensures the newly elected leader can promote itself 32 // to the primary lessor, refresh the leases and start to manage leases. 33 // TODO: use customized clock to make this test go faster? 34 func TestV3LeasePrmote(t *testing.T) { 35 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 36 defer clus.Terminate(t) 37 38 // create lease 39 lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 3}) 40 ttl := time.Duration(lresp.TTL) * time.Second 41 afterGrant := time.Now() 42 if err != nil { 43 t.Fatal(err) 44 } 45 if lresp.Error != "" { 46 t.Fatal(lresp.Error) 47 } 48 49 // wait until the lease is going to expire. 50 time.Sleep(time.Until(afterGrant.Add(ttl - time.Second))) 51 52 // kill the current leader, all leases should be refreshed. 53 toStop := clus.waitLeader(t, clus.Members) 54 beforeStop := time.Now() 55 clus.Members[toStop].Stop(t) 56 57 var toWait []*member 58 for i, m := range clus.Members { 59 if i != toStop { 60 toWait = append(toWait, m) 61 } 62 } 63 clus.waitLeader(t, toWait) 64 clus.Members[toStop].Restart(t) 65 clus.waitLeader(t, clus.Members) 66 afterReelect := time.Now() 67 68 // ensure lease is refreshed by waiting for a "long" time. 69 // it was going to expire anyway. 70 time.Sleep(time.Until(beforeStop.Add(ttl - time.Second))) 71 72 if !leaseExist(t, clus, lresp.ID) { 73 t.Error("unexpected lease not exists") 74 } 75 76 // wait until the renewed lease is expected to expire. 77 time.Sleep(time.Until(afterReelect.Add(ttl))) 78 79 // wait for up to 10 seconds for lease to expire. 80 expiredCondition := func() (bool, error) { 81 return !leaseExist(t, clus, lresp.ID), nil 82 } 83 expired, err := testutil.Poll(100*time.Millisecond, 10*time.Second, expiredCondition) 84 if err != nil { 85 t.Error(err) 86 } 87 88 if !expired { 89 t.Error("unexpected lease exists") 90 } 91 } 92 93 // TestV3LeaseRevoke ensures a key is deleted once its lease is revoked. 94 func TestV3LeaseRevoke(t *testing.T) { 95 defer testutil.AfterTest(t) 96 testLeaseRemoveLeasedKey(t, func(clus *ClusterV3, leaseID int64) error { 97 lc := toGRPC(clus.RandClient()).Lease 98 _, err := lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseID}) 99 return err 100 }) 101 } 102 103 // TestV3LeaseGrantById ensures leases may be created by a given id. 104 func TestV3LeaseGrantByID(t *testing.T) { 105 defer testutil.AfterTest(t) 106 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 107 defer clus.Terminate(t) 108 109 // create fixed lease 110 lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant( 111 context.TODO(), 112 &pb.LeaseGrantRequest{ID: 1, TTL: 1}) 113 if err != nil { 114 t.Errorf("could not create lease 1 (%v)", err) 115 } 116 if lresp.ID != 1 { 117 t.Errorf("got id %v, wanted id %v", lresp.ID, 1) 118 } 119 120 // create duplicate fixed lease 121 _, err = toGRPC(clus.RandClient()).Lease.LeaseGrant( 122 context.TODO(), 123 &pb.LeaseGrantRequest{ID: 1, TTL: 1}) 124 if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseExist) { 125 t.Error(err) 126 } 127 128 // create fresh fixed lease 129 lresp, err = toGRPC(clus.RandClient()).Lease.LeaseGrant( 130 context.TODO(), 131 &pb.LeaseGrantRequest{ID: 2, TTL: 1}) 132 if err != nil { 133 t.Errorf("could not create lease 2 (%v)", err) 134 } 135 if lresp.ID != 2 { 136 t.Errorf("got id %v, wanted id %v", lresp.ID, 2) 137 } 138 } 139 140 // TestV3LeaseExpire ensures a key is deleted once a key expires. 141 func TestV3LeaseExpire(t *testing.T) { 142 defer testutil.AfterTest(t) 143 testLeaseRemoveLeasedKey(t, func(clus *ClusterV3, leaseID int64) error { 144 // let lease lapse; wait for deleted key 145 146 ctx, cancel := context.WithCancel(context.Background()) 147 defer cancel() 148 wStream, err := toGRPC(clus.RandClient()).Watch.Watch(ctx) 149 if err != nil { 150 return err 151 } 152 153 wreq := &pb.WatchRequest{RequestUnion: &pb.WatchRequest_CreateRequest{ 154 CreateRequest: &pb.WatchCreateRequest{ 155 Key: []byte("foo"), StartRevision: 1}}} 156 if err := wStream.Send(wreq); err != nil { 157 return err 158 } 159 if _, err := wStream.Recv(); err != nil { 160 // the 'created' message 161 return err 162 } 163 if _, err := wStream.Recv(); err != nil { 164 // the 'put' message 165 return err 166 } 167 168 errc := make(chan error, 1) 169 go func() { 170 resp, err := wStream.Recv() 171 switch { 172 case err != nil: 173 errc <- err 174 case len(resp.Events) != 1: 175 fallthrough 176 case resp.Events[0].Type != mvccpb.DELETE: 177 errc <- fmt.Errorf("expected key delete, got %v", resp) 178 default: 179 errc <- nil 180 } 181 }() 182 183 select { 184 case <-time.After(15 * time.Second): 185 return fmt.Errorf("lease expiration too slow") 186 case err := <-errc: 187 return err 188 } 189 }) 190 } 191 192 // TestV3LeaseKeepAlive ensures keepalive keeps the lease alive. 193 func TestV3LeaseKeepAlive(t *testing.T) { 194 defer testutil.AfterTest(t) 195 testLeaseRemoveLeasedKey(t, func(clus *ClusterV3, leaseID int64) error { 196 lc := toGRPC(clus.RandClient()).Lease 197 lreq := &pb.LeaseKeepAliveRequest{ID: leaseID} 198 ctx, cancel := context.WithCancel(context.Background()) 199 defer cancel() 200 lac, err := lc.LeaseKeepAlive(ctx) 201 if err != nil { 202 return err 203 } 204 defer lac.CloseSend() 205 206 // renew long enough so lease would've expired otherwise 207 for i := 0; i < 3; i++ { 208 if err = lac.Send(lreq); err != nil { 209 return err 210 } 211 lresp, rxerr := lac.Recv() 212 if rxerr != nil { 213 return rxerr 214 } 215 if lresp.ID != leaseID { 216 return fmt.Errorf("expected lease ID %v, got %v", leaseID, lresp.ID) 217 } 218 time.Sleep(time.Duration(lresp.TTL/2) * time.Second) 219 } 220 _, err = lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseID}) 221 return err 222 }) 223 } 224 225 // TestV3LeaseExists creates a lease on a random client and confirms it exists in the cluster. 226 func TestV3LeaseExists(t *testing.T) { 227 defer testutil.AfterTest(t) 228 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 229 defer clus.Terminate(t) 230 231 // create lease 232 ctx0, cancel0 := context.WithCancel(context.Background()) 233 defer cancel0() 234 lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant( 235 ctx0, 236 &pb.LeaseGrantRequest{TTL: 30}) 237 if err != nil { 238 t.Fatal(err) 239 } 240 if lresp.Error != "" { 241 t.Fatal(lresp.Error) 242 } 243 244 if !leaseExist(t, clus, lresp.ID) { 245 t.Error("unexpected lease not exists") 246 } 247 } 248 249 // TestV3LeaseLeases creates leases and confirms list RPC fetches created ones. 250 func TestV3LeaseLeases(t *testing.T) { 251 defer testutil.AfterTest(t) 252 clus := NewClusterV3(t, &ClusterConfig{Size: 1}) 253 defer clus.Terminate(t) 254 255 ctx0, cancel0 := context.WithCancel(context.Background()) 256 defer cancel0() 257 258 // create leases 259 ids := []int64{} 260 for i := 0; i < 5; i++ { 261 lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant( 262 ctx0, 263 &pb.LeaseGrantRequest{TTL: 30}) 264 if err != nil { 265 t.Fatal(err) 266 } 267 if lresp.Error != "" { 268 t.Fatal(lresp.Error) 269 } 270 ids = append(ids, lresp.ID) 271 } 272 273 lresp, err := toGRPC(clus.RandClient()).Lease.LeaseLeases( 274 context.Background(), 275 &pb.LeaseLeasesRequest{}) 276 if err != nil { 277 t.Fatal(err) 278 } 279 for i := range lresp.Leases { 280 if lresp.Leases[i].ID != ids[i] { 281 t.Fatalf("#%d: lease ID expected %d, got %d", i, ids[i], lresp.Leases[i].ID) 282 } 283 } 284 } 285 286 // TestV3LeaseRenewStress keeps creating lease and renewing it immediately to ensure the renewal goes through. 287 // it was oberserved that the immediate lease renewal after granting a lease from follower resulted lease not found. 288 // related issue https://github.com/coreos/etcd/issues/6978 289 func TestV3LeaseRenewStress(t *testing.T) { 290 testLeaseStress(t, stressLeaseRenew) 291 } 292 293 // TestV3LeaseTimeToLiveStress keeps creating lease and retrieving it immediately to ensure the lease can be retrieved. 294 // it was oberserved that the immediate lease retrieval after granting a lease from follower resulted lease not found. 295 // related issue https://github.com/coreos/etcd/issues/6978 296 func TestV3LeaseTimeToLiveStress(t *testing.T) { 297 testLeaseStress(t, stressLeaseTimeToLive) 298 } 299 300 func testLeaseStress(t *testing.T, stresser func(context.Context, pb.LeaseClient) error) { 301 defer testutil.AfterTest(t) 302 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 303 defer clus.Terminate(t) 304 305 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 306 defer cancel() 307 errc := make(chan error) 308 309 for i := 0; i < 30; i++ { 310 for j := 0; j < 3; j++ { 311 go func(i int) { errc <- stresser(ctx, toGRPC(clus.Client(i)).Lease) }(j) 312 } 313 } 314 315 for i := 0; i < 90; i++ { 316 if err := <-errc; err != nil { 317 t.Fatal(err) 318 } 319 } 320 } 321 322 func stressLeaseRenew(tctx context.Context, lc pb.LeaseClient) (reterr error) { 323 defer func() { 324 if tctx.Err() != nil { 325 reterr = nil 326 } 327 }() 328 lac, err := lc.LeaseKeepAlive(tctx) 329 if err != nil { 330 return err 331 } 332 for tctx.Err() == nil { 333 resp, gerr := lc.LeaseGrant(tctx, &pb.LeaseGrantRequest{TTL: 60}) 334 if gerr != nil { 335 continue 336 } 337 err = lac.Send(&pb.LeaseKeepAliveRequest{ID: resp.ID}) 338 if err != nil { 339 continue 340 } 341 rresp, rxerr := lac.Recv() 342 if rxerr != nil { 343 continue 344 } 345 if rresp.TTL == 0 { 346 return fmt.Errorf("TTL shouldn't be 0 so soon") 347 } 348 } 349 return nil 350 } 351 352 func stressLeaseTimeToLive(tctx context.Context, lc pb.LeaseClient) (reterr error) { 353 defer func() { 354 if tctx.Err() != nil { 355 reterr = nil 356 } 357 }() 358 for tctx.Err() == nil { 359 resp, gerr := lc.LeaseGrant(tctx, &pb.LeaseGrantRequest{TTL: 60}) 360 if gerr != nil { 361 continue 362 } 363 _, kerr := lc.LeaseTimeToLive(tctx, &pb.LeaseTimeToLiveRequest{ID: resp.ID}) 364 if rpctypes.Error(kerr) == rpctypes.ErrLeaseNotFound { 365 return kerr 366 } 367 } 368 return nil 369 } 370 371 func TestV3PutOnNonExistLease(t *testing.T) { 372 defer testutil.AfterTest(t) 373 clus := NewClusterV3(t, &ClusterConfig{Size: 1}) 374 defer clus.Terminate(t) 375 376 ctx, cancel := context.WithCancel(context.Background()) 377 defer cancel() 378 379 badLeaseID := int64(0x12345678) 380 putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: badLeaseID} 381 _, err := toGRPC(clus.RandClient()).KV.Put(ctx, putr) 382 if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseNotFound) { 383 t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCLeaseNotFound) 384 } 385 } 386 387 // TestV3GetNonExistLease ensures client retrieving nonexistent lease on a follower doesn't result node panic 388 // related issue https://github.com/coreos/etcd/issues/6537 389 func TestV3GetNonExistLease(t *testing.T) { 390 defer testutil.AfterTest(t) 391 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 392 defer clus.Terminate(t) 393 394 ctx, cancel := context.WithCancel(context.Background()) 395 defer cancel() 396 lc := toGRPC(clus.RandClient()).Lease 397 lresp, err := lc.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: 10}) 398 if err != nil { 399 t.Errorf("failed to create lease %v", err) 400 } 401 _, err = lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID}) 402 if err != nil { 403 t.Fatal(err) 404 } 405 406 leaseTTLr := &pb.LeaseTimeToLiveRequest{ 407 ID: lresp.ID, 408 Keys: true, 409 } 410 411 for _, client := range clus.clients { 412 // quorum-read to ensure revoke completes before TimeToLive 413 if _, err := toGRPC(client).KV.Range(ctx, &pb.RangeRequest{Key: []byte("_")}); err != nil { 414 t.Fatal(err) 415 } 416 resp, err := toGRPC(client).Lease.LeaseTimeToLive(ctx, leaseTTLr) 417 if err != nil { 418 t.Fatalf("expected non nil error, but go %v", err) 419 } 420 if resp.TTL != -1 { 421 t.Fatalf("expected TTL to be -1, but got %v", resp.TTL) 422 } 423 } 424 } 425 426 // TestV3LeaseSwitch tests a key can be switched from one lease to another. 427 func TestV3LeaseSwitch(t *testing.T) { 428 defer testutil.AfterTest(t) 429 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 430 defer clus.Terminate(t) 431 432 key := "foo" 433 434 // create lease 435 ctx, cancel := context.WithCancel(context.Background()) 436 defer cancel() 437 lresp1, err1 := toGRPC(clus.RandClient()).Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: 30}) 438 if err1 != nil { 439 t.Fatal(err1) 440 } 441 lresp2, err2 := toGRPC(clus.RandClient()).Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: 30}) 442 if err2 != nil { 443 t.Fatal(err2) 444 } 445 446 // attach key on lease1 then switch it to lease2 447 put1 := &pb.PutRequest{Key: []byte(key), Lease: lresp1.ID} 448 _, err := toGRPC(clus.RandClient()).KV.Put(ctx, put1) 449 if err != nil { 450 t.Fatal(err) 451 } 452 put2 := &pb.PutRequest{Key: []byte(key), Lease: lresp2.ID} 453 _, err = toGRPC(clus.RandClient()).KV.Put(ctx, put2) 454 if err != nil { 455 t.Fatal(err) 456 } 457 458 // revoke lease1 should not remove key 459 _, err = toGRPC(clus.RandClient()).Lease.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: lresp1.ID}) 460 if err != nil { 461 t.Fatal(err) 462 } 463 rreq := &pb.RangeRequest{Key: []byte("foo")} 464 rresp, err := toGRPC(clus.RandClient()).KV.Range(context.TODO(), rreq) 465 if err != nil { 466 t.Fatal(err) 467 } 468 if len(rresp.Kvs) != 1 { 469 t.Fatalf("unexpect removal of key") 470 } 471 472 // revoke lease2 should remove key 473 _, err = toGRPC(clus.RandClient()).Lease.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: lresp2.ID}) 474 if err != nil { 475 t.Fatal(err) 476 } 477 rresp, err = toGRPC(clus.RandClient()).KV.Range(context.TODO(), rreq) 478 if err != nil { 479 t.Fatal(err) 480 } 481 if len(rresp.Kvs) != 0 { 482 t.Fatalf("lease removed but key remains") 483 } 484 } 485 486 // TestV3LeaseFailover ensures the old leader drops lease keepalive requests within 487 // election timeout after it loses its quorum. And the new leader extends the TTL of 488 // the lease to at least TTL + election timeout. 489 func TestV3LeaseFailover(t *testing.T) { 490 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 491 defer clus.Terminate(t) 492 493 toIsolate := clus.waitLeader(t, clus.Members) 494 495 lc := toGRPC(clus.Client(toIsolate)).Lease 496 497 // create lease 498 lresp, err := lc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 5}) 499 if err != nil { 500 t.Fatal(err) 501 } 502 if lresp.Error != "" { 503 t.Fatal(lresp.Error) 504 } 505 506 // isolate the current leader with its followers. 507 clus.Members[toIsolate].Pause() 508 509 lreq := &pb.LeaseKeepAliveRequest{ID: lresp.ID} 510 511 md := metadata.Pairs(rpctypes.MetadataRequireLeaderKey, rpctypes.MetadataHasLeader) 512 mctx := metadata.NewOutgoingContext(context.Background(), md) 513 ctx, cancel := context.WithCancel(mctx) 514 lac, err := lc.LeaseKeepAlive(ctx) 515 if err != nil { 516 t.Fatal(err) 517 } 518 defer func() { 519 lac.CloseSend() 520 cancel() 521 }() 522 523 // send keep alive to old leader until the old leader starts 524 // to drop lease request. 525 var expectedExp time.Time 526 for { 527 if err = lac.Send(lreq); err != nil { 528 break 529 } 530 lkresp, rxerr := lac.Recv() 531 if rxerr != nil { 532 break 533 } 534 expectedExp = time.Now().Add(time.Duration(lkresp.TTL) * time.Second) 535 time.Sleep(time.Duration(lkresp.TTL/2) * time.Second) 536 } 537 538 clus.Members[toIsolate].Resume() 539 clus.waitLeader(t, clus.Members) 540 541 // lease should not expire at the last received expire deadline. 542 time.Sleep(time.Until(expectedExp) - 500*time.Millisecond) 543 544 if !leaseExist(t, clus, lresp.ID) { 545 t.Error("unexpected lease not exists") 546 } 547 } 548 549 // TestV3LeaseRequireLeader ensures that a Recv will get a leader 550 // loss error if there is no leader. 551 func TestV3LeaseRequireLeader(t *testing.T) { 552 defer testutil.AfterTest(t) 553 554 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 555 defer clus.Terminate(t) 556 557 lc := toGRPC(clus.Client(0)).Lease 558 clus.Members[1].Stop(t) 559 clus.Members[2].Stop(t) 560 561 md := metadata.Pairs(rpctypes.MetadataRequireLeaderKey, rpctypes.MetadataHasLeader) 562 mctx := metadata.NewOutgoingContext(context.Background(), md) 563 ctx, cancel := context.WithCancel(mctx) 564 defer cancel() 565 lac, err := lc.LeaseKeepAlive(ctx) 566 if err != nil { 567 t.Fatal(err) 568 } 569 570 donec := make(chan struct{}) 571 go func() { 572 defer close(donec) 573 resp, err := lac.Recv() 574 if err == nil { 575 t.Fatalf("got response %+v, expected error", resp) 576 } 577 if rpctypes.ErrorDesc(err) != rpctypes.ErrNoLeader.Error() { 578 t.Errorf("err = %v, want %v", err, rpctypes.ErrNoLeader) 579 } 580 }() 581 select { 582 case <-time.After(5 * time.Second): 583 t.Fatal("did not receive leader loss error (in 5-sec)") 584 case <-donec: 585 } 586 } 587 588 const fiveMinTTL int64 = 300 589 590 // TestV3LeaseRecoverAndRevoke ensures that revoking a lease after restart deletes the attached key. 591 func TestV3LeaseRecoverAndRevoke(t *testing.T) { 592 clus := NewClusterV3(t, &ClusterConfig{Size: 1}) 593 defer clus.Terminate(t) 594 595 kvc := toGRPC(clus.Client(0)).KV 596 lsc := toGRPC(clus.Client(0)).Lease 597 598 lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL}) 599 if err != nil { 600 t.Fatal(err) 601 } 602 if lresp.Error != "" { 603 t.Fatal(lresp.Error) 604 } 605 _, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID}) 606 if err != nil { 607 t.Fatal(err) 608 } 609 610 // restart server and ensure lease still exists 611 clus.Members[0].Stop(t) 612 clus.Members[0].Restart(t) 613 clus.waitLeader(t, clus.Members) 614 615 // overwrite old client with newly dialed connection 616 // otherwise, error with "grpc: RPC failed fast due to transport failure" 617 nc, err := NewClientV3(clus.Members[0]) 618 if err != nil { 619 t.Fatal(err) 620 } 621 kvc = toGRPC(nc).KV 622 lsc = toGRPC(nc).Lease 623 defer nc.Close() 624 625 // revoke should delete the key 626 _, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID}) 627 if err != nil { 628 t.Fatal(err) 629 } 630 rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")}) 631 if err != nil { 632 t.Fatal(err) 633 } 634 if len(rresp.Kvs) != 0 { 635 t.Fatalf("lease removed but key remains") 636 } 637 } 638 639 // TestV3LeaseRevokeAndRecover ensures that revoked key stays deleted after restart. 640 func TestV3LeaseRevokeAndRecover(t *testing.T) { 641 clus := NewClusterV3(t, &ClusterConfig{Size: 1}) 642 defer clus.Terminate(t) 643 644 kvc := toGRPC(clus.Client(0)).KV 645 lsc := toGRPC(clus.Client(0)).Lease 646 647 lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL}) 648 if err != nil { 649 t.Fatal(err) 650 } 651 if lresp.Error != "" { 652 t.Fatal(lresp.Error) 653 } 654 _, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID}) 655 if err != nil { 656 t.Fatal(err) 657 } 658 659 // revoke should delete the key 660 _, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID}) 661 if err != nil { 662 t.Fatal(err) 663 } 664 665 // restart server and ensure revoked key doesn't exist 666 clus.Members[0].Stop(t) 667 clus.Members[0].Restart(t) 668 clus.waitLeader(t, clus.Members) 669 670 // overwrite old client with newly dialed connection 671 // otherwise, error with "grpc: RPC failed fast due to transport failure" 672 nc, err := NewClientV3(clus.Members[0]) 673 if err != nil { 674 t.Fatal(err) 675 } 676 kvc = toGRPC(nc).KV 677 defer nc.Close() 678 679 rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")}) 680 if err != nil { 681 t.Fatal(err) 682 } 683 if len(rresp.Kvs) != 0 { 684 t.Fatalf("lease removed but key remains") 685 } 686 } 687 688 // TestV3LeaseRecoverKeyWithDetachedLease ensures that revoking a detached lease after restart 689 // does not delete the key. 690 func TestV3LeaseRecoverKeyWithDetachedLease(t *testing.T) { 691 clus := NewClusterV3(t, &ClusterConfig{Size: 1}) 692 defer clus.Terminate(t) 693 694 kvc := toGRPC(clus.Client(0)).KV 695 lsc := toGRPC(clus.Client(0)).Lease 696 697 lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL}) 698 if err != nil { 699 t.Fatal(err) 700 } 701 if lresp.Error != "" { 702 t.Fatal(lresp.Error) 703 } 704 _, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID}) 705 if err != nil { 706 t.Fatal(err) 707 } 708 709 // overwrite lease with none 710 _, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")}) 711 if err != nil { 712 t.Fatal(err) 713 } 714 715 // restart server and ensure lease still exists 716 clus.Members[0].Stop(t) 717 clus.Members[0].Restart(t) 718 clus.waitLeader(t, clus.Members) 719 720 // overwrite old client with newly dialed connection 721 // otherwise, error with "grpc: RPC failed fast due to transport failure" 722 nc, err := NewClientV3(clus.Members[0]) 723 if err != nil { 724 t.Fatal(err) 725 } 726 kvc = toGRPC(nc).KV 727 lsc = toGRPC(nc).Lease 728 defer nc.Close() 729 730 // revoke the detached lease 731 _, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID}) 732 if err != nil { 733 t.Fatal(err) 734 } 735 rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")}) 736 if err != nil { 737 t.Fatal(err) 738 } 739 if len(rresp.Kvs) != 1 { 740 t.Fatalf("only detached lease removed, key should remain") 741 } 742 } 743 744 func TestV3LeaseRecoverKeyWithMutipleLease(t *testing.T) { 745 clus := NewClusterV3(t, &ClusterConfig{Size: 1}) 746 defer clus.Terminate(t) 747 748 kvc := toGRPC(clus.Client(0)).KV 749 lsc := toGRPC(clus.Client(0)).Lease 750 751 var leaseIDs []int64 752 for i := 0; i < 2; i++ { 753 lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL}) 754 if err != nil { 755 t.Fatal(err) 756 } 757 if lresp.Error != "" { 758 t.Fatal(lresp.Error) 759 } 760 leaseIDs = append(leaseIDs, lresp.ID) 761 762 _, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID}) 763 if err != nil { 764 t.Fatal(err) 765 } 766 } 767 768 // restart server and ensure lease still exists 769 clus.Members[0].Stop(t) 770 clus.Members[0].Restart(t) 771 clus.waitLeader(t, clus.Members) 772 for i, leaseID := range leaseIDs { 773 if !leaseExist(t, clus, leaseID) { 774 t.Errorf("#%d: unexpected lease not exists", i) 775 } 776 } 777 778 // overwrite old client with newly dialed connection 779 // otherwise, error with "grpc: RPC failed fast due to transport failure" 780 nc, err := NewClientV3(clus.Members[0]) 781 if err != nil { 782 t.Fatal(err) 783 } 784 kvc = toGRPC(nc).KV 785 lsc = toGRPC(nc).Lease 786 defer nc.Close() 787 788 // revoke the old lease 789 _, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseIDs[0]}) 790 if err != nil { 791 t.Fatal(err) 792 } 793 // key should still exist 794 rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")}) 795 if err != nil { 796 t.Fatal(err) 797 } 798 if len(rresp.Kvs) != 1 { 799 t.Fatalf("only detached lease removed, key should remain") 800 } 801 802 // revoke the latest lease 803 _, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseIDs[1]}) 804 if err != nil { 805 t.Fatal(err) 806 } 807 rresp, err = kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")}) 808 if err != nil { 809 t.Fatal(err) 810 } 811 if len(rresp.Kvs) != 0 { 812 t.Fatalf("lease removed but key remains") 813 } 814 } 815 816 // acquireLeaseAndKey creates a new lease and creates an attached key. 817 func acquireLeaseAndKey(clus *ClusterV3, key string) (int64, error) { 818 // create lease 819 lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant( 820 context.TODO(), 821 &pb.LeaseGrantRequest{TTL: 1}) 822 if err != nil { 823 return 0, err 824 } 825 if lresp.Error != "" { 826 return 0, fmt.Errorf(lresp.Error) 827 } 828 // attach to key 829 put := &pb.PutRequest{Key: []byte(key), Lease: lresp.ID} 830 if _, err := toGRPC(clus.RandClient()).KV.Put(context.TODO(), put); err != nil { 831 return 0, err 832 } 833 return lresp.ID, nil 834 } 835 836 // testLeaseRemoveLeasedKey performs some action while holding a lease with an 837 // attached key "foo", then confirms the key is gone. 838 func testLeaseRemoveLeasedKey(t *testing.T, act func(*ClusterV3, int64) error) { 839 clus := NewClusterV3(t, &ClusterConfig{Size: 3}) 840 defer clus.Terminate(t) 841 842 leaseID, err := acquireLeaseAndKey(clus, "foo") 843 if err != nil { 844 t.Fatal(err) 845 } 846 847 if err = act(clus, leaseID); err != nil { 848 t.Fatal(err) 849 } 850 851 // confirm no key 852 rreq := &pb.RangeRequest{Key: []byte("foo")} 853 rresp, err := toGRPC(clus.RandClient()).KV.Range(context.TODO(), rreq) 854 if err != nil { 855 t.Fatal(err) 856 } 857 if len(rresp.Kvs) != 0 { 858 t.Fatalf("lease removed but key remains") 859 } 860 } 861 862 func leaseExist(t *testing.T, clus *ClusterV3, leaseID int64) bool { 863 l := toGRPC(clus.RandClient()).Lease 864 865 _, err := l.LeaseGrant(context.Background(), &pb.LeaseGrantRequest{ID: leaseID, TTL: 5}) 866 if err == nil { 867 _, err = l.LeaseRevoke(context.Background(), &pb.LeaseRevokeRequest{ID: leaseID}) 868 if err != nil { 869 t.Fatalf("failed to check lease %v", err) 870 } 871 return false 872 } 873 874 if eqErrGRPC(err, rpctypes.ErrGRPCLeaseExist) { 875 return true 876 } 877 t.Fatalf("unexpecter error %v", err) 878 879 return true 880 }