// DeleteTablet removes a tablet record from the topology: // - the replication data record if any // - the tablet record func DeleteTablet(ctx context.Context, ts topo.Server, tablet *topodatapb.Tablet) error { // try to remove replication data, no fatal if we fail if err := topo.DeleteTabletReplicationData(ctx, ts, tablet); err != nil { if err == topo.ErrNoNode { log.V(6).Infof("no ShardReplication object for cell %v", tablet.Alias.Cell) err = nil } if err != nil { log.Warningf("remove replication data for %v failed: %v", topoproto.TabletAliasString(tablet.Alias), err) } } // then delete the tablet record return ts.DeleteTablet(ctx, tablet.Alias) }
// CheckTablet verifies the topo server API is correct for managing tablets. func CheckTablet(ctx context.Context, t *testing.T, ts topo.Server) { cell := getLocalCell(ctx, t, ts) tablet := &topo.Tablet{ Alias: topo.TabletAlias{Cell: cell, Uid: 1}, Hostname: "localhost", IPAddr: "10.11.12.13", Portmap: map[string]int{ "vt": 3333, "mysql": 3334, }, Tags: map[string]string{"tag": "value"}, Keyspace: "test_keyspace", Type: topo.TYPE_MASTER, KeyRange: newKeyRange("-10"), } if err := ts.CreateTablet(ctx, tablet); err != nil { t.Errorf("CreateTablet: %v", err) } if err := ts.CreateTablet(ctx, tablet); err != topo.ErrNodeExists { t.Errorf("CreateTablet(again): %v", err) } if _, err := ts.GetTablet(ctx, topo.TabletAlias{Cell: cell, Uid: 666}); err != topo.ErrNoNode { t.Errorf("GetTablet(666): %v", err) } ti, err := ts.GetTablet(ctx, tablet.Alias) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias, err) } if eq, err := tabletEqual(ti.Tablet, tablet); err != nil { t.Errorf("cannot compare tablets: %v", err) } else if !eq { t.Errorf("put and got tablets are not identical:\n%#v\n%#v", tablet, ti.Tablet) } if _, err := ts.GetTabletsByCell(ctx, "666"); err != topo.ErrNoNode { t.Errorf("GetTabletsByCell(666): %v", err) } inCell, err := ts.GetTabletsByCell(ctx, cell) if err != nil { t.Errorf("GetTabletsByCell: %v", err) } if len(inCell) != 1 || inCell[0] != tablet.Alias { t.Errorf("GetTabletsByCell: want [%v], got %v", tablet.Alias, inCell) } ti.Hostname = "remotehost" if err := topo.UpdateTablet(ctx, ts, ti); err != nil { t.Errorf("UpdateTablet: %v", err) } ti, err = ts.GetTablet(ctx, tablet.Alias) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias, err) } if want := "remotehost"; ti.Hostname != want { t.Errorf("ti.Hostname: want %v, got %v", want, ti.Hostname) } if err := topo.UpdateTabletFields(ctx, ts, tablet.Alias, func(t *topo.Tablet) error { t.Hostname = "anotherhost" return nil }); err != nil { t.Errorf("UpdateTabletFields: %v", err) } ti, err = ts.GetTablet(ctx, tablet.Alias) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias, err) } if want := "anotherhost"; ti.Hostname != want { t.Errorf("ti.Hostname: want %v, got %v", want, ti.Hostname) } if err := ts.DeleteTablet(ctx, tablet.Alias); err != nil { t.Errorf("DeleteTablet: %v", err) } if err := ts.DeleteTablet(ctx, tablet.Alias); err != topo.ErrNoNode { t.Errorf("DeleteTablet(again): %v", err) } if _, err := ts.GetTablet(ctx, tablet.Alias); err != topo.ErrNoNode { t.Errorf("GetTablet: expected error, tablet was deleted: %v", err) } }
// TestSuite runs the test suite on the given topo server and client func TestSuite(t *testing.T, ts topo.Server, client vtctlclient.VtctlClient) { ctx := context.Background() // Create a fake tablet tablet := &topodatapb.Tablet{ Alias: &topodatapb.TabletAlias{Cell: "cell1", Uid: 1}, Hostname: "localhost", Ip: "10.11.12.13", PortMap: map[string]int32{ "vt": 3333, "mysql": 3334, }, Tags: map[string]string{"tag": "value"}, Keyspace: "test_keyspace", Type: topodatapb.TabletType_MASTER, } if err := ts.CreateTablet(ctx, tablet); err != nil { t.Errorf("CreateTablet: %v", err) } // run a command that's gonna return something on the log channel stream, err := client.ExecuteVtctlCommand(ctx, []string{"ListAllTablets", "cell1"}, 30*time.Second) if err != nil { t.Fatalf("Remote error: %v", err) } got, err := stream.Recv() if err != nil { t.Fatalf("failed to get first line: %v", err) } expected := "cell1-0000000001 test_keyspace <null> master localhost:3333 localhost:3334 [tag: \"value\"]\n" if logutil.EventString(got) != expected { t.Errorf("Got unexpected log line '%v' expected '%v'", got.String(), expected) } got, err = stream.Recv() if err != io.EOF { t.Errorf("Didn't get end of log stream: %v %v", got, err) } // run a command that's gonna fail stream, err = client.ExecuteVtctlCommand(ctx, []string{"ListAllTablets", "cell2"}, 30*time.Second) if err != nil { t.Fatalf("Remote error: %v", err) } got, err = stream.Recv() expected = "node doesn't exist" if err == nil || !strings.Contains(err.Error(), expected) { t.Fatalf("Unexpected remote error, got: '%v' was expecting to find '%v'", err, expected) } // run a command that's gonna panic stream, err = client.ExecuteVtctlCommand(ctx, []string{"Panic"}, 30*time.Second) if err != nil { t.Fatalf("Remote error: %v", err) } got, err = stream.Recv() expected1 := "this command panics on purpose" expected2 := "uncaught vtctl panic" if err == nil || !strings.Contains(err.Error(), expected1) || !strings.Contains(err.Error(), expected2) { t.Fatalf("Unexpected remote error, got: '%v' was expecting to find '%v' and '%v'", err, expected1, expected2) } // and clean up the tablet if err := ts.DeleteTablet(ctx, tablet.Alias); err != nil { t.Errorf("DeleteTablet: %v", err) } }
func CheckTablet(t *testing.T, ts topo.Server) { cell := getLocalCell(t, ts) tablet := &topo.Tablet{ Cell: cell, Uid: 1, Addr: "localhost:3333", MysqlAddr: "localhost:3334", MysqlIpAddr: "10.11.12.13:3334", Alias: topo.TabletAlias{Cell: cell, Uid: 1}, Hostname: "localhost", IPAddr: "10.11.12.13", Portmap: map[string]int{ "vt": 3333, "mysql": 3334, }, Tags: map[string]string{"tag": "value"}, Keyspace: "test_keyspace", Type: topo.TYPE_MASTER, State: topo.STATE_READ_WRITE, KeyRange: newKeyRange("-10"), BlacklistedTables: []string{"black1", "black2"}, } if err := ts.CreateTablet(tablet); err != nil { t.Errorf("CreateTablet: %v", err) } if err := ts.CreateTablet(tablet); err != topo.ErrNodeExists { t.Errorf("CreateTablet(again): %v", err) } if _, err := ts.GetTablet(topo.TabletAlias{Cell: cell, Uid: 666}); err != topo.ErrNoNode { t.Errorf("GetTablet(666): %v", err) } ti, err := ts.GetTablet(tablet.Alias) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias, err) } if eq, err := tabletEqual(ti.Tablet, tablet); err != nil { t.Errorf("cannot compare tablets: %v", err) } else if !eq { t.Errorf("put and got tablets are not identical:\n%#v\n%#v", tablet, ti.Tablet) } if _, err := ts.GetTabletsByCell("666"); err != topo.ErrNoNode { t.Errorf("GetTabletsByCell(666): %v", err) } inCell, err := ts.GetTabletsByCell(cell) if err != nil { t.Errorf("GetTabletsByCell: %v", err) } if len(inCell) != 1 || inCell[0] != tablet.Alias { t.Errorf("GetTabletsByCell: want [%v], got %v", tablet.Alias, inCell) } ti.State = topo.STATE_READ_ONLY if err := topo.UpdateTablet(ts, ti); err != nil { t.Errorf("UpdateTablet: %v", err) } ti, err = ts.GetTablet(tablet.Alias) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias, err) } if want := topo.STATE_READ_ONLY; ti.State != want { t.Errorf("ti.State: want %v, got %v", want, ti.State) } if err := ts.UpdateTabletFields(tablet.Alias, func(t *topo.Tablet) error { t.State = topo.STATE_READ_WRITE return nil }); err != nil { t.Errorf("UpdateTabletFields: %v", err) } ti, err = ts.GetTablet(tablet.Alias) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias, err) } if want := topo.STATE_READ_WRITE; ti.State != want { t.Errorf("ti.State: want %v, got %v", want, ti.State) } if err := ts.DeleteTablet(tablet.Alias); err != nil { t.Errorf("DeleteTablet: %v", err) } if err := ts.DeleteTablet(tablet.Alias); err != topo.ErrNoNode { t.Errorf("DeleteTablet(again): %v", err) } if _, err := ts.GetTablet(tablet.Alias); err != topo.ErrNoNode { t.Errorf("GetTablet: expected error, tablet was deleted: %v", err) } }
func CheckTablet(t *testing.T, ts topo.Server) { cell := getLocalCell(t, ts) tablet := &topo.Tablet{ Cell: cell, Uid: 1, Parent: topo.TabletAlias{}, Addr: "localhost:3333", MysqlAddr: "localhost:3334", MysqlIpAddr: "10.11.12.13:3334", Keyspace: "test_keyspace", Type: topo.TYPE_MASTER, State: topo.STATE_READ_WRITE, KeyRange: newKeyRange("-10"), } if err := ts.CreateTablet(tablet); err != nil { t.Errorf("CreateTablet: %v", err) } if err := ts.CreateTablet(tablet); err != topo.ErrNodeExists { t.Errorf("CreateTablet(again): %v", err) } if _, err := ts.GetTablet(topo.TabletAlias{cell, 666}); err != topo.ErrNoNode { t.Errorf("GetTablet(666): %v", err) } ti, err := ts.GetTablet(tablet.Alias()) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias(), err) } if eq, err := tabletEqual(ti.Tablet, tablet); err != nil { t.Errorf("cannot compare tablets: %v", err) } else if !eq { t.Errorf("put and got tablets are not identical:\n%#v\n%#v", tablet, ti.Tablet) } if _, err := ts.GetTabletsByCell("666"); err != topo.ErrNoNode { t.Errorf("GetTabletsByCell(666): %v", err) } inCell, err := ts.GetTabletsByCell(cell) if err != nil { t.Errorf("GetTabletsByCell: %v", err) } if len(inCell) != 1 || inCell[0] != tablet.Alias() { t.Errorf("GetTabletsByCell: want [%v], got %v", tablet.Alias(), inCell) } ti.State = topo.STATE_READ_ONLY if err := topo.UpdateTablet(ts, ti); err != nil { t.Errorf("UpdateTablet: %v", err) } ti, err = ts.GetTablet(tablet.Alias()) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias(), err) } if want := topo.STATE_READ_ONLY; ti.State != want { t.Errorf("ti.State: want %v, got %v", want, ti.State) } if err := ts.UpdateTabletFields(tablet.Alias(), func(t *topo.Tablet) error { t.State = topo.STATE_READ_WRITE return nil }); err != nil { t.Errorf("UpdateTabletFields: %v", err) } ti, err = ts.GetTablet(tablet.Alias()) if err != nil { t.Errorf("GetTablet %v: %v", tablet.Alias(), err) } if want := topo.STATE_READ_WRITE; ti.State != want { t.Errorf("ti.State: want %v, got %v", want, ti.State) } if err := ts.DeleteTablet(tablet.Alias()); err != nil { t.Errorf("DeleteTablet: %v", err) } if err := ts.DeleteTablet(tablet.Alias()); err != topo.ErrNoNode { t.Errorf("DeleteTablet(again): %v", err) } if _, err := ts.GetTablet(tablet.Alias()); err != topo.ErrNoNode { t.Errorf("GetTablet: expected error, tablet was deleted: %v", err) } }