@@ -686,6 +686,15 @@ func TestConstructJobsFromTemplate(t *testing.T) {
686686
687687 for _ , tc := range tests {
688688 t .Run (tc .name , func (t * testing.T ) {
689+ // Here we update the expected Jobs with certain features which require
690+ // direct access to the JobSet object itself to calculate. For example,
691+ // the `jobset.sigs.k8s.io/job-global-index` annotation requires access to the
692+ // full JobSet spec to calculate a unique ID for each Job.
693+ for _ , expectedJob := range tc .want {
694+ addJobGlobalIndex (t , tc .js , expectedJob )
695+ }
696+
697+ // Now get the actual output of constructJobsFromTemplate, and diff the results.
689698 var got []* batchv1.Job
690699 for _ , rjob := range tc .js .Spec .ReplicatedJobs {
691700 jobs := constructJobsFromTemplate (tc .js , & rjob , tc .ownedJobs )
@@ -699,6 +708,26 @@ func TestConstructJobsFromTemplate(t *testing.T) {
699708 }
700709}
701710
711+ // addJobGlobalIndex modifies the Job object in place by adding
712+ // the `jobset.sigs.k8s.io/job-global-index` label/annotation to both the
713+ // Job itself and the Job template spec.`
714+ func addJobGlobalIndex (t * testing.T , js * jobset.JobSet , job * batchv1.Job ) {
715+ t .Helper ()
716+
717+ rjobName := job .Annotations [jobset .ReplicatedJobNameKey ]
718+ jobIdx , err := strconv .Atoi (job .Annotations [jobset .JobIndexKey ])
719+ if err != nil {
720+ t .Fatalf ("invalid test case: %v" , err )
721+ }
722+ // Job label/annotation
723+ job .Labels [jobset .JobGlobalIndexKey ] = globalJobIndex (js , rjobName , jobIdx )
724+ job .Annotations [jobset .JobGlobalIndexKey ] = globalJobIndex (js , rjobName , jobIdx )
725+
726+ // Job template spec label/annotation
727+ job .Spec .Template .Labels [jobset .JobGlobalIndexKey ] = globalJobIndex (js , rjobName , jobIdx )
728+ job .Spec .Template .Annotations [jobset .JobGlobalIndexKey ] = globalJobIndex (js , rjobName , jobIdx )
729+ }
730+
702731func TestUpdateConditions (t * testing.T ) {
703732 var (
704733 jobSetName = "test-jobset"
@@ -1381,3 +1410,64 @@ func TestCreateHeadlessSvcIfNecessary(t *testing.T) {
13811410 })
13821411 }
13831412}
1413+
1414+ func TestGlobalJobIndex (t * testing.T ) {
1415+ tests := []struct {
1416+ name string
1417+ jobSet * jobset.JobSet
1418+ replicatedJob string
1419+ jobIdx int
1420+ expectedJobGlobalIndex string
1421+ }{
1422+ {
1423+ name : "single replicated job" ,
1424+ jobSet : & jobset.JobSet {
1425+ Spec : jobset.JobSetSpec {
1426+ ReplicatedJobs : []jobset.ReplicatedJob {
1427+ {Name : "rjob" , Replicas : 3 },
1428+ },
1429+ },
1430+ },
1431+ replicatedJob : "rjob" ,
1432+ jobIdx : 1 ,
1433+ expectedJobGlobalIndex : "1" ,
1434+ },
1435+ {
1436+ name : "multiple replicated jobs" ,
1437+ jobSet : & jobset.JobSet {
1438+ Spec : jobset.JobSetSpec {
1439+ ReplicatedJobs : []jobset.ReplicatedJob {
1440+ {Name : "rjob1" , Replicas : 2 },
1441+ {Name : "rjob2" , Replicas : 4 },
1442+ {Name : "rjob3" , Replicas : 1 },
1443+ },
1444+ },
1445+ },
1446+ replicatedJob : "rjob2" ,
1447+ jobIdx : 3 ,
1448+ expectedJobGlobalIndex : "5" ,
1449+ },
1450+ {
1451+ name : "replicated job not found" ,
1452+ jobSet : & jobset.JobSet {
1453+ Spec : jobset.JobSetSpec {
1454+ ReplicatedJobs : []jobset.ReplicatedJob {
1455+ {Name : "rjob1" , Replicas : 2 },
1456+ },
1457+ },
1458+ },
1459+ replicatedJob : "rjob2" ,
1460+ jobIdx : 0 ,
1461+ expectedJobGlobalIndex : "" ,
1462+ },
1463+ }
1464+
1465+ for _ , tc := range tests {
1466+ t .Run (tc .name , func (t * testing.T ) {
1467+ actualJobGlobalIndex := globalJobIndex (tc .jobSet , tc .replicatedJob , tc .jobIdx )
1468+ if diff := cmp .Diff (tc .expectedJobGlobalIndex , actualJobGlobalIndex ); diff != "" {
1469+ t .Errorf ("unexpected global job index (-want/+got): %s" , diff )
1470+ }
1471+ })
1472+ }
1473+ }
0 commit comments