mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: update kubernetes to v1.20.0
updated kubernetes packages to latest release. Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
4abe128bd8
commit
83559144b1
5
vendor/k8s.io/utils/exec/README.md
generated
vendored
Normal file
5
vendor/k8s.io/utils/exec/README.md
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Exec
|
||||
|
||||
This package provides an interface for `os/exec`. It makes it easier to mock
|
||||
and replace in tests, especially with the [FakeExec](testing/fake_exec.go)
|
||||
struct.
|
4
vendor/k8s.io/utils/io/README.md
generated
vendored
Normal file
4
vendor/k8s.io/utils/io/README.md
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# IO
|
||||
|
||||
This package provides interfaces for working with file IO. Currently it
|
||||
provides functionality for consistently reading a file.
|
1
vendor/k8s.io/utils/mount/OWNERS
generated
vendored
1
vendor/k8s.io/utils/mount/OWNERS
generated
vendored
@ -8,6 +8,7 @@ reviewers:
|
||||
- andyzhangx
|
||||
- gnufied
|
||||
approvers:
|
||||
- andyzhangx
|
||||
- jingxu97
|
||||
- saad-ali
|
||||
- jsafrane
|
||||
|
2
vendor/k8s.io/utils/mount/fake_mounter.go
generated
vendored
2
vendor/k8s.io/utils/mount/fake_mounter.go
generated
vendored
@ -21,7 +21,7 @@ import (
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// FakeMounter implements mount.Interface for tests.
|
||||
|
14
vendor/k8s.io/utils/mount/mount.go
generated
vendored
14
vendor/k8s.io/utils/mount/mount.go
generated
vendored
@ -77,7 +77,7 @@ type Interface interface {
|
||||
var _ Interface = &Mounter{}
|
||||
|
||||
// MountPoint represents a single line in /proc/mounts or /etc/fstab.
|
||||
type MountPoint struct {
|
||||
type MountPoint struct { // nolint: golint
|
||||
Device string
|
||||
Path string
|
||||
Type string
|
||||
@ -86,7 +86,7 @@ type MountPoint struct {
|
||||
Pass int
|
||||
}
|
||||
|
||||
type MountErrorType string
|
||||
type MountErrorType string // nolint: golint
|
||||
|
||||
const (
|
||||
FilesystemMismatch MountErrorType = "FilesystemMismatch"
|
||||
@ -97,7 +97,7 @@ const (
|
||||
UnknownMountError MountErrorType = "UnknownMountError"
|
||||
)
|
||||
|
||||
type MountError struct {
|
||||
type MountError struct { // nolint: golint
|
||||
Type MountErrorType
|
||||
Message string
|
||||
}
|
||||
@ -346,14 +346,14 @@ func StartsWithBackstep(rel string) bool {
|
||||
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
||||
}
|
||||
|
||||
// sanitizedOptionsForLogging will return a comma seperated string containing
|
||||
// sanitizedOptionsForLogging will return a comma separated string containing
|
||||
// options and sensitiveOptions. Each entry in sensitiveOptions will be
|
||||
// replaced with the string sensitiveOptionsRemoved
|
||||
// e.g. o1,o2,<masked>,<masked>
|
||||
func sanitizedOptionsForLogging(options []string, sensitiveOptions []string) string {
|
||||
seperator := ""
|
||||
separator := ""
|
||||
if len(options) > 0 && len(sensitiveOptions) > 0 {
|
||||
seperator = ","
|
||||
separator = ","
|
||||
}
|
||||
|
||||
sensitiveOptionsStart := ""
|
||||
@ -364,7 +364,7 @@ func sanitizedOptionsForLogging(options []string, sensitiveOptions []string) str
|
||||
}
|
||||
|
||||
return strings.Join(options, ",") +
|
||||
seperator +
|
||||
separator +
|
||||
sensitiveOptionsStart +
|
||||
sensitiveOptionsEnd
|
||||
}
|
||||
|
2
vendor/k8s.io/utils/mount/mount_helper_common.go
generated
vendored
2
vendor/k8s.io/utils/mount/mount_helper_common.go
generated
vendored
@ -20,7 +20,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// CleanupMountPoint unmounts the given path and deletes the remaining directory
|
||||
|
2
vendor/k8s.io/utils/mount/mount_helper_unix.go
generated
vendored
2
vendor/k8s.io/utils/mount/mount_helper_unix.go
generated
vendored
@ -56,7 +56,7 @@ func IsCorruptedMnt(err error) bool {
|
||||
}
|
||||
|
||||
// MountInfo represents a single line in /proc/<pid>/mountinfo.
|
||||
type MountInfo struct {
|
||||
type MountInfo struct { // nolint: golint
|
||||
// Unique ID for the mount (maybe reused after umount).
|
||||
ID int
|
||||
// The ID of the parent mount (or of self for the root of this mount namespace's mount tree).
|
||||
|
2
vendor/k8s.io/utils/mount/mount_helper_windows.go
generated
vendored
2
vendor/k8s.io/utils/mount/mount_helper_windows.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// following failure codes are from https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes--1300-1699-
|
||||
|
6
vendor/k8s.io/utils/mount/mount_linux.go
generated
vendored
6
vendor/k8s.io/utils/mount/mount_linux.go
generated
vendored
@ -27,7 +27,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
utilio "k8s.io/utils/io"
|
||||
)
|
||||
@ -103,7 +103,7 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
||||
}
|
||||
|
||||
// doMount runs the mount command. mounterPath is the path to mounter binary if containerized mounter is used.
|
||||
// sensitiveOptions is an extention of options except they will not be logged (because they may contain sensitive material)
|
||||
// sensitiveOptions is an extension of options except they will not be logged (because they may contain sensitive material)
|
||||
func (mounter *Mounter) doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string, sensitiveOptions []string) error {
|
||||
mountArgs, mountArgsLogStr := MakeMountArgsSensitive(source, target, fstype, options, sensitiveOptions)
|
||||
if len(mounterPath) > 0 {
|
||||
@ -187,7 +187,7 @@ func MakeMountArgs(source, target, fstype string, options []string) (mountArgs [
|
||||
}
|
||||
|
||||
// MakeMountArgsSensitive makes the arguments to the mount(8) command.
|
||||
// sensitiveOptions is an extention of options except they will not be logged (because they may contain sensitive material)
|
||||
// sensitiveOptions is an extension of options except they will not be logged (because they may contain sensitive material)
|
||||
func MakeMountArgsSensitive(source, target, fstype string, options []string, sensitiveOptions []string) (mountArgs []string, mountArgsLogStr string) {
|
||||
// Build mount command as follows:
|
||||
// mount [-t $fstype] [-o $options] [$source] $target
|
||||
|
102
vendor/k8s.io/utils/mount/mount_windows.go
generated
vendored
102
vendor/k8s.io/utils/mount/mount_windows.go
generated
vendored
@ -25,10 +25,12 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/keymutex"
|
||||
utilpath "k8s.io/utils/path"
|
||||
)
|
||||
|
||||
const (
|
||||
accessDenied string = "access is denied"
|
||||
)
|
||||
|
||||
// Mounter provides the default implementation of mount.Interface
|
||||
@ -86,9 +88,8 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
||||
allOptions = append(allOptions, options...)
|
||||
allOptions = append(allOptions, sensitiveOptions...)
|
||||
if len(allOptions) < 2 {
|
||||
klog.Warningf("mount options(%q) command number(%d) less than 2, source:%q, target:%q, skip mounting",
|
||||
return fmt.Errorf("mount options(%q) should have at least 2 options, current number:%d, source:%q, target:%q",
|
||||
sanitizedOptionsForLogging, len(allOptions), source, target)
|
||||
return nil
|
||||
}
|
||||
|
||||
// currently only cifs mount is supported
|
||||
@ -100,25 +101,37 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
||||
getSMBMountMutex.LockKey(source)
|
||||
defer getSMBMountMutex.UnlockKey(source)
|
||||
|
||||
if output, err := newSMBMapping(allOptions[0], allOptions[1], source); err != nil {
|
||||
username := allOptions[0]
|
||||
password := allOptions[1]
|
||||
if output, err := newSMBMapping(username, password, source); err != nil {
|
||||
klog.Warningf("SMB Mapping(%s) returned with error(%v), output(%s)", source, err, string(output))
|
||||
if isSMBMappingExist(source) {
|
||||
klog.V(2).Infof("SMB Mapping(%s) already exists, now begin to remove and remount", source)
|
||||
if output, err := removeSMBMapping(source); err != nil {
|
||||
return fmt.Errorf("Remove-SmbGlobalMapping failed: %v, output: %q", err, output)
|
||||
}
|
||||
if output, err := newSMBMapping(allOptions[0], allOptions[1], source); err != nil {
|
||||
return fmt.Errorf("New-SmbGlobalMapping remount failed: %v, output: %q", err, output)
|
||||
valid, err := isValidPath(source)
|
||||
if !valid {
|
||||
if err == nil || isAccessDeniedError(err) {
|
||||
klog.V(2).Infof("SMB Mapping(%s) already exists while it's not valid, return error: %v, now begin to remove and remount", source, err)
|
||||
if output, err = removeSMBMapping(source); err != nil {
|
||||
return fmt.Errorf("Remove-SmbGlobalMapping failed: %v, output: %q", err, output)
|
||||
}
|
||||
if output, err := newSMBMapping(username, password, source); err != nil {
|
||||
return fmt.Errorf("New-SmbGlobalMapping(%s) failed: %v, output: %q", source, err, output)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
klog.V(2).Infof("SMB Mapping(%s) already exists and is still valid, skip error(%v)", source, err)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("New-SmbGlobalMapping failed: %v, output: %q", err, output)
|
||||
return fmt.Errorf("New-SmbGlobalMapping(%s) failed: %v, output: %q", source, err, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if output, err := exec.Command("cmd", "/c", "mklink", "/D", target, bindSource).CombinedOutput(); err != nil {
|
||||
output, err := exec.Command("cmd", "/c", "mklink", "/D", target, bindSource).CombinedOutput()
|
||||
if err != nil {
|
||||
klog.Errorf("mklink failed: %v, source(%q) target(%q) output: %q", err, bindSource, target, string(output))
|
||||
return err
|
||||
}
|
||||
klog.V(2).Infof("mklink source(%q) on target(%q) successfully, output: %q", bindSource, target, string(output))
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -153,6 +166,23 @@ func isSMBMappingExist(remotepath string) bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// check whether remotepath is valid
|
||||
// return (true, nil) if remotepath is valid
|
||||
func isValidPath(remotepath string) (bool, error) {
|
||||
cmd := exec.Command("powershell", "/c", `Test-Path $Env:remoteapth`)
|
||||
cmd.Env = append(os.Environ(), fmt.Sprintf("remoteapth=%s", remotepath))
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("returned output: %s, error: %v", string(output), err)
|
||||
}
|
||||
|
||||
return strings.HasPrefix(strings.ToLower(string(output)), "true"), nil
|
||||
}
|
||||
|
||||
func isAccessDeniedError(err error) bool {
|
||||
return err != nil && strings.Contains(strings.ToLower(err.Error()), accessDenied)
|
||||
}
|
||||
|
||||
// remove SMB mapping
|
||||
func removeSMBMapping(remotepath string) (string, error) {
|
||||
cmd := exec.Command("powershell", "/c", `Remove-SmbGlobalMapping -RemotePath $Env:smbremotepath -Force`)
|
||||
@ -183,19 +213,10 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
// If current file is a symlink, then it is a mountpoint.
|
||||
if stat.Mode()&os.ModeSymlink != 0 {
|
||||
target, err := os.Readlink(file)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("readlink error: %v", err)
|
||||
}
|
||||
exists, err := utilpath.Exists(utilpath.CheckFollowSymlink, target)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return !exists, nil
|
||||
}
|
||||
|
||||
if stat.Mode()&os.ModeSymlink != 0 {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@ -230,37 +251,38 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
||||
|
||||
// format disk if it is unformatted(raw)
|
||||
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru"+
|
||||
" | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype)
|
||||
" | New-Partition -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype)
|
||||
if output, err := mounter.Exec.Command("powershell", "/c", cmd).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output))
|
||||
}
|
||||
klog.V(4).Infof("diskMount: Disk successfully formatted, disk: %q, fstype: %q", source, fstype)
|
||||
|
||||
driveLetter, err := getDriveLetterByDiskNumber(source, mounter.Exec)
|
||||
volumeIds, err := listVolumesOnDisk(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
driverPath := driveLetter + ":"
|
||||
driverPath := volumeIds[0]
|
||||
target = NormalizeWindowsPath(target)
|
||||
klog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, driverPath, target)
|
||||
if output, err := mounter.Exec.Command("cmd", "/c", "mklink", "/D", target, driverPath).CombinedOutput(); err != nil {
|
||||
klog.Errorf("mklink failed: %v, output: %q", err, string(output))
|
||||
output, err := mounter.Exec.Command("cmd", "/c", "mklink", "/D", target, driverPath).CombinedOutput()
|
||||
if err != nil {
|
||||
klog.Errorf("mklink(%s, %s) failed: %v, output: %q", target, driverPath, err, string(output))
|
||||
return err
|
||||
}
|
||||
klog.V(2).Infof("formatAndMount disk(%s) fstype(%s) on(%s) with output(%s) successfully", driverPath, fstype, target, string(output))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get drive letter according to windows disk number
|
||||
func getDriveLetterByDiskNumber(diskNum string, exec utilexec.Interface) (string, error) {
|
||||
cmd := fmt.Sprintf("(Get-Partition -DiskNumber %s).DriveLetter", diskNum)
|
||||
// ListVolumesOnDisk - returns back list of volumes(volumeIDs) in the disk (requested in diskID).
|
||||
func listVolumesOnDisk(diskID string) (volumeIDs []string, err error) {
|
||||
cmd := fmt.Sprintf("(Get-Disk -DeviceId %s | Get-Partition | Get-Volume).UniqueId", diskID)
|
||||
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||
klog.V(4).Infof("listVolumesOnDisk id from %s: %s", diskID, string(output))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("azureMount: Get Drive Letter failed: %v, output: %q", err, string(output))
|
||||
return []string{}, fmt.Errorf("error list volumes on disk. cmd: %s, output: %s, error: %v", cmd, string(output), err)
|
||||
}
|
||||
if len(string(output)) < 1 {
|
||||
return "", fmt.Errorf("azureMount: Get Drive Letter failed, output is empty")
|
||||
}
|
||||
return string(output)[:1], nil
|
||||
|
||||
volumeIds := strings.Split(strings.TrimSpace(string(output)), "\r\n")
|
||||
return volumeIds, nil
|
||||
}
|
||||
|
||||
// getAllParentLinks walks all symbolic links and return all the parent targets recursively
|
||||
|
24
vendor/k8s.io/utils/net/net.go
generated
vendored
24
vendor/k8s.io/utils/net/net.go
generated
vendored
@ -137,6 +137,30 @@ func IsIPv6CIDR(cidr *net.IPNet) bool {
|
||||
return IsIPv6(ip)
|
||||
}
|
||||
|
||||
// IsIPv4 returns if netIP is IPv4.
|
||||
func IsIPv4(netIP net.IP) bool {
|
||||
return netIP != nil && netIP.To4() != nil
|
||||
}
|
||||
|
||||
// IsIPv4String returns if ip is IPv4.
|
||||
func IsIPv4String(ip string) bool {
|
||||
netIP := net.ParseIP(ip)
|
||||
return IsIPv4(netIP)
|
||||
}
|
||||
|
||||
// IsIPv4CIDR returns if a cidr is ipv4
|
||||
func IsIPv4CIDR(cidr *net.IPNet) bool {
|
||||
ip := cidr.IP
|
||||
return IsIPv4(ip)
|
||||
}
|
||||
|
||||
// IsIPv4CIDRString returns if cidr is IPv4.
|
||||
// This assumes cidr is a valid CIDR.
|
||||
func IsIPv4CIDRString(cidr string) bool {
|
||||
ip, _, _ := net.ParseCIDR(cidr)
|
||||
return IsIPv4(ip)
|
||||
}
|
||||
|
||||
// ParsePort parses a string representing an IP port. If the string is not a
|
||||
// valid port number, this returns an error.
|
||||
func ParsePort(port string, allowZero bool) (int, error) {
|
||||
|
4
vendor/k8s.io/utils/nsenter/README.md
generated
vendored
Normal file
4
vendor/k8s.io/utils/nsenter/README.md
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# NSEnter
|
||||
|
||||
This package provides interfaces for executing and interacting with processes
|
||||
running within a namespace.
|
2
vendor/k8s.io/utils/nsenter/nsenter.go
generated
vendored
2
vendor/k8s.io/utils/nsenter/nsenter.go
generated
vendored
@ -26,7 +26,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
|
2
vendor/k8s.io/utils/path/file.go
generated
vendored
2
vendor/k8s.io/utils/path/file.go
generated
vendored
@ -30,7 +30,7 @@ const (
|
||||
// the symlink exists.
|
||||
CheckFollowSymlink LinkTreatment = iota
|
||||
|
||||
// CheckSymlinkOnly does not follow the symlink and verfies only that they
|
||||
// CheckSymlinkOnly does not follow the symlink and verifies only that they
|
||||
// symlink itself exists.
|
||||
CheckSymlinkOnly
|
||||
)
|
||||
|
3
vendor/k8s.io/utils/pointer/README.md
generated
vendored
Normal file
3
vendor/k8s.io/utils/pointer/README.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Pointer
|
||||
|
||||
This package provides some functions for pointer-based operations.
|
49
vendor/k8s.io/utils/pointer/pointer.go
generated
vendored
49
vendor/k8s.io/utils/pointer/pointer.go
generated
vendored
@ -51,14 +51,23 @@ func Int32Ptr(i int32) *int32 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Int32PtrDerefOr dereference the int32 ptr and returns it if not nil,
|
||||
// else returns def.
|
||||
func Int32PtrDerefOr(ptr *int32, def int32) int32 {
|
||||
if ptr != nil {
|
||||
return *ptr
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// Int64Ptr returns a pointer to an int64
|
||||
func Int64Ptr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Int32PtrDerefOr dereference the int32 ptr and returns it if not nil,
|
||||
// Int64PtrDerefOr dereference the int64 ptr and returns it if not nil,
|
||||
// else returns def.
|
||||
func Int32PtrDerefOr(ptr *int32, def int32) int32 {
|
||||
func Int64PtrDerefOr(ptr *int64, def int64) int64 {
|
||||
if ptr != nil {
|
||||
return *ptr
|
||||
}
|
||||
@ -70,17 +79,53 @@ func BoolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
// BoolPtrDerefOr dereference the bool ptr and returns it if not nil,
|
||||
// else returns def.
|
||||
func BoolPtrDerefOr(ptr *bool, def bool) bool {
|
||||
if ptr != nil {
|
||||
return *ptr
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// StringPtr returns a pointer to the passed string.
|
||||
func StringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// StringPtrDerefOr dereference the string ptr and returns it if not nil,
|
||||
// else returns def.
|
||||
func StringPtrDerefOr(ptr *string, def string) string {
|
||||
if ptr != nil {
|
||||
return *ptr
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// Float32Ptr returns a pointer to the passed float32.
|
||||
func Float32Ptr(i float32) *float32 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Float32PtrDerefOr dereference the float32 ptr and returns it if not nil,
|
||||
// else returns def.
|
||||
func Float32PtrDerefOr(ptr *float32, def float32) float32 {
|
||||
if ptr != nil {
|
||||
return *ptr
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// Float64Ptr returns a pointer to the passed float64.
|
||||
func Float64Ptr(i float64) *float64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Float64PtrDerefOr dereference the float64 ptr and returns it if not nil,
|
||||
// else returns def.
|
||||
func Float64PtrDerefOr(ptr *float64, def float64) float64 {
|
||||
if ptr != nil {
|
||||
return *ptr
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
36
vendor/k8s.io/utils/strings/escape.go
generated
vendored
36
vendor/k8s.io/utils/strings/escape.go
generated
vendored
@ -1,36 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 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 strings
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// EscapeQualifiedName converts a plugin name, which might contain a / into a
|
||||
// string that is safe to use on-disk. This assumes that the input has already
|
||||
// been validates as a qualified name. we use "~" rather than ":" here in case
|
||||
// we ever use a filesystem that doesn't allow ":".
|
||||
func EscapeQualifiedName(in string) string {
|
||||
return strings.Replace(in, "/", "~", -1)
|
||||
}
|
||||
|
||||
// UnescapeQualifiedName converts an escaped plugin name (as per EscapeQualifiedName)
|
||||
// back to its normal form. This assumes that the input has already been
|
||||
// validates as a qualified name.
|
||||
func UnescapeQualifiedName(in string) string {
|
||||
return strings.Replace(in, "~", "/", -1)
|
||||
}
|
64
vendor/k8s.io/utils/strings/line_delimiter.go
generated
vendored
64
vendor/k8s.io/utils/strings/line_delimiter.go
generated
vendored
@ -1,64 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 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 strings
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// LineDelimiter is a filter that will split input on lines
|
||||
// and bracket each line with the delimiter string.
|
||||
type LineDelimiter struct {
|
||||
output io.Writer
|
||||
delimiter []byte
|
||||
buf bytes.Buffer
|
||||
}
|
||||
|
||||
// NewLineDelimiter allocates a new io.Writer that will split input on lines
|
||||
// and bracket each line with the delimiter string. This can be useful in
|
||||
// output tests where it is difficult to see and test trailing whitespace.
|
||||
func NewLineDelimiter(output io.Writer, delimiter string) *LineDelimiter {
|
||||
return &LineDelimiter{output: output, delimiter: []byte(delimiter)}
|
||||
}
|
||||
|
||||
// Write writes buf to the LineDelimiter ld. The only errors returned are ones
|
||||
// encountered while writing to the underlying output stream.
|
||||
func (ld *LineDelimiter) Write(buf []byte) (n int, err error) {
|
||||
return ld.buf.Write(buf)
|
||||
}
|
||||
|
||||
// Flush all lines up until now. This will assume insert a linebreak at the current point of the stream.
|
||||
func (ld *LineDelimiter) Flush() (err error) {
|
||||
lines := strings.Split(ld.buf.String(), "\n")
|
||||
for _, line := range lines {
|
||||
if _, err = ld.output.Write(ld.delimiter); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = ld.output.Write([]byte(line)); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = ld.output.Write(ld.delimiter); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = ld.output.Write([]byte("\n")); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
46
vendor/k8s.io/utils/strings/strings.go
generated
vendored
46
vendor/k8s.io/utils/strings/strings.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 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 strings
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SplitQualifiedName Splits a fully qualified name and returns its namespace and name.
|
||||
// Assumes that the input 'str' has been validated.
|
||||
func SplitQualifiedName(str string) (string, string) {
|
||||
parts := strings.Split(str, "/")
|
||||
if len(parts) < 2 {
|
||||
return "", str
|
||||
}
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
||||
// JoinQualifiedName joins 'namespace' and 'name' and returns a fully qualified name
|
||||
// Assumes that the input is valid.
|
||||
func JoinQualifiedName(namespace, name string) string {
|
||||
return path.Join(namespace, name)
|
||||
}
|
||||
|
||||
// ShortenString returns the first N slice of a string.
|
||||
func ShortenString(str string, n int) string {
|
||||
if len(str) <= n {
|
||||
return str
|
||||
}
|
||||
return str[:n]
|
||||
}
|
67
vendor/k8s.io/utils/trace/README.md
generated
vendored
Normal file
67
vendor/k8s.io/utils/trace/README.md
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# Trace
|
||||
|
||||
This package provides an interface for recording the latency of operations and logging details
|
||||
about all operations where the latency exceeds a limit.
|
||||
|
||||
## Usage
|
||||
|
||||
To create a trace:
|
||||
|
||||
```go
|
||||
func doSomething() {
|
||||
opTrace := trace.New("operation", Field{Key: "fieldKey1", Value: "fieldValue1"})
|
||||
defer opTrace.LogIfLong(100 * time.Millisecond)
|
||||
// do something
|
||||
}
|
||||
```
|
||||
|
||||
To split an trace into multiple steps:
|
||||
|
||||
```go
|
||||
func doSomething() {
|
||||
opTrace := trace.New("operation")
|
||||
defer opTrace.LogIfLong(100 * time.Millisecond)
|
||||
// do step 1
|
||||
opTrace.Step("step1", Field{Key: "stepFieldKey1", Value: "stepFieldValue1"})
|
||||
// do step 2
|
||||
opTrace.Step("step2")
|
||||
}
|
||||
```
|
||||
|
||||
To nest traces:
|
||||
|
||||
```go
|
||||
func doSomething() {
|
||||
rootTrace := trace.New("rootOperation")
|
||||
defer rootTrace.LogIfLong(100 * time.Millisecond)
|
||||
|
||||
func() {
|
||||
nestedTrace := rootTrace.Nest("nested", Field{Key: "nestedFieldKey1", Value: "nestedFieldValue1"})
|
||||
defer nestedTrace.LogIfLong(50 * time.Millisecond)
|
||||
// do nested operation
|
||||
}()
|
||||
}
|
||||
```
|
||||
|
||||
Traces can also be logged unconditionally or introspected:
|
||||
|
||||
```go
|
||||
opTrace.TotalTime() // Duration since the Trace was created
|
||||
opTrace.Log() // unconditionally log the trace
|
||||
```
|
||||
|
||||
### Using context.Context to nest traces
|
||||
|
||||
`context.Context` can be used to manage nested traces. Create traces by calling `trace.GetTraceFromContext(ctx).Nest`.
|
||||
This is safe even if there is no parent trace already in the context because `(*(Trace)nil).Nest()` returns
|
||||
a top level trace.
|
||||
|
||||
```go
|
||||
func doSomething(ctx context.Context) {
|
||||
opTrace := trace.FromContext(ctx).Nest("operation") // create a trace, possibly nested
|
||||
ctx = trace.ContextWithTrace(ctx, opTrace) // make this trace the parent trace of the context
|
||||
defer opTrace.LogIfLong(50 * time.Millisecond)
|
||||
|
||||
doSomethingElse(ctx)
|
||||
}
|
||||
```
|
245
vendor/k8s.io/utils/trace/trace.go
generated
vendored
245
vendor/k8s.io/utils/trace/trace.go
generated
vendored
@ -18,13 +18,18 @@ package trace
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var klogV = func(lvl klog.Level) bool {
|
||||
return klog.V(lvl).Enabled()
|
||||
}
|
||||
|
||||
// Field is a key value pair that provides additional details about the trace.
|
||||
type Field struct {
|
||||
Key string
|
||||
@ -44,19 +49,83 @@ func writeFields(b *bytes.Buffer, l []Field) {
|
||||
}
|
||||
}
|
||||
|
||||
func writeTraceItemSummary(b *bytes.Buffer, msg string, totalTime time.Duration, startTime time.Time, fields []Field) {
|
||||
b.WriteString(fmt.Sprintf("%q ", msg))
|
||||
if len(fields) > 0 {
|
||||
writeFields(b, fields)
|
||||
b.WriteString(" ")
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("%vms (%v)", durationToMilliseconds(totalTime), startTime.Format("15:04:00.000")))
|
||||
}
|
||||
|
||||
func durationToMilliseconds(timeDuration time.Duration) int64 {
|
||||
return timeDuration.Nanoseconds() / 1e6
|
||||
}
|
||||
|
||||
type traceItem interface {
|
||||
// time returns when the trace was recorded as completed.
|
||||
time() time.Time
|
||||
// writeItem outputs the traceItem to the buffer. If stepThreshold is non-nil, only output the
|
||||
// traceItem if its the duration exceeds the stepThreshold.
|
||||
// Each line of output is prefixed by formatter to visually indent nested items.
|
||||
writeItem(b *bytes.Buffer, formatter string, startTime time.Time, stepThreshold *time.Duration)
|
||||
}
|
||||
|
||||
type traceStep struct {
|
||||
stepTime time.Time
|
||||
msg string
|
||||
fields []Field
|
||||
}
|
||||
|
||||
func (s traceStep) time() time.Time {
|
||||
return s.stepTime
|
||||
}
|
||||
|
||||
func (s traceStep) writeItem(b *bytes.Buffer, formatter string, startTime time.Time, stepThreshold *time.Duration) {
|
||||
stepDuration := s.stepTime.Sub(startTime)
|
||||
if stepThreshold == nil || *stepThreshold == 0 || stepDuration >= *stepThreshold || klogV(4) {
|
||||
b.WriteString(fmt.Sprintf("%s---", formatter))
|
||||
writeTraceItemSummary(b, s.msg, stepDuration, s.stepTime, s.fields)
|
||||
}
|
||||
}
|
||||
|
||||
// Trace keeps track of a set of "steps" and allows us to log a specific
|
||||
// step if it took longer than its share of the total allowed time
|
||||
type Trace struct {
|
||||
name string
|
||||
fields []Field
|
||||
startTime time.Time
|
||||
steps []traceStep
|
||||
name string
|
||||
fields []Field
|
||||
threshold *time.Duration
|
||||
startTime time.Time
|
||||
endTime *time.Time
|
||||
traceItems []traceItem
|
||||
parentTrace *Trace
|
||||
}
|
||||
|
||||
func (t *Trace) time() time.Time {
|
||||
if t.endTime != nil {
|
||||
return *t.endTime
|
||||
}
|
||||
return t.startTime // if the trace is incomplete, don't assume an end time
|
||||
}
|
||||
|
||||
func (t *Trace) writeItem(b *bytes.Buffer, formatter string, startTime time.Time, stepThreshold *time.Duration) {
|
||||
if t.durationIsWithinThreshold() || klogV(4) {
|
||||
b.WriteString(fmt.Sprintf("%v[", formatter))
|
||||
writeTraceItemSummary(b, t.name, t.TotalTime(), t.startTime, t.fields)
|
||||
if st := t.calculateStepThreshold(); st != nil {
|
||||
stepThreshold = st
|
||||
}
|
||||
t.writeTraceSteps(b, formatter+" ", stepThreshold)
|
||||
b.WriteString("]")
|
||||
return
|
||||
}
|
||||
// If the trace should not be written, still check for nested traces that should be written
|
||||
for _, s := range t.traceItems {
|
||||
if nestedTrace, ok := s.(*Trace); ok {
|
||||
nestedTrace.writeItem(b, formatter, startTime, stepThreshold)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a Trace with the specified name. The name identifies the operation to be traced. The
|
||||
@ -69,63 +138,145 @@ func New(name string, fields ...Field) *Trace {
|
||||
// how long it took. The Fields add key value pairs to provide additional details about the trace
|
||||
// step.
|
||||
func (t *Trace) Step(msg string, fields ...Field) {
|
||||
if t.steps == nil {
|
||||
if t.traceItems == nil {
|
||||
// traces almost always have less than 6 steps, do this to avoid more than a single allocation
|
||||
t.steps = make([]traceStep, 0, 6)
|
||||
t.traceItems = make([]traceItem, 0, 6)
|
||||
}
|
||||
t.steps = append(t.steps, traceStep{stepTime: time.Now(), msg: msg, fields: fields})
|
||||
t.traceItems = append(t.traceItems, traceStep{stepTime: time.Now(), msg: msg, fields: fields})
|
||||
}
|
||||
|
||||
// Log is used to dump all the steps in the Trace
|
||||
// Nest adds a nested trace with the given message and fields and returns it.
|
||||
// As a convenience, if the receiver is nil, returns a top level trace. This allows
|
||||
// one to call FromContext(ctx).Nest without having to check if the trace
|
||||
// in the context is nil.
|
||||
func (t *Trace) Nest(msg string, fields ...Field) *Trace {
|
||||
newTrace := New(msg, fields...)
|
||||
if t != nil {
|
||||
newTrace.parentTrace = t
|
||||
t.traceItems = append(t.traceItems, newTrace)
|
||||
}
|
||||
return newTrace
|
||||
}
|
||||
|
||||
// Log is used to dump all the steps in the Trace. It also logs the nested trace messages using indentation.
|
||||
// If the Trace is nested it is not immediately logged. Instead, it is logged when the trace it is nested within
|
||||
// is logged.
|
||||
func (t *Trace) Log() {
|
||||
// an explicit logging request should dump all the steps out at the higher level
|
||||
t.logWithStepThreshold(0)
|
||||
}
|
||||
|
||||
func (t *Trace) logWithStepThreshold(stepThreshold time.Duration) {
|
||||
var buffer bytes.Buffer
|
||||
tracenum := rand.Int31()
|
||||
endTime := time.Now()
|
||||
|
||||
totalTime := endTime.Sub(t.startTime)
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: %q ", tracenum, t.name))
|
||||
if len(t.fields) > 0 {
|
||||
writeFields(&buffer, t.fields)
|
||||
buffer.WriteString(" ")
|
||||
t.endTime = &endTime
|
||||
// an explicit logging request should dump all the steps out at the higher level
|
||||
if t.parentTrace == nil { // We don't start logging until Log or LogIfLong is called on the root trace
|
||||
t.logTrace()
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf("(started: %v) (total time: %v):\n", t.startTime, totalTime))
|
||||
lastStepTime := t.startTime
|
||||
for _, step := range t.steps {
|
||||
stepDuration := step.stepTime.Sub(lastStepTime)
|
||||
if stepThreshold == 0 || stepDuration > stepThreshold || klog.V(4) {
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: [%v] [%v] ", tracenum, step.stepTime.Sub(t.startTime), stepDuration))
|
||||
buffer.WriteString(step.msg)
|
||||
if len(step.fields) > 0 {
|
||||
buffer.WriteString(" ")
|
||||
writeFields(&buffer, step.fields)
|
||||
}
|
||||
buffer.WriteString("\n")
|
||||
}
|
||||
lastStepTime = step.stepTime
|
||||
}
|
||||
stepDuration := endTime.Sub(lastStepTime)
|
||||
if stepThreshold == 0 || stepDuration > stepThreshold || klog.V(4) {
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: [%v] [%v] END\n", tracenum, endTime.Sub(t.startTime), stepDuration))
|
||||
}
|
||||
|
||||
klog.Info(buffer.String())
|
||||
}
|
||||
|
||||
// LogIfLong is used to dump steps that took longer than its share
|
||||
// LogIfLong only logs the trace if the duration of the trace exceeds the threshold.
|
||||
// Only steps that took longer than their share or the given threshold are logged.
|
||||
// If klog is at verbosity level 4 or higher and the trace took longer than the threshold,
|
||||
// all substeps and subtraces are logged. Otherwise, only those which took longer than
|
||||
// their own threshold.
|
||||
// If the Trace is nested it is not immediately logged. Instead, it is logged when the trace it
|
||||
// is nested within is logged.
|
||||
func (t *Trace) LogIfLong(threshold time.Duration) {
|
||||
if time.Since(t.startTime) >= threshold {
|
||||
t.threshold = &threshold
|
||||
t.Log()
|
||||
}
|
||||
|
||||
// logTopLevelTraces finds all traces in a hierarchy of nested traces that should be logged but do not have any
|
||||
// parents that will be logged, due to threshold limits, and logs them as top level traces.
|
||||
func (t *Trace) logTrace() {
|
||||
if t.durationIsWithinThreshold() {
|
||||
var buffer bytes.Buffer
|
||||
traceNum := rand.Int31()
|
||||
|
||||
totalTime := t.endTime.Sub(t.startTime)
|
||||
buffer.WriteString(fmt.Sprintf("Trace[%d]: %q ", traceNum, t.name))
|
||||
if len(t.fields) > 0 {
|
||||
writeFields(&buffer, t.fields)
|
||||
buffer.WriteString(" ")
|
||||
}
|
||||
|
||||
// if any step took more than it's share of the total allowed time, it deserves a higher log level
|
||||
stepThreshold := threshold / time.Duration(len(t.steps)+1)
|
||||
t.logWithStepThreshold(stepThreshold)
|
||||
buffer.WriteString(fmt.Sprintf("(%v) (total time: %vms):", t.startTime.Format("02-Jan-2006 15:04:05.000"), totalTime.Milliseconds()))
|
||||
stepThreshold := t.calculateStepThreshold()
|
||||
t.writeTraceSteps(&buffer, fmt.Sprintf("\nTrace[%d]: ", traceNum), stepThreshold)
|
||||
buffer.WriteString(fmt.Sprintf("\nTrace[%d]: [%v] [%v] END\n", traceNum, t.endTime.Sub(t.startTime), totalTime))
|
||||
|
||||
klog.Info(buffer.String())
|
||||
return
|
||||
}
|
||||
|
||||
// If the trace should not be logged, still check if nested traces should be logged
|
||||
for _, s := range t.traceItems {
|
||||
if nestedTrace, ok := s.(*Trace); ok {
|
||||
nestedTrace.logTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Trace) writeTraceSteps(b *bytes.Buffer, formatter string, stepThreshold *time.Duration) {
|
||||
lastStepTime := t.startTime
|
||||
for _, stepOrTrace := range t.traceItems {
|
||||
stepOrTrace.writeItem(b, formatter, lastStepTime, stepThreshold)
|
||||
lastStepTime = stepOrTrace.time()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Trace) durationIsWithinThreshold() bool {
|
||||
if t.endTime == nil { // we don't assume incomplete traces meet the threshold
|
||||
return false
|
||||
}
|
||||
return t.threshold == nil || *t.threshold == 0 || t.endTime.Sub(t.startTime) >= *t.threshold
|
||||
}
|
||||
|
||||
// TotalTime can be used to figure out how long it took since the Trace was created
|
||||
func (t *Trace) TotalTime() time.Duration {
|
||||
return time.Since(t.startTime)
|
||||
}
|
||||
|
||||
// calculateStepThreshold returns a threshold for the individual steps of a trace, or nil if there is no threshold and
|
||||
// all steps should be written.
|
||||
func (t *Trace) calculateStepThreshold() *time.Duration {
|
||||
if t.threshold == nil {
|
||||
return nil
|
||||
}
|
||||
lenTrace := len(t.traceItems) + 1
|
||||
traceThreshold := *t.threshold
|
||||
for _, s := range t.traceItems {
|
||||
nestedTrace, ok := s.(*Trace)
|
||||
if ok && nestedTrace.threshold != nil {
|
||||
traceThreshold = traceThreshold - *nestedTrace.threshold
|
||||
lenTrace--
|
||||
}
|
||||
}
|
||||
|
||||
// the limit threshold is used when the threshold(
|
||||
//remaining after subtracting that of the child trace) is getting very close to zero to prevent unnecessary logging
|
||||
limitThreshold := *t.threshold / 4
|
||||
if traceThreshold < limitThreshold {
|
||||
traceThreshold = limitThreshold
|
||||
lenTrace = len(t.traceItems) + 1
|
||||
}
|
||||
|
||||
stepThreshold := traceThreshold / time.Duration(lenTrace)
|
||||
return &stepThreshold
|
||||
}
|
||||
|
||||
// ContextTraceKey provides a common key for traces in context.Context values.
|
||||
type ContextTraceKey struct{}
|
||||
|
||||
// FromContext returns the trace keyed by ContextTraceKey in the context values, if one
|
||||
// is present, or nil If there is no trace in the Context.
|
||||
// It is safe to call Nest() on the returned value even if it is nil because ((*Trace)nil).Nest returns a top level
|
||||
// trace.
|
||||
func FromContext(ctx context.Context) *Trace {
|
||||
if v, ok := ctx.Value(ContextTraceKey{}).(*Trace); ok {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextWithTrace returns a context with trace included in the context values, keyed by ContextTraceKey.
|
||||
func ContextWithTrace(ctx context.Context, trace *Trace) context.Context {
|
||||
return context.WithValue(ctx, ContextTraceKey{}, trace)
|
||||
}
|
||||
|
Reference in New Issue
Block a user