Skip to content

Commit

Permalink
image: add tests, ensure path hashes are os-agnostic
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronFriel committed Mar 16, 2023
1 parent e8d2547 commit 783a801
Show file tree
Hide file tree
Showing 25 changed files with 104 additions and 12 deletions.
22 changes: 11 additions & 11 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"io"
"io/fs"
"os"
"path"
"path/filepath"
"runtime"
"strings"
Expand Down Expand Up @@ -432,8 +433,7 @@ type contextHashAccumulator struct {
input bytes.Buffer // This will hold the file info and content bytes to pass to a hash object
}

func (accumulator *contextHashAccumulator) hashPath(path string, fileMode fs.FileMode) error {

func (accumulator *contextHashAccumulator) hashPath(file string, fileMode fs.FileMode) error {
hash := sha256.New()

if fileMode.Type() == fs.ModeSymlink {
Expand All @@ -442,31 +442,31 @@ func (accumulator *contextHashAccumulator) hashPath(path string, fileMode fs.Fil
// a) ignore changes at the symlink target
// b) detect if the symlink _itself_ changes
// c) avoid a panic on io.Copy if the symlink target is a directory
symLinkPath, err := filepath.EvalSymlinks(filepath.Join(accumulator.dockerContextPath, path))
symLinkPath, err := filepath.EvalSymlinks(filepath.Join(accumulator.dockerContextPath, file))
if err != nil {
return fmt.Errorf("could not evaluate symlink at %s: %w", path, err)
return fmt.Errorf("could not evaluate symlink at %s: %w", file, err)
}
symLinkReader := strings.NewReader(symLinkPath)
_, err = io.Copy(hash, symLinkReader)
// Hashed content is the clean, os-agnostic file path:
_, err = io.Copy(hash, strings.NewReader(path.Clean(symLinkPath)))
if err != nil {
return fmt.Errorf("could not copy symlink path %s to hash: %w", path, err)
return fmt.Errorf("could not copy symlink path %s to hash: %w", file, err)
}
} else {
// For regular files, we can hash their content.
// TODO: consider only hashing file metadata to improve performance
f, err := os.Open(filepath.Join(accumulator.dockerContextPath, path))
f, err := os.Open(filepath.Join(accumulator.dockerContextPath, file))
if err != nil {
return fmt.Errorf("could not open file %s: %w", path, err)
return fmt.Errorf("could not open file %s: %w", file, err)
}
defer f.Close()
_, err = io.Copy(hash, f)
if err != nil {
return fmt.Errorf("could not copy file %s to hash: %w", path, err)
return fmt.Errorf("could not copy file %s to hash: %w", file, err)
}
}

// Capture all information in the accumulator buffer and add a separator
accumulator.input.Write([]byte(path))
accumulator.input.Write([]byte(filepath.Clean(file))) // use os-agnostic filepath
accumulator.input.Write([]byte(fileMode.String()))
accumulator.input.Write(hash.Sum(nil))
accumulator.input.WriteByte(0)
Expand Down
39 changes: 38 additions & 1 deletion provider/provider_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package provider

import (
"testing"

"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
rpc "github.com/pulumi/pulumi/sdk/v3/proto/go"
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/require"
)

func TestDiffUpdates(t *testing.T) {
Expand Down Expand Up @@ -106,3 +108,38 @@ func TestDiffUpdates(t *testing.T) {
})

}

func TestHashIgnoresFile(t *testing.T) {
baseResult, err := hashContext("./testdata/ignores/basedir", "./Dockerfile")
require.NoError(t, err)

result, err := hashContext("./testdata/ignores/basedir-with-ignored-files", "./Dockerfile")
require.NoError(t, err)

assert.Equal(t, result, baseResult)
}

func TestHashRenamingMatters(t *testing.T) {
baseResult, err := hashContext("./testdata/renaming-matters/step1", "./Dockerfile")
require.NoError(t, err)

result, err := hashContext("./testdata/renaming-matters/step2", "./Dockerfile")
require.NoError(t, err)

assert.NotEqual(t, result, baseResult)
}

func TestHashFilemodeMatters(t *testing.T) {
baseResult, err := hashContext("./testdata/filemode-matters/step1", "./Dockerfile")
require.NoError(t, err)

result, err := hashContext("./testdata/filemode-matters/step2-chmod-x", "./Dockerfile")
require.NoError(t, err)

assert.NotEqual(t, result, baseResult)
}

func TestHashDeepSymlinks(t *testing.T) {
_, err := hashContext("./testdata/symlinks", "./Dockerfile")
assert.NoError(t, err)
}
5 changes: 5 additions & 0 deletions provider/testdata/filemode-matters/step1/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch

WORKDIR /app

COPY ./bar .
3 changes: 3 additions & 0 deletions provider/testdata/filemode-matters/step1/foo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

echo "Hello, World!"
5 changes: 5 additions & 0 deletions provider/testdata/filemode-matters/step2-chmod-x/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch

WORKDIR /app

COPY ./bar .
3 changes: 3 additions & 0 deletions provider/testdata/filemode-matters/step2-chmod-x/foo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

echo "Hello, World!"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.dockerignore
ignored.txt
bar/ignored.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch

WORKDIR /app

COPY ./bar .
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("Pulumi 💜");
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
Empty file.
5 changes: 5 additions & 0 deletions provider/testdata/ignores/basedir/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch

WORKDIR /app

COPY ./bar .
1 change: 1 addition & 0 deletions provider/testdata/ignores/basedir/bar/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("Pulumi 💜");
1 change: 1 addition & 0 deletions provider/testdata/ignores/basedir/foo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
5 changes: 5 additions & 0 deletions provider/testdata/renaming-matters/step1/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch

WORKDIR /app

COPY ./bar .
1 change: 1 addition & 0 deletions provider/testdata/renaming-matters/step1/foo.a.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test
5 changes: 5 additions & 0 deletions provider/testdata/renaming-matters/step2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch

WORKDIR /app

COPY ./bar .
1 change: 1 addition & 0 deletions provider/testdata/renaming-matters/step2/foo.b.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test
5 changes: 5 additions & 0 deletions provider/testdata/symlinks/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch

WORKDIR /app

COPY ./bar .
1 change: 1 addition & 0 deletions provider/testdata/symlinks/linkedFromDeep.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello,
1 change: 1 addition & 0 deletions provider/testdata/symlinks/linkedToDeep.txt
1 change: 1 addition & 0 deletions provider/testdata/symlinks/proxy-for-sub
1 change: 1 addition & 0 deletions provider/testdata/symlinks/sub/dir/linkedFromTop.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
World!
1 change: 1 addition & 0 deletions provider/testdata/symlinks/sub/dir/linkedToTop.txt

0 comments on commit 783a801

Please sign in to comment.