Skip to content

Commit

Permalink
[Cherrypick 2.13.1] (#581)
Browse files Browse the repository at this point in the history
* fix(probe): Converting probeStatus as enum (#566)

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

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

* update(sdk): updating operator sdk version (#571)

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

* chore(httpProbe): Remove responseTimeout field, use the global probeTimeout field instead (#574)

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

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

* Chore(cmd-probe): Use experiment envs and volume in probe pod (#572)

* Chore(cmd-probe): Use experiment envs and volume in probe pod

Signed-off-by: uditgaurav <[email protected]>

Signed-off-by: Shubham Chaudhary <[email protected]>
Signed-off-by: uditgaurav <[email protected]>
Co-authored-by: Udit Gaurav <[email protected]>
  • Loading branch information
ispeakc0de and uditgaurav authored Oct 6, 2022
1 parent 8dadb14 commit 94939a9
Show file tree
Hide file tree
Showing 7 changed files with 410 additions and 251 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/aws/aws-sdk-go v1.38.59
github.com/containerd/cgroups v1.0.1
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/litmuschaos/chaos-operator v0.0.0-20220824040614-88dbe3eb960c
github.com/litmuschaos/chaos-operator v0.0.0-20220929101337-868b2827f820
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0
github.com/spf13/cobra v1.1.1
Expand All @@ -28,8 +28,8 @@ require (
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.2.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.1.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.3.1-0.20191028180845-3492b2aff503 // indirect
github.com/Azure/go-autorest/autorest/validation v0.2.1-0.20191028180845-3492b2aff503 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/cilium/ebpf v0.4.0 // indirect
Expand Down
473 changes: 299 additions & 174 deletions go.sum

Large diffs are not rendered by default.

62 changes: 59 additions & 3 deletions pkg/probe/cmdprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ func createProbePod(clients clients.ClientSets, chaosDetails *types.ChaosDetails
if err != nil {
return errors.Errorf("unable to get the serviceAccountName, err: %v", err)
}

expEnv, volume, expVolumeMount := inheritInputs(clients, chaosDetails.ChaosNamespace, chaosDetails.ChaosPodName, source)

cmdProbe := &apiv1.Pod{
ObjectMeta: v1.ObjectMeta{
Name: chaosDetails.ExperimentName + "-probe-" + runID,
Expand All @@ -146,7 +149,7 @@ func createProbePod(clients clients.ClientSets, chaosDetails *types.ChaosDetails
RestartPolicy: apiv1.RestartPolicyNever,
HostNetwork: source.HostNetwork,
ServiceAccountName: svcAccount,
Volumes: source.Volumes,
Volumes: volume,
NodeSelector: source.NodeSelector,
ImagePullSecrets: source.ImagePullSecrets,
Containers: []apiv1.Container{
Expand All @@ -157,11 +160,11 @@ func createProbePod(clients clients.ClientSets, chaosDetails *types.ChaosDetails
Command: getProbeCmd(source.Command),
Args: getProbeArgs(source.Args),
Resources: chaosDetails.Resources,
Env: source.ENVList,
Env: expEnv,
SecurityContext: &apiv1.SecurityContext{
Privileged: &source.Privileged,
},
VolumeMounts: source.VolumesMount,
VolumeMounts: expVolumeMount,
},
},
},
Expand All @@ -171,6 +174,59 @@ func createProbePod(clients clients.ClientSets, chaosDetails *types.ChaosDetails
return err
}

// inheritInputs will inherit the experiment details(ENVs and volumes) to the probe pod based on inheritInputs flag
func inheritInputs(clients clients.ClientSets, chaosNS, chaosPodName string, source v1alpha1.SourceDetails) ([]apiv1.EnvVar, []apiv1.Volume, []apiv1.VolumeMount) {

if !source.InheritInputs {
return source.ENVList, source.Volumes, source.VolumesMount
}
expEnv, expVolumeMount, volume := getEnvAndVolumeMountFromExperiment(clients, chaosNS, chaosPodName)

expEnv = append(expEnv, source.ENVList...)
expVolumeMount = append(expVolumeMount, source.VolumesMount...)
volume = append(volume, source.Volumes...)

return expEnv, volume, expVolumeMount

}

// getEnvAndVolumeMountFromExperiment get the env and volumeMount from the experiment pod and add in the probe pod
func getEnvAndVolumeMountFromExperiment(clients clients.ClientSets, chaosNamespace, podName string) ([]apiv1.EnvVar, []apiv1.VolumeMount, []apiv1.Volume) {

envVarList := make([]apiv1.EnvVar, 0)
volumeMountList := make([]apiv1.VolumeMount, 0)
volumeList := make([]apiv1.Volume, 0)

expPod, err := clients.KubeClient.CoreV1().Pods(chaosNamespace).Get(context.Background(), podName, v1.GetOptions{})
if err != nil {
log.Errorf("Unable to get the experiment pod, err: %v", err)
return nil, nil, nil
}

expContainerName := expPod.Labels["job-name"]

for _, container := range expPod.Spec.Containers {
if container.Name == expContainerName {
envVarList = append(envVarList, container.Env...)
}
for _, volumeMount := range container.VolumeMounts {
// NOTE: one can add custom volume mount from probe spec
if volumeMount.Name == "cloud-secret" {
volumeMountList = append(volumeMountList, volumeMount)
}
}
}

for _, vol := range expPod.Spec.Volumes {
// NOTE: one can add custom volume from probe spec
if vol.Name == "cloud-secret" {
volumeList = append(volumeList, vol)
}
}

return envVarList, volumeMountList, volumeList
}

// getProbeLabels adding provided labels to probePod
func getProbeLabels(sourceLabels map[string]string, chaosDetails *types.ChaosDetails, runID string) map[string]string {

Expand Down
12 changes: 5 additions & 7 deletions pkg/probe/httpprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func triggerHTTPProbe(probe v1alpha1.ProbeAttributes, resultDetails *types.Resul
method := getHTTPMethodType(probe.HTTPProbeInputs.Method)

// initialize simple http client with default attributes
timeout := time.Duration(probe.HTTPProbeInputs.ResponseTimeout) * time.Millisecond
timeout := time.Duration(probe.RunProperties.ProbeTimeout) * time.Millisecond
client := &http.Client{Timeout: timeout}
// impose properties to http client with cert check disabled
if probe.HTTPProbeInputs.InsecureSkipVerify {
Expand All @@ -75,7 +75,7 @@ func triggerHTTPProbe(probe v1alpha1.ProbeAttributes, resultDetails *types.Resul
"URL": probe.HTTPProbeInputs.URL,
"Criteria": probe.HTTPProbeInputs.Method.Get.Criteria,
"ResponseCode": probe.HTTPProbeInputs.Method.Get.ResponseCode,
"ResponseTimeout": probe.HTTPProbeInputs.ResponseTimeout,
"ResponseTimeout": probe.RunProperties.ProbeTimeout,
})
if err := httpGet(probe, client, resultDetails); err != nil {
return err
Expand All @@ -87,7 +87,7 @@ func triggerHTTPProbe(probe v1alpha1.ProbeAttributes, resultDetails *types.Resul
"Body": probe.HTTPProbeInputs.Method.Post.Body,
"BodyPath": probe.HTTPProbeInputs.Method.Post.BodyPath,
"ContentType": probe.HTTPProbeInputs.Method.Post.ContentType,
"ResponseTimeout": probe.HTTPProbeInputs.ResponseTimeout,
"ResponseTimeout": probe.RunProperties.ProbeTimeout,
})
if err := httpPost(probe, client, resultDetails); err != nil {
return err
Expand All @@ -111,9 +111,8 @@ func httpGet(probe v1alpha1.ProbeAttributes, client *http.Client, resultDetails
// it contains a timeout per iteration of retry. if the timeout expires without success then it will go to next try
// for a timeout, it will run the command, if it fails wait for the interval and again execute the command until timeout expires
return retry.Times(uint(probe.RunProperties.Retry)).
Timeout(int64(probe.RunProperties.ProbeTimeout)).
Wait(time.Duration(probe.RunProperties.Interval) * time.Second).
TryWithTimeout(func(attempt uint) error {
Try(func(attempt uint) error {
// getting the response from the given url
resp, err := client.Get(probe.HTTPProbeInputs.URL)
if err != nil {
Expand Down Expand Up @@ -146,9 +145,8 @@ func httpPost(probe v1alpha1.ProbeAttributes, client *http.Client, resultDetails
// it contains a timeout per iteration of retry. if the timeout expires without success then it will go to next try
// for a timeout, it will run the command, if it fails wait for the interval and again execute the command until timeout expires
return retry.Times(uint(probe.RunProperties.Retry)).
Timeout(int64(probe.RunProperties.ProbeTimeout)).
Wait(time.Duration(probe.RunProperties.Interval) * time.Second).
TryWithTimeout(func(attempt uint) error {
Try(func(attempt uint) error {
resp, err := client.Post(probe.HTTPProbeInputs.URL, probe.HTTPProbeInputs.Method.Post.ContentType, strings.NewReader(body))
if err != nil {
return err
Expand Down
88 changes: 33 additions & 55 deletions pkg/probe/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,36 +68,27 @@ func RunProbes(chaosDetails *types.ChaosDetails, clients clients.ClientSets, res

//setProbeVerdict mark the verdict of the probe in the chaosresult as passed
// on the basis of phase(pre/post chaos)
func setProbeVerdict(resultDetails *types.ResultDetails, probe v1alpha1.ProbeAttributes, verdict, phase string) {

func setProbeVerdict(resultDetails *types.ResultDetails, probe v1alpha1.ProbeAttributes, verdict v1alpha1.ProbeVerdict, description string) {
for index, probes := range resultDetails.ProbeDetails {
if probes.Name == probe.Name && probes.Type == probe.Type {
switch strings.ToLower(probe.Mode) {
case "sot", "edge", "eot":
if verdict == "Passed" {
resultDetails.ProbeDetails[index].Status[phase] = verdict + emoji.Sprint(" :thumbsup:")
} else {
resultDetails.ProbeDetails[index].Status[phase] = "Better Luck Next Time" + emoji.Sprint(" :thumbsdown:")
}
case "continuous", "onchaos":
if verdict == "Passed" {
resultDetails.ProbeDetails[index].Status[probe.Mode] = verdict + emoji.Sprint(" :thumbsup:")
} else {
resultDetails.ProbeDetails[index].Status[probe.Mode] = "Better Luck Next Time" + emoji.Sprint(" :thumbsdown:")
}
if probes.Mode == "Edge" && probes.Status.Verdict == v1alpha1.ProbeVerdictFailed {
return
}
resultDetails.ProbeDetails[index].Status = v1alpha1.ProbeStatus{
Verdict: verdict,
Description: description,
}
resultDetails.ProbeDetails[index].Phase = verdict
break
}
}
}

//SetProbeVerdictAfterFailure mark the verdict of all the failed/unrun probes as failed
func SetProbeVerdictAfterFailure(resultDetails *types.ResultDetails) {
for index := range resultDetails.ProbeDetails {
for _, phase := range []string{"PreChaos", "PostChaos", "Continuous", "OnChaos"} {
if resultDetails.ProbeDetails[index].Status[phase] == "Awaited" {
resultDetails.ProbeDetails[index].Status[phase] = "N/A" + emoji.Sprint(" :prohibited:")
}
func SetProbeVerdictAfterFailure(result *v1alpha1.ChaosResult) {
for index := range result.Status.ProbeStatuses {
if result.Status.ProbeStatuses[index].Status.Verdict == v1alpha1.ProbeVerdictAwaited {
result.Status.ProbeStatuses[index].Status.Verdict = v1alpha1.ProbeVerdictNA
result.Status.ProbeStatuses[index].Status.Description = "either probe is not executed or not evaluated"
}
}
}
Expand Down Expand Up @@ -133,7 +124,7 @@ func getProbesFromEngine(chaosDetails *types.ChaosDetails, clients clients.Clien
// it fetch the probe details from the chaosengine and set into the chaosresult
func InitializeProbesInChaosResultDetails(chaosDetails *types.ChaosDetails, clients clients.ClientSets, chaosresult *types.ResultDetails) error {

probeDetails := []types.ProbeDetails{}
var probeDetails []types.ProbeDetails
// get the probes from the chaosengine
probes, err := getProbesFromEngine(chaosDetails, clients)
if err != nil {
Expand All @@ -145,9 +136,12 @@ func InitializeProbesInChaosResultDetails(chaosDetails *types.ChaosDetails, clie
tempProbe := types.ProbeDetails{}
tempProbe.Name = probe.Name
tempProbe.Type = probe.Type
tempProbe.Mode = probe.Mode
tempProbe.Phase = "N/A"
tempProbe.RunCount = 0
setProbeInitialStatus(&tempProbe, probe.Mode)
tempProbe.Status = v1alpha1.ProbeStatus{
Verdict: "Awaited",
}
probeDetails = append(probeDetails, tempProbe)
}

Expand All @@ -167,33 +161,6 @@ func getAndIncrementRunCount(resultDetails *types.ResultDetails, probeName strin
return 0
}

//setProbeInitialStatus sets the initial status inside chaosresult
func setProbeInitialStatus(probeDetails *types.ProbeDetails, mode string) {
switch strings.ToLower(mode) {
case "sot":
probeDetails.Status = map[string]string{
"PreChaos": "Awaited",
}
case "eot":
probeDetails.Status = map[string]string{
"PostChaos": "Awaited",
}
case "edge":
probeDetails.Status = map[string]string{
"PreChaos": "Awaited",
"PostChaos": "Awaited",
}
case "continuous":
probeDetails.Status = map[string]string{
"Continuous": "Awaited",
}
case "onchaos":
probeDetails.Status = map[string]string{
"OnChaos": "Awaited",
}
}
}

//getRunIDFromProbe return the run_id for the dedicated probe
// which will used in the continuous cmd probe, run_id is used as suffix in the external pod name
func getRunIDFromProbe(resultDetails *types.ResultDetails, probeName, probeType string) string {
Expand All @@ -220,13 +187,14 @@ func setRunIDForProbe(resultDetails *types.ResultDetails, probeName, probeType,

// markedVerdictInEnd add the probe status in the chaosresult
func markedVerdictInEnd(err error, resultDetails *types.ResultDetails, probe v1alpha1.ProbeAttributes, phase string) error {
probeVerdict := "Passed"
probeVerdict := v1alpha1.ProbeVerdictPassed
var description string
if err != nil {
probeVerdict = "Failed"
probeVerdict = v1alpha1.ProbeVerdictFailed
}

switch probeVerdict {
case "Passed":
case v1alpha1.ProbeVerdictPassed:
log.InfoWithValues("[Probe]: "+probe.Name+" probe has been Passed "+emoji.Sprint(":smile:"), logrus.Fields{
"ProbeName": probe.Name,
"ProbeType": probe.Type,
Expand Down Expand Up @@ -254,15 +222,25 @@ func markedVerdictInEnd(err error, resultDetails *types.ResultDetails, probe v1a
"ProbeInstance": phase,
"ProbeStatus": probeVerdict,
})
description = getDescription(strings.ToLower(probe.Mode), phase)
}

setProbeVerdict(resultDetails, probe, probeVerdict, phase)
setProbeVerdict(resultDetails, probe, probeVerdict, description)
if !probe.RunProperties.StopOnFailure {
return nil
}
return err
}

func getDescription(mode, phase string) string {
switch mode {
case "edge":
return fmt.Sprintf("'%v' Probe didn't met the passing criteria", phase)
default:
return "Probe didn't met the passing criteria"
}
}

//CheckForErrorInContinuousProbe check for the error in the continuous probes
func checkForErrorInContinuousProbe(resultDetails *types.ResultDetails, probeName string) error {

Expand Down
15 changes: 8 additions & 7 deletions pkg/result/chaosresult.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func InitializeChaosResult(chaosDetails *types.ChaosDetails, clients clients.Cli
Verdict: resultDetails.Verdict,
ProbeSuccessPercentage: "Awaited",
},
ProbeStatus: probeStatus,
ProbeStatuses: probeStatus,
History: &v1alpha1.HistoryDetails{
PassedRuns: 0,
FailedRuns: 0,
Expand Down Expand Up @@ -128,14 +128,15 @@ func InitializeChaosResult(chaosDetails *types.ChaosDetails, clients clients.Cli
}

//GetProbeStatus fetch status of all probes
func GetProbeStatus(resultDetails *types.ResultDetails) (bool, []v1alpha1.ProbeStatus) {
func GetProbeStatus(resultDetails *types.ResultDetails) (bool, []v1alpha1.ProbeStatuses) {
isAllProbePassed := true

probeStatus := []v1alpha1.ProbeStatus{}
probeStatus := []v1alpha1.ProbeStatuses{}
for _, probe := range resultDetails.ProbeDetails {
probes := v1alpha1.ProbeStatus{}
probes := v1alpha1.ProbeStatuses{}
probes.Name = probe.Name
probes.Type = probe.Type
probes.Mode = probe.Mode
probes.Status = probe.Status
probeStatus = append(probeStatus, probes)
if probe.Phase == "Failed" {
Expand All @@ -161,7 +162,7 @@ func PatchChaosResult(result *v1alpha1.ChaosResult, clients clients.ClientSets,
result.ObjectMeta.Labels = chaosResultLabel
result.ObjectMeta.Annotations = annotations
result.Status.History.Targets = chaosDetails.Targets
isAllProbePassed, result.Status.ProbeStatus = GetProbeStatus(resultDetails)
isAllProbePassed, result.Status.ProbeStatuses = GetProbeStatus(resultDetails)
result.Status.ExperimentStatus.Verdict = resultDetails.Verdict

switch strings.ToLower(string(resultDetails.Phase)) {
Expand All @@ -176,15 +177,15 @@ func PatchChaosResult(result *v1alpha1.ChaosResult, clients clients.ClientSets,
result.Status.History.PassedRuns++
case "fail":
result.Status.History.FailedRuns++
probe.SetProbeVerdictAfterFailure(resultDetails)
probe.SetProbeVerdictAfterFailure(result)
if len(resultDetails.ProbeDetails) != 0 {
result.Status.ExperimentStatus.ProbeSuccessPercentage = strconv.Itoa((resultDetails.PassedProbeCount * 100) / len(resultDetails.ProbeDetails))
} else {
result.Status.ExperimentStatus.ProbeSuccessPercentage = "0"
}
case "stopped":
result.Status.History.StoppedRuns++
probe.SetProbeVerdictAfterFailure(resultDetails)
probe.SetProbeVerdictAfterFailure(result)
if len(resultDetails.ProbeDetails) != 0 {
result.Status.ExperimentStatus.ProbeSuccessPercentage = strconv.Itoa((resultDetails.PassedProbeCount * 100) / len(resultDetails.ProbeDetails))
} else {
Expand Down
5 changes: 3 additions & 2 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ type RegisterDetails struct {
// ProbeDetails is for collecting all the probe details
type ProbeDetails struct {
Name string
Phase string
Type string
Status map[string]string
Mode string
Phase string
Status v1alpha1.ProbeStatus
IsProbeFailedWithError error
RunID string
RunCount int
Expand Down

0 comments on commit 94939a9

Please sign in to comment.