1
16
17 package conditions
18
19 import (
20 "math/rand"
21 "testing"
22 "time"
23
24 cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
25 cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
26 "github.com/stretchr/testify/require"
27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28 clocktesting "k8s.io/utils/clock/testing"
29 )
30
31
32
33
34
35
36 func randomTime() time.Time {
37 min := time.Date(1970, 1, 0, 0, 0, 0, 0, time.UTC).Unix()
38 max := time.Date(2070, 1, 0, 0, 0, 0, 0, time.UTC).Unix()
39 delta := max - min
40
41 sec := rand.Int63n(delta) + min
42 return time.Unix(sec, 0)
43 }
44
45 func TestSetCertificateRequestStatusCondition(t *testing.T) {
46 type testCase struct {
47 name string
48
49 existingConditions []cmapi.CertificateRequestCondition
50 patchConditions []cmapi.CertificateRequestCondition
51 conditionType cmapi.CertificateRequestConditionType
52 status cmmeta.ConditionStatus
53
54 expectedCondition *cmapi.CertificateRequestCondition
55 expectNewEntry bool
56 }
57
58 fakeTime1 := randomTime()
59 fakeTimeObj1 := metav1.NewTime(fakeTime1)
60
61 fakeTime2 := randomTime()
62 fakeTimeObj2 := metav1.NewTime(fakeTime2)
63 fakeClock2 := clocktesting.NewFakeClock(fakeTime2)
64
65 testCases := []testCase{
66 {
67 name: "if the condition does NOT change its status, the last transition time should not be updated",
68 existingConditions: []cmapi.CertificateRequestCondition{
69 {
70 Type: cmapi.CertificateRequestConditionReady,
71 Status: cmmeta.ConditionTrue,
72 },
73 },
74 patchConditions: []cmapi.CertificateRequestCondition{},
75 conditionType: cmapi.CertificateRequestConditionReady,
76 status: cmmeta.ConditionTrue,
77
78 expectedCondition: &cmapi.CertificateRequestCondition{
79 Type: cmapi.CertificateRequestConditionReady,
80 Status: cmmeta.ConditionTrue,
81 LastTransitionTime: &fakeTimeObj1,
82 },
83 expectNewEntry: true,
84 },
85 {
86 name: "if the condition DOES change its status, the last transition time should be updated",
87 existingConditions: []cmapi.CertificateRequestCondition{
88 {
89 Type: cmapi.CertificateRequestConditionReady,
90 Status: cmmeta.ConditionTrue,
91 },
92 },
93 patchConditions: []cmapi.CertificateRequestCondition{},
94 conditionType: cmapi.CertificateRequestConditionReady,
95 status: cmmeta.ConditionFalse,
96
97 expectedCondition: &cmapi.CertificateRequestCondition{
98 Type: cmapi.CertificateRequestConditionReady,
99 Status: cmmeta.ConditionFalse,
100 LastTransitionTime: &fakeTimeObj2,
101 },
102 expectNewEntry: true,
103 },
104 {
105 name: "if the patch contains already contains the condition, it should get overwritten",
106 existingConditions: []cmapi.CertificateRequestCondition{
107 {
108 Type: cmapi.CertificateRequestConditionReady,
109 Status: cmmeta.ConditionTrue,
110 },
111 },
112 patchConditions: []cmapi.CertificateRequestCondition{
113 {
114 Type: cmapi.CertificateRequestConditionReady,
115 Status: cmmeta.ConditionTrue,
116 },
117 },
118 conditionType: cmapi.CertificateRequestConditionReady,
119 status: cmmeta.ConditionTrue,
120
121 expectedCondition: &cmapi.CertificateRequestCondition{
122 Type: cmapi.CertificateRequestConditionReady,
123 Status: cmmeta.ConditionTrue,
124 LastTransitionTime: &fakeTimeObj1,
125 },
126 expectNewEntry: false,
127 },
128 {
129 name: "if the patch contains another condition type, it should get added",
130 existingConditions: []cmapi.CertificateRequestCondition{
131 {
132 Type: cmapi.CertificateRequestConditionReady,
133 Status: cmmeta.ConditionTrue,
134 },
135 },
136 patchConditions: []cmapi.CertificateRequestCondition{
137 {
138 Type: cmapi.CertificateRequestConditionReady,
139 Status: cmmeta.ConditionTrue,
140 },
141 },
142 conditionType: cmapi.CertificateRequestConditionApproved,
143 status: cmmeta.ConditionTrue,
144
145 expectedCondition: &cmapi.CertificateRequestCondition{
146 Type: cmapi.CertificateRequestConditionApproved,
147 Status: cmmeta.ConditionTrue,
148 LastTransitionTime: &fakeTimeObj2,
149 },
150 expectNewEntry: true,
151 },
152 }
153
154 defaultConditions := func(t *testing.T, conditions []cmapi.CertificateRequestCondition) []cmapi.CertificateRequestCondition {
155 t.Helper()
156
157 for i := range conditions {
158 if conditions[i].LastTransitionTime != nil ||
159 conditions[i].Reason != "" ||
160 conditions[i].Message != "" {
161 t.Fatal("this field is managed by the test and should not be set")
162 }
163 conditions[i].LastTransitionTime = &fakeTimeObj1
164 conditions[i].Reason = "OldReason"
165 conditions[i].Message = "OldMessage"
166 }
167
168 return conditions
169 }
170
171 for _, test := range testCases {
172 test := test
173
174 t.Run(test.name, func(t *testing.T) {
175 test.existingConditions = defaultConditions(t, test.existingConditions)
176 test.patchConditions = defaultConditions(t, test.patchConditions)
177
178 patchConditions := append([]cmapi.CertificateRequestCondition{}, test.patchConditions...)
179
180 cond, time := SetCertificateRequestStatusCondition(
181 fakeClock2,
182 test.existingConditions,
183 &patchConditions,
184 test.conditionType,
185 test.status,
186 "NewReason",
187 "NewMessage",
188 )
189
190 if test.expectedCondition.Reason != "" ||
191 test.expectedCondition.Message != "" {
192 t.Fatal("this field is managed by the test and should not be set")
193 }
194 test.expectedCondition.Reason = "NewReason"
195 test.expectedCondition.Message = "NewMessage"
196 require.Equal(t, test.expectedCondition, cond)
197 require.Equal(t, &fakeTimeObj2, time)
198
199
200 if test.expectNewEntry {
201 require.Equal(t, len(test.patchConditions)+1, len(patchConditions))
202 } else {
203 require.Equal(t, len(test.patchConditions), len(patchConditions))
204 }
205
206
207 for _, c := range patchConditions {
208 if c.Type == test.conditionType {
209 require.Equal(t, test.expectedCondition, &c)
210 continue
211 }
212
213 for _, ec := range test.patchConditions {
214 if ec.Type == c.Type {
215 require.Equal(t, ec, c)
216 }
217 }
218 }
219 })
220 }
221 }
222
View as plain text