Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
384 changes: 166 additions & 218 deletions client/api/filesystem/v1beta2/api.pb.go

Large diffs are not rendered by default.

54 changes: 23 additions & 31 deletions client/api/filesystem/v1beta2/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@ package v1beta2;
option go_package = "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1beta2";

service Filesystem {
// PathExists checks if the requested path exists in the host's filesystem
// PathExists checks if the requested path exists in the host filesystem.
rpc PathExists(PathExistsRequest) returns (PathExistsResponse) {}

// Mkdir creates a directory at the requested path in the host's filesystem
// Mkdir creates a directory at the requested path in the host filesystem.
rpc Mkdir(MkdirRequest) returns (MkdirResponse) {}

// Rmdir removes the directory at the requested path in the host's filesystem.
// This may be used for unlinking a symlink created through LinkPath
// Rmdir removes the directory at the requested path in the host filesystem.
// This may be used for unlinking a symlink created through CreateSymlink.
rpc Rmdir(RmdirRequest) returns (RmdirResponse) {}

// LinkPath creates a local directory symbolic link between a source path
// and target path in the host's filesystem
rpc LinkPath(LinkPathRequest) returns (LinkPathResponse) {}
// CreateSymlink creates a symbolic link called target_path that points to source_path
// in the host filesystem (target_path is the name of the symbolic link created,
// source_path is the existing path).
rpc CreateSymlink(CreateSymlinkRequest) returns (CreateSymlinkResponse) {}

//IsMountPoint checks if a given path is mount or not
rpc IsMountPoint(IsMountPointRequest) returns (IsMountPointResponse) {}
// IsSymlink checks if a given path is a symlink.
rpc IsSymlink(IsSymlinkRequest) returns (IsSymlinkResponse) {}
}

// Context of the paths used for path prefix validation
Expand All @@ -47,11 +48,8 @@ message PathExistsRequest {
}

message PathExistsResponse {
// Error message if any. Empty string indicates success
string error = 1;

// Indicates whether the path in PathExistsRequest exists in the host's filesystem
bool exists = 2;
bool exists = 1;
}

message MkdirRequest {
Expand Down Expand Up @@ -81,8 +79,7 @@ message MkdirRequest {
}

message MkdirResponse {
// Error message if any. Empty string indicates success
string error = 1;
// Intentionally empty.
}

message RmdirRequest {
Expand Down Expand Up @@ -112,12 +109,11 @@ message RmdirRequest {
}

message RmdirResponse {
// Error message if any. Empty string indicates success
string error = 1;
// Intentionally empty.
}

message LinkPathRequest {
// The path where the symlink is created in the host's filesystem.
message CreateSymlinkRequest {
// The path of the existing directory to be linked.
// All special characters allowed by Windows in path names will be allowed
// except for restrictions noted below. For details, please check:
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
Expand All @@ -133,7 +129,7 @@ message LinkPathRequest {
// Maximum path length will be capped to 260 characters.
string source_path = 1;

// Target path in the host's filesystem used for the symlink creation.
// Target path is the location of the new directory entry to be created in the host's filesystem.
// All special characters allowed by Windows in path names will be allowed
// except for restrictions noted below. For details, please check:
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
Expand All @@ -151,20 +147,16 @@ message LinkPathRequest {
string target_path = 2;
}

message LinkPathResponse {
// Error message if any. Empty string indicates success
string error = 1;
message CreateSymlinkResponse {
// Intentionally empty.
}

message IsMountPointRequest {
// The path whose existence we want to check in the host's filesystem
message IsSymlinkRequest {
// The path whose existence as a symlink we want to check in the host's filesystem.
string path = 1;
}

message IsMountPointResponse {
// Error message if any. Empty string indicates success
string error = 1;

// Indicates whether the path in PathExistsRequest exists in the host's filesystem
bool is_mount_point = 2;
message IsSymlinkResponse {
// Indicates whether the path in IsSymlinkRequest is a symlink.
bool is_symlink = 1;
}
8 changes: 4 additions & 4 deletions client/groups/filesystem/v1beta2/client_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

154 changes: 7 additions & 147 deletions integrationtests/filesystem_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
package integrationtests

import (
"context"
"fmt"
"math/rand"
"os"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1beta2"
v1beta2client "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v1beta2"
)

func pathExists(path string) (bool, error) {
Expand All @@ -27,143 +17,13 @@ func pathExists(path string) (bool, error) {
}

func TestFilesystemAPIGroup(t *testing.T) {
t.Run("PathExists positive", func(t *testing.T) {
skipTestOnCondition(t, isRunningOnGhActions())

client, err := v1beta2client.NewClient()
require.Nil(t, err)
defer client.Close()

s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)

// simulate FS operations around staging a volume on a node
stagepath := getWorkDirPath(fmt.Sprintf("testplugin-%d.csi.io\\volume%d", r1.Intn(100), r1.Intn(100)), t)
mkdirReq := &v1beta2.MkdirRequest{
Path: stagepath,
Context: v1beta2.PathContext_PLUGIN,
}
mkdirRsp, err := client.Mkdir(context.Background(), mkdirReq)
if assert.Nil(t, err) {
assert.Equal(t, "", mkdirRsp.Error)
}

exists, err := pathExists(stagepath)
assert.True(t, exists, err)

// simulate operations around publishing a volume to a pod
podpath := getWorkDirPath(fmt.Sprintf("test-pod-id\\volumes\\kubernetes.io~csi\\pvc-test%d", r1.Intn(100)), t)
mkdirReq = &v1beta2.MkdirRequest{
Path: podpath,
Context: v1beta2.PathContext_POD,
}
mkdirRsp, err = client.Mkdir(context.Background(), mkdirReq)
if assert.Nil(t, err) {
assert.Equal(t, "", mkdirRsp.Error)
}
linkReq := &v1beta2.LinkPathRequest{
TargetPath: stagepath,
SourcePath: podpath + "\\rootvol",
}
linkRsp, err := client.LinkPath(context.Background(), linkReq)
if assert.Nil(t, err) {
assert.Equal(t, "", linkRsp.Error)
}

exists, err = pathExists(podpath + "\\rootvol")
assert.True(t, exists, err)

// cleanup pvpath
rmdirReq := &v1beta2.RmdirRequest{
Path: podpath,
Context: v1beta2.PathContext_POD,
Force: true,
}
rmdirRsp, err := client.Rmdir(context.Background(), rmdirReq)
if assert.Nil(t, err) {
assert.Equal(t, "", rmdirRsp.Error)
}

exists, err = pathExists(podpath)
assert.False(t, exists, err)

// cleanup plugin path
rmdirReq = &v1beta2.RmdirRequest{
Path: stagepath,
Context: v1beta2.PathContext_PLUGIN,
Force: true,
}
rmdirRsp, err = client.Rmdir(context.Background(), rmdirReq)
if assert.Nil(t, err) {
assert.Equal(t, "", rmdirRsp.Error)
}

exists, err = pathExists(stagepath)
assert.False(t, exists, err)
t.Run("v1beta2FilesystemTests", func(t *testing.T) {
v1beta2FilesystemTests(t)
})
t.Run("IsMount", func(t *testing.T) {
client, err := v1beta2client.NewClient()
require.Nil(t, err)
defer client.Close()

s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
rand1 := r1.Intn(100)
rand2 := r1.Intn(100)

testDir := getWorkDirPath(fmt.Sprintf("testplugin-%d.csi.io", rand1), t)
err = os.MkdirAll(testDir, os.ModeDir)
require.Nil(t, err)
defer os.RemoveAll(testDir)

// 1. Check the isMount on a path which does not exist. Failure scenario.
stagepath := getWorkDirPath(fmt.Sprintf("testplugin-%d.csi.io\\volume%d", rand1, rand2), t)
isMountRequest := &v1beta2.IsMountPointRequest{
Path: stagepath,
}
isMountResponse, err := client.IsMountPoint(context.Background(), isMountRequest)
require.NotNil(t, err)

// 2. Create the directory. This time its not a mount point. Failure scenario.
err = os.Mkdir(stagepath, os.ModeDir)
require.Nil(t, err)
defer os.Remove(stagepath)
isMountRequest = &v1beta2.IsMountPointRequest{
Path: stagepath,
}
isMountResponse, err = client.IsMountPoint(context.Background(), isMountRequest)
require.Nil(t, err)
require.Equal(t, isMountResponse.IsMountPoint, false)

err = os.Remove(stagepath)
require.Nil(t, err)
targetStagePath := getWorkDirPath(fmt.Sprintf("testplugin-%d.csi.io\\volume%d-tgt", rand1, rand2), t)
lnTargetStagePath := getWorkDirPath(fmt.Sprintf("testplugin-%d.csi.io\\volume%d-tgt-ln", rand1, rand2), t)

// 3. Create soft link to the directory and make sure target exists. Success scenario.
err = os.Mkdir(targetStagePath, os.ModeDir)
require.Nil(t, err)
defer os.Remove(targetStagePath)
// Create a sym link
err = os.Symlink(targetStagePath, lnTargetStagePath)
require.Nil(t, err)
defer os.Remove(lnTargetStagePath)

isMountRequest = &v1beta2.IsMountPointRequest{
Path: lnTargetStagePath,
}
isMountResponse, err = client.IsMountPoint(context.Background(), isMountRequest)
require.Nil(t, err)
require.Equal(t, isMountResponse.IsMountPoint, true)

// 4. Remove the path. Failure scenario.
err = os.Remove(targetStagePath)
require.Nil(t, err)
isMountRequest = &v1beta2.IsMountPointRequest{
Path: lnTargetStagePath,
}
isMountResponse, err = client.IsMountPoint(context.Background(), isMountRequest)
require.Nil(t, err)
require.Equal(t, isMountResponse.IsMountPoint, false)
t.Run("v1beta1FilesystemTests", func(t *testing.T) {
v1beta1FilesystemTests(t)
})
t.Run("v1alpha1FilesystemTests", func(t *testing.T) {
v1alpha1FilesystemTests(t)
})
}
Loading