summaryrefslogtreecommitdiff
path: root/testutil/fakecontext/context.go
blob: 26f8b4a4ffb786b8a4f7690ada93e5005e32ae06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package fakecontext // import "github.com/docker/docker/testutil/fakecontext"

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

	"github.com/docker/docker/pkg/archive"
)

// New creates a fake build context
func New(t testing.TB, dir string, modifiers ...func(*Fake) error) *Fake {
	t.Helper()
	fakeContext := &Fake{Dir: dir}
	if dir == "" {
		if err := newDir(fakeContext); err != nil {
			t.Fatal(err)
		}
	}

	for _, modifier := range modifiers {
		if err := modifier(fakeContext); err != nil {
			t.Fatal(err)
		}
	}

	return fakeContext
}

func newDir(fake *Fake) error {
	tmp, err := os.MkdirTemp("", "fake-context")
	if err != nil {
		return err
	}
	if err := os.Chmod(tmp, 0755); err != nil {
		return err
	}
	fake.Dir = tmp
	return nil
}

// WithFile adds the specified file (with content) in the build context
func WithFile(name, content string) func(*Fake) error {
	return func(ctx *Fake) error {
		return ctx.Add(name, content)
	}
}

// WithDockerfile adds the specified content as Dockerfile in the build context
func WithDockerfile(content string) func(*Fake) error {
	return WithFile("Dockerfile", content)
}

// WithFiles adds the specified files in the build context, content is a string
func WithFiles(files map[string]string) func(*Fake) error {
	return func(fakeContext *Fake) error {
		for file, content := range files {
			if err := fakeContext.Add(file, content); err != nil {
				return err
			}
		}
		return nil
	}
}

// WithBinaryFiles adds the specified files in the build context, content is binary
func WithBinaryFiles(files map[string]*bytes.Buffer) func(*Fake) error {
	return func(fakeContext *Fake) error {
		for file, content := range files {
			if err := fakeContext.Add(file, content.String()); err != nil {
				return err
			}
		}
		return nil
	}
}

// Fake creates directories that can be used as a build context
type Fake struct {
	Dir string
}

// Add a file at a path, creating directories where necessary
func (f *Fake) Add(file, content string) error {
	return f.addFile(file, []byte(content))
}

func (f *Fake) addFile(file string, content []byte) error {
	fp := filepath.Join(f.Dir, filepath.FromSlash(file))
	dirpath := filepath.Dir(fp)
	if dirpath != "." {
		if err := os.MkdirAll(dirpath, 0755); err != nil {
			return err
		}
	}
	return os.WriteFile(fp, content, 0644)
}

// Delete a file at a path
func (f *Fake) Delete(file string) error {
	fp := filepath.Join(f.Dir, filepath.FromSlash(file))
	return os.RemoveAll(fp)
}

// Close deletes the context
func (f *Fake) Close() error {
	return os.RemoveAll(f.Dir)
}

// AsTarReader returns a ReadCloser with the contents of Dir as a tar archive.
func (f *Fake) AsTarReader(t testing.TB) io.ReadCloser {
	t.Helper()
	reader, err := archive.TarWithOptions(f.Dir, &archive.TarOptions{})
	if err != nil {
		t.Fatalf("Failed to create tar from %s: %s", f.Dir, err)
	}
	return reader
}