func PachctlCmd() *cobra.Command {
	var verbose bool
	var noMetrics bool
	var noPortForwarding bool

	raw := false
	rawFlags := pflag.NewFlagSet("", pflag.ContinueOnError)
	rawFlags.BoolVar(&raw, "raw", false, "disable pretty printing, print raw json")

	marshaller := &jsonpb.Marshaler{Indent: "  "}

	rootCmd := &cobra.Command{
		Use: os.Args[0],
		Long: `Access the Pachyderm API.

Environment variables:
  PACHD_ADDRESS=<host>:<port>, the pachd server to connect to (e.g. 127.0.0.1:30650).
  PACH_CONFIG=<path>, the path where pachctl will attempt to load your pach config.
  JAEGER_ENDPOINT=<host>:<port>, the Jaeger server to connect to, if PACH_ENABLE_TRACING is set
  PACH_ENABLE_TRACING={true,false}, If true, and JAEGER_ENDPOINT is set, attach a
    Jaeger trace to all outgoing RPCs
`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			log.SetFormatter(new(prefixed.TextFormatter))

			if !verbose {
				log.SetLevel(log.ErrorLevel)
				// Silence grpc logs
				grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, ioutil.Discard))
			} else {
				log.SetLevel(log.DebugLevel)
				// etcd overrides grpc's logs--there's no way to enable one without
				// enabling both.
				// Error and warning logs are discarded because they will be
				// redundantly sent to the info logger. See:
				// https://godoc.org/google.golang.org/grpc/grpclog#NewLoggerV2
				logger := log.StandardLogger()
				etcd.SetLogger(grpclog.NewLoggerV2(
					logutil.NewGRPCLogWriter(logger, "etcd/grpc"),
					ioutil.Discard,
					ioutil.Discard,
				))
			}
		},
		BashCompletionFunction: bashCompletionFunc,
	}
	rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Output verbose logs")
	rootCmd.PersistentFlags().BoolVarP(&noMetrics, "no-metrics", "", false, "Don't report user metrics for this command")
	rootCmd.PersistentFlags().BoolVarP(&noPortForwarding, "no-port-forwarding", "", false, "Disable implicit port forwarding")

	var subcommands []*cobra.Command

	var clientOnly bool
	var timeoutFlag string
	versionCmd := &cobra.Command{
		Short: "Print Pachyderm version information.",
		Long:  "Print Pachyderm version information.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) (retErr error) {
			if clientOnly {
				if raw {
					if err := marshaller.Marshal(os.Stdout, version.Version); err != nil {
						return err
					}
				} else {
					fmt.Println(version.PrettyPrintVersion(version.Version))
				}
				return nil
			}
			if !noMetrics {
				start := time.Now()
				startMetricsWait := metrics.StartReportAndFlushUserAction("Version", start)
				defer startMetricsWait()
				defer func() {
					finishMetricsWait := metrics.FinishReportAndFlushUserAction("Version", retErr, start)
					finishMetricsWait()
				}()
			}

			// Print header + client version
			writer := ansiterm.NewTabWriter(os.Stdout, 20, 1, 3, ' ', 0)
			if raw {
				if err := marshaller.Marshal(os.Stdout, version.Version); err != nil {
					return err
				}
			} else {
				printVersionHeader(writer)
				printVersion(writer, "pachctl", version.Version)
				if err := writer.Flush(); err != nil {
					return err
				}
			}

			// Dial pachd & get server version
			var pachClient *client.APIClient
			var err error
			if timeoutFlag != "default" {
				var timeout time.Duration
				timeout, err = time.ParseDuration(timeoutFlag)
				if err != nil {
					return fmt.Errorf("could not parse timeout duration %q: %v", timeout, err)
				}
				pachClient, err = client.NewOnUserMachine(false, !noPortForwarding, "user", client.WithDialTimeout(timeout))
			} else {
				pachClient, err = client.NewOnUserMachine(false, !noPortForwarding, "user")
			}
			if err != nil {
				return err
			}
			defer pachClient.Close()
			ctx, cancel := context.WithTimeout(context.Background(), time.Second)
			defer cancel()
			version, err := pachClient.GetVersion(ctx, &types.Empty{})

			if err != nil {
				buf := bytes.NewBufferString("")
				errWriter := ansiterm.NewTabWriter(buf, 20, 1, 3, ' ', 0)
				fmt.Fprintf(errWriter, "pachd\t(version unknown) : error connecting to pachd server at address (%v): %v\n\nplease make sure pachd is up (`kubectl get all`) and portforwarding is enabled\n", pachClient.GetAddress(), grpc.ErrorDesc(err))
				errWriter.Flush()
				return errors.New(buf.String())
			}

			// print server version
			if raw {
				if err := marshaller.Marshal(os.Stdout, version); err != nil {
					return err
				}
			} else {
				printVersion(writer, "pachd", version)
				if err := writer.Flush(); err != nil {
					return err
				}
			}
			return nil
		}),
	}
	versionCmd.Flags().BoolVar(&clientOnly, "client-only", false, "If set, "+
		"only print pachctl's version, but don't make any RPCs to pachd. Useful "+
		"if pachd is unavailable")
	versionCmd.Flags().StringVar(&timeoutFlag, "timeout", "default", "If set, "+
		"'pachctl version' will timeout after the given duration (formatted as a "+
		"golang time duration--a number followed by ns, us, ms, s, m, or h). If "+
		"--client-only is set, this flag is ignored. If unset, pachctl will use a "+
		"default timeout; if set to 0s, the call will never time out.")
	versionCmd.Flags().AddFlagSet(rawFlags)
	subcommands = append(subcommands, cmdutil.CreateAlias(versionCmd, "version"))

	deleteAll := &cobra.Command{
		Short: "Delete everything.",
		Long: `Delete all repos, commits, files, pipelines and jobs.
This resets the cluster to its initial state.`,
		Run: cmdutil.RunFixedArgs(0, func(args []string) error {
			client, err := client.NewOnUserMachine(!noMetrics, !noPortForwarding, "user")
			if err != nil {
				return err
			}
			defer client.Close()
			red := color.New(color.FgRed).SprintFunc()
			var repos, pipelines []string
			repoInfos, err := client.ListRepo()
			if err != nil {
				return err
			}
			for _, ri := range repoInfos {
				repos = append(repos, red(ri.Repo.Name))
			}
			pipelineInfos, err := client.ListPipeline()
			if err != nil {
				return err
			}
			for _, pi := range pipelineInfos {
				pipelines = append(pipelines, red(pi.Pipeline.Name))
			}
			fmt.Println("All ACLs, repos, commits, files, pipelines and jobs will be deleted.")
			if len(repos) > 0 {
				fmt.Printf("Repos to delete: %s\n", strings.Join(repos, ", "))
			}
			if len(pipelines) > 0 {
				fmt.Printf("Pipelines to delete: %s\n", strings.Join(pipelines, ", "))
			}
			fmt.Println("Are you sure you want to do this? (y/n):")
			r := bufio.NewReader(os.Stdin)
			bytes, err := r.ReadBytes('\n')
			if err != nil {
				return err
			}
			if bytes[0] == 'y' || bytes[0] == 'Y' {
				return client.DeleteAll()
			}
			return nil
		}),
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(deleteAll, "delete all"))

	var port uint16
	var remotePort uint16
	var samlPort uint16
	var uiPort uint16
	var uiWebsocketPort uint16
	var pfsPort uint16
	var s3gatewayPort uint16
	var namespace string
	portForward := &cobra.Command{
		Short: "Forward a port on the local machine to pachd. This command blocks.",
		Long:  "Forward a port on the local machine to pachd. This command blocks.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) error {
			fw, err := client.NewPortForwarder(namespace)
			if err != nil {
				return err
			}

			if err = fw.Lock(); err != nil {
				return err
			}

			defer fw.Close()

			failCount := 0

			fmt.Println("Forwarding the pachd (Pachyderm daemon) port...")
			if err = fw.RunForDaemon(port, remotePort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the SAML ACS port...")
			if err = fw.RunForSAMLACS(samlPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Printf("Forwarding the dash (Pachyderm dashboard) UI port to http://localhost:%v...\n", uiPort)
			if err = fw.RunForDashUI(uiPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the dash (Pachyderm dashboard) websocket port...")
			if err = fw.RunForDashWebSocket(uiWebsocketPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the PFS port...")
			if err = fw.RunForPFS(pfsPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the s3gateway port...")
			if err = fw.RunForS3Gateway(s3gatewayPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			if failCount < 6 {
				fmt.Println("CTRL-C to exit")
				ch := make(chan os.Signal, 1)
				signal.Notify(ch, os.Interrupt)
				<-ch
			}

			return nil
		}),
	}
	portForward.Flags().Uint16VarP(&port, "port", "p", 30650, "The local port to bind pachd to.")
	portForward.Flags().Uint16Var(&remotePort, "remote-port", 650, "The remote port that pachd is bound to in the cluster.")
	portForward.Flags().Uint16Var(&samlPort, "saml-port", 30654, "The local port to bind pachd's SAML ACS to.")
	portForward.Flags().Uint16VarP(&uiPort, "ui-port", "u", 30080, "The local port to bind Pachyderm's dash service to.")
	portForward.Flags().Uint16VarP(&uiWebsocketPort, "proxy-port", "x", 30081, "The local port to bind Pachyderm's dash proxy service to.")
	portForward.Flags().Uint16VarP(&pfsPort, "pfs-port", "f", 30652, "The local port to bind PFS over HTTP to.")
	portForward.Flags().Uint16VarP(&s3gatewayPort, "s3gateway-port", "s", 30600, "The local port to bind the s3gateway to.")
	portForward.Flags().StringVar(&namespace, "namespace", "default", "Kubernetes namespace Pachyderm is deployed in.")
	subcommands = append(subcommands, cmdutil.CreateAlias(portForward, "port-forward"))

	var install bool
	var path string
	completion := &cobra.Command{
		Short: "Print or install the bash completion code.",
		Long:  "Print or install the bash completion code. This should be placed as the file `pachctl` in the bash completion directory (by default this is `/etc/bash_completion.d`. If bash-completion was installed via homebrew, this would be `$(brew --prefix)/etc/bash_completion.d`.)",
		Run: cmdutil.RunFixedArgs(0, func(args []string) (retErr error) {
			var dest io.Writer

			if install {
				f, err := os.Create(path)

				if err != nil {
					if os.IsPermission(err) {
						fmt.Fprintf(os.Stderr, "Permission error installing completions, rerun this command with sudo.\n")
					}
					return err
				}

				defer func() {
					if err := f.Close(); err != nil && retErr == nil {
						retErr = err
					}

					fmt.Printf("Bash completions installed in %s, you must restart bash to enable completions.\n", path)
				}()

				dest = f
			} else {
				dest = os.Stdout
			}

			// Remove 'hidden' flag from all commands so we can get bash completions for them as well
			var unhide func(*cobra.Command)
			unhide = func(cmd *cobra.Command) {
				cmd.Hidden = false
				for _, subcmd := range cmd.Commands() {
					unhide(subcmd)
				}
			}
			unhide(rootCmd)

			return rootCmd.GenBashCompletion(dest)
		}),
	}
	completion.Flags().BoolVar(&install, "install", false, "Install the completion.")
	completion.Flags().StringVar(&path, "path", "/etc/bash_completion.d/pachctl", "Path to install the completion to. This will default to `/etc/bash_completion.d/` if unspecified.")
	subcommands = append(subcommands, cmdutil.CreateAlias(completion, "completion"))

	// Logical commands for grouping commands by verb (no run functions)
	deleteDocs := &cobra.Command{
		Short: "Delete an existing Pachyderm resource.",
		Long:  "Delete an existing Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(deleteDocs, "delete"))

	createDocs := &cobra.Command{
		Short: "Create a new instance of a Pachyderm resource.",
		Long:  "Create a new instance of a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(createDocs, "create"))

	updateDocs := &cobra.Command{
		Short: "Change the properties of an existing Pachyderm resource.",
		Long:  "Change the properties of an existing Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(updateDocs, "update"))

	inspectDocs := &cobra.Command{
		Short: "Show detailed information about a Pachyderm resource.",
		Long:  "Show detailed information about a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(inspectDocs, "inspect"))

	listDocs := &cobra.Command{
		Short: "Print a list of Pachyderm resources of a specific type.",
		Long:  "Print a list of Pachyderm resources of a specific type.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(listDocs, "list"))

	startDocs := &cobra.Command{
		Short: "Start a Pachyderm resource.",
		Long:  "Start a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(startDocs, "start"))

	finishDocs := &cobra.Command{
		Short: "Finish a Pachyderm resource.",
		Long:  "Finish a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(finishDocs, "finish"))

	flushDocs := &cobra.Command{
		Short: "Wait for the side-effects of a Pachyderm resource to propagate.",
		Long:  "Wait for the side-effects of a Pachyderm resource to propagate.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(flushDocs, "flush"))

	subscribeDocs := &cobra.Command{
		Short: "Wait for notifications of changes to a Pachyderm resource.",
		Long:  "Wait for notifications of changes to a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(subscribeDocs, "subscribe"))

	putDocs := &cobra.Command{
		Short: "Insert data into Pachyderm.",
		Long:  "Insert data into Pachyderm.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(putDocs, "put"))

	copyDocs := &cobra.Command{
		Short: "Copy a Pachyderm resource.",
		Long:  "Copy a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(copyDocs, "copy"))

	getDocs := &cobra.Command{
		Short: "Get the raw data represented by a Pachyderm resource.",
		Long:  "Get the raw data represented by a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(getDocs, "get"))

	globDocs := &cobra.Command{
		Short: "Print a list of Pachyderm resources matching a glob pattern.",
		Long:  "Print a list of Pachyderm resources matching a glob pattern.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(globDocs, "glob"))

	diffDocs := &cobra.Command{
		Short: "Show the differences between two Pachyderm resources.",
		Long:  "Show the differences between two Pachyderm resources.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(diffDocs, "diff"))

	stopDocs := &cobra.Command{
		Short: "Cancel an ongoing task.",
		Long:  "Cancel an ongoing task.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(stopDocs, "stop"))

	restartDocs := &cobra.Command{
		Short: "Cancel and restart an ongoing task.",
		Long:  "Cancel and restart an ongoing task.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(restartDocs, "restart"))

	editDocs := &cobra.Command{
		Short: "Edit the value of an existing Pachyderm resource.",
		Long:  "Edit the value of an existing Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(editDocs, "edit"))

	subcommands = append(subcommands, pfscmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, ppscmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, deploycmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, authcmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, enterprisecmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, admincmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, debugcmds.Cmds(&noMetrics, &noPortForwarding)...)

	cmdutil.MergeCommands(rootCmd, subcommands)

	applyRootUsageFunc(rootCmd)
	applyCommandCompat1_8(rootCmd, &noMetrics, &noPortForwarding)

	return rootCmd
}
func PachctlCmd() *cobra.Command {
	var verbose bool
	var noMetrics bool
	var noPortForwarding bool

	raw := false
	rawFlags := pflag.NewFlagSet("", pflag.ContinueOnError)
	rawFlags.BoolVar(&raw, "raw", false, "disable pretty printing, print raw json")

	marshaller := &jsonpb.Marshaler{Indent: "  "}

	rootCmd := &cobra.Command{
		Use: os.Args[0],
		Long: `Access the Pachyderm API.

Environment variables:
  PACHD_ADDRESS=<host>:<port>, the pachd server to connect to (e.g. 127.0.0.1:30650).
  PACH_CONFIG=<path>, the path where pachctl will attempt to load your pach config.
  JAEGER_ENDPOINT=<host>:<port>, the Jaeger server to connect to, if PACH_ENABLE_TRACING is set
  PACH_ENABLE_TRACING={true,false}, If true, and JAEGER_ENDPOINT is set, attach a
    Jaeger trace to all outgoing RPCs
`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			log.SetFormatter(new(prefixed.TextFormatter))

			if !verbose {
				log.SetLevel(log.ErrorLevel)
				// Silence grpc logs
				grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, ioutil.Discard))
			} else {
				log.SetLevel(log.DebugLevel)
				// etcd overrides grpc's logs--there's no way to enable one without
				// enabling both.
				// Error and warning logs are discarded because they will be
				// redundantly sent to the info logger. See:
				// https://godoc.org/google.golang.org/grpc/grpclog#NewLoggerV2
				logger := log.StandardLogger()
				etcd.SetLogger(grpclog.NewLoggerV2(
					logutil.NewGRPCLogWriter(logger, "etcd/grpc"),
					ioutil.Discard,
					ioutil.Discard,
				))
			}
		},
		BashCompletionFunction: bashCompletionFunc,
	}
	rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Output verbose logs")
	rootCmd.PersistentFlags().BoolVarP(&noMetrics, "no-metrics", "", false, "Don't report user metrics for this command")
	rootCmd.PersistentFlags().BoolVarP(&noPortForwarding, "no-port-forwarding", "", false, "Disable implicit port forwarding")

	var subcommands []*cobra.Command

	var clientOnly bool
	var timeoutFlag string
	versionCmd := &cobra.Command{
		Short: "Print Pachyderm version information.",
		Long:  "Print Pachyderm version information.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) (retErr error) {
			if clientOnly {
				if raw {
					if err := marshaller.Marshal(os.Stdout, version.Version); err != nil {
						return err
					}
				} else {
					fmt.Println(version.PrettyPrintVersion(version.Version))
				}
				return nil
			}
			if !noMetrics {
				start := time.Now()
				startMetricsWait := metrics.StartReportAndFlushUserAction("Version", start)
				defer startMetricsWait()
				defer func() {
					finishMetricsWait := metrics.FinishReportAndFlushUserAction("Version", retErr, start)
					finishMetricsWait()
				}()
			}

			// Print header + client version
			writer := ansiterm.NewTabWriter(os.Stdout, 20, 1, 3, ' ', 0)
			if raw {
				if err := marshaller.Marshal(os.Stdout, version.Version); err != nil {
					return err
				}
			} else {
				printVersionHeader(writer)
				printVersion(writer, "pachctl", version.Version)
				if err := writer.Flush(); err != nil {
					return err
				}
			}

			// Dial pachd & get server version
			var pachClient *client.APIClient
			var err error
			if timeoutFlag != "default" {
				var timeout time.Duration
				timeout, err = time.ParseDuration(timeoutFlag)
				if err != nil {
					return fmt.Errorf("could not parse timeout duration %q: %v", timeout, err)
				}
				pachClient, err = client.NewOnUserMachine(false, !noPortForwarding, "user", client.WithDialTimeout(timeout))
			} else {
				pachClient, err = client.NewOnUserMachine(false, !noPortForwarding, "user")
			}
			if err != nil {
				return err
			}
			defer pachClient.Close()
			ctx, cancel := context.WithTimeout(context.Background(), time.Second)
			defer cancel()
			version, err := pachClient.GetVersion(ctx, &types.Empty{})

			if err != nil {
				buf := bytes.NewBufferString("")
				errWriter := ansiterm.NewTabWriter(buf, 20, 1, 3, ' ', 0)
				fmt.Fprintf(errWriter, "pachd\t(version unknown) : error connecting to pachd server at address (%v): %v\n\nplease make sure pachd is up (`kubectl get all`) and portforwarding is enabled\n", pachClient.GetAddress(), grpc.ErrorDesc(err))
				errWriter.Flush()
				return errors.New(buf.String())
			}

			// print server version
			if raw {
				if err := marshaller.Marshal(os.Stdout, version); err != nil {
					return err
				}
			} else {
				printVersion(writer, "pachd", version)
				if err := writer.Flush(); err != nil {
					return err
				}
			}
			return nil
		}),
	}
	versionCmd.Flags().BoolVar(&clientOnly, "client-only", false, "If set, "+
		"only print pachctl's version, but don't make any RPCs to pachd. Useful "+
		"if pachd is unavailable")
	versionCmd.Flags().StringVar(&timeoutFlag, "timeout", "default", "If set, "+
		"'pachctl version' will timeout after the given duration (formatted as a "+
		"golang time duration--a number followed by ns, us, ms, s, m, or h). If "+
		"--client-only is set, this flag is ignored. If unset, pachctl will use a "+
		"default timeout; if set to 0s, the call will never time out.")
	versionCmd.Flags().AddFlagSet(rawFlags)
	subcommands = append(subcommands, cmdutil.CreateAlias(versionCmd, "version"))

	deleteAll := &cobra.Command{
		Short: "Delete everything.",
		Long: `Delete all repos, commits, files, pipelines and jobs.
This resets the cluster to its initial state.`,
		Run: cmdutil.RunFixedArgs(0, func(args []string) error {
			client, err := client.NewOnUserMachine(!noMetrics, !noPortForwarding, "user")
			if err != nil {
				return err
			}
			defer client.Close()
			red := color.New(color.FgRed).SprintFunc()
			var repos, pipelines []string
			repoInfos, err := client.ListRepo()
			if err != nil {
				return err
			}
			for _, ri := range repoInfos {
				repos = append(repos, red(ri.Repo.Name))
			}
			pipelineInfos, err := client.ListPipeline()
			if err != nil {
				return err
			}
			for _, pi := range pipelineInfos {
				pipelines = append(pipelines, red(pi.Pipeline.Name))
			}
			fmt.Println("All ACLs, repos, commits, files, pipelines and jobs will be deleted.")
			if len(repos) > 0 {
				fmt.Printf("Repos to delete: %s\n", strings.Join(repos, ", "))
			}
			if len(pipelines) > 0 {
				fmt.Printf("Pipelines to delete: %s\n", strings.Join(pipelines, ", "))
			}
			fmt.Println("Are you sure you want to do this? (y/n):")
			r := bufio.NewReader(os.Stdin)
			bytes, err := r.ReadBytes('\n')
			if err != nil {
				return err
			}
			if bytes[0] == 'y' || bytes[0] == 'Y' {
				return client.DeleteAll()
			}
			return nil
		}),
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(deleteAll, "delete all"))

	var port uint16
	var remotePort uint16
	var samlPort uint16
	var uiPort uint16
	var uiWebsocketPort uint16
	var pfsPort uint16
	var s3gatewayPort uint16
	var namespace string
	portForward := &cobra.Command{
		Short: "Forward a port on the local machine to pachd. This command blocks.",
		Long:  "Forward a port on the local machine to pachd. This command blocks.",
		Run: cmdutil.RunFixedArgs(0, func(args []string) error {
			fw, err := client.NewPortForwarder(namespace)
			if err != nil {
				return err
			}

			if err = fw.Lock(); err != nil {
				return err
			}

			defer fw.Close()

			failCount := 0

			fmt.Println("Forwarding the pachd (Pachyderm daemon) port...")
			if err = fw.RunForDaemon(port, remotePort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the SAML ACS port...")
			if err = fw.RunForSAMLACS(samlPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Printf("Forwarding the dash (Pachyderm dashboard) UI port to http://localhost:%v...\n", uiPort)
			if err = fw.RunForDashUI(uiPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the dash (Pachyderm dashboard) websocket port...")
			if err = fw.RunForDashWebSocket(uiWebsocketPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the PFS port...")
			if err = fw.RunForPFS(pfsPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			fmt.Println("Forwarding the s3gateway port...")
			if err = fw.RunForS3Gateway(s3gatewayPort); err != nil {
				fmt.Printf("%v\n", err)
				failCount++
			}

			if failCount < 6 {
				fmt.Println("CTRL-C to exit")
				ch := make(chan os.Signal, 1)
				signal.Notify(ch, os.Interrupt)
				<-ch
			}

			return nil
		}),
	}
	portForward.Flags().Uint16VarP(&port, "port", "p", 30650, "The local port to bind pachd to.")
	portForward.Flags().Uint16Var(&remotePort, "remote-port", 650, "The remote port that pachd is bound to in the cluster.")
	portForward.Flags().Uint16Var(&samlPort, "saml-port", 30654, "The local port to bind pachd's SAML ACS to.")
	portForward.Flags().Uint16VarP(&uiPort, "ui-port", "u", 30080, "The local port to bind Pachyderm's dash service to.")
	portForward.Flags().Uint16VarP(&uiWebsocketPort, "proxy-port", "x", 30081, "The local port to bind Pachyderm's dash proxy service to.")
	portForward.Flags().Uint16VarP(&pfsPort, "pfs-port", "f", 30652, "The local port to bind PFS over HTTP to.")
	portForward.Flags().Uint16VarP(&s3gatewayPort, "s3gateway-port", "s", 30600, "The local port to bind the s3gateway to.")
	portForward.Flags().StringVar(&namespace, "namespace", "default", "Kubernetes namespace Pachyderm is deployed in.")
	subcommands = append(subcommands, cmdutil.CreateAlias(portForward, "port-forward"))

	var install bool
	var path string
	completion := &cobra.Command{
		Short: "Print or install the bash completion code.",
		Long:  "Print or install the bash completion code. This should be placed as the file `pachctl` in the bash completion directory (by default this is `/etc/bash_completion.d`. If bash-completion was installed via homebrew, this would be `$(brew --prefix)/etc/bash_completion.d`.)",
		Run: cmdutil.RunFixedArgs(0, func(args []string) (retErr error) {
			var dest io.Writer

			if install {
				f, err := os.Create(path)

				if err != nil {
					if os.IsPermission(err) {
						fmt.Fprintf(os.Stderr, "Permission error installing completions, rerun this command with sudo.\n")
					}
					return err
				}

				defer func() {
					if err := f.Close(); err != nil && retErr == nil {
						retErr = err
					}

					fmt.Printf("Bash completions installed in %s, you must restart bash to enable completions.\n", path)
				}()

				dest = f
			} else {
				dest = os.Stdout
			}

			// Remove 'hidden' flag from all commands so we can get bash completions for them as well
			var unhide func(*cobra.Command)
			unhide = func(cmd *cobra.Command) {
				cmd.Hidden = false
				for _, subcmd := range cmd.Commands() {
					unhide(subcmd)
				}
			}
			unhide(rootCmd)

			return rootCmd.GenBashCompletion(dest)
		}),
	}
	completion.Flags().BoolVar(&install, "install", false, "Install the completion.")
	completion.Flags().StringVar(&path, "path", "/etc/bash_completion.d/pachctl", "Path to install the completion to. This will default to `/etc/bash_completion.d/` if unspecified.")
	subcommands = append(subcommands, cmdutil.CreateAlias(completion, "completion"))

	// Logical commands for grouping commands by verb (no run functions)
	deleteDocs := &cobra.Command{
		Short: "Delete an existing Pachyderm resource.",
		Long:  "Delete an existing Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(deleteDocs, "delete"))

	createDocs := &cobra.Command{
		Short: "Create a new instance of a Pachyderm resource.",
		Long:  "Create a new instance of a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(createDocs, "create"))

	updateDocs := &cobra.Command{
		Short: "Change the properties of an existing Pachyderm resource.",
		Long:  "Change the properties of an existing Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(updateDocs, "update"))

	inspectDocs := &cobra.Command{
		Short: "Show detailed information about a Pachyderm resource.",
		Long:  "Show detailed information about a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(inspectDocs, "inspect"))

	listDocs := &cobra.Command{
		Short: "Print a list of Pachyderm resources of a specific type.",
		Long:  "Print a list of Pachyderm resources of a specific type.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(listDocs, "list"))

	startDocs := &cobra.Command{
		Short: "Start a Pachyderm resource.",
		Long:  "Start a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(startDocs, "start"))

	finishDocs := &cobra.Command{
		Short: "Finish a Pachyderm resource.",
		Long:  "Finish a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(finishDocs, "finish"))

	flushDocs := &cobra.Command{
		Short: "Wait for the side-effects of a Pachyderm resource to propagate.",
		Long:  "Wait for the side-effects of a Pachyderm resource to propagate.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(flushDocs, "flush"))

	subscribeDocs := &cobra.Command{
		Short: "Wait for notifications of changes to a Pachyderm resource.",
		Long:  "Wait for notifications of changes to a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(subscribeDocs, "subscribe"))

	putDocs := &cobra.Command{
		Short: "Insert data into Pachyderm.",
		Long:  "Insert data into Pachyderm.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(putDocs, "put"))

	copyDocs := &cobra.Command{
		Short: "Copy a Pachyderm resource.",
		Long:  "Copy a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(copyDocs, "copy"))

	getDocs := &cobra.Command{
		Short: "Get the raw data represented by a Pachyderm resource.",
		Long:  "Get the raw data represented by a Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(getDocs, "get"))

	globDocs := &cobra.Command{
		Short: "Print a list of Pachyderm resources matching a glob pattern.",
		Long:  "Print a list of Pachyderm resources matching a glob pattern.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(globDocs, "glob"))

	diffDocs := &cobra.Command{
		Short: "Show the differences between two Pachyderm resources.",
		Long:  "Show the differences between two Pachyderm resources.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(diffDocs, "diff"))

	stopDocs := &cobra.Command{
		Short: "Cancel an ongoing task.",
		Long:  "Cancel an ongoing task.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(stopDocs, "stop"))

	restartDocs := &cobra.Command{
		Short: "Cancel and restart an ongoing task.",
		Long:  "Cancel and restart an ongoing task.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(restartDocs, "restart"))

	editDocs := &cobra.Command{
		Short: "Edit the value of an existing Pachyderm resource.",
		Long:  "Edit the value of an existing Pachyderm resource.",
	}
	subcommands = append(subcommands, cmdutil.CreateAlias(editDocs, "edit"))

	subcommands = append(subcommands, pfscmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, ppscmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, deploycmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, authcmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, enterprisecmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, admincmds.Cmds(&noMetrics, &noPortForwarding)...)
	subcommands = append(subcommands, debugcmds.Cmds(&noMetrics, &noPortForwarding)...)

	cmdutil.MergeCommands(rootCmd, subcommands)

	applyRootUsageFunc(rootCmd)
	applyCommandCompat1_8(rootCmd, &noMetrics, &noPortForwarding)

	return rootCmd
}
// PachctlCmd creates a cobra.Command which can deploy pachyderm clusters and
// interact with them (it implements the pachctl binary).