Skip to content

Commit

Permalink
chore(spring-boot): spliting spring-boot-chaos experiment to separate…
Browse files Browse the repository at this point in the history
… experiments (#594)

Signed-off-by: Shubham Chaudhary <[email protected]>

Signed-off-by: Shubham Chaudhary <[email protected]>
Signed-off-by: Rocio Roman <[email protected]>
  • Loading branch information
ispeakc0de authored and rociomroman committed Nov 17, 2022
1 parent 481344e commit e461c82
Show file tree
Hide file tree
Showing 25 changed files with 1,602 additions and 161 deletions.
18 changes: 15 additions & 3 deletions bin/experiment/experiment.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ import (
ebsLossByTag "github.com/litmuschaos/litmus-go/experiments/kube-aws/ebs-loss-by-tag/experiment"
ec2TerminateByID "github.com/litmuschaos/litmus-go/experiments/kube-aws/ec2-terminate-by-id/experiment"
ec2TerminateByTag "github.com/litmuschaos/litmus-go/experiments/kube-aws/ec2-terminate-by-tag/experiment"
springBootChaos "github.com/litmuschaos/litmus-go/experiments/spring-boot/spring-boot-chaos/experiment"
springBootAppKill "github.com/litmuschaos/litmus-go/experiments/spring-boot/spring-boot-app-kill/experiment"
springBootCpuStress "github.com/litmuschaos/litmus-go/experiments/spring-boot/spring-boot-cpu-stress/experiment"
springBootExceptions "github.com/litmuschaos/litmus-go/experiments/spring-boot/spring-boot-exceptions/experiment"
springBootLatency "github.com/litmuschaos/litmus-go/experiments/spring-boot/spring-boot-latency/experiment"
springBootMemoryStress "github.com/litmuschaos/litmus-go/experiments/spring-boot/spring-boot-memory-stress/experiment"
vmpoweroff "github.com/litmuschaos/litmus-go/experiments/vmware/vm-poweroff/experiment"

"github.com/litmuschaos/litmus-go/pkg/clients"
Expand Down Expand Up @@ -182,8 +186,16 @@ func main() {
gcpVMInstanceStopByLabel.GCPVMInstanceStopByLabel(clients)
case "gcp-vm-disk-loss-by-label":
gcpVMDiskLossByLabel.GCPVMDiskLossByLabel(clients)
case "spring-boot-chaos":
springBootChaos.Experiment(clients)
case "spring-boot-cpu-stress":
springBootCpuStress.Experiment(clients)
case "spring-boot-memory-stress":
springBootMemoryStress.Experiment(clients)
case "spring-boot-latency":
springBootLatency.Experiment(clients)
case "spring-boot-exceptions":
springBootExceptions.Experiment(clients)
case "spring-boot-app-kill":
springBootAppKill.Experiment(clients)
default:
log.Errorf("Unsupported -name %v, please provide the correct value of -name args", *experimentName)
return
Expand Down
15 changes: 2 additions & 13 deletions chaoslib/litmus/spring-boot-chaos/lib/spring-boot-chaos.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,6 @@ func PrepareChaos(experimentsDetails *experimentTypes.ExperimentDetails, clients
"Controller": experimentsDetails.ChaosMonkeyWatchers.Controller,
"RestController": experimentsDetails.ChaosMonkeyWatchers.RestController,
})
log.InfoWithValues("[Info]: Chaos monkeys assaults will be injected to the target pods as follows", logrus.Fields{
"CPU Assault": experimentsDetails.ChaosMonkeyAssault.CPUActive,
"Memory Assault": experimentsDetails.ChaosMonkeyAssault.MemoryActive,
"Kill App Assault": experimentsDetails.ChaosMonkeyAssault.KillApplicationActive,
"Latency Assault": experimentsDetails.ChaosMonkeyAssault.LatencyActive,
"Exception Assault": experimentsDetails.ChaosMonkeyAssault.ExceptionsActive,
})

switch strings.ToLower(experimentsDetails.Sequence) {
case "serial":
Expand Down Expand Up @@ -156,12 +149,8 @@ func setChaosMonkeyWatchers(chaosMonkeyPort string, chaosMonkeyPath string, watc
return nil
}

func startAssault(chaosMonkeyPort string, chaosMonkeyPath string, assault experimentTypes.ChaosMonkeyAssault, pod corev1.Pod) error {
jsonValue, err := json.Marshal(assault)
if err != nil {
return err
}
if err := setChaosMonkeyAssault(chaosMonkeyPort, chaosMonkeyPath, jsonValue, pod); err != nil {
func startAssault(chaosMonkeyPort string, chaosMonkeyPath string, assault []byte, pod corev1.Pod) error {
if err := setChaosMonkeyAssault(chaosMonkeyPort, chaosMonkeyPath, assault, pod); err != nil {
return err
}
log.Infof("[Chaos]: Activating Chaos Monkey assault on pod: %v", pod.Name)
Expand Down
15 changes: 0 additions & 15 deletions experiments/spring-boot/README.md

This file was deleted.

15 changes: 15 additions & 0 deletions experiments/spring-boot/spring-boot-app-kill/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Experiment Metadata

<table>
<tr>
<th> Name </th>
<th> Description </th>
<th> Documentation Link </th>
</tr>
<tr>
<td> Spring Boot App Kill </td>
<td> This experiment allows injecting Chaos Monkey app-kill assaults on Spring Boot applications, which have the [Chaos Monkey for Spring Boot](https://codecentric.github.io/chaos-monkey-spring-boot/) in their classpath. It can target random pods with a Spring Boot application and allows configuring the assaults to inject app-kill. It tests the resiliency of the system when some applications are having unexpected faulty behavior.</td>
<td> TODO </td>
</tr>
</table>

Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package experiment

import (
"os"

"github.com/litmuschaos/chaos-operator/api/litmuschaos/v1alpha1"
litmusLIB "github.com/litmuschaos/litmus-go/chaoslib/litmus/spring-boot-chaos/lib"
"github.com/litmuschaos/litmus-go/pkg/clients"
"github.com/litmuschaos/litmus-go/pkg/events"
"github.com/litmuschaos/litmus-go/pkg/log"
"github.com/litmuschaos/litmus-go/pkg/probe"
"github.com/litmuschaos/litmus-go/pkg/result"
experimentEnv "github.com/litmuschaos/litmus-go/pkg/spring-boot/spring-boot-chaos/environment"
experimentTypes "github.com/litmuschaos/litmus-go/pkg/spring-boot/spring-boot-chaos/types"
"github.com/litmuschaos/litmus-go/pkg/status"
"github.com/litmuschaos/litmus-go/pkg/types"
"github.com/litmuschaos/litmus-go/pkg/utils/common"
"github.com/sirupsen/logrus"
)

// Experiment contains steps to inject chaos
func Experiment(clients clients.ClientSets) {

experimentsDetails := experimentTypes.ExperimentDetails{}
resultDetails := types.ResultDetails{}
eventsDetails := types.EventDetails{}
chaosDetails := types.ChaosDetails{}

//Fetching all the ENV passed from the runner pod
log.Infof("[PreReq]: Getting the ENV for the %v experiment", os.Getenv("EXPERIMENT_NAME"))
experimentEnv.GetENV(&experimentsDetails, "spring-boot-app-kill")

// Initialize the chaos attributes
types.InitialiseChaosVariables(&chaosDetails)

// Initialize Chaos Result Parameters
types.SetResultAttributes(&resultDetails, chaosDetails)

if experimentsDetails.EngineName != "" {
// Initialize the probe details. Bail out upon error, as we haven't entered exp business logic yet
if err := probe.InitializeProbesInChaosResultDetails(&chaosDetails, clients, &resultDetails); err != nil {
log.Errorf("Unable to initialize the probes, err: %v", err)
return
}
}

//Updating the chaos result in the beginning of experiment
log.Infof("[PreReq]: Updating the chaos result of %v experiment (SOT)", experimentsDetails.ExperimentName)
if err := result.ChaosResult(&chaosDetails, clients, &resultDetails, "SOT"); err != nil {
log.Errorf("Unable to Create the Chaos Result, err: %v", err)
failStep := "[pre-chaos]: Failed to update the chaos result of spring-boot-chaos experiment (SOT), err: " + err.Error()
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}

// Set the chaos result uid
_ = result.SetResultUID(&resultDetails, clients, &chaosDetails)

// generating the event in chaosResult to mark the verdict as awaited
msg := "experiment: " + experimentsDetails.ExperimentName + ", Result: Awaited"
types.SetResultEventAttributes(&eventsDetails, types.AwaitedVerdict, msg, "Normal", &resultDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosResult")

//DISPLAY THE APP INFORMATION
log.InfoWithValues("[Info]: The application information is as follows", logrus.Fields{
"Namespace": experimentsDetails.AppNS,
"Label": experimentsDetails.AppLabel,
"Chaos Duration": experimentsDetails.ChaosDuration,
})

// Calling AbortWatcher go routine, it will continuously watch for the abort signal and generate the required events and result
go common.AbortWatcherWithoutExit(experimentsDetails.ExperimentName, clients, &resultDetails, &chaosDetails, &eventsDetails)

// Select targeted pods
log.Infof("[PreCheck]: Geting targeted pods list")
if err := litmusLIB.SetTargetPodList(&experimentsDetails, clients, &chaosDetails); err != nil {
log.Errorf("Failed to get target pod list, err: %v", err)
failStep := "[pre-chaos]: Failed to get pod list, err: " + err.Error()
types.SetEngineEventAttributes(&eventsDetails, types.PreChaosCheck, "Pods: Not Found", "Warning", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}
podNames := make([]string, 0, 1)
for _, pod := range experimentsDetails.TargetPodList.Items {
podNames = append(podNames, pod.Name)
}
log.Infof("[PreCheck]: Target pods list for chaos, %v", podNames)

// Check if the targeted pods have the chaos monkey endpoint
log.Infof("[PreCheck]: Checking for ChaosMonkey endpoint in target pods")
if _, err := litmusLIB.CheckChaosMonkey(experimentsDetails.ChaosMonkeyPort, experimentsDetails.ChaosMonkeyPath, experimentsDetails.TargetPodList); err != nil {
log.Errorf("Some target pods don't have the chaos monkey endpoint, err: %v", err)
failStep := "[pre-chaos]: Some target pods don't have the chaos monkey endpoint, err: " + err.Error()
types.SetEngineEventAttributes(&eventsDetails, types.PreChaosCheck, "ChaosMonkey: Not Found", "Warning", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}

//PRE-CHAOS APPLICATION STATUS CHECK
if chaosDetails.DefaultHealthCheck {
log.Info("[Status]: Verify that the AUT (Application Under Test) is running (pre-chaos)")
if err := status.AUTStatusCheck(experimentsDetails.AppNS, experimentsDetails.AppLabel, experimentsDetails.TargetContainer, experimentsDetails.Timeout, experimentsDetails.Delay, clients, &chaosDetails); err != nil {
log.Errorf("Application status check failed, err: %v", err)
failStep := "[pre-chaos]: Failed to verify that the AUT (Application Under Test) is in running state, err: " + err.Error()
types.SetEngineEventAttributes(&eventsDetails, types.PreChaosCheck, "AUT: Not Running", "Warning", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}
}

if experimentsDetails.EngineName != "" {
// marking AUT as running, as we already checked the status of application under test
msg := "AUT: Running"

// run the probes in the pre-chaos check
if len(resultDetails.ProbeDetails) != 0 {
if err := probe.RunProbes(&chaosDetails, clients, &resultDetails, "PreChaos", &eventsDetails); err != nil {
log.Errorf("Probe Failed, err: %v", err)
failStep := "[pre-chaos]: Failed while running probes, err: " + err.Error()
msg := "AUT: Running, Probes: Unsuccessful"
types.SetEngineEventAttributes(&eventsDetails, types.PreChaosCheck, msg, "Warning", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}
msg = "AUT: Running, Probes: Successful"
}
// generating the events for the pre-chaos check
types.SetEngineEventAttributes(&eventsDetails, types.PreChaosCheck, msg, "Normal", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
}

// Including the litmus lib
switch experimentsDetails.ChaosLib {
case "litmus":
if err := litmusLIB.PrepareChaos(&experimentsDetails, clients, &resultDetails, &eventsDetails, &chaosDetails); err != nil {
log.Errorf("Chaos injection failed, err: %v", err)
failStep := "[chaos]: Failed inside the chaoslib, err: " + err.Error()
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}
default:
log.Error("[Invalid]: Please Provide the correct LIB")
failStep := "[chaos]: no match found for specified lib"
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}

log.Infof("[Confirmation]: %v chaos has been injected successfully", experimentsDetails.ExperimentName)
resultDetails.Verdict = v1alpha1.ResultVerdictPassed

// POST-CHAOS APPLICATION STATUS CHECK
if chaosDetails.DefaultHealthCheck {
log.Info("[Status]: Verify that the AUT (Application Under Test) is running (post-chaos)")
if err := status.AUTStatusCheck(experimentsDetails.AppNS, experimentsDetails.AppLabel, experimentsDetails.TargetContainer, experimentsDetails.Timeout, experimentsDetails.Delay, clients, &chaosDetails); err != nil {
log.Errorf("Application status check failed, err: %v", err)
failStep := "[post-chaos]: Failed to verify that the AUT (Application Under Test) is running, err: " + err.Error()
types.SetEngineEventAttributes(&eventsDetails, types.PostChaosCheck, "AUT: Not Running", "Warning", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}
}

if experimentsDetails.EngineName != "" {
// marking AUT as running, as we already checked the status of application under test
msg := "AUT: Running"

// run the probes in the post-chaos check
if len(resultDetails.ProbeDetails) != 0 {
if err := probe.RunProbes(&chaosDetails, clients, &resultDetails, "PostChaos", &eventsDetails); err != nil {
log.Errorf("Probes Failed, err: %v", err)
failStep := "[post-chaos]: Failed while running probes, err: " + err.Error()
msg := "AUT: Running, Probes: Unsuccessful"
types.SetEngineEventAttributes(&eventsDetails, types.PostChaosCheck, msg, "Warning", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
result.RecordAfterFailure(&chaosDetails, &resultDetails, failStep, clients, &eventsDetails)
return
}
msg = "AUT: Running, Probes: Successful"
}

// generating post chaos event
types.SetEngineEventAttributes(&eventsDetails, types.PostChaosCheck, msg, "Normal", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
}

//Updating the chaosResult in the end of experiment
log.Infof("[The End]: Updating the chaos result of %v experiment (EOT)", experimentsDetails.ExperimentName)
if err := result.ChaosResult(&chaosDetails, clients, &resultDetails, "EOT"); err != nil {
log.Errorf("Unable to Update the Chaos Result, err: %v", err)
return
}

// generating the event in chaosResult to mark the verdict as pass/fail
msg = "experiment: " + experimentsDetails.ExperimentName + ", Result: " + string(resultDetails.Verdict)
reason := types.PassVerdict
eventType := "Normal"
if resultDetails.Verdict != "Pass" {
reason = types.FailVerdict
eventType = "Warning"
}
types.SetResultEventAttributes(&eventsDetails, reason, msg, eventType, &resultDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosResult")

if experimentsDetails.EngineName != "" {
msg := experimentsDetails.ExperimentName + " experiment has been " + string(resultDetails.Verdict) + "ed"
types.SetEngineEventAttributes(&eventsDetails, types.Summary, msg, "Normal", &chaosDetails)
_ = events.GenerateEvents(&eventsDetails, clients, &chaosDetails, "ChaosEngine")
}
}
36 changes: 36 additions & 0 deletions experiments/spring-boot/spring-boot-app-kill/rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: spring-boot-app-kill-sa
namespace: podtato
labels:
name: spring-boot-app-kill-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: spring-boot-app-kill-sa
labels:
name: spring-boot-app-kill-sa
rules:
- apiGroups: [ "","litmuschaos.io","batch","apps" ]
resources: [ "pods","deployments","pods/log","events","jobs","pods/exec","statefulsets","configmaps","chaosengines","chaosexperiments","chaosresults" ]
verbs: [ "create","list","get","patch","delete","update" ]
- apiGroups: [ "" ]
resources: [ "nodes" ]
verbs: [ "get","list" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: spring-boot-app-kill-sa
labels:
name: spring-boot-app-kill-sa
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: spring-boot-app-kill-sa
subjects:
- kind: ServiceAccount
name: spring-boot-app-kill-sa
namespace: podtato
Loading

0 comments on commit e461c82

Please sign in to comment.