Skip to content

Commit 45d3a58

Browse files
committed
Filesystem API and unit tests
Signed-off-by: Deep Debroy <[email protected]>
1 parent 5ff39c7 commit 45d3a58

File tree

14 files changed

+1555
-94
lines changed

14 files changed

+1555
-94
lines changed

client/api/filesystem/v1alpha1/api.pb.go

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

client/api/filesystem/v1alpha1/api.proto

Lines changed: 141 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,156 @@ syntax = "proto3";
22

33
package v1alpha1;
44

5-
import "github.com/kubernetes-csi/csi-proxy/client/api/errors.proto";
6-
7-
// FIXME: this is just an almost empty service, not actually implemented; it's just
8-
// here as an example of what API group and versions will look like. It will actually
9-
// be implemented in a later patch.
10-
115
service Filesystem {
12-
// PathExists checks if the given path exists on the host.
6+
// PathExists checks if the requested path exists in the host's filesystem
137
rpc PathExists(PathExistsRequest) returns (PathExistsResponse) {}
8+
9+
// Mkdir creates a directory at the requested path in the host's filesystem
10+
rpc Mkdir(MkdirRequest) returns (MkdirResponse) {}
11+
12+
// Rmdir removes the directory at the requested path in the host's filesystem.
13+
// This may be used for unlinking a symlink created through LinkPath
14+
rpc Rmdir(RmdirRequest) returns (RmdirResponse) {}
15+
16+
// LinkPath creates a local directory symbolic link between a source path
17+
// and target path in the host's filesystem
18+
rpc LinkPath(LinkPathRequest) returns (LinkPathResponse) {}
19+
}
20+
21+
// Context of the paths used for path prefix validation
22+
enum PathContext {
23+
// Indicates the kubelet-csi-plugins-path parameter of csi-proxy be used as the path context
24+
PLUGIN = 0;
25+
// Indicates the kubelet-pod-path parameter of csi-proxy be used as the path context
26+
CONTAINER = 1;
1427
}
1528

1629
message PathExistsRequest {
17-
// The path to check in the host file system.
30+
// The path whose existence we want to check in the host's filesystem
1831
string path = 1;
32+
33+
// Context of the path parameter.
34+
// This is used to determine the root for relative path parameters
35+
PathContext context = 2;
1936
}
2037

2138
message PathExistsResponse {
22-
bool success = 1;
39+
// Error message if any. Empty string indicates success
40+
string error = 1;
41+
42+
// Indicates whether the path in PathExistsRequest exists in the host's filesystem
43+
bool exists = 2;
44+
}
45+
46+
message MkdirRequest {
47+
// The path to create in the host's filesystem.
48+
// All special characters allowed by Windows in path names will be allowed
49+
// except for restrictions noted below. For details, please check:
50+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
51+
// Non-existent parent directories in the path will be automatically created.
52+
// Directories will be created with Read and Write privileges of the Windows
53+
// User account under which csi-proxy is started (typically LocalSystem).
54+
//
55+
// Restrictions:
56+
// If an absolute path (indicated by a drive letter prefix: e.g. "C:\") is passed,
57+
// depending on the context parameter of this function, the path prefix needs
58+
// to match the paths specified either as kubelet-csi-plugins-path
59+
// or as kubelet-pod-path parameters of csi-proxy.
60+
// If a relative path is passed, depending on the context parameter of this
61+
// function, the path will be considered relative to the path specified either as
62+
// kubelet-csi-plugins-path or as kubelet-pod-path parameters of csi-proxy.
63+
// The path parameter cannot already exist on host filesystem.
64+
// UNC paths of the form "\\server\share\path\file" are not allowed.
65+
// All directory separators need to be backslash character: "\".
66+
// Characters: .. / : | ? * in the path are not allowed.
67+
// Maximum path length will be capped to 260 characters.
68+
string path = 1;
2369

24-
// present iff success is false
25-
api.CmdletError cmdlet_error = 2;
70+
// Context of the path parameter.
71+
// This is used to [1] determine the root for relative path parameters
72+
// or [2] validate prefix for absolute paths (indicated by a drive letter
73+
// prefix: e.g. "C:\")
74+
PathContext context = 2;
75+
}
76+
77+
message MkdirResponse {
78+
// Error message if any. Empty string indicates success
79+
string error = 1;
80+
}
81+
82+
message RmdirRequest {
83+
// The path to remove in the host's filesystem.
84+
// All special characters allowed by Windows in path names will be allowed
85+
// except for restrictions noted below. For details, please check:
86+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
87+
//
88+
// Restrictions:
89+
// If an absolute path (indicated by a drive letter prefix: e.g. "C:\") is passed,
90+
// depending on the context parameter of this function, the path prefix needs
91+
// to match the paths specified either as kubelet-csi-plugins-path
92+
// or as kubelet-pod-path parameters of csi-proxy.
93+
// If a relative path is passed, depending on the context parameter of this
94+
// function, the path will be considered relative to the path specified either as
95+
// kubelet-csi-plugins-path or as kubelet-pod-path parameters of csi-proxy.
96+
// UNC paths of the form "\\server\share\path\file" are not allowed.
97+
// All directory separators need to be backslash character: "\".
98+
// Characters: .. / : | ? * in the path are not allowed.
99+
// Path cannot be a file of type symlink.
100+
// Maximum path length will be capped to 260 characters.
101+
string path = 1;
102+
103+
// Context of the path creation used for path prefix validation
104+
// This is used to [1] determine the root for relative path parameters
105+
// or [2] validate prefix for absolute paths (indicated by a drive letter
106+
// prefix: e.g. "C:\")
107+
PathContext context = 2;
108+
}
109+
110+
message RmdirResponse {
111+
// Error message if any. Empty string indicates success
112+
string error = 1;
113+
}
114+
115+
message LinkPathRequest {
116+
// The path where the symlink is created in the host's filesystem.
117+
// All special characters allowed by Windows in path names will be allowed
118+
// except for restrictions noted below. For details, please check:
119+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
120+
//
121+
// Restrictions:
122+
// If an absolute path (indicated by a drive letter prefix: e.g. "C:\") is passed,
123+
// the path prefix needs to match the path specified as kubelet-csi-plugins-path
124+
// parameter of csi-proxy.
125+
// If a relative path is passed, the path will be considered relative to the
126+
// path specified as kubelet-csi-plugins-path parameter of csi-proxy.
127+
// UNC paths of the form "\\server\share\path\file" are not allowed.
128+
// All directory separators need to be backslash character: "\".
129+
// Characters: .. / : | ? * in the path are not allowed.
130+
// source_path cannot already exist in the host filesystem.
131+
// Maximum path length will be capped to 260 characters.
132+
string source_path = 1;
133+
134+
// Target path in the host's filesystem used for the symlink creation.
135+
// All special characters allowed by Windows in path names will be allowed
136+
// except for restrictions noted below. For details, please check:
137+
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
138+
//
139+
// Restrictions:
140+
// If an absolute path (indicated by a drive letter prefix: e.g. "C:\") is passed,
141+
// the path prefix needs to match the path specified as kubelet-pod-path
142+
// parameter of csi-proxy.
143+
// If a relative path is passed, the path will be considered relative to the
144+
// path specified as kubelet-pod-path parameter of csi-proxy.
145+
// UNC paths of the form "\\server\share\path\file" are not allowed.
146+
// All directory separators need to be backslash character: "\".
147+
// Characters: .. / : | ? * in the path are not allowed.
148+
// target_path needs to exist as a directory in the host that is empty.
149+
// target_path cannot be a symbolic link.
150+
// Maximum path length will be capped to 260 characters.
151+
string target_path = 2;
152+
}
26153

27-
bool exists = 4;
154+
message LinkPathResponse {
155+
// Error message if any. Empty string indicates success
156+
string error = 1;
28157
}

client/groups/filesystem/v1alpha1/client_generated.go

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

cmd/server/main.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,39 @@
11
package main
22

33
import (
4+
"runtime"
5+
6+
filesystemapi "github.com/kubernetes-csi/csi-proxy/internal/os/filesystem"
47
"github.com/kubernetes-csi/csi-proxy/internal/server"
5-
filesystem "github.com/kubernetes-csi/csi-proxy/internal/server/filesystem"
8+
srvtypes "github.com/kubernetes-csi/csi-proxy/internal/server/types"
9+
filesystemsrv "github.com/kubernetes-csi/csi-proxy/internal/server/filesystem"
10+
flag "github.com/spf13/pflag"
11+
)
12+
13+
var (
14+
kubeletCSIPluginsPath = flag.String("kubelet-csi-plugins-path", `C:\var\lib\kubelet\plugins`, "Absolute path of the Kubelet plugin directory in the host file system")
15+
kubeletPodPath = flag.String("kubelet-pod-path", `C:\var\lib\kubelet\pods`, "Absolute path of the kubelet pod directory in the host file system")
616
)
717

818
func main() {
9-
s := server.NewServer(apiGroups()...)
19+
flag.Parse()
20+
apiGroups, err := apiGroups()
21+
if err != nil {
22+
panic(err)
23+
}
24+
s := server.NewServer(apiGroups...)
1025
if err := s.Start(nil); err != nil {
1126
panic(err)
1227
}
1328
}
1429

1530
// apiGroups returns the list of enabled API groups.
16-
func apiGroups() []server.APIGroup {
17-
return []server.APIGroup{
18-
&filesystem.Server{},
31+
func apiGroups() ([]srvtypes.APIGroup, error) {
32+
fssrv, err := filesystemsrv.NewServer(runtime.GOOS, *kubeletCSIPluginsPath, *kubeletPodPath, filesystemapi.New())
33+
if err != nil {
34+
return []srvtypes.APIGroup{}, err
1935
}
36+
return []srvtypes.APIGroup{
37+
fssrv,
38+
}, nil
2039
}

internal/os/filesystem/api.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package filesystem
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
"runtime"
8+
)
9+
10+
// Implements the Filesystem OS API calls. All code here should be very simple
11+
// pass-through to the OS APIs. Any logic around the APIs should go in
12+
// internal/server/filesystem/server.go so that logic can be easily unit-tested
13+
// without requiring specific OS environments.
14+
15+
type APIImplementor struct{}
16+
17+
func New() APIImplementor {
18+
return APIImplementor{}
19+
}
20+
21+
func (APIImplementor) PathExists(path string) (bool, error) {
22+
_, err := os.Stat(path)
23+
if err == nil {
24+
return true, nil
25+
}
26+
if os.IsNotExist(err) {
27+
return false, nil
28+
}
29+
return true, err
30+
}
31+
32+
func (APIImplementor) Mkdir(path string) error {
33+
err := os.MkdirAll(path, 0755)
34+
return err
35+
}
36+
37+
func (APIImplementor) Rmdir(path string) error {
38+
err := os.RemoveAll(path)
39+
return err
40+
}
41+
42+
func (APIImplementor) LinkPath(tgt string, src string) error {
43+
var err error
44+
if runtime.GOOS == "windows" {
45+
_, err = exec.Command("cmd", "/c", "mklink", "/D", tgt, src).CombinedOutput()
46+
} else {
47+
err = fmt.Errorf("LinkPath not implemented for %s", runtime.GOOS)
48+
}
49+
return err
50+
}

internal/server/filesystem/api_group_generated.go

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

0 commit comments

Comments
 (0)