Skip to content

Commit

Permalink
feat: find parent objects
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 25, 2023
1 parent 3621766 commit b29c6e4
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 28 deletions.
3 changes: 1 addition & 2 deletions cmd/find/problems.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ var problemsCmd = &cobra.Command{
}
fmt.Println(string(j))
default:
fmt.Printf("%s %s: %s \n%s\n", color.CyanString("%d", n), color.YellowString(analysis.Name), color.RedString(analysis.Error), color.GreenString(analysis.Details))

fmt.Printf("%s %s(%s): %s \n%s\n", color.CyanString("%d", n), color.YellowString(analysis.Name), color.CyanString(analysis.ParentObject), color.RedString(analysis.Error), color.GreenString(analysis.Details))
}
}

Expand Down
20 changes: 16 additions & 4 deletions pkg/analyzer/analysis.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
package analyzer

import (
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)

type PreAnalysis struct {
Pod v1.Pod
FailureDetails []string
ReplicaSet appsv1.ReplicaSet
}

type Analysis struct {
Kind string
Name string
Error string
Details string
Kind string `json:"kind"`
Name string `json:"name"`
Error string `json:"error"`
Details string `json:"details"`
ParentObject string `json:"parentObject"`
}
89 changes: 72 additions & 17 deletions pkg/analyzer/podAnalyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,30 @@ func AnalyzePod(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI,
if err != nil {
return err
}

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

for _, pod := range list.Items {

var failures []string
// 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}
if containerStatus.Message != "" {
failures = []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
if containerStatus.State.Waiting.Message != "" {
failures = append(failures, containerStatus.State.Waiting.Message)
}
}
// This represents a container that is still being created or blocked due to conditions such as OOMKilled
if containerStatus.State.Waiting.Reason == "ContainerCreating" && pod.Status.Phase == "Pending" {
Expand All @@ -55,24 +55,30 @@ func AnalyzePod(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI,
if err != nil {
continue
}
if evt.Reason == "FailedCreatePodSandBox" {
failureDetails = append(failureDetails, evt.Message)
brokenPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = failureDetails
if evt.Reason == "FailedCreatePodSandBox" && evt.Message != "" {
failures = append(failures, evt.Message)
}
}

}
}

if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = PreAnalysis{
Pod: pod,
FailureDetails: failures,
}
}
}

for key, value := range brokenPods {
inputValue := strings.Join(value, " ")
for key, value := range preAnalysis {
inputValue := strings.Join(value.FailureDetails, " ")
var currentAnalysis = Analysis{
Kind: "Pod",
Name: key,
Error: value[0],
Error: value.FailureDetails[0],
}

parent, _ := getParent(client, value.Pod.ObjectMeta)

if explain {
s := spinner.New(spinner.CharSets[35], 100*time.Millisecond) // Build our new spinner
s.Start()
Expand Down Expand Up @@ -112,10 +118,59 @@ func AnalyzePod(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI,
}
}
currentAnalysis.Details = response

}
currentAnalysis.ParentObject = parent
*analysisResults = append(*analysisResults, currentAnalysis)
}

return nil
}

func getParent(client *kubernetes.Client, meta metav1.ObjectMeta) (string, bool) {
if meta.OwnerReferences != nil {
for _, owner := range meta.OwnerReferences {
switch owner.Kind {
case "ReplicaSet":
rs, err := client.GetClient().AppsV1().ReplicaSets(meta.Namespace).Get(context.Background(), owner.Name, metav1.GetOptions{})
if err != nil {
return "", false
}
if rs.OwnerReferences != nil {
return getParent(client, rs.ObjectMeta)
}
return "ReplicaSet/" + rs.Name, false

case "Deployment":
dep, err := client.GetClient().AppsV1().Deployments(meta.Namespace).Get(context.Background(), owner.Name, metav1.GetOptions{})
if err != nil {
return "", false
}
if dep.OwnerReferences != nil {
return getParent(client, dep.ObjectMeta)
}
return "Deployment/" + dep.Name, false

case "StatefulSet":
sts, err := client.GetClient().AppsV1().StatefulSets(meta.Namespace).Get(context.Background(), owner.Name, metav1.GetOptions{})
if err != nil {
return "", false
}
if sts.OwnerReferences != nil {
return getParent(client, sts.ObjectMeta)
}
return "StatefulSet/" + sts.Name, false

case "DaemonSet":
ds, err := client.GetClient().AppsV1().DaemonSets(meta.Namespace).Get(context.Background(), owner.Name, metav1.GetOptions{})
if err != nil {
return "", false
}
if ds.OwnerReferences != nil {
return getParent(client, ds.ObjectMeta)
}
return "DaemonSet/" + ds.Name, false
}
}
}
return meta.Name, false
}
20 changes: 15 additions & 5 deletions pkg/analyzer/rsAnalyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,43 @@ func AnalyzeReplicaSet(ctx context.Context, client *kubernetes.Client, aiClient
return err
}

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

for _, rs := range list.Items {
var failures []string

// 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}
failures = []string{rsStatus.Message}
}
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", rs.Namespace, rs.Name)] = PreAnalysis{
ReplicaSet: rs,
FailureDetails: failures,
}
}
}

for key, value := range brokenRS {
for key, value := range preAnalysis {
var currentAnalysis = Analysis{
Kind: "ReplicaSet",
Name: key,
Error: value[0],
Error: value.FailureDetails[0],
}

parent, _ := getParent(client, value.ReplicaSet.ObjectMeta)

if explain {
s := spinner.New(spinner.CharSets[35], 100*time.Millisecond) // Build our new spinner
s.Start()

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

// Check for cached data
sEnc := base64.StdEncoding.EncodeToString([]byte(inputValue))
Expand Down Expand Up @@ -88,6 +97,7 @@ func AnalyzeReplicaSet(ctx context.Context, client *kubernetes.Client, aiClient
}
currentAnalysis.Details = response
}
currentAnalysis.ParentObject = parent
*analysisResults = append(*analysisResults, currentAnalysis)
}

Expand Down

0 comments on commit b29c6e4

Please sign in to comment.