Skip to content

Commit 54e1faf

Browse files
authored
Merge pull request #8500 from coreweave/bugfix-update-nodegoup
Update nodegoup for CoreWeave Provider
2 parents 7b9cb8c + 38ddaaa commit 54e1faf

File tree

5 files changed

+112
-47
lines changed

5 files changed

+112
-47
lines changed

cluster-autoscaler/cloudprovider/coreweave/coreweave_manager.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ func (m *CoreWeaveManager) ListNodePools() ([]*CoreWeaveNodePool, error) {
7070
return nil, fmt.Errorf("failed to list nodepools: %v", err)
7171
}
7272
if list == nil || len(list.Items) == 0 {
73-
return nil, fmt.Errorf("no nodepools found")
73+
klog.V(4).Info("No nodepools found")
74+
return []*CoreWeaveNodePool{}, nil
7475
}
7576
klog.V(4).Infof("Found %d node pools", len(list.Items))
7677
// Convert unstructured items to CoreWeaveNodePool instances
@@ -122,7 +123,8 @@ func (m *CoreWeaveManager) UpdateNodeGroup() ([]cloudprovider.NodeGroup, error)
122123
// If no node pools are found, return an empty slice
123124
if len(nodepools) == 0 {
124125
klog.Info("No node pools found, returning empty node groups")
125-
return nil, nil
126+
m.nodeGroups = []cloudprovider.NodeGroup{}
127+
return m.nodeGroups, nil
126128
}
127129
klog.V(4).Infof("Found %d node pools", len(nodepools))
128130
m.nodeGroups = make([]cloudprovider.NodeGroup, len(nodepools))
@@ -143,6 +145,8 @@ func (m *CoreWeaveManager) GetNodeGroup(nodePoolUID string) (cloudprovider.NodeG
143145
return ng, nil
144146
}
145147
}
146-
// If no node group is found, return an error
147-
return nil, fmt.Errorf("node group for nodepool %s not found", nodePoolUID)
148+
// If no node group is found, return nil (not an error) - this handles the case where
149+
// nodes exist with CoreWeave labels but no corresponding node pools are configured
150+
klog.V(4).Infof("No node group found for nodepool UID %s", nodePoolUID)
151+
return nil, nil
148152
}

cluster-autoscaler/cloudprovider/coreweave/coreweave_manager_test.go

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ func TestListNodePools_ListError(t *testing.T) {
136136
dynamicClient: dynClient,
137137
}
138138
_, err := manager.ListNodePools()
139-
if err == nil {
140-
t.Error("expected error, got nil")
139+
if err != nil {
140+
t.Error("unexpected error, got ", err)
141141
}
142142
}
143143

@@ -186,10 +186,96 @@ func TestListNodePools_EmptyList(t *testing.T) {
186186
// Create a manager with no nodepool items
187187
manager := makeTestManagerWithNodePools(nil)
188188
nodePools, err := manager.ListNodePools()
189-
if err == nil {
190-
t.Errorf("expected error for empty nodepools list, got nil")
189+
if err != nil {
190+
t.Errorf("unexpected error for empty nodepools list, got %v", err)
191191
}
192192
if len(nodePools) != 0 {
193193
t.Errorf("expected empty nodepools list, got %d", len(nodePools))
194194
}
195195
}
196+
197+
func TestUpdateNodeGroup_EmptyNodePools(t *testing.T) {
198+
// Create a nodepool with autoscaling disabled - this will result in empty list after filtering
199+
obj := map[string]interface{}{
200+
"apiVersion": coreWeaveGroup + "/" + coreWeaveVersion,
201+
"kind": coreWeaveResource,
202+
"metadata": map[string]interface{}{
203+
"name": "np1",
204+
"namespace": "default",
205+
"uid": "uid1",
206+
},
207+
"spec": map[string]interface{}{
208+
"minNodes": int64(1),
209+
"maxNodes": int64(5),
210+
"targetNodes": int64(3),
211+
"autoscaling": false, // Autoscaling disabled - will be filtered out
212+
},
213+
}
214+
item := unstructured.Unstructured{Object: obj}
215+
manager := makeTestManagerWithNodePools(nil, item)
216+
217+
// UpdateNodeGroup should return empty slice when all nodepools have autoscaling disabled
218+
nodeGroups, err := manager.UpdateNodeGroup()
219+
if err != nil {
220+
t.Errorf("unexpected error: %v", err)
221+
}
222+
if nodeGroups == nil {
223+
t.Error("expected empty slice, got nil")
224+
}
225+
if len(nodeGroups) != 0 {
226+
t.Errorf("expected empty node groups, got %d", len(nodeGroups))
227+
}
228+
}
229+
230+
func TestUpdateNodeGroup_NoNodePools(t *testing.T) {
231+
// Create a manager with no nodepool items at all
232+
manager := makeTestManagerWithNodePools(nil) // No items passed
233+
234+
// UpdateNodeGroup should return an empty slice when ListNodePools fails (no nodepools found)
235+
nodeGroups, err := manager.UpdateNodeGroup()
236+
if err != nil {
237+
t.Errorf("unexpected error when no nodepools exist, got: %v", err)
238+
}
239+
if nodeGroups == nil {
240+
t.Error("expected empty nodeGroups got: nil")
241+
}
242+
243+
// Verify that nodeGroups field remains nil when ListNodePools returns no pools
244+
if manager.nodeGroups == nil {
245+
t.Error("expected nodeGroups field to be empty when ListNodePools returns no pools")
246+
}
247+
}
248+
249+
func TestGetNodeGroup_NoNodePools(t *testing.T) {
250+
// Create a manager with no nodepool items
251+
manager := makeTestManagerWithNodePools(nil)
252+
_, err := manager.UpdateNodeGroup()
253+
if err != nil {
254+
t.Errorf("unexpected error when updating node group: %v", err)
255+
}
256+
// GetNodeGroup should return nil, nil (not found) rather than an error
257+
nodeGroup, err := manager.GetNodeGroup("nonexistent-uid")
258+
if err != nil {
259+
t.Errorf("expected no error when nodegroup not found, got: %v", err)
260+
}
261+
if nodeGroup != nil {
262+
t.Errorf("expected nil nodegroup when not found, got: %v", nodeGroup)
263+
}
264+
}
265+
266+
func TestGetNodeGroup_NotInitialized(t *testing.T) {
267+
// Create a manager and don't call UpdateNodeGroup to test uninitialized state
268+
manager := makeTestManagerWithNodePools(nil)
269+
270+
// GetNodeGroup should return an error when nodeGroups is not initialized
271+
nodeGroup, err := manager.GetNodeGroup("some-uid")
272+
if err == nil {
273+
t.Error("expected error when nodeGroups not initialized, got nil")
274+
}
275+
if nodeGroup != nil {
276+
t.Errorf("expected nil nodegroup when error occurs, got: %v", nodeGroup)
277+
}
278+
if err.Error() != "node groups are not initialized" {
279+
t.Errorf("expected specific error message, got: %v", err)
280+
}
281+
}

cluster-autoscaler/cloudprovider/coreweave/coreweave_nodegroup.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -122,28 +122,8 @@ func (ng *CoreWeaveNodeGroup) Debug() string {
122122

123123
// Nodes returns the list of nodes in the node group.
124124
func (ng *CoreWeaveNodeGroup) Nodes() ([]cloudprovider.Instance, error) {
125-
// Check if we have cached nodes
126-
nodes, err := ng.getNodes()
127-
if err != nil {
128-
klog.Errorf("Failed to get nodes for node group %s: %v", ng.Name, err)
129-
return nil, fmt.Errorf("failed to get nodes for node group %s: %v", ng.Name, err)
130-
}
131-
return nodes, nil
132-
}
133-
134-
// getNodes returns the list of nodes in the node group.
135-
func (ng *CoreWeaveNodeGroup) getNodes() ([]cloudprovider.Instance, error) {
136-
nodes, err := ng.nodepool.GetNodes()
137-
if err != nil {
138-
return nil, err
139-
}
140-
instances := make([]cloudprovider.Instance, len(nodes))
141-
for i, node := range nodes {
142-
instances[i] = cloudprovider.Instance{
143-
Id: node.Name,
144-
}
145-
}
146-
return instances, nil
125+
// Return empty slice to avoid "not registered" warnings
126+
return []cloudprovider.Instance{}, nil
147127
}
148128

149129
// TemplateNodeInfo returns a template NodeInfo for the node group.

cluster-autoscaler/cloudprovider/coreweave/coreweave_nodegroup_test.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,6 @@ func TestId(t *testing.T) {
8383
}
8484
}
8585

86-
func TestNodes(t *testing.T) {
87-
ng := makeTestNodeGroup("ng-1", "uid-1", 1, 5, 3)
88-
nodes, err := ng.Nodes()
89-
if err != nil {
90-
t.Errorf("unexpected error: %v", err)
91-
}
92-
if len(nodes) != 2 {
93-
t.Errorf("expected 2 nodes, got %d", len(nodes))
94-
}
95-
}
96-
9786
func TestMinMaxTargetSize(t *testing.T) {
9887
ng := makeTestNodeGroup("ng-1", "uid-1", 2, 10, 5)
9988
if ng.MinSize() != 2 {

cluster-autoscaler/cloudprovider/coreweave/coreweave_provider_test.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,12 @@ func TestCoreWeaveCloudProvider_NodeGroupForNode_GetNodePoolByNameError(t *testi
144144
manager.UpdateNodeGroup()
145145
cp := &CoreWeaveCloudProvider{manager: manager}
146146
node := &apiv1.Node{ObjectMeta: metav1.ObjectMeta{Name: "n1", Labels: map[string]string{coreWeaveNodePoolUID: "missing"}}}
147-
_, err := cp.NodeGroupForNode(node)
148-
if err == nil {
149-
t.Error("expected error from GetNodePoolByName")
147+
nodeGroup, err := cp.NodeGroupForNode(node)
148+
if err != nil {
149+
t.Errorf("unexpected error from NodeGroupForNode: %v", err)
150+
}
151+
if nodeGroup != nil {
152+
t.Error("expected nil nodeGroup for non-existent nodepool UID")
150153
}
151154
}
152155

@@ -157,9 +160,12 @@ func TestCoreWeaveCloudProvider_NodeGroupForNode_GetNodePoolByUIDError(t *testin
157160
manager.UpdateNodeGroup()
158161
cp := &CoreWeaveCloudProvider{manager: manager}
159162
node := &apiv1.Node{ObjectMeta: metav1.ObjectMeta{Name: "n1", Labels: map[string]string{coreWeaveNodePoolUID: "wrong-uid"}}}
160-
_, err := cp.NodeGroupForNode(node)
161-
if err == nil {
162-
t.Error("expected error from GetNodePoolByUID")
163+
nodeGroup, err := cp.NodeGroupForNode(node)
164+
if err != nil {
165+
t.Errorf("unexpected error from NodeGroupForNode: %v", err)
166+
}
167+
if nodeGroup != nil {
168+
t.Error("expected nil nodeGroup for non-existent nodepool UID")
163169
}
164170
}
165171

0 commit comments

Comments
 (0)