Skip to content

Commit ef01c86

Browse files
dangraclaude
andauthored
Add MachineRootfs type with SizeGB field (#206)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent db3fb95 commit ef01c86

File tree

2 files changed

+86
-7
lines changed

2 files changed

+86
-7
lines changed

machine_types.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ func (mpr *MachinePersistRootfs) UnmarshalJSON(raw []byte) error {
414414
return nil
415415
}
416416

417+
type MachineRootfs struct {
418+
Persist MachinePersistRootfs `toml:"persist,omitempty" json:"persist,omitempty" enums:"never,always,restart"`
419+
SizeGB uint64 `toml:"size_gb,omitempty" json:"size_gb,omitempty"`
420+
}
421+
417422
// @description The Machine restart policy defines whether and how flyd restarts a Machine after its main process exits. See https://fly.io/docs/machines/guides-examples/machine-restart-policy/.
418423
type MachineRestart struct {
419424
// * no - Never try to restart a Machine automatically when its main process exits, whether that’s on purpose or on a crash.
@@ -439,13 +444,14 @@ type MachineMount struct {
439444
}
440445

441446
type MachineGuest struct {
442-
CPUKind string `toml:"cpu_kind,omitempty" json:"cpu_kind,omitempty"`
443-
CPUs int `toml:"cpus,omitempty" json:"cpus,omitempty"`
444-
MemoryMB int `toml:"memory_mb,omitempty" json:"memory_mb,omitempty"`
445-
GPUs int `toml:"gpus,omitempty" json:"gpus,omitempty"`
446-
GPUKind string `toml:"gpu_kind,omitempty" json:"gpu_kind,omitempty"`
447-
HostDedicationID string `toml:"host_dedication_id,omitempty" json:"host_dedication_id,omitempty"`
448-
PersistRootfs MachinePersistRootfs `toml:"persist_rootfs,omitempty" json:"persist_rootfs,omitempty" enums:"never,always,restart"`
447+
CPUKind string `toml:"cpu_kind,omitempty" json:"cpu_kind,omitempty"`
448+
CPUs int `toml:"cpus,omitempty" json:"cpus,omitempty"`
449+
MemoryMB int `toml:"memory_mb,omitempty" json:"memory_mb,omitempty"`
450+
GPUs int `toml:"gpus,omitempty" json:"gpus,omitempty"`
451+
GPUKind string `toml:"gpu_kind,omitempty" json:"gpu_kind,omitempty"`
452+
HostDedicationID string `toml:"host_dedication_id,omitempty" json:"host_dedication_id,omitempty"`
453+
// Deprecated: use MachineConfig.Rootfs instead
454+
PersistRootfs MachinePersistRootfs `toml:"persist_rootfs,omitempty" json:"persist_rootfs,omitempty" enums:"never,always,restart"`
449455

450456
KernelArgs []string `toml:"kernel_args,omitempty" json:"kernel_args,omitempty"`
451457
}
@@ -804,6 +810,8 @@ type MachineConfig struct {
804810
// with containers
805811
Volumes []*VolumeConfig `toml:"volumes,omitempty" json:"volumes,omitempty"`
806812

813+
Rootfs *MachineRootfs `toml:"rootfs,omitempty" json:"rootfs,omitempty"`
814+
807815
// Deprecated: use Guest instead
808816
VMSize string `toml:"size,omitempty" json:"size,omitempty"`
809817
// Deprecated: use Service.Autostart instead

machine_types_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,77 @@ func TestMachinePersistRootfsUnmarshalJSON(t *testing.T) {
303303
}
304304
}
305305

306+
func TestMachineRootfsJSON(t *testing.T) {
307+
t.Run("marshal", func(t *testing.T) {
308+
cases := []struct {
309+
name string
310+
input MachineConfig
311+
output string
312+
}{
313+
{
314+
name: "rootfs with persist and size",
315+
input: MachineConfig{Rootfs: &MachineRootfs{Persist: MachinePersistRootfsAlways, SizeGB: 10}},
316+
output: `{"init":{},"rootfs":{"persist":"always","size_gb":10}}`,
317+
},
318+
{
319+
name: "rootfs with persist only",
320+
input: MachineConfig{Rootfs: &MachineRootfs{Persist: MachinePersistRootfsRestart}},
321+
output: `{"init":{},"rootfs":{"persist":"restart"}}`,
322+
},
323+
{
324+
name: "nil rootfs omitted",
325+
input: MachineConfig{},
326+
output: `{"init":{}}`,
327+
},
328+
}
329+
for _, tc := range cases {
330+
b, err := json.Marshal(tc.input)
331+
if err != nil {
332+
t.Errorf("%s: unexpected error: %v", tc.name, err)
333+
} else if string(b) != tc.output {
334+
t.Errorf("%s: got %s, want %s", tc.name, string(b), tc.output)
335+
}
336+
}
337+
})
338+
339+
t.Run("unmarshal", func(t *testing.T) {
340+
cases := []struct {
341+
name string
342+
input string
343+
persist MachinePersistRootfs
344+
sizeGB uint64
345+
}{
346+
{"persist and size", `{"rootfs":{"persist":"always","size_gb":10}}`, MachinePersistRootfsAlways, 10},
347+
{"persist only", `{"rootfs":{"persist":"restart"}}`, MachinePersistRootfsRestart, 0},
348+
{"size only", `{"rootfs":{"size_gb":5}}`, MachinePersistRootfsNone, 5},
349+
{"no rootfs", `{}`, MachinePersistRootfsNone, 0},
350+
}
351+
for _, tc := range cases {
352+
var mc MachineConfig
353+
if err := json.Unmarshal([]byte(tc.input), &mc); err != nil {
354+
t.Errorf("%s: unexpected error: %v", tc.name, err)
355+
continue
356+
}
357+
if tc.persist == MachinePersistRootfsNone && tc.sizeGB == 0 {
358+
if mc.Rootfs != nil {
359+
t.Errorf("%s: expected nil rootfs, got %+v", tc.name, mc.Rootfs)
360+
}
361+
continue
362+
}
363+
if mc.Rootfs == nil {
364+
t.Errorf("%s: expected non-nil rootfs", tc.name)
365+
continue
366+
}
367+
if mc.Rootfs.Persist != tc.persist {
368+
t.Errorf("%s: persist got %v, want %v", tc.name, mc.Rootfs.Persist, tc.persist)
369+
}
370+
if mc.Rootfs.SizeGB != tc.sizeGB {
371+
t.Errorf("%s: size_gb got %d, want %d", tc.name, mc.Rootfs.SizeGB, tc.sizeGB)
372+
}
373+
}
374+
})
375+
}
376+
306377
func TestMachineAutostopUnmarshalJSON(t *testing.T) {
307378
type testcase struct {
308379
input string

0 commit comments

Comments
 (0)