Skip to content

Commit 070bea4

Browse files
committed
fix(nebius): score-based image selection in getWorkingPublicImageID
1 parent df17220 commit 070bea4

1 file changed

Lines changed: 59 additions & 45 deletions

File tree

v1/providers/nebius/instance.go

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,11 +1265,9 @@ func (c *NebiusClient) buildDiskCreateRequest(ctx context.Context, diskName stri
12651265
return nil, fmt.Errorf("could not resolve image %s to either a working family or image ID: %w", attrs.ImageID, err)
12661266
}
12671267

1268-
// getWorkingPublicImageID gets a working public image ID based on the requested image type
1269-
//
1270-
//nolint:gocognit,gocyclo // Complex function trying multiple image resolution strategies
1268+
// getWorkingPublicImageID gets a working public image ID based on the requested image type.
1269+
// It scores every non-ARM64 image and returns the highest-scored one, this is done to handle change in ordering of images from nebius api.
12711270
func (c *NebiusClient) getWorkingPublicImageID(ctx context.Context, requestedImage string) (string, error) {
1272-
// Get available public images from the correct region
12731271
publicImagesParent := c.getPublicImagesParent()
12741272
imagesResp, err := c.sdk.Services().Compute().V1().Image().List(ctx, &compute.ListImagesRequest{
12751273
ParentId: publicImagesParent,
@@ -1282,67 +1280,83 @@ func (c *NebiusClient) getWorkingPublicImageID(ctx context.Context, requestedIma
12821280
return "", fmt.Errorf("no public images available")
12831281
}
12841282

1285-
// Try to find the best match based on the requested image
12861283
requestedLower := strings.ToLower(requestedImage)
12871284

1288-
var bestMatch *compute.Image
1289-
var fallbackImage *compute.Image
1285+
var bestImage *compute.Image
1286+
bestScore := -1
12901287

12911288
for _, image := range imagesResp.GetItems() {
12921289
if image.Metadata == nil {
12931290
continue
12941291
}
1295-
12961292
if image.Spec != nil && image.Spec.GetCpuArchitecture() == compute.ImageSpec_ARM64 {
12971293
continue
12981294
}
12991295

1300-
imageName := strings.ToLower(image.Metadata.Name)
1301-
1302-
// Set fallback to first available image
1303-
if fallbackImage == nil {
1304-
fallbackImage = image
1296+
score := scoreImage(image, requestedLower)
1297+
if score > bestScore {
1298+
bestScore = score
1299+
bestImage = image
13051300
}
1301+
}
13061302

1307-
// Look for Ubuntu matches
1308-
if strings.Contains(requestedLower, "ubuntu") && strings.Contains(imageName, "ubuntu") {
1309-
// Prefer specific version matches
1310-
//nolint:gocritic // if-else chain is clearer than switch for version matching logic
1311-
if strings.Contains(requestedLower, "24.04") || strings.Contains(requestedLower, "24") {
1312-
if strings.Contains(imageName, "ubuntu24.04") {
1313-
bestMatch = image
1314-
break
1315-
}
1316-
} else if strings.Contains(requestedLower, "22.04") || strings.Contains(requestedLower, "22") {
1317-
if strings.Contains(imageName, "ubuntu22.04") {
1318-
bestMatch = image
1319-
break
1320-
}
1321-
} else if strings.Contains(requestedLower, "20.04") || strings.Contains(requestedLower, "20") {
1322-
if strings.Contains(imageName, "ubuntu20.04") {
1323-
bestMatch = image
1324-
break
1325-
}
1326-
}
1303+
if bestImage == nil {
1304+
return "", fmt.Errorf("no suitable public image found")
1305+
}
1306+
1307+
return bestImage.Metadata.Id, nil
1308+
}
13271309

1328-
// Any Ubuntu image is better than non-Ubuntu
1329-
if bestMatch == nil {
1330-
bestMatch = image
1310+
// scoreImage assigns a priority score to an image. Higher score = better match.
1311+
// When requestedImage is empty (default deploy), the function uses a standard
1312+
// preference order: Ubuntu 24 CUDA 13 > Ubuntu 24 CUDA 12 > Ubuntu 22 CUDA 12
1313+
// > Ubuntu 24 driverless > any Ubuntu > worker node > anything else.
1314+
// When requestedImage is non-empty, exact family/name matches get a bonus.
1315+
func scoreImage(image *compute.Image, requestedLower string) int {
1316+
family := ""
1317+
if image.Spec != nil {
1318+
family = strings.ToLower(image.Spec.GetImageFamily())
1319+
}
1320+
name := strings.ToLower(image.Metadata.Name)
1321+
1322+
isWorkerNode := strings.Contains(family, "mk8s-worker") || strings.Contains(name, "worker-node")
1323+
isUbuntu := strings.Contains(family, "ubuntu") || strings.Contains(name, "ubuntu")
1324+
hasCuda13 := strings.Contains(family, "cuda13") || strings.Contains(name, "cuda13")
1325+
hasCuda12 := strings.Contains(family, "cuda12") || strings.Contains(name, "cuda12")
1326+
isUbuntu24 := strings.Contains(family, "ubuntu24") || strings.Contains(name, "ubuntu24")
1327+
isUbuntu22 := strings.Contains(family, "ubuntu22") || strings.Contains(name, "ubuntu22")
1328+
1329+
score := 1 // baseline for any non-ARM64 image
1330+
1331+
if isWorkerNode {
1332+
score = 10
1333+
} else if isUbuntu {
1334+
score = 50
1335+
if isUbuntu24 {
1336+
score = 60
1337+
if hasCuda13 {
1338+
score = 100
1339+
} else if hasCuda12 {
1340+
score = 90
1341+
}
1342+
} else if isUbuntu22 {
1343+
score = 55
1344+
if hasCuda12 {
1345+
score = 80
13311346
}
13321347
}
13331348
}
13341349

1335-
// Use best match if found, otherwise fallback
1336-
selectedImage := bestMatch
1337-
if selectedImage == nil {
1338-
selectedImage = fallbackImage
1339-
}
1340-
1341-
if selectedImage == nil {
1342-
return "", fmt.Errorf("no suitable public image found")
1350+
// If the caller explicitly requested something, boost images that match the request
1351+
if requestedLower != "" {
1352+
if strings.Contains(name, requestedLower) || strings.Contains(family, requestedLower) || requestedLower == family {
1353+
score += 200
1354+
} else if isUbuntu && strings.Contains(requestedLower, "ubuntu") {
1355+
score += 50
1356+
}
13431357
}
13441358

1345-
return selectedImage.Metadata.Id, nil
1359+
return score
13461360
}
13471361

13481362
// getPublicImagesParent determines the correct public images parent ID based on project routing code

0 commit comments

Comments
 (0)