vtctl: Add -force flag to DeleteCellInfo.

We need to have a way to remove CellInfo for a cell whose local
topology server has already been permanently shut down.

Signed-off-by: Anthony Yeh <enisoc@planetscale.com>
This commit is contained in:
Anthony Yeh 2020-04-03 14:36:47 -07:00
Родитель 291202f439
Коммит a2d104a638
3 изменённых файлов: 33 добавлений и 12 удалений

Просмотреть файл

@ -17,7 +17,6 @@ limitations under the License.
package topo
import (
"fmt"
"path"
"github.com/golang/protobuf/proto"
@ -25,6 +24,7 @@ import (
"vitess.io/vitess/go/vt/vterrors"
topodatapb "vitess.io/vitess/go/vt/proto/topodata"
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
)
// This file provides the utility methods to save / retrieve CellInfo
@ -135,18 +135,21 @@ func (ts *Server) UpdateCellInfoFields(ctx context.Context, cell string, update
}
// DeleteCellInfo deletes the specified CellInfo.
// We first make sure no Shard record points to the cell.
func (ts *Server) DeleteCellInfo(ctx context.Context, cell string) error {
// We first try to make sure no Shard record points to the cell,
// but we'll continue regardless if 'force' is true.
func (ts *Server) DeleteCellInfo(ctx context.Context, cell string, force bool) error {
srvKeyspaces, err := ts.GetSrvKeyspaceNames(ctx, cell)
switch {
case err == nil:
if len(srvKeyspaces) != 0 {
return vterrors.Wrap(err, fmt.Sprintf("cell %v has serving keyspaces. Before deleting, delete keyspace with: DeleteKeyspace", cell))
if len(srvKeyspaces) != 0 && !force {
return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "cell %v has serving keyspaces. Before deleting, delete keyspace with DeleteKeyspace, or use -force to continue anyway.", cell)
}
case IsErrType(err, NoNode):
// Nothing to do.
default:
return vterrors.Wrap(err, "GetSrvKeyspaceNames() failed")
if !force {
return vterrors.Wrap(err, "can't list SrvKeyspace entries in the cell; use -force flag to continue anyway (e.g. if cell-local topo was already permanently shut down)")
}
}
filePath := pathForCellInfo(cell)

Просмотреть файл

@ -99,11 +99,28 @@ func TestCellInfo(t *testing.T) {
t.Fatalf("unexpected CellInfo: %v", ci)
}
// Might as well test DeleteCellInfo.
if err := ts.DeleteCellInfo(ctx, newCell); err != nil {
t.Fatalf("DeleteCellInfo failed: %v", err)
// Add a record that should block CellInfo deletion for safety reasons.
if err := ts.UpdateSrvKeyspace(ctx, cell, "keyspace", &topodatapb.SrvKeyspace{}); err != nil {
t.Fatalf("UpdateSrvKeyspace failed: %v", err)
}
if _, err := ts.GetCellInfo(ctx, newCell, true /*strongRead*/); !topo.IsErrType(err, topo.NoNode) {
srvKeyspaces, err := ts.GetSrvKeyspaceNames(ctx, cell)
if err != nil {
t.Fatalf("GetSrvKeyspaceNames failed: %v", err)
}
if len(srvKeyspaces) == 0 {
t.Fatalf("UpdateSrvKeyspace did not add SrvKeyspace.")
}
// Try to delete without force; it should fail.
if err := ts.DeleteCellInfo(ctx, cell, false); err == nil {
t.Fatalf("DeleteCellInfo should have failed without -force")
}
// Use the force.
if err := ts.DeleteCellInfo(ctx, cell, true); err != nil {
t.Fatalf("DeleteCellInfo failed even with -force: %v", err)
}
if _, err := ts.GetCellInfo(ctx, cell, true /*strongRead*/); !topo.IsErrType(err, topo.NoNode) {
t.Fatalf("GetCellInfo(non-existing cell) failed: %v", err)
}
}

Просмотреть файл

@ -51,7 +51,7 @@ func init() {
addCommand(cellsGroupName, command{
"DeleteCellInfo",
commandDeleteCellInfo,
"<cell>",
"[-force] <cell>",
"Deletes the CellInfo for the provided cell. The cell cannot be referenced by any Shard record."})
addCommand(cellsGroupName, command{
@ -111,6 +111,7 @@ func commandUpdateCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags
}
func commandDeleteCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
force := subFlags.Bool("force", false, "Proceeds even if the cell's topology server cannot be reached. The assumption is that you turned down the entire cell, and just need to update the global topo data.")
if err := subFlags.Parse(args); err != nil {
return err
}
@ -119,7 +120,7 @@ func commandDeleteCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags
}
cell := subFlags.Arg(0)
return wr.TopoServer().DeleteCellInfo(ctx, cell)
return wr.TopoServer().DeleteCellInfo(ctx, cell, *force)
}
func commandGetCellInfoNames(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {