Skip to content

Commit a7fb833

Browse files
authored
Tart: mount the working directory to $HOME when --dirty is specified (#723)
* Respect --{,tart-}lazy-pull for non-standby Tart instances * Tart: mount the working directory to $HOME when --dirty is specified To avoid issues with spaces in "/Volumes/My Shared Files".
1 parent b069551 commit a7fb833

File tree

3 files changed

+101
-13
lines changed

3 files changed

+101
-13
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package tart
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/cirruslabs/cirrus-cli/internal/executor/instance/persistentworker/remoteagent"
7+
"github.com/cirruslabs/echelon"
8+
"golang.org/x/crypto/ssh"
9+
)
10+
11+
func mountWorkingDirectoryHook(tag string, logger *echelon.Logger) remoteagent.WaitForAgentHook {
12+
return func(ctx context.Context, sshClient *ssh.Client) error {
13+
syncLogger := logger.Scoped("mounting the working directory")
14+
15+
command := fmt.Sprintf("mkdir %q && mount_virtiofs %q %q",
16+
macOSAutomountDirectoryPath, tag, macOSAutomountDirectoryPath)
17+
18+
syncLogger.Infof("running command: %s", command)
19+
20+
sshSess, err := sshClient.NewSession()
21+
if err != nil {
22+
syncLogger.Finish(false)
23+
return err
24+
}
25+
26+
if err := sshSess.Run(command); err != nil {
27+
_ = sshSess.Close()
28+
29+
syncLogger.Finish(false)
30+
return err
31+
}
32+
33+
_ = sshSess.Close()
34+
35+
syncLogger.Finish(true)
36+
return nil
37+
}
38+
}
39+
40+
func unmountWorkingDirectoryHook(logger *echelon.Logger) remoteagent.WaitForAgentHook {
41+
return func(ctx context.Context, sshClient *ssh.Client) error {
42+
syncLogger := logger.Scoped("unmounting the working directory")
43+
44+
command := fmt.Sprintf("umount %q", macOSAutomountDirectoryPath)
45+
46+
syncLogger.Infof("running command: %s", command)
47+
48+
sshSess, err := sshClient.NewSession()
49+
if err != nil {
50+
syncLogger.Finish(false)
51+
return err
52+
}
53+
54+
if err := sshSess.Run(command); err != nil {
55+
_ = sshSess.Close()
56+
57+
syncLogger.Finish(false)
58+
return err
59+
}
60+
61+
_ = sshSess.Close()
62+
63+
syncLogger.Finish(true)
64+
return nil
65+
}
66+
}

internal/executor/instance/persistentworker/isolation/tart/tart.go

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ var (
3333

3434
const (
3535
vmNamePrefix = "cirrus-cli-"
36-
macOSAutomountDirectoryPath = "/Volumes/My Shared Files"
36+
macOSAutomountDirectoryPath = "$HOME/working-dir"
3737
macOSAutomountDirectoryItem = "working-dir"
3838
)
3939

@@ -50,7 +50,9 @@ type Tart struct {
5050
display string
5151
volumes []*api.Isolation_Tart_Volume
5252

53-
vm *VM
53+
vm *VM
54+
initializeHooks []remoteagent.WaitForAgentHook
55+
terminateHooks []remoteagent.WaitForAgentHook
5456
}
5557

5658
func New(
@@ -101,14 +103,15 @@ func (tart *Tart) Warmup(
101103
additionalEnvironment map[string]string,
102104
logger *echelon.Logger,
103105
) error {
104-
return tart.bootVM(ctx, ident, additionalEnvironment, "", logger)
106+
return tart.bootVM(ctx, ident, additionalEnvironment, "", false, logger)
105107
}
106108

107109
func (tart *Tart) bootVM(
108110
ctx context.Context,
109111
ident string,
110112
additionalEnvironment map[string]string,
111113
automountDir string,
114+
lazyPull bool,
112115
logger *echelon.Logger,
113116
) error {
114117
ctx, prepareInstanceSpan := tracer.Start(ctx, "prepare-instance")
@@ -128,7 +131,7 @@ func (tart *Tart) bootVM(
128131
tmpVMName := vmNamePrefix + identToBeInjected + uuid.NewString()
129132
vm, err := NewVMClonedFrom(ctx,
130133
tart.vmName, tmpVMName,
131-
false, // always clone from the base image
134+
lazyPull,
132135
additionalEnvironment,
133136
logger,
134137
)
@@ -143,11 +146,17 @@ func (tart *Tart) bootVM(
143146

144147
var directoryMounts []directoryMount
145148
if automountDir != "" {
149+
tag := fmt.Sprintf("tart.virtiofs.%s", macOSAutomountDirectoryItem)
150+
146151
directoryMounts = append(directoryMounts, directoryMount{
147152
Name: macOSAutomountDirectoryItem,
148153
Path: automountDir,
154+
Tag: tag,
149155
ReadOnly: false,
150156
})
157+
158+
tart.initializeHooks = append(tart.initializeHooks, mountWorkingDirectoryHook(tag, logger))
159+
tart.terminateHooks = append(tart.terminateHooks, unmountWorkingDirectoryHook(logger))
151160
}
152161

153162
// Convert volumes to directory mounts
@@ -237,7 +246,7 @@ func (tart *Tart) Run(ctx context.Context, config *runconfig.RunConfig) (err err
237246
automountProjectDir = config.ProjectDir
238247
}
239248
err = tart.bootVM(ctx, strconv.FormatInt(config.TaskID, 10), config.AdditionalEnvironment,
240-
automountProjectDir, config.Logger())
249+
automountProjectDir, config.TartOptions.LazyPull, config.Logger())
241250
if err != nil {
242251
return err
243252
}
@@ -249,8 +258,8 @@ func (tart *Tart) Run(ctx context.Context, config *runconfig.RunConfig) (err err
249258
return err
250259
}
251260

252-
initializeHooks := tart.initializeHooks(config)
253-
terminateHooks := tart.terminateHooks(config)
261+
initializeHooks := tart.getInitializeHooks(config)
262+
terminateHooks := tart.getTerminateHooks(config)
254263

255264
addTartListBreadcrumb(ctx)
256265
addDHCPDLeasesBreadcrumb(ctx)
@@ -333,7 +342,7 @@ func Cleanup() error {
333342
return nil
334343
}
335344

336-
func (tart *Tart) initializeHooks(config *runconfig.RunConfig) []remoteagent.WaitForAgentHook {
345+
func (tart *Tart) getInitializeHooks(config *runconfig.RunConfig) []remoteagent.WaitForAgentHook {
337346
var hooks []remoteagent.WaitForAgentHook
338347

339348
if config.ProjectDir != "" && !config.DirtyMode {
@@ -365,12 +374,14 @@ func (tart *Tart) initializeHooks(config *runconfig.RunConfig) []remoteagent.Wai
365374

366375
sshSess, err := sshClient.NewSession()
367376
if err != nil {
377+
syncLogger.Finish(false)
368378
return err
369379
}
370380

371381
if err := sshSess.Run(command); err != nil {
372382
_ = sshSess.Close()
373383

384+
syncLogger.Finish(false)
374385
return err
375386
}
376387

@@ -382,10 +393,10 @@ func (tart *Tart) initializeHooks(config *runconfig.RunConfig) []remoteagent.Wai
382393
})
383394
}
384395

385-
return hooks
396+
return append(tart.initializeHooks, hooks...)
386397
}
387398

388-
func (tart *Tart) terminateHooks(config *runconfig.RunConfig) []remoteagent.WaitForAgentHook {
399+
func (tart *Tart) getTerminateHooks(config *runconfig.RunConfig) []remoteagent.WaitForAgentHook {
389400
var hooks []remoteagent.WaitForAgentHook
390401

391402
targetfulVolumes := lo.Filter(tart.volumes, func(volume *api.Isolation_Tart_Volume, index int) bool {
@@ -420,7 +431,7 @@ func (tart *Tart) terminateHooks(config *runconfig.RunConfig) []remoteagent.Wait
420431
})
421432
}
422433

423-
return hooks
434+
return append(tart.terminateHooks, hooks...)
424435
}
425436

426437
func addTartListBreadcrumb(ctx context.Context) {

internal/executor/instance/persistentworker/isolation/tart/vm.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type VM struct {
2424
type directoryMount struct {
2525
Name string
2626
Path string
27+
Tag string
2728
ReadOnly bool
2829
}
2930

@@ -146,10 +147,20 @@ func (vm *VM) Start(
146147
}
147148

148149
for _, directoryMount := range directoryMounts {
149-
dirArgumentValue := fmt.Sprintf("%s:%s", directoryMount.Name, directoryMount.Path)
150+
var opts []string
151+
152+
if tag := directoryMount.Tag; tag != "" {
153+
opts = append(opts, fmt.Sprintf("tag=%s", tag))
154+
}
150155

151156
if directoryMount.ReadOnly {
152-
dirArgumentValue += ":ro"
157+
opts = append(opts, "ro")
158+
}
159+
160+
dirArgumentValue := fmt.Sprintf("%s:%s", directoryMount.Name, directoryMount.Path)
161+
162+
if len(opts) != 0 {
163+
dirArgumentValue += ":" + strings.Join(opts, ",")
153164
}
154165

155166
args = append(args, "--dir", dirArgumentValue)

0 commit comments

Comments
 (0)