Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding abstraction to code and enhance the codecov #138

Merged
merged 13 commits into from
Aug 25, 2023
42 changes: 31 additions & 11 deletions controller/collect-data.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,23 @@ import (
clientTypes "k8s.io/apimachinery/pkg/types"
)

//go:generate mockgen -destination=mocks/mock_collect-data.go -package=mocks github.com/litmuschaos/chaos-exporter/controller ResultCollector

// ResultCollector interface for the both functions GetResultList and getExperimentMetricsFromResult
type ResultCollector interface {
GetResultList(clients clients.ClientSets, chaosNamespace string, monitoringEnabled *MonitoringEnabled) (litmuschaosv1alpha1.ChaosResultList, error)
GetExperimentMetricsFromResult(chaosResult *litmuschaosv1alpha1.ChaosResult, clients clients.ClientSets) (bool, error)
SetResultDetails()
GetResultDetails() ChaosResultDetails
}
type ResultDetails struct {
resultDetails ChaosResultDetails
}

// GetResultList return the result list correspond to the monitoring enabled chaosengine
func GetResultList(clients clients.ClientSets, chaosNamespace string, monitoringEnabled *MonitoringEnabled) (litmuschaosv1alpha1.ChaosResultList, error) {
func (r *ResultDetails) GetResultList(clients clients.ClientSets, chaosNamespace string, monitoringEnabled *MonitoringEnabled) (litmuschaosv1alpha1.ChaosResultList, error) {

chaosResultList, err := clients.LitmusClient.ChaosResults(chaosNamespace).List(context.Background(), metav1.ListOptions{})
chaosResultList, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosResults(chaosNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
return litmuschaosv1alpha1.ChaosResultList{}, err
}
Expand All @@ -41,15 +54,14 @@ func GetResultList(clients clients.ClientSets, chaosNamespace string, monitoring
return *chaosResultList, nil
}

// getExperimentMetricsFromResult derive all the metrics data from the chaosresult and set into resultDetails struct
func (resultDetails *ChaosResultDetails) getExperimentMetricsFromResult(chaosResult *litmuschaosv1alpha1.ChaosResult, clients clients.ClientSets) (bool, error) {
// GetExperimentMetricsFromResult derive all the metrics data from the chaosresult and set into resultDetails struct
func (r *ResultDetails) GetExperimentMetricsFromResult(chaosResult *litmuschaosv1alpha1.ChaosResult, clients clients.ClientSets) (bool, error) {
verdict := strings.ToLower(string(chaosResult.Status.ExperimentStatus.Verdict))
probeSuccesPercentage, err := getProbeSuccessPercentage(chaosResult)
if err != nil {
return false, err
}

engine, err := clients.LitmusClient.ChaosEngines(chaosResult.Namespace).Get(context.Background(), chaosResult.Spec.EngineName, metav1.GetOptions{})
engine, err := clients.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(chaosResult.Namespace).Get(context.Background(), chaosResult.Spec.EngineName, metav1.GetOptions{})
if err != nil {
// k8serrors.IsNotFound(err) checking k8s resource is found or not,
// It will skip this result if k8s resource is not found.
Expand All @@ -64,9 +76,8 @@ func (resultDetails *ChaosResultDetails) getExperimentMetricsFromResult(chaosRes
if err != nil {
return false, err
}

// setting all the values inside resultdetails struct
resultDetails.setName(chaosResult.Name).
r.resultDetails.setName(chaosResult.Name).
setUID(chaosResult.UID).
setNamespace(chaosResult.Namespace).
setProbeSuccessPercentage(probeSuccesPercentage).
Expand All @@ -89,19 +100,28 @@ func (resultDetails *ChaosResultDetails) getExperimentMetricsFromResult(chaosRes
// experiment's final verdict[passed,failed,stopped] is already exported/overridden
// and 'litmuschaos_experiment_verdict' metric was reset to 0
if engine.Status.EngineStatus == v1alpha1.EngineStatusCompleted {
result, ok := matchVerdict[string(resultDetails.UID)]
if !ok || (ok && result.Verdict == resultDetails.Verdict && result.VerdictReset) {
result, ok := matchVerdict[string(r.resultDetails.UID)]
if !ok || (ok && result.Verdict == r.resultDetails.Verdict && result.VerdictReset) {
return true, nil
}
}

return false, nil
}

func (r *ResultDetails) SetResultDetails() {
r.resultDetails.PassedExperiments = 0
r.resultDetails.AwaitedExperiments = 0
r.resultDetails.FailedExperiments = 0
}

func (r *ResultDetails) GetResultDetails() ChaosResultDetails {
return r.resultDetails
}

// initialiseResult create the new instance of the ChaosResultDetails struct
func initialiseResult() *ChaosResultDetails {
return &ChaosResultDetails{}

}

// setName sets name inside resultDetails struct
Expand Down
187 changes: 187 additions & 0 deletions controller/collect-data_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package controller_test

import (
"context"
"github.com/litmuschaos/chaos-exporter/controller"
"github.com/litmuschaos/chaos-exporter/pkg/clients"
"github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
litmusFakeClientSet "github.com/litmuschaos/chaos-operator/pkg/client/clientset/versioned/fake"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/fake"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"testing"
)

func TestGetResultList(t *testing.T) {
FakeChaosNameSpace := "Fake Namespace"
FakeEngineName := "Fake Engine"

tests := []struct {
name string
execFunc func(client clients.ClientSets, chaosResult *v1alpha1.ChaosResult)
chaosResult *v1alpha1.ChaosResult
monitoring *controller.MonitoringEnabled
isErr bool
}{
{
name: "success:chaos result found",
execFunc: func(client clients.ClientSets, chaosResult *v1alpha1.ChaosResult) {
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosResults(chaosResult.Namespace).Create(context.Background(), chaosResult, metav1.CreateOptions{})
if err != nil {
t.Fatalf("chaosresult not created")
}
},

chaosResult: &v1alpha1.ChaosResult{
ObjectMeta: metav1.ObjectMeta{
Name: FakeEngineName,
Namespace: FakeChaosNameSpace,
},
Spec: v1alpha1.ChaosResultSpec{
ExperimentName: "exp-1",
EngineName: FakeEngineName,
},
},

isErr: false,
monitoring: &controller.MonitoringEnabled{
IsChaosResultsAvailable: true,
},
},
{
name: "success:empty chaosResult",
chaosResult: &v1alpha1.ChaosResult{},
execFunc: func(client clients.ClientSets, chaosResult *v1alpha1.ChaosResult) {},
isErr: false,
monitoring: &controller.MonitoringEnabled{
IsChaosResultsAvailable: true,
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := CreateFakeClient(t)
tt.execFunc(client, tt.chaosResult)
resultDetails := &controller.ResultDetails{}
_, err := resultDetails.GetResultList(client, FakeChaosNameSpace, tt.monitoring)
if tt.isErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}

func TestGetExperimentMetricsFromResult(t *testing.T) {
FakeEngineName := "Fake Engine"
FakeNamespace := "Fake Namespace"
fakeServiceAcc := "Fake Service Account"
fakeAppLabel := "Fake Label"
fakeAppKind := "Fake Kind"

tests := map[string]struct {
chaosengine *v1alpha1.ChaosEngine
chaosresult *v1alpha1.ChaosResult
expectedVerdict bool
isErr bool
verdict bool
execFunc func(client clients.ClientSets, engine *v1alpha1.ChaosEngine, result *v1alpha1.ChaosResult)
}{
"success": {
chaosengine: &v1alpha1.ChaosEngine{
ObjectMeta: metav1.ObjectMeta{
Name: FakeEngineName,
Namespace: FakeNamespace,
},
Spec: v1alpha1.ChaosEngineSpec{
ChaosServiceAccount: fakeServiceAcc,
Appinfo: v1alpha1.ApplicationParams{
Appns: FakeNamespace,
Applabel: fakeAppLabel,
AppKind: fakeAppKind,
},
Experiments: []v1alpha1.ExperimentList{
{
Name: "Fake-Exp-Name",
},
},
},
Status: v1alpha1.ChaosEngineStatus{
EngineStatus: v1alpha1.EngineStatusCompleted,
Experiments: []v1alpha1.ExperimentStatuses{
{
Name: "Fake-Exp-Name",
Status: v1alpha1.ExperimentStatusRunning,
},
},
},
},
chaosresult: &v1alpha1.ChaosResult{
ObjectMeta: metav1.ObjectMeta{
Name: FakeEngineName + "-" + "Fake-Exp-Name",
Namespace: FakeNamespace,
UID: "Fake-UID",
},
Spec: v1alpha1.ChaosResultSpec{
EngineName: FakeEngineName,
ExperimentName: "Fake-Exp-Name",
},
Status: v1alpha1.ChaosResultStatus{
ExperimentStatus: v1alpha1.TestStatus{
Phase: "Completed",
Verdict: "Pass",
},
History: &v1alpha1.HistoryDetails{},
},
},

execFunc: func(client clients.ClientSets, engine *v1alpha1.ChaosEngine, result *v1alpha1.ChaosResult) {
_, err := client.LitmusClient.LitmuschaosV1alpha1().ChaosEngines(engine.Namespace).Create(context.Background(), engine, metav1.CreateOptions{})
if err != nil {
t.Fatalf("engine not created for test, err: %v", err)
}

_, err = client.LitmusClient.LitmuschaosV1alpha1().ChaosResults(result.Namespace).Create(context.Background(), result, metav1.CreateOptions{})
if err != nil {
t.Fatalf("chaosresult not created fortest, err: %v", err)
}
},
isErr: false,
verdict: true,
},
"failure: No Chaos Engine": {
chaosresult: &v1alpha1.ChaosResult{},
isErr: false,
verdict: true,
execFunc: func(client clients.ClientSets, engine *v1alpha1.ChaosEngine, result *v1alpha1.ChaosResult) {
},
},
}

for name, tt := range tests {
t.Run(name, func(t *testing.T) {
client := CreateFakeClient(t)
resultDetails := controller.ResultDetails{}
tt.execFunc(client, tt.chaosengine, tt.chaosresult)
verdict, err := resultDetails.GetExperimentMetricsFromResult(tt.chaosresult, client)
assert.Equal(t, tt.verdict, verdict)
if tt.isErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}

func CreateFakeClient(t *testing.T) clients.ClientSets {
cs := clients.ClientSets{}
cs.KubeClient = fake.NewSimpleClientset([]runtime.Object{}...)
cs.LitmusClient = litmusFakeClientSet.NewSimpleClientset([]runtime.Object{}...)
return cs
}
9 changes: 6 additions & 3 deletions controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ func Exporter(clients clients.ClientSets) {
// Register the fixed (count) chaos metrics
log.Info("Registering Fixed Metrics")

gaugeMetrics := GaugeMetrics{}
r := MetricesCollecter{
ResultCollector: &ResultDetails{},
}
//gaugeMetrics := GaugeMetrics{}
overallChaosResults := litmuschaosv1alpha1.ChaosResultList{}

gaugeMetrics.InitializeGaugeMetrics().
r.GaugeMetrics.InitializeGaugeMetrics().
RegisterFixedMetrics()

monitoringEnabled := MonitoringEnabled{
Expand All @@ -43,7 +46,7 @@ func Exporter(clients clients.ClientSets) {
}

for {
if err := gaugeMetrics.GetLitmusChaosMetrics(clients, &overallChaosResults, &monitoringEnabled); err != nil {
if err := r.GetLitmusChaosMetrics(clients, &overallChaosResults, &monitoringEnabled); err != nil {
log.Errorf("err: %v", err)
}
time.Sleep(1000 * time.Millisecond)
Expand Down
Loading
Loading