Skip to content

Commit ddc8feb

Browse files
committed
feedback: address feedback and fix tests on windows
1 parent eba47c0 commit ddc8feb

File tree

5 files changed

+144
-71
lines changed

5 files changed

+144
-71
lines changed

pkg/secrets-store/nodeserver_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ func TestNodeUnpublishVolume(t *testing.T) {
363363
name: "Success for a mounted volume with a retry",
364364
nodeUnpublishVolReq: csi.NodeUnpublishVolumeRequest{
365365
VolumeId: "testvolid1",
366-
TargetPath: tmpdir.New(t, "", `*\\pods\\fakePod\\volumes\\kubernetes.io~csi\\myvol\\mount`),
366+
TargetPath: tmpdir.New(t, "", `*mount`),
367367
},
368368
mountPoints: []mount.MountPoint{},
369369
shouldRetryUnmount: true,

pkg/secrets-store/provider_client_test.go

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"os"
2424
"reflect"
25+
"runtime"
2526
"sync"
2627
"testing"
2728
"time"
@@ -64,6 +65,7 @@ func TestMountContent(t *testing.T) {
6465
files []*v1alpha1.File
6566
// expectations
6667
expectedFiles map[string]os.FileMode
68+
skipon string
6769
}{
6870
{
6971
name: "provider successful response (no files)",
@@ -77,13 +79,13 @@ func TestMountContent(t *testing.T) {
7779
files: []*v1alpha1.File{
7880
{
7981
Path: "foo",
80-
Mode: 0644,
82+
Mode: 0666,
8183
Contents: []byte("foo"),
8284
},
8385
},
8486
objectVersions: map[string]string{"foo": "v1"},
8587
expectedFiles: map[string]os.FileMode{
86-
"foo": 0644,
88+
"foo": 0666,
8789
},
8890
},
8991
{
@@ -92,23 +94,23 @@ func TestMountContent(t *testing.T) {
9294
files: []*v1alpha1.File{
9395
{
9496
Path: "foo",
95-
Mode: 0644,
97+
Mode: 0666,
9698
Contents: []byte("foo"),
9799
},
98100
{
99101
Path: "bar",
100-
Mode: 0777,
102+
Mode: 0444,
101103
Contents: []byte("bar"),
102104
},
103105
},
104106
objectVersions: map[string]string{"foo": "v1"},
105107
expectedFiles: map[string]os.FileMode{
106-
"foo": 0644,
107-
"bar": 0777,
108+
"foo": 0666,
109+
"bar": 0444,
108110
},
109111
},
110112
{
111-
name: "provider response with nested files",
113+
name: "provider response with nested files (linux)",
112114
permission: "777",
113115
files: []*v1alpha1.File{
114116
{
@@ -133,11 +135,46 @@ func TestMountContent(t *testing.T) {
133135
"baz/bar": 0777,
134136
"baz/qux": 0777,
135137
},
138+
skipon: "windows",
139+
},
140+
{
141+
// note: this is a bit weird because the path `baz\bar` on windows
142+
// should be a file `bar` nested in a folder `baz`. it _actually_
143+
// works on linux though because the `\` character is just treated
144+
// as part of the filename.
145+
name: "provider response with nested files (windows)",
146+
permission: "777",
147+
files: []*v1alpha1.File{
148+
{
149+
Path: "foo",
150+
Mode: 0444,
151+
Contents: []byte("foo"),
152+
},
153+
{
154+
Path: "baz\\bar",
155+
Mode: 0444,
156+
Contents: []byte("bar"),
157+
},
158+
{
159+
Path: "baz\\qux",
160+
Mode: 0666,
161+
Contents: []byte("qux"),
162+
},
163+
},
164+
objectVersions: map[string]string{"foo": "v1"},
165+
expectedFiles: map[string]os.FileMode{
166+
"foo": 0444,
167+
"baz\\bar": 0444,
168+
"baz\\qux": 0666,
169+
},
136170
},
137171
}
138172

139173
for _, test := range cases {
140174
t.Run(test.name, func(t *testing.T) {
175+
if test.skipon == runtime.GOOS {
176+
t.SkipNow()
177+
}
141178
socketPath := tmpdir.New(t, "", "ut")
142179
targetPath := tmpdir.New(t, "", "ut")
143180

pkg/util/fileutil/filesystem.go

Lines changed: 38 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,40 @@ var (
3636
func GetMountedFiles(targetPath string) (map[string]string, error) {
3737
paths := make(map[string]string)
3838

39+
// visitor is called for each file walked.
40+
// root is the root that will be walked, and base is the starting path
41+
// relative to targetPath when walking began
42+
visitor := func(root, base string) filepath.WalkFunc {
43+
return func(path string, info os.FileInfo, err error) error {
44+
// if there was an error walking path immediately propagate it
45+
if err != nil {
46+
return err
47+
}
48+
49+
// do not include directories in result
50+
if info.IsDir() {
51+
return nil
52+
}
53+
54+
// find the relative path of the root that was walked
55+
rel, err := filepath.Rel(root, path)
56+
if err != nil {
57+
return err
58+
}
59+
60+
paths[filepath.Join(base, rel)] = path
61+
return nil
62+
}
63+
}
64+
3965
// atomic writer will write data to, but filepath.Walk does not follow
40-
// symlinks
66+
// symlinks. follow any symlinks in the targetPath and then walk every item.
4167
d, err := os.ReadDir(targetPath)
4268
if err != nil {
43-
return paths, err
69+
return nil, err
4470
}
4571

46-
// for each item in the targetPath, walk that item
72+
// for each file/directory in the targetPath, walk that entry
4773
for _, entry := range d {
4874
// skip the reserved paths of targetPath/..*
4975
if strings.HasPrefix(entry.Name(), "..") {
@@ -52,7 +78,7 @@ func GetMountedFiles(targetPath string) (map[string]string, error) {
5278

5379
info, err := entry.Info()
5480
if err != nil {
55-
continue
81+
return nil, err
5682
}
5783

5884
// the path to the file relative to targetPath
@@ -61,67 +87,24 @@ func GetMountedFiles(targetPath string) (map[string]string, error) {
6187

6288
// the path before following the symlink
6389
// i.e. targetPath/foo
64-
p := filepath.Join(targetPath, info.Name())
90+
root := filepath.Join(targetPath, base)
6591

6692
// for symlinks in the targetPath...
6793
if info.Mode()&os.ModeSymlink != 0 {
6894
// the resolved relative path
6995
// i.e. ..data/foo
70-
actual, err := os.Readlink(p)
96+
actual, err := os.Readlink(root)
7197
if err != nil {
72-
continue
98+
return nil, err
7399
}
74100

75-
// the root path to walk
101+
// update the root path to walk to be after following the symlink
76102
// i.e. targetPath/..data/foo
77-
root := filepath.Join(targetPath, actual)
78-
79-
if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
80-
// if there was an error walking path immediately propagate it
81-
if err != nil {
82-
return err
83-
}
84-
85-
// do not include directories in result
86-
if info.IsDir() {
87-
return nil
88-
}
89-
90-
// We want the relative path before following the symbolic link.
91-
// Compute the relative path within the symlink'd directory.
92-
rel, err := filepath.Rel(root, path)
93-
if err != nil {
94-
return err
95-
}
96-
paths[filepath.Join(base, rel)] = path
97-
98-
return nil
99-
}); err != nil {
100-
return paths, err
101-
}
102-
} else {
103-
if err := filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
104-
// if there was an error walking path immediately propagate it
105-
if err != nil {
106-
return err
107-
}
108-
109-
// do not include directories in result
110-
if info.IsDir() {
111-
return nil
112-
}
113-
114-
// determine relative path
115-
rel, err := filepath.Rel(targetPath, path)
116-
if err != nil {
117-
return err
118-
}
119-
paths[rel] = path
103+
root = filepath.Join(targetPath, actual)
104+
}
120105

121-
return nil
122-
}); err != nil {
123-
return paths, err
124-
}
106+
if err := filepath.Walk(root, visitor(root, base)); err != nil {
107+
return paths, err
125108
}
126109
}
127110
return paths, nil

pkg/util/fileutil/filesystem_test.go

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package fileutil
1919
import (
2020
"os"
2121
"path/filepath"
22+
"sort"
2223
"testing"
2324

2425
"github.com/google/go-cmp/cmp"
@@ -49,7 +50,13 @@ func TestGetMountedFiles(t *testing.T) {
4950
name: "target path dir/file found",
5051
targetPath: func(t *testing.T) string {
5152
dir := tmpdir.New(t, "", "ut")
52-
os.Create(filepath.Join(dir, "secret.txt"))
53+
f, err := os.Create(filepath.Join(dir, "secret.txt"))
54+
if err != nil {
55+
t.Fatalf("error writing file: %s", err)
56+
}
57+
if err := f.Close(); err != nil {
58+
t.Fatalf("error writing file: %s", err)
59+
}
5360
return dir
5461
},
5562
expectedErr: false,
@@ -59,12 +66,20 @@ func TestGetMountedFiles(t *testing.T) {
5966
name: "target path dir/dir/file found",
6067
targetPath: func(t *testing.T) string {
6168
dir := tmpdir.New(t, "", "ut")
62-
os.MkdirAll(filepath.Join(dir, "subdir"), 0700)
63-
os.Create(filepath.Join(dir, "subdir", "secret.txt"))
69+
if err := os.MkdirAll(filepath.Join(dir, "subdir"), 0700); err != nil {
70+
t.Fatalf("could not make subdir: %s", err)
71+
}
72+
f, err := os.Create(filepath.Join(dir, "subdir", "secret.txt"))
73+
if err != nil {
74+
t.Fatalf("could not write file: %s", err)
75+
}
76+
if err := f.Close(); err != nil {
77+
t.Fatalf("error writing file: %s", err)
78+
}
6479
return dir
6580
},
6681
expectedErr: false,
67-
want: []string{"subdir/secret.txt"},
82+
want: []string{filepath.Join("subdir", "secret.txt")},
6883
},
6984
{
7085
name: "target path with atomic_writer symlinks",
@@ -79,14 +94,26 @@ func TestGetMountedFiles(t *testing.T) {
7994
Data: []byte("foo"),
8095
Mode: 0700,
8196
},
97+
"foo/baz.txt": {
98+
Data: []byte("baz"),
99+
Mode: 0700,
100+
},
101+
"foo.txt": {
102+
Data: []byte("foo.txt"),
103+
Mode: 0700,
104+
},
82105
})
83106
if err != nil {
84107
t.Fatalf("unable to write FileProjection: %s", err)
85108
}
86109
return dir
87110
},
88111
expectedErr: false,
89-
want: []string{"foo/bar.txt"},
112+
want: []string{
113+
"foo.txt",
114+
filepath.Join("foo", "bar.txt"),
115+
filepath.Join("foo", "baz.txt"),
116+
},
90117
},
91118
}
92119

@@ -101,6 +128,7 @@ func TestGetMountedFiles(t *testing.T) {
101128
for k := range got {
102129
gotKeys = append(gotKeys, k)
103130
}
131+
sort.Strings(gotKeys)
104132

105133
if diff := cmp.Diff(test.want, gotKeys, cmpopts.EquateEmpty()); diff != "" {
106134
t.Errorf("GetMountedFiles() keys mismatch (-want +got):\n%s", diff)

pkg/util/fileutil/writer_test.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"io/fs"
2424
"os"
2525
"path/filepath"
26+
"runtime"
2627
"strings"
2728
"testing"
2829

@@ -34,6 +35,7 @@ func TestValidate_Success(t *testing.T) {
3435
cases := []struct {
3536
name string
3637
payload []*v1alpha1.File
38+
skipon string
3739
}{
3840
{
3941
name: "valid double payload",
@@ -55,17 +57,31 @@ func TestValidate_Success(t *testing.T) {
5557
},
5658
},
5759
{
58-
name: "valid nested path",
60+
name: "valid nested path (linux)",
5961
payload: []*v1alpha1.File{
6062
{
6163
Path: "foo/bar",
6264
},
6365
},
66+
skipon: "windows",
67+
},
68+
{
69+
name: "valid nested path (windows)",
70+
// note: on linux this will be treated as a file with name `foo\bar`
71+
// not a file `bar` nested in the directory `foo`.
72+
payload: []*v1alpha1.File{
73+
{
74+
Path: "foo\\bar",
75+
},
76+
},
6477
},
6578
}
6679

6780
for _, tc := range cases {
6881
t.Run(tc.name, func(t *testing.T) {
82+
if tc.skipon == runtime.GOOS {
83+
t.SkipNow()
84+
}
6985
if err := Validate(tc.payload); err != nil {
7086
t.Errorf("%v: unexpected error: %v", tc.name, err)
7187
}
@@ -426,9 +442,18 @@ func readPayloads(path string, payloads []*v1alpha1.File) error {
426442
if err != nil {
427443
return err
428444
}
429-
if info.Mode() != fs.FileMode(p.Mode) {
430-
return fmt.Errorf("unexpected file mode. got: %v, want: %v", info.Mode(), fs.FileMode(p.Mode))
445+
if runtime.GOOS == "windows" {
446+
// on windows only the 0200 bitmask is used by chmod
447+
// https://golang.org/src/os/file.go?s=15847:15891#L522
448+
if (info.Mode() & 0200) != (fs.FileMode(p.Mode) & 0200) {
449+
return fmt.Errorf("unexpected file mode. got: %v, want: %v", info.Mode(), fs.FileMode(p.Mode))
450+
}
451+
} else {
452+
if info.Mode() != fs.FileMode(p.Mode) {
453+
return fmt.Errorf("unexpected file mode. got: %v, want: %v", info.Mode(), fs.FileMode(p.Mode))
454+
}
431455
}
456+
432457
contents, err := os.ReadFile(fp)
433458
if err != nil {
434459
return err

0 commit comments

Comments
 (0)