Skip to content

Commit

Permalink
feat: added analysis for pvcs
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 14e85b0 commit 88d49ae
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 3 deletions.
7 changes: 4 additions & 3 deletions pkg/analyzer/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
)

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

type Analysis struct {
Expand Down
5 changes: 5 additions & 0 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@ func RunAnalysis(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI
if err != nil {
return err
}

err = AnalyzePersistentVolumeClaim(ctx, client, aiClient, explain, analysisResults)
if err != nil {
return err
}
return nil
}
24 changes: 24 additions & 0 deletions pkg/analyzer/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,27 @@ func FetchLatestPodEvent(ctx context.Context, kubernetesClient *kubernetes.Clien
}
return latestEvent, nil
}

func FetchLatestPvcEvent(ctx context.Context, kubernetesClient *kubernetes.Client, pvc *v1.PersistentVolumeClaim) (*v1.Event, error) {

// get the list of events
events, err := kubernetesClient.GetClient().CoreV1().Events(pvc.Namespace).List(ctx,
metav1.ListOptions{
FieldSelector: "involvedObject.name=" + pvc.Name,
})

if err != nil {
return nil, err
}
// find most recent event
var latestEvent *v1.Event
for _, event := range events.Items {
if latestEvent == nil {
latestEvent = &event
}
if event.LastTimestamp.After(latestEvent.LastTimestamp.Time) {
latestEvent = &event
}
}
return latestEvent, nil
}
108 changes: 108 additions & 0 deletions pkg/analyzer/pvcAnalyzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
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 AnalyzePersistentVolumeClaim(ctx context.Context, client *kubernetes.Client, aiClient ai.IAI, explain bool, analysisResults *[]Analysis) error {

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

var preAnalysis = map[string]PreAnalysis{}

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

// Check for empty rs
if pvc.Status.Phase == "Pending" {

// parse the event log and append details
evt, err := FetchLatestPvcEvent(ctx, client, &pvc)
if err != nil || evt == nil {
continue
}
if evt.Reason == "ProvisioningFailed" && evt.Message != "" {
failures = append(failures, evt.Message)
}
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", pvc.Namespace, pvc.Name)] = PreAnalysis{
PersistentVolumeClaim: pvc,
FailureDetails: failures,
}
}
}

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

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

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

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

// 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
}
currentAnalysis.Details = string(output)
currentAnalysis.ParentObject = parent
*analysisResults = append(*analysisResults, currentAnalysis)
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
}
}
currentAnalysis.Details = response
}
currentAnalysis.ParentObject = parent
*analysisResults = append(*analysisResults, currentAnalysis)
}

return nil
}

0 comments on commit 88d49ae

Please sign in to comment.