|
| 1 | +package cli |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "os" |
| 6 | + "strings" |
| 7 | + |
| 8 | + "github.com/replicatedhq/troubleshoot/cmd/internal/util" |
| 9 | + "github.com/replicatedhq/troubleshoot/pkg/k8sutil" |
| 10 | + "github.com/replicatedhq/troubleshoot/pkg/logger" |
| 11 | + "github.com/spf13/cobra" |
| 12 | + "github.com/spf13/viper" |
| 13 | + "k8s.io/klog/v2" |
| 14 | +) |
| 15 | + |
| 16 | +// validateArgs allows certain flags to run without requiring bundle arguments |
| 17 | +func validateArgs(cmd *cobra.Command, args []string) error { |
| 18 | + // Special flags that don't require bundle arguments |
| 19 | + if cmd.Flags().Changed("check-ollama") || cmd.Flags().Changed("setup-ollama") || |
| 20 | + cmd.Flags().Changed("list-models") || cmd.Flags().Changed("pull-model") { |
| 21 | + return nil |
| 22 | + } |
| 23 | + |
| 24 | + // For all other cases, require at least 1 argument (the bundle path) |
| 25 | + if len(args) < 1 { |
| 26 | + return fmt.Errorf("requires at least 1 arg(s), only received %d. Usage: analyze [bundle-path] or use --check-ollama/--setup-ollama", len(args)) |
| 27 | + } |
| 28 | + |
| 29 | + return nil |
| 30 | +} |
| 31 | + |
| 32 | +func RootCmd() *cobra.Command { |
| 33 | + cmd := &cobra.Command{ |
| 34 | + Use: "analyze [url]", |
| 35 | + Args: validateArgs, |
| 36 | + Short: "Analyze a support bundle", |
| 37 | + Long: `Run a series of analyzers on a support bundle archive`, |
| 38 | + SilenceUsage: true, |
| 39 | + PreRun: func(cmd *cobra.Command, args []string) { |
| 40 | + v := viper.GetViper() |
| 41 | + v.BindPFlags(cmd.Flags()) |
| 42 | + |
| 43 | + logger.SetupLogger(v) |
| 44 | + |
| 45 | + if err := util.StartProfiling(); err != nil { |
| 46 | + klog.Errorf("Failed to start profiling: %v", err) |
| 47 | + } |
| 48 | + }, |
| 49 | + RunE: func(cmd *cobra.Command, args []string) error { |
| 50 | + v := viper.GetViper() |
| 51 | + |
| 52 | + // Handle cases where no bundle argument is provided (for utility flags) |
| 53 | + var bundlePath string |
| 54 | + if len(args) > 0 { |
| 55 | + bundlePath = args[0] |
| 56 | + } |
| 57 | + |
| 58 | + return runAnalyzers(v, bundlePath) |
| 59 | + }, |
| 60 | + PostRun: func(cmd *cobra.Command, args []string) { |
| 61 | + if err := util.StopProfiling(); err != nil { |
| 62 | + klog.Errorf("Failed to stop profiling: %v", err) |
| 63 | + } |
| 64 | + }, |
| 65 | + } |
| 66 | + |
| 67 | + cobra.OnInitialize(initConfig) |
| 68 | + |
| 69 | + cmd.AddCommand(util.VersionCmd()) |
| 70 | + |
| 71 | + cmd.Flags().String("analyzers", "", "filename or url of the analyzers to use") |
| 72 | + cmd.Flags().Bool("debug", false, "enable debug logging") |
| 73 | + |
| 74 | + // Advanced analysis flags |
| 75 | + cmd.Flags().Bool("advanced-analysis", false, "use advanced analysis engine with AI capabilities") |
| 76 | + cmd.Flags().StringSlice("agents", []string{"local"}, "analysis agents to use: local, hosted, ollama") |
| 77 | + cmd.Flags().Bool("enable-ollama", false, "enable Ollama AI-powered analysis") |
| 78 | + cmd.Flags().Bool("disable-ollama", false, "explicitly disable Ollama AI-powered analysis") |
| 79 | + cmd.Flags().String("ollama-endpoint", "http://localhost:11434", "Ollama server endpoint") |
| 80 | + cmd.Flags().String("ollama-model", "llama2:7b", "Ollama model to use for analysis") |
| 81 | + cmd.Flags().Bool("use-codellama", false, "use CodeLlama model for code-focused analysis") |
| 82 | + cmd.Flags().Bool("use-mistral", false, "use Mistral model for fast analysis") |
| 83 | + cmd.Flags().Bool("auto-pull-model", true, "automatically pull model if not available") |
| 84 | + cmd.Flags().Bool("list-models", false, "list all available/installed Ollama models and exit") |
| 85 | + cmd.Flags().Bool("pull-model", false, "pull the specified model and exit") |
| 86 | + cmd.Flags().Bool("setup-ollama", false, "automatically setup and configure Ollama") |
| 87 | + cmd.Flags().Bool("check-ollama", false, "check Ollama installation status and exit") |
| 88 | + cmd.Flags().Bool("include-remediation", true, "include remediation suggestions in analysis results") |
| 89 | + cmd.Flags().String("output-file", "", "save analysis results to file (e.g., --output-file results.json)") |
| 90 | + |
| 91 | + viper.BindPFlags(cmd.Flags()) |
| 92 | + |
| 93 | + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) |
| 94 | + |
| 95 | + // Initialize klog flags |
| 96 | + logger.InitKlogFlags(cmd) |
| 97 | + |
| 98 | + k8sutil.AddFlags(cmd.Flags()) |
| 99 | + |
| 100 | + // CPU and memory profiling flags |
| 101 | + util.AddProfilingFlags(cmd) |
| 102 | + |
| 103 | + return cmd |
| 104 | +} |
| 105 | + |
| 106 | +func InitAndExecute() { |
| 107 | + if err := RootCmd().Execute(); err != nil { |
| 108 | + os.Exit(1) |
| 109 | + } |
| 110 | +} |
| 111 | + |
| 112 | +func initConfig() { |
| 113 | + viper.SetEnvPrefix("TROUBLESHOOT") |
| 114 | + viper.AutomaticEnv() |
| 115 | +} |
0 commit comments