@@ -11,6 +11,7 @@ import (
1111 "github.com/stretchr/testify/require"
1212
1313 appsv1 "k8s.io/api/apps/v1"
14+ batchv1 "k8s.io/api/batch/v1"
1415 corev1 "k8s.io/api/core/v1"
1516 "k8s.io/apimachinery/pkg/runtime"
1617)
@@ -221,6 +222,104 @@ const (
221222 "updatedReplicas": 1
222223 }
223224}
225+ `
226+
227+ tJob = `
228+ {
229+ "apiVersion": "batch/v1",
230+ "kind": "Job",
231+ "metadata": {
232+ "annotations": {
233+ "batch.kubernetes.io/job-tracking": ""
234+ },
235+ "creationTimestamp": "2023-04-12T08:32:12Z",
236+ "generation": 1,
237+ "labels": {
238+ "app.kubernetes.io/managed-by": "triggermesh-core",
239+ "app.kubernetes.io/part-of": "triggermesh",
240+ "controller-uid": "dad9425a-3410-40ea-832e-31b087f8f808",
241+ "job-name": "test"
242+ },
243+ "name": "test",
244+ "namespace": "default",
245+ "resourceVersion": "650907",
246+ "uid": "dad9425a-3410-40ea-832e-31b087f8f808"
247+ },
248+ "spec": {
249+ "backoffLimit": 3,
250+ "completionMode": "NonIndexed",
251+ "completions": 1,
252+ "parallelism": 1,
253+ "selector": {
254+ "matchLabels": {
255+ "controller-uid": "dad9425a-3410-40ea-832e-31b087f8f808"
256+ }
257+ },
258+ "suspend": false,
259+ "template": {
260+ "metadata": {
261+ "creationTimestamp": null,
262+ "labels": {
263+ "app.kubernetes.io/managed-by": "triggermesh-core",
264+ "app.kubernetes.io/part-of": "triggermesh",
265+ "controller-uid": "dad9425a-3410-40ea-832e-31b087f8f808",
266+ "job-name": "test"
267+ },
268+ "ownerReferences": [
269+ {
270+ "apiVersion": "eventing.triggermesh.io/v1alpha1",
271+ "kind": "TestKind",
272+ "name": "test",
273+ "uid": "186f3c1b-952b-4e45-9837-2ee6bd4436ec"
274+ }
275+ ]
276+ },
277+ "spec": {
278+ "containers": [
279+ {
280+ "env": [
281+ {
282+ "name": "ENV_ONE",
283+ "value": "1"
284+ },
285+ {
286+ "name": "ENV_TWO",
287+ "value": "2"
288+ }
289+ ],
290+ "image": "test/test:latest",
291+ "imagePullPolicy": "Always",
292+ "name": "test",
293+ "resources": {},
294+ "terminationMessagePath": "/dev/termination-log",
295+ "terminationMessagePolicy": "File"
296+ }
297+ ],
298+ "dnsPolicy": "ClusterFirst",
299+ "restartPolicy": "Never",
300+ "schedulerName": "default-scheduler",
301+ "securityContext": {},
302+ "terminationGracePeriodSeconds": 30
303+ }
304+ }
305+ },
306+ "status": {
307+ "conditions": [
308+ {
309+ "lastProbeTime": "2023-04-12T08:34:02Z",
310+ "lastTransitionTime": "2023-04-12T08:34:02Z",
311+ "message": "Job has reached the specified backoff limit",
312+ "reason": "BackoffLimitExceeded",
313+ "status": "True",
314+ "type": "Failed"
315+ }
316+ ],
317+ "failed": 1,
318+ "ready": 0,
319+ "startTime": "2023-04-12T08:32:12Z",
320+ "uncountedTerminatedPods": {}
321+ }
322+ }
224323`
225324)
226325
@@ -404,3 +503,90 @@ func loadFixture(t *testing.T, contents string, obj runtime.Object) {
404503 t .Fatalf ("Error deserializing fixture object: %s" , err )
405504 }
406505}
506+
507+ func TestJobEqual (t * testing.T ) {
508+ current := & batchv1.Job {}
509+ loadFixture (t , tJob , current )
510+
511+ require .GreaterOrEqual (t , len (current .Labels ), 2 ,
512+ "Test suite requires a reference object with at least 2 labels to run properly" )
513+ require .True (t , len (current .Spec .Template .Spec .Containers ) > 0 &&
514+ len (current .Spec .Template .Spec .Containers [0 ].Env ) > 0 &&
515+ current .Spec .Template .Spec .Containers [0 ].Env [0 ].Value != "" ,
516+ "Test suite requires a reference object with a Container that has at least 1 EnvVar to run properly" )
517+
518+ assert .True (t , deploymentEqual (nil , nil ), "Two nil elements should be equal" )
519+
520+ testCases := map [string ]struct {
521+ prep func () * batchv1.Job
522+ expect bool
523+ }{
524+ "not equal when one element is nil" : {
525+ func () * batchv1.Job {
526+ return nil
527+ },
528+ false ,
529+ },
530+ // counter intuitive but expected result for deep derivative comparisons
531+ "equal when all desired attributes are empty" : {
532+ func () * batchv1.Job {
533+ return & batchv1.Job {}
534+ },
535+ true ,
536+ },
537+ "not equal when some existing attribute differs" : {
538+ func () * batchv1.Job {
539+ desired := current .DeepCopy ()
540+ for k := range desired .Labels {
541+ desired .Labels [k ] += "test"
542+ break // changing one is enough
543+ }
544+ return desired
545+ },
546+ false ,
547+ },
548+ "equal when current has more attributes than desired" : {
549+ func () * batchv1.Job {
550+ desired := current .DeepCopy ()
551+ for k := range desired .Labels {
552+ delete (desired .Labels , k )
553+ break // deleting one is enough
554+ }
555+ return desired
556+ },
557+ true ,
558+ },
559+ "not equal when desired has more attributes than current" : {
560+ func () * batchv1.Job {
561+ desired := current .DeepCopy ()
562+ for k := range desired .Labels {
563+ desired .Labels [k + "test" ] = "test"
564+ break // adding one is enough
565+ }
566+ return desired
567+ },
568+ false ,
569+ },
570+ "not equal when EnvVar desired value is empty" : {
571+ func () * batchv1.Job {
572+ desired := current .DeepCopy ()
573+ desired .Spec .Template .Spec .Containers [0 ].Env [0 ].Value = ""
574+ return desired
575+ },
576+ false ,
577+ },
578+ }
579+
580+ for name , tc := range testCases {
581+ //nolint:scopelint
582+ t .Run (name , func (t * testing.T ) {
583+ desired := tc .prep ()
584+ switch tc .expect {
585+ case true :
586+ assert .True (t , jobEqual (desired , current ))
587+ case false :
588+ assert .False (t , jobEqual (desired , current ))
589+ }
590+ })
591+ }
592+ }
0 commit comments