...

Source file src/k8s.io/kubernetes/pkg/util/filesystem/util_windows.go

Documentation: k8s.io/kubernetes/pkg/util/filesystem

     1  //go:build windows
     2  // +build windows
     3  
     4  /*
     5  Copyright 2023 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package filesystem
    21  
    22  import (
    23  	"fmt"
    24  	"net"
    25  	"os"
    26  	"path/filepath"
    27  	"strings"
    28  	"time"
    29  
    30  	"k8s.io/apimachinery/pkg/util/wait"
    31  	"k8s.io/klog/v2"
    32  )
    33  
    34  const (
    35  	// Amount of time to wait between attempting to use a Unix domain socket.
    36  	// As detailed in https://github.com/kubernetes/kubernetes/issues/104584
    37  	// the first attempt will most likely fail, hence the need to retry
    38  	socketDialRetryPeriod = 1 * time.Second
    39  	// Overall timeout value to dial a Unix domain socket, including retries
    40  	socketDialTimeout = 4 * time.Second
    41  )
    42  
    43  // IsUnixDomainSocket returns whether a given file is a AF_UNIX socket file
    44  // Note that due to the retry logic inside, it could take up to 4 seconds
    45  // to determine whether or not the file path supplied is a Unix domain socket
    46  func IsUnixDomainSocket(filePath string) (bool, error) {
    47  	// Due to the absence of golang support for os.ModeSocket in Windows (https://github.com/golang/go/issues/33357)
    48  	// we need to dial the file and check if we receive an error to determine if a file is Unix Domain Socket file.
    49  
    50  	// Note that querrying for the Reparse Points (https://docs.microsoft.com/en-us/windows/win32/fileio/reparse-points)
    51  	// for the file (using FSCTL_GET_REPARSE_POINT) and checking for reparse tag: reparseTagSocket
    52  	// does NOT work in 1809 if the socket file is created within a bind mounted directory by a container
    53  	// and the FSCTL is issued in the host by the kubelet.
    54  
    55  	// If the file does not exist, it cannot be a Unix domain socket.
    56  	if _, err := os.Stat(filePath); os.IsNotExist(err) {
    57  		return false, fmt.Errorf("File %s not found. Err: %v", filePath, err)
    58  	}
    59  
    60  	klog.V(6).InfoS("Function IsUnixDomainSocket starts", "filePath", filePath)
    61  	// As detailed in https://github.com/kubernetes/kubernetes/issues/104584 we cannot rely
    62  	// on the Unix Domain socket working on the very first try, hence the potential need to
    63  	// dial multiple times
    64  	var lastSocketErr error
    65  	err := wait.PollImmediate(socketDialRetryPeriod, socketDialTimeout,
    66  		func() (bool, error) {
    67  			klog.V(6).InfoS("Dialing the socket", "filePath", filePath)
    68  			var c net.Conn
    69  			c, lastSocketErr = net.Dial("unix", filePath)
    70  			if lastSocketErr == nil {
    71  				c.Close()
    72  				klog.V(6).InfoS("Socket dialed successfully", "filePath", filePath)
    73  				return true, nil
    74  			}
    75  			klog.V(6).InfoS("Failed the current attempt to dial the socket, so pausing before retry",
    76  				"filePath", filePath, "err", lastSocketErr, "socketDialRetryPeriod",
    77  				socketDialRetryPeriod)
    78  			return false, nil
    79  		})
    80  
    81  	// PollImmediate will return "timed out waiting for the condition" if the function it
    82  	// invokes never returns true
    83  	if err != nil {
    84  		klog.V(2).InfoS("Failed all attempts to dial the socket so marking it as a non-Unix Domain socket. Last socket error along with the error from PollImmediate follow",
    85  			"filePath", filePath, "lastSocketErr", lastSocketErr, "err", err)
    86  		return false, nil
    87  	}
    88  	return true, nil
    89  }
    90  
    91  // IsAbs returns whether the given path is absolute or not.
    92  // On Windows, filepath.IsAbs will not return True for paths prefixed with a slash, even
    93  // though they can be used as absolute paths (https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats).
    94  //
    95  // WARN: It isn't safe to use this for API values which will propagate across systems (e.g. REST API values
    96  // that get validated on Unix, persisted, then consumed by Windows, etc).
    97  func IsAbs(path string) bool {
    98  	return filepath.IsAbs(path) || strings.HasPrefix(path, `\`) || strings.HasPrefix(path, `/`)
    99  }
   100  

View as plain text