Skip to content

Commit 0f201b3

Browse files
authored
fixed sf compute tagging for v0 until tags (#97)
* fixed sf compute tagging for v0 until tags * fixed comments
1 parent ff74550 commit 0f201b3

2 files changed

Lines changed: 58 additions & 14 deletions

File tree

v1/providers/sfcompute/instance.go

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ func (c *SFCClient) CreateInstance(ctx context.Context, attrs v1.CreateInstanceA
2929
return nil, errors.WrapAndTrace(err)
3030
}
3131

32-
// Create a name for the node
33-
name := brevDataToSFCName(attrs.RefID, attrs.Name)
32+
// Pack cloud cred ref ID, brev stage, instance ref ID, and name into the SFC node name.
33+
// SFC has no tags API, so the node name is the only place to persist this metadata.
34+
stage := getStageFromTags(attrs.Tags)
35+
name := brevDataToSFCName(c.refID, stage, attrs.RefID, attrs.Name)
3436

3537
// Create the node
3638
resp, err := c.client.Nodes.New(ctx, sfcnodes.NodeNewParams{
@@ -231,11 +233,15 @@ type sfcNodeInfo struct {
231233
}
232234

233235
func (c *SFCClient) sfcNodeToBrevInstance(node sfcNodeInfo) (*v1.Instance, error) {
234-
// Get the refID and name from the node name
235-
refID, name, err := sfcNameToBrevData(node.name)
236+
// Parse cloud cred ref ID, brev stage, instance ref ID, and name from the node name.
237+
// Old-format names (refID_name) return empty cloudCredRefID — fall back to c.refID.
238+
cloudCredRefID, _, refID, name, err := sfcNameToBrevData(node.name)
236239
if err != nil {
237240
return nil, errors.WrapAndTrace(err)
238241
}
242+
if cloudCredRefID == "" {
243+
cloudCredRefID = c.refID
244+
}
239245

240246
// Get the instance type for the zone
241247
instanceType, err := getInstanceTypeForZone(*node.zone)
@@ -270,7 +276,7 @@ func (c *SFCClient) sfcNodeToBrevInstance(node sfcNodeInfo) (*v1.Instance, error
270276
Spot: false,
271277
Stoppable: false,
272278
Rebootable: false,
273-
CloudCredRefID: c.refID, // TODO: this should be pulled from the node itself
279+
CloudCredRefID: cloudCredRefID,
274280
}
275281
return inst, nil
276282
}
@@ -448,16 +454,45 @@ func (c *SFCClient) getSSHHostnameFromVM(ctx context.Context, vmID string, vmSta
448454
return sshResponse.SSHHostname, nil
449455
}
450456

451-
func brevDataToSFCName(refID string, name string) string {
452-
return fmt.Sprintf("%s_%s", refID, name)
457+
// brevDataToSFCName packs cloud credential ref ID, brev stage, instance ref ID, and instance
458+
// name into a single SFC node name, separated by underscores. This is necessary because SFC
459+
// has no tags/labels API — the node name is the only place to store metadata.
460+
//
461+
// Format: {cloudCredRefID}_{brevStage}_{refID}_{name}
462+
func brevDataToSFCName(cloudCredRefID string, brevStage string, refID string, name string) string {
463+
return fmt.Sprintf("%s_%s_%s_%s", cloudCredRefID, brevStage, refID, name)
464+
}
465+
466+
// sfcNameToBrevData parses an SFC node name back into its components.
467+
//
468+
// Supports two formats for backward compatibility:
469+
// - New (4+ parts): {cloudCredRefID}_{brevStage}_{refID}_{name}
470+
// - Old (2 parts): {refID}_{name} — cloudCredRefID and brevStage returned empty
471+
func sfcNameToBrevData(name string) (cloudCredRefID string, brevStage string, refID string, instanceName string, err error) {
472+
parts := strings.SplitN(name, "_", 4)
473+
switch len(parts) {
474+
case 4:
475+
// New format: cloudCredRefID_brevStage_refID_name
476+
return parts[0], parts[1], parts[2], parts[3], nil
477+
case 2:
478+
// Old format: refID_name (backward compat — cloudCredRefID and stage unknown)
479+
// TODO: remove this case once all old-format nodes have been cleaned up
480+
return "", "", parts[0], parts[1], nil
481+
default:
482+
return "", "", "", "", errors.WrapAndTrace(fmt.Errorf("invalid node name %s: expected 2 or 4 underscore-separated parts", name))
483+
}
453484
}
454485

455-
func sfcNameToBrevData(name string) (string, string, error) {
456-
parts := strings.SplitN(name, "_", 2)
457-
if len(parts) != 2 {
458-
return "", "", errors.WrapAndTrace(fmt.Errorf("invalid node name %s", name))
486+
// getStageFromTags extracts the control plane stage value from instance tags.
487+
// The tag key is prefixed by the control plane
488+
// so we match any key ending with "-stage" to avoid coupling to a specific prefix.
489+
func getStageFromTags(tags v1.Tags) string {
490+
for k, v := range tags {
491+
if strings.HasSuffix(k, "-stage") {
492+
return v
493+
}
459494
}
460-
return parts[0], parts[1], nil
495+
return "unknown"
461496
}
462497

463498
// Optional if supported:

v1/providers/sfcompute/instancetype.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ const (
2121
interconnectInfiniband = "infiniband"
2222
formFactorSXM5 = "sxm5"
2323
diskTypeSSD = "ssd"
24+
25+
// Currently only 8xH100/H200 instance types are available
26+
// so it's safe to hardcode vCPU and GPU count.
27+
sfcVCPU = 112
28+
sfcGPUCount = 8
2429
)
2530

2631
func makeDefaultInstanceTypePrice(amount string, currencyCode string) currency.Amount {
@@ -112,6 +117,7 @@ func getInstanceTypeForZone(zone sfcnodes.ZoneListResponseData) (*v1.InstanceTyp
112117
Type: makeInstanceTypeName(zone),
113118
Memory: ram,
114119
MemoryBytes: gpuMetadata.memoryBytes,
120+
VCPU: gpuMetadata.vcpu,
115121
Location: zoneToLocation(zone).Name,
116122
Stoppable: false,
117123
Rebootable: false,
@@ -216,6 +222,7 @@ type sfcInstanceTypeMetadata struct {
216222
architecture v1.Architecture
217223
memoryBytes v1.Bytes
218224
diskBytes v1.Bytes
225+
vcpu int32
219226
gpuCount int32
220227
gpuManufacturer v1.Manufacturer
221228
gpuVRAM v1.Bytes
@@ -240,7 +247,8 @@ var h100InstanceTypeMetadata = sfcInstanceTypeMetadata{
240247
architecture: v1.ArchitectureX86_64,
241248
memoryBytes: v1.NewBytes(960, v1.Gigabyte),
242249
diskBytes: v1.NewBytes(1500, v1.Gigabyte),
243-
gpuCount: 8,
250+
vcpu: sfcVCPU,
251+
gpuCount: sfcGPUCount,
244252
gpuManufacturer: v1.ManufacturerNVIDIA,
245253
gpuVRAM: v1.NewBytes(80, v1.Gigabyte),
246254
estimatedDeployTime: 14 * time.Minute,
@@ -253,7 +261,8 @@ var h200InstanceTypeMetadata = sfcInstanceTypeMetadata{
253261
architecture: v1.ArchitectureX86_64,
254262
memoryBytes: v1.NewBytes(960, v1.Gigabyte),
255263
diskBytes: v1.NewBytes(1500, v1.Gigabyte),
256-
gpuCount: 8,
264+
vcpu: sfcVCPU,
265+
gpuCount: sfcGPUCount,
257266
gpuManufacturer: v1.ManufacturerNVIDIA,
258267
gpuVRAM: v1.NewBytes(141, v1.Gigabyte),
259268
estimatedDeployTime: 14 * time.Minute,

0 commit comments

Comments
 (0)