@@ -11,6 +11,7 @@ import (
1111 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1212 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1313 "k8s.io/apimachinery/pkg/runtime/schema"
14+ "k8s.io/apimachinery/pkg/types"
1415 "sigs.k8s.io/controller-runtime/pkg/client"
1516
1617 "github.com/NVIDIA/KAI-scheduler/pkg/podgrouper/podgroup"
@@ -67,19 +68,19 @@ func (gg *GroveGrouper) GetPodGroupMetadata(
6768 Name : podGangName ,
6869 }, podGang )
6970 if err != nil {
70- return nil , fmt .Errorf ("failed to get PodGang %s/%s : %w" ,
71+ return nil , fmt .Errorf ("failed to get PodGang %s/%s. Err : %w" ,
7172 pod .Namespace , podGangName , err )
7273 }
7374
7475 metadata , err := gg .DefaultGrouper .GetPodGroupMetadata (podGang , pod )
7576 if err != nil {
76- return nil , fmt .Errorf ("failed to get DefaultGrouper metadata for PodGang %s/%s : %w" ,
77+ return nil , fmt .Errorf ("failed to get DefaultGrouper metadata for PodGang %s/%s. Err : %w" ,
7778 pod .Namespace , podGangName , err )
7879 }
7980
8081 priorityClassName , found , err := unstructured .NestedString (podGang .Object , "spec" , "priorityClassName" )
8182 if err != nil {
82- return nil , fmt .Errorf ("failed to get spec.priorityClassName from PodGang %s/%s : %w" ,
83+ return nil , fmt .Errorf ("failed to get spec.priorityClassName from PodGang %s/%s. Err : %w" ,
8384 pod .Namespace , podGangName , err )
8485 }
8586 if found {
@@ -89,27 +90,99 @@ func (gg *GroveGrouper) GetPodGroupMetadata(
8990 var minAvailable int32
9091 pgSlice , found , err := unstructured .NestedSlice (podGang .Object , "spec" , "podgroups" )
9192 if err != nil {
92- return nil , fmt .Errorf ("failed to get spec.podgroups from PodGang %s/%s : %w" ,
93+ return nil , fmt .Errorf ("failed to get spec.podgroups from PodGang %s/%s. Err : %w" ,
9394 pod .Namespace , podGangName , err )
9495 }
95- for idx , v := range pgSlice {
96+ for pgIndex , v := range pgSlice {
9697 pgr , ok := v .(map [string ]interface {})
9798 if ! ok {
9899 return nil , fmt .Errorf ("invalid structure of spec.podgroup[%v] in PodGang %s/%s" ,
99- idx , pod .Namespace , podGangName )
100+ pgIndex , pod .Namespace , podGangName )
100101 }
101- podSlice , found , err := unstructured . NestedSlice (pgr , "podReferences" )
102+ subGroup , err := parseGroveSubGroup (pgr , pgIndex , pod . Namespace , podGangName )
102103 if err != nil {
103- return nil , fmt .Errorf ("failed to get podReferences from spec.podgroup[%v] of PodGang %s/%s : %w" ,
104- idx , pod .Namespace , podGangName , err )
104+ return nil , fmt .Errorf ("failed to parse spec.podgroups[%d] from PodGang %s/%s. Err : %w" ,
105+ pgIndex , pod .Namespace , podGangName , err )
105106 }
106- if ! found {
107- return nil , fmt .Errorf ("missing podReferences in spec.podgroup[%v] of PodGang %s/%s" ,
108- idx , pod .Namespace , podGangName )
109- }
110- minAvailable += int32 (len (podSlice ))
107+ metadata .SubGroups = append (metadata .SubGroups , subGroup )
108+
109+ minAvailable += subGroup .MinAvailable
111110 }
112111 metadata .MinAvailable = minAvailable
113112
114113 return metadata , nil
115114}
115+
116+ func parseGroveSubGroup (
117+ pg map [string ]interface {}, pgIndex int , namespace , podGangName string ,
118+ ) (* podgroup.SubGroupMetadata , error ) {
119+ // Name
120+ name , found , err := unstructured .NestedString (pg , "name" )
121+ if err != nil {
122+ return nil , fmt .Errorf ("failed to parse 'name' field. Err: %v" , err )
123+ }
124+ if ! found {
125+ return nil , fmt .Errorf ("missing required 'name' field" )
126+ }
127+
128+ // MinReplicas
129+ minAvailable , found , err := unstructured .NestedInt64 (pg , "minReplicas" )
130+ if err != nil {
131+ return nil , fmt .Errorf ("failed to parse 'minReplicas' field. Err: %v" , err )
132+ }
133+ if ! found {
134+ return nil , fmt .Errorf ("missing required 'minReplicas' field" )
135+ }
136+ if minAvailable <= 0 {
137+ return nil , fmt .Errorf ("invalid 'minReplicas' field. Must be greater than 0" )
138+ }
139+
140+ // PodReferences
141+ podReferences , found , err := unstructured .NestedSlice (pg , "podReferences" )
142+ if err != nil {
143+ return nil , fmt .Errorf ("failed to parse 'podReferences' field. Err: %w" , err )
144+ }
145+ if ! found {
146+ return nil , fmt .Errorf ("missing required 'podReferences' field" )
147+ }
148+ var pods []* types.NamespacedName
149+ for podIndex , podRef := range podReferences {
150+ reference , ok := podRef .(map [string ]interface {})
151+ if ! ok {
152+ return nil , fmt .Errorf ("invalid spec.podgroup[%d].podReferences[%d] in PodGang %s/%s" ,
153+ pgIndex , podIndex , namespace , podGangName )
154+ }
155+ namespacedName , err := parsePodReference (reference )
156+ if err != nil {
157+ return nil , fmt .Errorf ("failed to parse spec.podgroups[%d].podreferences[%d] from PodGang %s/%s. Err: %w" ,
158+ pgIndex , podIndex , namespace , podGangName , err )
159+ }
160+ pods = append (pods , namespacedName )
161+ }
162+
163+ return & podgroup.SubGroupMetadata {
164+ Name : name ,
165+ MinAvailable : int32 (minAvailable ),
166+ PodsReferences : pods ,
167+ }, nil
168+ }
169+
170+ func parsePodReference (podRef map [string ]interface {}) (* types.NamespacedName , error ) {
171+ podNamespace , found , err := unstructured .NestedString (podRef , "namespace" )
172+ if err != nil {
173+ return nil , fmt .Errorf ("failed to parse 'namespace' field. Err: %v" , err )
174+ }
175+ if ! found {
176+ return nil , fmt .Errorf ("missing required 'namespace' field" )
177+ }
178+
179+ podName , found , err := unstructured .NestedString (podRef , "name" )
180+ if err != nil {
181+ return nil , fmt .Errorf ("failed to parse 'name' field. Err: %v" , err )
182+ }
183+ if ! found {
184+ return nil , fmt .Errorf ("missing required 'name' field" )
185+ }
186+
187+ return & types.NamespacedName {Namespace : podNamespace , Name : podName }, nil
188+ }
0 commit comments