Skip to content

Commit

Permalink
feat: introduce StatefulSet analyser.
Browse files Browse the repository at this point in the history
Signed-off-by: Aris Boutselis <aris.boutselis@senseon.io>
  • Loading branch information
Aris Boutselis committed Apr 6, 2023
1 parent 5b098fd commit c041ce2
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var coreAnalyzerMap = map[string]IAnalyzer{
"PersistentVolumeClaim": PvcAnalyzer{},
"Service": ServiceAnalyzer{},
"Ingress": IngressAnalyzer{},
"StatefulSet": StatefulSetAnalyzer{},
}

var additionalAnalyzerMap = map[string]IAnalyzer{
Expand Down
49 changes: 49 additions & 0 deletions pkg/analyzer/statefulset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package analyzer

import (
"fmt"

"github.com/k8sgpt-ai/k8sgpt/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type StatefulSetAnalyzer struct{}

func (StatefulSetAnalyzer) Analyze(a Analyzer) ([]Result, error) {
list, err := a.Client.GetClient().AppsV1().StatefulSets(a.Namespace).List(a.Context, metav1.ListOptions{})
if err != nil {
return nil, err
}
var preAnalysis = map[string]PreAnalysis{}

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

// get serviceName
serviceName := sts.Spec.ServiceName
_, err := a.Client.GetClient().CoreV1().Services(sts.Namespace).Get(a.Context, serviceName, metav1.GetOptions{})
if err != nil {
failures = append(failures, fmt.Sprintf("StatefulSet uses the service %s/%s which does not exist.", sts.Namespace, serviceName))
}
if len(failures) > 0 {
preAnalysis[fmt.Sprintf("%s/%s", sts.Namespace, sts.Name)] = PreAnalysis{
StatefulSet: sts,
FailureDetails: failures,
}
}
}

for key, value := range preAnalysis {
var currentAnalysis = Result{
Kind: "StatefulSet",
Name: key,
Error: value.FailureDetails,
}

parent, _ := util.GetParent(a.Client, value.StatefulSet.ObjectMeta)
currentAnalysis.ParentObject = parent
a.Results = append(a.Results, currentAnalysis)
}

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

import (
"context"
"testing"

"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
"github.com/magiconair/properties/assert"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)

func TestStatefulSetAnalyzer(t *testing.T) {
clientset := fake.NewSimpleClientset(
&appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
})
statefulSetAnalyzer := StatefulSetAnalyzer{}

config := Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := statefulSetAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(analysisResults), 1)
}

func TestStatefulSetAnalyzerWithoutService(t *testing.T) {
clientset := fake.NewSimpleClientset(
&appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "example",
Namespace: "default",
},
Spec: appsv1.StatefulSetSpec{
ServiceName: "example-svc",
},
})
statefulSetAnalyzer := StatefulSetAnalyzer{}

config := Analyzer{
Client: &kubernetes.Client{
Client: clientset,
},
Context: context.Background(),
Namespace: "default",
}
analysisResults, err := statefulSetAnalyzer.Analyze(config)
if err != nil {
t.Error(err)
}
var errorFound bool
want := "StatefulSet uses the service default/example-svc which does not exist."

for _, analysis := range analysisResults {
for _, got := range analysis.Error {
if want == got {
errorFound = true
}
}
if errorFound {
break
}
}
if !errorFound {
t.Errorf("Error expected: '%v', not found in StatefulSet's analysis results", want)
}
}
1 change: 1 addition & 0 deletions pkg/analyzer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type PreAnalysis struct {
Ingress networkv1.Ingress
HorizontalPodAutoscalers autov1.HorizontalPodAutoscaler
PodDisruptionBudget policyv1.PodDisruptionBudget
StatefulSet appsv1.StatefulSet
}

type Result struct {
Expand Down

0 comments on commit c041ce2

Please sign in to comment.