Skip to content

Commit f3bcac2

Browse files
authored
refactor: improve overlayFS errors (#17808)
1 parent 4d00b76 commit f3bcac2

File tree

3 files changed

+19
-62
lines changed

3 files changed

+19
-62
lines changed

coderd/files/overlay.go

Lines changed: 17 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ import (
44
"io/fs"
55
"path"
66
"strings"
7-
8-
"golang.org/x/xerrors"
97
)
108

11-
// overlayFS allows you to "join" together the template files tar file fs.FS
12-
// with the Terraform modules tar file fs.FS. We could potentially turn this
13-
// into something more parameterized/configurable, but the requirements here are
14-
// a _bit_ odd, because every file in the modulesFS includes the
15-
// .terraform/modules/ folder at the beginning of it's path.
9+
// overlayFS allows you to "join" together multiple fs.FS. Files in any specific
10+
// overlay will only be accessible if their path starts with the base path
11+
// provided for the overlay. eg. An overlay at the path .terraform/modules
12+
// should contain files with paths inside the .terraform/modules folder.
1613
type overlayFS struct {
1714
baseFS fs.FS
1815
overlays []Overlay
@@ -23,64 +20,32 @@ type Overlay struct {
2320
fs.FS
2421
}
2522

26-
func NewOverlayFS(baseFS fs.FS, overlays []Overlay) (fs.FS, error) {
27-
if err := valid(baseFS); err != nil {
28-
return nil, xerrors.Errorf("baseFS: %w", err)
29-
}
30-
31-
for _, overlay := range overlays {
32-
if err := valid(overlay.FS); err != nil {
33-
return nil, xerrors.Errorf("overlayFS: %w", err)
34-
}
35-
}
36-
23+
func NewOverlayFS(baseFS fs.FS, overlays []Overlay) fs.FS {
3724
return overlayFS{
3825
baseFS: baseFS,
3926
overlays: overlays,
40-
}, nil
27+
}
4128
}
4229

43-
func (f overlayFS) Open(p string) (fs.File, error) {
30+
func (f overlayFS) target(p string) fs.FS {
31+
target := f.baseFS
4432
for _, overlay := range f.overlays {
4533
if strings.HasPrefix(path.Clean(p), overlay.Path) {
46-
return overlay.FS.Open(p)
34+
target = overlay.FS
35+
break
4736
}
4837
}
49-
return f.baseFS.Open(p)
38+
return target
5039
}
5140

52-
func (f overlayFS) ReadDir(p string) ([]fs.DirEntry, error) {
53-
for _, overlay := range f.overlays {
54-
if strings.HasPrefix(path.Clean(p), overlay.Path) {
55-
//nolint:forcetypeassert
56-
return overlay.FS.(fs.ReadDirFS).ReadDir(p)
57-
}
58-
}
59-
//nolint:forcetypeassert
60-
return f.baseFS.(fs.ReadDirFS).ReadDir(p)
41+
func (f overlayFS) Open(p string) (fs.File, error) {
42+
return f.target(p).Open(p)
6143
}
6244

63-
func (f overlayFS) ReadFile(p string) ([]byte, error) {
64-
for _, overlay := range f.overlays {
65-
if strings.HasPrefix(path.Clean(p), overlay.Path) {
66-
//nolint:forcetypeassert
67-
return overlay.FS.(fs.ReadFileFS).ReadFile(p)
68-
}
69-
}
70-
//nolint:forcetypeassert
71-
return f.baseFS.(fs.ReadFileFS).ReadFile(p)
45+
func (f overlayFS) ReadDir(p string) ([]fs.DirEntry, error) {
46+
return fs.ReadDir(f.target(p), p)
7247
}
7348

74-
// valid checks that the fs.FS implements the required interfaces.
75-
// The fs.FS interface is not sufficient.
76-
func valid(fsys fs.FS) error {
77-
_, ok := fsys.(fs.ReadDirFS)
78-
if !ok {
79-
return xerrors.New("overlayFS does not implement ReadDirFS")
80-
}
81-
_, ok = fsys.(fs.ReadFileFS)
82-
if !ok {
83-
return xerrors.New("overlayFS does not implement ReadFileFS")
84-
}
85-
return nil
49+
func (f overlayFS) ReadFile(p string) ([]byte, error) {
50+
return fs.ReadFile(f.target(p), p)
8651
}

coderd/files/overlay_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ func TestOverlayFS(t *testing.T) {
2121
afero.WriteFile(b, ".terraform/modules/modules.json", []byte("{}"), 0o644)
2222
afero.WriteFile(b, ".terraform/modules/example_module/main.tf", []byte("terraform {}"), 0o644)
2323

24-
it, err := files.NewOverlayFS(afero.NewIOFS(a), []files.Overlay{{
24+
it := files.NewOverlayFS(afero.NewIOFS(a), []files.Overlay{{
2525
Path: ".terraform/modules",
2626
FS: afero.NewIOFS(b),
2727
}})
28-
require.NoError(t, err)
2928

3029
content, err := fs.ReadFile(it, "main.tf")
3130
require.NoError(t, err)

coderd/parameters.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,7 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http
9797
return
9898
}
9999
defer api.FileCache.Release(tf.CachedModuleFiles.UUID)
100-
templateFS, err = files.NewOverlayFS(templateFS, []files.Overlay{{Path: ".terraform/modules", FS: moduleFilesFS}})
101-
if err != nil {
102-
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
103-
Message: "Internal error creating overlay filesystem.",
104-
Detail: err.Error(),
105-
})
106-
return
107-
}
100+
templateFS = files.NewOverlayFS(templateFS, []files.Overlay{{Path: ".terraform/modules", FS: moduleFilesFS}})
108101
}
109102
} else if !xerrors.Is(err, sql.ErrNoRows) {
110103
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{

0 commit comments

Comments
 (0)