Skip to content

Commit e2ace04

Browse files
authored
Merge pull request #187 from mauriciopoppe/fileystem-v2alpha1
Bump Filesystem API from v1 to v2alpha1
2 parents 7ed8d11 + 88cadeb commit e2ace04

File tree

13 files changed

+3030
-0
lines changed

13 files changed

+3030
-0
lines changed

client/api/filesystem/v2alpha1/api.pb.go

Lines changed: 1046 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
syntax = "proto3";
2+
3+
package v2alpha1;
4+
5+
option go_package = "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v2alpha1";
6+
7+
service Filesystem {
8+
// PathExists checks if the requested path exists in the host filesystem.
9+
rpc PathExists(PathExistsRequest) returns (PathExistsResponse) {}
10+
11+
// Mkdir creates a directory at the requested path in the host filesystem.
12+
rpc Mkdir(MkdirRequest) returns (MkdirResponse) {}
13+
14+
// Rmdir removes the directory at the requested path in the host filesystem.
15+
// This may be used for unlinking a symlink created through CreateSymlink.
16+
rpc Rmdir(RmdirRequest) returns (RmdirResponse) {}
17+
18+
// CreateSymlink creates a symbolic link called target_path that points to source_path
19+
// in the host filesystem (target_path is the name of the symbolic link created,
20+
// source_path is the existing path).
21+
rpc CreateSymlink(CreateSymlinkRequest) returns (CreateSymlinkResponse) {}
22+
23+
// IsSymlink checks if a given path is a symlink.
24+
rpc IsSymlink(IsSymlinkRequest) returns (IsSymlinkResponse) {}
25+
}
26+
27+
message PathExistsRequest {
28+
// The path whose existence we want to check in the host's filesystem
29+
string path = 1;
30+
}
31+
32+
message PathExistsResponse {
33+
// Indicates whether the path in PathExistsRequest exists in the host's filesystem
34+
bool exists = 1;
35+
}
36+
37+
message MkdirRequest {
38+
// The path to create in the host's filesystem.
39+
// All special characters allowed by Windows in path names will be allowed
40+
// except for restrictions noted below. For details, please check:
41+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
42+
// Non-existent parent directories in the path will be automatically created.
43+
// Directories will be created with Read and Write privileges of the Windows
44+
// User account under which csi-proxy is started (typically LocalSystem).
45+
//
46+
// Restrictions:
47+
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
48+
// Depending on the context parameter of this function, the path prefix needs
49+
// to match the paths specified either as kubelet-csi-plugins-path
50+
// or as kubelet-pod-path parameters of csi-proxy.
51+
// The path parameter cannot already exist in the host's filesystem.
52+
// UNC paths of the form "\\server\share\path\file" are not allowed.
53+
// All directory separators need to be backslash character: "\".
54+
// Characters: .. / : | ? * in the path are not allowed.
55+
// Maximum path length will be capped to 260 characters.
56+
string path = 1;
57+
}
58+
59+
message MkdirResponse {
60+
// Intentionally empty.
61+
}
62+
63+
message RmdirRequest {
64+
// The path to remove in the host's filesystem.
65+
// All special characters allowed by Windows in path names will be allowed
66+
// except for restrictions noted below. For details, please check:
67+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
68+
//
69+
// Restrictions:
70+
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
71+
// Depending on the context parameter of this function, the path prefix needs
72+
// to match the paths specified either as kubelet-csi-plugins-path
73+
// or as kubelet-pod-path parameters of csi-proxy.
74+
// UNC paths of the form "\\server\share\path\file" are not allowed.
75+
// All directory separators need to be backslash character: "\".
76+
// Characters: .. / : | ? * in the path are not allowed.
77+
// Path cannot be a file of type symlink.
78+
// Maximum path length will be capped to 260 characters.
79+
string path = 1;
80+
81+
// Force remove all contents under path (if any).
82+
bool force = 2;
83+
}
84+
85+
message RmdirResponse {
86+
// Intentionally empty.
87+
}
88+
89+
message CreateSymlinkRequest {
90+
// The path of the existing directory to be linked.
91+
// All special characters allowed by Windows in path names will be allowed
92+
// except for restrictions noted below. For details, please check:
93+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
94+
//
95+
// Restrictions:
96+
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
97+
// The path prefix needs needs to match the paths specified as
98+
// kubelet-csi-plugins-path parameter of csi-proxy.
99+
// UNC paths of the form "\\server\share\path\file" are not allowed.
100+
// All directory separators need to be backslash character: "\".
101+
// Characters: .. / : | ? * in the path are not allowed.
102+
// source_path cannot already exist in the host filesystem.
103+
// Maximum path length will be capped to 260 characters.
104+
string source_path = 1;
105+
106+
// Target path is the location of the new directory entry to be created in the host's filesystem.
107+
// All special characters allowed by Windows in path names will be allowed
108+
// except for restrictions noted below. For details, please check:
109+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
110+
//
111+
// Restrictions:
112+
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
113+
// The path prefix needs to match the paths specified as
114+
// kubelet-pod-path parameter of csi-proxy.
115+
// UNC paths of the form "\\server\share\path\file" are not allowed.
116+
// All directory separators need to be backslash character: "\".
117+
// Characters: .. / : | ? * in the path are not allowed.
118+
// target_path needs to exist as a directory in the host that is empty.
119+
// target_path cannot be a symbolic link.
120+
// Maximum path length will be capped to 260 characters.
121+
string target_path = 2;
122+
}
123+
124+
message CreateSymlinkResponse {
125+
// Intentionally empty.
126+
}
127+
128+
message IsSymlinkRequest {
129+
// The path whose existence as a symlink we want to check in the host's filesystem.
130+
string path = 1;
131+
}
132+
133+
message IsSymlinkResponse {
134+
// Indicates whether the path in IsSymlinkRequest is a symlink.
135+
bool is_symlink = 1;
136+
}

client/groups/filesystem/v2alpha1/client_generated.go

Lines changed: 86 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

integrationtests/filesystem_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ func pathExists(path string) (bool, error) {
1717
}
1818

1919
func TestFilesystemAPIGroup(t *testing.T) {
20+
t.Run("v2alpha1FilesystemTests", func(t *testing.T) {
21+
v2alpha1FilesystemTests(t)
22+
})
2023
t.Run("v1FilesystemTests", func(t *testing.T) {
2124
v1FilesystemTests(t)
2225
})
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package integrationtests
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"math/rand"
7+
"os"
8+
"path/filepath"
9+
"testing"
10+
"time"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
15+
"github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v2alpha1"
16+
v2alpha1client "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v2alpha1"
17+
)
18+
19+
func v2alpha1FilesystemTests(t *testing.T) {
20+
t.Run("PathExists positive", func(t *testing.T) {
21+
client, err := v2alpha1client.NewClient()
22+
require.Nil(t, err)
23+
defer client.Close()
24+
25+
s1 := rand.NewSource(time.Now().UnixNano())
26+
r1 := rand.New(s1)
27+
28+
// simulate FS operations around staging a volume on a node
29+
stagepath := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io\\volume%d", r1.Intn(100), r1.Intn(100)), t)
30+
mkdirReq := &v2alpha1.MkdirRequest{
31+
Path: stagepath,
32+
}
33+
_, err = client.Mkdir(context.Background(), mkdirReq)
34+
require.NoError(t, err)
35+
36+
exists, err := pathExists(stagepath)
37+
assert.True(t, exists, err)
38+
39+
// simulate operations around publishing a volume to a pod
40+
podpath := getKubeletPathForTest(fmt.Sprintf("test-pod-id\\volumes\\kubernetes.io~csi\\pvc-test%d", r1.Intn(100)), t)
41+
mkdirReq = &v2alpha1.MkdirRequest{
42+
Path: podpath,
43+
}
44+
_, err = client.Mkdir(context.Background(), mkdirReq)
45+
require.NoError(t, err)
46+
47+
exists, err = pathExists(podpath)
48+
assert.True(t, exists, err)
49+
50+
sourcePath := stagepath
51+
targetPath := filepath.Join(podpath, "rootvol")
52+
// source <- target
53+
linkReq := &v2alpha1.CreateSymlinkRequest{
54+
SourcePath: sourcePath,
55+
TargetPath: targetPath,
56+
}
57+
_, err = client.CreateSymlink(context.Background(), linkReq)
58+
require.NoError(t, err)
59+
60+
exists, err = pathExists(podpath + "\\rootvol")
61+
assert.True(t, exists, err)
62+
63+
// cleanup pvpath
64+
rmdirReq := &v2alpha1.RmdirRequest{
65+
Path: podpath,
66+
Force: true,
67+
}
68+
_, err = client.Rmdir(context.Background(), rmdirReq)
69+
require.NoError(t, err)
70+
71+
exists, err = pathExists(podpath)
72+
assert.False(t, exists, err)
73+
74+
// cleanup plugin path
75+
rmdirReq = &v2alpha1.RmdirRequest{
76+
Path: stagepath,
77+
Force: true,
78+
}
79+
_, err = client.Rmdir(context.Background(), rmdirReq)
80+
require.NoError(t, err)
81+
82+
exists, err = pathExists(stagepath)
83+
assert.False(t, exists, err)
84+
})
85+
t.Run("IsMount", func(t *testing.T) {
86+
client, err := v2alpha1client.NewClient()
87+
require.Nil(t, err)
88+
defer client.Close()
89+
90+
s1 := rand.NewSource(time.Now().UnixNano())
91+
r1 := rand.New(s1)
92+
rand1 := r1.Intn(100)
93+
rand2 := r1.Intn(100)
94+
95+
testDir := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io", rand1), t)
96+
err = os.MkdirAll(testDir, os.ModeDir)
97+
require.Nil(t, err)
98+
defer os.RemoveAll(testDir)
99+
100+
// 1. Check the isMount on a path which does not exist. Failure scenario.
101+
stagepath := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io\\volume%d", rand1, rand2), t)
102+
IsSymlinkRequest := &v2alpha1.IsSymlinkRequest{
103+
Path: stagepath,
104+
}
105+
isSymlink, err := client.IsSymlink(context.Background(), IsSymlinkRequest)
106+
require.NotNil(t, err)
107+
108+
// 2. Create the directory. This time its not a mount point. Failure scenario.
109+
err = os.Mkdir(stagepath, os.ModeDir)
110+
require.Nil(t, err)
111+
defer os.Remove(stagepath)
112+
IsSymlinkRequest = &v2alpha1.IsSymlinkRequest{
113+
Path: stagepath,
114+
}
115+
isSymlink, err = client.IsSymlink(context.Background(), IsSymlinkRequest)
116+
require.Nil(t, err)
117+
require.Equal(t, isSymlink.IsSymlink, false)
118+
119+
err = os.Remove(stagepath)
120+
require.Nil(t, err)
121+
targetStagePath := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io\\volume%d-tgt", rand1, rand2), t)
122+
lnTargetStagePath := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io\\volume%d-tgt-ln", rand1, rand2), t)
123+
124+
// 3. Create soft link to the directory and make sure target exists. Success scenario.
125+
err = os.Mkdir(targetStagePath, os.ModeDir)
126+
require.Nil(t, err)
127+
defer os.Remove(targetStagePath)
128+
// Create a sym link
129+
err = os.Symlink(targetStagePath, lnTargetStagePath)
130+
require.Nil(t, err)
131+
defer os.Remove(lnTargetStagePath)
132+
133+
IsSymlinkRequest = &v2alpha1.IsSymlinkRequest{
134+
Path: lnTargetStagePath,
135+
}
136+
isSymlink, err = client.IsSymlink(context.Background(), IsSymlinkRequest)
137+
require.Nil(t, err)
138+
require.Equal(t, isSymlink.IsSymlink, true)
139+
140+
// 4. Remove the path. Failure scenario.
141+
err = os.Remove(targetStagePath)
142+
require.Nil(t, err)
143+
IsSymlinkRequest = &v2alpha1.IsSymlinkRequest{
144+
Path: lnTargetStagePath,
145+
}
146+
isSymlink, err = client.IsSymlink(context.Background(), IsSymlinkRequest)
147+
require.Nil(t, err)
148+
require.Equal(t, isSymlink.IsSymlink, false)
149+
})
150+
}

0 commit comments

Comments
 (0)