Skip to content

Commit

Permalink
feat: find replicaset errors
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Schuetz <thomas.schuetz@t-sc.eu>
  • Loading branch information
thschue committed Mar 22, 2023
1 parent 2452b0d commit 8ac56e0
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 88 deletions.
92 changes: 4 additions & 88 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,19 @@ package analyzer

import (
"context"
"encoding/base64"
"fmt"
"strings"
"time"

"github.com/briandowns/spinner"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/viper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func RunAnalysis(ctx context.Context, client *kubernetes.Client, aiClient *ai.Client, explain bool) error {

// search all namespaces for pods that are not running
list, err := client.GetClient().CoreV1().Pods("").List(ctx, metav1.ListOptions{})
err := AnalyzePod(ctx, client, aiClient, explain)
if err != nil {
return err
}

var brokenPods = map[string][]string{}

for _, pod := range list.Items {

// Check for pending pods
if pod.Status.Phase == "Pending" {

// Check through container status to check for crashes
for _, containerStatus := range pod.Status.Conditions {
if containerStatus.Type == "PodScheduled" && containerStatus.Reason == "Unschedulable" {
brokenPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = []string{containerStatus.Message}
}
}
}

// Check through container status to check for crashes
var failureDetails = []string{}
for _, containerStatus := range pod.Status.ContainerStatuses {
if containerStatus.State.Waiting != nil {
if containerStatus.State.Waiting.Reason == "CrashLoopBackOff" || containerStatus.State.Waiting.Reason == "ImagePullBackOff" {

failureDetails = append(failureDetails, containerStatus.State.Waiting.Message)
brokenPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = failureDetails
}

}
}

}

count := 0
for key, value := range brokenPods {
fmt.Printf("%s: %s: %s\n", color.CyanString("%d", count), color.YellowString(key), color.RedString(value[0]))
count++
if explain {
s := spinner.New(spinner.CharSets[35], 100*time.Millisecond) // Build our new spinner
s.Start()

inputValue := strings.Join(value, " ")

// Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputValue))
// find in viper cache
if viper.IsSet(sEnc) {
s.Stop()
// retrieve data from cache
response := viper.GetString(sEnc)
if response == "" {
color.Red("error retrieving cached data")
continue
}
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
continue
}

color.Green(string(output))
continue
}

response, err := aiClient.GetCompletion(ctx, inputValue)
s.Stop()
if err != nil {
color.Red("error getting completion: %v", err)
continue
}

if !viper.IsSet(sEnc) {
viper.Set(sEnc, base64.StdEncoding.EncodeToString([]byte(response)))
if err := viper.WriteConfig(); err != nil {
return err
}
}
}
err = AnalyzeReplicaSet(ctx, client, aiClient, explain)
if err != nil {
return err
}

return nil
}
103 changes: 103 additions & 0 deletions pkg/analyzer/podAnalyzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package analyzer

import (
"context"
"encoding/base64"
"fmt"
"github.com/briandowns/spinner"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/viper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"strings"
"time"
)

func AnalyzePod(ctx context.Context, client *kubernetes.Client, aiClient *ai.Client, explain bool) error {

// search all namespaces for pods that are not running
list, err := client.GetClient().CoreV1().Pods("").List(ctx, metav1.ListOptions{})
if err != nil {
return err
}

var brokenPods = map[string][]string{}

for _, pod := range list.Items {

// Check for pending pods
if pod.Status.Phase == "Pending" {

// Check through container status to check for crashes
for _, containerStatus := range pod.Status.Conditions {
if containerStatus.Type == "PodScheduled" && containerStatus.Reason == "Unschedulable" {
brokenPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = []string{containerStatus.Message}
}
}
}

// Check through container status to check for crashes
var failureDetails = []string{}
for _, containerStatus := range pod.Status.ContainerStatuses {
if containerStatus.State.Waiting != nil {
if containerStatus.State.Waiting.Reason == "CrashLoopBackOff" || containerStatus.State.Waiting.Reason == "ImagePullBackOff" {

failureDetails = append(failureDetails, containerStatus.State.Waiting.Message)
brokenPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = failureDetails
}

}
}

}

count := 0
for key, value := range brokenPods {
fmt.Printf("%s: %s: %s\n", color.CyanString("%d", count), color.YellowString(key), color.RedString(value[0]))
count++
if explain {
s := spinner.New(spinner.CharSets[35], 100*time.Millisecond) // Build our new spinner
s.Start()

inputValue := strings.Join(value, " ")

// Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputValue))
// find in viper cache
if viper.IsSet(sEnc) {
s.Stop()
// retrieve data from cache
response := viper.GetString(sEnc)
if response == "" {
color.Red("error retrieving cached data")
continue
}
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
continue
}

color.Green(string(output))
continue
}

response, err := aiClient.GetCompletion(ctx, inputValue)
s.Stop()
if err != nil {
color.Red("error getting completion: %v", err)
continue
}

if !viper.IsSet(sEnc) {
viper.Set(sEnc, base64.StdEncoding.EncodeToString([]byte(response)))
if err := viper.WriteConfig(); err != nil {
return err
}
}
}
}

return nil
}
89 changes: 89 additions & 0 deletions pkg/analyzer/rsAnalyzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package analyzer

import (
"context"
"encoding/base64"
"fmt"
"github.com/briandowns/spinner"
"github.com/fatih/color"
"github.com/k8sgpt-ai/k8sgpt/pkg/ai"
"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/spf13/viper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"strings"
"time"
)

func AnalyzeReplicaSet(ctx context.Context, client *kubernetes.Client, aiClient *ai.Client, explain bool) error {

// search all namespaces for pods that are not running
list, err := client.GetClient().AppsV1().ReplicaSets("").List(ctx, metav1.ListOptions{})
if err != nil {
return err
}

var brokenRS = map[string][]string{}

for _, rs := range list.Items {

// Check for empty rs
if rs.Status.Replicas == 0 {

// Check through container status to check for crashes
for _, rsStatus := range rs.Status.Conditions {
if rsStatus.Type == "ReplicaFailure" && rsStatus.Reason == "FailedCreate" {
brokenRS[fmt.Sprintf("%s/%s", rs.Namespace, rs.Name)] = []string{rsStatus.Message}
}
}
}
}

count := 0
for key, value := range brokenRS {
fmt.Printf("%s: %s: %s\n", color.CyanString("%d", count), color.YellowString(key), color.RedString(value[0]))
count++
if explain {
s := spinner.New(spinner.CharSets[35], 100*time.Millisecond) // Build our new spinner
s.Start()

inputValue := strings.Join(value, " ")

// Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputValue))
// find in viper cache
if viper.IsSet(sEnc) {
s.Stop()
// retrieve data from cache
response := viper.GetString(sEnc)
if response == "" {
color.Red("error retrieving cached data")
continue
}
output, err := base64.StdEncoding.DecodeString(response)
if err != nil {
color.Red("error decoding cached data: %v", err)
continue
}

color.Green(string(output))
continue
}

response, err := aiClient.GetCompletion(ctx, inputValue)
s.Stop()
if err != nil {
color.Red("error getting completion: %v", err)
continue
}

if !viper.IsSet(sEnc) {
viper.Set(sEnc, base64.StdEncoding.EncodeToString([]byte(response)))
if err := viper.WriteConfig(); err != nil {
return err
}
}
}
}

return nil
}

0 comments on commit 8ac56e0

Please sign in to comment.