Skip to content

Commit dc61caa

Browse files
author
Sprite
committed
Remove the GPU surface
GPU machines are no longer offered, and the Machines API rejects any request that carries a GPU guest with a 400. Drops the GPU validation and preset handling, the MCP tool arguments that advertised GPUs, and the GPU table in `fly platform vm-sizes`. `--vm-gpus` and `--vm-gpu-kind` (and the `--vm-gpukind` alias) are kept as hidden flags that error out, so a script still passing one gets an explanation rather than "unknown flag". `fly mcp launch` keeps forwarding them for the same reason: dropping them there would quietly launch a CPU machine instead. The four GPU size presets live in fly-go's `MachinePresets`, which this change leaves alone, so they are filtered out of `vm-sizes` here rather than deleted. `--vm-size a100-40gb` still resolves to a guest and gets rejected by the API, which is the intended degradation.
1 parent d87dfac commit dc61caa

7 files changed

Lines changed: 77 additions & 164 deletions

File tree

internal/command/mcp/launch.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ func runLaunch(ctx context.Context) error {
287287
args = append(args, "--vm-cpus", fmt.Sprintf("%d", vmCpus))
288288
}
289289

290+
// Forwarded so that `fly launch` rejects them, rather than dropping a
291+
// GPU request on the floor and quietly launching a CPU machine.
290292
if vmGpuKind := flag.GetString(ctx, "vm-gpu-kind"); vmGpuKind != "" {
291293
args = append(args, "--vm-gpu-kind", vmGpuKind)
292294
}

internal/command/mcp/server/machine.go

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,6 @@ var MachineCommands = []FlyCommand{
7676
Required: false,
7777
Type: "number",
7878
},
79-
"vm-gpu-kind": {
80-
Description: "If set, the GPU model to attach",
81-
Required: false,
82-
Type: "enum",
83-
Enum: []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
84-
},
85-
"vm-gpus": {
86-
Description: "The number of GPUs to use for the new machine",
87-
Required: false,
88-
Type: "number",
89-
},
9079
"vm-memory": {
9180
Description: "The amount of memory (in megabytes) to use for the new machine",
9281
Required: false,
@@ -172,14 +161,6 @@ var MachineCommands = []FlyCommand{
172161
cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
173162
}
174163

175-
if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
176-
cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
177-
}
178-
179-
if vmGpus, ok := args["vm-gpus"]; ok {
180-
cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
181-
}
182-
183164
if vmMemory, ok := args["vm-memory"]; ok {
184165
cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
185166
}
@@ -348,17 +329,6 @@ var MachineCommands = []FlyCommand{
348329
Required: false,
349330
Type: "number",
350331
},
351-
"vm-gpu-kind": {
352-
Description: "If set, the GPU model to attach",
353-
Required: false,
354-
Type: "enum",
355-
Enum: []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
356-
},
357-
"vm-gpus": {
358-
Description: "The number of GPUs to use for the new machine",
359-
Required: false,
360-
Type: "number",
361-
},
362332
"vm-memory": {
363333
Description: "The amount of memory (in megabytes) to use for the new machine",
364334
Required: false,
@@ -483,14 +453,6 @@ var MachineCommands = []FlyCommand{
483453
cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
484454
}
485455

486-
if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
487-
cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
488-
}
489-
490-
if vmGpus, ok := args["vm-gpus"]; ok {
491-
cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
492-
}
493-
494456
if vmMemory, ok := args["vm-memory"]; ok {
495457
cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
496458
}
@@ -1030,17 +992,6 @@ var MachineCommands = []FlyCommand{
1030992
Required: false,
1031993
Type: "number",
1032994
},
1033-
"vm-gpu-kind": {
1034-
Description: "If set, the GPU model to attach",
1035-
Required: false,
1036-
Type: "enum",
1037-
Enum: []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
1038-
},
1039-
"vm-gpus": {
1040-
Description: "The number of GPUs to use for the new machine",
1041-
Required: false,
1042-
Type: "number",
1043-
},
1044995
"vm-memory": {
1045996
Description: "The amount of memory (in megabytes) to use for the new machine",
1046997
Required: false,
@@ -1175,14 +1126,6 @@ var MachineCommands = []FlyCommand{
11751126
cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
11761127
}
11771128

1178-
if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
1179-
cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
1180-
}
1181-
1182-
if vmGpus, ok := args["vm-gpus"]; ok {
1183-
cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
1184-
}
1185-
11861129
if vmMemory, ok := args["vm-memory"]; ok {
11871130
cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
11881131
}
@@ -1516,17 +1459,6 @@ var MachineCommands = []FlyCommand{
15161459
Required: false,
15171460
Type: "number",
15181461
},
1519-
"vm-gpu-kind": {
1520-
Description: "If set, the GPU model to attach",
1521-
Required: false,
1522-
Type: "enum",
1523-
Enum: []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
1524-
},
1525-
"vm-gpus": {
1526-
Description: "The number of GPUs to use for the new machine",
1527-
Required: false,
1528-
Type: "number",
1529-
},
15301462
"vm-memory": {
15311463
Description: "The amount of memory (in megabytes) to use for the new machine",
15321464
Required: false,
@@ -1643,14 +1575,6 @@ var MachineCommands = []FlyCommand{
16431575
cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
16441576
}
16451577

1646-
if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
1647-
cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
1648-
}
1649-
1650-
if vmGpus, ok := args["vm-gpus"]; ok {
1651-
cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
1652-
}
1653-
16541578
if vmMemory, ok := args["vm-memory"]; ok {
16551579
cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
16561580
}

internal/command/platform/vmsizes.go

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,19 @@ func runMachineVMSizes(ctx context.Context) error {
4343
strings []string
4444
}
4545

46-
sortedPresets := lo.MapToSlice(fly.MachinePresets, func(key string, value *fly.MachineGuest) preset {
46+
// GPU presets are still in fly-go, but GPU machines are no longer offered.
47+
sortedPresets := lo.FilterMap(lo.Entries(fly.MachinePresets), func(e lo.Entry[string, *fly.MachineGuest], _ int) (preset, bool) {
48+
if e.Value.GPUKind != "" {
49+
return preset{}, false
50+
}
51+
4752
arr := []string{
48-
key,
49-
cores(value.CPUs),
50-
memory(value.MemoryMB),
51-
value.GPUKind,
53+
e.Key,
54+
cores(e.Value.CPUs),
55+
memory(e.Value.MemoryMB),
5256
}
5357

54-
return preset{value, arr}
58+
return preset{e.Value, arr}, true
5559
})
5660

5761
sort.Slice(sortedPresets, func(i, j int) bool {
@@ -60,10 +64,8 @@ func runMachineVMSizes(ctx context.Context) error {
6064
switch {
6165
case a.CPUs != b.CPUs:
6266
return a.CPUs < b.CPUs
63-
case a.MemoryMB != b.MemoryMB:
64-
return a.MemoryMB < b.MemoryMB
6567
default:
66-
return a.GPUKind < b.GPUKind
68+
return a.MemoryMB < b.MemoryMB
6769
}
6870
})
6971

@@ -78,26 +80,18 @@ func runMachineVMSizes(ctx context.Context) error {
7880

7981
// Filter and display shared cpu sizes.
8082
shared := lo.FilterMap(sortedPresets, func(p preset, _ int) ([]string, bool) {
81-
return p.strings, p.guest.CPUKind == "shared" && p.guest.GPUKind == ""
83+
return p.strings, p.guest.CPUKind == "shared"
8284
})
8385
if err := render.Table(out, "Machines platform", shared, "Name", "CPU Cores", "Memory"); err != nil {
8486
return err
8587
}
8688

8789
// Filter and display performance cpu sizes.
8890
performance := lo.FilterMap(sortedPresets, func(p preset, _ int) ([]string, bool) {
89-
return p.strings, p.guest.CPUKind == "performance" && p.guest.GPUKind == ""
90-
})
91-
if err := render.Table(out, "", performance, "Name", "CPU Cores", "Memory"); err != nil {
92-
return err
93-
}
94-
95-
// Filter and display gpu sizes.
96-
gpus := lo.FilterMap(sortedPresets, func(p preset, _ int) ([]string, bool) {
97-
return p.strings, p.guest.GPUKind != ""
91+
return p.strings, p.guest.CPUKind == "performance"
9892
})
9993

100-
return render.Table(out, "", gpus, "Name", "CPU Cores", "Memory", "GPU model")
94+
return render.Table(out, "", performance, "Name", "CPU Cores", "Memory")
10195
}
10296

10397
func cores(cores int) string {

internal/flag/machines.go

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,19 @@ package flag
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
6-
"slices"
7-
"strings"
87

98
"github.com/docker/go-units"
10-
"github.com/samber/lo"
119
fly "github.com/superfly/fly-go"
1210
"github.com/superfly/flyctl/helpers"
1311
)
1412

15-
var (
16-
validGPUKinds = []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"}
17-
gpuKindAliases = map[string]string{
18-
"a100-40gb": "a100-pcie-40gb",
19-
"a100-80gb": "a100-sxm4-80gb",
20-
}
21-
)
22-
2313
// Returns a MachineGuest based on the flags provided overwriting a default VM
2414
func GetMachineGuest(ctx context.Context, guest *fly.MachineGuest) (*fly.MachineGuest, error) {
25-
defaultVMSize := fly.DefaultVMSize
26-
if IsSpecified(ctx, "vm-gpu-kind") {
27-
defaultVMSize = fly.DefaultGPUVMSize
28-
}
29-
3015
if guest == nil {
3116
guest = &fly.MachineGuest{}
32-
guest.SetSize(defaultVMSize)
17+
guest.SetSize(fly.DefaultVMSize)
3318
}
3419

3520
if IsSpecified(ctx, "vm-size") {
@@ -78,33 +63,8 @@ func GetMachineGuest(ctx context.Context, guest *fly.MachineGuest) (*fly.Machine
7863
}
7964
}
8065

81-
if IsSpecified(ctx, "vm-gpu-kind") {
82-
m := GetString(ctx, "vm-gpu-kind")
83-
m = lo.ValueOr(gpuKindAliases, m, m)
84-
if !slices.Contains(validGPUKinds, m) {
85-
return nil, fmt.Errorf("--vm-gpu-kind must be set to one of: %v", strings.Join(validGPUKinds, ", "))
86-
}
87-
if m == "none" {
88-
guest.GPUs = 0
89-
guest.GPUKind = ""
90-
} else {
91-
guest.GPUKind = m
92-
if guest.GPUs == 0 {
93-
guest.GPUs = 1
94-
}
95-
}
96-
}
97-
98-
if IsSpecified(ctx, "vm-gpus") {
99-
guest.GPUs = GetInt(ctx, "vm-gpus")
100-
switch {
101-
case guest.GPUKind != "" && guest.GPUs == 0:
102-
return nil, fmt.Errorf("--vm-gpus must be greater than zero, got: %d", guest.GPUs)
103-
case guest.GPUKind == "" && guest.GPUs > 0:
104-
return nil, fmt.Errorf("--vm-gpus requires a GPU Model to be set, pass --vm-gpu-kind=X where X is one of: %v", strings.Join(validGPUKinds, ", "))
105-
case guest.GPUs < 0:
106-
return nil, fmt.Errorf("--vm-gpus must be greater than or equal to zero, got: %d", guest.GPUs)
107-
}
66+
if IsSpecified(ctx, "vm-gpu-kind") || IsSpecified(ctx, "vm-gpus") {
67+
return nil, errors.New("GPU machines are no longer supported: --vm-gpu-kind and --vm-gpus are no longer accepted")
10868
}
10969

11070
if IsSpecified(ctx, "host-dedication-id") {
@@ -139,14 +99,18 @@ var VMSizeFlags = Set{
13999
Description: "Maximum memory (in megabytes) to allow for the VM",
140100
Hidden: true,
141101
},
102+
// GPU machines are no longer supported. Both flags are kept so that
103+
// passing one fails with an explanation rather than "unknown flag".
142104
Int{
143105
Name: "vm-gpus",
144-
Description: "Number of GPUs. Must also choose the GPU model with --vm-gpu-kind flag",
106+
Description: "GPU machines are no longer supported",
107+
Hidden: true,
145108
},
146109
String{
147110
Name: "vm-gpu-kind",
148-
Description: fmt.Sprintf("If set, the GPU model to attach (%v) (also --vm-gpukind)", strings.Join(validGPUKinds, ", ")),
111+
Description: "GPU machines are no longer supported",
149112
Aliases: []string{"vm-gpukind"},
113+
Hidden: true,
150114
},
151115
String{
152116
Name: "host-dedication-id",

internal/flag/machines_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package flag
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/spf13/cobra"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
"github.com/superfly/flyctl/internal/cmdutil/preparers"
11+
)
12+
13+
func ctxWithFlags(t *testing.T, args ...string) context.Context {
14+
t.Helper()
15+
16+
cmd := &cobra.Command{Use: "test"}
17+
VMSizeFlags.addTo(cmd)
18+
19+
fs := cmd.Flags()
20+
require.NoError(t, fs.Parse(args))
21+
22+
// Aliases only resolve onto their main flag once this preparer has run.
23+
ctx, err := preparers.ApplyAliases(NewContext(context.Background(), fs))
24+
require.NoError(t, err)
25+
26+
return ctx
27+
}
28+
29+
func TestGetMachineGuestRejectsGPUFlags(t *testing.T) {
30+
for _, args := range [][]string{
31+
{"--vm-gpu-kind", "l40s"},
32+
{"--vm-gpukind", "l40s"},
33+
{"--vm-gpus", "1"},
34+
} {
35+
_, err := GetMachineGuest(ctxWithFlags(t, args...), nil)
36+
assert.ErrorContains(t, err, "GPU machines are no longer supported", "for %v", args)
37+
}
38+
}
39+
40+
func TestGetMachineGuestWithoutGPUFlags(t *testing.T) {
41+
guest, err := GetMachineGuest(ctxWithFlags(t, "--vm-cpus", "2"), nil)
42+
require.NoError(t, err)
43+
assert.Equal(t, 2, guest.CPUs)
44+
}

test/preflight/apps_v2_integration_test.go

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -502,27 +502,16 @@ func TestErrOutput(t *testing.T) {
502502
res = f.FlyAllowExitFailure("machine update --vm-memory 10 %s --yes", firstMachine.ID)
503503
require.Contains(f, res.StdErrString(), "invalid memory size")
504504

505-
// This should fail on GPU machines because they're performance VMs.
506-
if f.IsGpuMachine() {
507-
res = f.FlyAllowExitFailure("machine update --vm-cpus 4 %s --vm-memory 2048 --yes", firstMachine.ID)
508-
require.Contains(f, res.StdErrString(), "memory size for config is too low")
509-
} else {
510-
f.Fly("machine update --vm-cpus 4 %s --vm-memory 2048 --yes", firstMachine.ID)
511-
}
505+
f.Fly("machine update --vm-cpus 4 %s --vm-memory 2048 --yes", firstMachine.ID)
512506

513-
// Not applicable for GPU machines since this size is too small.
514-
if !f.IsGpuMachine() {
515-
res = f.FlyAllowExitFailure("machine update --vm-memory 256 %s --yes", firstMachine.ID)
516-
require.Contains(f, res.StdErrString(), "memory size for config is too low")
517-
}
507+
res = f.FlyAllowExitFailure("machine update --vm-memory 256 %s --yes", firstMachine.ID)
508+
require.Contains(f, res.StdErrString(), "memory size for config is too low")
518509

519-
if !f.IsGpuMachine() {
520-
res = f.FlyAllowExitFailure("machine update --vm-memory 16384 %s --yes", firstMachine.ID)
521-
require.Contains(f, res.StdErrString(), "memory size for config is too high")
510+
res = f.FlyAllowExitFailure("machine update --vm-memory 16384 %s --yes", firstMachine.ID)
511+
require.Contains(f, res.StdErrString(), "memory size for config is too high")
522512

523-
res = f.FlyAllowExitFailure("machine update -a %s %s -y --wait-timeout 1 --vm-size performance-1x", appName, firstMachine.ID)
524-
require.Contains(f, res.StdErrString(), "timeout reached waiting for machine's state to change")
525-
}
513+
res = f.FlyAllowExitFailure("machine update -a %s %s -y --wait-timeout 1 --vm-size performance-1x", appName, firstMachine.ID)
514+
require.Contains(f, res.StdErrString(), "timeout reached waiting for machine's state to change")
526515
}
527516

528517
func TestImageLabel(t *testing.T) {

test/preflight/testlib/test_env.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,3 @@ func (f *FlyctlTestEnv) Skipped() bool {
473473
func (f *FlyctlTestEnv) TempDir() string {
474474
return f.t.TempDir()
475475
}
476-
477-
func (f *FlyctlTestEnv) IsGpuMachine() bool {
478-
return strings.Contains(f.VMSize, "a10") || strings.Contains(f.VMSize, "l40s")
479-
}

0 commit comments

Comments
 (0)