From e049e594cd1666b0608694d5211363dd094144cb Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Tue, 28 Apr 2020 07:44:27 -0400 Subject: [PATCH] Copy util directory for use in cri/remote package Signed-off-by: Davanum Srinivas --- .../portforward => }/.import-restrictions | 0 pkg/kubelet/cri/remote/fake/fake_runtime.go | 2 +- pkg/kubelet/cri/remote/remote_image.go | 2 +- pkg/kubelet/cri/remote/remote_runtime.go | 2 +- pkg/kubelet/cri/remote/util/util_unix.go | 145 +++++++++++++ pkg/kubelet/cri/remote/util/util_unix_test.go | 135 ++++++++++++ .../cri/remote/util/util_unsupported.go | 55 +++++ pkg/kubelet/cri/remote/util/util_windows.go | 149 +++++++++++++ .../cri/remote/util/util_windows_test.go | 195 ++++++++++++++++++ .../cri/streaming/.import-restrictions | 6 - .../remotecommand/.import-restrictions | 5 - 11 files changed, 682 insertions(+), 14 deletions(-) rename pkg/kubelet/cri/{streaming/portforward => }/.import-restrictions (100%) create mode 100644 pkg/kubelet/cri/remote/util/util_unix.go create mode 100644 pkg/kubelet/cri/remote/util/util_unix_test.go create mode 100644 pkg/kubelet/cri/remote/util/util_unsupported.go create mode 100644 pkg/kubelet/cri/remote/util/util_windows.go create mode 100644 pkg/kubelet/cri/remote/util/util_windows_test.go delete mode 100644 pkg/kubelet/cri/streaming/.import-restrictions delete mode 100644 pkg/kubelet/cri/streaming/remotecommand/.import-restrictions diff --git a/pkg/kubelet/cri/streaming/portforward/.import-restrictions b/pkg/kubelet/cri/.import-restrictions similarity index 100% rename from pkg/kubelet/cri/streaming/portforward/.import-restrictions rename to pkg/kubelet/cri/.import-restrictions diff --git a/pkg/kubelet/cri/remote/fake/fake_runtime.go b/pkg/kubelet/cri/remote/fake/fake_runtime.go index 23067b4fded..339561f9b8e 100644 --- a/pkg/kubelet/cri/remote/fake/fake_runtime.go +++ b/pkg/kubelet/cri/remote/fake/fake_runtime.go @@ -24,7 +24,7 @@ import ( "google.golang.org/grpc" kubeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" apitest "k8s.io/cri-api/pkg/apis/testing" - "k8s.io/kubernetes/pkg/kubelet/util" + "k8s.io/kubernetes/pkg/kubelet/cri/remote/util" utilexec "k8s.io/utils/exec" ) diff --git a/pkg/kubelet/cri/remote/remote_image.go b/pkg/kubelet/cri/remote/remote_image.go index ea9ae628b80..e8089f666d0 100644 --- a/pkg/kubelet/cri/remote/remote_image.go +++ b/pkg/kubelet/cri/remote/remote_image.go @@ -27,7 +27,7 @@ import ( internalapi "k8s.io/cri-api/pkg/apis" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/util" + "k8s.io/kubernetes/pkg/kubelet/cri/remote/util" ) // RemoteImageService is a gRPC implementation of internalapi.ImageManagerService. diff --git a/pkg/kubelet/cri/remote/remote_runtime.go b/pkg/kubelet/cri/remote/remote_runtime.go index a6596b0f719..24b6012b911 100644 --- a/pkg/kubelet/cri/remote/remote_runtime.go +++ b/pkg/kubelet/cri/remote/remote_runtime.go @@ -29,7 +29,7 @@ import ( "k8s.io/component-base/logs/logreduction" internalapi "k8s.io/cri-api/pkg/apis" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" - "k8s.io/kubernetes/pkg/kubelet/util" + "k8s.io/kubernetes/pkg/kubelet/cri/remote/util" utilexec "k8s.io/utils/exec" ) diff --git a/pkg/kubelet/cri/remote/util/util_unix.go b/pkg/kubelet/cri/remote/util/util_unix.go new file mode 100644 index 00000000000..df9a65c5fa0 --- /dev/null +++ b/pkg/kubelet/cri/remote/util/util_unix.go @@ -0,0 +1,145 @@ +// +build freebsd linux darwin + +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "context" + "fmt" + "io/ioutil" + "net" + "net/url" + "os" + "path/filepath" + + "golang.org/x/sys/unix" + "k8s.io/klog" +) + +const ( + // unixProtocol is the network protocol of unix socket. + unixProtocol = "unix" +) + +// CreateListener creates a listener on the specified endpoint. +func CreateListener(endpoint string) (net.Listener, error) { + protocol, addr, err := parseEndpointWithFallbackProtocol(endpoint, unixProtocol) + if err != nil { + return nil, err + } + if protocol != unixProtocol { + return nil, fmt.Errorf("only support unix socket endpoint") + } + + // Unlink to cleanup the previous socket file. + err = unix.Unlink(addr) + if err != nil && !os.IsNotExist(err) { + return nil, fmt.Errorf("failed to unlink socket file %q: %v", addr, err) + } + + if err := os.MkdirAll(filepath.Dir(addr), 0750); err != nil { + return nil, fmt.Errorf("error creating socket directory %q: %v", filepath.Dir(addr), err) + } + + // Create the socket on a tempfile and move it to the destination socket to handle improprer cleanup + file, err := ioutil.TempFile(filepath.Dir(addr), "") + if err != nil { + return nil, fmt.Errorf("failed to create temporary file: %v", err) + } + + if err := os.Remove(file.Name()); err != nil { + return nil, fmt.Errorf("failed to remove temporary file: %v", err) + } + + l, err := net.Listen(protocol, file.Name()) + if err != nil { + return nil, err + } + + if err = os.Rename(file.Name(), addr); err != nil { + return nil, fmt.Errorf("failed to move temporary file to addr %q: %v", addr, err) + } + + return l, nil +} + +// GetAddressAndDialer returns the address parsed from the given endpoint and a context dialer. +func GetAddressAndDialer(endpoint string) (string, func(ctx context.Context, addr string) (net.Conn, error), error) { + protocol, addr, err := parseEndpointWithFallbackProtocol(endpoint, unixProtocol) + if err != nil { + return "", nil, err + } + if protocol != unixProtocol { + return "", nil, fmt.Errorf("only support unix socket endpoint") + } + + return addr, dial, nil +} + +func dial(ctx context.Context, addr string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, unixProtocol, addr) +} + +func parseEndpointWithFallbackProtocol(endpoint string, fallbackProtocol string) (protocol string, addr string, err error) { + if protocol, addr, err = parseEndpoint(endpoint); err != nil && protocol == "" { + fallbackEndpoint := fallbackProtocol + "://" + endpoint + protocol, addr, err = parseEndpoint(fallbackEndpoint) + if err == nil { + klog.Warningf("Using %q as endpoint is deprecated, please consider using full url format %q.", endpoint, fallbackEndpoint) + } + } + return +} + +func parseEndpoint(endpoint string) (string, string, error) { + u, err := url.Parse(endpoint) + if err != nil { + return "", "", err + } + + switch u.Scheme { + case "tcp": + return "tcp", u.Host, nil + + case "unix": + return "unix", u.Path, nil + + case "": + return "", "", fmt.Errorf("using %q as endpoint is deprecated, please consider using full url format", endpoint) + + default: + return u.Scheme, "", fmt.Errorf("protocol %q not supported", u.Scheme) + } +} + +// IsUnixDomainSocket returns whether a given file is a AF_UNIX socket file +func IsUnixDomainSocket(filePath string) (bool, error) { + fi, err := os.Stat(filePath) + if err != nil { + return false, fmt.Errorf("stat file %s failed: %v", filePath, err) + } + if fi.Mode()&os.ModeSocket == 0 { + return false, nil + } + return true, nil +} + +// NormalizePath is a no-op for Linux for now +func NormalizePath(path string) string { + return path +} diff --git a/pkg/kubelet/cri/remote/util/util_unix_test.go b/pkg/kubelet/cri/remote/util/util_unix_test.go new file mode 100644 index 00000000000..fea4e409f5e --- /dev/null +++ b/pkg/kubelet/cri/remote/util/util_unix_test.go @@ -0,0 +1,135 @@ +// +build freebsd linux darwin + +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "io/ioutil" + "net" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseEndpoint(t *testing.T) { + tests := []struct { + endpoint string + expectError bool + expectedProtocol string + expectedAddr string + }{ + { + endpoint: "unix:///tmp/s1.sock", + expectedProtocol: "unix", + expectedAddr: "/tmp/s1.sock", + }, + { + endpoint: "tcp://localhost:15880", + expectedProtocol: "tcp", + expectedAddr: "localhost:15880", + }, + { + endpoint: "npipe://./pipe/mypipe", + expectedProtocol: "npipe", + expectError: true, + }, + { + endpoint: "tcp1://abc", + expectedProtocol: "tcp1", + expectError: true, + }, + { + endpoint: "a b c", + expectError: true, + }, + } + + for _, test := range tests { + protocol, addr, err := parseEndpoint(test.endpoint) + assert.Equal(t, test.expectedProtocol, protocol) + if test.expectError { + assert.NotNil(t, err, "Expect error during parsing %q", test.endpoint) + continue + } + assert.Nil(t, err, "Expect no error during parsing %q", test.endpoint) + assert.Equal(t, test.expectedAddr, addr) + } + +} + +func TestIsUnixDomainSocket(t *testing.T) { + tests := []struct { + label string + listenOnSocket bool + expectSocket bool + expectError bool + invalidFile bool + }{ + { + label: "Domain Socket file", + listenOnSocket: true, + expectSocket: true, + expectError: false, + }, + { + label: "Non Existent file", + invalidFile: true, + expectError: true, + }, + { + label: "Regular file", + listenOnSocket: false, + expectSocket: false, + expectError: false, + }, + } + for _, test := range tests { + f, err := ioutil.TempFile("", "test-domain-socket") + require.NoErrorf(t, err, "Failed to create file for test purposes: %v while setting up: %s", err, test.label) + addr := f.Name() + f.Close() + var ln *net.UnixListener + if test.listenOnSocket { + os.Remove(addr) + ta, err := net.ResolveUnixAddr("unix", addr) + require.NoErrorf(t, err, "Failed to ResolveUnixAddr: %v while setting up: %s", err, test.label) + ln, err = net.ListenUnix("unix", ta) + require.NoErrorf(t, err, "Failed to ListenUnix: %v while setting up: %s", err, test.label) + } + fileToTest := addr + if test.invalidFile { + fileToTest = fileToTest + ".invalid" + } + result, err := IsUnixDomainSocket(fileToTest) + if test.listenOnSocket { + // this takes care of removing the file associated with the domain socket + ln.Close() + } else { + // explicitly remove regular file + os.Remove(addr) + } + if test.expectError { + assert.NotNil(t, err, "Unexpected nil error from IsUnixDomainSocket for %s", test.label) + } else { + assert.Nil(t, err, "Unexpected error invoking IsUnixDomainSocket for %s", test.label) + } + assert.Equal(t, result, test.expectSocket, "Unexpected result from IsUnixDomainSocket: %v for %s", result, test.label) + } +} diff --git a/pkg/kubelet/cri/remote/util/util_unsupported.go b/pkg/kubelet/cri/remote/util/util_unsupported.go new file mode 100644 index 00000000000..dbf86a5a43b --- /dev/null +++ b/pkg/kubelet/cri/remote/util/util_unsupported.go @@ -0,0 +1,55 @@ +// +build !freebsd,!linux,!windows,!darwin + +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "context" + "fmt" + "net" + "time" +) + +// CreateListener creates a listener on the specified endpoint. +func CreateListener(endpoint string) (net.Listener, error) { + return nil, fmt.Errorf("CreateListener is unsupported in this build") +} + +// GetAddressAndDialer returns the address parsed from the given endpoint and a context dialer. +func GetAddressAndDialer(endpoint string) (string, func(ctx context.Context, addr string) (net.Conn, error), error) { + return "", nil, fmt.Errorf("GetAddressAndDialer is unsupported in this build") +} + +// LockAndCheckSubPath empty implementation +func LockAndCheckSubPath(volumePath, subPath string) ([]uintptr, error) { + return []uintptr{}, nil +} + +// UnlockPath empty implementation +func UnlockPath(fileHandles []uintptr) { +} + +// LocalEndpoint empty implementation +func LocalEndpoint(path, file string) (string, error) { + return "", fmt.Errorf("LocalEndpoints are unsupported in this build") +} + +// GetBootTime empty implementation +func GetBootTime() (time.Time, error) { + return time.Time{}, fmt.Errorf("GetBootTime is unsupported in this build") +} diff --git a/pkg/kubelet/cri/remote/util/util_windows.go b/pkg/kubelet/cri/remote/util/util_windows.go new file mode 100644 index 00000000000..bc62eaa3641 --- /dev/null +++ b/pkg/kubelet/cri/remote/util/util_windows.go @@ -0,0 +1,149 @@ +// +build windows + +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "context" + "fmt" + "net" + "net/url" + "strings" + "syscall" + "time" + + "github.com/Microsoft/go-winio" +) + +const ( + tcpProtocol = "tcp" + npipeProtocol = "npipe" +) + +// CreateListener creates a listener on the specified endpoint. +func CreateListener(endpoint string) (net.Listener, error) { + protocol, addr, err := parseEndpoint(endpoint) + if err != nil { + return nil, err + } + + switch protocol { + case tcpProtocol: + return net.Listen(tcpProtocol, addr) + + case npipeProtocol: + return winio.ListenPipe(addr, nil) + + default: + return nil, fmt.Errorf("only support tcp and npipe endpoint") + } +} + +// GetAddressAndDialer returns the address parsed from the given endpoint and a context dialer. +func GetAddressAndDialer(endpoint string) (string, func(ctx context.Context, addr string) (net.Conn, error), error) { + protocol, addr, err := parseEndpoint(endpoint) + if err != nil { + return "", nil, err + } + + if protocol == tcpProtocol { + return addr, tcpDial, nil + } + + if protocol == npipeProtocol { + return addr, npipeDial, nil + } + + return "", nil, fmt.Errorf("only support tcp and npipe endpoint") +} + +func tcpDial(ctx context.Context, addr string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, tcpProtocol, addr) +} + +func npipeDial(ctx context.Context, addr string) (net.Conn, error) { + return winio.DialPipeContext(ctx, addr) +} + +func parseEndpoint(endpoint string) (string, string, error) { + // url.Parse doesn't recognize \, so replace with / first. + endpoint = strings.Replace(endpoint, "\\", "/", -1) + u, err := url.Parse(endpoint) + if err != nil { + return "", "", err + } + + if u.Scheme == "tcp" { + return "tcp", u.Host, nil + } else if u.Scheme == "npipe" { + if strings.HasPrefix(u.Path, "//./pipe") { + return "npipe", u.Path, nil + } + + // fallback host if not provided. + host := u.Host + if host == "" { + host = "." + } + return "npipe", fmt.Sprintf("//%s%s", host, u.Path), nil + } else if u.Scheme == "" { + return "", "", fmt.Errorf("Using %q as endpoint is deprecated, please consider using full url format", endpoint) + } else { + return u.Scheme, "", fmt.Errorf("protocol %q not supported", u.Scheme) + } +} + +var tickCount = syscall.NewLazyDLL("kernel32.dll").NewProc("GetTickCount64") + +// GetBootTime returns the time at which the machine was started, truncated to the nearest second +func GetBootTime() (time.Time, error) { + currentTime := time.Now() + output, _, err := tickCount.Call() + if errno, ok := err.(syscall.Errno); !ok || errno != 0 { + return time.Time{}, err + } + return currentTime.Add(-time.Duration(output) * time.Millisecond).Truncate(time.Second), nil +} + +// IsUnixDomainSocket returns whether a given file is a AF_UNIX socket file +func IsUnixDomainSocket(filePath string) (bool, error) { + // Due to the absence of golang support for os.ModeSocket in Windows (https://github.com/golang/go/issues/33357) + // we need to dial the file and check if we receive an error to determine if a file is Unix Domain Socket file. + + // Note that querrying for the Reparse Points (https://docs.microsoft.com/en-us/windows/win32/fileio/reparse-points) + // for the file (using FSCTL_GET_REPARSE_POINT) and checking for reparse tag: reparseTagSocket + // does NOT work in 1809 if the socket file is created within a bind mounted directory by a container + // and the FSCTL is issued in the host by the kubelet. + + c, err := net.Dial("unix", filePath) + if err == nil { + c.Close() + return true, nil + } + return false, nil +} + +// NormalizePath converts FS paths returned by certain go frameworks (like fsnotify) +// to native Windows paths that can be passed to Windows specific code +func NormalizePath(path string) string { + path = strings.ReplaceAll(path, "/", "\\") + if strings.HasPrefix(path, "\\") { + path = "c:" + path + } + return path +} diff --git a/pkg/kubelet/cri/remote/util/util_windows_test.go b/pkg/kubelet/cri/remote/util/util_windows_test.go new file mode 100644 index 00000000000..7bf2ada2dec --- /dev/null +++ b/pkg/kubelet/cri/remote/util/util_windows_test.go @@ -0,0 +1,195 @@ +// +build windows + +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package util + +import ( + "io/ioutil" + "math/rand" + "net" + "os" + "testing" + "time" + + winio "github.com/Microsoft/go-winio" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseEndpoint(t *testing.T) { + tests := []struct { + endpoint string + expectError bool + expectedProtocol string + expectedAddr string + }{ + { + endpoint: "unix:///tmp/s1.sock", + expectedProtocol: "unix", + expectError: true, + }, + { + endpoint: "tcp://localhost:15880", + expectedProtocol: "tcp", + expectedAddr: "localhost:15880", + }, + { + endpoint: "npipe://./pipe/mypipe", + expectedProtocol: "npipe", + expectedAddr: "//./pipe/mypipe", + }, + { + endpoint: "npipe:////./pipe/mypipe2", + expectedProtocol: "npipe", + expectedAddr: "//./pipe/mypipe2", + }, + { + endpoint: "npipe:/pipe/mypipe3", + expectedProtocol: "npipe", + expectedAddr: "//./pipe/mypipe3", + }, + { + endpoint: "npipe:\\\\.\\pipe\\mypipe4", + expectedProtocol: "npipe", + expectedAddr: "//./pipe/mypipe4", + }, + { + endpoint: "npipe:\\pipe\\mypipe5", + expectedProtocol: "npipe", + expectedAddr: "//./pipe/mypipe5", + }, + { + endpoint: "tcp1://abc", + expectedProtocol: "tcp1", + expectError: true, + }, + { + endpoint: "a b c", + expectError: true, + }, + } + + for _, test := range tests { + protocol, addr, err := parseEndpoint(test.endpoint) + assert.Equal(t, test.expectedProtocol, protocol) + if test.expectError { + assert.NotNil(t, err, "Expect error during parsing %q", test.endpoint) + continue + } + require.Nil(t, err, "Expect no error during parsing %q", test.endpoint) + assert.Equal(t, test.expectedAddr, addr) + } + +} + +func testPipe(t *testing.T, label string) { + generatePipeName := func(suffixlen int) string { + rand.Seed(time.Now().UnixNano()) + letter := []rune("abcdef0123456789") + b := make([]rune, suffixlen) + for i := range b { + b[i] = letter[rand.Intn(len(letter))] + } + return "\\\\.\\pipe\\test-pipe" + string(b) + } + testFile := generatePipeName(4) + pipeln, err := winio.ListenPipe(testFile, &winio.PipeConfig{SecurityDescriptor: "D:P(A;;GA;;;BA)(A;;GA;;;SY)"}) + defer pipeln.Close() + + require.NoErrorf(t, err, "Failed to listen on named pipe for test purposes: %v while setting up: %s", err, label) + result, err := IsUnixDomainSocket(testFile) + assert.Nil(t, err, "Unexpected error: %v from IsUnixDomainSocket for %s", err, label) + assert.False(t, result, "Unexpected result: true from IsUnixDomainSocket: %v for %s", result, label) +} + +func testRegularFile(t *testing.T, label string, exists bool) { + f, err := ioutil.TempFile("", "test-file") + require.NoErrorf(t, err, "Failed to create file for test purposes: %v while setting up: %s", err, label) + testFile := f.Name() + if !exists { + testFile = testFile + ".absent" + } + f.Close() + result, err := IsUnixDomainSocket(testFile) + os.Remove(f.Name()) + assert.Nil(t, err, "Unexpected error: %v from IsUnixDomainSocket for %s", err, label) + assert.False(t, result, "Unexpected result: true from IsUnixDomainSocket: %v for %s", result, label) +} + +func testUnixDomainSocket(t *testing.T, label string) { + f, err := ioutil.TempFile("", "test-domain-socket") + require.NoErrorf(t, err, "Failed to create file for test purposes: %v while setting up: %s", err, label) + testFile := f.Name() + f.Close() + os.Remove(testFile) + ta, err := net.ResolveUnixAddr("unix", testFile) + require.NoErrorf(t, err, "Failed to ResolveUnixAddr: %v while setting up: %s", err, label) + unixln, err := net.ListenUnix("unix", ta) + require.NoErrorf(t, err, "Failed to ListenUnix: %v while setting up: %s", err, label) + result, err := IsUnixDomainSocket(testFile) + unixln.Close() + assert.Nil(t, err, "Unexpected error: %v from IsUnixDomainSocket for %s", err, label) + assert.True(t, result, "Unexpected result: false from IsUnixDomainSocket: %v for %s", result, label) +} + +func TestIsUnixDomainSocket(t *testing.T) { + testPipe(t, "Named Pipe") + testRegularFile(t, "Regular File that Exists", true) + testRegularFile(t, "Regular File that Does Not Exist", false) + testUnixDomainSocket(t, "Unix Domain Socket File") +} + +func TestNormalizePath(t *testing.T) { + tests := []struct { + originalpath string + normalizedPath string + }{ + { + originalpath: "\\path\\to\\file", + normalizedPath: "c:\\path\\to\\file", + }, + { + originalpath: "/path/to/file", + normalizedPath: "c:\\path\\to\\file", + }, + { + originalpath: "/path/to/dir/", + normalizedPath: "c:\\path\\to\\dir\\", + }, + { + originalpath: "\\path\\to\\dir\\", + normalizedPath: "c:\\path\\to\\dir\\", + }, + { + originalpath: "/file", + normalizedPath: "c:\\file", + }, + { + originalpath: "\\file", + normalizedPath: "c:\\file", + }, + { + originalpath: "fileonly", + normalizedPath: "fileonly", + }, + } + + for _, test := range tests { + assert.Equal(t, test.normalizedPath, NormalizePath(test.originalpath)) + } +} diff --git a/pkg/kubelet/cri/streaming/.import-restrictions b/pkg/kubelet/cri/streaming/.import-restrictions deleted file mode 100644 index de0b1e13135..00000000000 --- a/pkg/kubelet/cri/streaming/.import-restrictions +++ /dev/null @@ -1,6 +0,0 @@ -rules: - # prevent exposing internal api in streaming packages - - selectorRegexp: k8s[.]io/kubernetes - allowedPrefixes: - - k8s.io/kubernetes/pkg/kubelet/server/portforward - - k8s.io/kubernetes/pkg/kubelet/server/remotecommand diff --git a/pkg/kubelet/cri/streaming/remotecommand/.import-restrictions b/pkg/kubelet/cri/streaming/remotecommand/.import-restrictions deleted file mode 100644 index 26ce0c0c025..00000000000 --- a/pkg/kubelet/cri/streaming/remotecommand/.import-restrictions +++ /dev/null @@ -1,5 +0,0 @@ -rules: - # prevent exposing internal api in streaming packages - - selectorRegexp: k8s[.]io/kubernetes - forbiddenPrefixes: - - ''