diff --git a/cmd/finch/virtual_machine.go b/cmd/finch/virtual_machine.go index ad2c08091..66371d706 100644 --- a/cmd/finch/virtual_machine.go +++ b/cmd/finch/virtual_machine.go @@ -109,7 +109,7 @@ func virtualMachineCommands( lcc, logger, dependencies(ecc, fc, fp, fs, lcc, logger, fp.FinchDir(finchRootPath)), - config.NewLimaApplier(fc, ecc, fs, fp.LimaOverrideConfigPath(), system.NewStdLib()), + config.NewLimaApplier(fc, ecc, fs, fp.LimaDefaultConfigPath(), fp.LimaOverrideConfigPath(), system.NewStdLib()), config.NewNerdctlApplier( fssh.NewDialer(), fs, diff --git a/cmd/finch/virtual_machine_init.go b/cmd/finch/virtual_machine_init.go index 203fb5b4f..1b64f2309 100644 --- a/cmd/finch/virtual_machine_init.go +++ b/cmd/finch/virtual_machine_init.go @@ -76,16 +76,21 @@ func (iva *initVMAction) run() error { return err } - err = dependency.InstallOptionalDeps(iva.optionalDepGroups, iva.logger) + err = iva.limaConfigApplier.ConfigureDefaultLimaYaml() if err != nil { - iva.logger.Errorf("Dependency error: %v", err) + return err } - err = iva.limaConfigApplier.Apply(true) + err = iva.limaConfigApplier.ConfigureOverrideLimaYaml() if err != nil { return err } + err = dependency.InstallOptionalDeps(iva.optionalDepGroups, iva.logger) + if err != nil { + iva.logger.Errorf("Dependency error: %v", err) + } + // ignore error, this is to ensure that the disk is only mounted once _ = iva.diskManager.DetachUserDataDisk() diff --git a/cmd/finch/virtual_machine_init_test.go b/cmd/finch/virtual_machine_init_test.go index b401f353c..db45ab44d 100644 --- a/cmd/finch/virtual_machine_init_test.go +++ b/cmd/finch/virtual_machine_init_test.go @@ -72,7 +72,8 @@ func TestInitVMAction_runAdapter(t *testing.T) { logger.EXPECT().Debugf("Status of virtual machine: %s", "") command := mocks.NewCommand(ctrl) - lca.EXPECT().Apply(true).Return(nil) + lca.EXPECT().ConfigureDefaultLimaYaml().Return(nil) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) dm.EXPECT().DetachUserDataDisk().Return(nil) dm.EXPECT().EnsureUserDataDisk().Return(nil) lcc.EXPECT().CreateWithoutStdio("start", fmt.Sprintf("--name=%s", limaInstanceName), @@ -137,7 +138,8 @@ func TestInitVMAction_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte(""), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "") - lca.EXPECT().Apply(true).Return(nil) + lca.EXPECT().ConfigureDefaultLimaYaml().Return(nil) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) dm.EXPECT().DetachUserDataDisk().Return(nil) dm.EXPECT().EnsureUserDataDisk().Return(nil) @@ -228,11 +230,10 @@ func TestInitVMAction_run(t *testing.T) { }, }, { - // TODO: split this test case up: // should succeed even if some optional dependencies fail to be installed // return an error if Lima config fails to be applied - name: "should print out error if InstallOptionalDeps fails and return error if LoadAndApplyLimaConfig fails", - wantErr: errors.New("load config fails"), + name: "should print out error if InstallOptionalDeps fails", + wantErr: nil, groups: func(ctrl *gomock.Controller) []*dependency.Group { dep := mocks.NewDependency(ctrl) deps := dependency.NewGroup([]dependency.Dependency{dep}, "", "mock_error_msg") @@ -248,7 +249,7 @@ func TestInitVMAction_run(t *testing.T) { lcc *mocks.LimaCmdCreator, logger *mocks.Logger, lca *mocks.LimaConfigApplier, - _ *mocks.UserDataDiskManager, + dm *mocks.UserDataDiskManager, ctrl *gomock.Controller, ) { getVMStatusC := mocks.NewCommand(ctrl) @@ -256,14 +257,50 @@ func TestInitVMAction_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte(""), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "") - lca.EXPECT().Apply(true).Return(errors.New("load config fails")) + lca.EXPECT().ConfigureDefaultLimaYaml().Return(nil) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) + logger.EXPECT().Errorf("Dependency error: %v", fmt.Errorf("failed to install dependencies: %w", errors.Join(fmt.Errorf("%s: %w", "mock_error_msg", errors.Join(errors.New("dependency error occurs")))), ), ) + dm.EXPECT().DetachUserDataDisk().Return(nil) + dm.EXPECT().EnsureUserDataDisk().Return(nil) + + command := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("start", fmt.Sprintf("--name=%s", limaInstanceName), + mockBaseYamlFilePath, "--tty=false").Return(command) + command.EXPECT().CombinedOutput() + + logger.EXPECT().Info("Initializing and starting Finch virtual machine...") + logger.EXPECT().Info("Finch virtual machine started successfully") }, }, + { + // should succeed even if some optional dependencies fail to be installed + // return an error if Lima config fails to be applied + name: "return error if LoadAndApplyLimaConfig fails", + wantErr: errors.New("load config fails"), + groups: func(_ *gomock.Controller) []*dependency.Group { + return nil + }, + mockSvc: func( + lcc *mocks.LimaCmdCreator, + logger *mocks.Logger, + lca *mocks.LimaConfigApplier, + _ *mocks.UserDataDiskManager, + ctrl *gomock.Controller, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte(""), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "") + + lca.EXPECT().ConfigureDefaultLimaYaml().Return(errors.New("load config fails")) + }, + }, + { name: "should print error if instance fails to initialize", wantErr: errors.New("failed to init instance"), @@ -282,7 +319,8 @@ func TestInitVMAction_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte(""), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "") - lca.EXPECT().Apply(true).Return(nil) + lca.EXPECT().ConfigureDefaultLimaYaml().Return(nil) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) dm.EXPECT().DetachUserDataDisk().Return(nil) dm.EXPECT().EnsureUserDataDisk().Return(nil) diff --git a/cmd/finch/virtual_machine_start.go b/cmd/finch/virtual_machine_start.go index 27260d0ff..a1a9d6b11 100644 --- a/cmd/finch/virtual_machine_start.go +++ b/cmd/finch/virtual_machine_start.go @@ -74,7 +74,7 @@ func (sva *startVMAction) run() error { sva.logger.Errorf("Dependency error: %v", err) } - err = sva.limaConfigApplier.Apply(false) + err = sva.limaConfigApplier.ConfigureOverrideLimaYaml() if err != nil { return err } diff --git a/cmd/finch/virtual_machine_start_test.go b/cmd/finch/virtual_machine_start_test.go index 5d841a092..f7e0ce5c3 100644 --- a/cmd/finch/virtual_machine_start_test.go +++ b/cmd/finch/virtual_machine_start_test.go @@ -71,7 +71,7 @@ func TestStartVMAction_runAdapter(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Stopped"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Stopped") - lca.EXPECT().Apply(false).Return(nil) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) dm.EXPECT().EnsureUserDataDisk().Return(nil) @@ -146,7 +146,7 @@ func TestStartVMAction_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Stopped"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Stopped") - lca.EXPECT().Apply(false).Return(nil) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) dm.EXPECT().EnsureUserDataDisk().Return(nil) @@ -238,8 +238,31 @@ func TestStartVMAction_run(t *testing.T) { // TODO: split this test case up: // should succeed even if some optional dependencies fail to be installed // return an error if Lima config fails to be applied - name: "should print out error if InstallOptionalDeps fails and return error if LoadAndApplyLimaConfig fails", + name: "should return error if LoadAndApplyLimaConfig fails", wantErr: errors.New("load config fails"), + groups: func(_ *gomock.Controller) []*dependency.Group { + return nil + }, + mockSvc: func( + lcc *mocks.LimaCmdCreator, + logger *mocks.Logger, + lca *mocks.LimaConfigApplier, + _ *mocks.UserDataDiskManager, + ctrl *gomock.Controller, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Stopped"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Stopped") + + lca.EXPECT().ConfigureOverrideLimaYaml().Return(errors.New("load config fails")) + }, + }, + { + // should succeed even if some optional dependencies fail to be installed + // return an error if Lima config fails to be applied + name: "should print out error if InstallOptionalDeps fails", + wantErr: nil, groups: func(ctrl *gomock.Controller) []*dependency.Group { dep := mocks.NewDependency(ctrl) deps := dependency.NewGroup([]dependency.Dependency{dep}, "", "mock_error_msg") @@ -255,7 +278,7 @@ func TestStartVMAction_run(t *testing.T) { lcc *mocks.LimaCmdCreator, logger *mocks.Logger, lca *mocks.LimaConfigApplier, - _ *mocks.UserDataDiskManager, + dm *mocks.UserDataDiskManager, ctrl *gomock.Controller, ) { getVMStatusC := mocks.NewCommand(ctrl) @@ -263,7 +286,16 @@ func TestStartVMAction_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Stopped"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Stopped") - lca.EXPECT().Apply(false).Return(errors.New("load config fails")) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) + + dm.EXPECT().EnsureUserDataDisk().Return(nil) + + command := mocks.NewCommand(ctrl) + command.EXPECT().CombinedOutput() + lcc.EXPECT().CreateWithoutStdio("start", limaInstanceName).Return(command) + + logger.EXPECT().Info("Starting existing Finch virtual machine...") + logger.EXPECT().Info("Finch virtual machine started successfully") logger.EXPECT().Errorf("Dependency error: %v", fmt.Errorf("failed to install dependencies: %w", @@ -296,7 +328,7 @@ func TestStartVMAction_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Stopped"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Stopped") - lca.EXPECT().Apply(false).Return(nil) + lca.EXPECT().ConfigureOverrideLimaYaml().Return(nil) dm.EXPECT().EnsureUserDataDisk().Return(nil) diff --git a/docs/design/config_to_support_additional_directories.md b/docs/design/config_to_support_additional_directories.md index 456c88793..fdfa2f201 100644 --- a/docs/design/config_to_support_additional_directories.md +++ b/docs/design/config_to_support_additional_directories.md @@ -6,7 +6,7 @@ ## Approach -The [finch.yaml](https://github.com/runfinch/finch/blob/d8174ff773f0f92ec94d6d97c753a872a98f74a0/finch.yaml#L35) file which is used to boot in Lima has Mounts field to handle the mount points. However, changing it in finch.yaml would make the configs only applied in `vm init`, and finch.yaml is expected to be the place to keep Finch's default config without being messed up with user's customized configs. So instead of adding to finch.yaml, I recommended adding additional_directories to Lima’s override.yaml file. Both `vm init` and `vm start` can apply the configs in override.yaml. This is same to how Finch applies cpu and memory configs today. +The [finch.yaml](https://github.com/runfinch/finch/blob/d8174ff773f0f92ec94d6d97c753a872a98f74a0/finch.yaml#L35) file which is used to boot in Lima has Mounts field to handle the mount points. Mount Points added in finch.yaml will configure override.yaml on `vm init` and `vm start`. For example, for Finch config: @@ -36,8 +36,6 @@ sshfs: protocolVersion: 9p2000.L msize: 128KiB cache: mmap -networks: -- lima: finch-shared ``` Different to cpu and memory, the “mounts” field in override.yaml will be appended to the default mounts instead of replacing it. So we don’t have to add the default home directory to the override.yaml file. [Reference](https://github.com/lima-vm/lima/blob/585d6e25af62d0337cec83ffca226a2c8146a428/pkg/limayaml/defaults.go#L410) diff --git a/e2e/vm/additional_disk_test.go b/e2e/vm/additional_disk_test.go index 90330a7ed..6e45ead74 100644 --- a/e2e/vm/additional_disk_test.go +++ b/e2e/vm/additional_disk_test.go @@ -23,7 +23,7 @@ const ( var testAdditionalDisk = func(o *option.Option, installed bool) { ginkgo.Describe("Additional disk", ginkgo.Serial, func() { ginkgo.It("Retains container user data after the VM is deleted", func() { - resetVM(o, installed) + resetVM(o) resetDisks(o, installed) command.New(o, virtualMachineRootCmd, "init").WithoutCheckingExitCode().WithTimeoutInSeconds(160).Run() command.Run(o, "volume", "create", volumeName) diff --git a/e2e/vm/config_darwin_test.go b/e2e/vm/config_darwin_test.go index de26081ed..c9e1bebb5 100644 --- a/e2e/vm/config_darwin_test.go +++ b/e2e/vm/config_darwin_test.go @@ -6,6 +6,7 @@ package vm import ( "os" + "os/exec" "path/filepath" "runtime" @@ -16,12 +17,25 @@ import ( "github.com/runfinch/common-tests/option" "gopkg.in/yaml.v3" + "github.com/runfinch/finch/e2e" finch_cmd "github.com/runfinch/finch/pkg/command" "github.com/runfinch/finch/pkg/config" ) var finchConfigFilePath = os.Getenv("HOME") + "/.finch/finch.yaml" +func limaDataDirPath(installed bool) string { + limaConfigFilePath := defaultLimaDataDirPath + if installed { + path, err := exec.LookPath(e2e.InstalledTestSubject) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + realFinchPath, err := filepath.EvalSymlinks(path) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + limaConfigFilePath = filepath.Join(realFinchPath, "..", "..", "lima", "data") + } + return limaConfigFilePath +} + var testConfig = func(o *option.Option, installed bool) { ginkgo.Describe("Config (after init)", ginkgo.Serial, func() { ginkgo.It("updates init-only config values when values are changed after init", func() { @@ -31,14 +45,15 @@ var testConfig = func(o *option.Option, installed bool) { ginkgo.Skip("Skipping because existing init only configuration options require Virtualization.framework support to test") } - limaConfigFilePath := resetVM(o, installed) + resetVM(o) resetDisks(o, installed) writeFile(finchConfigFilePath, []byte("memory: 4GiB\ncpus: 6\nvmType: vz\nrosetta: false")) // vm init with VZ set sometimes takes 2 minutes just to convert the disk to raw command.New(o, "vm", "init").WithoutCheckingExitCode().WithTimeoutInSeconds(240).Run() - gomega.Expect(limaConfigFilePath).Should(gomega.BeARegularFile()) - cfgBuf, err := os.ReadFile(filepath.Clean(limaConfigFilePath)) + overrideConfigFilePath := filepath.Join(limaDataDirPath(installed), "_config", "override.yaml") + gomega.Expect(overrideConfigFilePath).Should(gomega.BeARegularFile()) + cfgBuf, err := os.ReadFile(filepath.Clean(overrideConfigFilePath)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) var limaCfg limayaml.LimaYAML @@ -46,6 +61,13 @@ var testConfig = func(o *option.Option, installed bool) { gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(*limaCfg.CPUs).Should(gomega.Equal(6)) gomega.Expect(*limaCfg.Memory).Should(gomega.Equal("4GiB")) + + defaultConfigFilePath := filepath.Join(limaDataDirPath(installed), "_config", "default.yaml") + gomega.Expect(defaultConfigFilePath).Should(gomega.BeARegularFile()) + cfgBuf, err = os.ReadFile(filepath.Clean(defaultConfigFilePath)) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + err = yaml.Unmarshal(cfgBuf, &limaCfg) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(*limaCfg.VMType).Should(gomega.Equal("vz")) gomega.Expect(*limaCfg.Rosetta.Enabled).Should(gomega.Equal(false)) gomega.Expect(*limaCfg.Rosetta.BinFmt).Should(gomega.Equal(false)) diff --git a/e2e/vm/config_test.go b/e2e/vm/config_test.go index bbeed05b9..0ff58dd51 100644 --- a/e2e/vm/config_test.go +++ b/e2e/vm/config_test.go @@ -7,7 +7,6 @@ import ( "errors" "io/fs" "os" - "os/exec" "path/filepath" "time" @@ -19,13 +18,12 @@ import ( "github.com/runfinch/common-tests/option" "github.com/xorcare/pointer" "gopkg.in/yaml.v3" - - "github.com/runfinch/finch/e2e" ) var ( - defaultLimaDataDirPath = filepath.Join("..", "..", "_output/lima/data") - defaultLimaConfigFilePath = filepath.Join(defaultLimaDataDirPath, "_config/override.yaml") + defaultLimaDataDirPath = filepath.Join("..", "..", "_output/lima/data") + defaultLimaConfigFilePath = filepath.Join(defaultLimaDataDirPath, "_config/default.yaml") + overrideLimaConfigFilePath = filepath.Join(defaultLimaDataDirPath, "_config/override.yaml") ) func readFile(filePath string) []byte { @@ -55,32 +53,20 @@ func updateAndApplyConfig(o *option.Option, configBytes []byte) *gexec.Session { // Many test cases only check partial file contents, rather than strictly checking // the exact contents, because other modules can update the same files. // -// For example, pkg/dependency/vde/update_override_lima_config.go's appendNetworkConfiguration function -// updates the lima override.yaml config file, independently of the config file module's function. +// For example, pkg/dependency/vde/update_network_lima_config.go's appendNetworkConfiguration function +// updates the lima default.yaml config file, independently of the config file module's function. // // For simplicity, the cleanup for this test suite currently does not distinguish between an // empty and a non-existent Finch config.yaml. Meaning, if you run this without an existing config.yaml, // an empty config.yaml will be created after all test cases are run. This currently does not change the behavior // of Finch, but may need to be revisited later. -var _ = func(o *option.Option, installed bool) { +var _ = func(o *option.Option) { // These tests are run in serial because we only define one virtual machine instance, and it requires disk I/O. ginkgo.Describe("Config", ginkgo.Serial, func() { - var limaConfigFilePath string ginkgo.BeforeEach(func() { origFinchCfg := readFile(finchConfigFilePath) - limaConfigFilePath = defaultLimaConfigFilePath - if installed { - path, err := exec.LookPath(e2e.InstalledTestSubject) - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - realFinchPath, err := filepath.EvalSymlinks(path) - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - limaConfigFilePath = filepath.Join(realFinchPath, "../../lima/data/_config/override.yaml") - } - origLimaCfg := readFile(limaConfigFilePath) - ginkgo.DeferCleanup(func() { writeFile(finchConfigFilePath, origFinchCfg) - writeFile(limaConfigFilePath, origLimaCfg) command.New(o, virtualMachineRootCmd, "stop").WithoutCheckingExitCode().WithTimeoutInSeconds(90).Run() time.Sleep(1 * time.Second) @@ -92,12 +78,16 @@ var _ = func(o *option.Option, installed bool) { startCmdSession := updateAndApplyConfig(o, []byte("memory: 4GiB\ncpus: 6")) gomega.Expect(startCmdSession).Should(gexec.Exit(0)) - gomega.Expect(limaConfigFilePath).Should(gomega.BeARegularFile()) - cfgBuf, err := os.ReadFile(filepath.Clean(limaConfigFilePath)) + gomega.Expect(defaultLimaConfigFilePath).Should(gomega.BeARegularFile()) + _, err := os.ReadFile(filepath.Clean(defaultLimaConfigFilePath)) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + gomega.Expect(overrideLimaConfigFilePath).Should(gomega.BeARegularFile()) + overrideCfgBuf, err := os.ReadFile(filepath.Clean(overrideLimaConfigFilePath)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) var limaCfg limayaml.LimaYAML - err = yaml.Unmarshal(cfgBuf, &limaCfg) + err = yaml.Unmarshal(overrideCfgBuf, &limaCfg) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(*limaCfg.CPUs).Should(gomega.Equal(6)) gomega.Expect(*limaCfg.Memory).Should(gomega.Equal("4GiB")) @@ -107,12 +97,16 @@ var _ = func(o *option.Option, installed bool) { startCmdSession := updateAndApplyConfig(o, []byte("memory: 6GiB")) gomega.Expect(startCmdSession).Should(gexec.Exit(0)) - gomega.Expect(limaConfigFilePath).Should(gomega.BeARegularFile()) - cfgBuf, err := os.ReadFile(filepath.Clean(limaConfigFilePath)) + gomega.Expect(defaultLimaConfigFilePath).Should(gomega.BeARegularFile()) + _, err := os.ReadFile(filepath.Clean(defaultLimaConfigFilePath)) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + gomega.Expect(overrideLimaConfigFilePath).Should(gomega.BeARegularFile()) + overrideCfgBuf, err := os.ReadFile(filepath.Clean(overrideLimaConfigFilePath)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) var limaCfg limayaml.LimaYAML - err = yaml.Unmarshal(cfgBuf, &limaCfg) + err = yaml.Unmarshal(overrideCfgBuf, &limaCfg) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(limaCfg.CPUs).ShouldNot(gomega.BeNil()) gomega.Expect(*limaCfg.Memory).Should(gomega.Equal("6GiB")) @@ -122,12 +116,16 @@ var _ = func(o *option.Option, installed bool) { startCmdSession := updateAndApplyConfig(o, nil) gomega.Expect(startCmdSession).Should(gexec.Exit(0)) - gomega.Expect(limaConfigFilePath).Should(gomega.BeARegularFile()) - cfgBuf, err := os.ReadFile(filepath.Clean(limaConfigFilePath)) + gomega.Expect(defaultLimaConfigFilePath).Should(gomega.BeARegularFile()) + _, err := os.ReadFile(filepath.Clean(defaultLimaConfigFilePath)) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + gomega.Expect(overrideLimaConfigFilePath).Should(gomega.BeARegularFile()) + overrideCfgBuf, err := os.ReadFile(filepath.Clean(overrideLimaConfigFilePath)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) var limaCfg limayaml.LimaYAML - err = yaml.Unmarshal(cfgBuf, &limaCfg) + err = yaml.Unmarshal(overrideCfgBuf, &limaCfg) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(limaCfg.CPUs).ShouldNot(gomega.BeNil()) gomega.Expect(*limaCfg.Memory).Should(gomega.MatchRegexp(`\dGiB`)) @@ -156,11 +154,16 @@ additional_directories: - path: /tmp/workspace`)) gomega.Expect(startCmdSession).Should(gexec.Exit(0)) - gomega.Expect(limaConfigFilePath).Should(gomega.BeARegularFile()) - cfgBuf, err := os.ReadFile(filepath.Clean(limaConfigFilePath)) + gomega.Expect(defaultLimaConfigFilePath).Should(gomega.BeARegularFile()) + _, err := os.ReadFile(filepath.Clean(defaultLimaConfigFilePath)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + gomega.Expect(overrideLimaConfigFilePath).Should(gomega.BeARegularFile()) + overrideCfgBuf, err := os.ReadFile(filepath.Clean(overrideLimaConfigFilePath)) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + var limaCfg limayaml.LimaYAML - err = yaml.Unmarshal(cfgBuf, &limaCfg) + err = yaml.Unmarshal(overrideCfgBuf, &limaCfg) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(*limaCfg.CPUs).Should(gomega.Equal(6)) gomega.Expect(*limaCfg.Memory).Should(gomega.Equal("4GiB")) @@ -175,15 +178,22 @@ additional_directories: startCmdSession := updateAndApplyConfig(o, []byte("memory: 4GiB\ncpus: 6\nvmType: vz\nrosetta: true")) gomega.Expect(startCmdSession).Should(gexec.Exit(0)) - gomega.Expect(limaConfigFilePath).Should(gomega.BeARegularFile()) - cfgBuf, err := os.ReadFile(filepath.Clean(limaConfigFilePath)) + gomega.Expect(defaultLimaConfigFilePath).Should(gomega.BeARegularFile()) + defaultCfgBuf, err := os.ReadFile(filepath.Clean(defaultLimaConfigFilePath)) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + gomega.Expect(overrideLimaConfigFilePath).Should(gomega.BeARegularFile()) + overrideCfgBuf, err := os.ReadFile(filepath.Clean(overrideLimaConfigFilePath)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) var limaCfg limayaml.LimaYAML - err = yaml.Unmarshal(cfgBuf, &limaCfg) + err = yaml.Unmarshal(overrideCfgBuf, &limaCfg) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(*limaCfg.CPUs).Should(gomega.Equal(6)) gomega.Expect(*limaCfg.Memory).Should(gomega.Equal("4GiB")) + + err = yaml.Unmarshal(defaultCfgBuf, &limaCfg) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(*limaCfg.VMType).Should(gomega.Equal("qemu")) gomega.Expect(*limaCfg.Rosetta.Enabled).Should(gomega.Equal(false)) gomega.Expect(*limaCfg.Rosetta.BinFmt).Should(gomega.Equal(false)) diff --git a/e2e/vm/cred_helper_test.go b/e2e/vm/cred_helper_test.go index e3324d8e8..e86ebbf34 100644 --- a/e2e/vm/cred_helper_test.go +++ b/e2e/vm/cred_helper_test.go @@ -28,7 +28,7 @@ var testCredHelper = func(o *option.Option, installed bool, registry string) { if registry == "" { ginkgo.Skip("No Provided Container Registry Url") } - resetVM(o, installed) + resetVM(o) resetDisks(o, installed) writeFile(finchConfigFilePath, []byte(fmt.Sprintf("cpus: 6\nmemory: 4GiB\ncreds_helpers:\n "+ "- ecr-login\nvmType: %s\nrosetta: true", vmType))) diff --git a/e2e/vm/soci_test.go b/e2e/vm/soci_test.go index 324f51196..bd0c65dc4 100644 --- a/e2e/vm/soci_test.go +++ b/e2e/vm/soci_test.go @@ -61,7 +61,7 @@ var testSoci = func(o *option.Option, installed bool) { }) ginkgo.It("finch pull should have same mounts as nerdctl pull with SOCI", func() { - resetVM(o, installed) + resetVM(o) resetDisks(o, installed) writeFile(finchConfigFilePath, []byte(fmt.Sprintf("cpus: 6\nmemory: 4GiB\nsnapshotters:\n "+ "- soci\nvmType: %s\nrosetta: false", vmType))) @@ -77,7 +77,7 @@ var testSoci = func(o *option.Option, installed bool) { }) ginkgo.It("finch run should have same mounts as nerdctl run with SOCI", func() { - resetVM(o, installed) + resetVM(o) resetDisks(o, installed) writeFile(finchConfigFilePath, []byte(fmt.Sprintf("cpus: 6\nmemory: 4GiB\nsnapshotters:\n "+ "- soci\nvmType: %s\nrosetta: false", vmType))) @@ -92,7 +92,7 @@ var testSoci = func(o *option.Option, installed bool) { gomega.Expect(finchPullMounts).Should(gomega.Equal(nerdctlPullMounts)) }) ginkgo.It("finch push should work", func() { - resetVM(o, installed) + resetVM(o) resetDisks(o, installed) writeFile(finchConfigFilePath, []byte(fmt.Sprintf("cpus: 6\nmemory: 4GiB\nsnapshotters:\n "+ "- soci\nvmType: %s\nrosetta: false", vmType))) diff --git a/e2e/vm/virtualization_framework_rosetta_darwin_test.go b/e2e/vm/virtualization_framework_rosetta_darwin_test.go index fe1177d1a..2bc0d1c7d 100644 --- a/e2e/vm/virtualization_framework_rosetta_darwin_test.go +++ b/e2e/vm/virtualization_framework_rosetta_darwin_test.go @@ -29,7 +29,7 @@ var testVirtualizationFrameworkAndRosetta = func(o *option.Option, installed boo ginkgo.Skip("Skipping because system does not support Virtualization.framework") } - resetVM(o, installed) + resetVM(o) resetDisks(o, installed) writeFile(finchConfigFilePath, []byte("memory: 4GiB\ncpus: 6\nvmType: vz\nrosetta: false")) // vm init with VZ set sometimes takes 2 minutes just to convert the disk to raw @@ -52,7 +52,7 @@ var testVirtualizationFrameworkAndRosetta = func(o *option.Option, installed boo ginkgo.Skip("Skipping because system does not support Rosetta") } - resetVM(o, installed) + resetVM(o) resetDisks(o, installed) writeFile(finchConfigFilePath, []byte("memory: 4GiB\ncpus: 6\nvmType: vz\nrosetta: true")) // vm init with VZ set sometimes takes 2 minutes just to convert the disk to raw diff --git a/e2e/vm/vm_test.go b/e2e/vm/vm_test.go index 3af93cfc1..90d57b174 100644 --- a/e2e/vm/vm_test.go +++ b/e2e/vm/vm_test.go @@ -5,7 +5,6 @@ package vm import ( "os/exec" - "path/filepath" "runtime" "time" @@ -13,30 +12,14 @@ import ( "github.com/onsi/gomega" "github.com/runfinch/common-tests/command" "github.com/runfinch/common-tests/option" - - "github.com/runfinch/finch/e2e" ) const ( virtualMachineRootCmd = "vm" ) -func limaDataDirPath(installed bool) string { - limaConfigFilePath := defaultLimaDataDirPath - if installed { - path, err := exec.LookPath(e2e.InstalledTestSubject) - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - realFinchPath, err := filepath.EvalSymlinks(path) - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - limaConfigFilePath = filepath.Join(realFinchPath, "..", "..", "lima", "data") - } - return limaConfigFilePath -} - -var resetVM = func(o *option.Option, installed bool) string { +var resetVM = func(o *option.Option) { origFinchCfg := readFile(finchConfigFilePath) - limaConfigFilePath := filepath.Join(limaDataDirPath(installed), "_config", "override.yaml") - origLimaCfg := readFile(limaConfigFilePath) command.New(o, virtualMachineRootCmd, "stop", "-f").WithoutCheckingExitCode().WithTimeoutInSeconds(20).Run() time.Sleep(1 * time.Second) @@ -51,7 +34,6 @@ var resetVM = func(o *option.Option, installed bool) string { ginkgo.DeferCleanup(func() { writeFile(finchConfigFilePath, origFinchCfg) - writeFile(limaConfigFilePath, origLimaCfg) command.New(o, virtualMachineRootCmd, "stop", "-f").WithoutCheckingExitCode().WithTimeoutInSeconds(20).Run() time.Sleep(1 * time.Second) command.New(o, virtualMachineRootCmd, "remove", "-f").WithoutCheckingExitCode().WithTimeoutInSeconds(10).Run() @@ -61,6 +43,4 @@ var resetVM = func(o *option.Option, installed bool) string { time.Sleep(1 * time.Second) command.New(o, virtualMachineRootCmd, "init").WithoutCheckingExitCode().WithTimeoutInSeconds(160).Run() }) - - return limaConfigFilePath } diff --git a/go.mod b/go.mod index e973bf5ff..19cde1f64 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,12 @@ module github.com/runfinch/finch go 1.22.0 require ( - github.com/aws/aws-sdk-go-v2 v1.24.1 - github.com/docker/cli v24.0.7+incompatible + github.com/aws/aws-sdk-go-v2 v1.25.0 + github.com/docker/cli v25.0.3+incompatible github.com/docker/docker v25.0.3+incompatible github.com/golang/mock v1.6.0 github.com/google/go-licenses v1.6.1-0.20230903011517-706b9c60edd4 - github.com/lima-vm/lima v0.20.0 + github.com/lima-vm/lima v0.20.1 github.com/onsi/ginkgo/v2 v2.15.0 github.com/onsi/gomega v1.31.1 github.com/pelletier/go-toml v1.9.5 @@ -25,48 +25,48 @@ require ( golang.org/x/exp v0.0.0-20230810033253-352e893a4cad golang.org/x/tools v0.17.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/apimachinery v0.28.4 + k8s.io/apimachinery v0.29.1 ) require ( - github.com/aws/smithy-go v1.19.0 // indirect - github.com/containerd/containerd v1.7.12 // indirect + github.com/aws/smithy-go v1.20.0 // indirect + github.com/containerd/containerd v1.7.13 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/docker/docker-credential-helpers v0.7.0 // indirect - github.com/docker/go-connections v0.4.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/docker/docker-credential-helpers v0.8.1 // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/licenseclassifier/v2 v2.0.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/lima-vm/go-qcow2reader v0.1.1 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/opencontainers/image-spec v1.1.0-rc6 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/tc-hib/winres v0.1.6 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tklauser/go-sysconf v0.3.13 // indirect + github.com/tklauser/numcpus v0.7.0 // indirect github.com/urfave/cli/v2 v2.3.0 // indirect - github.com/yusufpapurcu/wmi v1.2.3 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect golang.org/x/image v0.10.0 // indirect golang.org/x/sync v0.6.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/go-units v0.5.0 - github.com/fatih/color v1.15.0 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/go-logr/logr v1.4.1 // indirect - github.com/goccy/go-yaml v1.11.3 + github.com/goccy/go-yaml v1.11.3 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -84,7 +84,7 @@ require ( golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.17.0 golang.org/x/text v0.14.0 - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect k8s.io/klog/v2 v2.120.1 // indirect ) diff --git a/go.sum b/go.sum index 51be0db85..5674662d8 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,17 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU= -github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= -github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= -github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/aws/aws-sdk-go-v2 v1.25.0 h1:sv7+1JVJxOu/dD/sz/csHX7jFqmP001TIY7aytBWDSQ= +github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= +github.com/aws/smithy-go v1.20.0 h1:6+kZsCXZwKxZS9RfISnPc4EXlHoyAkm2hPuM8X2BrrQ= +github.com/aws/smithy-go v1.20.0/go.mod h1:uo5RKksAl4PzhqaAbjd4rLgFoq5koTsQKYuGe7dklGc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= -github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= +github.com/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is= +github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -21,26 +21,27 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= -github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6/EsX/6284= +github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v25.0.3+incompatible h1:D5fy/lYmY7bvZa0XTZ5/UJPljor41F+vdyJG5luQLfQ= github.com/docker/docker v25.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= -github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= +github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= @@ -113,10 +114,11 @@ github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lima-vm/go-qcow2reader v0.1.1 h1:UegxTAU4usoSzKLDqhbaNmmV4Ec4qhQO11QYeLLy7Jc= github.com/lima-vm/go-qcow2reader v0.1.1/go.mod h1:e3p29BzLT8hNh4jbLezdFAHU4eBijf0bm5GilStCRKE= -github.com/lima-vm/lima v0.20.0 h1:ifVowJNX1y93AWKyZuc7eFPCbiNCdm+N1loEzIo0JPc= -github.com/lima-vm/lima v0.20.0/go.mod h1:N8HdwkX0PjeVeoyCqOCfIDiMh4HFN7tVNgzBvMIVc8c= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lima-vm/lima v0.20.1 h1:X7YDxVyEm1UN9iMgDBKd2OAVcvRCFWK7/C78NMN6/J4= +github.com/lima-vm/lima v0.20.1/go.mod h1:ya+IyquUmntJUEzzERwi1gBGOQKnVOyrVx4OePFfwP4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0= +github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -130,8 +132,8 @@ github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= -github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= +github.com/opencontainers/image-spec v1.1.0-rc6/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= @@ -146,8 +148,9 @@ github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= @@ -189,10 +192,12 @@ github.com/tc-hib/go-winres v0.3.1 h1:9r67V7Ep34yyx8SL716BzcKePRvEBOjan47SmMnxEd github.com/tc-hib/go-winres v0.3.1/go.mod h1:lTPf0MW3eu6rmvMyLrPXSy6xsSz4t5dRxB7dc5YFP6k= github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= +github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= +github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/xorcare/pointer v1.2.2 h1:zjD77b5DTehClND4MK+9dDE0DcpFIZisAJ/+yVJvKYA= @@ -201,8 +206,9 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -310,22 +316,22 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 h1:hZB7eLIaYlW9qXRfCq/qDaPdbeY3757uARz5Vvfv+cY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -337,8 +343,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -354,7 +360,7 @@ gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= -k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= +k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc= +k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= diff --git a/installer-builder/darwin/scripts/postinstall b/installer-builder/darwin/scripts/postinstall index a9dc98e74..421bf914a 100755 --- a/installer-builder/darwin/scripts/postinstall +++ b/installer-builder/darwin/scripts/postinstall @@ -17,6 +17,7 @@ chmod -R 755 /Applications/Finch/dependencies/lima-socket_vmnet/opt/finch sudo ln -sf /Applications/Finch/bin/finch /usr/local/bin/finch sudo rm -rf "/Applications/Finch/lima/data/finch/" sudo rm -rf "/Applications/Finch/lima/data/_config/override.yaml" +sudo rm -rf "/Applications/Finch/lima/data/_config/default.yaml" sudo rm -rf "/Applications/Finch/lima/data/_config/user" sudo rm -rf "/Applications/Finch/lima/data/_config/user.pub" sudo rm -rf "/Applications/Finch/lima/data/_networks/" diff --git a/msi-builder/postinstall.bat b/msi-builder/postinstall.bat index 7b51231e5..b6a7f474c 100644 --- a/msi-builder/postinstall.bat +++ b/msi-builder/postinstall.bat @@ -11,6 +11,7 @@ icacls "%InstallDir%\lima\data" /grant Users:(OI)(CI)M :: Delete files and directories if they exist if exist "%InstallDir%\lima\data\finch\" rmdir /s /q "%InstallDir%\lima\data\finch\" if exist "%InstallDir%\lima\data\_config\override.yaml" del /f /q "%InstallDir%\lima\data\_config\override.yaml" +if exist "%InstallDir%\lima\data\_config\default.yaml" del /f /q "%InstallDir%\lima\data\_config\default.yaml" if exist "%InstallDir%\lima\data\_config\user" del /f /q "%InstallDir%\lima\data\_config\user" if exist "%InstallDir%\lima\data\_config\user.pub" del /f /q "%InstallDir%\lima\data\_config\user.pub" if exist "%InstallDir%\lima\data\_networks\" rmdir /s /q "%InstallDir%\lima\data\_networks\" diff --git a/pkg/config/config.go b/pkg/config/config.go index 795b50152..8dbf3bc70 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -75,7 +75,8 @@ type Nerdctl struct { // //go:generate mockgen -copyright_file=../../copyright_header -destination=../mocks/pkg_config_lima_config_applier.go -package=mocks -mock_names LimaConfigApplier=LimaConfigApplier . LimaConfigApplier type LimaConfigApplier interface { - Apply(isInit bool) error + ConfigureOverrideLimaYaml() error + ConfigureDefaultLimaYaml() error } // NerdctlConfigApplier applies nerdctl configuration changes. diff --git a/pkg/config/lima_config_applier.go b/pkg/config/lima_config_applier.go index 57717d8d9..cd4991ee7 100644 --- a/pkg/config/lima_config_applier.go +++ b/pkg/config/lima_config_applier.go @@ -7,7 +7,6 @@ import ( "fmt" "strings" - goyaml "github.com/goccy/go-yaml" "github.com/lima-vm/lima/pkg/limayaml" "github.com/spf13/afero" "github.com/xorcare/pointer" @@ -20,7 +19,8 @@ import ( const ( sociVersion = "0.4.0" - sociInstallationProvisioningScriptHeader = "# soci installation and configuring" + snapshotterProvisioningScriptHeader = "# snapshotter provisioning script" + sociInstallationProvisioningScriptHeader = snapshotterProvisioningScriptHeader + ": soci" sociFileNameFormat = "soci-snapshotter-%s-linux-%s.tar.gz" sociDownloadURLFormat = "https://github.com/awslabs/soci-snapshotter/releases/download/v%s/%s" sociServiceDownloadURLFormat = "https://raw.githubusercontent.com/awslabs/soci-snapshotter/v%s/soci-snapshotter.service" @@ -54,6 +54,21 @@ sudo systemctl restart containerd.service userModeEmulationProvisioningScriptHeader = "# cross-arch tools" wslDiskFormatScriptHeader = "# wsl disk format script" + qemuPkgInstallationScript = `%s +#!/bin/bash +qemu_pkgs="" +if [ ! -f /usr/bin/qemu-aarch64-static ]; then + qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" +elif [ ! -f /usr/bin/qemu-aarch64-static ]; then + qemu_pkgs="$qemu_pkgs qemu-user-static-arm" +elif [ ! -f /usr/bin/qemu-aarch64-static ]; then + qemu_pkgs="$qemu_pkgs qemu-user-static-x86" +fi + +if [[ $qemu_pkgs ]]; then + dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} +fi +` ) // LimaConfigApplierSystemDeps contains the system dependencies for LimaConfigApplier. @@ -65,11 +80,12 @@ type LimaConfigApplierSystemDeps interface { } type limaConfigApplier struct { - cfg *Finch - cmdCreator command.Creator - fs afero.Fs - limaConfigPath string - systemDeps LimaConfigApplierSystemDeps + cfg *Finch + cmdCreator command.Creator + fs afero.Fs + limaDefaultConfigPath string + limaOverrideConfigPath string + systemDeps LimaConfigApplierSystemDeps } var _ LimaConfigApplier = (*limaConfigApplier)(nil) @@ -80,46 +96,64 @@ func NewLimaApplier( cfg *Finch, cmdCreator command.Creator, fs afero.Fs, - limaConfigPath string, + limaDefaultConfigPath string, + limaOverrideConfigPath string, systemDeps LimaConfigApplierSystemDeps, ) LimaConfigApplier { return &limaConfigApplier{ - cfg: cfg, - cmdCreator: cmdCreator, - fs: fs, - limaConfigPath: limaConfigPath, - systemDeps: systemDeps, + cfg: cfg, + cmdCreator: cmdCreator, + fs: fs, + limaDefaultConfigPath: limaDefaultConfigPath, + limaOverrideConfigPath: limaOverrideConfigPath, + systemDeps: systemDeps, } } -// Apply writes Lima-specific config values from Finch's config to the supplied lima config file path. -// Apply will create a lima config file at the path if it does not exist. -func (lca *limaConfigApplier) Apply(isInit bool) error { - if cfgExists, err := afero.Exists(lca.fs, lca.limaConfigPath); err != nil { - return fmt.Errorf("error checking if file at path %s exists, error: %w", lca.limaConfigPath, err) - } else if !cfgExists { - if err := afero.WriteFile(lca.fs, lca.limaConfigPath, []byte(""), 0o600); err != nil { - return fmt.Errorf("failed to create the an empty lima config file: %w", err) - } +// ConfigureDefaultLimaYaml writes Lima-specific config values from Finch's config to default.yaml at lima config file path. +// ConfigureDefaultLimaYaml will create a default.yaml at the path if it does not exist. +func (lca *limaConfigApplier) ConfigureDefaultLimaYaml() error { + if err := afero.WriteFile(lca.fs, lca.limaDefaultConfigPath, []byte(""), 0o600); err != nil { + return fmt.Errorf("failed to create the an empty lima config file: %w", err) + } + + var limaCfg limayaml.LimaYAML + + if limaCfg.Rosetta.Enabled == nil { + limaCfg.Rosetta.Enabled = pointer.Bool(false) + limaCfg.Rosetta.BinFmt = pointer.Bool(false) } - b, err := afero.ReadFile(lca.fs, lca.limaConfigPath) + cfgAfterInit, err := lca.configureVirtualizationFramework(&limaCfg) if err != nil { - return fmt.Errorf("failed to load the lima config file: %w", err) + return fmt.Errorf("failed to apply init-only config values: %w", err) } + limaCfg = *cfgAfterInit - var limaCfg limayaml.LimaYAML - if err := yaml.Unmarshal(b, &limaCfg); err != nil { - return fmt.Errorf("failed to unmarshal the lima config file: %w", err) + limaCfgBytes, err := yaml.Marshal(limaCfg) + if err != nil { + return fmt.Errorf("failed to marshal the lima config file: %w", err) } - // Unmarshall with custom unmarshaler for Disk: - // https://github.com/lima-vm/lima/blob/v0.17.2/pkg/limayaml/load.go#L16 - if err := goyaml.UnmarshalWithOptions(b, &limaCfg, goyaml.DisallowDuplicateKey(), - goyaml.CustomUnmarshaler[limayaml.Disk](unmarshalDisk)); err != nil { - return fmt.Errorf("failed to unmarshal the lima config file: %w", err) + if err := afero.WriteFile(lca.fs, lca.limaDefaultConfigPath, limaCfgBytes, 0o600); err != nil { + return fmt.Errorf("failed to write to the lima config file: %w", err) } + if err != nil { + return fmt.Errorf("unable to apply override config: %w", err) + } + + return nil +} + +// ConfigureOverrideLimaYaml writes Lima-specific config values from Finch's config to override.yaml at lima config file path. +// ConfigureOverrideLimaYaml will create a override.yaml at the path if it does not exist. +func (lca *limaConfigApplier) ConfigureOverrideLimaYaml() error { + if err := afero.WriteFile(lca.fs, lca.limaOverrideConfigPath, []byte(""), 0o600); err != nil { + return fmt.Errorf("failed to create the an empty lima config file: %w", err) + } + var limaCfg limayaml.LimaYAML + limaCfg.CPUs = lca.cfg.CPUs limaCfg.Memory = lca.cfg.Memory limaCfg.Mounts = []limayaml.Mount{} @@ -128,36 +162,6 @@ func (lca *limaConfigApplier) Apply(isInit bool) error { Location: *ad.Path, Writable: pointer.Bool(true), }) } - if limaCfg.Rosetta.Enabled == nil { - limaCfg.Rosetta.Enabled = pointer.Bool(false) - limaCfg.Rosetta.BinFmt = pointer.Bool(false) - } - - if isInit { - cfgAfterInit, err := lca.applyInit(&limaCfg) - if err != nil { - return fmt.Errorf("failed to apply init-only config values: %w", err) - } - limaCfg = *cfgAfterInit - } - - supportedSnapshotters := []string{"overlayfs", "soci"} - snapshotters := make(map[string][2]bool) - for i, snapshotter := range lca.cfg.Snapshotters { - if !slices.Contains(supportedSnapshotters, snapshotter) { - return fmt.Errorf("invalid snapshotter config value: %s", snapshotter) - } - - isDefaultSnapshotter := false - if i == 0 { - isDefaultSnapshotter = true - } - - isEnabled := true - snapshotters[snapshotter] = [2]bool{isEnabled, isDefaultSnapshotter} - } - - toggleSnaphotters(&limaCfg, snapshotters) if *lca.cfg.VMType != "wsl2" && len(limaCfg.AdditionalDisks) == 0 { limaCfg.AdditionalDisks = append(limaCfg.AdditionalDisks, limayaml.Disk{ @@ -165,6 +169,16 @@ func (lca *limaConfigApplier) Apply(isInit bool) error { }) } + err := lca.provisionSnapshotters(&limaCfg) + if err != nil { + return fmt.Errorf("failed to provision snapshotters: %w", err) + } + + err = lca.configureDefaultSnapshotter(&limaCfg) + if err != nil { + return fmt.Errorf("failed to configure default snapshotter: %w", err) + } + if *lca.cfg.VMType == "wsl2" { ensureWslDiskFormatScript(&limaCfg) } @@ -174,64 +188,63 @@ func (lca *limaConfigApplier) Apply(isInit bool) error { return fmt.Errorf("failed to marshal the lima config file: %w", err) } - if err := afero.WriteFile(lca.fs, lca.limaConfigPath, limaCfgBytes, 0o600); err != nil { + if err := afero.WriteFile(lca.fs, lca.limaOverrideConfigPath, limaCfgBytes, 0o600); err != nil { return fmt.Errorf("failed to write to the lima config file: %w", err) } return nil } -// toggles snapshotters and sets default snapshotter. -func toggleSnaphotters(limaCfg *limayaml.LimaYAML, snapshotters map[string][2]bool) { - toggleOverlayFs(limaCfg, snapshotters["overlayfs"][1]) - toggleSoci(limaCfg, snapshotters["soci"][0], snapshotters["soci"][1], sociVersion) -} - -// sets overlayfs as the default snapshotter. -func toggleOverlayFs(limaCfg *limayaml.LimaYAML, isDefault bool) { - if isDefault { - limaCfg.Env = map[string]string{"CONTAINERD_SNAPSHOTTER": ""} +func validateSnapshotter(snapshotter string) error { + supportedSnapshotters := []string{"overlayfs", "soci"} + if !slices.Contains(supportedSnapshotters, snapshotter) { + return fmt.Errorf("snapshotter %s is not supported", snapshotter) } + return nil } -func toggleSoci(limaCfg *limayaml.LimaYAML, enabled bool, isDefault bool, sociVersion string) { - idx, hasScript := findSociInstallationScript(limaCfg) - sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, system.NewStdLib().Arch()) - sociDownloadURL := fmt.Sprintf(sociDownloadURLFormat, sociVersion, sociFileName) - sociServiceDownloadURL := fmt.Sprintf(sociServiceDownloadURLFormat, sociVersion) - sociInstallationScript := fmt.Sprintf(sociInstallationScriptFormat, sociInstallationProvisioningScriptHeader, - sociDownloadURL, sociFileName, sociServiceDownloadURL) - if !hasScript && enabled { - limaCfg.Provision = append(limaCfg.Provision, limayaml.Provision{ - Mode: "system", - Script: sociInstallationScript, - }) - } else if hasScript && !enabled { - if len(limaCfg.Provision) > 0 { - limaCfg.Provision = append(limaCfg.Provision[:idx], limaCfg.Provision[idx+1:]...) - } +func (lca *limaConfigApplier) configureDefaultSnapshotter(limaCfg *limayaml.LimaYAML) error { + if len(lca.cfg.Snapshotters) == 0 { + limaCfg.Env = map[string]string{} + return nil } - if isDefault { - limaCfg.Env = map[string]string{"CONTAINERD_SNAPSHOTTER": "soci"} - } else { - limaCfg.Env = map[string]string{"CONTAINERD_SNAPSHOTTER": ""} + snapshotter := lca.cfg.Snapshotters[0] + err := validateSnapshotter(snapshotter) + if err != nil { + return err } + + limaCfg.Env = map[string]string{"CONTAINERD_SNAPSHOTTER": snapshotter} + + return nil } -func findSociInstallationScript(limaCfg *limayaml.LimaYAML) (int, bool) { - hasSociInstallationScript := false - var scriptIdx int - for idx, prov := range limaCfg.Provision { - trimmed := strings.Trim(prov.Script, " ") - if !hasSociInstallationScript && strings.HasPrefix(trimmed, sociInstallationProvisioningScriptHeader) { - hasSociInstallationScript = true - scriptIdx = idx - break +func (lca *limaConfigApplier) provisionSnapshotters(limaCfg *limayaml.LimaYAML) error { + for _, snapshotter := range lca.cfg.Snapshotters { + switch snapshotter { + case "soci": + lca.provisionSociSnapshotter(limaCfg) + case "overlayfs": + continue + default: + return fmt.Errorf("snapshotter %s is not supported", snapshotter) } } - return scriptIdx, hasSociInstallationScript + return nil +} + +func (lca *limaConfigApplier) provisionSociSnapshotter(limaCfg *limayaml.LimaYAML) { + sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, lca.systemDeps.Arch()) + sociDownloadURL := fmt.Sprintf(sociDownloadURLFormat, sociVersion, sociFileName) + sociServiceDownloadURL := fmt.Sprintf(sociServiceDownloadURLFormat, sociVersion) + sociInstallationScript := fmt.Sprintf(sociInstallationScriptFormat, sociInstallationProvisioningScriptHeader, + sociDownloadURL, sociFileName, sociServiceDownloadURL) + limaCfg.Provision = append(limaCfg.Provision, limayaml.Provision{ + Mode: "system", + Script: sociInstallationScript, + }) } func ensureWslDiskFormatScript(limaCfg *limayaml.LimaYAML) { @@ -259,13 +272,3 @@ func findWslDiskFormatScript(limaCfg *limayaml.LimaYAML) bool { return hasWslDiskFormatScript } - -// https://github.com/lima-vm/lima/blob/v0.17.2/pkg/limayaml/load.go#L16 -func unmarshalDisk(dst *limayaml.Disk, b []byte) error { - var s string - if err := goyaml.Unmarshal(b, &s); err == nil { - *dst = limayaml.Disk{Name: s} - return nil - } - return goyaml.Unmarshal(b, dst) -} diff --git a/pkg/config/lima_config_applier_darwin.go b/pkg/config/lima_config_applier_darwin.go index 0a9465f34..9537323d0 100644 --- a/pkg/config/lima_config_applier_darwin.go +++ b/pkg/config/lima_config_applier_darwin.go @@ -8,14 +8,13 @@ package config import ( "errors" "fmt" - "strings" "github.com/lima-vm/lima/pkg/limayaml" "github.com/xorcare/pointer" ) -// applyInit changes settings that will only apply to the VM after a new init. -func (lca *limaConfigApplier) applyInit(limaCfg *limayaml.LimaYAML) (*limayaml.LimaYAML, error) { +// configureVirtualizationFramework changes settings that will only apply to the VM after a new init. +func (lca *limaConfigApplier) configureVirtualizationFramework(limaCfg *limayaml.LimaYAML) (*limayaml.LimaYAML, error) { hasSupport, hasSupportErr := SupportsVirtualizationFramework(lca.cmdCreator) if *lca.cfg.Rosetta && lca.systemDeps.Arch() == "arm64" { @@ -30,7 +29,6 @@ func (lca *limaConfigApplier) applyInit(limaCfg *limayaml.LimaYAML) (*limayaml.L limaCfg.Rosetta.BinFmt = pointer.Bool(true) limaCfg.VMType = pointer.String("vz") limaCfg.MountType = pointer.String("virtiofs") - toggleUserModeEmulationInstallationScript(limaCfg, false) } else { switch *lca.cfg.VMType { case "vz": @@ -54,50 +52,15 @@ func (lca *limaConfigApplier) applyInit(limaCfg *limayaml.LimaYAML) (*limayaml.L limaCfg.Rosetta.Enabled = pointer.Bool(false) limaCfg.Rosetta.BinFmt = pointer.Bool(false) limaCfg.VMType = lca.cfg.VMType - toggleUserModeEmulationInstallationScript(limaCfg, true) + userModeEmulationInstallationScript(limaCfg) } return limaCfg, nil } -func toggleUserModeEmulationInstallationScript(limaCfg *limayaml.LimaYAML, enabled bool) { - idx, hasScript := hasUserModeEmulationInstallationScript(limaCfg) - if !hasScript && enabled { - limaCfg.Provision = append(limaCfg.Provision, limayaml.Provision{ - Mode: "system", - Script: fmt.Sprintf(`%s -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, userModeEmulationProvisioningScriptHeader), - }) - } else if hasScript && !enabled { - if len(limaCfg.Provision) > 0 { - limaCfg.Provision = append(limaCfg.Provision[:idx], limaCfg.Provision[idx+1:]...) - } - } -} - -func hasUserModeEmulationInstallationScript(limaCfg *limayaml.LimaYAML) (int, bool) { - hasCrossArchToolInstallationScript := false - var scriptIdx int - for idx, prov := range limaCfg.Provision { - trimmed := strings.Trim(prov.Script, " ") - if !hasCrossArchToolInstallationScript && strings.HasPrefix(trimmed, userModeEmulationProvisioningScriptHeader) { - hasCrossArchToolInstallationScript = true - scriptIdx = idx - } - } - - return scriptIdx, hasCrossArchToolInstallationScript +func userModeEmulationInstallationScript(limaCfg *limayaml.LimaYAML) { + limaCfg.Provision = append(limaCfg.Provision, limayaml.Provision{ + Mode: "system", + Script: fmt.Sprintf(qemuPkgInstallationScript, userModeEmulationProvisioningScriptHeader), + }) } diff --git a/pkg/config/lima_config_applier_darwin_test.go b/pkg/config/lima_config_applier_darwin_test.go index 65a416a86..83ae2d2a3 100644 --- a/pkg/config/lima_config_applier_darwin_test.go +++ b/pkg/config/lima_config_applier_darwin_test.go @@ -18,18 +18,20 @@ import ( "gopkg.in/yaml.v3" "github.com/runfinch/finch/pkg/mocks" - "github.com/runfinch/finch/pkg/system" ) +var qemuPkgScriptWithHeader = fmt.Sprintf(qemuPkgInstallationScript, userModeEmulationProvisioningScriptHeader) + func TestDiskLimaConfigApplier_Apply(t *testing.T) { t.Parallel() testCases := []struct { - name string - config *Finch - path string - isInit bool - mockSvc func( + name string + config *Finch + defaultPath string + overridePath string + isInit bool + mockSvc func( fs afero.Fs, l *mocks.Logger, cmd *mocks.Command, @@ -47,22 +49,21 @@ func TestDiskLimaConfigApplier_Apply(t *testing.T) { VMType: pointer.String("qemu"), Rosetta: pointer.Bool(false), }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( - fs afero.Fs, + _ afero.Fs, _ *mocks.Logger, cmd *mocks.Command, creator *mocks.CommandCreator, _ *mocks.LimaConfigApplierSystemDeps, ) { - err := afero.WriteFile(fs, "/lima.yaml", []byte("memory: 4GiB\ncpus: 8"), 0o600) - require.NoError(t, err) cmd.EXPECT().Output().Return([]byte("13.0.0"), nil) creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") require.NoError(t, err) var limaCfg limayaml.LimaYAML @@ -70,23 +71,14 @@ func TestDiskLimaConfigApplier_Apply(t *testing.T) { require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) - require.Equal(t, "reverse-sshfs", *limaCfg.MountType) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -99,25 +91,24 @@ fi Rosetta: pointer.Bool(false), Snapshotters: []string{"soci"}, }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, cmd *mocks.Command, creator *mocks.CommandCreator, - _ *mocks.LimaConfigApplierSystemDeps, + deps *mocks.LimaConfigApplierSystemDeps, ) { err := afero.WriteFile(fs, "/lima.yaml", []byte("memory: 4GiB\ncpus: 8"), 0o600) require.NoError(t, err) cmd.EXPECT().Output().Return([]byte("13.0.0"), nil) creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) + deps.EXPECT().Arch() }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") - require.NoError(t, err) - - sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, system.NewStdLib().Arch()) + sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, "") sociDownloadURL := fmt.Sprintf(sociDownloadURLFormat, sociVersion, sociFileName) sociServiceDownloadURL := fmt.Sprintf(sociServiceDownloadURLFormat, sociVersion) sociInstallationScript := fmt.Sprintf(sociInstallationScriptFormat, @@ -126,31 +117,26 @@ fi sociFileName, sociServiceDownloadURL) + buf, err := afero.ReadFile(fs, "/override.yaml") + require.NoError(t, err) + var limaCfg limayaml.LimaYAML err = yaml.Unmarshal(buf, &limaCfg) require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) - require.Equal(t, "reverse-sshfs", *limaCfg.MountType) - require.Equal(t, "system", limaCfg.Provision[1].Mode) + require.Equal(t, "system", limaCfg.Provision[0].Mode) require.Equal(t, "soci", limaCfg.Env["CONTAINERD_SNAPSHOTTER"]) - require.Equal(t, sociInstallationScript, limaCfg.Provision[1].Script) + require.Equal(t, sociInstallationScript, limaCfg.Provision[0].Script) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -163,8 +149,9 @@ fi Rosetta: pointer.Bool(false), Snapshotters: []string{}, }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, @@ -178,7 +165,7 @@ fi creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") require.NoError(t, err) var limaCfg limayaml.LimaYAML @@ -186,25 +173,18 @@ fi require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) + val, ok := limaCfg.Env["CONTAINERD_SNAPSHOTTER"] + require.Equal(t, "", val) + require.False(t, ok) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, "", limaCfg.Env["CONTAINERD_SNAPSHOTTER"]) - require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -217,8 +197,9 @@ fi Rosetta: pointer.Bool(false), Snapshotters: []string{"overlayfs"}, }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, @@ -232,7 +213,7 @@ fi creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") require.NoError(t, err) var limaCfg limayaml.LimaYAML @@ -240,25 +221,16 @@ fi require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) + require.Equal(t, "overlayfs", limaCfg.Env["CONTAINERD_SNAPSHOTTER"]) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, "", limaCfg.Env["CONTAINERD_SNAPSHOTTER"]) - require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -271,25 +243,24 @@ fi Rosetta: pointer.Bool(false), Snapshotters: []string{"overlayfs", "soci"}, }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, cmd *mocks.Command, creator *mocks.CommandCreator, - _ *mocks.LimaConfigApplierSystemDeps, + deps *mocks.LimaConfigApplierSystemDeps, ) { err := afero.WriteFile(fs, "/lima.yaml", []byte("memory: 4GiB\ncpus: 8"), 0o600) require.NoError(t, err) cmd.EXPECT().Output().Return([]byte("13.0.0"), nil) creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) + deps.EXPECT().Arch() }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") - require.NoError(t, err) - - sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, system.NewStdLib().Arch()) + sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, "") sociDownloadURL := fmt.Sprintf(sociDownloadURLFormat, sociVersion, sociFileName) sociServiceDownloadURL := fmt.Sprintf(sociServiceDownloadURLFormat, sociVersion) sociInstallationScript := fmt.Sprintf(sociInstallationScriptFormat, @@ -298,31 +269,27 @@ fi sociFileName, sociServiceDownloadURL) + buf, err := afero.ReadFile(fs, "/override.yaml") + require.NoError(t, err) + var limaCfg limayaml.LimaYAML err = yaml.Unmarshal(buf, &limaCfg) require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) + require.Equal(t, "system", limaCfg.Provision[0].Mode) + require.Equal(t, "overlayfs", limaCfg.Env["CONTAINERD_SNAPSHOTTER"]) + require.Equal(t, sociInstallationScript, limaCfg.Provision[0].Script) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, "", limaCfg.Env["CONTAINERD_SNAPSHOTTER"]) - require.Equal(t, sociInstallationScript, limaCfg.Provision[1].Script) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -335,25 +302,24 @@ fi Rosetta: pointer.Bool(false), Snapshotters: []string{"soci", "overlayfs"}, }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, cmd *mocks.Command, creator *mocks.CommandCreator, - _ *mocks.LimaConfigApplierSystemDeps, + deps *mocks.LimaConfigApplierSystemDeps, ) { err := afero.WriteFile(fs, "/lima.yaml", []byte("memory: 4GiB\ncpus: 8"), 0o600) require.NoError(t, err) cmd.EXPECT().Output().Return([]byte("13.0.0"), nil) creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) + deps.EXPECT().Arch() }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") - require.NoError(t, err) - - sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, system.NewStdLib().Arch()) + sociFileName := fmt.Sprintf(sociFileNameFormat, sociVersion, "") sociDownloadURL := fmt.Sprintf(sociDownloadURLFormat, sociVersion, sociFileName) sociServiceDownloadURL := fmt.Sprintf(sociServiceDownloadURLFormat, sociVersion) sociInstallationScript := fmt.Sprintf(sociInstallationScriptFormat, @@ -362,31 +328,26 @@ fi sociFileName, sociServiceDownloadURL) + buf, err := afero.ReadFile(fs, "/override.yaml") + require.NoError(t, err) + var limaCfg limayaml.LimaYAML err = yaml.Unmarshal(buf, &limaCfg) require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) - require.Equal(t, "reverse-sshfs", *limaCfg.MountType) - require.Equal(t, "system", limaCfg.Provision[0].Mode) require.Equal(t, "soci", limaCfg.Env["CONTAINERD_SNAPSHOTTER"]) - require.Equal(t, sociInstallationScript, limaCfg.Provision[1].Script) + require.Equal(t, sociInstallationScript, limaCfg.Provision[0].Script) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) + require.Equal(t, "system", limaCfg.Provision[0].Mode) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -398,8 +359,9 @@ fi VMType: pointer.String("vz"), Rosetta: pointer.Bool(true), }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, @@ -407,34 +369,33 @@ fi creator *mocks.CommandCreator, deps *mocks.LimaConfigApplierSystemDeps, ) { - err := afero.WriteFile(fs, "/lima.yaml", []byte(`memory: 4GiB -cpus: 8 -vmType: "qemu" -provision: -- mode: system - script: | - # cross-arch tools - #!/bin/bash - qemu_pkgs="" - if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" - elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" - elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" - fi - - if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} - fi -`), 0o600) + err := afero.WriteFile(fs, "/default.yaml", []byte(` + vmType: "qemu" + provision: + - mode: system + script: | + # cross-arch tools + #!/bin/bash + qemu_pkgs="" + if [ ! -f /usr/bin/qemu-aarch64-static ]; then + qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" + elif [ ! -f /usr/bin/qemu-aarch64-static ]; then + qemu_pkgs="$qemu_pkgs qemu-user-static-arm" + elif [ ! -f /usr/bin/qemu-aarch64-static ]; then + qemu_pkgs="$qemu_pkgs qemu-user-static-x86" + fi + + if [[ $qemu_pkgs ]]; then + dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} + fi + `), 0o600) require.NoError(t, err) cmd.EXPECT().Output().Return([]byte("13.0.0"), nil) creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) deps.EXPECT().Arch().Return("arm64") }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") require.NoError(t, err) var limaCfg limayaml.LimaYAML @@ -442,6 +403,12 @@ provision: require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + require.Equal(t, "vz", *limaCfg.VMType) require.Equal(t, "virtiofs", *limaCfg.MountType) require.Equal(t, true, *limaCfg.Rosetta.BinFmt) @@ -458,8 +425,9 @@ provision: VMType: pointer.String("qemu"), Rosetta: pointer.Bool(false), }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, @@ -467,19 +435,18 @@ provision: creator *mocks.CommandCreator, _ *mocks.LimaConfigApplierSystemDeps, ) { - err := afero.WriteFile(fs, "/lima.yaml", []byte(`memory: 4GiB -cpus: 8 + err := afero.WriteFile(fs, "/default.yaml", []byte(` vmType: "vz" rosetta: - enabled: true - binfmt: true + enabled: true + binfmt: true `), 0o600) require.NoError(t, err) cmd.EXPECT().Output().Return([]byte("13.0.0"), nil) creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") require.NoError(t, err) var limaCfg limayaml.LimaYAML @@ -487,26 +454,17 @@ rosetta: require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) require.Equal(t, "qemu", *limaCfg.VMType) require.Equal(t, false, *limaCfg.Rosetta.Enabled) require.Equal(t, false, *limaCfg.Rosetta.BinFmt) require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -518,8 +476,9 @@ fi VMType: pointer.String("vz"), Rosetta: pointer.Bool(false), }, - path: "/lima.yaml", - isInit: false, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: false, mockSvc: func( fs afero.Fs, _ *mocks.Logger, @@ -527,57 +486,19 @@ fi _ *mocks.CommandCreator, _ *mocks.LimaConfigApplierSystemDeps, ) { - err := afero.WriteFile(fs, "/lima.yaml", []byte(`memory: 4GiB -cpus: 8 -vmType: "qemu" -mountType: "reverse-sshfs" -provision: -- mode: system - script: | - # cross-arch tools - #!/bin/bash - qemu_pkgs="" - if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" - elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" - elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" - fi - - if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} - fi -`), 0o600) + err := afero.WriteFile(fs, "/default.yaml", []byte(`vmType: "qemu" +mountType: "reverse-sshfs"`), 0o600) require.NoError(t, err) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/default.yaml") require.NoError(t, err) - var limaCfg limayaml.LimaYAML err = yaml.Unmarshal(buf, &limaCfg) require.NoError(t, err) - require.Equal(t, 4, *limaCfg.CPUs) - require.Equal(t, "2GiB", *limaCfg.Memory) require.Equal(t, "qemu", *limaCfg.VMType) require.Equal(t, "reverse-sshfs", *limaCfg.MountType) - require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, len(limaCfg.Provision), 0) }, want: nil, }, @@ -589,8 +510,9 @@ fi VMType: pointer.String("qemu"), Rosetta: pointer.Bool(false), }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, @@ -604,7 +526,7 @@ fi creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") require.NoError(t, err) var limaCfg limayaml.LimaYAML @@ -612,51 +534,59 @@ fi require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, { - name: "lima config file does not contain valid YAML", - config: nil, - path: "/lima.yaml", - isInit: true, + name: "lima config file does not contain valid YAML", + config: &Finch{ + Memory: pointer.String("2GiB"), + CPUs: pointer.Int(4), + VMType: pointer.String("qemu"), + Rosetta: pointer.Bool(false), + }, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, - _ *mocks.Command, - _ *mocks.CommandCreator, + cmd *mocks.Command, + creator *mocks.CommandCreator, _ *mocks.LimaConfigApplierSystemDeps, ) { - err := afero.WriteFile(fs, "/lima.yaml", []byte("this isn't YAML"), 0o600) + err := afero.WriteFile(fs, "/default.yaml", []byte("this isn't YAML"), 0o600) require.NoError(t, err) + cmd.EXPECT().Output().Return([]byte("13.0.0"), nil) + creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") + require.NoError(t, err) + + var limaCfg limayaml.LimaYAML + err = yaml.Unmarshal(buf, &limaCfg) require.NoError(t, err) + require.Equal(t, 4, *limaCfg.CPUs) + require.Equal(t, "2GiB", *limaCfg.Memory) - require.Equal(t, buf, []byte("this isn't YAML")) + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) + require.Equal(t, "system", limaCfg.Provision[0].Mode) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, - want: fmt.Errorf( - "failed to unmarshal the lima config file: %w", - &yaml.TypeError{Errors: []string{"line 1: cannot unmarshal !!str `this is...` into limayaml.LimaYAML"}}, - ), + want: nil, }, { name: "lima config file with additional directories", @@ -667,8 +597,9 @@ fi VMType: pointer.String("qemu"), Rosetta: pointer.Bool(false), }, - path: "/lima.yaml", - isInit: true, + defaultPath: "/default.yaml", + overridePath: "/override.yaml", + isInit: true, mockSvc: func( fs afero.Fs, _ *mocks.Logger, @@ -682,7 +613,7 @@ fi creator.EXPECT().Create("sw_vers", "-productVersion").Return(cmd) }, postRunCheck: func(t *testing.T, fs afero.Fs) { - buf, err := afero.ReadFile(fs, "/lima.yaml") + buf, err := afero.ReadFile(fs, "/override.yaml") require.NoError(t, err) var limaCfg limayaml.LimaYAML @@ -690,26 +621,17 @@ fi require.NoError(t, err) require.Equal(t, 4, *limaCfg.CPUs) require.Equal(t, "2GiB", *limaCfg.Memory) - require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, 1, len(limaCfg.Mounts)) require.Equal(t, "/Volumes", limaCfg.Mounts[0].Location) require.Equal(t, true, *limaCfg.Mounts[0].Writable) + + buf, err = afero.ReadFile(fs, "/default.yaml") + require.NoError(t, err) + err = yaml.Unmarshal(buf, &limaCfg) + require.NoError(t, err) + require.Equal(t, "reverse-sshfs", *limaCfg.MountType) require.Equal(t, "system", limaCfg.Provision[0].Mode) - require.Equal(t, `# cross-arch tools -#!/bin/bash -qemu_pkgs="" -if [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-aarch64" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-arm" -elif [ ! -f /usr/bin/qemu-aarch64-static ]; then - qemu_pkgs="$qemu_pkgs qemu-user-static-x86" -fi - -if [[ $qemu_pkgs ]]; then - dnf install -y --setopt=install_weak_deps=False ${qemu_pkgs} -fi -`, limaCfg.Provision[0].Script) + require.Equal(t, qemuPkgScriptWithHeader, limaCfg.Provision[0].Script) }, want: nil, }, @@ -728,7 +650,13 @@ fi fs := afero.NewMemMapFs() tc.mockSvc(fs, l, cmd, cmdCreator, deps) - got := NewLimaApplier(tc.config, cmdCreator, fs, tc.path, deps).Apply(tc.isInit) + var got error + if tc.isInit { + got = NewLimaApplier(tc.config, cmdCreator, fs, tc.defaultPath, tc.overridePath, deps).ConfigureDefaultLimaYaml() + _ = NewLimaApplier(tc.config, cmdCreator, fs, tc.defaultPath, tc.overridePath, deps).ConfigureOverrideLimaYaml() + } else { + got = NewLimaApplier(tc.config, cmdCreator, fs, tc.defaultPath, tc.overridePath, deps).ConfigureOverrideLimaYaml() + } require.Equal(t, tc.want, got) tc.postRunCheck(t, fs) diff --git a/pkg/config/lima_config_applier_windows.go b/pkg/config/lima_config_applier_windows.go index 538445c55..a69c68fb3 100644 --- a/pkg/config/lima_config_applier_windows.go +++ b/pkg/config/lima_config_applier_windows.go @@ -12,7 +12,7 @@ import ( "github.com/xorcare/pointer" ) -func (lca *limaConfigApplier) applyInit(limaCfg *limayaml.LimaYAML) (*limayaml.LimaYAML, error) { +func (lca *limaConfigApplier) configureVirtualizationFramework(limaCfg *limayaml.LimaYAML) (*limayaml.LimaYAML, error) { // Check if system supports wsl2 if err := SupportsWSL2(lca.cmdCreator); err != nil { diff --git a/pkg/dependency/dependency.go b/pkg/dependency/dependency.go index 4a50fd9c8..c3707366f 100644 --- a/pkg/dependency/dependency.go +++ b/pkg/dependency/dependency.go @@ -82,7 +82,6 @@ func InstallOptionalDeps(groups []*Group, logger flog.Logger) error { errs = append(errs, err) } } - if len(errs) > 0 { return fmt.Errorf("failed to install dependencies: %w", errors.Join(errs...)) } diff --git a/pkg/dependency/vmnet/update_override_lima_config_unix.go b/pkg/dependency/vmnet/update_network_lima_config_unix.go similarity index 71% rename from pkg/dependency/vmnet/update_override_lima_config_unix.go rename to pkg/dependency/vmnet/update_network_lima_config_unix.go index 6d935939a..e68107b14 100644 --- a/pkg/dependency/vmnet/update_override_lima_config_unix.go +++ b/pkg/dependency/vmnet/update_network_lima_config_unix.go @@ -19,8 +19,8 @@ import ( "gopkg.in/yaml.v3" ) -// overrideLimaConfig updates the lima configuration after other network dependencies are installed. -type overrideLimaConfig struct { +// defaultLimaConfig updates the lima configuration after other network dependencies are installed. +type defaultLimaConfig struct { fp path.Finch binaries dependency.Dependency sudoersFile dependency.Dependency @@ -28,16 +28,16 @@ type overrideLimaConfig struct { l flog.Logger } -var _ dependency.Dependency = (*overrideLimaConfig)(nil) +var _ dependency.Dependency = (*defaultLimaConfig)(nil) -func newOverrideLimaConfig( +func newDefaultLimaConfig( fp path.Finch, binaries dependency.Dependency, sudoersFile dependency.Dependency, fs afero.Fs, l flog.Logger, -) *overrideLimaConfig { - return &overrideLimaConfig{ +) *defaultLimaConfig { + return &defaultLimaConfig{ // TODO: consider replacing fp with only the strings that are used instead of the entire type fp: fp, binaries: binaries, @@ -60,7 +60,7 @@ type NetworkConfig struct { } // verifyConfigHasNetworkSection deserializes a yaml file at filePath and verifies that it has the expected value. -func (overConf *overrideLimaConfig) verifyConfigHasNetworkSection(filePath string) bool { +func (overConf *defaultLimaConfig) verifyConfigHasNetworkSection(filePath string) bool { yamlFile, err := afero.ReadFile(overConf.fs, filePath) if err != nil { if errors.Is(err, fs.ErrNotExist) { @@ -73,13 +73,15 @@ func (overConf *overrideLimaConfig) verifyConfigHasNetworkSection(filePath strin var cfg NetworkConfig err = yaml.Unmarshal(yamlFile, &cfg) if err != nil { - overConf.l.Errorf("failed to unmarshal YAML from override config file: %v", err) + overConf.l.Errorf("failed to unmarshal YAML from default config file: %v", err) return false } networksLen := len(cfg.Networks) - if networksLen != 1 { - overConf.l.Errorf("override config file has incorrect number of Networks defined (%d)", networksLen) + if networksLen > 1 { + overConf.l.Errorf("default config file has incorrect number of Networks defined (%d)", networksLen) + return false + } else if networksLen == 0 { return false } @@ -87,7 +89,7 @@ func (overConf *overrideLimaConfig) verifyConfigHasNetworkSection(filePath strin } // appendNetworkConfiguration adds a new network config section to a file at filePath. -func (overConf *overrideLimaConfig) appendNetworkConfiguration(filePath string) error { +func (overConf *defaultLimaConfig) appendNetworkConfiguration(filePath string) error { f, err := overConf.fs.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { return fmt.Errorf("error opening file at path %s, error: %w", filePath, err) @@ -106,24 +108,24 @@ func (overConf *overrideLimaConfig) appendNetworkConfiguration(filePath string) // shouldAddNetworksConfig returns true iff binaries and sudoers are installed as // updating the network config without those dependencies leads to a broken user experience. -func (overConf *overrideLimaConfig) shouldAddNetworksConfig() bool { +func (overConf *defaultLimaConfig) shouldAddNetworksConfig() bool { return overConf.binaries.Installed() && overConf.sudoersFile.Installed() } // Installed returns true iff lima config has been updated. -func (overConf *overrideLimaConfig) Installed() bool { - return overConf.verifyConfigHasNetworkSection(overConf.fp.LimaOverrideConfigPath()) +func (overConf *defaultLimaConfig) Installed() bool { + return overConf.verifyConfigHasNetworkSection(overConf.fp.LimaDefaultConfigPath()) } -// Install adds the networks config block to liam's override config yaml file. +// Install adds the networks config block to lima's default config yaml file. // Only adds if the shouldAddNetworksConfig() helper function is true. -func (overConf *overrideLimaConfig) Install() error { +func (overConf *defaultLimaConfig) Install() error { if !overConf.shouldAddNetworksConfig() { return fmt.Errorf("skipping installation of network configuration because pre-requisites are missing") } - return overConf.appendNetworkConfiguration(overConf.fp.LimaOverrideConfigPath()) + return overConf.appendNetworkConfiguration(overConf.fp.LimaDefaultConfigPath()) } -func (overConf *overrideLimaConfig) RequiresRoot() bool { +func (overConf *defaultLimaConfig) RequiresRoot() bool { return false } diff --git a/pkg/dependency/vmnet/update_override_lima_config_unix_test.go b/pkg/dependency/vmnet/update_network_lima_config_unix_test.go similarity index 83% rename from pkg/dependency/vmnet/update_override_lima_config_unix_test.go rename to pkg/dependency/vmnet/update_network_lima_config_unix_test.go index 873022cee..c7fba4b02 100644 --- a/pkg/dependency/vmnet/update_override_lima_config_unix_test.go +++ b/pkg/dependency/vmnet/update_network_lima_config_unix_test.go @@ -23,7 +23,7 @@ import ( "github.com/runfinch/finch/pkg/path" ) -func TestOverrideLimaConfig_verifyConfigHasNetworkSection(t *testing.T) { +func TestDefaultLimaConfig_verifyConfigHasNetworkSection(t *testing.T) { t.Parallel() testCases := []struct { @@ -62,7 +62,7 @@ func TestOverrideLimaConfig_verifyConfigHasNetworkSection(t *testing.T) { var typeErr yaml.TypeError typeErr.Errors = []string{"line 1: cannot unmarshal !!str `this is...` into vmnet.NetworkConfig"} - l.EXPECT().Errorf("failed to unmarshal YAML from override config file: %v", &typeErr) + l.EXPECT().Errorf("failed to unmarshal YAML from default config file: %v", &typeErr) }, want: false, }, @@ -76,7 +76,7 @@ func TestOverrideLimaConfig_verifyConfigHasNetworkSection(t *testing.T) { ` require.NoError(t, afero.WriteFile(mFs, "mock_config_file", []byte(data), 0o644)) - l.EXPECT().Errorf("override config file has incorrect number of Networks defined (%d)", 2) + l.EXPECT().Errorf("default config file has incorrect number of Networks defined (%d)", 2) }, want: false, }, @@ -101,13 +101,13 @@ func TestOverrideLimaConfig_verifyConfigHasNetworkSection(t *testing.T) { mFs := afero.NewMemMapFs() tc.mockSvc(t, mFs, l) - got := newOverrideLimaConfig("", nil, nil, mFs, l).verifyConfigHasNetworkSection(tc.filePath) + got := newDefaultLimaConfig("", nil, nil, mFs, l).verifyConfigHasNetworkSection(tc.filePath) assert.Equal(t, tc.want, got) }) } } -func TestOverrideLimaConfig_appendNetworkConfiguration(t *testing.T) { +func TestDefaultLimaConfig_appendNetworkConfiguration(t *testing.T) { t.Parallel() testCases := []struct { @@ -138,14 +138,14 @@ func TestOverrideLimaConfig_appendNetworkConfiguration(t *testing.T) { mFs := afero.NewMemMapFs() tc.mockSvc(mFs) - got := newOverrideLimaConfig("", nil, nil, mFs, nil).appendNetworkConfiguration(tc.filePath) + got := newDefaultLimaConfig("", nil, nil, mFs, nil).appendNetworkConfiguration(tc.filePath) require.Equal(t, tc.want, got) tc.postRunCheck(t, mFs) }) } } -func TestOverrideLimaConfig_shouldAddNetworksConfig(t *testing.T) { +func TestDefaultLimaConfig_shouldAddNetworksConfig(t *testing.T) { t.Parallel() testCases := []struct { @@ -188,13 +188,13 @@ func TestOverrideLimaConfig_shouldAddNetworksConfig(t *testing.T) { s := mocks.NewDependency(ctrl) tc.mockSvc(b, s) - got := newOverrideLimaConfig(mockFinchPath, b, s, nil, nil).shouldAddNetworksConfig() + got := newDefaultLimaConfig(mockFinchPath, b, s, nil, nil).shouldAddNetworksConfig() assert.Equal(t, got, tc.want) }) } } -func TestOverrideLimaConfig_Installed(t *testing.T) { +func TestDefaultLimaConfig_Installed(t *testing.T) { t.Parallel() testCases := []struct { @@ -205,7 +205,7 @@ func TestOverrideLimaConfig_Installed(t *testing.T) { { name: "happy path", mockSvc: func(t *testing.T, mFs afero.Fs, fp path.Finch) { - file, err := mFs.Create(fp.LimaOverrideConfigPath()) + file, err := mFs.Create(fp.LimaDefaultConfigPath()) require.NoError(t, err) _, err = file.WriteString(networkConfigString) @@ -223,13 +223,13 @@ func TestOverrideLimaConfig_Installed(t *testing.T) { mFs := afero.NewMemMapFs() tc.mockSvc(t, mFs, mockFinchPath) - got := newOverrideLimaConfig(mockFinchPath, nil, nil, mFs, nil).Installed() + got := newDefaultLimaConfig(mockFinchPath, nil, nil, mFs, nil).Installed() assert.Equal(t, tc.want, got) }) } } -func TestOverrideLimaConfig_Install(t *testing.T) { +func TestDefaultLimaConfig_Install(t *testing.T) { t.Parallel() testCases := []struct { @@ -243,7 +243,7 @@ func TestOverrideLimaConfig_Install(t *testing.T) { b.EXPECT().Installed().Return(true) s.EXPECT().Installed().Return(true) - _, err := mFs.Create(fp.LimaOverrideConfigPath()) + _, err := mFs.Create(fp.LimaDefaultConfigPath()) require.NoError(t, err) }, want: nil, @@ -268,16 +268,16 @@ func TestOverrideLimaConfig_Install(t *testing.T) { mFs := afero.NewMemMapFs() tc.mockSvc(t, b, s, mFs, mockFinchPath) - overrideLimaConfig := newOverrideLimaConfig(mockFinchPath, b, s, mFs, nil) - got := overrideLimaConfig.Install() + defaultLimaConfig := newDefaultLimaConfig(mockFinchPath, b, s, mFs, nil) + got := defaultLimaConfig.Install() assert.Equal(t, got, tc.want) }) } } -func TestOverrideLimaConfig_RequiresRoot(t *testing.T) { +func TestDefaultLimaConfig_RequiresRoot(t *testing.T) { t.Parallel() - got := newOverrideLimaConfig("", nil, nil, nil, nil).RequiresRoot() + got := newDefaultLimaConfig("", nil, nil, nil, nil).RequiresRoot() assert.Equal(t, false, got) } diff --git a/pkg/dependency/vmnet/vmnet_unix.go b/pkg/dependency/vmnet/vmnet_unix.go index 695d17d47..6257dab3c 100644 --- a/pkg/dependency/vmnet/vmnet_unix.go +++ b/pkg/dependency/vmnet/vmnet_unix.go @@ -48,12 +48,12 @@ func newDeps( ) []dependency.Dependency { binaries := newBinaries(fp, fs, execCmdCreator, logger) sudoersFile := newSudoersFile(fs, execCmdCreator, limaCmdCreator, logger) - overrideLimaConfig := newOverrideLimaConfig(fp, binaries, sudoersFile, fs, logger) + defaultLimaConfig := newDefaultLimaConfig(fp, binaries, sudoersFile, fs, logger) - // Ordering of these dependencies is important because overrideLimaConfig has a dependency on binaries and sudoersFile. - // Adding the network configuration to Lima's overrideConfig without first installing binaries and sudoers leads + // Ordering of these dependencies is important because defaultLimaConfig has a dependency on binaries and sudoersFile. + // Adding the network configuration to Lima's defaultConfig without first installing binaries and sudoers leads // to a broken user experience. // Since Group.Install() installs dependencies serially, in-order, and continues to the next dependency after an error, - // overrideLimaConfig itself checks to make sure that binaries and sudoers are installed before installing itself. - return []dependency.Dependency{binaries, sudoersFile, overrideLimaConfig} + // defaultLimaConfig itself checks to make sure that binaries and sudoers are installed before installing itself. + return []dependency.Dependency{binaries, sudoersFile, defaultLimaConfig} } diff --git a/pkg/mocks/pkg_config_lima_config_applier.go b/pkg/mocks/pkg_config_lima_config_applier.go index 968e25947..172eeadd9 100644 --- a/pkg/mocks/pkg_config_lima_config_applier.go +++ b/pkg/mocks/pkg_config_lima_config_applier.go @@ -36,16 +36,30 @@ func (m *LimaConfigApplier) EXPECT() *LimaConfigApplierMockRecorder { return m.recorder } -// Apply mocks base method. -func (m *LimaConfigApplier) Apply(arg0 bool) error { +// ConfigureDefaultLimaYaml mocks base method. +func (m *LimaConfigApplier) ConfigureDefaultLimaYaml() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Apply", arg0) + ret := m.ctrl.Call(m, "ConfigureDefaultLimaYaml") ret0, _ := ret[0].(error) return ret0 } -// Apply indicates an expected call of Apply. -func (mr *LimaConfigApplierMockRecorder) Apply(arg0 interface{}) *gomock.Call { +// ConfigureDefaultLimaYaml indicates an expected call of ConfigureDefaultLimaYaml. +func (mr *LimaConfigApplierMockRecorder) ConfigureDefaultLimaYaml() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*LimaConfigApplier)(nil).Apply), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigureDefaultLimaYaml", reflect.TypeOf((*LimaConfigApplier)(nil).ConfigureDefaultLimaYaml)) +} + +// ConfigureOverrideLimaYaml mocks base method. +func (m *LimaConfigApplier) ConfigureOverrideLimaYaml() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConfigureOverrideLimaYaml") + ret0, _ := ret[0].(error) + return ret0 +} + +// ConfigureOverrideLimaYaml indicates an expected call of ConfigureOverrideLimaYaml. +func (mr *LimaConfigApplierMockRecorder) ConfigureOverrideLimaYaml() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConfigureOverrideLimaYaml", reflect.TypeOf((*LimaConfigApplier)(nil).ConfigureOverrideLimaYaml)) } diff --git a/pkg/path/finch.go b/pkg/path/finch.go index 32a9877dd..b8b60eff1 100644 --- a/pkg/path/finch.go +++ b/pkg/path/finch.go @@ -67,6 +67,11 @@ func (w Finch) LimaConfigDirectoryPath() string { return filepath.Join(string(w), "lima", "data", "_config") } +// LimaDefaultConfigPath returns the lima override config file path. +func (w Finch) LimaDefaultConfigPath() string { + return filepath.Join(string(w), "lima", "data", "_config", "default.yaml") +} + // LimaOverrideConfigPath returns the lima override config file path. func (w Finch) LimaOverrideConfigPath() string { return filepath.Join(string(w), "lima", "data", "_config", "override.yaml") diff --git a/pkg/path/finch_test.go b/pkg/path/finch_test.go index 81b541bab..db462d3f3 100644 --- a/pkg/path/finch_test.go +++ b/pkg/path/finch_test.go @@ -71,6 +71,13 @@ func TestFinch_LimaConfigDirectoryPath(t *testing.T) { assert.Equal(t, res, filepath.Join("mock_finch", "lima", "data", "_config")) } +func TestFinch_LimaDefaultConfigPath(t *testing.T) { + t.Parallel() + + res := mockFinch.LimaDefaultConfigPath() + assert.Equal(t, res, filepath.Join("mock_finch", "lima", "data", "_config", "default.yaml")) +} + func TestFinch_LimaOverrideConfigPath(t *testing.T) { t.Parallel()