diff --git a/doc/releasenotes/15_0_0_summary.md b/doc/releasenotes/15_0_0_summary.md index 1bd9b2a6f0d..0ca9ccee6c6 100644 --- a/doc/releasenotes/15_0_0_summary.md +++ b/doc/releasenotes/15_0_0_summary.md @@ -24,6 +24,7 @@ - The deprecated `--mutex-profile-fraction` flag has been removed. Please use `--pprof=mutex` instead. - The deprecated vtgate/vtexplain/vtcombo flag `--planner_version` has been removed. Please use `--planner-version` instead. - The deprecated flag `--master_connect_retry` has been removed. Please use `--replication_connect_retry` instead. +- `vtctl` commands that take shard names and ranges as positional arguments (e.g. `vtctl Reshard ks.workflow -80 -40,40-80`) need to have their positional arguments separated from their flag arguments by a double-dash separator to avoid the new parsing library from mistaking them as flags (e.g. `vtctl Reshard ks.workflow -- -80 -40,40-80`). #### Vindex Interface @@ -85,10 +86,10 @@ connections, similar to the way pooling happens for write buffers. Defaults to o We introduced the ability to resume a VDiff2 workflow: ``` -$ vtctlclient --server=localhost:15999 VDiff -- --v2 customer.commerce2customer resume 4c664dc2-eba9-11ec-9ef7-920702940ee0 +$ vtctlclient --server=localhost:15999 VDiff --v2 customer.commerce2customer resume 4c664dc2-eba9-11ec-9ef7-920702940ee0 VDiff 4c664dc2-eba9-11ec-9ef7-920702940ee0 resumed on target shards, use show to view progress -$ vtctlclient --server=localhost:15999 VDiff -- --v2 customer.commerce2customer show last +$ vtctlclient --server=localhost:15999 VDiff --v2 customer.commerce2customer show last VDiff Summary for customer.commerce2customer (4c664dc2-eba9-11ec-9ef7-920702940ee0) State: completed @@ -99,7 +100,7 @@ CompletedAt: 2022-06-26 22:44:31 Use "--format=json" for more detailed output. -$ vtctlclient --server=localhost:15999 VDiff -- --v2 --format=json customer.commerce2customer show last +$ vtctlclient --server=localhost:15999 VDiff --v2 --format=json customer.commerce2customer show last { "Workflow": "commerce2customer", "Keyspace": "customer", diff --git a/examples/local/scripts/consul-up.sh b/examples/local/scripts/consul-up.sh index 44c15d62dc2..4a69d1e1902 100755 --- a/examples/local/scripts/consul-up.sh +++ b/examples/local/scripts/consul-up.sh @@ -43,7 +43,7 @@ sleep 5 echo "add $cell CellInfo" set +e # shellcheck disable=SC2086 -vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo -- \ +vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo \ --root "vitess/$cell" \ --server-address "${CONSUL_SERVER}:${consul_http_port}" \ "$cell" diff --git a/examples/local/scripts/etcd-up.sh b/examples/local/scripts/etcd-up.sh index 1eac151ec6c..5d262217c88 100755 --- a/examples/local/scripts/etcd-up.sh +++ b/examples/local/scripts/etcd-up.sh @@ -40,7 +40,7 @@ etcdctl --endpoints "http://${ETCD_SERVER}" mkdir /vitess/$cell & echo "add $cell CellInfo" set +e # shellcheck disable=SC2086 -vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo -- \ +vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo \ --root /vitess/$cell \ --server-address "${ETCD_SERVER}" \ $cell diff --git a/examples/local/scripts/k3s-up.sh b/examples/local/scripts/k3s-up.sh index 52797e18c67..b2ead1a86d6 100755 --- a/examples/local/scripts/k3s-up.sh +++ b/examples/local/scripts/k3s-up.sh @@ -52,7 +52,7 @@ $KUBECTL create -f ../../go/vt/topo/k8stopo/VitessTopoNodes-crd.yaml # Add the CellInfo description for the cell set +e echo "add $cell CellInfo" -vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo -- \ +vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo \ --root /vitess/$cell \ $cell set -e diff --git a/examples/local/scripts/zk-up.sh b/examples/local/scripts/zk-up.sh index a762436b69d..d689e167988 100755 --- a/examples/local/scripts/zk-up.sh +++ b/examples/local/scripts/zk-up.sh @@ -53,7 +53,7 @@ echo "Started zk servers." # If the node already exists, it's fine, means we used existing data. set +e # shellcheck disable=SC2086 -vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo -- \ +vtctl $TOPOLOGY_FLAGS VtctldCommand AddCellInfo \ --root /vitess/$cell \ --server-address $ZK_SERVER \ $cell diff --git a/go/cmd/vtctl/vtctl.go b/go/cmd/vtctl/vtctl.go index d0ca5777ff2..45f63026982 100644 --- a/go/cmd/vtctl/vtctl.go +++ b/go/cmd/vtctl/vtctl.go @@ -52,6 +52,29 @@ var ( func init() { servenv.OnParse(func(fs *pflag.FlagSet) { + // N.B. This is necessary for subcommand pflag parsing when not using + // cobra (cobra is where we're headed, but for `vtctl` it's a big lift + // before the RC cut). + // + // Essentially, the situation we have here is that commands look like: + // + // `vtctl [global flags] [subcommand flags]` + // + // Since the default behavior of pflag is to allow "interspersed" flag + // and positional arguments, this means that the initial servenv parse + // will complain if _any_ subocmmand's flag is provided; for example, if + // you were to invoke + // + // `vtctl AddCellInfo --root /vitess/global --server_address "1.2.3.4" global + // + // then you would get the error "unknown flag --root", even though that + // is a valid flag for the AddCellInfo flag. + // + // By disabling interspersal on the top-level parse, anything after the + // command name ("AddCellInfo", in this example) will be forwarded to + // the subcommand's flag set for further parsing. + fs.SetInterspersed(false) + logger := logutil.NewConsoleLogger() fs.SetOutput(logutil.NewLoggerWriter(logger)) fs.Usage = func() { @@ -156,12 +179,14 @@ func main() { default: log.Warningf("WARNING: vtctl should only be used for VDiff workflows. Consider using vtctldclient for all other commands.") + wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) + if args[0] == "--" { + vtctl.PrintDoubleDashDeprecationNotice(wr) args = args[1:] } action = args[0] - wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) err := vtctl.RunCommand(ctx, wr, args) cancel() switch err { diff --git a/go/test/endtoend/recovery/pitr/shardedpitr_test.go b/go/test/endtoend/recovery/pitr/shardedpitr_test.go index 56ead8f7f32..6ae2e72b1a9 100644 --- a/go/test/endtoend/recovery/pitr/shardedpitr_test.go +++ b/go/test/endtoend/recovery/pitr/shardedpitr_test.go @@ -299,7 +299,7 @@ func performResharding(t *testing.T) { require.NoError(t, err) } - err = clusterInstance.VtctlclientProcess.ExecuteCommand("Reshard", "--", "--v1", "ks.reshardWorkflow", "0", "-80,80-") + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Reshard", "--", "--v1", "ks.reshardWorkflow", "0", "--", "-80,80-") require.NoError(t, err) err = clusterInstance.VtctlclientProcess.ExecuteCommand("SwitchReads", "--", "--tablet_types=rdonly", "ks.reshardWorkflow") diff --git a/go/test/endtoend/recovery/pitrtls/shardedpitr_tls_test.go b/go/test/endtoend/recovery/pitrtls/shardedpitr_tls_test.go index f323333ce1e..ab0020d3734 100644 --- a/go/test/endtoend/recovery/pitrtls/shardedpitr_tls_test.go +++ b/go/test/endtoend/recovery/pitrtls/shardedpitr_tls_test.go @@ -418,7 +418,7 @@ func tlsPerformResharding(t *testing.T) { require.NoError(t, err) } - err = clusterInstance.VtctlclientProcess.ExecuteCommand("Reshard", "ks.reshardWorkflow", "0", "-80,80-") + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Reshard", "ks.reshardWorkflow", "0", "--", "-80,80-") require.NoError(t, err) err = clusterInstance.VtctlclientProcess.ExecuteCommand("SwitchReads", "--", "--tablet_type=rdonly", "ks.reshardWorkflow") diff --git a/go/test/endtoend/vreplication/vreplication_test.go b/go/test/endtoend/vreplication/vreplication_test.go index dda74629a4a..40e34bbfce4 100644 --- a/go/test/endtoend/vreplication/vreplication_test.go +++ b/go/test/endtoend/vreplication/vreplication_test.go @@ -841,7 +841,7 @@ func reshard(t *testing.T, ksName string, tableName string, workflow string, sou t.Fatal(err) } } - if err := vc.VtctlClient.ExecuteCommand("Reshard", "--", "--v1", "--cells="+sourceCellOrAlias, "--tablet_types=replica,primary", ksWorkflow, sourceShards, targetShards); err != nil { + if err := vc.VtctlClient.ExecuteCommand("Reshard", "--", "--v1", "--cells="+sourceCellOrAlias, "--tablet_types=replica,primary", ksWorkflow, "--", sourceShards, targetShards); err != nil { t.Fatalf("Reshard command failed with %+v\n", err) } tablets := vc.getVttabletsInKeyspace(t, defaultCell, ksName, "primary") diff --git a/go/test/endtoend/vtctldweb/vtctld_web_test.go b/go/test/endtoend/vtctldweb/vtctld_web_test.go index 8c798c0bdea..fed8a98320f 100644 --- a/go/test/endtoend/vtctldweb/vtctld_web_test.go +++ b/go/test/endtoend/vtctldweb/vtctld_web_test.go @@ -120,11 +120,11 @@ func TestCreateKs(t *testing.T) { case 0: err := ele.SendKeys("test_keyspace3") require.Nil(t, err) - assertDialogCommand(t, dialog, []string{"CreateKeyspace", "-force=false", "test_keyspace3"}) + assertDialogCommand(t, dialog, []string{"CreateKeyspace", "--force=false", "test_keyspace3"}) } } - assertDialogCommand(t, dialog, []string{"CreateKeyspace", "-force=false", "test_keyspace3"}) + assertDialogCommand(t, dialog, []string{"CreateKeyspace", "--force=false", "test_keyspace3"}) create, err := dialog.FindElement(selenium.ByID, "vt-action") require.Nil(t, err) @@ -195,14 +195,14 @@ func TestDashboardValidate(t *testing.T) { dialog, err := dashboardContent.FindElement(selenium.ByTagName, "vt-dialog") require.Nil(t, err) - assertDialogCommand(t, dialog, []string{"Validate", "-ping-tablets=false"}) + assertDialogCommand(t, dialog, []string{"Validate", "--ping-tablets=false"}) checkBoxes, err := dialog.FindElements(selenium.ByClassName, "md-checkbox-inner-container") require.Nil(t, err) click(t, checkBoxes[0]) - assertDialogCommand(t, dialog, []string{"Validate", "-ping-tablets"}) + assertDialogCommand(t, dialog, []string{"Validate", "--ping-tablets"}) validate, err := dialog.FindElement(selenium.ByID, "vt-action") require.Nil(t, err) diff --git a/go/test/endtoend/vtgate/schema/schema_test.go b/go/test/endtoend/vtgate/schema/schema_test.go index a452f66b2b5..38cc74514df 100644 --- a/go/test/endtoend/vtgate/schema/schema_test.go +++ b/go/test/endtoend/vtgate/schema/schema_test.go @@ -230,7 +230,7 @@ func testDropNonExistentTables(t *testing.T) { func testCreateInvalidView(t *testing.T) { for _, ddlStrategy := range []string{"direct", "direct -allow-zero-in-date"} { createInvalidView := "CREATE OR REPLACE VIEW invalid_view AS SELECT * FROM nonexistent_table;" - output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ApplySchema", "--", "-skip_preflight", "-ddl_strategy", ddlStrategy, "--sql", createInvalidView, keyspaceName) + output, err := clusterInstance.VtctlclientProcess.ExecuteCommandWithOutput("ApplySchema", "--", "--skip_preflight", "--ddl_strategy", ddlStrategy, "--sql", createInvalidView, keyspaceName) require.Error(t, err) assert.Contains(t, output, "doesn't exist (errno 1146)") } diff --git a/go/vt/vtctl/backup.go b/go/vt/vtctl/backup.go index eb03a1c0397..7d73c352efc 100644 --- a/go/vt/vtctl/backup.go +++ b/go/vt/vtctl/backup.go @@ -18,10 +18,10 @@ package vtctl import ( "context" - "flag" "fmt" "time" + "github.com/spf13/pflag" "google.golang.org/grpc" "vitess.io/vitess/go/protoutil" @@ -70,7 +70,7 @@ func init() { }) } -func commandBackup(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandBackup(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { concurrency := subFlags.Int("concurrency", 4, "Specifies the number of compression/checksum jobs to run simultaneously") allowPrimary := subFlags.Bool("allow_primary", false, "Allows backups to be taken on primary. Warning!! If you are using the builtin backup engine, this will shutdown your primary mysql for as long as it takes to create a backup.") @@ -108,7 +108,7 @@ func (b *backupEventStreamLogger) Send(resp *vtctldatapb.BackupResponse) error { return nil } -func commandBackupShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandBackupShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { concurrency := subFlags.Int("concurrency", 4, "Specifies the number of compression/checksum jobs to run simultaneously") allowPrimary := subFlags.Bool("allow_primary", false, "Whether to use primary tablet for backup. Warning!! If you are using the builtin backup engine, this will shutdown your primary mysql for as long as it takes to create a backup.") @@ -132,7 +132,7 @@ func commandBackupShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl }, &backupEventStreamLogger{logger: wr.Logger(), ctx: ctx}) } -func commandListBackups(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandListBackups(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -161,7 +161,7 @@ func commandListBackups(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return nil } -func commandRemoveBackup(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRemoveBackup(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -198,7 +198,7 @@ func (b *backupRestoreEventStreamLogger) Send(resp *vtctldatapb.RestoreFromBacku return nil } -func commandRestoreFromBackup(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRestoreFromBackup(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { backupTimestampStr := subFlags.String("backup_timestamp", "", "Use the backup taken at or before this timestamp rather than using the latest backup.") if err := subFlags.Parse(args); err != nil { return err diff --git a/go/vt/vtctl/cell_info.go b/go/vt/vtctl/cell_info.go index 0478af4e50b..cef29de6c82 100644 --- a/go/vt/vtctl/cell_info.go +++ b/go/vt/vtctl/cell_info.go @@ -18,10 +18,11 @@ package vtctl import ( "context" - "flag" "fmt" "strings" + "github.com/spf13/pflag" + "vitess.io/vitess/go/vt/wrangler" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -71,7 +72,7 @@ func init() { }) } -func commandAddCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandAddCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { serverAddress := subFlags.String("server_address", "", "The address the topology server is using for that cell.") root := subFlags.String("root", "", "The root path the topology server is using for that cell.") if err := subFlags.Parse(args); err != nil { @@ -92,7 +93,7 @@ func commandAddCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return err } -func commandUpdateCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandUpdateCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { serverAddress := subFlags.String("server_address", "", "The address the topology server is using for that cell.") root := subFlags.String("root", "", "The root path the topology server is using for that cell.") if err := subFlags.Parse(args); err != nil { @@ -113,7 +114,7 @@ func commandUpdateCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags return err } -func commandDeleteCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandDeleteCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.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 @@ -130,7 +131,7 @@ func commandDeleteCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags return err } -func commandGetCellInfoNames(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetCellInfoNames(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -145,7 +146,7 @@ func commandGetCellInfoNames(ctx context.Context, wr *wrangler.Wrangler, subFlag return nil } -func commandGetCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetCellInfo(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } diff --git a/go/vt/vtctl/cells_aliases.go b/go/vt/vtctl/cells_aliases.go index eaf016e1b28..9fd7fea9aca 100644 --- a/go/vt/vtctl/cells_aliases.go +++ b/go/vt/vtctl/cells_aliases.go @@ -18,10 +18,11 @@ package vtctl import ( "context" - "flag" "fmt" "strings" + "github.com/spf13/pflag" + "vitess.io/vitess/go/vt/wrangler" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -64,8 +65,8 @@ func init() { }) } -func commandAddCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { - cellsString := subFlags.String("cells", "", "The list of cell names that are members of this alias.") +func commandAddCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { + cells := subFlags.StringSlice("cells", nil, "The list of cell names that are members of this alias.") if err := subFlags.Parse(args); err != nil { return err } @@ -73,21 +74,20 @@ func commandAddCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlags * return fmt.Errorf("the argument is required for the AddCellsAlias command") } - cells := strings.Split(*cellsString, ",") - for i, cell := range cells { - cells[i] = strings.TrimSpace(cell) + for i, cell := range *cells { + (*cells)[i] = strings.TrimSpace(cell) } alias := subFlags.Arg(0) _, err := wr.VtctldServer().AddCellsAlias(ctx, &vtctldatapb.AddCellsAliasRequest{ Name: alias, - Cells: cells, + Cells: *cells, }) return err } -func commandUpdateCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { - cellsString := subFlags.String("cells", "", "The list of cell names that are members of this alias.") +func commandUpdateCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { + cells := subFlags.StringSlice("cells", nil, "The list of cell names that are members of this alias.") if err := subFlags.Parse(args); err != nil { return err } @@ -95,22 +95,21 @@ func commandUpdateCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlag return fmt.Errorf("the argument is required for the UpdateCellsAlias command") } - cells := strings.Split(*cellsString, ",") - for i, cell := range cells { - cells[i] = strings.TrimSpace(cell) + for i, cell := range *cells { + (*cells)[i] = strings.TrimSpace(cell) } alias := subFlags.Arg(0) _, err := wr.VtctldServer().UpdateCellsAlias(ctx, &vtctldatapb.UpdateCellsAliasRequest{ Name: alias, CellsAlias: &topodatapb.CellsAlias{ - Cells: cells, + Cells: *cells, }, }) return err } -func commandDeleteCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandDeleteCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -125,7 +124,7 @@ func commandDeleteCellsAlias(ctx context.Context, wr *wrangler.Wrangler, subFlag return err } -func commandGetCellsAliases(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetCellsAliases(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } diff --git a/go/vt/vtctl/endtoend/get_schema_test.go b/go/vt/vtctl/endtoend/get_schema_test.go index 5bed5cbdc24..fe25080c7ae 100644 --- a/go/vt/vtctl/endtoend/get_schema_test.go +++ b/go/vt/vtctl/endtoend/get_schema_test.go @@ -177,7 +177,7 @@ func TestGetSchema(t *testing.T) { utils.MustMatch(t, sd, actual) // reset for the next invocation, where we verify that passing - // -table_sizes_only does not include the create table statement or columns. + // --table_sizes_only does not include the create table statement or columns. logger.Events = nil sd = &tabletmanagerdatapb.SchemaDefinition{ TableDefinitions: []*tabletmanagerdatapb.TableDefinition{ @@ -202,7 +202,7 @@ func TestGetSchema(t *testing.T) { err = vtctl.RunCommand(ctx, wrangler.New(logger, topo, &tmc), []string{ "GetSchema", - "-table_sizes_only", + "--table_sizes_only", topoproto.TabletAliasString(tablet.Alias), }) require.NoError(t, err) diff --git a/go/vt/vtctl/reparent.go b/go/vt/vtctl/reparent.go index a4c285e93a9..b2f030e0756 100644 --- a/go/vt/vtctl/reparent.go +++ b/go/vt/vtctl/reparent.go @@ -18,9 +18,10 @@ package vtctl import ( "context" - "flag" "fmt" + "github.com/spf13/pflag" + "vitess.io/vitess/go/vt/mysqlctl" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" @@ -63,7 +64,7 @@ func init() { }) } -func commandReparentTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandReparentTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if mysqlctl.DisableActiveReparents { return fmt.Errorf("active reparent commands disabled (unset the --disable_active_reparents flag to enable)") } @@ -81,7 +82,7 @@ func commandReparentTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags return wr.ReparentTablet(ctx, tabletAlias) } -func commandInitShardPrimary(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandInitShardPrimary(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if mysqlctl.DisableActiveReparents { return fmt.Errorf("active reparent commands disabled (unset the --disable_active_reparents flag to enable)") } @@ -105,7 +106,7 @@ func commandInitShardPrimary(ctx context.Context, wr *wrangler.Wrangler, subFlag return wr.InitShardPrimary(ctx, keyspace, shard, tabletAlias, *force, *waitReplicasTimeout) } -func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if mysqlctl.DisableActiveReparents { return fmt.Errorf("active reparent commands disabled (unset the --disable_active_reparents flag to enable)") } @@ -149,7 +150,7 @@ func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, sub return wr.PlannedReparentShard(ctx, keyspace, shard, newPrimaryAlias, avoidTabletAlias, *waitReplicasTimeout) } -func commandEmergencyReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandEmergencyReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if mysqlctl.DisableActiveReparents { return fmt.Errorf("active reparent commands disabled (unset the --disable_active_reparents flag to enable)") } @@ -189,7 +190,7 @@ func commandEmergencyReparentShard(ctx context.Context, wr *wrangler.Wrangler, s return wr.EmergencyReparentShard(ctx, keyspace, shard, tabletAlias, *waitReplicasTimeout, unreachableReplicas, *preventCrossCellPromotion) } -func commandTabletExternallyReparented(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandTabletExternallyReparented(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } diff --git a/go/vt/vtctl/topo.go b/go/vt/vtctl/topo.go index 465e731f8ab..308d1f305f9 100644 --- a/go/vt/vtctl/topo.go +++ b/go/vt/vtctl/topo.go @@ -19,11 +19,11 @@ package vtctl import ( "context" "encoding/json" - "flag" "fmt" "os" "path" + "github.com/spf13/pflag" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" @@ -110,7 +110,7 @@ func DecodeContent(filename string, data []byte, json bool) (string, error) { return string(marshalled), err } -func commandTopoCat(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandTopoCat(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cell := subFlags.String("cell", topo.GlobalCell, "topology cell to cat the file from. Defaults to global cell.") long := subFlags.Bool("long", false, "long listing.") decodeProtoJSON := subFlags.Bool("decode_proto_json", false, "decode proto files and display them as json") @@ -146,7 +146,7 @@ func commandTopoCat(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.F return topologyDecoder.decode(ctx, resolved, conn, wr, *long) } -func commandTopoCp(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandTopoCp(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cell := subFlags.String("cell", topo.GlobalCell, "topology cell to use for the copy. Defaults to global cell.") toTopo := subFlags.Bool("to_topo", false, "copies from local server to topo instead (reverse direction).") subFlags.Parse(args) diff --git a/go/vt/vtctl/vdiff2.go b/go/vt/vtctl/vdiff2.go index 88065820c1b..e97b56edb68 100644 --- a/go/vt/vtctl/vdiff2.go +++ b/go/vt/vtctl/vdiff2.go @@ -21,7 +21,6 @@ package vtctl import ( "context" "encoding/json" - "flag" "fmt" "math" "reflect" @@ -33,17 +32,19 @@ import ( "github.com/bndr/gotabulate" "github.com/google/uuid" + "github.com/spf13/pflag" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/log" - tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" - vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/tabletmanager/vdiff" "vitess.io/vitess/go/vt/wrangler" + + tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) -func commandVDiff2(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandVDiff2(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { _ = subFlags.Bool("v2", false, "Use VDiff2") timeout := subFlags.Duration("filtered_replication_wait_time", 30*time.Second, "Specifies the maximum time to wait, in seconds, for filtered replication to catch up on primary migrations. The migration will be cancelled on a timeout.") diff --git a/go/vt/vtctl/vtctl.go b/go/vt/vtctl/vtctl.go index b643aff1372..143740267a5 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -94,16 +94,16 @@ import ( "sync" "time" + "github.com/spf13/pflag" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" - "vitess.io/vitess/go/textutil" - "vitess.io/vitess/go/cmd/vtctldclient/cli" "vitess.io/vitess/go/flagutil" "vitess.io/vitess/go/json2" "vitess.io/vitess/go/protoutil" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/textutil" hk "vitess.io/vitess/go/vt/hook" "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/log" @@ -123,9 +123,6 @@ import ( vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/proto/vttime" - - // Include deprecation warnings for soon-to-be-unsupported flag invocations. - _flag "vitess.io/vitess/go/internal/flag" ) var ( @@ -142,13 +139,18 @@ var ( type command struct { name string - method func(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error + method func(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error params string help string // if help is empty, won't list the command // if set, PrintAllCommands will not show this command hidden bool + // (ajm188) - before we transition to cobra, we need to know whether to + // strip off a -- after the action (i.e. "command") name in RunCommand so + // that parsing continues to work. + disableFlagInterspersal bool + // deprecation support deprecated bool deprecatedBy string @@ -260,6 +262,7 @@ var commands = []commandGroup{ params: " [ ...]", help: "Runs the specified hook on the given tablet. A hook is a script that resides in the $VTROOT/vthook directory. You can put any script into that directory and use this command to run that script.\n" + "For this command, the param=value arguments are parameters that the command passes to the specified hook.", + disableFlagInterspersal: true, }, { name: "ExecuteFetchAsApp", @@ -434,7 +437,7 @@ var commands = []commandGroup{ name: "Reshard", method: commandReshard, params: "[--source_shards=] [--target_shards=] [--cells=] [--tablet_types=] [--skip_schema_copy] 'action must be one of the following: Create, Complete, Cancel, SwitchTraffic, ReverseTrafffic, Show, or Progress' ", - help: "Start a Resharding process. Example: Reshard --cells='zone1,alias1' --tablet_types='PRIMARY,REPLICA,RDONLY' ks.workflow001 '0' '-80,80-'", + help: "Start a Resharding process. Example: Reshard --cells='zone1,alias1' --tablet_types='PRIMARY,REPLICA,RDONLY' ks.workflow001 -- '0' '-80,80-'", }, { name: "MoveTables", @@ -539,9 +542,9 @@ var commands = []commandGroup{ }, { name: "LegacyVtctlCommand", - method: func(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + method: func(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { subFlags.Usage = func() { - fmt.Fprintln(subFlags.Output(), "Runs the vtctl request through the legacy vtctlclient program syntax (default).") + wr.Logger().Printf("Runs the vtctl request through the legacy vtctlclient program syntax (default).\n") } return subFlags.Parse(args) @@ -551,9 +554,9 @@ var commands = []commandGroup{ }, { name: "VtctldCommand", - method: func(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + method: func(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { subFlags.Usage = func() { - fmt.Fprintln(subFlags.Output(), "Runs the vtctl request through the new vtctldclient program syntax. This will become the default in a future version of Vitess.") + wr.Logger().Printf("Runs the vtctl request through the new vtctldclient program syntax. This will become the default in a future version of Vitess.\n") } return subFlags.Parse(args) @@ -915,7 +918,7 @@ func parseTabletType(param string, types []topodatapb.TabletType) (topodatapb.Ta return tabletType, nil } -func commandInitTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandInitTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { dbNameOverride := subFlags.String("db_name_override", "", "Overrides the name of the database that the vttablet uses") allowUpdate := subFlags.Bool("allow_update", false, "Use this flag to force initialization if a tablet with the same name already exists. Use with caution.") allowPrimaryOverride := subFlags.Bool("allow_master_override", false, "Use this flag to force initialization if a tablet is created as primary, and a primary for the keyspace/shard already exists. Use with caution.") @@ -971,7 +974,7 @@ func commandInitTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *fla return wr.TopoServer().InitTablet(ctx, tablet, *allowPrimaryOverride, *createShardAndKeyspace, *allowUpdate) } -func commandGetTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -991,7 +994,7 @@ func commandGetTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag return printJSON(wr.Logger(), tabletInfo.Tablet) } -func commandUpdateTabletAddrs(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandUpdateTabletAddrs(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { hostname := subFlags.String("hostname", "", "The fully qualified host name of the server on which the tablet is running.") mysqlHost := subFlags.String("mysql_host", "", "The mysql host for the mysql server") mysqlPort := subFlags.Int("mysql-port", 0, "The mysql port for the mysql daemon") @@ -1036,7 +1039,7 @@ func commandUpdateTabletAddrs(ctx context.Context, wr *wrangler.Wrangler, subFla return err } -func commandDeleteTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandDeleteTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { allowPrimary := subFlags.Bool("allow_primary", false, "Allows for the primary tablet of a shard to be deleted. Use with caution.") if err := subFlags.Parse(args); err != nil { @@ -1058,7 +1061,7 @@ func commandDeleteTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return nil } -func commandSetReadOnly(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSetReadOnly(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1077,7 +1080,7 @@ func commandSetReadOnly(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return err } -func commandSetReadWrite(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSetReadWrite(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1096,7 +1099,7 @@ func commandSetReadWrite(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return err } -func commandStartReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandStartReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1115,7 +1118,7 @@ func commandStartReplication(ctx context.Context, wr *wrangler.Wrangler, subFlag return err } -func commandStopReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandStopReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1134,7 +1137,7 @@ func commandStopReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags return err } -func commandChangeTabletType(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandChangeTabletType(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { dryRun := subFlags.Bool("dry-run", false, "Lists the proposed change without actually executing it") if err := subFlags.Parse(args); err != nil { @@ -1172,7 +1175,7 @@ func commandChangeTabletType(ctx context.Context, wr *wrangler.Wrangler, subFlag return wr.ChangeTabletType(ctx, tabletAlias, newType) } -func commandPing(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandPing(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1189,7 +1192,7 @@ func commandPing(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.Flag return err } -func commandRefreshState(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRefreshState(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1207,7 +1210,7 @@ func commandRefreshState(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return err } -func commandRefreshStateByShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRefreshStateByShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cellsStr := subFlags.String("cells", "", "Specifies a comma-separated list of cells whose tablets are included. If empty, all cells are considered.") if err := subFlags.Parse(args); err != nil { return err @@ -1234,7 +1237,7 @@ func commandRefreshStateByShard(ctx context.Context, wr *wrangler.Wrangler, subF return err } -func commandRunHealthCheck(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRunHealthCheck(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1252,7 +1255,7 @@ func commandRunHealthCheck(ctx context.Context, wr *wrangler.Wrangler, subFlags return err } -func commandSleep(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSleep(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1275,7 +1278,7 @@ func commandSleep(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.Fla return err } -func commandExecuteFetchAsApp(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandExecuteFetchAsApp(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { maxRows := subFlags.Int("max_rows", 10000, "Specifies the maximum number of rows to allow in fetch") usePool := subFlags.Bool("use_pool", false, "Use connection from pool") json := subFlags.Bool("json", false, "Output JSON instead of human-readable table") @@ -1304,7 +1307,7 @@ func commandExecuteFetchAsApp(ctx context.Context, wr *wrangler.Wrangler, subFla return nil } -func commandExecuteFetchAsDba(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandExecuteFetchAsDba(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { maxRows := subFlags.Int("max_rows", 10000, "Specifies the maximum number of rows to allow in fetch") disableBinlogs := subFlags.Bool("disable_binlogs", false, "Disables writing to binlogs during the query") reloadSchema := subFlags.Bool("reload_schema", false, "Indicates whether the tablet schema will be reloaded after executing the SQL command. The default value is false, which indicates that the tablet schema will not be reloaded.") @@ -1334,7 +1337,7 @@ func commandExecuteFetchAsDba(ctx context.Context, wr *wrangler.Wrangler, subFla return nil } -func commandVReplicationExec(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandVReplicationExec(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { json := subFlags.Bool("json", false, "Output JSON instead of human-readable table") if err := subFlags.Parse(args); err != nil { @@ -1361,7 +1364,9 @@ func commandVReplicationExec(ctx context.Context, wr *wrangler.Wrangler, subFlag return nil } -func commandExecuteHook(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandExecuteHook(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { + subFlags.SetInterspersed(false) // all flags should be treated as posargs to pass them to the actual hook + if err := subFlags.Parse(args); err != nil { return err } @@ -1393,7 +1398,7 @@ func commandExecuteHook(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return printJSON(wr.Logger(), hr) } -func commandCreateShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandCreateShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { force := subFlags.Bool("force", false, "Proceeds with the command even if the shard already exists") parent := subFlags.Bool("parent", false, "Creates the parent keyspace if it doesn't already exist") if err := subFlags.Parse(args); err != nil { @@ -1421,7 +1426,7 @@ func commandCreateShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return err } -func commandGetShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1441,7 +1446,7 @@ func commandGetShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag. return printJSON(wr.Logger(), shardInfo.Shard) } -func commandValidateShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidateShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { pingTablets := subFlags.Bool("ping-tablets", true, "Indicates whether all tablets should be pinged during the validation process") if err := subFlags.Parse(args); err != nil { return err @@ -1457,7 +1462,7 @@ func commandValidateShard(ctx context.Context, wr *wrangler.Wrangler, subFlags * return wr.ValidateShard(ctx, keyspace, shard, *pingTablets) } -func commandShardReplicationPositions(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandShardReplicationPositions(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1493,7 +1498,7 @@ func commandShardReplicationPositions(ctx context.Context, wr *wrangler.Wrangler return nil } -func commandListShardTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandListShardTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1521,7 +1526,7 @@ func commandListShardTablets(ctx context.Context, wr *wrangler.Wrangler, subFlag return nil } -func commandSetShardIsPrimaryServing(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSetShardIsPrimaryServing(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1546,7 +1551,7 @@ func commandSetShardIsPrimaryServing(ctx context.Context, wr *wrangler.Wrangler, return err } -func commandUpdateSrvKeyspacePartition(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandUpdateSrvKeyspacePartition(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cellsStr := subFlags.String("cells", "", "Specifies a comma-separated list of cells to update") remove := subFlags.Bool("remove", false, "Removes shard from serving keyspace partition") @@ -1577,7 +1582,7 @@ func commandUpdateSrvKeyspacePartition(ctx context.Context, wr *wrangler.Wrangle return nil } -func commandSetShardTabletControl(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSetShardTabletControl(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cellsStr := subFlags.String("cells", "", "Specifies a comma-separated list of cells to update") deniedTablesStr := subFlags.String("denied_tables", "", "Specifies a comma-separated list of tables to add to the denylist (used for VReplication). Each is either an exact match, or a regular expression of the form '/regexp/'.") @@ -1618,7 +1623,7 @@ func commandSetShardTabletControl(ctx context.Context, wr *wrangler.Wrangler, su return err } -func commandSourceShardDelete(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSourceShardDelete(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1637,7 +1642,7 @@ func commandSourceShardDelete(ctx context.Context, wr *wrangler.Wrangler, subFla return wr.SourceShardDelete(ctx, keyspace, shard, uint32(uid)) } -func commandSourceShardAdd(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSourceShardAdd(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { keyRange := subFlags.String("key_range", "", "Identifies the key range to use for the SourceShard") tablesStr := subFlags.String("tables", "", "Specifies a comma-separated list of tables to replicate. Each is either an exact match, or a regular expression of the form /regexp/") if err := subFlags.Parse(args); err != nil { @@ -1671,7 +1676,7 @@ func commandSourceShardAdd(ctx context.Context, wr *wrangler.Wrangler, subFlags return wr.SourceShardAdd(ctx, keyspace, shard, uint32(uid), skeyspace, sshard, kr, tables) } -func commandShardReplicationAdd(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandShardReplicationAdd(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1696,7 +1701,7 @@ func commandShardReplicationAdd(ctx context.Context, wr *wrangler.Wrangler, subF return err } -func commandShardReplicationRemove(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandShardReplicationRemove(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1721,7 +1726,7 @@ func commandShardReplicationRemove(ctx context.Context, wr *wrangler.Wrangler, s return err } -func commandShardReplicationFix(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandShardReplicationFix(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1738,7 +1743,7 @@ func commandShardReplicationFix(ctx context.Context, wr *wrangler.Wrangler, subF return err } -func commandWaitForFilteredReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWaitForFilteredReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { maxDelay := subFlags.Duration("max_delay", wrangler.DefaultWaitForFilteredReplicationMaxDelay, "Specifies the maximum delay, in seconds, the filtered replication of the"+ " given destination shard should lag behind the source shard. When"+ @@ -1757,7 +1762,7 @@ func commandWaitForFilteredReplication(ctx context.Context, wr *wrangler.Wrangle return wr.WaitForFilteredReplication(ctx, keyspace, shard, *maxDelay) } -func commandRemoveShardCell(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRemoveShardCell(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.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.") recursive := subFlags.Bool("recursive", false, "Also delete all tablets in that cell belonging to the specified shard.") if err := subFlags.Parse(args); err != nil { @@ -1784,7 +1789,7 @@ func commandRemoveShardCell(ctx context.Context, wr *wrangler.Wrangler, subFlags return err } -func commandDeleteShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandDeleteShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { recursive := subFlags.Bool("recursive", false, "Also delete all tablets belonging to the shard.") evenIfServing := subFlags.Bool("even_if_serving", false, "Remove the shard even if it is serving. Use with caution.") if err := subFlags.Parse(args); err != nil { @@ -1812,7 +1817,7 @@ func commandDeleteShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return nil } -func commandCreateKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandCreateKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { force := subFlags.Bool("force", false, "Proceeds even if the keyspace already exists") allowEmptyVSchema := subFlags.Bool("allow_empty_vschema", false, "If set this will allow a new keyspace to have no vschema") @@ -1925,7 +1930,7 @@ func commandCreateKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags return wr.TopoServer().RebuildSrvVSchema(ctx, []string{} /* cells */) } -func commandDeleteKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandDeleteKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { recursive := subFlags.Bool("recursive", false, "Also recursively delete all shards in the keyspace.") if err := subFlags.Parse(args); err != nil { return err @@ -1941,7 +1946,7 @@ func commandDeleteKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags return err } -func commandRemoveKeyspaceCell(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRemoveKeyspaceCell(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.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.") recursive := subFlags.Bool("recursive", false, "Also delete all tablets in that cell belonging to the specified keyspace.") if err := subFlags.Parse(args); err != nil { @@ -1963,7 +1968,7 @@ func commandRemoveKeyspaceCell(ctx context.Context, wr *wrangler.Wrangler, subFl return err } -func commandGetKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -1983,7 +1988,7 @@ func commandGetKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return printJSON(wr.Logger(), keyspaceInfo.Keyspace.Keyspace) } -func commandGetKeyspaces(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetKeyspaces(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { resp, err := wr.VtctldServer().GetKeyspaces(ctx, &vtctldatapb.GetKeyspacesRequest{}) if err != nil { return err @@ -1998,7 +2003,7 @@ func commandGetKeyspaces(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return nil } -func commandRebuildKeyspaceGraph(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandRebuildKeyspaceGraph(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cells := subFlags.String("cells", "", "Specifies a comma-separated list of cells to update") allowPartial := subFlags.Bool("allow_partial", false, "Specifies whether a SNAPSHOT keyspace is allowed to serve with an incomplete set of shards. Ignored for all other types of keyspaces") if err := subFlags.Parse(args); err != nil { @@ -2030,7 +2035,7 @@ func commandRebuildKeyspaceGraph(ctx context.Context, wr *wrangler.Wrangler, sub return nil } -func commandValidateKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidateKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { pingTablets := subFlags.Bool("ping-tablets", false, "Specifies whether all tablets will be pinged during the validation process") if err := subFlags.Parse(args); err != nil { return err @@ -2052,7 +2057,7 @@ func useV1(args []string) bool { return false } -func commandReshard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandReshard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if !useV1(args) { log.Infof("*** Using Reshard v2 flow ***") return commandVRWorkflow(ctx, wr, subFlags, args, wrangler.ReshardWorkflow) @@ -2083,7 +2088,7 @@ func commandReshard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.F *tabletTypes, *autoStart, *stopAfterCopy) } -func commandMoveTables(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandMoveTables(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if !useV1(args) { log.Infof("*** Using MoveTables v2 flow ***") return commandVRWorkflow(ctx, wr, subFlags, args, wrangler.MoveTablesWorkflow) @@ -2141,7 +2146,7 @@ const ( vReplicationWorkflowActionGetState = "getstate" ) -func commandMigrate(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandMigrate(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { return commandVRWorkflow(ctx, wr, subFlags, args, wrangler.MigrateWorkflow) } @@ -2156,7 +2161,7 @@ func getSourceKeyspace(clusterKeyspace string) (clusterName string, sourceKeyspa // commandVRWorkflow is the common entry point for MoveTables/Reshard/Migrate workflows // FIXME: this function needs a refactor. Also validations for params should to be done per workflow type -func commandVRWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string, +func commandVRWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string, workflowType wrangler.VReplicationWorkflowType) error { const defaultWaitTime = time.Duration(30 * time.Second) @@ -2514,7 +2519,7 @@ func commandVRWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *fla return nil } -func commandCreateLookupVindex(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandCreateLookupVindex(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cells := subFlags.String("cells", "", "Source cells to replicate from.") tabletTypes := subFlags.String("tablet_types", "", "Source tablet types to replicate from.") continueAfterCopyWithOwner := subFlags.Bool("continue_after_copy_with_owner", false, "Vindex will continue materialization after copy when an owner is provided") @@ -2532,7 +2537,7 @@ func commandCreateLookupVindex(ctx context.Context, wr *wrangler.Wrangler, subFl return wr.CreateLookupVindex(ctx, keyspace, specs, *cells, *tabletTypes, *continueAfterCopyWithOwner) } -func commandExternalizeVindex(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandExternalizeVindex(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -2542,7 +2547,7 @@ func commandExternalizeVindex(ctx context.Context, wr *wrangler.Wrangler, subFla return wr.ExternalizeVindex(ctx, subFlags.Arg(0)) } -func commandMaterialize(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandMaterialize(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { cells := subFlags.String("cells", "", "Source cells to replicate from.") tabletTypes := subFlags.String("tablet_types", "", "Source tablet types to replicate from.") if err := subFlags.Parse(args); err != nil { @@ -2569,7 +2574,7 @@ func useVDiffV2(args []string) bool { return false } -func commandVDiff(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandVDiff(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if useVDiffV2(args) { log.Infof("*** Using (experimental) VDiff2 ***") return commandVDiff2(ctx, wr, subFlags, args) @@ -2627,7 +2632,7 @@ func splitKeyspaceWorkflow(in string) (keyspace, workflow string, err error) { return splits[0], splits[1], nil } -func commandDropSources(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandDropSources(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { wr.Logger().Printf("*** DropSources is deprecated. Consider using v2 commands instead, see https://vitess.io/docs/reference/vreplication/v2/ ***\n") dryRun := subFlags.Bool("dry_run", false, "Does a dry run of commandDropSources and only reports the actions to be taken") renameTables := subFlags.Bool("rename_tables", false, "Rename tables instead of dropping them") @@ -2660,7 +2665,7 @@ func commandDropSources(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return nil } -func commandSwitchReads(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSwitchReads(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { wr.Logger().Printf("*** SwitchReads is deprecated. Consider using v2 commands instead, see https://vitess.io/docs/reference/vreplication/v2/ ***\n") reverse := subFlags.Bool("reverse", false, "Moves the served tablet type backward instead of forward.") @@ -2706,7 +2711,7 @@ func commandSwitchReads(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return nil } -func commandSwitchWrites(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandSwitchWrites(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { wr.Logger().Printf("*** SwitchWrites is deprecated. Consider using v2 commands instead, see https://vitess.io/docs/reference/vreplication/v2/ ***\n") timeout := subFlags.Duration("timeout", 30*time.Second, "Specifies the maximum time to wait, in seconds, for vreplication to catch up on primary migrations. The migration will be cancelled on a timeout.") @@ -2744,7 +2749,7 @@ func commandSwitchWrites(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return nil } -func commandFindAllShardsInKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandFindAllShardsInKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -2770,7 +2775,7 @@ func commandFindAllShardsInKeyspace(ctx context.Context, wr *wrangler.Wrangler, return printJSON(wr.Logger(), legacyShardMap) } -func commandValidate(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidate(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { pingTablets := subFlags.Bool("ping-tablets", false, "Indicates whether all tablets should be pinged during the validation process") if err := subFlags.Parse(args); err != nil { return err @@ -2782,7 +2787,7 @@ func commandValidate(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag. return wr.Validate(ctx, *pingTablets) } -func commandListAllTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandListAllTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { keyspaceFilter := subFlags.String("keyspace", "", "Keyspace to filter on") tabletTypeStr := subFlags.String("tablet_type", "", "Tablet type to filter on") var err error @@ -2819,7 +2824,7 @@ func commandListAllTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags return nil } -func commandListTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandListTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -2852,7 +2857,7 @@ func commandListTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return nil } -func commandGetSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { tables := subFlags.String("tables", "", "Specifies a comma-separated list of tables for which we should gather information. Each is either an exact match, or a regular expression of the form /regexp/") excludeTables := subFlags.String("exclude_tables", "", "Specifies a comma-separated list of tables to exclude. Each is either an exact match, or a regular expression of the form /regexp/") includeViews := subFlags.Bool("include-views", false, "Includes views in the output") @@ -2903,7 +2908,7 @@ func commandGetSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag return printJSON(wr.Logger(), resp.Schema) } -func commandReloadSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandReloadSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -2920,7 +2925,7 @@ func commandReloadSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return err } -func commandReloadSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandReloadSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { concurrency := subFlags.Int("concurrency", 10, "How many tablets to reload in parallel") includePrimary := subFlags.Bool("include_primary", true, "Include the primary tablet") @@ -2949,7 +2954,7 @@ func commandReloadSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFla return err } -func commandReloadSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandReloadSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { concurrency := subFlags.Int("concurrency", 10, "How many tablets to reload in parallel") includePrimary := subFlags.Bool("include_primary", true, "Include the primary tablet(s)") @@ -2973,7 +2978,7 @@ func commandReloadSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, sub return err } -func commandValidateSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidateSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { excludeTables := subFlags.String("exclude_tables", "", "Specifies a comma-separated list of tables to exclude. Each is either an exact match, or a regular expression of the form /regexp/") includeViews := subFlags.Bool("include-views", false, "Includes views in the validation") includeVSchema := subFlags.Bool("include-vschema", false, "Validate schemas against the vschema") @@ -2995,7 +3000,7 @@ func commandValidateSchemaShard(ctx context.Context, wr *wrangler.Wrangler, subF return wr.ValidateSchemaShard(ctx, keyspace, shard, excludeTableArray, *includeViews, *includeVSchema) } -func commandValidateSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidateSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { excludeTables := subFlags.String("exclude_tables", "", "Specifies a comma-separated list of tables to exclude. Each is either an exact match, or a regular expression of the form /regexp/") includeViews := subFlags.Bool("include-views", false, "Includes views in the validation") skipNoPrimary := subFlags.Bool("skip-no-primary", true, "Skip shards that don't have primary when performing validation") @@ -3037,7 +3042,7 @@ func commandValidateSchemaKeyspace(ctx context.Context, wr *wrangler.Wrangler, s return nil } -func commandApplySchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandApplySchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { allowLongUnavailability := subFlags.Bool("allow_long_unavailability", false, "Allow large schema changes which incur a longer unavailability of the database.") sql := subFlags.String("sql", "", "A list of semicolon-delimited SQL commands") sqlFile := subFlags.String("sql-file", "", "Identifies the file that contains the SQL commands") @@ -3105,7 +3110,7 @@ func commandApplySchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return nil } -func commandOnlineDDL(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandOnlineDDL(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { json := subFlags.Bool("json", false, "Output JSON instead of human-readable table") orderBy := subFlags.String("order", "ascending", "Sort the results by `id` property of the Schema migration (default is ascending. Allowed values are `ascending` or `descending`.") limit := subFlags.Int64("limit", 0, "Limit number of rows returned in output") @@ -3206,7 +3211,7 @@ func commandOnlineDDL(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag return nil } -func commandCopySchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandCopySchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { tables := subFlags.String("tables", "", "Specifies a comma-separated list of tables to copy. Each is either an exact match, or a regular expression of the form /regexp/") excludeTables := subFlags.String("exclude_tables", "", "Specifies a comma-separated list of tables to exclude. Each is either an exact match, or a regular expression of the form /regexp/") includeViews := subFlags.Bool("include-views", true, "Includes views in the output") @@ -3244,7 +3249,7 @@ func commandCopySchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags return err } -func commandValidateVersionShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidateVersionShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3259,7 +3264,7 @@ func commandValidateVersionShard(ctx context.Context, wr *wrangler.Wrangler, sub return wr.ValidateVersionShard(ctx, keyspace, shard) } -func commandValidateVersionKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidateVersionKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3285,7 +3290,7 @@ func commandValidateVersionKeyspace(ctx context.Context, wr *wrangler.Wrangler, return nil } -func commandGetPermissions(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetPermissions(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3310,7 +3315,7 @@ func commandGetPermissions(ctx context.Context, wr *wrangler.Wrangler, subFlags return nil } -func commandValidatePermissionsShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidatePermissionsShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3325,7 +3330,7 @@ func commandValidatePermissionsShard(ctx context.Context, wr *wrangler.Wrangler, return wr.ValidatePermissionsShard(ctx, keyspace, shard) } -func commandValidatePermissionsKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandValidatePermissionsKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3337,7 +3342,7 @@ func commandValidatePermissionsKeyspace(ctx context.Context, wr *wrangler.Wrangl return wr.ValidatePermissionsKeyspace(ctx, keyspace) } -func commandGetVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3358,7 +3363,7 @@ func commandGetVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *fla return nil } -func commandGetRoutingRules(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetRoutingRules(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3377,9 +3382,9 @@ func commandGetRoutingRules(ctx context.Context, wr *wrangler.Wrangler, subFlags return nil } -func commandRebuildVSchemaGraph(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { - var cells flagutil.StringListValue - subFlags.Var(&cells, "cells", "Specifies a comma-separated list of cells to look for tablets") +func commandRebuildVSchemaGraph(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { + var cells []string + subFlags.StringSliceVar(&cells, "cells", cells, "Specifies a comma-separated list of cells to look for tablets") if err := subFlags.Parse(args); err != nil { return err @@ -3394,15 +3399,15 @@ func commandRebuildVSchemaGraph(ctx context.Context, wr *wrangler.Wrangler, subF return err } -func commandApplyVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandApplyVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { vschema := subFlags.String("vschema", "", "Identifies the VTGate routing schema") vschemaFile := subFlags.String("vschema_file", "", "Identifies the VTGate routing schema file") sql := subFlags.String("sql", "", "A vschema ddl SQL statement (e.g. `add vindex`, `alter table t add vindex hash(id)`, etc)") sqlFile := subFlags.String("sql_file", "", "A vschema ddl SQL statement (e.g. `add vindex`, `alter table t add vindex hash(id)`, etc)") dryRun := subFlags.Bool("dry-run", false, "If set, do not save the altered vschema, simply echo to console.") skipRebuild := subFlags.Bool("skip_rebuild", false, "If set, do not rebuild the SrvSchema objects.") - var cells flagutil.StringListValue - subFlags.Var(&cells, "cells", "If specified, limits the rebuild to the cells, after upload. Ignored if --skip_rebuild is set.") + var cells []string + subFlags.StringSliceVar(&cells, "cells", cells, "If specified, limits the rebuild to the cells, after upload. Ignored if --skip_rebuild is set.") if err := subFlags.Parse(args); err != nil { return err @@ -3508,13 +3513,13 @@ func commandApplyVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return wr.TopoServer().RebuildSrvVSchema(ctx, cells) } -func commandApplyRoutingRules(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandApplyRoutingRules(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { routingRules := subFlags.String("rules", "", "Specify rules as a string") routingRulesFile := subFlags.String("rules_file", "", "Specify rules in a file") skipRebuild := subFlags.Bool("skip_rebuild", false, "If set, do no rebuild the SrvSchema objects.") dryRun := subFlags.Bool("dry-run", false, "Do not upload the routing rules, but print what actions would be taken") - var cells flagutil.StringListValue - subFlags.Var(&cells, "cells", "If specified, limits the rebuild to the cells, after upload. Ignored if skipRebuild is set.") + var cells []string + subFlags.StringSliceVar(&cells, "cells", cells, "If specified, limits the rebuild to the cells, after upload. Ignored if skipRebuild is set.") if err := subFlags.Parse(args); err != nil { return err @@ -3584,7 +3589,7 @@ func commandApplyRoutingRules(ctx context.Context, wr *wrangler.Wrangler, subFla return nil } -func commandGetSrvKeyspaceNames(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetSrvKeyspaceNames(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3613,7 +3618,7 @@ func commandGetSrvKeyspaceNames(ctx context.Context, wr *wrangler.Wrangler, subF return nil } -func commandGetSrvKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetSrvKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3639,7 +3644,7 @@ func commandGetSrvKeyspace(ctx context.Context, wr *wrangler.Wrangler, subFlags return printJSON(wr.Logger(), cellKs) } -func commandGetSrvVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetSrvVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3654,7 +3659,7 @@ func commandGetSrvVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags * return printJSON(wr.Logger(), srvVSchema) } -func commandDeleteSrvVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandDeleteSrvVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3668,7 +3673,7 @@ func commandDeleteSrvVSchema(ctx context.Context, wr *wrangler.Wrangler, subFlag return err } -func commandGetShardReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGetShardReplication(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3688,7 +3693,7 @@ func commandGetShardReplication(ctx context.Context, wr *wrangler.Wrangler, subF return printJSON(wr.Logger(), shardReplication.ShardReplication) } -func commandHelp(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandHelp(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if err := subFlags.Parse(args); err != nil { return err } @@ -3705,7 +3710,7 @@ func commandHelp(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.Flag return nil } -func commandVExec(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandVExec(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { deprecationMessage := `VExec command will be deprecated in version v12. For Online DDL control, use "vtctl OnlineDDL" commands or SQL syntax` log.Warningf(deprecationMessage) @@ -3744,7 +3749,7 @@ func commandVExec(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.Fla return nil } -func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { dryRun := subFlags.Bool("dry_run", false, "Does a dry run of Workflow and only reports the final query and list of tablets on which the operation will be applied") if err := subFlags.Parse(args); err != nil { return err @@ -3807,7 +3812,7 @@ func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag. return nil } -func commandMount(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandMount(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { clusterType := subFlags.String("type", "vitess", "Specify cluster type: mysql or vitess, only vitess clustered right now") unmount := subFlags.Bool("unmount", false, "Unmount cluster") show := subFlags.Bool("show", false, "Display contents of cluster") @@ -3863,7 +3868,7 @@ func commandMount(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.Fla } } -func commandGenerateShardRanges(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandGenerateShardRanges(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { numShards := subFlags.Int("num_shards", 2, "Number of shards to generate shard ranges for.") if err := subFlags.Parse(args); err != nil { @@ -3878,7 +3883,7 @@ func commandGenerateShardRanges(ctx context.Context, wr *wrangler.Wrangler, subF return printJSON(wr.Logger(), shardRanges) } -func commandPanic(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandPanic(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { panic(fmt.Errorf("this command panics on purpose")) } @@ -3973,30 +3978,42 @@ func RunCommand(ctx context.Context, wr *wrangler.Wrangler, args []string) error for _, group := range commands { for _, cmd := range group.commands { if strings.ToLower(cmd.name) == actionLowerCase { - subFlags := flag.NewFlagSet(action, flag.ContinueOnError) + subFlags := pflag.NewFlagSet(action, pflag.ContinueOnError) subFlags.SetOutput(logutil.NewLoggerWriter(wr.Logger())) - _flag.SetUsage(subFlags, _flag.UsageOptions{ - Preface: func(w io.Writer) { - if cmd.deprecated { - msg := &strings.Builder{} - msg.WriteString("WARNING: ") - msg.WriteString(action) - msg.WriteString(" is deprecated and will be removed in a future release.") - if cmd.deprecatedBy != "" { - msg.WriteString(" Use ") - msg.WriteString(cmd.deprecatedBy) - msg.WriteString(" instead.") - } - - wr.Logger().Printf("%s\n", msg.String()) + subFlags.Usage = func() { + if cmd.deprecated { + msg := &strings.Builder{} + msg.WriteString("WARNING: ") + msg.WriteString(action) + msg.WriteString(" is deprecated and will be removed in a future release.") + if cmd.deprecatedBy != "" { + msg.WriteString(" Use ") + msg.WriteString(cmd.deprecatedBy) + msg.WriteString(" instead.") } - wr.Logger().Printf("Usage: %s %s\n\n", action, cmd.params) - wr.Logger().Printf("%s\n\n", cmd.help) - }, - }) + wr.Logger().Printf("%s\n", msg.String()) + } + + wr.Logger().Printf("Usage: %s %s\n\n", action, cmd.params) + wr.Logger().Printf("%s\n\n", cmd.help) - return cmd.method(ctx, wr, subFlags, args[1:]) + wr.Logger().Printf("%s\n", subFlags.FlagUsages()) + } + + if len(args) > 1 && args[1] == "--" && !cmd.disableFlagInterspersal { + PrintDoubleDashDeprecationNotice(wr) + args = args[1:] + } + + switch err := cmd.method(ctx, wr, subFlags, args[1:]); err { + case pflag.ErrHelp: + // Don't actually error if the user requested --help on a + // subcommand. + return nil + default: + return err + } } } } @@ -4005,6 +4022,17 @@ func RunCommand(ctx context.Context, wr *wrangler.Wrangler, args []string) error return ErrUnknownCommand } +func PrintDoubleDashDeprecationNotice(wr *wrangler.Wrangler) { + msg := (`DEPRECATION NOTICE: in v14, users needed to add a double-dash ("--") separator to split up top-level and sub-command arguments/flags. +Beginning in v16, this will no longer work properly. Please remove any double-dashes that preceed sub-command **flags** only. + +Note that this does not mean you do not need a separator to split up position arguments. +For example, to pass a flag to a hook via ExecuteHook, "vtctl ExecuteHook myhook.sh -- --hook-flag 5" is the correct formation. +For v1 Reshard commands, you will also need a separator if your shard names begin with a hyphen, i.e. "Reshard ks.workflow -- -80,80-" needs a double-dash, but "Reshard ks.workflow 40-80,80-c0" does not.`) + + wr.Logger().Warningf(msg) +} + // PrintAllCommands will print the list of commands to the logger func PrintAllCommands(logger logutil.Logger) { msg := &strings.Builder{} @@ -4035,9 +4063,9 @@ func PrintAllCommands(logger logutil.Logger) { // userPassedFlag returns true if the flag name given was provided // as a command-line argument by the user. -func userPassedFlag(flags *flag.FlagSet, name string) bool { +func userPassedFlag(flags *pflag.FlagSet, name string) bool { passed := false - flags.Visit(func(f *flag.Flag) { + flags.Visit(func(f *pflag.Flag) { if f.Name == name { passed = true } diff --git a/go/vt/vtctl/workflow.go b/go/vt/vtctl/workflow.go index 5fe7d444ece..88a4053f1c1 100644 --- a/go/vt/vtctl/workflow.go +++ b/go/vt/vtctl/workflow.go @@ -18,9 +18,10 @@ package vtctl import ( "context" - "flag" "fmt" + "github.com/spf13/pflag" + "vitess.io/vitess/go/vt/workflow" "vitess.io/vitess/go/vt/wrangler" ) @@ -83,7 +84,7 @@ func init() { }) } -func commandWorkflowCreate(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflowCreate(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } @@ -109,7 +110,7 @@ func commandWorkflowCreate(ctx context.Context, wr *wrangler.Wrangler, subFlags return nil } -func commandWorkflowStart(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflowStart(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } @@ -124,7 +125,7 @@ func commandWorkflowStart(ctx context.Context, wr *wrangler.Wrangler, subFlags * return WorkflowManager.Start(ctx, uuid) } -func commandWorkflowStop(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflowStop(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } @@ -139,7 +140,7 @@ func commandWorkflowStop(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return WorkflowManager.Stop(ctx, uuid) } -func commandWorkflowDelete(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflowDelete(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } @@ -154,7 +155,7 @@ func commandWorkflowDelete(ctx context.Context, wr *wrangler.Wrangler, subFlags return WorkflowManager.Delete(ctx, uuid) } -func commandWorkflowWait(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflowWait(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } @@ -169,7 +170,7 @@ func commandWorkflowWait(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return WorkflowManager.Wait(ctx, uuid) } -func commandWorkflowTree(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflowTree(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } @@ -189,7 +190,7 @@ func commandWorkflowTree(ctx context.Context, wr *wrangler.Wrangler, subFlags *f return nil } -func commandWorkflowAction(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { +func commandWorkflowAction(ctx context.Context, wr *wrangler.Wrangler, subFlags *pflag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } diff --git a/go/vt/wrangler/testlib/apply_schema_flaky_test.go b/go/vt/wrangler/testlib/apply_schema_flaky_test.go index 9a39d373d5e..de72983aa3b 100644 --- a/go/vt/wrangler/testlib/apply_schema_flaky_test.go +++ b/go/vt/wrangler/testlib/apply_schema_flaky_test.go @@ -38,7 +38,7 @@ import ( ) // TestApplySchema_AllowLongUnavailability is an integration test for the -// -allow_long_unavailability flag of vtctl ApplySchema. +// --allow_long_unavailability flag of vtctl ApplySchema. // Only if the flag is specified, potentially long running schema changes are // allowed. func TestApplySchema_AllowLongUnavailability(t *testing.T) { @@ -107,7 +107,7 @@ func TestApplySchema_AllowLongUnavailability(t *testing.T) { db.AddQuery(addColumn, &sqltypes.Result{}) // First ApplySchema fails because the table is very big and -allow_long_unavailability is missing. - if err := vp.Run([]string{"ApplySchema", "-sql", addColumn, "ks"}); err == nil { + if err := vp.Run([]string{"ApplySchema", "--sql", addColumn, "ks"}); err == nil { t.Fatal("ApplySchema should have failed but did not.") } else if !strings.Contains(err.Error(), "big schema change detected") || !strings.Contains(strings.ToLower(err.Error()), "alter table table1") { @@ -115,7 +115,7 @@ func TestApplySchema_AllowLongUnavailability(t *testing.T) { } // Second ApplySchema succeeds because -allow_long_unavailability is set. - if err := vp.Run([]string{"ApplySchema", "-allow_long_unavailability", "-sql", addColumn, "ks"}); err != nil { + if err := vp.Run([]string{"ApplySchema", "--allow_long_unavailability", "--sql", addColumn, "ks"}); err != nil { t.Fatalf("ApplySchema failed: %v", err) } if count := db.GetQueryCalledNum(changeToDb); count != 2 { diff --git a/go/vt/wrangler/testlib/copy_schema_shard_test.go b/go/vt/wrangler/testlib/copy_schema_shard_test.go index e23e687e272..8620d7e7565 100644 --- a/go/vt/wrangler/testlib/copy_schema_shard_test.go +++ b/go/vt/wrangler/testlib/copy_schema_shard_test.go @@ -172,7 +172,7 @@ func copySchema(t *testing.T, useShardAsSource bool) { if useShardAsSource { source = "ks/-80" } - if err := vp.Run([]string{"CopySchemaShard", "-include-views", source, "ks/-40"}); err != nil { + if err := vp.Run([]string{"CopySchemaShard", "--include-views", source, "ks/-40"}); err != nil { t.Fatalf("CopySchemaShard failed: %v", err) } diff --git a/go/vt/wrangler/testlib/emergency_reparent_shard_test.go b/go/vt/wrangler/testlib/emergency_reparent_shard_test.go index a8066ea4fb0..014029504a9 100644 --- a/go/vt/wrangler/testlib/emergency_reparent_shard_test.go +++ b/go/vt/wrangler/testlib/emergency_reparent_shard_test.go @@ -181,7 +181,7 @@ func TestEmergencyReparentShard(t *testing.T) { // run EmergencyReparentShard waitReplicaTimeout := time.Second * 2 - err := vp.Run([]string{"EmergencyReparentShard", "-wait_replicas_timeout", waitReplicaTimeout.String(), newPrimary.Tablet.Keyspace + "/" + newPrimary.Tablet.Shard, + err := vp.Run([]string{"EmergencyReparentShard", "--wait_replicas_timeout", waitReplicaTimeout.String(), newPrimary.Tablet.Keyspace + "/" + newPrimary.Tablet.Shard, topoproto.TabletAliasString(newPrimary.Tablet.Alias)}) require.NoError(t, err) // check what was run diff --git a/go/vt/wrangler/testlib/shard_test.go b/go/vt/wrangler/testlib/shard_test.go index 9fd4a3000e7..1b00ad82769 100644 --- a/go/vt/wrangler/testlib/shard_test.go +++ b/go/vt/wrangler/testlib/shard_test.go @@ -68,7 +68,7 @@ func TestDeleteShardCleanup(t *testing.T) { // without recursive flag, should fail on existing tablets. if err := vp.Run([]string{ "DeleteShard", - "-even_if_serving", + "--even_if_serving", primary.Tablet.Keyspace + "/" + primary.Tablet.Shard, }); err == nil || !strings.Contains(err.Error(), "use -recursive or remove them manually") { t.Fatalf("DeleteShard(evenIfServing=true) returned wrong error: %v", err) @@ -78,8 +78,8 @@ func TestDeleteShardCleanup(t *testing.T) { // it should just work. if err := vp.Run([]string{ "DeleteShard", - "-recursive", - "-even_if_serving", + "--recursive", + "--even_if_serving", primary.Tablet.Keyspace + "/" + primary.Tablet.Shard, }); err != nil { t.Fatalf("DeleteShard(recursive=true, evenIfServing=true) should have worked but returned: %v", err) diff --git a/go/vt/wrangler/testlib/vtctl_topo_test.go b/go/vt/wrangler/testlib/vtctl_topo_test.go index 932132a38f7..d3dd5d8cb21 100644 --- a/go/vt/wrangler/testlib/vtctl_topo_test.go +++ b/go/vt/wrangler/testlib/vtctl_topo_test.go @@ -65,7 +65,7 @@ func TestVtctlTopoCommands(t *testing.T) { tmp := t.TempDir() // Test TopoCat. - testVtctlTopoCommand(t, vp, []string{"TopoCat", "-long", "-decode_proto", "/keyspaces/*/Keyspace"}, `path=/keyspaces/ks1/Keyspace version=V + testVtctlTopoCommand(t, vp, []string{"TopoCat", "--long", "--decode_proto", "/keyspaces/*/Keyspace"}, `path=/keyspaces/ks1/Keyspace version=V path=/keyspaces/ks2/Keyspace version=V keyspace_type:SNAPSHOT `) @@ -90,7 +90,7 @@ keyspace_type:SNAPSHOT } // Test TopoCp from disk to topo. - _, err = vp.RunAndOutput([]string{"TopoCp", "-to_topo", ksFile, "/keyspaces/ks3/Keyspace"}) + _, err = vp.RunAndOutput([]string{"TopoCp", "--to_topo", ksFile, "/keyspaces/ks3/Keyspace"}) if err != nil { t.Fatalf("TopoCp(/keyspaces/ks3/Keyspace) failed: %v", err) } diff --git a/web/vtctld2/app/index.html b/web/vtctld2/app/index.html index 7b89e825df0..08884ffd6be 100644 --- a/web/vtctld2/app/index.html +++ b/web/vtctld2/app/index.html @@ -27,5 +27,5 @@ Loading... - + diff --git a/web/vtctld2/app/inline.js b/web/vtctld2/app/inline.js index 76ae7eb4efa..6893c536150 100644 --- a/web/vtctld2/app/inline.js +++ b/web/vtctld2/app/inline.js @@ -1 +1 @@ -!function(e){function __webpack_require__(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,__webpack_require__),n.l=!0,n.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,o,c){for(var _,a,i,u=0,p=[];u=this.length?i.$EOF:o.StringWrapper.charCodeAt(this.input,this.index)},_Scanner.prototype.scanToken=function(){for(var e=this.input,t=this.length,n=this.peek,r=this.index;n<=i.$SPACE;){if(++r>=t){n=i.$EOF;break}n=o.StringWrapper.charCodeAt(e,r)}if(this.peek=n,this.index=r,r>=t)return null;if(isIdentifierStart(n))return this.scanIdentifier();if(i.isDigit(n))return this.scanNumber(r);var s=r;switch(n){case i.$PERIOD:return this.advance(),i.isDigit(this.peek)?this.scanNumber(s):newCharacterToken(s,i.$PERIOD);case i.$LPAREN:case i.$RPAREN:case i.$LBRACE:case i.$RBRACE:case i.$LBRACKET:case i.$RBRACKET:case i.$COMMA:case i.$COLON:case i.$SEMICOLON:return this.scanCharacter(s,n);case i.$SQ:case i.$DQ:return this.scanString();case i.$HASH:case i.$PLUS:case i.$MINUS:case i.$STAR:case i.$SLASH:case i.$PERCENT:case i.$CARET:return this.scanOperator(s,o.StringWrapper.fromCharCode(n));case i.$QUESTION:return this.scanComplexOperator(s,"?",i.$PERIOD,".");case i.$LT:case i.$GT:return this.scanComplexOperator(s,o.StringWrapper.fromCharCode(n),i.$EQ,"=");case i.$BANG:case i.$EQ:return this.scanComplexOperator(s,o.StringWrapper.fromCharCode(n),i.$EQ,"=",i.$EQ,"=");case i.$AMPERSAND:return this.scanComplexOperator(s,"&",i.$AMPERSAND,"&");case i.$BAR:return this.scanComplexOperator(s,"|",i.$BAR,"|");case i.$NBSP:for(;i.isWhitespace(this.peek);)this.advance();return this.scanToken()}return this.advance(),this.error("Unexpected character ["+o.StringWrapper.fromCharCode(n)+"]",0)},_Scanner.prototype.scanCharacter=function(e,t){return this.advance(),newCharacterToken(e,t)},_Scanner.prototype.scanOperator=function(e,t){return this.advance(),newOperatorToken(e,t)},_Scanner.prototype.scanComplexOperator=function(e,t,n,r,i,s){this.advance();var a=t;return this.peek==n&&(this.advance(),a+=r),o.isPresent(i)&&this.peek==i&&(this.advance(),a+=s),newOperatorToken(e,a)},_Scanner.prototype.scanIdentifier=function(){var e=this.index;for(this.advance();isIdentifierPart(this.peek);)this.advance();var t=this.input.substring(e,this.index);return a.indexOf(t)>-1?newKeywordToken(e,t):newIdentifierToken(e,t)},_Scanner.prototype.scanNumber=function(e){var t=this.index===e;for(this.advance();;){if(i.isDigit(this.peek));else if(this.peek==i.$PERIOD)t=!1;else{if(!isExponentStart(this.peek))break;if(this.advance(),isExponentSign(this.peek)&&this.advance(),!i.isDigit(this.peek))return this.error("Invalid exponent",-1);t=!1}this.advance()}var n=this.input.substring(e,this.index),r=t?o.NumberWrapper.parseIntAutoRadix(n):o.NumberWrapper.parseFloat(n);return newNumberToken(e,r)},_Scanner.prototype.scanString=function(){var e=this.index,t=this.peek;this.advance();for(var n,r=this.index,s=this.input;this.peek!=t;)if(this.peek==i.$BACKSLASH){null==n&&(n=new o.StringJoiner),n.add(s.substring(r,this.index)),this.advance();var a;if(this.peek==i.$u){var l=s.substring(this.index+1,this.index+5);try{a=o.NumberWrapper.parseInt(l,16)}catch(c){return this.error("Invalid unicode escape [\\u"+l+"]",0)}for(var u=0;u<5;u++)this.advance()}else a=unescape(this.peek),this.advance();n.add(o.StringWrapper.fromCharCode(a)),r=this.index}else{if(this.peek==i.$EOF)return this.error("Unterminated quote",0);this.advance()}var p=s.substring(r,this.index);this.advance();var d=p;return null!=n&&(n.add(p),d=n.toString()),newStringToken(e,d)},_Scanner.prototype.error=function(e,t){var n=this.index+t;return newErrorToken(n,"Lexer Error: "+e+" at column "+n+" in expression ["+this.input+"]")},_Scanner}();t.isIdentifier=isIdentifier,t.isQuote=isQuote},function(e,t,n){"use strict";function _createInterpolateRegExp(e){var t=o.escapeRegExp(e.start)+"([\\s\\S]*?)"+o.escapeRegExp(e.end);return new RegExp(t,"g")}var r=n(0),i=n(233),o=n(5),s=n(68),a=n(236),l=n(151),c=function(){function SplitInterpolation(e,t){this.strings=e,this.expressions=t}return SplitInterpolation}();t.SplitInterpolation=c;var u=function(){function TemplateBindingParseResult(e,t,n){this.templateBindings=e,this.warnings=t,this.errors=n}return TemplateBindingParseResult}();t.TemplateBindingParseResult=u;var p=function(){function Parser(e){this._lexer=e,this.errors=[]}return Parser.prototype.parseAction=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG),this._checkNoInterpolation(e,t,n);var r=this._lexer.tokenize(this._stripComments(e)),i=new d(e,t,r,(!0),this.errors).parseChain();return new a.ASTWithSource(i,e,t,this.errors)},Parser.prototype.parseBinding=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG);var r=this._parseBindingAst(e,t,n);return new a.ASTWithSource(r,e,t,this.errors)},Parser.prototype.parseSimpleBinding=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG);var r=this._parseBindingAst(e,t,n);return h.check(r)||this._reportError("Host binding expression can only contain field access and constants",e,t),new a.ASTWithSource(r,e,t,this.errors)},Parser.prototype._reportError=function(e,t,n,r){this.errors.push(new a.ParserError(e,t,n,r))},Parser.prototype._parseBindingAst=function(e,t,n){var r=this._parseQuote(e,t);if(o.isPresent(r))return r;this._checkNoInterpolation(e,t,n);var i=this._lexer.tokenize(this._stripComments(e));return new d(e,t,i,(!1),this.errors).parseChain()},Parser.prototype._parseQuote=function(e,t){if(o.isBlank(e))return null;var n=e.indexOf(":");if(n==-1)return null;var r=e.substring(0,n).trim();if(!l.isIdentifier(r))return null;var i=e.substring(n+1);return new a.Quote(new a.ParseSpan(0,e.length),r,i,t)},Parser.prototype.parseTemplateBindings=function(e,t){var n=this._lexer.tokenize(e);return new d(e,t,n,(!1),this.errors).parseTemplateBindings()},Parser.prototype.parseInterpolation=function(e,t,n){void 0===n&&(n=s.DEFAULT_INTERPOLATION_CONFIG);var r=this.splitInterpolation(e,t,n);if(null==r)return null;for(var i=[],l=0;l0?l.push(p):this._reportError("Blank expressions are not allowed in interpolated strings",e,"at column "+this._findInterpolationErrorColumn(i,u,n)+" in",t)}return new c(a,l)},Parser.prototype.wrapLiteralPrimitive=function(e,t){return new a.ASTWithSource(new a.LiteralPrimitive(new a.ParseSpan(0,o.isBlank(e)?0:e.length),e),e,t,this.errors)},Parser.prototype._stripComments=function(e){var t=this._commentStart(e);return o.isPresent(t)?e.substring(0,t).trim():e},Parser.prototype._commentStart=function(e){for(var t=null,n=0;n1&&this._reportError("Got interpolation ("+n.start+n.end+") where expression was expected",e,"at column "+this._findInterpolationErrorColumn(i,1,n)+" in",t)},Parser.prototype._findInterpolationErrorColumn=function(e,t,n){for(var r="",i=0;i":case"<=":case">=":this.advance();var n=this.parseAdditive();e=new a.Binary(this.span(e.span.start),t,e,n);continue}break}return e},_ParseAST.prototype.parseAdditive=function(){for(var e=this.parseMultiplicative();this.next.type==l.TokenType.Operator;){var t=this.next.strValue;switch(t){case"+":case"-":this.advance();var n=this.parseMultiplicative();e=new a.Binary(this.span(e.span.start),t,e,n);continue}break}return e},_ParseAST.prototype.parseMultiplicative=function(){for(var e=this.parsePrefix();this.next.type==l.TokenType.Operator;){var t=this.next.strValue;switch(t){case"*":case"%":case"/":this.advance();var n=this.parsePrefix();e=new a.Binary(this.span(e.span.start),t,e,n);continue}break}return e},_ParseAST.prototype.parsePrefix=function(){if(this.next.type==l.TokenType.Operator){var e=this.inputIndex,t=this.next.strValue,n=void 0;switch(t){case"+":return this.advance(),this.parsePrefix();case"-":return this.advance(),n=this.parsePrefix(),new a.Binary(this.span(e),t,new a.LiteralPrimitive(new a.ParseSpan(e,e),0),n);case"!":return this.advance(),n=this.parsePrefix(),new a.PrefixNot(this.span(e),n)}}return this.parseCallChain()},_ParseAST.prototype.parseCallChain=function(){for(var e=this.parsePrimary();;)if(this.optionalCharacter(i.$PERIOD))e=this.parseAccessMemberOrMethodCall(e,!1);else if(this.optionalOperator("?."))e=this.parseAccessMemberOrMethodCall(e,!0);else if(this.optionalCharacter(i.$LBRACKET)){this.rbracketsExpected++;var t=this.parsePipe();if(this.rbracketsExpected--,this.expectCharacter(i.$RBRACKET),this.optionalOperator("=")){var n=this.parseConditional();e=new a.KeyedWrite(this.span(e.span.start),e,t,n)}else e=new a.KeyedRead(this.span(e.span.start),e,t)}else{if(!this.optionalCharacter(i.$LPAREN))return e;this.rparensExpected++;var r=this.parseCallArguments();this.rparensExpected--,this.expectCharacter(i.$RPAREN),e=new a.FunctionCall(this.span(e.span.start),e,r)}},_ParseAST.prototype.parsePrimary=function(){var e=this.inputIndex;if(this.optionalCharacter(i.$LPAREN)){this.rparensExpected++;var t=this.parsePipe();return this.rparensExpected--,this.expectCharacter(i.$RPAREN),t}if(this.next.isKeywordNull())return this.advance(),new a.LiteralPrimitive(this.span(e),null);if(this.next.isKeywordUndefined())return this.advance(),new a.LiteralPrimitive(this.span(e),(void 0));if(this.next.isKeywordTrue())return this.advance(),new a.LiteralPrimitive(this.span(e),(!0));if(this.next.isKeywordFalse())return this.advance(),new a.LiteralPrimitive(this.span(e),(!1));if(this.next.isKeywordThis())return this.advance(),new a.ImplicitReceiver(this.span(e));if(this.optionalCharacter(i.$LBRACKET)){this.rbracketsExpected++;var n=this.parseExpressionList(i.$RBRACKET);return this.rbracketsExpected--,this.expectCharacter(i.$RBRACKET),new a.LiteralArray(this.span(e),n)}if(this.next.isCharacter(i.$LBRACE))return this.parseLiteralMap();if(this.next.isIdentifier())return this.parseAccessMemberOrMethodCall(new a.ImplicitReceiver(this.span(e)),!1);if(this.next.isNumber()){var r=this.next.toNumber();return this.advance(),new a.LiteralPrimitive(this.span(e),r)}if(this.next.isString()){var o=this.next.toString();return this.advance(),new a.LiteralPrimitive(this.span(e),o)}return this.index>=this.tokens.length?(this.error("Unexpected end of expression: "+this.input),new a.EmptyExpr(this.span(e))):(this.error("Unexpected token "+this.next),new a.EmptyExpr(this.span(e)))},_ParseAST.prototype.parseExpressionList=function(e){var t=[];if(!this.next.isCharacter(e))do t.push(this.parsePipe());while(this.optionalCharacter(i.$COMMA));return t},_ParseAST.prototype.parseLiteralMap=function(){var e=[],t=[],n=this.inputIndex;if(this.expectCharacter(i.$LBRACE),!this.optionalCharacter(i.$RBRACE)){this.rbracesExpected++;do{var r=this.expectIdentifierOrKeywordOrString();e.push(r),this.expectCharacter(i.$COLON),t.push(this.parsePipe())}while(this.optionalCharacter(i.$COMMA));this.rbracesExpected--,this.expectCharacter(i.$RBRACE)}return new a.LiteralMap(this.span(n),e,t)},_ParseAST.prototype.parseAccessMemberOrMethodCall=function(e,t){void 0===t&&(t=!1);var n=e.span.start,r=this.expectIdentifierOrKeyword();if(this.optionalCharacter(i.$LPAREN)){this.rparensExpected++;var o=this.parseCallArguments();this.expectCharacter(i.$RPAREN),this.rparensExpected--;var s=this.span(n);return t?new a.SafeMethodCall(s,e,r,o):new a.MethodCall(s,e,r,o)}if(t)return this.optionalOperator("=")?(this.error("The '?.' operator cannot be used in the assignment"),new a.EmptyExpr(this.span(n))):new a.SafePropertyRead(this.span(n),e,r);if(this.optionalOperator("=")){if(!this.parseAction)return this.error("Bindings cannot contain assignments"),new a.EmptyExpr(this.span(n));var l=this.parseConditional();return new a.PropertyWrite(this.span(n),e,r,l)}return new a.PropertyRead(this.span(n),e,r)},_ParseAST.prototype.parseCallArguments=function(){if(this.next.isCharacter(i.$RPAREN))return[];var e=[];do e.push(this.parsePipe());while(this.optionalCharacter(i.$COMMA));return e},_ParseAST.prototype.expectTemplateBindingKey=function(){var e="",t=!1;do e+=this.expectIdentifierOrKeywordOrString(),t=this.optionalOperator("-"),t&&(e+="-");while(t);return e.toString()},_ParseAST.prototype.parseTemplateBindings=function(){for(var e=[],t=null,n=[];this.index0&&e[e.length-1]===t}var r=this&&this.__extends||function(e,t){function __(){this.constructor=e}for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);e.prototype=null===t?Object.create(t):(__.prototype=t.prototype,new __)},i=n(10),o=n(5),s=n(60),a=n(85),l=n(68),c=n(546),u=n(102),p=function(e){function TreeError(t,n,r){e.call(this,n,r),this.elementName=t}return r(TreeError,e),TreeError.create=function(e,t,n){return new TreeError(e,t,n)},TreeError}(s.ParseError);t.TreeError=p;var d=function(){function ParseTreeResult(e,t){this.rootNodes=e,this.errors=t}return ParseTreeResult}();t.ParseTreeResult=d;var h=function(){function Parser(e){this._getTagDefinition=e}return Parser.prototype.parse=function(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r=l.DEFAULT_INTERPOLATION_CONFIG);var i=c.tokenize(e,t,this._getTagDefinition,n,r),o=new f(i.tokens,this._getTagDefinition).build();return new d(o.rootNodes,i.errors.concat(o.errors))},Parser}();t.Parser=h;var f=function(){function _TreeBuilder(e,t){this.tokens=e,this.getTagDefinition=t,this._index=-1,this._rootNodes=[],this._errors=[],this._elementStack=[],this._advance()}return _TreeBuilder.prototype.build=function(){for(;this._peek.type!==c.TokenType.EOF;)this._peek.type===c.TokenType.TAG_OPEN_START?this._consumeStartTag(this._advance()):this._peek.type===c.TokenType.TAG_CLOSE?this._consumeEndTag(this._advance()):this._peek.type===c.TokenType.CDATA_START?(this._closeVoidElement(),this._consumeCdata(this._advance())):this._peek.type===c.TokenType.COMMENT_START?(this._closeVoidElement(),this._consumeComment(this._advance())):this._peek.type===c.TokenType.TEXT||this._peek.type===c.TokenType.RAW_TEXT||this._peek.type===c.TokenType.ESCAPABLE_RAW_TEXT?(this._closeVoidElement(),this._consumeText(this._advance())):this._peek.type===c.TokenType.EXPANSION_FORM_START?this._consumeExpansion(this._advance()):this._advance();return new d(this._rootNodes,this._errors)},_TreeBuilder.prototype._advance=function(){var e=this._peek;return this._index0)return this._errors=this._errors.concat(i.errors),null;var l=new s.ParseSourceSpan(e.sourceSpan.start,r.sourceSpan.end),u=new s.ParseSourceSpan(t.sourceSpan.start,r.sourceSpan.end);return new a.ExpansionCase(e.parts[0],i.rootNodes,l,e.sourceSpan,u)},_TreeBuilder.prototype._collectExpansionExpTokens=function(e){for(var t=[],n=[c.TokenType.EXPANSION_CASE_EXP_START];;){if(this._peek.type!==c.TokenType.EXPANSION_FORM_START&&this._peek.type!==c.TokenType.EXPANSION_CASE_EXP_START||n.push(this._peek.type),this._peek.type===c.TokenType.EXPANSION_CASE_EXP_END){if(!lastOnStack(n,c.TokenType.EXPANSION_CASE_EXP_START))return this._errors.push(p.create(null,e.sourceSpan,"Invalid ICU message. Missing '}'.")),null;if(n.pop(),0==n.length)return t}if(this._peek.type===c.TokenType.EXPANSION_FORM_END){if(!lastOnStack(n,c.TokenType.EXPANSION_FORM_START))return this._errors.push(p.create(null,e.sourceSpan,"Invalid ICU message. Missing '}'.")),null;n.pop()}if(this._peek.type===c.TokenType.EOF)return this._errors.push(p.create(null,e.sourceSpan,"Invalid ICU message. Missing '}'.")),null;t.push(this._advance())}},_TreeBuilder.prototype._consumeText=function(e){var t=e.parts[0];if(t.length>0&&"\n"==t[0]){var n=this._getParentElement();o.isPresent(n)&&0==n.children.length&&this.getTagDefinition(n.name).ignoreFirstLf&&(t=t.substring(1))}t.length>0&&this._addToParent(new a.Text(t,e.sourceSpan))},_TreeBuilder.prototype._closeVoidElement=function(){if(this._elementStack.length>0){var e=i.ListWrapper.last(this._elementStack);this.getTagDefinition(e.name).isVoid&&this._elementStack.pop()}},_TreeBuilder.prototype._consumeStartTag=function(e){for(var t=e.parts[0],n=e.parts[1],r=[];this._peek.type===c.TokenType.ATTR_NAME;)r.push(this._consumeAttr(this._advance()));var i=this._getElementFullName(t,n,this._getParentElement()),o=!1;if(this._peek.type===c.TokenType.TAG_OPEN_END_VOID){this._advance(),o=!0;var l=this.getTagDefinition(i);l.canSelfClose||null!==u.getNsPrefix(i)||l.isVoid||this._errors.push(p.create(i,e.sourceSpan,'Only void and foreign elements can be self closed "'+e.parts[1]+'"'))}else this._peek.type===c.TokenType.TAG_OPEN_END&&(this._advance(),o=!1);var d=this._peek.sourceSpan.start,h=new s.ParseSourceSpan(e.sourceSpan.start,d),f=new a.Element(i,r,[],h,h,null);this._pushElement(f),o&&(this._popElement(i),f.endSourceSpan=h)},_TreeBuilder.prototype._pushElement=function(e){if(this._elementStack.length>0){var t=i.ListWrapper.last(this._elementStack);this.getTagDefinition(t.name).isClosedByChild(e.name)&&this._elementStack.pop()}var n=this.getTagDefinition(e.name),r=this._getParentElementSkippingContainers(),s=r.parent,l=r.container;if(o.isPresent(s)&&n.requireExtraParent(s.name)){var c=new a.Element(n.parentToAdd,[],[],e.sourceSpan,e.startSourceSpan,e.endSourceSpan);this._insertBeforeContainer(s,l,c)}this._addToParent(e),this._elementStack.push(e)},_TreeBuilder.prototype._consumeEndTag=function(e){var t=this._getElementFullName(e.parts[0],e.parts[1],this._getParentElement());this._getParentElement()&&(this._getParentElement().endSourceSpan=e.sourceSpan),this.getTagDefinition(t).isVoid?this._errors.push(p.create(t,e.sourceSpan,'Void elements do not have end tags "'+e.parts[1]+'"')):this._popElement(t)||this._errors.push(p.create(t,e.sourceSpan,'Unexpected closing tag "'+e.parts[1]+'"'))},_TreeBuilder.prototype._popElement=function(e){for(var t=this._elementStack.length-1;t>=0;t--){var n=this._elementStack[t];if(n.name==e)return i.ListWrapper.splice(this._elementStack,t,this._elementStack.length-t),!0;if(!this.getTagDefinition(n.name).closedByParent)return!1}return!1},_TreeBuilder.prototype._consumeAttr=function(e){var t=u.mergeNsAndName(e.parts[0],e.parts[1]),n=e.sourceSpan.end,r="";if(this._peek.type===c.TokenType.ATTR_VALUE){var i=this._advance();r=i.parts[0],n=i.sourceSpan.end}return new a.Attribute(t,r,new s.ParseSourceSpan(e.sourceSpan.start,n))},_TreeBuilder.prototype._getParentElement=function(){return this._elementStack.length>0?i.ListWrapper.last(this._elementStack):null},_TreeBuilder.prototype._getParentElementSkippingContainers=function(){for(var e=null,t=this._elementStack.length-1;t>=0;t--){if("ng-container"!==this._elementStack[t].name)return{parent:this._elementStack[t],container:e};e=this._elementStack[t]}return{parent:i.ListWrapper.last(this._elementStack),container:e}},_TreeBuilder.prototype._addToParent=function(e){var t=this._getParentElement();o.isPresent(t)?t.children.push(e):this._rootNodes.push(e)},_TreeBuilder.prototype._insertBeforeContainer=function(e,t,n){if(t){if(e){var r=e.children.indexOf(t);e.children[r]=n}else this._rootNodes.push(n);n.children.push(t),this._elementStack.splice(this._elementStack.indexOf(t),0,n)}else this._addToParent(n),this._elementStack.push(n)},_TreeBuilder.prototype._getElementFullName=function(e,t,n){return o.isBlank(e)&&(e=this.getTagDefinition(t).implicitNamespacePrefix,o.isBlank(e)&&o.isPresent(n)&&(e=u.getNsPrefix(n.name))),u.mergeNsAndName(e,t)},_TreeBuilder}()},function(e,t,n){"use strict";function splitClasses(e){return e.trim().split(/\s+/g)}function createElementCssSelector(e,t){var n=new w.CssSelector,r=y.splitNsName(e)[1];n.setElement(r);for(var i=0;i0&&this._console.warn("Template parse warnings:\n"+a.join("\n")),l.length>0){var c=l.join("\n");throw new u.BaseException("Template parse errors:\n"+c)}return s.templateAst},TemplateParser.prototype.tryParse=function(e,t,n,r,i,o){var a;e.template&&(a=g.InterpolationConfig.fromArray(e.template.interpolation));var l,c=this._htmlParser.parse(t,o,!0,a),u=c.errors;if(0==u.length){var d=m.expandNodes(c.rootNodes);u.push.apply(u,d.errors),c=new f.ParseTreeResult(d.nodes,u)}if(c.rootNodes.length>0){var y=s.removeIdentifierDuplicates(n),v=s.removeIdentifierDuplicates(r),_=new b.ProviderViewContext(e,c.rootNodes[0].sourceSpan),w=new j(_,y,v,i,this._exprParser,this._schemaRegistry);l=h.visitAll(w,c.rootNodes,z),u.push.apply(u,w.errors.concat(_.errors))}else l=[];return this._assertNoReferenceDuplicationOnTemplate(l,u),u.length>0?new L(l,u):(p.isPresent(this.transforms)&&this.transforms.forEach(function(e){l=E.templateVisitAll(e,l)}),new L(l,u))},TemplateParser.prototype._assertNoReferenceDuplicationOnTemplate=function(e,t){var n=[];e.filter(function(e){return!!e.references}).forEach(function(e){return e.references.forEach(function(e){var r=e.name;if(n.indexOf(r)<0)n.push(r);else{var i=new V('Reference "#'+r+'" is defined several times',e.sourceSpan,v.ParseErrorLevel.FATAL);t.push(i)}})})},TemplateParser.decorators=[{type:i.Injectable}],TemplateParser.ctorParameters=[{type:l.Parser},{type:_.ElementSchemaRegistry},{type:f.HtmlParser},{type:o.Console},{type:Array,decorators:[{type:i.Optional},{type:i.Inject,args:[t.TEMPLATE_TRANSFORMS]}]}],TemplateParser}();t.TemplateParser=F;var j=function(){function TemplateParseVisitor(e,t,n,r,i,o){var s=this;this.providerViewContext=e,this._schemas=r,this._exprParser=i,this._schemaRegistry=o,this.errors=[],this.directivesIndex=new Map,this.ngContentCount=0,this.selectorMatcher=new w.SelectorMatcher;var a=e.component.template;p.isPresent(a)&&p.isPresent(a.interpolation)&&(this._interpolationConfig={start:a.interpolation[0],end:a.interpolation[1]}),c.ListWrapper.forEachWithIndex(t,function(e,t){var n=w.CssSelector.parse(e.selector);s.selectorMatcher.addSelectables(n,e),s.directivesIndex.set(e,t)}),this.pipesByName=new Map,n.forEach(function(e){return s.pipesByName.set(e.name,e)})}return TemplateParseVisitor.prototype._reportError=function(e,t,n){void 0===n&&(n=v.ParseErrorLevel.FATAL),this.errors.push(new V(e,t,n))},TemplateParseVisitor.prototype._reportParserErors=function(e,t){for(var n=0,r=e;no.MAX_INTERPOLATION_VALUES)throw new u.BaseException("Only support at most "+o.MAX_INTERPOLATION_VALUES+" interpolation values!");return r}catch(i){return this._reportError(""+i,t),this._exprParser.wrapLiteralPrimitive("ERROR",n)}},TemplateParseVisitor.prototype._parseAction=function(e,t){var n=t.start.toString();try{var r=this._exprParser.parseAction(e,n,this._interpolationConfig);return r&&this._reportParserErors(r.errors,t),!r||r.ast instanceof a.EmptyExpr?(this._reportError("Empty expressions are not allowed",t),this._exprParser.wrapLiteralPrimitive("ERROR",n)):(this._checkPipes(r,t),r)}catch(i){return this._reportError(""+i,t),this._exprParser.wrapLiteralPrimitive("ERROR",n)}},TemplateParseVisitor.prototype._parseBinding=function(e,t){var n=t.start.toString();try{var r=this._exprParser.parseBinding(e,n,this._interpolationConfig);return r&&this._reportParserErors(r.errors,t),this._checkPipes(r,t),r}catch(i){return this._reportError(""+i,t),this._exprParser.wrapLiteralPrimitive("ERROR",n)}},TemplateParseVisitor.prototype._parseTemplateBindings=function(e,t){var n=this,r=t.start.toString();try{var i=this._exprParser.parseTemplateBindings(e,r);return this._reportParserErors(i.errors,t),i.templateBindings.forEach(function(e){p.isPresent(e.expression)&&n._checkPipes(e.expression,t)}),i.warnings.forEach(function(e){n._reportError(e,t,v.ParseErrorLevel.WARNING)}),i.templateBindings}catch(o){return this._reportError(""+o,t),[]}},TemplateParseVisitor.prototype._checkPipes=function(e,t){var n=this;if(p.isPresent(e)){var r=new q;e.visit(r),r.pipes.forEach(function(e){n.pipesByName.has(e)||n._reportError("The pipe '"+e+"' could not be found",t)})}},TemplateParseVisitor.prototype.visitExpansion=function(e,t){return null},TemplateParseVisitor.prototype.visitExpansionCase=function(e,t){return null},TemplateParseVisitor.prototype.visitText=function(e,t){var n=t.findNgContentIndex(N),r=this._parseInterpolation(e.value,e.sourceSpan);return p.isPresent(r)?new E.BoundTextAst(r,n,e.sourceSpan):new E.TextAst(e.value,n,e.sourceSpan)},TemplateParseVisitor.prototype.visitAttribute=function(e,t){return new E.AttrAst(e.name,e.value,e.sourceSpan)},TemplateParseVisitor.prototype.visitComment=function(e,t){return null},TemplateParseVisitor.prototype.visitElement=function(e,t){var n=this,r=e.name,i=R.preparseElement(e);if(i.type===R.PreparsedElementType.SCRIPT||i.type===R.PreparsedElementType.STYLE)return null;if(i.type===R.PreparsedElementType.STYLESHEET&&S.isStyleUrlResolvable(i.hrefAttr))return null;var o=[],s=[],a=[],l=[],c=[],u=[],d=[],f=[],m=[],g=!1,v=[],_=y.splitNsName(r.toLowerCase())[1],C=_==T;e.attrs.forEach(function(e){var t=n._parseAttr(C,e,o,s,c,u,a,l),r=n._parseInlineTemplateBinding(e,f,d,m);r&&g&&n._reportError("Can't have multiple template bindings on one element. Use only one attribute named 'template' or prefixed with *",e.sourceSpan),t||r||(v.push(n.visitAttribute(e,null)),o.push([e.name,e.value])),r&&(g=!0)});var P=createElementCssSelector(r,o),x=this._parseDirectives(this.selectorMatcher,P),M=[],k=this._createDirectiveAsts(C,e.name,x,s,a,e.sourceSpan,M),I=this._createElementPropertyAsts(e.name,s,k).concat(c),A=t.isTemplateElement||g,O=new b.ProviderElementContext(this.providerViewContext,t.providerContext,A,k,v,M,e.sourceSpan),D=h.visitAll(i.nonBindable?G:this,e.children,U.create(C,k,C?t.providerContext:O));O.afterElement();var N,V=p.isPresent(i.projectAs)?w.CssSelector.parse(i.projectAs)[0]:P,L=t.findNgContentIndex(V);if(i.type===R.PreparsedElementType.NG_CONTENT)p.isPresent(e.children)&&e.children.length>0&&this._reportError(" element cannot have content. must be immediately followed by ",e.sourceSpan),N=new E.NgContentAst((this.ngContentCount++),g?null:L,e.sourceSpan);else if(C)this._assertAllEventsPublishedByDirectives(k,u),this._assertNoComponentsNorElementBindingsOnTemplate(k,I,e.sourceSpan),N=new E.EmbeddedTemplateAst(v,u,M,l,O.transformedDirectiveAsts,O.transformProviders,O.transformedHasViewContainer,D,g?null:L,e.sourceSpan);else{this._assertOnlyOneComponent(k,e.sourceSpan);var F=g?null:t.findNgContentIndex(V);N=new E.ElementAst(r,v,I,u,M,O.transformedDirectiveAsts,O.transformProviders,O.transformedHasViewContainer,D,g?null:F,e.sourceSpan)}if(g){var j=createElementCssSelector(T,f),B=this._parseDirectives(this.selectorMatcher,j),W=this._createDirectiveAsts(!0,e.name,B,d,[],e.sourceSpan,[]),H=this._createElementPropertyAsts(e.name,d,W);this._assertNoComponentsNorElementBindingsOnTemplate(W,H,e.sourceSpan);var z=new b.ProviderElementContext(this.providerViewContext,t.providerContext,t.isTemplateElement,W,[],[],e.sourceSpan);z.afterElement(),N=new E.EmbeddedTemplateAst([],[],[],m,z.transformedDirectiveAsts,z.transformProviders,z.transformedHasViewContainer,[N],L,e.sourceSpan)}return N},TemplateParseVisitor.prototype._parseInlineTemplateBinding=function(e,t,n,r){var i=null;if(this._normalizeAttributeName(e.name)==x)i=e.value;else if(e.name.startsWith(M)){var o=e.name.substring(M.length);i=0==e.value.length?o:o+" "+e.value}if(p.isPresent(i)){for(var s=this._parseTemplateBindings(i,e.sourceSpan),a=0;a elements is deprecated. Use "let-" instead!',t.sourceSpan,v.ParseErrorLevel.WARNING),this._parseVariable(h,c,t.sourceSpan,a)):(this._reportError('"var-" on non