Skip to content

Commit cc3c2f2

Browse files
committed
Convert limayaml.VMType to an abstract map
The format of the VMOpts is known only to the driver, everyone else will see a basic map[string]any or something similar to it. Converting from the abstract format to the actual format is done using YAML, just like it was before when the format was known. Signed-off-by: Anders F Björklund <[email protected]>
1 parent e2f09da commit cc3c2f2

File tree

11 files changed

+228
-49
lines changed

11 files changed

+228
-49
lines changed

pkg/driver/qemu/qemu.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,13 @@ func defaultCPUType() limatype.CPUType {
449449
func resolveCPUType(y *limatype.LimaYAML) string {
450450
cpuType := defaultCPUType()
451451
var overrideCPUType bool
452-
for k, v := range y.VMOpts.QEMU.CPUType {
452+
var qemuOpts limatype.QEMUOpts
453+
if y.VMOpts[limatype.QEMU] != nil {
454+
if err := limayaml.Convert(y.VMOpts[limatype.QEMU], &qemuOpts, "vmOpts.qemu"); err != nil {
455+
logrus.WithError(err).Warnf("Couldn't convert %q", y.VMOpts[limatype.QEMU])
456+
}
457+
}
458+
for k, v := range qemuOpts.CPUType {
453459
if !slices.Contains(limatype.ArchTypes, *y.Arch) {
454460
logrus.Warnf("field `vmOpts.qemu.cpuType` uses unsupported arch %q", k)
455461
continue
@@ -460,7 +466,10 @@ func resolveCPUType(y *limatype.LimaYAML) string {
460466
}
461467
}
462468
if overrideCPUType {
463-
y.VMOpts.QEMU.CPUType = cpuType
469+
qemuOpts.CPUType = cpuType
470+
}
471+
if y.VMOpts[limatype.QEMU] != nil {
472+
y.VMOpts[limatype.QEMU] = qemuOpts
464473
}
465474

466475
return cpuType[*y.Arch]
@@ -490,8 +499,12 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
490499
if version.LessThan(softMin) {
491500
logrus.Warnf("QEMU %v is too old, %v or later is recommended", version, softMin)
492501
}
493-
if y.VMOpts.QEMU.MinimumVersion != nil && version.LessThan(*semver.New(*y.VMOpts.QEMU.MinimumVersion)) {
494-
logrus.Fatalf("QEMU %v is too old, template requires %q or later", version, *y.VMOpts.QEMU.MinimumVersion)
502+
var qemuOpts limatype.QEMUOpts
503+
if err := limayaml.Convert(y.VMOpts[limatype.QEMU], &qemuOpts, "vmOpts.qemu"); err != nil {
504+
logrus.WithError(err).Warnf("Couldn't convert %q", y.VMOpts[limatype.QEMU])
505+
}
506+
if qemuOpts.MinimumVersion != nil && version.LessThan(*semver.New(*qemuOpts.MinimumVersion)) {
507+
logrus.Fatalf("QEMU %v is too old, template requires %q or later", version, *qemuOpts.MinimumVersion)
495508
}
496509
}
497510

pkg/driver/qemu/qemu_driver.go

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,15 @@ func validateConfig(ctx context.Context, cfg *limatype.LimaYAML) error {
110110
}
111111
}
112112

113-
if cfg.VMOpts.QEMU.MinimumVersion != nil {
114-
if _, err := semver.NewVersion(*cfg.VMOpts.QEMU.MinimumVersion); err != nil {
115-
return fmt.Errorf("field `vmOpts.qemu.minimumVersion` must be a semvar value, got %q: %w", *cfg.VMOpts.QEMU.MinimumVersion, err)
113+
if cfg.VMOpts[limatype.QEMU] != nil {
114+
var qemuOpts limatype.QEMUOpts
115+
if err := limayaml.Convert(cfg.VMOpts[limatype.QEMU], &qemuOpts, "vmOpts.qemu"); err != nil {
116+
return err
117+
}
118+
if qemuOpts.MinimumVersion != nil {
119+
if _, err := semver.NewVersion(*qemuOpts.MinimumVersion); err != nil {
120+
return fmt.Errorf("field `vmOpts.qemu.minimumVersion` must be a semvar value, got %q: %w", *qemuOpts.MinimumVersion, err)
121+
}
116122
}
117123
}
118124

@@ -146,25 +152,32 @@ func (l *LimaQemuDriver) FillConfig(ctx context.Context, cfg *limatype.LimaYAML,
146152
cfg.Video.VNC.Display = ptr.Of("127.0.0.1:0,to=9")
147153
}
148154

149-
if cfg.VMOpts.QEMU.CPUType == nil {
150-
cfg.VMOpts.QEMU.CPUType = limatype.CPUType{}
155+
if cfg.VMOpts == nil {
156+
cfg.VMOpts = limatype.VMOpts{}
151157
}
152-
153-
//nolint:staticcheck // Migration of top-level CPUTYPE if specified
154-
if len(cfg.CPUType) > 0 {
155-
logrus.Warn("The top-level `cpuType` field is deprecated and will be removed in a future release. Please migrate to `vmOpts.qemu.cpuType`.")
156-
for arch, v := range cfg.CPUType {
157-
if v == "" {
158-
continue
159-
}
160-
if existing, ok := cfg.VMOpts.QEMU.CPUType[arch]; ok && existing != "" && existing != v {
161-
logrus.Warnf("Conflicting cpuType for arch %q: top-level=%q, vmOpts.qemu=%q; using vmOpts.qemu value", arch, v, existing)
162-
continue
163-
}
164-
cfg.VMOpts.QEMU.CPUType[arch] = v
158+
var qemuOpts limatype.QEMUOpts
159+
if err := limayaml.Convert(cfg.VMOpts[limatype.QEMU], &qemuOpts, "vmOpts.qemu"); err != nil {
160+
logrus.WithError(err).Warnf("Couldn't convert %q", cfg.VMOpts[limatype.QEMU])
161+
}
162+
if qemuOpts.CPUType == nil {
163+
qemuOpts.CPUType = limatype.CPUType{}
164+
}
165+
//nolint:staticcheck // Migration of top-level CPUType if specified
166+
for arch, v := range cfg.CPUType {
167+
if v == "" {
168+
continue
165169
}
166-
cfg.CPUType = nil
170+
if existing, ok := qemuOpts.CPUType[arch]; ok && existing != "" && existing != v {
171+
logrus.Warnf("Conflicting cpuType for arch %q: top-level=%q, vmOpts.qemu=%q; using vmOpts.qemu value", arch, v, existing)
172+
continue
173+
}
174+
qemuOpts.CPUType[arch] = v
175+
}
176+
var opts any
177+
if err := limayaml.Convert(qemuOpts, &opts, ""); err != nil {
178+
logrus.WithError(err).Warnf("Couldn't convert %+v", qemuOpts)
167179
}
180+
cfg.VMOpts[limatype.QEMU] = opts
168181

169182
mountTypesUnsupported := make(map[string]struct{})
170183
for _, f := range cfg.MountTypesUnsupported {

pkg/driver/vz/vm_darwin.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,14 @@ func attachFolderMounts(inst *limatype.Instance, vmConfig *vz.VirtualMachineConf
583583
}
584584
}
585585

586-
if *inst.Config.VMOpts.VZ.Rosetta.Enabled {
586+
var vzOpts limatype.VZOpts
587+
if inst.Config.VMOpts[limatype.VZ] != nil {
588+
if err := limayaml.Convert(inst.Config.VMOpts[limatype.VZ], &vzOpts, "vmOpts.vz"); err != nil {
589+
logrus.WithError(err).Warnf("Couldn't convert %q", inst.Config.VMOpts[limatype.VZ])
590+
}
591+
}
592+
593+
if vzOpts.Rosetta.Enabled != nil && *vzOpts.Rosetta.Enabled {
587594
logrus.Info("Setting up Rosetta share")
588595
directorySharingDeviceConfig, err := createRosettaDirectoryShareConfiguration()
589596
if err != nil {

pkg/driver/vz/vz_driver_darwin.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,20 @@ func (l *LimaVzDriver) Configure(inst *limatype.Instance) *driver.ConfiguredDriv
108108
}
109109
}
110110

111+
var vzOpts limatype.VZOpts
112+
if l.Instance.Config.VMOpts[limatype.VZ] != nil {
113+
if err := limayaml.Convert(l.Instance.Config.VMOpts[limatype.VZ], &vzOpts, "vmOpts.vz"); err != nil {
114+
logrus.WithError(err).Warnf("Couldn't convert %q", l.Instance.Config.VMOpts[limatype.VZ])
115+
}
116+
}
117+
111118
if runtime.GOOS == "darwin" && limayaml.IsNativeArch(limatype.AARCH64) {
112-
if l.Instance.Config.VMOpts.VZ.Rosetta.Enabled != nil {
113-
l.rosettaEnabled = *l.Instance.Config.VMOpts.VZ.Rosetta.Enabled
119+
if vzOpts.Rosetta.Enabled != nil {
120+
l.rosettaEnabled = *vzOpts.Rosetta.Enabled
114121
}
115122
}
116-
if l.Instance.Config.VMOpts.VZ.Rosetta.BinFmt != nil {
117-
l.rosettaBinFmt = *l.Instance.Config.VMOpts.VZ.Rosetta.BinFmt
123+
if vzOpts.Rosetta.BinFmt != nil {
124+
l.rosettaBinFmt = *vzOpts.Rosetta.BinFmt
118125
}
119126

120127
return &driver.ConfiguredDriver{
@@ -131,22 +138,35 @@ func (l *LimaVzDriver) FillConfig(ctx context.Context, cfg *limatype.LimaYAML, _
131138
cfg.MountType = ptr.Of(limatype.VIRTIOFS)
132139
}
133140

141+
var vzOpts limatype.VZOpts
142+
if cfg.VMOpts[limatype.VZ] != nil {
143+
if err := limayaml.Convert(cfg.VMOpts[limatype.VZ], &vzOpts, "vmOpts.vz"); err != nil {
144+
logrus.WithError(err).Warnf("Couldn't convert %q", cfg.VMOpts[limatype.VZ])
145+
}
146+
}
147+
134148
//nolint:staticcheck // Migration of top-level Rosetta if specified
135-
if (cfg.VMOpts.VZ.Rosetta.Enabled == nil && cfg.VMOpts.VZ.Rosetta.BinFmt == nil) && (!isEmpty(cfg.Rosetta)) {
149+
if (vzOpts.Rosetta.Enabled == nil && vzOpts.Rosetta.BinFmt == nil) && (!isEmpty(cfg.Rosetta)) {
136150
logrus.Debug("Migrating top-level Rosetta configuration to vmOpts.vz.rosetta")
137-
cfg.VMOpts.VZ.Rosetta = cfg.Rosetta
151+
vzOpts.Rosetta = cfg.Rosetta
138152
}
139153
//nolint:staticcheck // Warning about both top-level and vmOpts.vz.Rosetta being set
140-
if (cfg.VMOpts.VZ.Rosetta.Enabled != nil && cfg.VMOpts.VZ.Rosetta.BinFmt != nil) && (!isEmpty(cfg.Rosetta)) {
154+
if (vzOpts.Rosetta.Enabled != nil && vzOpts.Rosetta.BinFmt != nil) && (!isEmpty(cfg.Rosetta)) {
141155
logrus.Warn("Both top-level 'rosetta' and 'vmOpts.vz.rosetta' are configured. Using vmOpts.vz.rosetta. Top-level 'rosetta' is deprecated.")
142156
}
143157

144-
if cfg.VMOpts.VZ.Rosetta.Enabled == nil {
145-
cfg.VMOpts.VZ.Rosetta.Enabled = ptr.Of(false)
158+
if vzOpts.Rosetta.Enabled == nil {
159+
vzOpts.Rosetta.Enabled = ptr.Of(false)
146160
}
147-
if cfg.VMOpts.VZ.Rosetta.BinFmt == nil {
148-
cfg.VMOpts.VZ.Rosetta.BinFmt = ptr.Of(false)
161+
if vzOpts.Rosetta.BinFmt == nil {
162+
vzOpts.Rosetta.BinFmt = ptr.Of(false)
163+
}
164+
165+
var opts any
166+
if err := limayaml.Convert(vzOpts, &opts, ""); err != nil {
167+
logrus.WithError(err).Warnf("Couldn't convert %+v", vzOpts)
149168
}
169+
cfg.VMOpts[limatype.VZ] = opts
150170

151171
return validateConfig(ctx, cfg)
152172
}

pkg/limatmpl/embed.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/lima-vm/lima/v2/pkg/limatype"
2222
"github.com/lima-vm/lima/v2/pkg/limatype/dirnames"
2323
"github.com/lima-vm/lima/v2/pkg/limatype/filenames"
24+
"github.com/lima-vm/lima/v2/pkg/limayaml"
2425
"github.com/lima-vm/lima/v2/pkg/version/versionutil"
2526
"github.com/lima-vm/lima/v2/pkg/yqutil"
2627
)
@@ -179,12 +180,22 @@ func (tmpl *Template) mergeBase(base *Template) error {
179180
tmpl.copyField(minimumLimaVersion, minimumLimaVersion)
180181
}
181182
}
182-
if tmpl.Config.VMOpts.QEMU.MinimumVersion != nil && base.Config.VMOpts.QEMU.MinimumVersion != nil {
183-
tmplVersion := *semver.New(*tmpl.Config.VMOpts.QEMU.MinimumVersion)
184-
baseVersion := *semver.New(*base.Config.VMOpts.QEMU.MinimumVersion)
185-
if tmplVersion.LessThan(baseVersion) {
186-
const minimumQEMUVersion = "vmOpts.qemu.minimumVersion"
187-
tmpl.copyField(minimumQEMUVersion, minimumQEMUVersion)
183+
if tmpl.Config.VMOpts[limatype.QEMU] != nil && base.Config.VMOpts[limatype.QEMU] != nil {
184+
var tmplOpts limatype.QEMUOpts
185+
if err := limayaml.Convert(tmpl.Config.VMOpts[limatype.QEMU], &tmplOpts, "vmOpts.qemu"); err != nil {
186+
return err
187+
}
188+
var baseOpts limatype.QEMUOpts
189+
if err := limayaml.Convert(base.Config.VMOpts[limatype.QEMU], &baseOpts, "vmOpts.qemu"); err != nil {
190+
return err
191+
}
192+
if tmplOpts.MinimumVersion != nil && baseOpts.MinimumVersion != nil {
193+
tmplVersion := *semver.New(*tmplOpts.MinimumVersion)
194+
baseVersion := *semver.New(*baseOpts.MinimumVersion)
195+
if tmplVersion.LessThan(baseVersion) {
196+
const minimumQEMUVersion = "vmOpts.qemu.minimumVersion"
197+
tmpl.copyField(minimumQEMUVersion, minimumQEMUVersion)
198+
}
188199
}
189200
}
190201
return nil

pkg/limatype/lima_yaml.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type LimaYAML struct {
2020
OS *OS `yaml:"os,omitempty" json:"os,omitempty" jsonschema:"nullable"`
2121
Arch *Arch `yaml:"arch,omitempty" json:"arch,omitempty" jsonschema:"nullable"`
2222
Images []Image `yaml:"images,omitempty" json:"images,omitempty" jsonschema:"nullable"`
23-
// Deprecated: Use VMOpts.Qemu.CPUType instead.
23+
// Deprecated: Use vmOpts.qemu.cpuType instead.
2424
CPUType CPUType `yaml:"cpuType,omitempty" json:"cpuType,omitempty" jsonschema:"nullable"`
2525
CPUs *int `yaml:"cpus,omitempty" json:"cpus,omitempty" jsonschema:"nullable"`
2626
Memory *string `yaml:"memory,omitempty" json:"memory,omitempty" jsonschema:"nullable"` // go-units.RAMInBytes
@@ -51,7 +51,7 @@ type LimaYAML struct {
5151
// `useHostResolver` was deprecated in Lima v0.8.1, removed in Lima v0.14.0. Use `hostResolver.enabled` instead.
5252
PropagateProxyEnv *bool `yaml:"propagateProxyEnv,omitempty" json:"propagateProxyEnv,omitempty" jsonschema:"nullable"`
5353
CACertificates CACertificates `yaml:"caCerts,omitempty" json:"caCerts,omitempty"`
54-
// Deprecated: Use VMOpts.VZ.Rosetta instead.
54+
// Deprecated: Use vmOpts.vz.rosetta instead.
5555
Rosetta Rosetta `yaml:"rosetta,omitempty" json:"rosetta,omitempty"`
5656
Plain *bool `yaml:"plain,omitempty" json:"plain,omitempty" jsonschema:"nullable"`
5757
TimeZone *string `yaml:"timezone,omitempty" json:"timezone,omitempty" jsonschema:"nullable"`
@@ -110,10 +110,7 @@ type User struct {
110110
UID *uint32 `yaml:"uid,omitempty" json:"uid,omitempty" jsonschema:"nullable"`
111111
}
112112

113-
type VMOpts struct {
114-
QEMU QEMUOpts `yaml:"qemu,omitempty" json:"qemu,omitempty"`
115-
VZ VZOpts `yaml:"vz,omitempty" json:"vz,omitempty"`
116-
}
113+
type VMOpts map[VMType]any
117114

118115
type QEMUOpts struct {
119116
MinimumVersion *string `yaml:"minimumVersion,omitempty" json:"minimumVersion,omitempty" jsonschema:"nullable"`

pkg/limayaml/limayaml_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func TestDefaultYAML(t *testing.T) {
5151
y.Images = nil // remove default images
5252
y.Mounts = nil // remove default mounts
5353
y.Base = nil // remove default base templates
54+
y.VMOpts = nil // remove default vmopts mapping
5455
y.MinimumLimaVersion = nil // remove minimum Lima version
5556
y.MountTypesUnsupported = nil // remove default workaround for kernel 6.9-6.11
5657
t.Log(dumpJSON(t, y))

pkg/limayaml/marshal.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,16 @@ func Unmarshal(data []byte, y *limatype.LimaYAML, comment string) error {
8282
}
8383
return nil
8484
}
85+
86+
// Convert converts from x to y, using YAML.
87+
func Convert(x, y any, comment string) error {
88+
b, err := yaml.Marshal(x)
89+
if err != nil {
90+
return err
91+
}
92+
err = yaml.Unmarshal(b, y)
93+
if err != nil {
94+
return fmt.Errorf("failed to unmarshal YAML (%s): %w", comment, err)
95+
}
96+
return nil
97+
}

0 commit comments

Comments
 (0)