linkerd2/cli/cmd/root.go

157 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"fmt"
"os"
"regexp"
"strings"
"github.com/fatih/color"
"github.com/linkerd/linkerd2/cli/flag"
jaeger "github.com/linkerd/linkerd2/jaeger/cmd"
multicluster "github.com/linkerd/linkerd2/multicluster/cmd"
pkgcmd "github.com/linkerd/linkerd2/pkg/cmd"
"github.com/linkerd/linkerd2/pkg/flags"
"github.com/linkerd/linkerd2/pkg/healthcheck"
viz "github.com/linkerd/linkerd2/viz/cmd"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
const (
defaultLinkerdNamespace = "linkerd"
defaultCNINamespace = "linkerd-cni"
defaultClusterDomain = "cluster.local"
defaultDockerRegistry = "cr.l5d.io/linkerd"
jsonOutput = healthcheck.JSONOutput
tableOutput = healthcheck.TableOutput
shortOutput = healthcheck.ShortOutput
)
var (
// special handling for Windows, on all other platforms these resolve to
// os.Stdout and os.Stderr, thanks to https://github.com/mattn/go-colorable
stdout = color.Output
stderr = color.Error
okStatus = color.New(color.FgGreen, color.Bold).SprintFunc()("\u221A") // √
warnStatus = color.New(color.FgYellow, color.Bold).SprintFunc()("\u203C") // ‼
failStatus = color.New(color.FgRed, color.Bold).SprintFunc()("\u00D7") // ×
controlPlaneNamespace string
cniNamespace string
apiAddr string // An empty value means "use the Kubernetes configuration"
kubeconfigPath string
kubeContext string
impersonate string
impersonateGroup []string
verbose bool
// These regexs are not as strict as they could be, but are a quick and dirty
// sanity check against illegal characters.
alphaNumDash = regexp.MustCompile(`^[a-zA-Z0-9-]+$`)
alphaNumDashDot = regexp.MustCompile(`^[\.a-zA-Z0-9-]+$`)
alphaNumDashDotSlashColon = regexp.MustCompile(`^[\./a-zA-Z0-9-:]+$`)
// Full Rust log level syntax at
// https://docs.rs/env_logger/0.6.0/env_logger/#enabling-logging
r = strings.NewReplacer("\t", "", "\n", "")
validProxyLogLevel = regexp.MustCompile(r.Replace(`
^(
(
(trace|debug|warn|info|error)|
(\w|::)+|
((\w|::)+=(trace|debug|warn|info|error))
)(?:,|$)
)+$`))
)
// RootCmd represents the root Cobra command
var RootCmd = &cobra.Command{
Use: "linkerd",
Short: "linkerd manages the Linkerd service mesh",
Long: `linkerd manages the Linkerd service mesh.`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// enable / disable logging
if verbose {
log.SetLevel(log.DebugLevel)
} else {
log.SetLevel(log.PanicLevel)
}
controlPlaneNamespaceFromEnv := os.Getenv(flags.EnvOverrideNamespace)
if controlPlaneNamespace == defaultLinkerdNamespace && controlPlaneNamespaceFromEnv != "" {
controlPlaneNamespace = controlPlaneNamespaceFromEnv
}
if !alphaNumDash.MatchString(controlPlaneNamespace) {
return fmt.Errorf("%s is not a valid namespace", controlPlaneNamespace)
}
return nil
},
}
func init() {
RootCmd.PersistentFlags().StringVarP(&controlPlaneNamespace, "linkerd-namespace", "L",
defaultLinkerdNamespace,
fmt.Sprintf("Namespace in which Linkerd is installed ($%s)", flags.EnvOverrideNamespace))
RootCmd.PersistentFlags().StringVarP(&cniNamespace, "cni-namespace", "", defaultCNINamespace, "Namespace in which the Linkerd CNI plugin is installed")
RootCmd.PersistentFlags().StringVar(&kubeconfigPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests")
RootCmd.PersistentFlags().StringVar(&kubeContext, "context", "", "Name of the kubeconfig context to use")
RootCmd.PersistentFlags().StringVar(&impersonate, "as", "", "Username to impersonate for Kubernetes operations")
RootCmd.PersistentFlags().StringArrayVar(&impersonateGroup, "as-group", []string{}, "Group to impersonate for Kubernetes operations")
RootCmd.PersistentFlags().StringVar(&apiAddr, "api-addr", "", "Override kubeconfig and communicate directly with the control plane at host:port (mostly for testing)")
RootCmd.PersistentFlags().BoolVar(&verbose, "verbose", false, "Turn on debug logging")
RootCmd.AddCommand(newCmdAlpha())
RootCmd.AddCommand(newCmdCheck())
RootCmd.AddCommand(newCmdCompletion())
RootCmd.AddCommand(newCmdDiagnostics())
RootCmd.AddCommand(newCmdDoc())
RootCmd.AddCommand(newCmdIdentity())
RootCmd.AddCommand(newCmdInject())
RootCmd.AddCommand(newCmdInstall())
RootCmd.AddCommand(newCmdInstallCNIPlugin())
RootCmd.AddCommand(newCmdProfile())
RootCmd.AddCommand(newCmdAuthz())
RootCmd.AddCommand(newCmdUninject())
RootCmd.AddCommand(newCmdUpgrade())
RootCmd.AddCommand(newCmdVersion())
RootCmd.AddCommand(newCmdUninstall())
RootCmd.AddCommand(newCmdPrune())
// Extension Sub Commands
RootCmd.AddCommand(jaeger.NewCmdJaeger())
RootCmd.AddCommand(multicluster.NewCmdMulticluster())
RootCmd.AddCommand(viz.NewCmdViz())
// Viz Extension sub commands
RootCmd.AddCommand(deprecateCmd(viz.NewCmdDashboard()))
RootCmd.AddCommand(deprecateCmd(viz.NewCmdEdges()))
RootCmd.AddCommand(deprecateCmd(viz.NewCmdRoutes()))
RootCmd.AddCommand(deprecateCmd(viz.NewCmdStat()))
RootCmd.AddCommand(deprecateCmd(viz.NewCmdTap()))
RootCmd.AddCommand(deprecateCmd(viz.NewCmdTop()))
// resource-aware completion flag configurations
pkgcmd.ConfigureNamespaceFlagCompletion(
RootCmd, []string{"linkerd-namespace", "cni-namespace"},
kubeconfigPath, impersonate, impersonateGroup, kubeContext)
pkgcmd.ConfigureKubeContextFlagCompletion(RootCmd, kubeconfigPath)
}
func deprecateCmd(cmd *cobra.Command) *cobra.Command {
cmd.Deprecated = fmt.Sprintf("use instead 'linkerd viz %s'\n", cmd.Use)
return cmd
}
func flattenFlags(flags ...[]flag.Flag) []flag.Flag {
out := []flag.Flag{}
for _, f := range flags {
out = append(out, f...)
}
return out
}