1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package statuscheck
17
18 import (
19 "time"
20
21 corev1 "k8s.io/api/core/v1"
22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23
24 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
25 )
26
27 type conditionMap map[v1alpha1.StatusCheckConditionType]v1alpha1.StatusCheckCondition
28
29 func toConditionMap(conditions []v1alpha1.StatusCheckCondition) conditionMap {
30 result := make(map[v1alpha1.StatusCheckConditionType]v1alpha1.StatusCheckCondition)
31 for _, condition := range conditions {
32 condition := condition
33 result[condition.Type] = condition
34 }
35 return result
36 }
37
38 func toConditionList(conditions conditionMap) []v1alpha1.StatusCheckCondition {
39 result := make([]v1alpha1.StatusCheckCondition, 0, len(conditions))
40 for _, condition := range conditions {
41 condition := condition
42 result = append(result, condition)
43 }
44 return result
45 }
46
47 func (in conditionMap) setCondition(
48 t v1alpha1.StatusCheckConditionType,
49 status corev1.ConditionStatus,
50 reason v1alpha1.StatusCheckReason) {
51 condition, ok := in[t]
52 now := &metav1.Time{Time: time.Now()}
53 if !ok {
54 in[t] = v1alpha1.StatusCheckCondition{
55 Type: t,
56 Status: status,
57 Reason: reason,
58 LastProbeTime: now,
59 LastTransitionTime: now,
60 }
61 } else {
62 condition.LastProbeTime = now
63 condition.Reason = reason
64 if status != condition.Status {
65 condition.Status = status
66 condition.LastTransitionTime = now
67 }
68 in[t] = condition
69 }
70 }
71
72 func (in conditionMap) isCompleted() bool {
73 cond, ok := in[v1alpha1.StatusCheckConditionCompleted]
74 return ok && cond.Status == corev1.ConditionTrue
75 }
76
77 func (in conditionMap) isDurationExceed() bool {
78 cond, ok := in[v1alpha1.StatusCheckConditionDurationExceed]
79 return ok && cond.Status == corev1.ConditionTrue
80 }
81
82 func (in conditionMap) isFailureThresholdExceed() bool {
83 cond, ok := in[v1alpha1.StatusCheckConditionFailureThresholdExceed]
84 return ok && cond.Status == corev1.ConditionTrue
85 }
86
87 func (in conditionMap) isSuccessThresholdExceed() bool {
88 cond, ok := in[v1alpha1.StatusCheckConditionSuccessThresholdExceed]
89 return ok && cond.Status == corev1.ConditionTrue
90 }
91
92 func setDurationExceedCondition(statusCheck v1alpha1.StatusCheck, conditions conditionMap) error {
93 now := time.Now()
94 ok, _, err := statusCheck.DurationExceed(now)
95 if err != nil {
96 return err
97 }
98 if !ok {
99 conditions.setCondition(v1alpha1.StatusCheckConditionDurationExceed, corev1.ConditionFalse, "")
100 } else {
101 conditions.setCondition(v1alpha1.StatusCheckConditionDurationExceed, corev1.ConditionTrue, "")
102 }
103 return nil
104 }
105
106
107
108
109 func setFailureThresholdExceedCondition(statusCheck v1alpha1.StatusCheck, conditions conditionMap) {
110 if isThresholdExceed(statusCheck.Status.Records, v1alpha1.StatusCheckOutcomeFailure, statusCheck.Spec.FailureThreshold) {
111 conditions.setCondition(v1alpha1.StatusCheckConditionFailureThresholdExceed, corev1.ConditionTrue, "")
112 } else {
113 conditions.setCondition(v1alpha1.StatusCheckConditionFailureThresholdExceed, corev1.ConditionFalse, "")
114 }
115 }
116
117
118
119
120 func setSuccessThresholdExceedCondition(statusCheck v1alpha1.StatusCheck, conditions conditionMap) {
121 if isThresholdExceed(statusCheck.Status.Records, v1alpha1.StatusCheckOutcomeSuccess, statusCheck.Spec.SuccessThreshold) {
122 conditions.setCondition(v1alpha1.StatusCheckConditionSuccessThresholdExceed, corev1.ConditionTrue, "")
123 } else {
124 conditions.setCondition(v1alpha1.StatusCheckConditionSuccessThresholdExceed, corev1.ConditionFalse, "")
125 }
126 }
127
128 func setCompletedCondition(statusCheck v1alpha1.StatusCheck, conditions conditionMap) {
129 if conditions.isDurationExceed() {
130 conditions.setCondition(v1alpha1.StatusCheckConditionCompleted, corev1.ConditionTrue, v1alpha1.StatusCheckDurationExceed)
131 return
132 }
133 if conditions.isFailureThresholdExceed() {
134 conditions.setCondition(v1alpha1.StatusCheckConditionCompleted, corev1.ConditionTrue, v1alpha1.StatusCheckFailureThresholdExceed)
135 return
136 }
137 if statusCheck.Spec.Mode == v1alpha1.StatusCheckSynchronous {
138 if conditions.isSuccessThresholdExceed() {
139 conditions.setCondition(v1alpha1.StatusCheckConditionCompleted, corev1.ConditionTrue, v1alpha1.StatusCheckSuccessThresholdExceed)
140 return
141 }
142 }
143 conditions.setCondition(v1alpha1.StatusCheckConditionCompleted, corev1.ConditionFalse, "")
144 }
145
146 func isThresholdExceed(records []v1alpha1.StatusCheckRecord, outcome v1alpha1.StatusCheckOutcome, threshold int) bool {
147 count := 0
148 for i := len(records) - 1; i >= 0; i-- {
149 if records[i].Outcome != outcome {
150 return false
151 }
152 count++
153 if count >= threshold {
154 return true
155 }
156 }
157 return false
158 }
159