feat: added namespace filter (#127)

* feat: added namespace filter

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>

* chore: Moved the explain bool out

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>

---------

Signed-off-by: AlexsJones <alexsimonjones@gmail.com>
This commit is contained in:
Alex Jones 2023-03-28 20:10:42 +01:00 committed by GitHub
parent c8b92aaa0e
commit b78ab3d9b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 53 additions and 27 deletions

View File

@ -103,6 +103,11 @@ _Filter on resource_
k8sgpt analyze --explain --filter=Service k8sgpt analyze --explain --filter=Service
``` ```
_Filter by namespace_
```
k8sgpt analyze --explain --filter=Pod --namespace=default
```
_Output to JSON_ _Output to JSON_
``` ```

View File

@ -17,12 +17,13 @@ import (
) )
var ( var (
explain bool explain bool
backend string backend string
output string output string
filters []string filters []string
language string language string
nocache bool nocache bool
namespace string
) )
// AnalyzeCmd represents the problems command // AnalyzeCmd represents the problems command
@ -68,9 +69,16 @@ var AnalyzeCmd = &cobra.Command{
ctx := context.Background() ctx := context.Background()
// Get kubernetes client from viper // Get kubernetes client from viper
client := viper.Get("kubernetesClient").(*kubernetes.Client) client := viper.Get("kubernetesClient").(*kubernetes.Client)
// Analysis configuration
config := &analyzer.AnalysisConfiguration{
Namespace: namespace,
NoCache: nocache,
Explain: explain,
}
var analysisResults *[]analyzer.Analysis = &[]analyzer.Analysis{} 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) color.Red("Error: %v", err)
os.Exit(1) os.Exit(1)
} }
@ -102,7 +110,7 @@ var AnalyzeCmd = &cobra.Command{
for _, analysis := range *analysisResults { for _, analysis := range *analysisResults {
if explain { if explain {
parsedText, err := analyzer.ParseViaAI(ctx, aiClient, analysis.Error, nocache) parsedText, err := analyzer.ParseViaAI(ctx, config, aiClient, analysis.Error)
if err != nil { if err != nil {
// Check for exhaustion // Check for exhaustion
if strings.Contains(err.Error(), "status code: 429") { if strings.Contains(err.Error(), "status code: 429") {
@ -141,10 +149,13 @@ var AnalyzeCmd = &cobra.Command{
func init() { 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 // array of strings flag
AnalyzeCmd.Flags().StringSliceVarP(&filters, "filter", "f", []string{}, "Filter for these analzyers (e.g. Pod,PersistentVolumeClaim,Service,ReplicaSet)") 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") AnalyzeCmd.Flags().BoolVarP(&explain, "explain", "e", false, "Explain the problem to me")
// add flag for backend // add flag for backend
AnalyzeCmd.Flags().StringVarP(&backend, "backend", "b", "openai", "Backend AI provider") AnalyzeCmd.Flags().StringVarP(&backend, "backend", "b", "openai", "Backend AI provider")

View File

@ -5,6 +5,12 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
type AnalysisConfiguration struct {
Namespace string
NoCache bool
Explain bool
}
type PreAnalysis struct { type PreAnalysis struct {
Pod v1.Pod Pod v1.Pod
FailureDetails []string FailureDetails []string

View File

@ -11,39 +11,40 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
) )
func RunAnalysis(ctx context.Context, client *kubernetes.Client, func RunAnalysis(ctx context.Context, config *AnalysisConfiguration,
aiClient ai.IAI, explain bool, analysisResults *[]Analysis) error { 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 { if err != nil {
return err return err
} }
err = AnalyzeReplicaSet(ctx, client, aiClient, explain, analysisResults) err = AnalyzeReplicaSet(ctx, config, client, aiClient, analysisResults)
if err != nil { if err != nil {
return err return err
} }
err = AnalyzePersistentVolumeClaim(ctx, client, aiClient, explain, analysisResults) err = AnalyzePersistentVolumeClaim(ctx, config, client, aiClient, analysisResults)
if err != nil { if err != nil {
return err return err
} }
err = AnalyzeEndpoints(ctx, client, aiClient, explain, analysisResults) err = AnalyzeEndpoints(ctx, config, client, aiClient, analysisResults)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func ParseViaAI(ctx context.Context, aiClient ai.IAI, prompt []string, func ParseViaAI(ctx context.Context, config *AnalysisConfiguration,
nocache bool) (string, error) { aiClient ai.IAI, prompt []string) (string, error) {
// parse the text with the AI backend // parse the text with the AI backend
inputKey := strings.Join(prompt, " ") inputKey := strings.Join(prompt, " ")
// Check for cached data // Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey)) sEnc := base64.StdEncoding.EncodeToString([]byte(inputKey))
// find in viper cache // find in viper cache
if viper.IsSet(sEnc) && !nocache { if viper.IsSet(sEnc) && !config.NoCache {
// retrieve data from cache // retrieve data from cache
response := viper.GetString(sEnc) response := viper.GetString(sEnc)
if response == "" { if response == "" {

View File

@ -10,10 +10,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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 // 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 { if err != nil {
return err return err
} }

View File

@ -10,10 +10,10 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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 // 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 { if err != nil {
return err return err
} }

View File

@ -10,10 +10,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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 // 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 { if err != nil {
return err return err
} }

View File

@ -11,10 +11,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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 // 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 { if err != nil {
return err return err
} }