diff --git a/README.md b/README.md index 2551cd5a22..3baa2cf988 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,11 @@ _Filter on resource_ k8sgpt analyze --explain --filter=Service ``` +_Filter by namespace_ +``` +k8sgpt analyze --explain --filter=Pod --namespace=default +``` + _Output to JSON_ ``` diff --git a/cmd/analyze/analyze.go b/cmd/analyze/analyze.go index 5cccc665a5..cc7362a18a 100644 --- a/cmd/analyze/analyze.go +++ b/cmd/analyze/analyze.go @@ -17,12 +17,13 @@ import ( ) var ( - explain bool - backend string - output string - filters []string - language string - nocache bool + explain bool + backend string + output string + filters []string + language string + nocache bool + namespace string ) // AnalyzeCmd represents the problems command @@ -68,9 +69,16 @@ var AnalyzeCmd = &cobra.Command{ ctx := context.Background() // Get kubernetes client from viper client := viper.Get("kubernetesClient").(*kubernetes.Client) + // Analysis configuration + config := &analyzer.AnalysisConfiguration{ + Namespace: namespace, + NoCache: nocache, + Explain: explain, + } var analysisResults *[]analyzer.Analysis = &[]analyzer.Analysis{} - if err := analyzer.RunAnalysis(ctx, client, aiClient, explain, analysisResults); err != nil { + if err := analyzer.RunAnalysis(ctx, config, client, + aiClient, analysisResults); err != nil { color.Red("Error: %v", err) os.Exit(1) } @@ -102,7 +110,7 @@ var AnalyzeCmd = &cobra.Command{ for _, analysis := range *analysisResults { if explain { - parsedText, err := analyzer.ParseViaAI(ctx, aiClient, analysis.Error, nocache) + parsedText, err := analyzer.ParseViaAI(ctx, config, aiClient, analysis.Error) if err != nil { // Check for exhaustion if strings.Contains(err.Error(), "status code: 429") { @@ -141,10 +149,13 @@ var AnalyzeCmd = &cobra.Command{ func init() { - AnalyzeCmd.Flags().BoolVarP(&nocache, "no-cache", "n", false, "Do not use cached data") + // namespace flag + AnalyzeCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "Namespace to analyze") + // no cache flag + AnalyzeCmd.Flags().BoolVarP(&nocache, "no-cache", "c", false, "Do not use cached data") // array of strings flag AnalyzeCmd.Flags().StringSliceVarP(&filters, "filter", "f", []string{}, "Filter for these analzyers (e.g. Pod,PersistentVolumeClaim,Service,ReplicaSet)") - + // explain flag AnalyzeCmd.Flags().BoolVarP(&explain, "explain", "e", false, "Explain the problem to me") // add flag for backend AnalyzeCmd.Flags().StringVarP(&backend, "backend", "b", "openai", "Backend AI provider") diff --git a/pkg/analyzer/analysis.go b/pkg/analyzer/analysis.go index 99237df3aa..07ef4b146f 100644 --- a/pkg/analyzer/analysis.go +++ b/pkg/analyzer/analysis.go @@ -5,6 +5,12 @@ import ( v1 "k8s.io/api/core/v1" ) +type AnalysisConfiguration struct { + Namespace string + NoCache bool + Explain bool +} + type PreAnalysis struct { Pod v1.Pod FailureDetails []string diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go index c5bd24a2dd..d45e90cec7 100644 --- a/pkg/analyzer/analyzer.go +++ b/pkg/analyzer/analyzer.go @@ -11,39 +11,40 @@ import ( "github.com/spf13/viper" ) -func RunAnalysis(ctx context.Context, client *kubernetes.Client, - aiClient ai.IAI, explain bool, analysisResults *[]Analysis) error { +func RunAnalysis(ctx context.Context, config *AnalysisConfiguration, + client *kubernetes.Client, + aiClient ai.IAI, analysisResults *[]Analysis) error { - err := AnalyzePod(ctx, client, aiClient, explain, analysisResults) + err := AnalyzePod(ctx, config, client, aiClient, analysisResults) if err != nil { return err } - err = AnalyzeReplicaSet(ctx, client, aiClient, explain, analysisResults) + err = AnalyzeReplicaSet(ctx, config, client, aiClient, analysisResults) if err != nil { return err } - err = AnalyzePersistentVolumeClaim(ctx, client, aiClient, explain, analysisResults) + err = AnalyzePersistentVolumeClaim(ctx, config, client, aiClient, analysisResults) if err != nil { return err } - err = AnalyzeEndpoints(ctx, client, aiClient, explain, analysisResults) + err = AnalyzeEndpoints(ctx, config, client, aiClient, analysisResults) if err != nil { return err } return nil } -func ParseViaAI(ctx context.Context, aiClient ai.IAI, prompt []string, - nocache bool) (string, error) { +func ParseViaAI(ctx context.Context, config *AnalysisConfiguration, + aiClient ai.IAI, prompt []string) (string, error) { // parse the text with the AI backend inputKey := strings.Join(prompt, " ") // Check for cached data sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey)) // find in viper cache - if viper.IsSet(sEnc) && !nocache { + if viper.IsSet(sEnc) && !config.NoCache { // retrieve data from cache response := viper.GetString(sEnc) if response == "" { diff --git a/pkg/analyzer/podAnalyzer.go b/pkg/analyzer/podAnalyzer.go index d12ea1c9e9..9ce7b803e1 100644 --- a/pkg/analyzer/podAnalyzer.go +++ b/pkg/analyzer/podAnalyzer.go @@ -10,10 +10,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func AnalyzePod(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI, explain bool, analysisResults *[]Analysis) error { +func AnalyzePod(ctx context.Context, config *AnalysisConfiguration, + client *kubernetes.Client, aiClient ai.IAI, analysisResults *[]Analysis) error { // search all namespaces for pods that are not running - list, err := client.GetClient().CoreV1().Pods("").List(ctx, metav1.ListOptions{}) + list, err := client.GetClient().CoreV1().Pods(config.Namespace).List(ctx, metav1.ListOptions{}) if err != nil { return err } diff --git a/pkg/analyzer/pvcAnalyzer.go b/pkg/analyzer/pvcAnalyzer.go index 791ae6ba6f..6823bca61f 100644 --- a/pkg/analyzer/pvcAnalyzer.go +++ b/pkg/analyzer/pvcAnalyzer.go @@ -10,10 +10,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func AnalyzePersistentVolumeClaim(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI, explain bool, analysisResults *[]Analysis) error { +func AnalyzePersistentVolumeClaim(ctx context.Context, config *AnalysisConfiguration, client *kubernetes.Client, aiClient ai.IAI, analysisResults *[]Analysis) error { // search all namespaces for pods that are not running - list, err := client.GetClient().CoreV1().PersistentVolumeClaims("").List(ctx, metav1.ListOptions{}) + list, err := client.GetClient().CoreV1().PersistentVolumeClaims(config.Namespace).List(ctx, metav1.ListOptions{}) if err != nil { return err } diff --git a/pkg/analyzer/rsAnalyzer.go b/pkg/analyzer/rsAnalyzer.go index 61fa7c799f..360c7ef038 100644 --- a/pkg/analyzer/rsAnalyzer.go +++ b/pkg/analyzer/rsAnalyzer.go @@ -10,10 +10,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func AnalyzeReplicaSet(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI, explain bool, analysisResults *[]Analysis) error { +func AnalyzeReplicaSet(ctx context.Context, config *AnalysisConfiguration, + client *kubernetes.Client, aiClient ai.IAI, analysisResults *[]Analysis) error { // search all namespaces for pods that are not running - list, err := client.GetClient().AppsV1().ReplicaSets("").List(ctx, metav1.ListOptions{}) + list, err := client.GetClient().AppsV1().ReplicaSets(config.Namespace).List(ctx, metav1.ListOptions{}) if err != nil { return err } diff --git a/pkg/analyzer/serviceAnalyzer.go b/pkg/analyzer/serviceAnalyzer.go index d2b41da829..34c8e930b2 100644 --- a/pkg/analyzer/serviceAnalyzer.go +++ b/pkg/analyzer/serviceAnalyzer.go @@ -11,10 +11,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func AnalyzeEndpoints(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI, explain bool, analysisResults *[]Analysis) error { +func AnalyzeEndpoints(ctx context.Context, config *AnalysisConfiguration, client *kubernetes.Client, aiClient ai.IAI, + analysisResults *[]Analysis) error { // search all namespaces for pods that are not running - list, err := client.GetClient().CoreV1().Endpoints("").List(ctx, metav1.ListOptions{}) + list, err := client.GetClient().CoreV1().Endpoints(config.Namespace).List(ctx, metav1.ListOptions{}) if err != nil { return err }