Skip to content

Commit

Permalink
Recreate layer symlink if it already exists (#386)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanmoran authored Aug 1, 2022
1 parent f00ab4e commit 08de848
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 87 deletions.
7 changes: 6 additions & 1 deletion cmd/setup-symlinks/internal/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ func Run(executablePath, appDir, tmpDir string) error {
layerPath = fmt.Sprintf("/%s", layerPath)
}

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

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

it("creates a symlink to the node_modules dir in the layer", func() {
Expand All @@ -63,14 +64,31 @@ func testRun(t *testing.T, context spec.G, it spec.S) {
Expect(link).To(Equal(filepath.Join(layerDir, "node_modules")))
})

context("when the symlink already exists", func() {
it.Before(func() {
Expect(os.Symlink("some-location", filepath.Join(tmpDir, "node_modules"))).To(Succeed())
})

it("replaces it", func() {
err := internal.Run(executablePath, appDir, tmpDir)
Expect(err).NotTo(HaveOccurred())

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 tmp dir node_modules cannot be removed", func() {
it.Before(func() {
Expect(os.Chmod(tmpDir, 0444)).To(Succeed())
})

it.After(func() {
Expect(os.Chmod(tmpDir, os.ModePerm)).To(Succeed())
})

it("returns an error", func() {
err := internal.Run(executablePath, appDir, tmpDir)
Expect(err).To(MatchError(ContainSubstring("permission denied")))
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.16
require (
github.com/BurntSushi/toml v1.2.0
github.com/onsi/gomega v1.20.0
github.com/paketo-buildpacks/occam v0.9.0
github.com/paketo-buildpacks/occam v0.11.0
github.com/paketo-buildpacks/packit/v2 v2.3.1
github.com/sclevine/spec v1.4.0
)
80 changes: 2 additions & 78 deletions go.sum

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions integration/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/sclevine/spec/report"

. "github.com/onsi/gomega"
"github.com/onsi/gomega/format"
)

var (
Expand All @@ -31,6 +32,9 @@ var (
)

func TestIntegration(t *testing.T) {
format.MaxLength = 0
SetDefaultEventuallyTimeout(30 * time.Second)

var (
Expect = NewWithT(t).Expect
err error
Expand Down Expand Up @@ -84,22 +88,21 @@ func TestIntegration(t *testing.T) {

npmList = filepath.Join(root, "integration", "testdata", "npm-list-buildpack")

SetDefaultEventuallyTimeout(10 * time.Second)

suite := spec.New("Integration", spec.Parallel(), spec.Report(report.Terminal{}))
suite("Caching", testCaching)
suite("DevDependenciesDuringBuild", testDevDependenciesDuringBuild)
suite("EmptyNodeModules", testEmptyNodeModules)
suite("Logging", testLogging)
suite("NoNodeModules", testNoNodeModules)
suite("Npmrc", testNpmrc)
suite("PackageLockMismatch", testPackageLockMismatch)
suite("PrePostScriptsRebuild", testPrePostScriptRebuild)
suite("ProjectPath", testProjectPath)
suite("Restart", testRestart)
suite("SimpleApp", testSimpleApp)
suite("UnmetDependencies", testUnmetDependencies)
suite("Vendored", testVendored)
suite("VendoredWithBinaries", testVendoredWithBinaries)
suite("Versioning", testVersioning)
suite("PackageLockMismatch", testPackageLockMismatch)
suite("ProjectPath", testProjectPath)
suite.Run(t)
}
83 changes: 83 additions & 0 deletions integration/restart_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package integration_test

import (
"os"
"path/filepath"
"testing"

"github.com/paketo-buildpacks/occam"
"github.com/sclevine/spec"

. "github.com/onsi/gomega"
. "github.com/paketo-buildpacks/occam/matchers"
)

func testRestart(t *testing.T, context spec.G, it spec.S) {
var (
Expect = NewWithT(t).Expect
Eventually = NewWithT(t).Eventually

pack occam.Pack
docker occam.Docker

image occam.Image
container occam.Container

name string
source string
sbomDir string
)

it.Before(func() {
pack = occam.NewPack()
docker = occam.NewDocker()

var err error
name, err = occam.RandomName()
Expect(err).NotTo(HaveOccurred())

sbomDir, err = os.MkdirTemp("", "sbom")
Expect(err).NotTo(HaveOccurred())
Expect(os.Chmod(sbomDir, os.ModePerm)).To(Succeed())
})

it.After(func() {
Expect(docker.Container.Remove.Execute(container.ID)).To(Succeed())
Expect(docker.Image.Remove.Execute(image.ID)).To(Succeed())
Expect(docker.Volume.Remove.Execute(occam.CacheVolumeNames(name))).To(Succeed())
Expect(os.RemoveAll(source)).To(Succeed())
Expect(os.RemoveAll(sbomDir)).To(Succeed())
})

it("allows the process to be restarted", func() {
var err error
source, err = occam.Source(filepath.Join("testdata", "simple_app"))
Expect(err).NotTo(HaveOccurred())

image, _, err = pack.Build.
WithBuildpacks(nodeURI, buildpackURI, buildPlanURI).
WithPullPolicy("never").
WithSBOMOutputDir(sbomDir).
Execute(name, source)
Expect(err).NotTo(HaveOccurred())

container, err = docker.Container.Run.
WithDirect().
WithCommand("node").
WithCommandArgs([]string{"server.js"}).
WithEnv(map[string]string{"PORT": "8080"}).
WithPublish("8080:8080").
Execute(image.ID)
Expect(err).NotTo(HaveOccurred())

Eventually(container).Should(Serve("Hello World!"), func() string {
logs, _ := docker.Container.Logs.Execute(container.ID)
return logs.String()
})

err = docker.Container.Restart.Execute(container.ID)
Expect(err).NotTo(HaveOccurred())

Eventually(container).Should(Serve("Hello World!"))
})
}
12 changes: 9 additions & 3 deletions integration/testdata/simple_app/server.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
const http = require('http');
const leftpad = require('leftpad');

const port = process.env.PORT || 8080;

const server = http.createServer((request, response) => {
response.end(JSON.stringify(process.env))
switch (request.url) {
case '/process':
response.end(JSON.stringify(process.env))
break;

default:
response.end('Hello World!');
}
});

const port = process.env.PORT || 8080;
server.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err);
Expand Down

0 comments on commit 08de848

Please sign in to comment.