mirror of https://github.com/k3s-io/k3s
Merge pull request #62154 from dixudx/fix-hostpath-type-windows
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. fix incompatible file type checking on Windows **What this PR does / why we need it**: **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes #62121 **Special notes for your reviewer**: /cc @msau42 @jsafrane /assign @andyzhangx **Release note**: ```release-note fix incompatible file type checking on Windows ```pull/8/head
commit
77d18dbad9
|
@ -102,6 +102,7 @@ go_test(
|
||||||
] + select({
|
] + select({
|
||||||
"@io_bazel_rules_go//go/platform:linux": [
|
"@io_bazel_rules_go//go/platform:linux": [
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
"@io_bazel_rules_go//go/platform:windows": [
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
|
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
||||||
package mount
|
package mount
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -337,3 +338,37 @@ func startsWithBackstep(rel string) bool {
|
||||||
// normalize to / and check for ../
|
// normalize to / and check for ../
|
||||||
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getFileType checks for file/directory/socket and block/character devices
|
||||||
|
func getFileType(pathname string) (FileType, error) {
|
||||||
|
var pathType FileType
|
||||||
|
info, err := os.Stat(pathname)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return pathType, fmt.Errorf("path %q does not exist", pathname)
|
||||||
|
}
|
||||||
|
// err in call to os.Stat
|
||||||
|
if err != nil {
|
||||||
|
return pathType, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks whether the mode is the target mode
|
||||||
|
isSpecificMode := func(mode, targetMode os.FileMode) bool {
|
||||||
|
return mode&targetMode == targetMode
|
||||||
|
}
|
||||||
|
|
||||||
|
mode := info.Mode()
|
||||||
|
if mode.IsDir() {
|
||||||
|
return FileTypeDirectory, nil
|
||||||
|
} else if mode.IsRegular() {
|
||||||
|
return FileTypeFile, nil
|
||||||
|
} else if isSpecificMode(mode, os.ModeSocket) {
|
||||||
|
return FileTypeSocket, nil
|
||||||
|
} else if isSpecificMode(mode, os.ModeDevice) {
|
||||||
|
if isSpecificMode(mode, os.ModeCharDevice) {
|
||||||
|
return FileTypeCharDev, nil
|
||||||
|
}
|
||||||
|
return FileTypeBlockDev, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
||||||
|
}
|
||||||
|
|
|
@ -423,31 +423,7 @@ func (mounter *Mounter) MakeRShared(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||||
var pathType FileType
|
return getFileType(pathname)
|
||||||
finfo, err := os.Stat(pathname)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return pathType, fmt.Errorf("path %q does not exist", pathname)
|
|
||||||
}
|
|
||||||
// err in call to os.Stat
|
|
||||||
if err != nil {
|
|
||||||
return pathType, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mode := finfo.Sys().(*syscall.Stat_t).Mode
|
|
||||||
switch mode & syscall.S_IFMT {
|
|
||||||
case syscall.S_IFSOCK:
|
|
||||||
return FileTypeSocket, nil
|
|
||||||
case syscall.S_IFBLK:
|
|
||||||
return FileTypeBlockDev, nil
|
|
||||||
case syscall.S_IFCHR:
|
|
||||||
return FileTypeCharDev, nil
|
|
||||||
case syscall.S_IFDIR:
|
|
||||||
return FileTypeDirectory, nil
|
|
||||||
case syscall.S_IFREG:
|
|
||||||
return FileTypeFile, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *Mounter) MakeDir(pathname string) error {
|
func (mounter *Mounter) MakeDir(pathname string) error {
|
||||||
|
|
|
@ -25,10 +25,12 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"strconv"
|
"k8s.io/utils/exec"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
@ -1680,3 +1682,110 @@ func TestFindExistingPrefix(t *testing.T) {
|
||||||
os.RemoveAll(base)
|
os.RemoveAll(base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetFileType(t *testing.T) {
|
||||||
|
mounter := Mounter{"fake/path", false}
|
||||||
|
|
||||||
|
testCase := []struct {
|
||||||
|
name string
|
||||||
|
expectedType FileType
|
||||||
|
setUp func() (string, string, error)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Directory Test",
|
||||||
|
FileTypeDirectory,
|
||||||
|
func() (string, string, error) {
|
||||||
|
tempDir, err := ioutil.TempDir("", "test-get-filetype-")
|
||||||
|
return tempDir, tempDir, err
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File Test",
|
||||||
|
FileTypeFile,
|
||||||
|
func() (string, string, error) {
|
||||||
|
tempFile, err := ioutil.TempFile("", "test-get-filetype")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
tempFile.Close()
|
||||||
|
return tempFile.Name(), tempFile.Name(), nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Socket Test",
|
||||||
|
FileTypeSocket,
|
||||||
|
func() (string, string, error) {
|
||||||
|
tempDir, err := ioutil.TempDir("", "test-get-filetype-")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
tempSocketFile, err := createSocketFile(tempDir)
|
||||||
|
return tempSocketFile, tempDir, err
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Block Device Test",
|
||||||
|
FileTypeBlockDev,
|
||||||
|
func() (string, string, error) {
|
||||||
|
tempDir, err := ioutil.TempDir("", "test-get-filetype-")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
tempBlockFile := filepath.Join(tempDir, "test_blk_dev")
|
||||||
|
outputBytes, err := exec.New().Command("mknod", tempBlockFile, "b", "89", "1").CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("%v: %s ", err, outputBytes)
|
||||||
|
}
|
||||||
|
return tempBlockFile, tempDir, err
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Character Device Test",
|
||||||
|
FileTypeCharDev,
|
||||||
|
func() (string, string, error) {
|
||||||
|
tempDir, err := ioutil.TempDir("", "test-get-filetype-")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
tempCharFile := filepath.Join(tempDir, "test_char_dev")
|
||||||
|
outputBytes, err := exec.New().Command("mknod", tempCharFile, "c", "89", "1").CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("%v: %s ", err, outputBytes)
|
||||||
|
}
|
||||||
|
return tempCharFile, tempDir, err
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, tc := range testCase {
|
||||||
|
path, cleanUpPath, err := tc.setUp()
|
||||||
|
if err != nil {
|
||||||
|
// Locally passed, but upstream CI is not friendly to create such device files
|
||||||
|
// Leave "Operation not permitted" out, which can be covered in an e2e test
|
||||||
|
if isOperationNotPermittedError(err) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Fatalf("[%d-%s] unexpected error : %v", idx, tc.name, err)
|
||||||
|
}
|
||||||
|
if len(cleanUpPath) > 0 {
|
||||||
|
defer os.RemoveAll(cleanUpPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileType, err := mounter.GetFileType(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("[%d-%s] unexpected error : %v", idx, tc.name, err)
|
||||||
|
}
|
||||||
|
if fileType != tc.expectedType {
|
||||||
|
t.Fatalf("[%d-%s] expected %s, but got %s", idx, tc.name, tc.expectedType, fileType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isOperationNotPermittedError(err error) bool {
|
||||||
|
if strings.Contains(err.Error(), "Operation not permitted") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -201,31 +201,7 @@ func (mounter *Mounter) MakeRShared(path string) error {
|
||||||
|
|
||||||
// GetFileType checks for sockets/block/character devices
|
// GetFileType checks for sockets/block/character devices
|
||||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||||
var pathType FileType
|
return getFileType(pathname)
|
||||||
info, err := os.Stat(pathname)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return pathType, fmt.Errorf("path %q does not exist", pathname)
|
|
||||||
}
|
|
||||||
// err in call to os.Stat
|
|
||||||
if err != nil {
|
|
||||||
return pathType, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mode := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
|
||||||
switch mode & syscall.S_IFMT {
|
|
||||||
case syscall.S_IFSOCK:
|
|
||||||
return FileTypeSocket, nil
|
|
||||||
case syscall.S_IFBLK:
|
|
||||||
return FileTypeBlockDev, nil
|
|
||||||
case syscall.S_IFCHR:
|
|
||||||
return FileTypeCharDev, nil
|
|
||||||
case syscall.S_IFDIR:
|
|
||||||
return FileTypeDirectory, nil
|
|
||||||
case syscall.S_IFREG:
|
|
||||||
return FileTypeFile, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeFile creates a new directory
|
// MakeFile creates a new directory
|
||||||
|
|
|
@ -20,6 +20,7 @@ package mount
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -551,3 +552,52 @@ func TestPathWithinBase(t *testing.T) {
|
||||||
test.fullPath, test.basePath, result, test.expectedResult)
|
test.fullPath, test.basePath, result, test.expectedResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetFileType(t *testing.T) {
|
||||||
|
mounter := New("fake/path")
|
||||||
|
|
||||||
|
testCase := []struct {
|
||||||
|
name string
|
||||||
|
expectedType FileType
|
||||||
|
setUp func() (string, string, error)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Directory Test",
|
||||||
|
FileTypeDirectory,
|
||||||
|
func() (string, string, error) {
|
||||||
|
tempDir, err := ioutil.TempDir("", "test-get-filetype-")
|
||||||
|
return tempDir, tempDir, err
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File Test",
|
||||||
|
FileTypeFile,
|
||||||
|
func() (string, string, error) {
|
||||||
|
tempFile, err := ioutil.TempFile("", "test-get-filetype")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
tempFile.Close()
|
||||||
|
return tempFile.Name(), tempFile.Name(), nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, tc := range testCase {
|
||||||
|
path, cleanUpPath, err := tc.setUp()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("[%d-%s] unexpected error : %v", idx, tc.name, err)
|
||||||
|
}
|
||||||
|
if len(cleanUpPath) > 0 {
|
||||||
|
defer os.RemoveAll(cleanUpPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileType, err := mounter.GetFileType(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("[%d-%s] unexpected error : %v", idx, tc.name, err)
|
||||||
|
}
|
||||||
|
if fileType != tc.expectedType {
|
||||||
|
t.Fatalf("[%d-%s] expected %s, but got %s", idx, tc.name, tc.expectedType, fileType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue