Skip to content

Commit 57a8e99

Browse files
authored
Merge pull request #449 from roots/refactor-lima-config-management
Refactor Lima config management
2 parents 4122c50 + bca23c1 commit 57a8e99

File tree

5 files changed

+204
-59
lines changed

5 files changed

+204
-59
lines changed

cmd/vm_start.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,19 @@ func (c *VmStartCommand) Run(args []string) int {
7373
return 1
7474
}
7575

76-
// VM doesn't exist yet, create it
76+
// VM doesn't exist yet, create and start it
7777
if err = manager.CreateInstance(siteName); err != nil {
7878
c.UI.Error("Error creating VM.")
7979
c.UI.Error(err.Error())
8080
return 1
8181
}
8282

83+
if err = manager.StartInstance(siteName); err != nil {
84+
c.UI.Error("Error starting VM.")
85+
c.UI.Error(err.Error())
86+
return 1
87+
}
88+
8389
c.UI.Info("\nProvisioning VM...")
8490

8591
provisionCmd := NewProvisionCommand(c.UI, c.Trellis)

pkg/lima/instance.go

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package lima
22

33
import (
4+
"bytes"
45
_ "embed"
56
"errors"
67
"fmt"
78
"os"
9+
"path/filepath"
810
"regexp"
911
"text/template"
1012

@@ -40,7 +42,6 @@ type Config struct {
4042
}
4143

4244
type Instance struct {
43-
ConfigFile string
4445
InventoryFile string
4546
Sites map[string]*trellis.Site
4647
Name string `json:"name"`
@@ -55,16 +56,29 @@ type Instance struct {
5556
Username string `json:"username,omitempty"`
5657
}
5758

58-
func (i *Instance) CreateConfig() error {
59+
func (i *Instance) ConfigFile() string {
60+
return filepath.Join(i.Dir, "lima.yaml")
61+
}
62+
63+
func (i *Instance) GenerateConfig() (*bytes.Buffer, error) {
64+
var contents bytes.Buffer
65+
5966
tpl := template.Must(template.New("lima").Parse(ConfigTemplate))
6067

61-
file, err := os.Create(i.ConfigFile)
62-
if err != nil {
63-
return fmt.Errorf("%v: %w", ConfigErr, err)
68+
if err := tpl.Execute(&contents, i); err != nil {
69+
return &contents, fmt.Errorf("%v: %w", ConfigErr, err)
6470
}
6571

66-
err = tpl.Execute(file, i)
72+
return &contents, nil
73+
}
74+
75+
func (i *Instance) UpdateConfig() error {
76+
contents, err := i.GenerateConfig()
6777
if err != nil {
78+
return err
79+
}
80+
81+
if err := os.WriteFile(i.ConfigFile(), contents.Bytes(), 0666); err != nil {
6882
return fmt.Errorf("%v: %w", ConfigErr, err)
6983
}
7084

@@ -91,15 +105,6 @@ func (i *Instance) CreateInventoryFile() error {
91105
return nil
92106
}
93107

94-
func (i *Instance) DeleteConfig() error {
95-
err := os.Remove(i.ConfigFile)
96-
if err != nil {
97-
return fmt.Errorf("Could not delete config file: %v", err)
98-
}
99-
100-
return nil
101-
}
102-
103108
/*
104109
Gets the IP address of the instance using the output of `ip route`:
105110
default via 192.168.64.1 proto dhcp src 192.168.64.2 metric 100

pkg/lima/instance_test.go

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,17 @@ import (
1010
"github.com/roots/trellis-cli/trellis"
1111
)
1212

13-
func TestCreateConfig(t *testing.T) {
13+
func TestGenerateConfig(t *testing.T) {
1414
defer trellis.LoadFixtureProject(t)()
1515
trellis := trellis.NewTrellis()
1616
if err := trellis.LoadProject(); err != nil {
1717
t.Fatal(err)
1818
}
1919

2020
dir := t.TempDir()
21-
configFile := filepath.Join(dir, "lima.yaml")
2221

2322
instance := &Instance{
24-
Dir: dir,
25-
ConfigFile: configFile,
23+
Dir: dir,
2624
Config: Config{
2725
Images: []Image{
2826
{
@@ -40,12 +38,83 @@ func TestCreateConfig(t *testing.T) {
4038
Sites: trellis.Environments["development"].WordPressSites,
4139
}
4240

43-
err := instance.CreateConfig()
41+
content, err := instance.GenerateConfig()
4442
if err != nil {
4543
t.Fatal(err)
4644
}
4745

48-
content, err := os.ReadFile(configFile)
46+
absSitePath := filepath.Join(trellis.Path, "../site")
47+
48+
expected := fmt.Sprintf(`vmType: "vz"
49+
rosetta:
50+
enabled: false
51+
images:
52+
- location: http://ubuntu.com/focal
53+
arch: aarch64
54+
55+
mounts:
56+
- location: %s
57+
mountPoint: /srv/www/example.com/current
58+
writable: true
59+
60+
mountType: "virtiofs"
61+
ssh:
62+
forwardAgent: true
63+
networks:
64+
- vzNAT: true
65+
66+
portForwards:
67+
- guestPort: 80
68+
hostPort: 1234
69+
70+
containerd:
71+
user: false
72+
provision:
73+
- mode: system
74+
script: |
75+
#!/bin/bash
76+
echo "127.0.0.1 $(hostname)" >> /etc/hosts
77+
`, absSitePath)
78+
79+
if content.String() != expected {
80+
t.Errorf("expected %s\ngot %s", expected, content.String())
81+
}
82+
}
83+
84+
func TestUpdateConfig(t *testing.T) {
85+
defer trellis.LoadFixtureProject(t)()
86+
trellis := trellis.NewTrellis()
87+
if err := trellis.LoadProject(); err != nil {
88+
t.Fatal(err)
89+
}
90+
91+
dir := t.TempDir()
92+
93+
instance := &Instance{
94+
Dir: dir,
95+
Config: Config{
96+
Images: []Image{
97+
{
98+
Location: "http://ubuntu.com/focal",
99+
Arch: "aarch64",
100+
},
101+
},
102+
PortForwards: []PortForward{
103+
{
104+
HostPort: 1234,
105+
GuestPort: 80,
106+
},
107+
},
108+
},
109+
Sites: trellis.Environments["development"].WordPressSites,
110+
}
111+
112+
err := instance.UpdateConfig()
113+
if err != nil {
114+
t.Fatal(err)
115+
}
116+
117+
content, err := os.ReadFile(instance.ConfigFile())
49118

50119
if err != nil {
51120
t.Fatal(err)

pkg/lima/manager.go

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,18 @@ func (m *Manager) GetInstance(name string) (Instance, bool) {
8080
func (m *Manager) CreateInstance(name string) error {
8181
instance := m.newInstance(name)
8282

83-
if err := instance.CreateConfig(); err != nil {
84-
return err
85-
}
86-
87-
err := command.WithOptions(
83+
cmd := command.WithOptions(
8884
command.WithTermOutput(),
8985
command.WithLogging(m.ui),
90-
).Cmd("limactl", []string{"start", "--tty=false", "--name=" + instance.Name, instance.ConfigFile}).Run()
86+
).Cmd("limactl", []string{"create", "--tty=false", "--name=" + instance.Name, "-"})
9187

88+
configContents, err := instance.GenerateConfig()
9289
if err != nil {
9390
return err
9491
}
9592

96-
return postStart(m, instance)
93+
cmd.Stdin = configContents
94+
return cmd.Run()
9795
}
9896

9997
func (m *Manager) DeleteInstance(name string) error {
@@ -114,10 +112,6 @@ func (m *Manager) DeleteInstance(name string) error {
114112
return err
115113
}
116114

117-
if err := instance.DeleteConfig(); err != nil {
118-
return err
119-
}
120-
121115
return nil
122116
} else {
123117
return fmt.Errorf("Error: VM is running. Run `trellis vm stop` to stop it.")
@@ -158,6 +152,10 @@ func (m *Manager) StartInstance(name string) error {
158152
return nil
159153
}
160154

155+
if err := instance.UpdateConfig(); err != nil {
156+
return err
157+
}
158+
161159
err := command.WithOptions(
162160
command.WithTermOutput(),
163161
command.WithLogging(m.ui),
@@ -167,7 +165,24 @@ func (m *Manager) StartInstance(name string) error {
167165
return err
168166
}
169167

170-
return postStart(m, instance)
168+
user, err := instance.getUsername()
169+
if err != nil {
170+
return fmt.Errorf("Could not get username: %v", err)
171+
}
172+
173+
instance.Username = string(user)
174+
175+
// Hydrate instance with data from limactl that is only available after starting (mainly the forwarded SSH local port)
176+
err = m.hydrateInstance(&instance)
177+
if err != nil {
178+
return err
179+
}
180+
181+
if err = m.addHosts(instance); err != nil {
182+
return err
183+
}
184+
185+
return nil
171186
}
172187

173188
func (m *Manager) StopInstance(name string) error {
@@ -213,7 +228,6 @@ func (m *Manager) hydrateInstance(instance *Instance) error {
213228
}
214229

215230
func (m *Manager) initInstance(instance *Instance) {
216-
instance.ConfigFile = filepath.Join(m.ConfigPath, instance.Name+".yml")
217231
instance.InventoryFile = m.InventoryPath()
218232
instance.Sites = m.Sites
219233
}
@@ -281,27 +295,6 @@ func (m *Manager) removeHosts(instance Instance) error {
281295
return m.HostsResolver.RemoveHosts(instance.Name)
282296
}
283297

284-
func postStart(manager *Manager, instance Instance) error {
285-
user, err := instance.getUsername()
286-
if err != nil {
287-
return fmt.Errorf("Could not get username: %v", err)
288-
}
289-
290-
instance.Username = string(user)
291-
292-
// Hydrate instance with data from limactl that is only available after starting (mainly the forwarded SSH local port)
293-
err = manager.hydrateInstance(&instance)
294-
if err != nil {
295-
return err
296-
}
297-
298-
if err = manager.addHosts(instance); err != nil {
299-
return err
300-
}
301-
302-
return nil
303-
}
304-
305298
func getMacOSVersion() (string, error) {
306299
cmd := command.Cmd("sw_vers", []string{"-productVersion"})
307300
b, err := cmd.Output()

0 commit comments

Comments
 (0)