Skip to content

Commit f0a8fe2

Browse files
authored
Merge pull request #489 from ivo1116/fix-docker-workdir-nonexistent-home-directory
Fix working directory for Docker images without home directories
2 parents 475c35f + 29a621c commit f0a8fe2

2 files changed

Lines changed: 116 additions & 1 deletion

File tree

rundmc/processes/builder.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package processes
22

33
import (
4+
"os"
5+
"path/filepath"
6+
47
"code.cloudfoundry.org/garden"
58
"code.cloudfoundry.org/guardian/rundmc/goci"
69
"code.cloudfoundry.org/guardian/rundmc/users"
@@ -45,7 +48,7 @@ func (p *ProcBuilder) BuildProcess(bndl goci.Bndl, spec garden.ProcessSpec, user
4548
AdditionalGids: additionalGIDs,
4649
Username: spec.User,
4750
},
48-
Cwd: spec.Dir,
51+
Cwd: getRootDir(bndl.RootFS(), spec.Dir, user.Home),
4952
Capabilities: p.capabilities(bndl, user.Gid),
5053
Rlimits: toRlimits(spec.Limits),
5154
Terminal: spec.TTY != nil,
@@ -103,3 +106,21 @@ func toUint32Slice(slice []int) []uint32 {
103106
}
104107
return result
105108
}
109+
110+
func getRootDir(rootFS, specDir, home string) string {
111+
dir := specDir
112+
if dir == "" {
113+
dir = home
114+
}
115+
116+
if dir == "" {
117+
return "/"
118+
}
119+
120+
fullPath := filepath.Join(rootFS, dir)
121+
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
122+
return "/"
123+
}
124+
125+
return dir
126+
}

rundmc/processes/builder_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package processes_test
22

33
import (
4+
"os"
5+
"path/filepath"
6+
47
"code.cloudfoundry.org/garden"
58
"code.cloudfoundry.org/guardian/rundmc/goci"
69
"code.cloudfoundry.org/guardian/rundmc/processes"
@@ -21,13 +24,20 @@ var _ = Describe("ProcBuilder", func() {
2124
bndl goci.Bndl
2225
processSpec garden.ProcessSpec
2326
user *users.ExecUser
27+
tmpRootFS string
2428
)
2529

2630
BeforeEach(func() {
31+
var err error
32+
tmpRootFS, err = os.MkdirTemp("", "rootfs")
33+
Expect(err).NotTo(HaveOccurred())
34+
Expect(os.MkdirAll(filepath.Join(tmpRootFS, "dir"), 0755)).To(Succeed())
35+
2736
envDeterminer = new(fakes.FakeEnvDeterminer)
2837
envDeterminer.EnvForReturns([]string{"ENV"})
2938

3039
bndl = goci.Bundle().
40+
WithRootFS(tmpRootFS).
3141
WithHostname("some-hostname").
3242
WithUIDMappings(specs.LinuxIDMapping{
3343
ContainerID: 0,
@@ -73,6 +83,10 @@ var _ = Describe("ProcBuilder", func() {
7383
}
7484
})
7585

86+
AfterEach(func() {
87+
Expect(os.RemoveAll(tmpRootFS)).To(Succeed())
88+
})
89+
7690
Describe("the built process", func() {
7791
var preparedProc *specs.Process
7892

@@ -207,6 +221,86 @@ var _ = Describe("ProcBuilder", func() {
207221
})
208222
})
209223
})
224+
225+
Describe("working directory resolution", func() {
226+
var (
227+
preparedProc *specs.Process
228+
tmpRootFS string
229+
)
230+
231+
BeforeEach(func() {
232+
var err error
233+
tmpRootFS, err = os.MkdirTemp("", "rootfs")
234+
Expect(err).NotTo(HaveOccurred())
235+
236+
bndl = bndl.WithRootFS(tmpRootFS)
237+
})
238+
239+
AfterEach(func() {
240+
Expect(os.RemoveAll(tmpRootFS)).To(Succeed())
241+
})
242+
243+
JustBeforeEach(func() {
244+
procBuilder = processes.NewBuilder(envDeterminer, nonRootMaxCaps)
245+
preparedProc = procBuilder.BuildProcess(bndl, processSpec, user)
246+
})
247+
248+
Context("when spec.Dir is set", func() {
249+
BeforeEach(func() {
250+
processSpec.Dir = "/app"
251+
})
252+
253+
Context("and the directory exists", func() {
254+
BeforeEach(func() {
255+
Expect(os.MkdirAll(filepath.Join(tmpRootFS, "app"), 0755)).To(Succeed())
256+
})
257+
258+
It("uses spec.Dir as Cwd", func() {
259+
Expect(preparedProc.Cwd).To(Equal("/app"))
260+
})
261+
})
262+
263+
Context("and the directory does not exist", func() {
264+
It("falls back to '/'", func() {
265+
Expect(preparedProc.Cwd).To(Equal("/"))
266+
})
267+
})
268+
})
269+
270+
Context("when spec.Dir is empty", func() {
271+
BeforeEach(func() {
272+
processSpec.Dir = ""
273+
user.Home = "/home/robot"
274+
})
275+
276+
Context("and the home directory exists", func() {
277+
BeforeEach(func() {
278+
Expect(os.MkdirAll(filepath.Join(tmpRootFS, "home", "robot"), 0755)).To(Succeed())
279+
})
280+
281+
It("uses home directory as Cwd", func() {
282+
Expect(preparedProc.Cwd).To(Equal("/home/robot"))
283+
})
284+
})
285+
286+
Context("and the home directory does not exist", func() {
287+
It("falls back to '/'", func() {
288+
Expect(preparedProc.Cwd).To(Equal("/"))
289+
})
290+
})
291+
})
292+
293+
Context("when both spec.Dir and home are empty", func() {
294+
BeforeEach(func() {
295+
processSpec.Dir = ""
296+
user.Home = ""
297+
})
298+
299+
It("falls back to '/'", func() {
300+
Expect(preparedProc.Cwd).To(Equal("/"))
301+
})
302+
})
303+
})
210304
})
211305

212306
func ptr(i uint64) *uint64 {

0 commit comments

Comments
 (0)