Skip to content

Commit

Permalink
Merge pull request #187 from mauriciopoppe/fileystem-v2alpha1
Browse files Browse the repository at this point in the history
Bump Filesystem API from v1 to v2alpha1
  • Loading branch information
k8s-ci-robot authored Jan 8, 2022
2 parents 7ed8d11 + 88cadeb commit e2ace04
Show file tree
Hide file tree
Showing 13 changed files with 3,030 additions and 0 deletions.
1,046 changes: 1,046 additions & 0 deletions client/api/filesystem/v2alpha1/api.pb.go

Large diffs are not rendered by default.

136 changes: 136 additions & 0 deletions client/api/filesystem/v2alpha1/api.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
syntax = "proto3";

package v2alpha1;

option go_package = "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v2alpha1";

service 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 filesystem.
rpc Mkdir(MkdirRequest) returns (MkdirResponse) {}

// 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) {}

// 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) {}

// IsSymlink checks if a given path is a symlink.
rpc IsSymlink(IsSymlinkRequest) returns (IsSymlinkResponse) {}
}

message PathExistsRequest {
// The path whose existence we want to check in the host's filesystem
string path = 1;
}

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

message MkdirRequest {
// The path to create 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
// Non-existent parent directories in the path will be automatically created.
// Directories will be created with Read and Write privileges of the Windows
// User account under which csi-proxy is started (typically LocalSystem).
//
// Restrictions:
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
// Depending on the context parameter of this function, the path prefix needs
// to match the paths specified either as kubelet-csi-plugins-path
// or as kubelet-pod-path parameters of csi-proxy.
// The path parameter cannot already exist in the host's filesystem.
// UNC paths of the form "\\server\share\path\file" are not allowed.
// All directory separators need to be backslash character: "\".
// Characters: .. / : | ? * in the path are not allowed.
// Maximum path length will be capped to 260 characters.
string path = 1;
}

message MkdirResponse {
// Intentionally empty.
}

message RmdirRequest {
// The path to remove 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
//
// Restrictions:
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
// Depending on the context parameter of this function, the path prefix needs
// to match the paths specified either as kubelet-csi-plugins-path
// or as kubelet-pod-path parameters of csi-proxy.
// UNC paths of the form "\\server\share\path\file" are not allowed.
// All directory separators need to be backslash character: "\".
// Characters: .. / : | ? * in the path are not allowed.
// Path cannot be a file of type symlink.
// Maximum path length will be capped to 260 characters.
string path = 1;

// Force remove all contents under path (if any).
bool force = 2;
}

message RmdirResponse {
// Intentionally empty.
}

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
//
// Restrictions:
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
// The path prefix needs needs to match the paths specified as
// kubelet-csi-plugins-path parameter of csi-proxy.
// UNC paths of the form "\\server\share\path\file" are not allowed.
// All directory separators need to be backslash character: "\".
// Characters: .. / : | ? * in the path are not allowed.
// source_path cannot already exist in the host filesystem.
// Maximum path length will be capped to 260 characters.
string source_path = 1;

// 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
//
// Restrictions:
// Only absolute path (indicated by a drive letter prefix: e.g. "C:\") is accepted.
// The path prefix needs to match the paths specified as
// kubelet-pod-path parameter of csi-proxy.
// UNC paths of the form "\\server\share\path\file" are not allowed.
// All directory separators need to be backslash character: "\".
// Characters: .. / : | ? * in the path are not allowed.
// target_path needs to exist as a directory in the host that is empty.
// target_path cannot be a symbolic link.
// Maximum path length will be capped to 260 characters.
string target_path = 2;
}

message CreateSymlinkResponse {
// Intentionally empty.
}

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

message IsSymlinkResponse {
// Indicates whether the path in IsSymlinkRequest is a symlink.
bool is_symlink = 1;
}
86 changes: 86 additions & 0 deletions client/groups/filesystem/v2alpha1/client_generated.go

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

3 changes: 3 additions & 0 deletions integrationtests/filesystem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ func pathExists(path string) (bool, error) {
}

func TestFilesystemAPIGroup(t *testing.T) {
t.Run("v2alpha1FilesystemTests", func(t *testing.T) {
v2alpha1FilesystemTests(t)
})
t.Run("v1FilesystemTests", func(t *testing.T) {
v1FilesystemTests(t)
})
Expand Down
150 changes: 150 additions & 0 deletions integrationtests/filesystem_v2alpha1_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package integrationtests

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

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

"github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v2alpha1"
v2alpha1client "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v2alpha1"
)

func v2alpha1FilesystemTests(t *testing.T) {
t.Run("PathExists positive", func(t *testing.T) {
client, err := v2alpha1client.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 := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io\\volume%d", r1.Intn(100), r1.Intn(100)), t)
mkdirReq := &v2alpha1.MkdirRequest{
Path: stagepath,
}
_, err = client.Mkdir(context.Background(), mkdirReq)
require.NoError(t, err)

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

// simulate operations around publishing a volume to a pod
podpath := getKubeletPathForTest(fmt.Sprintf("test-pod-id\\volumes\\kubernetes.io~csi\\pvc-test%d", r1.Intn(100)), t)
mkdirReq = &v2alpha1.MkdirRequest{
Path: podpath,
}
_, err = client.Mkdir(context.Background(), mkdirReq)
require.NoError(t, err)

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

sourcePath := stagepath
targetPath := filepath.Join(podpath, "rootvol")
// source <- target
linkReq := &v2alpha1.CreateSymlinkRequest{
SourcePath: sourcePath,
TargetPath: targetPath,
}
_, err = client.CreateSymlink(context.Background(), linkReq)
require.NoError(t, err)

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

// cleanup pvpath
rmdirReq := &v2alpha1.RmdirRequest{
Path: podpath,
Force: true,
}
_, err = client.Rmdir(context.Background(), rmdirReq)
require.NoError(t, err)

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

// cleanup plugin path
rmdirReq = &v2alpha1.RmdirRequest{
Path: stagepath,
Force: true,
}
_, err = client.Rmdir(context.Background(), rmdirReq)
require.NoError(t, err)

exists, err = pathExists(stagepath)
assert.False(t, exists, err)
})
t.Run("IsMount", func(t *testing.T) {
client, err := v2alpha1client.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 := getKubeletPathForTest(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 := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io\\volume%d", rand1, rand2), t)
IsSymlinkRequest := &v2alpha1.IsSymlinkRequest{
Path: stagepath,
}
isSymlink, err := client.IsSymlink(context.Background(), IsSymlinkRequest)
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)
IsSymlinkRequest = &v2alpha1.IsSymlinkRequest{
Path: stagepath,
}
isSymlink, err = client.IsSymlink(context.Background(), IsSymlinkRequest)
require.Nil(t, err)
require.Equal(t, isSymlink.IsSymlink, false)

err = os.Remove(stagepath)
require.Nil(t, err)
targetStagePath := getKubeletPathForTest(fmt.Sprintf("testplugin-%d.csi.io\\volume%d-tgt", rand1, rand2), t)
lnTargetStagePath := getKubeletPathForTest(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)

IsSymlinkRequest = &v2alpha1.IsSymlinkRequest{
Path: lnTargetStagePath,
}
isSymlink, err = client.IsSymlink(context.Background(), IsSymlinkRequest)
require.Nil(t, err)
require.Equal(t, isSymlink.IsSymlink, true)

// 4. Remove the path. Failure scenario.
err = os.Remove(targetStagePath)
require.Nil(t, err)
IsSymlinkRequest = &v2alpha1.IsSymlinkRequest{
Path: lnTargetStagePath,
}
isSymlink, err = client.IsSymlink(context.Background(), IsSymlinkRequest)
require.Nil(t, err)
require.Equal(t, isSymlink.IsSymlink, false)
})
}
Loading

0 comments on commit e2ace04

Please sign in to comment.