Skip to content

Commit

Permalink
Create intermediate symlink for switching between build and launch mo…
Browse files Browse the repository at this point in the history
…dules
  • Loading branch information
thitch97 authored and ryanmoran committed Jul 14, 2022
1 parent 5c69c85 commit f9c3c9a
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 38 deletions.
21 changes: 10 additions & 11 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ func Build(projectPathParser PathParser,
pruneProcess PruneProcess,
clock chronos.Clock,
logger scribe.Emitter,
sbomGenerator SBOMGenerator) packit.BuildFunc {
sbomGenerator SBOMGenerator,
tmpDir string,
) packit.BuildFunc {
return func(context packit.BuildContext) (packit.BuildResult, error) {
logger.Title("%s %s", context.BuildpackInfo.Name, context.BuildpackInfo.Version)

Expand Down Expand Up @@ -219,11 +221,17 @@ func Build(projectPathParser PathParser,
return packit.BuildResult{}, err
}

err = os.Symlink(filepath.Join(buildLayerPath, "node_modules"), filepath.Join(projectPath, "node_modules"))
err = os.Symlink(filepath.Join(buildLayerPath, "node_modules"), filepath.Join(tmpDir, "node_modules"))
if err != nil {
return packit.BuildResult{}, err
}

err = os.Symlink(filepath.Join(tmpDir, "node_modules"), filepath.Join(projectPath, "node_modules"))
if err != nil {
return packit.BuildResult{}, err
}

layer.ExecD = []string{filepath.Join(context.CNBPath, "bin", "setup-symlinks")}
}

logger.Action("Completed in %s", duration.Round(time.Millisecond))
Expand Down Expand Up @@ -264,7 +272,6 @@ func Build(projectPathParser PathParser,
}
}

layer.ExecD = []string{filepath.Join(context.CNBPath, "bin", "setup-symlinks")}
} else {
logger.Process("Reusing cached layer %s", layer.Path)
if !build {
Expand Down Expand Up @@ -295,14 +302,6 @@ func Build(projectPathParser PathParser,
return packit.BuildResult{}, err
}

// Makes the projectPath group-writable to facilitate executing exec.d
// script at runtime under a different uid.
// https://github.com/paketo-buildpacks/rfcs/blob/main/text/0045-user-ids.md
err = os.Chmod(projectPath, 0775)
if err != nil {
return packit.BuildResult{}, err
}

logger.Break()

return packit.BuildResult{Layers: layers}, nil
Expand Down
28 changes: 18 additions & 10 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Expect = NewWithT(t).Expect

layersDir string
tmpDir string
workingDir string
cnbDir string

Expand All @@ -49,6 +50,9 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
layersDir, err = os.MkdirTemp("", "layers")
Expect(err).NotTo(HaveOccurred())

tmpDir, err = os.MkdirTemp("", "tmp")
Expect(err).NotTo(HaveOccurred())

workingDir, err = os.MkdirTemp("", "working-dir")
Expect(err).NotTo(HaveOccurred())

Expand Down Expand Up @@ -103,11 +107,13 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
chronos.DefaultClock,
logger,
sbomGenerator,
tmpDir,
)
})

it.After(func() {
Expect(os.RemoveAll(layersDir)).To(Succeed())
Expect(os.RemoveAll(tmpDir)).To(Succeed())
Expect(os.RemoveAll(workingDir)).To(Succeed())
})

Expand Down Expand Up @@ -193,10 +199,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Expect(processWorkingDir).To(Equal(workingDir))
Expect(processNpmrcPath).To(Equal(""))

workingDirInfo, err := os.Stat(workingDir)
Expect(err).NotTo(HaveOccurred())
Expect(workingDirInfo.Mode()).To(Equal(os.FileMode(os.ModeDir | 0775)))

})
})

Expand Down Expand Up @@ -243,9 +245,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
map[string]interface{}{
"cache_sha": "some-sha",
}))
Expect(launchLayer.ExecD).To(Equal([]string{
filepath.Join(cnbDir, "bin", "setup-symlinks"),
}))

Expect(launchLayer.SBOM.Formats()).To(Equal([]packit.SBOMFormat{
{
Expand Down Expand Up @@ -370,6 +369,9 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
map[string]interface{}{
"cache_sha": "some-sha",
}))
Expect(launchLayer.ExecD).To(Equal([]string{
filepath.Join(cnbDir, "bin", "setup-symlinks"),
}))

Expect(launchLayer.SBOM.Formats()).To(Equal([]packit.SBOMFormat{
{
Expand Down Expand Up @@ -401,6 +403,15 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Expect(pruneProcess.RunCall.Receives.CacheDir).To(Equal(cacheLayer.Path))
Expect(pruneProcess.RunCall.Receives.WorkingDir).To(Equal(workingDir))
Expect(pruneProcess.RunCall.Receives.NpmrcPath).To(Equal(""))

link, err := os.Readlink(filepath.Join(tmpDir, "node_modules"))
Expect(err).NotTo(HaveOccurred())
Expect(link).To(Equal(filepath.Join(buildLayer.Path, "node_modules")))

link, err = os.Readlink(filepath.Join(workingDir, "node_modules"))
Expect(err).NotTo(HaveOccurred())
Expect(link).To(Equal(filepath.Join(tmpDir, "node_modules")))

})
})

Expand Down Expand Up @@ -514,9 +525,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Expect(processCacheDir).To(Equal(filepath.Join(layersDir, npminstall.LayerNameCache)))
Expect(processWorkingDir).To(Equal(filepath.Join(workingDir, "some-dir")))

procWorkingDirInfo, err := os.Stat(processWorkingDir)
Expect(err).NotTo(HaveOccurred())
Expect(procWorkingDirInfo.Mode()).To(Equal(os.FileMode(os.ModeDir | 0775)))
})
})

Expand Down
9 changes: 2 additions & 7 deletions cmd/setup-symlinks/internal/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@ import (
"strings"
)

func Run(executablePath, appDir string) error {
func Run(executablePath, appDir, tmpDir string) error {
fname := strings.Split(executablePath, "/")
layerPath := filepath.Join(fname[:len(fname)-2]...)
if filepath.IsAbs(executablePath) {
layerPath = fmt.Sprintf("/%s", layerPath)
}

err := os.RemoveAll(filepath.Join(appDir, "node_modules"))
if err != nil {
return err
}

err = os.Symlink(filepath.Join(layerPath, "node_modules"), filepath.Join(appDir, "node_modules"))
err := os.Symlink(filepath.Join(layerPath, "node_modules"), filepath.Join(tmpDir, "node_modules"))
if err != nil {
return err
}
Expand Down
18 changes: 10 additions & 8 deletions cmd/setup-symlinks/internal/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func testRun(t *testing.T, context spec.G, it spec.S) {
layerDir string
executablePath string
appDir string
tmpDir string
)

it.Before(func() {
Expand All @@ -35,6 +36,9 @@ func testRun(t *testing.T, context spec.G, it spec.S) {
appDir, err = os.MkdirTemp("", "appDir")
Expect(err).NotTo(HaveOccurred())

tmpDir, err = os.MkdirTemp("", "tmp")
Expect(err).NotTo(HaveOccurred())

Expect(os.MkdirAll(filepath.Join(layerDir, "node_modules"), os.ModePerm)).To(Succeed())

executablePath = filepath.Join(layerDir, "execd", "0-setup-symlinks")
Expand All @@ -43,8 +47,6 @@ func testRun(t *testing.T, context spec.G, it spec.S) {
err = os.WriteFile(executablePath, []byte(""), 0600)
Expect(err).NotTo(HaveOccurred())

Expect(os.Symlink("build-modules", filepath.Join(appDir, "node_modules"))).To(Succeed())

})

it.After(func() {
Expand All @@ -53,24 +55,24 @@ func testRun(t *testing.T, context spec.G, it spec.S) {
})

it("creates a symlink to the node_modules dir in the layer", func() {
err := internal.Run(executablePath, appDir)
err := internal.Run(executablePath, appDir, tmpDir)
Expect(err).NotTo(HaveOccurred())

link, err := os.Readlink(filepath.Join(appDir, "node_modules"))
link, err := os.Readlink(filepath.Join(tmpDir, "node_modules"))
Expect(err).NotTo(HaveOccurred())
Expect(link).To(Equal(filepath.Join(layerDir, "node_modules")))
})

context("failure cases", func() {
context("when the app dir node_modules cannot be removed", func() {
context("when the tmp dir node_modules cannot be removed", func() {
it.Before(func() {
Expect(os.Chmod(appDir, 0444)).To(Succeed())
Expect(os.Chmod(tmpDir, 0444)).To(Succeed())
})
it.After(func() {
Expect(os.Chmod(appDir, os.ModePerm)).To(Succeed())
Expect(os.Chmod(tmpDir, os.ModePerm)).To(Succeed())
})
it("returns an error", func() {
err := internal.Run(executablePath, appDir)
err := internal.Run(executablePath, appDir, tmpDir)
Expect(err).To(MatchError(ContainSubstring("permission denied")))
})
})
Expand Down
2 changes: 1 addition & 1 deletion cmd/setup-symlinks/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func main() {
log.Fatal(err)
}

err = internal.Run(os.Args[0], wd)
err = internal.Run(os.Args[0], wd, "/tmp")
if err != nil {
log.Fatal(err)
}
Expand Down
5 changes: 4 additions & 1 deletion run/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func main() {
entryResolver := draft.NewPlanner()
sbomGenerator := SBOMGenerator{}
packageManagerConfigurationManager := npminstall.NewPackageManagerConfigurationManager(servicebindings.NewResolver(), logger)
tmpDir := "/tmp"

packit.Run(
npminstall.Detect(
Expand All @@ -45,6 +46,8 @@ func main() {
pruneBuildProcess,
chronos.DefaultClock,
logger,
sbomGenerator),
sbomGenerator,
tmpDir,
),
)
}

0 comments on commit f9c3c9a

Please sign in to comment.