github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/helper/containercenter/mount_windows.go (about)

     1  // Copyright 2021 iLogtail Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package containercenter
    16  
    17  import (
    18  	"flag"
    19  	"fmt"
    20  	"io/fs"
    21  	"os"
    22  	"strings"
    23  
    24  	"github.com/alibaba/ilogtail/pkg/util"
    25  )
    26  
    27  // Used to collect text files in containers.
    28  // Users need to mount the path expected to collect to driver C, so that
    29  // Logtail container can access them from this path.
    30  // For example, user container mounts host path C:\logs\ to container
    31  // path C:\app\logs\, then Logtail can access this directory through
    32  // C:\logtail_host\logs\. Therefore, user can set Logtail to collect
    33  // text files under C:\app\logs\, such as C:\app\logs\nginx\.
    34  // Type of mount:
    35  // - Docker: -v option when run container.
    36  // - Kubernetes: emptyDir volumn.
    37  var DefaultLogtailMountPath string
    38  
    39  const dockerInstallPathFlagName = "WINDOWS_DOCKER_INSTALL_PATH"
    40  const dockerDataMountPathFlagName = "WINDOWS_DOCKER_DATA_MOUNT_PATH"
    41  
    42  // DockerInstallPath and DockerDataMountPath are used for Windows that
    43  // has multiple drivers. For such case, docker data can be saved on
    44  // non-C driver (DockerInstallPath) and be mounted to driver C (DockerDataMountPath).
    45  //
    46  // Example:
    47  // DockerInstallPath is E:\docker\, DockerDataMountPath is C:\ProgramData\docker\,
    48  // user file path from docker engine is E:\docker\containers\<id>\<id>.json,
    49  // Logtail can access it from C:\ProgramData\docker\containers\<id>\<id>.json,
    50  // because DockerDataMountPath will be mounted into Logtail container with
    51  // same path.
    52  var DockerInstallPath = flag.String(dockerInstallPathFlagName, "", "")
    53  var DockerDataMountPath = flag.String(dockerDataMountPathFlagName, "C:\\ProgramData\\docker", "")
    54  
    55  func init() {
    56  	util.InitFromEnvString(dockerInstallPathFlagName, DockerInstallPath, *DockerInstallPath)
    57  	*DockerInstallPath = addPathSeparatorAtEnd(*DockerInstallPath)
    58  	// Driver letter is removed from DockerInstallPath to support Kubernetes,
    59  	// because different Nodes can install docker to different drivers.
    60  	// eg. Node 1 installs docker in D:\docker\, Node 2 installs docker
    61  	// in E:\docker\, both of them mount docker path to C:\ProgramData\docker,
    62  	// so the actual driver letter is unnecessary.
    63  	*DockerInstallPath = removeDriverLetter(*DockerInstallPath)
    64  
    65  	util.InitFromEnvString(dockerDataMountPathFlagName, DockerDataMountPath, *DockerDataMountPath)
    66  	*DockerDataMountPath = addPathSeparatorAtEnd(*DockerDataMountPath)
    67  
    68  	defaultPath := "C:\\logtail_host"
    69  	_, err := os.Stat(defaultPath)
    70  	// only change default mount path when `C:\logtail_host` path exists.
    71  	if err == nil {
    72  		DefaultLogtailMountPath = defaultPath
    73  	} else {
    74  		DefaultLogtailMountPath = "C:"
    75  	}
    76  	fmt.Printf("running with mount path: %s", DefaultLogtailMountPath)
    77  }
    78  
    79  // addPathSeparatorAtEnd adds path separator at the end of file path.
    80  func addPathSeparatorAtEnd(filePath string) string {
    81  	if filePath == "" || isPathSeparator(filePath[len(filePath)-1]) {
    82  		return filePath
    83  	}
    84  	return filePath + "\\"
    85  }
    86  
    87  // removeDriverLetter removes driver letter and its colon.
    88  // Examples:
    89  // - D:\ -> \
    90  // - E:\docker\ -> \docker\
    91  func removeDriverLetter(filePath string) string {
    92  	if colonPos := strings.Index(filePath, ":"); colonPos != -1 {
    93  		return filePath[colonPos+1:]
    94  	}
    95  	return filePath
    96  }
    97  
    98  func GetMountedFilePath(filePath string) string {
    99  	// No specific installed path, use driver C.
   100  	if *DockerInstallPath == "" {
   101  		return GetMountedFilePathWithBasePath(DefaultLogtailMountPath, filePath)
   102  	}
   103  	// Installed path is not under driver C, remove prefix from filePath
   104  	// and use mount path as base path.
   105  	tempFilePath := removeDriverLetter(filePath)
   106  	if strings.HasPrefix(tempFilePath, *DockerInstallPath) {
   107  		return *DockerDataMountPath + tempFilePath[len(*DockerInstallPath):]
   108  	}
   109  	return filePath
   110  }
   111  
   112  func GetMountedFilePathWithBasePath(basePath, filePath string) string {
   113  	if 0 == len(filePath) || 0 == len(basePath) {
   114  		return ""
   115  	}
   116  	colonPos := strings.Index(filePath, ":")
   117  	if -1 == colonPos {
   118  		// Case: containerd, filePath is not start with driver letter. e.g. \\var\\logs\\pods\\xxx\\0.log.
   119  		return filePath
   120  	}
   121  	return basePath + filePath[colonPos+1:]
   122  }
   123  
   124  func TryGetRealPath(path string) (string, fs.FileInfo) {
   125  	if f, err := os.Stat(path); err == nil {
   126  		return path, f
   127  	}
   128  	return "", nil
   129  }