node: re-implement Localendpoint on windows

this will allows us to move forward with the podresources
endpoint GA graduation.

xref: https://github.com/kubernetes/kubernetes/issues/78628

Signed-off-by: Francesco Romani <fromani@redhat.com>
This commit is contained in:
Francesco Romani 2023-01-17 15:43:14 +01:00
parent 195fc2f516
commit 6b4ffdb9f7
3 changed files with 67 additions and 2 deletions

View File

@ -230,6 +230,7 @@ func ListenAndServePodResources(endpoint string, providers podresources.PodResou
os.Exit(1)
}
klog.InfoS("Starting to serve the podresources API", "endpoint", endpoint)
if err := server.Serve(l); err != nil {
klog.ErrorS(err, "Failed to serve")
os.Exit(1)

View File

@ -24,6 +24,7 @@ import (
"fmt"
"net"
"net/url"
"path/filepath"
"strings"
"syscall"
"time"
@ -117,9 +118,27 @@ func parseEndpoint(endpoint string) (string, string, error) {
}
}
// LocalEndpoint empty implementation
// LocalEndpoint returns the full path to a named pipe at the given endpoint - unlike on unix, we can't use sockets.
func LocalEndpoint(path, file string) (string, error) {
return "", fmt.Errorf("LocalEndpoints are unsupported in this build")
// extract the podresources config name from the path. We only need this on windows because the preferred layout of pipes,
// this is why we have the extra logic in here instead of changing the function signature. Join the file to make sure the
// last path component is a file, so the operation chain works..
podResourcesDir := filepath.Base(filepath.Dir(filepath.Join(path, file)))
if podResourcesDir == "" {
// should not happen because the user can configure a root directory, and we expected a subdirectory inside
// the user supplied root directory named like "pod-resources" or so.
return "", fmt.Errorf("cannot infer the podresources directory from path %q", path)
}
// windows pipes are expected to use forward slashes: https://learn.microsoft.com/windows/win32/ipc/pipe-names
// so using `url` like we do on unix gives us unclear benefits - see https://github.com/kubernetes/kubernetes/issues/78628
// So we just construct the path from scratch.
// Format: \\ServerName\pipe\PipeName
// Where where ServerName is either the name of a remote computer or a period, to specify the local computer.
// We only consider PipeName as regular windows path, while the pipe path components are fixed, hence we use constants.
serverPart := `\\.`
pipePart := "pipe"
pipeName := "kubelet-" + podResourcesDir
return npipeProtocol + "://" + filepath.Join(serverPart, pipePart, pipeName), nil
}
var tickCount = syscall.NewLazyDLL("kernel32.dll").NewProc("GetTickCount64")

View File

@ -277,3 +277,48 @@ func TestNormalizePath(t *testing.T) {
assert.Equal(t, test.normalizedPath, NormalizePath(test.originalpath))
}
}
func TestLocalEndpoint(t *testing.T) {
tests := []struct {
path string
file string
expectError bool
expectedFullPath string
}{
{
path: "/var/lib/kubelet/pod-resources",
file: "kube.sock", // this is not the default, but it's not relevant here
expectError: false,
expectedFullPath: `npipe://\\.\pipe\kubelet-pod-resources`,
},
}
for _, test := range tests {
fullPath, err := LocalEndpoint(test.path, test.file)
if test.expectError {
assert.NotNil(t, err, "expected error")
continue
}
assert.Nil(t, err, "expected no error")
assert.Equal(t, test.expectedFullPath, fullPath)
}
}
func TestLocalEndpointRoundTrip(t *testing.T) {
npipeDialPointer := reflect.ValueOf(npipeDial).Pointer()
expectedDialerName := runtime.FuncForPC(npipeDialPointer).Name()
expectedAddress := "//./pipe/kubelet-pod-resources"
fullPath, err := LocalEndpoint(`pod-resources`, "kubelet")
require.NoErrorf(t, err, "Failed to create the local endpoint path")
address, dialer, err := GetAddressAndDialer(fullPath)
require.NoErrorf(t, err, "Failed to parse the endpoint path and get back address and dialer (path=%q)", fullPath)
dialerPointer := reflect.ValueOf(dialer).Pointer()
actualDialerName := runtime.FuncForPC(dialerPointer).Name()
assert.Equalf(t, npipeDialPointer, dialerPointer,
"Expected dialer %s, but get %s", expectedDialerName, actualDialerName)
assert.Equal(t, expectedAddress, address)
}