command

package
v0.11.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 14, 2021 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package command contains the commands used by vtctldclient. It is intended only for use in vtctldclient's main package and entrypoint. The rest of this documentation is intended for maintainers.

Commands are grouped into files by the types of resources they interact with ( e.g. GetTablet, CreateTablet, DeleteTablet, GetTablets) or by what they do (e.g. PlannedReparentShard, EmergencyReparentShard, InitShardPrimary). Please add the command to the appropriate existing file, alphabetically, or create a new grouping if one does not exist.

The root command lives in root.go, and commands must attach themselves to this during an init function in order to be reachable from the CLI. root.go also contains the global variables available to any subcommand that are managed by the root command's pre- and post-run functions. Commands must not attempt to manage these, as that may conflict with Root's post-run cleanup actions. All commands should, at a minimum, use the commandCtx rather than creating their own context.Background to start, as it contains root tracing spans that would be lost.

Commands should not keep their logic in an anonymous function on the cobra.Command struct, but instead in a separate function that is assigned to RunE. Commands should strive to keep declaration, function definition, and flag initialization located as closely together as possible, to make the code easier to follow and understand (the global variables declared near Root are the exception here, not the rule). Commands should also prevent individual flag names from polluting the package namespace.

A good pattern we have found is to do the following:

package command

// (imports ...)

var (
	CreateTablet = &cobra.Command{
		Use: "CreateTablet [options] --keyspace=<keyspace> --shard=<shard-range> <tablet-alias> <tablet-type>",
		Args: cobra.ExactArgs(2),
		RunE: commandCreateTablet,
	}
	GetTablet = &cobra.Command{
		Use: "GetTablet <tablet-alias>",
		Args: cobra.ExactArgs(1),
		RunE: commandGetTablet,
	}
)

var createTabletOptions = struct {
	Opt1 string
	Opt2 bool
	Keyspace string
	Shard string
}{}

func commandCreateTablet(cmd *cobra.Command, args []string) error {
	aliasStr := cmd.Flags().Args(0)
	tabletTypeStr := cmd.Flags().Args(1)

	// do stuff with:
	// - client
	// - commandCtx
	// - createTabletOptions
	// - aliasStr
	// - tabletTypeStr

	return nil
}

// GetTablet takes no flags, so it needs no anonymous struct to store them
func commandGetTablet(cmd *cobra.Command, args []string) error {
	aliasStr := cmd.Flags().Arg(0)

	// do stuff with:
	// - client
	// - commandCtx
	// - aliasStr

	return nil
}

// finally, hook up all the commands in this file to Root, and add any flags
// to each of those commands

func init() {
	CreateTablet.Flags().StringVar(&createTabletOptions.Opt1, "opt1", "default", "help")
	CreateTablet.Flags().BoolVar(&createTabletOptions.Opt2, "opt2", false, "help")
	CreateTablet.Flags().StringVarP(&createTabletOptions.Keyspace, "keyspace", "k", "keyspace of tablet")
	CreateTablet.MarkFlagRequired("keyspace")
	CreateTablet.Flags().StringVarP(&createTabletOptions.Shard, "shard", "s", "shard range of tablet")
	CreateTablet.MarkFlagRequired("shard")
	Root.AddCommand(CreateTablet)

	Root.AddCommand(GetTablet)
}

A note on RunE and SilenceUsage:

We prefer using RunE over Run for the entrypoint to our subcommands, because it allows us return errors back up to the vtctldclient main function and do error handling, logging, and exit-code management once, in one place, rather than on a per-command basis. However, cobra treats errors returned from a command's RunE as usage errors, and therefore will print the command's full usage text to stderr when RunE returns non-nil, in addition to propagating that error back up to the result of the root command's Execute() method. This is decidedly not what we want. There is no plan to address this in cobra v1. 1

The suggested workaround for this issue is to set SilenceUsage: true, either on the root command or on every subcommand individually. This also does not work for vtctldclient, because not every flag can be parsed during pflag.Parse time, and for certain flags (mutually exclusive options, optional flags that require other flags to be set with them, etc) we do additional parsing and validation of flags in an individual subcommand. We want errors during this phase to be treated as usage errors, so setting SilenceUsage=true before this point would not cause usage text to be printed for us.

So, for us, we want to individually set cmd.SilenceUsage = true at *particular points* in each command, dependending on whether that command needs to do an additional parse & validation pass. In most cases, the command does not need to post-validate its options, and can set cmd.SilencUsage = true as their first line. We feel, though, that a line that reads "SilenceUsage = true" to be potentially confusing in how it reads. A maintainer without sufficient context may read this and say "Silence usage? We don't want that" and remove the lines, so we provide a wrapper function that communicates intent, cli.FinishedParsing, that each subcommand should call when they have transitioned from the parsing & validation phase of their entrypoint to the actual logic.

Index

Constants

This section is empty.

Variables

View Source
var (
	// AddCellInfo makes an AddCellInfo gRPC call to a vtctld.
	AddCellInfo = &cobra.Command{
		Use:   "AddCellInfo --root <root> [--server-address <addr>] <cell>",
		Short: "Registers a local topology service in a new cell by creating the CellInfo.",
		Long: `Registers a local topology service in a new cell by creating the CellInfo
with the provided parameters.

The address will be used to connect to the topology service, and Vitess data will
be stored starting at the provided root.`,
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandAddCellInfo,
	}
	// AddCellsAlias makes an AddCellsAlias gRPC call to a vtctld.
	AddCellsAlias = &cobra.Command{
		Use:   "AddCellsAlias --cells <cell1,cell2,...> [--cells <cell3> ...] <alias>",
		Short: "Defines a group of cells that can be referenced by a single name (the alias).",
		Long: `Defines a group of cells that can be referenced by a single name (the alias).

When routing query traffic, replica/rdonly traffic can be routed across cells
within the group (alias). Only primary traffic can be routed across cells not in
the same group (alias).`,
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandAddCellsAlias,
	}
	// DeleteCellInfo makes a DeleteCellInfo gRPC call to a vtctld.
	DeleteCellInfo = &cobra.Command{
		Use:                   "DeleteCellInfo [--force] <cell>",
		Short:                 "Deletes the CellInfo for the provided cell.",
		Long:                  "Deletes the CellInfo for the provided cell. The cell cannot be referenced by any Shard record.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandDeleteCellInfo,
	}
	// DeleteCellsAlias makes a DeleteCellsAlias gRPC call to a vtctld.
	DeleteCellsAlias = &cobra.Command{
		Use:                   "DeleteCellsAlias <alias>",
		Short:                 "Deletes the CellsAlias for the provided alias.",
		Long:                  "Deletes the CellsAlias for the provided alias.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandDeleteCellsAlias,
	}
	// GetCellInfoNames makes a GetCellInfoNames gRPC call to a vtctld.
	GetCellInfoNames = &cobra.Command{
		Use:  "GetCellInfoNames",
		Args: cobra.NoArgs,
		RunE: commandGetCellInfoNames,
	}
	// GetCellInfo makes a GetCellInfo gRPC call to a vtctld.
	GetCellInfo = &cobra.Command{
		Use:  "GetCellInfo cell",
		Args: cobra.ExactArgs(1),
		RunE: commandGetCellInfo,
	}
	// GetCellsAliases makes a GetCellsAliases gRPC call to a vtctld.
	GetCellsAliases = &cobra.Command{
		Use:  "GetCellsAliases",
		Args: cobra.NoArgs,
		RunE: commandGetCellsAliases,
	}
	// UpdateCellInfo makes an UpdateCellInfo gRPC call to a vtctld.
	UpdateCellInfo = &cobra.Command{
		Use:   "UpdateCellInfo [--root <root>] [--server-address <addr>] <cell>",
		Short: "Updates the content of a CellInfo with the provided parameters, creating the CellInfo if it does not exist.",
		Long: `Updates the content of a CellInfo with the provided parameters, creating the CellInfo if it does not exist.

If a value is empty, it is ignored.`,
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandUpdateCellInfo,
	}
	// UpdateCellsAlias makes an UpdateCellsAlias gRPC call to a vtctld.
	UpdateCellsAlias = &cobra.Command{
		Use:                   "UpdateCellsAlias [--cells <cell1,cell2,...> [--cells <cell4> ...]] <alias>",
		Short:                 "Updates the content of a CellsAlias with the provided parameters, creating the CellsAlias if it does not exist.",
		Long:                  "Updates the content of a CellsAlias with the provided parameters, creating the CellsAlias if it does not exist.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandUpdateCellsAlias,
	}
)
View Source
var (
	// CreateKeyspace makes a CreateKeyspace gRPC call to a vtctld.
	CreateKeyspace = &cobra.Command{
		Use:  "CreateKeyspace KEYSPACE_NAME [--force] [--sharding-column-name NAME --sharding-column-type TYPE] [--base-keyspace KEYSPACE --snapshot-timestamp TIME] [--served-from DB_TYPE:KEYSPACE ...]",
		Args: cobra.ExactArgs(1),
		RunE: commandCreateKeyspace,
	}
	// DeleteKeyspace makes a DeleteKeyspace gRPC call to a vtctld.
	DeleteKeyspace = &cobra.Command{
		Use:  "DeleteKeyspace KEYSPACE_NAME",
		Args: cobra.ExactArgs(1),
		RunE: commandDeleteKeyspace,
	}
	// FindAllShardsInKeyspace makes a FindAllShardsInKeyspace gRPC call to a vtctld.
	FindAllShardsInKeyspace = &cobra.Command{
		Use:     "FindAllShardsInKeyspace keyspace",
		Aliases: []string{"findallshardsinkeyspace"},
		Args:    cobra.ExactArgs(1),
		RunE:    commandFindAllShardsInKeyspace,
	}
	// GetKeyspace makes a GetKeyspace gRPC call to a vtctld.
	GetKeyspace = &cobra.Command{
		Use:     "GetKeyspace keyspace",
		Aliases: []string{"getkeyspace"},
		Args:    cobra.ExactArgs(1),
		RunE:    commandGetKeyspace,
	}
	// GetKeyspaces makes a GetKeyspaces gRPC call to a vtctld.
	GetKeyspaces = &cobra.Command{
		Use:     "GetKeyspaces",
		Aliases: []string{"getkeyspaces"},
		Args:    cobra.NoArgs,
		RunE:    commandGetKeyspaces,
	}
	// RemoveKeyspaceCell makes a RemoveKeyspaceCell gRPC call to a vtctld.
	RemoveKeyspaceCell = &cobra.Command{
		Use:  "RemoveKeyspaceCell <keyspace> <cell>",
		Args: cobra.ExactArgs(2),
		RunE: commandRemoveKeyspaceCell,
	}
)
View Source
var (
	// EmergencyReparentShard makes an EmergencyReparent gRPC call to a vtctld.
	EmergencyReparentShard = &cobra.Command{
		Use:  "EmergencyReparentShard <keyspace/shard>",
		Args: cobra.ExactArgs(1),
		Long: "Reparents the shard to the new primary. Assumes the old primary is dead and not responding",
		RunE: commandEmergencyReparentShard,
	}
	// InitShardPrimary makes an InitShardPrimary gRPC call to a vtctld.
	InitShardPrimary = &cobra.Command{
		Use:  "InitShardPrimary <keyspace/shard> <primary alias>",
		Args: cobra.ExactArgs(2),
		RunE: commandInitShardPrimary,
	}
	// PlannedReparentShard makes a PlannedReparentShard gRPC call to a vtctld.
	PlannedReparentShard = &cobra.Command{
		Use:  "PlannedReparentShard <keyspace/shard>",
		Args: cobra.ExactArgs(1),
		Long: "string",
		RunE: commandPlannedReparentShard,
	}
	// ReparentTablet makes a ReparentTablet gRPC call to a vtctld.
	ReparentTablet = &cobra.Command{
		Use: "ReparentTablet <alias>",
		Long: "Reparent a tablet to the current primary in the shard. This only works if the current replica position " +
			"matches the last known reparent action.",
		Args: cobra.ExactArgs(1),
		RunE: commandReparentTablet,
	}
	// TabletExternallyReparented makes a TabletExternallyReparented gRPC call
	// to a vtctld.
	TabletExternallyReparented = &cobra.Command{
		Use:  "TabletExternallyReparented <alias>",
		Args: cobra.ExactArgs(1),
		RunE: commandTabletExternallyReparented,
	}
)
View Source
var (
	// ApplyRoutingRules makes an ApplyRoutingRules gRPC call to a vtctld.
	ApplyRoutingRules = &cobra.Command{
		Use:                   "ApplyRoutingRules {--rules RULES | --rules-file RULES_FILE} [--cells=c1,c2,...] [--skip-rebuild] [--dry-run]",
		Short:                 "Applies the VSchema routing rules.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.NoArgs,
		RunE:                  commandApplyRoutingRules,
	}
	// GetRoutingRules makes a GetRoutingRules gRPC call to a vtctld.
	GetRoutingRules = &cobra.Command{
		Use:                   "GetRoutingRules",
		Short:                 "Displays the VSchema routing rules.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.NoArgs,
		RunE:                  commandGetRoutingRules,
	}
)
View Source
var (
	// GetSrvKeyspaces makes a GetSrvKeyspaces gRPC call to a vtctld.
	GetSrvKeyspaces = &cobra.Command{
		Use:                   "GetSrvKeyspaces <keyspace> [<cell> ...]",
		Short:                 "Returns the SrvKeyspaces for the given keyspace in one or more cells.",
		Args:                  cobra.MinimumNArgs(1),
		RunE:                  commandGetSrvKeyspaces,
		DisableFlagsInUseLine: true,
	}
	// GetSrvVSchema makes a GetSrvVSchema gRPC call to a vtctld.
	GetSrvVSchema = &cobra.Command{
		Use:                   "GetSrvVSchema cell",
		Short:                 "Returns the SrvVSchema for the given cell.",
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandGetSrvVSchema,
		DisableFlagsInUseLine: true,
	}
	// GetSrvVSchemas makes a GetSrvVSchemas gRPC call to a vtctld.
	GetSrvVSchemas = &cobra.Command{
		Use:                   "GetSrvVSchemas [<cell> ...]",
		Short:                 "Returns the SrvVSchema for all cells, optionally filtered by the given cells.",
		Args:                  cobra.ArbitraryArgs,
		RunE:                  commandGetSrvVSchemas,
		DisableFlagsInUseLine: true,
	}
	// RebuildVSchemaGraph makes a RebuildVSchemaGraph gRPC call to a vtctld.
	RebuildVSchemaGraph = &cobra.Command{
		Use:                   "RebuildVSchemaGraph [--cells=c1,c2,...]",
		Short:                 "Rebuilds the cell-specific SrvVSchema from the global VSchema objects in the provided cells (or all cells if none provided).",
		DisableFlagsInUseLine: true,
		Args:                  cobra.NoArgs,
		RunE:                  commandRebuildVSchemaGraph,
	}
)
View Source
var (
	// CreateShard makes a CreateShard gRPC request to a vtctld.
	CreateShard = &cobra.Command{
		Use:  "CreateShard <keyspace/shard>",
		Args: cobra.ExactArgs(1),
		RunE: commandCreateShard,
	}
	// DeleteShards makes a DeleteShards gRPC request to a vtctld.
	DeleteShards = &cobra.Command{
		Use:  "DeleteShards <keyspace/shard> [<keyspace/shard> ...]",
		Args: cobra.MinimumNArgs(1),
		RunE: commandDeleteShards,
	}
	// GetShard makes a GetShard gRPC request to a vtctld.
	GetShard = &cobra.Command{
		Use:  "GetShard <keyspace/shard>",
		Args: cobra.ExactArgs(1),
		RunE: commandGetShard,
	}
	// RemoveShardCell makes a RemoveShardCell gRPC request to a vtctld.
	RemoveShardCell = &cobra.Command{
		Use:  "RemoveShardCell <keyspace/shard> <cell>",
		Args: cobra.ExactArgs(2),
		RunE: commandRemoveShardCell,
	}
	// ShardReplicationPositions makes a ShardReplicationPositions gRPC request
	// to a vtctld.
	ShardReplicationPositions = &cobra.Command{
		Use: "ShardReplicationPositions <keyspace/shard>",
		Long: `Shows the replication status of each tablet in the shard graph.
Output is sorted by tablet type, then replication position.
Use ctrl-C to interrupt the command and see partial results if needed.`,
		Args: cobra.ExactArgs(1),
		RunE: commandShardReplicationPositions,
	}
)
View Source
var (
	// ChangeTabletType makes a ChangeTabletType gRPC call to a vtctld.
	ChangeTabletType = &cobra.Command{
		Use:   "ChangeTabletType [--dry-run] <alias> <tablet-type>",
		Short: "Changes the db type for the specified tablet, if possible.",
		Long: `Changes the db type for the specified tablet, if possible.

This command is used primarily to arrange replicas, and it will not convert a primary.
NOTE: This command automatically updates the serving graph.`,
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(2),
		RunE:                  commandChangeTabletType,
	}
	// DeleteTablets makes a DeleteTablets gRPC call to a vtctld.
	DeleteTablets = &cobra.Command{
		Use:                   "DeleteTablets <alias> [ <alias> ... ]",
		Short:                 "Deletes tablet(s) from the topology.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.MinimumNArgs(1),
		RunE:                  commandDeleteTablets,
	}
	// GetTablet makes a GetTablet gRPC call to a vtctld.
	GetTablet = &cobra.Command{
		Use:                   "GetTablet <alias>",
		Short:                 "Outputs a JSON structure that contains information about the tablet.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandGetTablet,
	}
	// GetTablets makes a GetTablets gRPC call to a vtctld.
	GetTablets = &cobra.Command{
		Use:   "GetTablets [--strict] [{--cell $c1 [--cell $c2 ...], --keyspace $ks [--shard $shard], --tablet-alias $alias}]",
		Short: "Looks up tablets according to filter criteria.",
		Long: `Looks up tablets according to the filter criteria.

If --tablet-alias is passed, none of the other filters (keyspace, shard, cell) may
be passed, and tablets are looked up by tablet alias only.

If --keyspace is passed, then all tablets in the keyspace are retrieved. The
--shard flag may also be passed to further narrow the set of tablets to that
<keyspace/shard>. Passing --shard without also passing --keyspace will fail.

Passing --cell limits the set of tablets to those in the specified cells. The
--cell flag accepts a CSV argument (e.g. --cell "c1,c2") and may be repeated
(e.g. --cell "c1" --cell "c2").

Valid output formats are "awk" and "json".`,
		DisableFlagsInUseLine: true,
		Args:                  cobra.NoArgs,
		RunE:                  commandGetTablets,
	}
	// RefreshState makes a RefreshState gRPC call to a vtctld.
	RefreshState = &cobra.Command{
		Use:                   "RefreshState <alias>",
		Short:                 "Reloads the tablet record on the specified tablet.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandRefreshState,
	}
	// RefreshStateByShard makes a RefreshStateByShard gRPC call to a vtcld.
	RefreshStateByShard = &cobra.Command{
		Use:                   "RefreshStateByShard [--cell <cell1> ...] <keyspace/shard>",
		Short:                 "Reloads the tablet record all tablets in the shard, optionally limited to the specified cells.",
		DisableFlagsInUseLine: true,
		Args:                  cobra.ExactArgs(1),
		RunE:                  commandRefreshStateByShard,
	}
)
View Source
var (
	// GetVSchema makes a GetVSchema gRPC call to a vtctld.
	GetVSchema = &cobra.Command{
		Use:  "GetVSchema keyspace",
		Args: cobra.ExactArgs(1),
		RunE: commandGetVSchema,
	}
	// ApplyVSchema makes an ApplyVSchema gRPC call to a vtctld.
	ApplyVSchema = &cobra.Command{
		Use:                   "ApplyVSchema {-vschema=<vschema> || -vschema-file=<vschema file> || -sql=<sql> || -sql-file=<sql file>} [-cells=c1,c2,...] [-skip-rebuild] [-dry-run] <keyspace>",
		Args:                  cobra.ExactArgs(1),
		DisableFlagsInUseLine: true,
		RunE:                  commandApplyVSchema,
		Short:                 "Applies the VTGate routing schema to the provided keyspace. Shows the result after application.",
	}
)
View Source
var GetBackups = &cobra.Command{
	Use:  "GetBackups <keyspace/shard>",
	Args: cobra.ExactArgs(1),
	RunE: commandGetBackups,
}

GetBackups makes a GetBackups gRPC call to a vtctld.

View Source
var GetSchema = &cobra.Command{
	Use:  "GetSchema [--tables TABLES ...] [--exclude-tables EXCLUDE_TABLES ...] [{--table-names-only | --table-sizes-only}] [--include-views] alias",
	Args: cobra.ExactArgs(1),
	RunE: commandGetSchema,
}

GetSchema makes a GetSchema gRPC call to a vtctld.

View Source
var (
	// GetWorkflows makes a GetWorkflows gRPC call to a vtctld.
	GetWorkflows = &cobra.Command{
		Use:  "GetWorkflows <keyspace>",
		Args: cobra.ExactArgs(1),
		RunE: commandGetWorkflows,
	}
)
View Source
var (
	// LegacyVtctlCommand provides a shim to make legacy ExecuteVtctlCommand
	// RPCs. This allows users to use a single binary to make RPCs against both
	// the new and old vtctld gRPC APIs.
	LegacyVtctlCommand = &cobra.Command{
		Use:   "LegacyVtctlCommand -- <command> [flags ...] [args ...]",
		Short: "Invoke a legacy vtctlclient command. Flag parsing is best effort.",
		Args:  cobra.ArbitraryArgs,
		RunE: func(cmd *cobra.Command, args []string) error {
			cli.FinishedParsing(cmd)
			return runLegacyCommand(args)
		},
		Long: strings.TrimSpace(`
LegacyVtctlCommand uses the legacy vtctl grpc client to make an ExecuteVtctlCommand
rpc to a vtctld.

This command exists to support a smooth transition of any scripts that relied on
vtctlclient during the migration to the new vtctldclient, and will be removed,
following the Vitess project's standard deprecation cycle, once all commands
have been migrated to the new VtctldServer api.

To see the list of available legacy commands, run "LegacyVtctlCommand -- help".
Note that, as with the old client, this requires a running server, as the flag
parsing and help/usage text generation, is done server-side.

Also note that, in order to defer that flag parsing to the server side, you must
use the double-dash ("--") after the LegacyVtctlCommand subcommand string, or
the client-side flag parsing library we are using will attempt to parse those
flags (and fail).
`),
		Example: strings.TrimSpace(`
LegacyVtctlCommand help # displays this help message
LegacyVtctlCommand -- help # displays help for supported legacy vtctl commands

# When using legacy command that take arguments, a double dash must be used
# before the first flag argument, like in the first example. The double dash may
# be used, however, at any point after the "LegacyVtctlCommand" string, as in
# the second example.
LegacyVtctlCommand AddCellInfo -- -server_address "localhost:1234" -root "/vitess/cell1"
LegacyVtctlCommand -- AddCellInfo -server_address "localhost:5678" -root "/vitess/cell1"`),
	}
)
View Source
var (

	// Root is the main entrypoint to the vtctldclient CLI.
	Root = &cobra.Command{

		PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
			traceCloser = trace.StartTracing("vtctldclient")
			if err := ensureServerArg(); err != nil {
				return err
			}

			client, err = vtctldclient.New("grpc", server)

			commandCtx, commandCancel = context.WithTimeout(context.Background(), actionTimeout)
			return err
		},

		PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
			commandCancel()
			err := client.Close()
			trace.LogErrorsWhenClosing(traceCloser)
			return err
		},
		TraverseChildren: true,

		SilenceErrors: true,
	}
)

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL