Merge pull request #394 from andyzhangx/force-unmount
fix: use force unmount to fix unmount NFS volume stuck issue
This commit is contained in:
commit
f084312ad0
13
go.mod
13
go.mod
@ -9,16 +9,16 @@ require (
|
|||||||
github.com/onsi/ginkgo v1.14.0
|
github.com/onsi/ginkgo v1.14.0
|
||||||
github.com/onsi/gomega v1.10.1
|
github.com/onsi/gomega v1.10.1
|
||||||
github.com/pborman/uuid v1.2.0
|
github.com/pborman/uuid v1.2.0
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/net v0.4.0
|
golang.org/x/net v0.4.0
|
||||||
google.golang.org/grpc v1.40.0
|
google.golang.org/grpc v1.40.0
|
||||||
k8s.io/api v0.23.3
|
k8s.io/api v0.23.3
|
||||||
k8s.io/apimachinery v0.23.3
|
k8s.io/apimachinery v0.23.3
|
||||||
k8s.io/client-go v0.23.3
|
k8s.io/client-go v0.23.3
|
||||||
k8s.io/klog/v2 v2.30.0
|
k8s.io/klog/v2 v2.80.1
|
||||||
k8s.io/kubernetes v1.23.3
|
k8s.io/kubernetes v1.23.3
|
||||||
k8s.io/mount-utils v0.23.3
|
k8s.io/mount-utils v0.23.3
|
||||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed
|
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ require (
|
|||||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||||
github.com/go-logr/logr v1.2.0 // indirect
|
github.com/go-logr/logr v1.2.3 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/go-cmp v0.5.5 // indirect
|
github.com/google/go-cmp v0.5.5 // indirect
|
||||||
@ -48,6 +48,7 @@ require (
|
|||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||||
github.com/moby/spdystream v0.2.0 // indirect
|
github.com/moby/spdystream v0.2.0 // indirect
|
||||||
|
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/nxadm/tail v1.4.4 // indirect
|
github.com/nxadm/tail v1.4.4 // indirect
|
||||||
@ -85,7 +86,7 @@ require (
|
|||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/apiserver v0.23.3 // indirect
|
k8s.io/apiserver v0.23.3 // indirect
|
||||||
k8s.io/cloud-provider v0.23.3 // indirect
|
k8s.io/cloud-provider v0.23.3 // indirect
|
||||||
k8s.io/component-base v0.23.3 // indirect
|
k8s.io/component-base v0.23.3 // indirect
|
||||||
@ -122,7 +123,7 @@ replace (
|
|||||||
k8s.io/kubelet => k8s.io/kubelet v0.23.3
|
k8s.io/kubelet => k8s.io/kubelet v0.23.3
|
||||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.3
|
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.3
|
||||||
k8s.io/metrics => k8s.io/metrics v0.23.3
|
k8s.io/metrics => k8s.io/metrics v0.23.3
|
||||||
k8s.io/mount-utils => k8s.io/mount-utils v0.23.3
|
k8s.io/mount-utils => k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2
|
||||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.3
|
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.3
|
||||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.3
|
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.3
|
||||||
k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.3
|
k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.3
|
||||||
|
|||||||
24
go.sum
24
go.sum
@ -212,8 +212,9 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
|||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||||
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
|
|
||||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||||
|
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
|
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
@ -429,6 +430,8 @@ github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hx
|
|||||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||||
|
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||||
|
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
|
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@ -544,7 +547,6 @@ github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE
|
|||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
|
||||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
@ -566,13 +568,16 @@ github.com/storageos/go-api v2.2.0+incompatible/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwb
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
@ -1097,8 +1102,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
@ -1134,8 +1140,9 @@ k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAE
|
|||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||||
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||||
k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
|
|
||||||
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||||
|
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
|
||||||
|
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||||
k8s.io/kube-aggregator v0.23.3/go.mod h1:pt5QJ3QaIdhZzNlUvN5wndbM0LNT4BvhszGkzy2QdFo=
|
k8s.io/kube-aggregator v0.23.3/go.mod h1:pt5QJ3QaIdhZzNlUvN5wndbM0LNT4BvhszGkzy2QdFo=
|
||||||
k8s.io/kube-controller-manager v0.23.3/go.mod h1:e8m5dhjei67DlLZA/QTvenxiGyonG9UhgHtU1LMslJE=
|
k8s.io/kube-controller-manager v0.23.3/go.mod h1:e8m5dhjei67DlLZA/QTvenxiGyonG9UhgHtU1LMslJE=
|
||||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||||
@ -1151,15 +1158,16 @@ k8s.io/kubernetes v1.23.3 h1:weuFJOkRP7+057uvhNUYbVTVCog/klquhbtKRD+UHUo=
|
|||||||
k8s.io/kubernetes v1.23.3/go.mod h1:C0AB/I7M4Nu6d1ELyGdC8qrrHEc6J5l8CHUashza1Io=
|
k8s.io/kubernetes v1.23.3/go.mod h1:C0AB/I7M4Nu6d1ELyGdC8qrrHEc6J5l8CHUashza1Io=
|
||||||
k8s.io/legacy-cloud-providers v0.23.3/go.mod h1:s9vv59dUv4SU+HAm9C/YDdyw2OY9qmFYmcGEwr/ecDc=
|
k8s.io/legacy-cloud-providers v0.23.3/go.mod h1:s9vv59dUv4SU+HAm9C/YDdyw2OY9qmFYmcGEwr/ecDc=
|
||||||
k8s.io/metrics v0.23.3/go.mod h1:Ut8TvkbsO4oMVeUzaTArvPrcw9QRFLs2XNzUlORjdYE=
|
k8s.io/metrics v0.23.3/go.mod h1:Ut8TvkbsO4oMVeUzaTArvPrcw9QRFLs2XNzUlORjdYE=
|
||||||
k8s.io/mount-utils v0.23.3 h1:zPRPjS5rCOeEo4M6H5ysnwddVuYwEgJsiMgo2fgbPH0=
|
k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2 h1:kfACKquxtsEA7XXDy+iC92lg/1stK0UtzAhf7R2Y8Fc=
|
||||||
k8s.io/mount-utils v0.23.3/go.mod h1:OTN3LQPiOGMfx/SmVlsnySwsAmh4gYrDYLchlMHtf98=
|
k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2/go.mod h1:au99w4FWU5ZWelLb3Yx6kJc8RZ387IyWVM9tN65Yhxo=
|
||||||
k8s.io/pod-security-admission v0.23.3/go.mod h1:vULEGUgsujyrKBz3RRRZnvrJJt115gu0GICArDmgzqo=
|
k8s.io/pod-security-admission v0.23.3/go.mod h1:vULEGUgsujyrKBz3RRRZnvrJJt115gu0GICArDmgzqo=
|
||||||
k8s.io/sample-apiserver v0.23.3/go.mod h1:5yDZRMfFvp7/2BOXBwk0AFNsD00iyuXeEsWZSoLFeGw=
|
k8s.io/sample-apiserver v0.23.3/go.mod h1:5yDZRMfFvp7/2BOXBwk0AFNsD00iyuXeEsWZSoLFeGw=
|
||||||
k8s.io/system-validators v1.6.0/go.mod h1:bPldcLgkIUK22ALflnsXk8pvkTEndYdNuaHH6gRrl0Q=
|
k8s.io/system-validators v1.6.0/go.mod h1:bPldcLgkIUK22ALflnsXk8pvkTEndYdNuaHH6gRrl0Q=
|
||||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed h1:ck1fRPWPJWsMd8ZRFsWc6mh/zHp5fZ/shhbrgPUxDAE=
|
|
||||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
|
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs=
|
||||||
|
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||||
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
|
||||||
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
|
||||||
|
|||||||
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package nfs
|
package nfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||||
@ -108,7 +109,12 @@ func (n *Driver) Run(testMode bool) {
|
|||||||
}
|
}
|
||||||
klog.V(2).Infof("\nDRIVER INFORMATION:\n-------------------\n%s\n\nStreaming logs below:", versionMeta)
|
klog.V(2).Infof("\nDRIVER INFORMATION:\n-------------------\n%s\n\nStreaming logs below:", versionMeta)
|
||||||
|
|
||||||
n.ns = NewNodeServer(n, mount.New(""))
|
mounter := mount.New("")
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
// MounterForceUnmounter is only implemented on Linux now
|
||||||
|
mounter = mounter.(mount.MounterForceUnmounter)
|
||||||
|
}
|
||||||
|
n.ns = NewNodeServer(n, mounter)
|
||||||
s := NewNonBlockingGRPCServer()
|
s := NewNonBlockingGRPCServer()
|
||||||
s.Start(n.endpoint,
|
s.Start(n.endpoint,
|
||||||
NewDefaultIdentityServer(n),
|
NewDefaultIdentityServer(n),
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
@ -154,7 +155,15 @@ func (ns *NodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
klog.V(2).Infof("NodeUnpublishVolume: unmounting volume %s on %s", volumeID, targetPath)
|
klog.V(2).Infof("NodeUnpublishVolume: unmounting volume %s on %s", volumeID, targetPath)
|
||||||
err := mount.CleanupMountPoint(targetPath, ns.mounter, true /*extensiveMountPointCheck*/)
|
var err error
|
||||||
|
extensiveMountPointCheck := true
|
||||||
|
forceUnmounter, ok := ns.mounter.(mount.MounterForceUnmounter)
|
||||||
|
if ok {
|
||||||
|
klog.V(2).Infof("force unmount %s on %s", volumeID, targetPath)
|
||||||
|
err = mount.CleanupMountWithForce(targetPath, forceUnmounter, extensiveMountPointCheck, 30*time.Second)
|
||||||
|
} else {
|
||||||
|
err = mount.CleanupMountPoint(targetPath, ns.mounter, extensiveMountPointCheck)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "failed to unmount target %q: %v", targetPath, err)
|
return nil, status.Errorf(codes.Internal, "failed to unmount target %q: %v", targetPath, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,6 @@ package nfs
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@ -217,11 +216,6 @@ func TestNodeUnpublishVolume(t *testing.T) {
|
|||||||
req: csi.NodeUnpublishVolumeRequest{VolumeId: "vol_1"},
|
req: csi.NodeUnpublishVolumeRequest{VolumeId: "vol_1"},
|
||||||
expectedErr: status.Error(codes.InvalidArgument, "Target path missing in request"),
|
expectedErr: status.Error(codes.InvalidArgument, "Target path missing in request"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
desc: "[Error] Unmount error mocked by IsLikelyNotMountPoint",
|
|
||||||
req: csi.NodeUnpublishVolumeRequest{TargetPath: errorTarget, VolumeId: "vol_1"},
|
|
||||||
expectedErr: fmt.Errorf("fake IsLikelyNotMountPoint: fake error"),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
desc: "[Success] Volume not mounted",
|
desc: "[Success] Volume not mounted",
|
||||||
req: csi.NodeUnpublishVolumeRequest{TargetPath: targetFile, VolumeId: "vol_1"},
|
req: csi.NodeUnpublishVolumeRequest{TargetPath: targetFile, VolumeId: "vol_1"},
|
||||||
|
|||||||
4
vendor/github.com/go-logr/logr/README.md
generated
vendored
4
vendor/github.com/go-logr/logr/README.md
generated
vendored
@ -105,14 +105,18 @@ with higher verbosity means more (and less important) logs will be generated.
|
|||||||
There are implementations for the following logging libraries:
|
There are implementations for the following logging libraries:
|
||||||
|
|
||||||
- **a function** (can bridge to non-structured libraries): [funcr](https://github.com/go-logr/logr/tree/master/funcr)
|
- **a function** (can bridge to non-structured libraries): [funcr](https://github.com/go-logr/logr/tree/master/funcr)
|
||||||
|
- **a testing.T** (for use in Go tests, with JSON-like output): [testr](https://github.com/go-logr/logr/tree/master/testr)
|
||||||
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
|
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
|
||||||
- **k8s.io/klog** (for Kubernetes): [klogr](https://git.k8s.io/klog/klogr)
|
- **k8s.io/klog** (for Kubernetes): [klogr](https://git.k8s.io/klog/klogr)
|
||||||
|
- **a testing.T** (with klog-like text output): [ktesting](https://git.k8s.io/klog/ktesting)
|
||||||
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
|
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
|
||||||
- **log** (the Go standard library logger): [stdr](https://github.com/go-logr/stdr)
|
- **log** (the Go standard library logger): [stdr](https://github.com/go-logr/stdr)
|
||||||
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
|
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
|
||||||
- **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
|
- **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
|
||||||
- **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
|
- **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
|
||||||
- **github.com/rs/zerolog**: [zerologr](https://github.com/go-logr/zerologr)
|
- **github.com/rs/zerolog**: [zerologr](https://github.com/go-logr/zerologr)
|
||||||
|
- **github.com/go-kit/log**: [gokitlogr](https://github.com/tonglil/gokitlogr) (also compatible with github.com/go-kit/kit/log since v0.12.0)
|
||||||
|
- **bytes.Buffer** (writing to a buffer): [bufrlogr](https://github.com/tonglil/buflogr) (useful for ensuring values were logged, like during testing)
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
|
|||||||
20
vendor/github.com/go-logr/logr/logr.go
generated
vendored
20
vendor/github.com/go-logr/logr/logr.go
generated
vendored
@ -43,7 +43,9 @@ limitations under the License.
|
|||||||
//
|
//
|
||||||
// Info() and Error() are very similar, but they are separate methods so that
|
// Info() and Error() are very similar, but they are separate methods so that
|
||||||
// LogSink implementations can choose to do things like attach additional
|
// LogSink implementations can choose to do things like attach additional
|
||||||
// information (such as stack traces) on calls to Error().
|
// information (such as stack traces) on calls to Error(). Error() messages are
|
||||||
|
// always logged, regardless of the current verbosity. If there is no error
|
||||||
|
// instance available, passing nil is valid.
|
||||||
//
|
//
|
||||||
// Verbosity
|
// Verbosity
|
||||||
//
|
//
|
||||||
@ -53,6 +55,7 @@ limitations under the License.
|
|||||||
// Log-lines with V-levels that are not enabled (as per the LogSink) will not
|
// Log-lines with V-levels that are not enabled (as per the LogSink) will not
|
||||||
// be written. Level V(0) is the default, and logger.V(0).Info() has the same
|
// be written. Level V(0) is the default, and logger.V(0).Info() has the same
|
||||||
// meaning as logger.Info(). Negative V-levels have the same meaning as V(0).
|
// meaning as logger.Info(). Negative V-levels have the same meaning as V(0).
|
||||||
|
// Error messages do not have a verbosity level and are always logged.
|
||||||
//
|
//
|
||||||
// Where we might have written:
|
// Where we might have written:
|
||||||
// if flVerbose >= 2 {
|
// if flVerbose >= 2 {
|
||||||
@ -112,6 +115,15 @@ limitations under the License.
|
|||||||
// may be any Go value, but how the value is formatted is determined by the
|
// may be any Go value, but how the value is formatted is determined by the
|
||||||
// LogSink implementation.
|
// LogSink implementation.
|
||||||
//
|
//
|
||||||
|
// Logger instances are meant to be passed around by value. Code that receives
|
||||||
|
// such a value can call its methods without having to check whether the
|
||||||
|
// instance is ready for use.
|
||||||
|
//
|
||||||
|
// Calling methods with the null logger (Logger{}) as instance will crash
|
||||||
|
// because it has no LogSink. Therefore this null logger should never be passed
|
||||||
|
// around. For cases where passing a logger is optional, a pointer to Logger
|
||||||
|
// should be used.
|
||||||
|
//
|
||||||
// Key Naming Conventions
|
// Key Naming Conventions
|
||||||
//
|
//
|
||||||
// Keys are not strictly required to conform to any specification or regex, but
|
// Keys are not strictly required to conform to any specification or regex, but
|
||||||
@ -253,11 +265,13 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) {
|
|||||||
// Error logs an error, with the given message and key/value pairs as context.
|
// Error logs an error, with the given message and key/value pairs as context.
|
||||||
// It functions similarly to Info, but may have unique behavior, and should be
|
// It functions similarly to Info, but may have unique behavior, and should be
|
||||||
// preferred for logging errors (see the package documentations for more
|
// preferred for logging errors (see the package documentations for more
|
||||||
// information).
|
// information). The log message will always be emitted, regardless of
|
||||||
|
// verbosity level.
|
||||||
//
|
//
|
||||||
// The msg argument should be used to add context to any underlying error,
|
// The msg argument should be used to add context to any underlying error,
|
||||||
// while the err argument should be used to attach the actual error that
|
// while the err argument should be used to attach the actual error that
|
||||||
// triggered this log line, if present.
|
// triggered this log line, if present. The err parameter is optional
|
||||||
|
// and nil may be passed instead of an error instance.
|
||||||
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
|
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||||
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
|
||||||
withHelper.GetCallStackHelper()()
|
withHelper.GetCallStackHelper()()
|
||||||
|
|||||||
202
vendor/github.com/moby/sys/mountinfo/LICENSE
generated
vendored
Normal file
202
vendor/github.com/moby/sys/mountinfo/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
44
vendor/github.com/moby/sys/mountinfo/doc.go
generated
vendored
Normal file
44
vendor/github.com/moby/sys/mountinfo/doc.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Package mountinfo provides a set of functions to retrieve information about OS mounts.
|
||||||
|
//
|
||||||
|
// Currently it supports Linux. For historical reasons, there is also some support for FreeBSD and OpenBSD,
|
||||||
|
// and a shallow implementation for Windows, but in general this is Linux-only package, so
|
||||||
|
// the rest of the document only applies to Linux, unless explicitly specified otherwise.
|
||||||
|
//
|
||||||
|
// In Linux, information about mounts seen by the current process is available from
|
||||||
|
// /proc/self/mountinfo. Note that due to mount namespaces, different processes can
|
||||||
|
// see different mounts. A per-process mountinfo table is available from /proc/<PID>/mountinfo,
|
||||||
|
// where <PID> is a numerical process identifier.
|
||||||
|
//
|
||||||
|
// In general, /proc is not a very efficient interface, and mountinfo is not an exception.
|
||||||
|
// For example, there is no way to get information about a specific mount point (i.e. it
|
||||||
|
// is all-or-nothing). This package tries to hide the /proc ineffectiveness by using
|
||||||
|
// parse filters while reading mountinfo. A filter can skip some entries, or stop
|
||||||
|
// processing the rest of the file once the needed information is found.
|
||||||
|
//
|
||||||
|
// For mountinfo filters that accept path as an argument, the path must be absolute,
|
||||||
|
// having all symlinks resolved, and being cleaned (i.e. no extra slashes or dots).
|
||||||
|
// One way to achieve all of the above is to employ filepath.Abs followed by
|
||||||
|
// filepath.EvalSymlinks (the latter calls filepath.Clean on the result so
|
||||||
|
// there is no need to explicitly call filepath.Clean).
|
||||||
|
//
|
||||||
|
// NOTE that in many cases there is no need to consult mountinfo at all. Here are some
|
||||||
|
// of the cases where mountinfo should not be parsed:
|
||||||
|
//
|
||||||
|
// 1. Before performing a mount. Usually, this is not needed, but if required (say to
|
||||||
|
// prevent over-mounts), to check whether a directory is mounted, call os.Lstat
|
||||||
|
// on it and its parent directory, and compare their st.Sys().(*syscall.Stat_t).Dev
|
||||||
|
// fields -- if they differ, then the directory is the mount point. NOTE this does
|
||||||
|
// not work for bind mounts. Optionally, the filesystem type can also be checked
|
||||||
|
// by calling unix.Statfs and checking the Type field (i.e. filesystem type).
|
||||||
|
//
|
||||||
|
// 2. After performing a mount. If there is no error returned, the mount succeeded;
|
||||||
|
// checking the mount table for a new mount is redundant and expensive.
|
||||||
|
//
|
||||||
|
// 3. Before performing an unmount. It is more efficient to do an unmount and ignore
|
||||||
|
// a specific error (EINVAL) which tells the directory is not mounted.
|
||||||
|
//
|
||||||
|
// 4. After performing an unmount. If there is no error returned, the unmount succeeded.
|
||||||
|
//
|
||||||
|
// 5. To find the mount point root of a specific directory. You can perform os.Stat()
|
||||||
|
// on the directory and traverse up until the Dev field of a parent directory differs.
|
||||||
|
package mountinfo
|
||||||
101
vendor/github.com/moby/sys/mountinfo/mounted_linux.go
generated
vendored
Normal file
101
vendor/github.com/moby/sys/mountinfo/mounted_linux.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MountedFast is a method of detecting a mount point without reading
|
||||||
|
// mountinfo from procfs. A caller can only trust the result if no error
|
||||||
|
// and sure == true are returned. Otherwise, other methods (e.g. parsing
|
||||||
|
// /proc/mounts) have to be used. If unsure, use Mounted instead (which
|
||||||
|
// uses MountedFast, but falls back to parsing mountinfo if needed).
|
||||||
|
//
|
||||||
|
// If a non-existent path is specified, an appropriate error is returned.
|
||||||
|
// In case the caller is not interested in this particular error, it should
|
||||||
|
// be handled separately using e.g. errors.Is(err, fs.ErrNotExist).
|
||||||
|
//
|
||||||
|
// This function is only available on Linux. When available (since kernel
|
||||||
|
// v5.6), openat2(2) syscall is used to reliably detect all mounts. Otherwise,
|
||||||
|
// the implementation falls back to using stat(2), which can reliably detect
|
||||||
|
// normal (but not bind) mounts.
|
||||||
|
func MountedFast(path string) (mounted, sure bool, err error) {
|
||||||
|
// Root is always mounted.
|
||||||
|
if path == string(os.PathSeparator) {
|
||||||
|
return true, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err = normalizePath(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, false, err
|
||||||
|
}
|
||||||
|
mounted, sure, err = mountedFast(path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// mountedByOpenat2 is a method of detecting a mount that works for all kinds
|
||||||
|
// of mounts (incl. bind mounts), but requires a recent (v5.6+) linux kernel.
|
||||||
|
func mountedByOpenat2(path string) (bool, error) {
|
||||||
|
dir, last := filepath.Split(path)
|
||||||
|
|
||||||
|
dirfd, err := unix.Openat2(unix.AT_FDCWD, dir, &unix.OpenHow{
|
||||||
|
Flags: unix.O_PATH | unix.O_CLOEXEC,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return false, &os.PathError{Op: "openat2", Path: dir, Err: err}
|
||||||
|
}
|
||||||
|
fd, err := unix.Openat2(dirfd, last, &unix.OpenHow{
|
||||||
|
Flags: unix.O_PATH | unix.O_CLOEXEC | unix.O_NOFOLLOW,
|
||||||
|
Resolve: unix.RESOLVE_NO_XDEV,
|
||||||
|
})
|
||||||
|
_ = unix.Close(dirfd)
|
||||||
|
switch err { //nolint:errorlint // unix errors are bare
|
||||||
|
case nil: // definitely not a mount
|
||||||
|
_ = unix.Close(fd)
|
||||||
|
return false, nil
|
||||||
|
case unix.EXDEV: // definitely a mount
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
// not sure
|
||||||
|
return false, &os.PathError{Op: "openat2", Path: path, Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mountedFast is similar to MountedFast, except it expects a normalized path.
|
||||||
|
func mountedFast(path string) (mounted, sure bool, err error) {
|
||||||
|
// Root is always mounted.
|
||||||
|
if path == string(os.PathSeparator) {
|
||||||
|
return true, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try a fast path, using openat2() with RESOLVE_NO_XDEV.
|
||||||
|
mounted, err = mountedByOpenat2(path)
|
||||||
|
if err == nil {
|
||||||
|
return mounted, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Another fast path: compare st.st_dev fields.
|
||||||
|
mounted, err = mountedByStat(path)
|
||||||
|
// This does not work for bind mounts, so false negative
|
||||||
|
// is possible, therefore only trust if return is true.
|
||||||
|
if mounted && err == nil {
|
||||||
|
return true, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func mounted(path string) (bool, error) {
|
||||||
|
path, err := normalizePath(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
mounted, sure, err := mountedFast(path)
|
||||||
|
if sure && err == nil {
|
||||||
|
return mounted, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to parsing mountinfo.
|
||||||
|
return mountedByMountinfo(path)
|
||||||
|
}
|
||||||
53
vendor/github.com/moby/sys/mountinfo/mounted_unix.go
generated
vendored
Normal file
53
vendor/github.com/moby/sys/mountinfo/mounted_unix.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//go:build linux || freebsd || openbsd || darwin
|
||||||
|
// +build linux freebsd openbsd darwin
|
||||||
|
|
||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mountedByStat(path string) (bool, error) {
|
||||||
|
var st unix.Stat_t
|
||||||
|
|
||||||
|
if err := unix.Lstat(path, &st); err != nil {
|
||||||
|
return false, &os.PathError{Op: "stat", Path: path, Err: err}
|
||||||
|
}
|
||||||
|
dev := st.Dev
|
||||||
|
parent := filepath.Dir(path)
|
||||||
|
if err := unix.Lstat(parent, &st); err != nil {
|
||||||
|
return false, &os.PathError{Op: "stat", Path: parent, Err: err}
|
||||||
|
}
|
||||||
|
if dev != st.Dev {
|
||||||
|
// Device differs from that of parent,
|
||||||
|
// so definitely a mount point.
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
// NB: this does not detect bind mounts on Linux.
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizePath(path string) (realPath string, err error) {
|
||||||
|
if realPath, err = filepath.Abs(path); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if realPath, err = filepath.EvalSymlinks(realPath); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(realPath); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return realPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mountedByMountinfo(path string) (bool, error) {
|
||||||
|
entries, err := GetMounts(SingleEntryFilter(path))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(entries) > 0, nil
|
||||||
|
}
|
||||||
67
vendor/github.com/moby/sys/mountinfo/mountinfo.go
generated
vendored
Normal file
67
vendor/github.com/moby/sys/mountinfo/mountinfo.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetMounts retrieves a list of mounts for the current running process,
|
||||||
|
// with an optional filter applied (use nil for no filter).
|
||||||
|
func GetMounts(f FilterFunc) ([]*Info, error) {
|
||||||
|
return parseMountTable(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mounted determines if a specified path is a mount point. In case of any
|
||||||
|
// error, false (and an error) is returned.
|
||||||
|
//
|
||||||
|
// If a non-existent path is specified, an appropriate error is returned.
|
||||||
|
// In case the caller is not interested in this particular error, it should
|
||||||
|
// be handled separately using e.g. errors.Is(err, fs.ErrNotExist).
|
||||||
|
func Mounted(path string) (bool, error) {
|
||||||
|
// root is always mounted
|
||||||
|
if path == string(os.PathSeparator) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return mounted(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info reveals information about a particular mounted filesystem. This
|
||||||
|
// struct is populated from the content in the /proc/<pid>/mountinfo file.
|
||||||
|
type Info struct {
|
||||||
|
// ID is a unique identifier of the mount (may be reused after umount).
|
||||||
|
ID int
|
||||||
|
|
||||||
|
// Parent is the ID of the parent mount (or of self for the root
|
||||||
|
// of this mount namespace's mount tree).
|
||||||
|
Parent int
|
||||||
|
|
||||||
|
// Major and Minor are the major and the minor components of the Dev
|
||||||
|
// field of unix.Stat_t structure returned by unix.*Stat calls for
|
||||||
|
// files on this filesystem.
|
||||||
|
Major, Minor int
|
||||||
|
|
||||||
|
// Root is the pathname of the directory in the filesystem which forms
|
||||||
|
// the root of this mount.
|
||||||
|
Root string
|
||||||
|
|
||||||
|
// Mountpoint is the pathname of the mount point relative to the
|
||||||
|
// process's root directory.
|
||||||
|
Mountpoint string
|
||||||
|
|
||||||
|
// Options is a comma-separated list of mount options.
|
||||||
|
Options string
|
||||||
|
|
||||||
|
// Optional are zero or more fields of the form "tag[:value]",
|
||||||
|
// separated by a space. Currently, the possible optional fields are
|
||||||
|
// "shared", "master", "propagate_from", and "unbindable". For more
|
||||||
|
// information, see mount_namespaces(7) Linux man page.
|
||||||
|
Optional string
|
||||||
|
|
||||||
|
// FSType is the filesystem type in the form "type[.subtype]".
|
||||||
|
FSType string
|
||||||
|
|
||||||
|
// Source is filesystem-specific information, or "none".
|
||||||
|
Source string
|
||||||
|
|
||||||
|
// VFSOptions is a comma-separated list of superblock options.
|
||||||
|
VFSOptions string
|
||||||
|
}
|
||||||
56
vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go
generated
vendored
Normal file
56
vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//go:build freebsd || openbsd || darwin
|
||||||
|
// +build freebsd openbsd darwin
|
||||||
|
|
||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
// parseMountTable returns information about mounted filesystems
|
||||||
|
func parseMountTable(filter FilterFunc) ([]*Info, error) {
|
||||||
|
count, err := unix.Getfsstat(nil, unix.MNT_WAIT)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
entries := make([]unix.Statfs_t, count)
|
||||||
|
_, err = unix.Getfsstat(entries, unix.MNT_WAIT)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var out []*Info
|
||||||
|
for _, entry := range entries {
|
||||||
|
var skip, stop bool
|
||||||
|
mountinfo := getMountinfo(&entry)
|
||||||
|
|
||||||
|
if filter != nil {
|
||||||
|
// filter out entries we're not interested in
|
||||||
|
skip, stop = filter(mountinfo)
|
||||||
|
if skip {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out = append(out, mountinfo)
|
||||||
|
if stop {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mounted(path string) (bool, error) {
|
||||||
|
path, err := normalizePath(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
// Fast path: compare st.st_dev fields.
|
||||||
|
// This should always work for FreeBSD and OpenBSD.
|
||||||
|
mounted, err := mountedByStat(path)
|
||||||
|
if err == nil {
|
||||||
|
return mounted, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to parsing mountinfo
|
||||||
|
return mountedByMountinfo(path)
|
||||||
|
}
|
||||||
63
vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go
generated
vendored
Normal file
63
vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// FilterFunc is a type defining a callback function for GetMount(),
|
||||||
|
// used to filter out mountinfo entries we're not interested in,
|
||||||
|
// and/or stop further processing if we found what we wanted.
|
||||||
|
//
|
||||||
|
// It takes a pointer to the Info struct (fully populated with all available
|
||||||
|
// fields on the GOOS platform), and returns two booleans:
|
||||||
|
//
|
||||||
|
// skip: true if the entry should be skipped;
|
||||||
|
//
|
||||||
|
// stop: true if parsing should be stopped after the entry.
|
||||||
|
type FilterFunc func(*Info) (skip, stop bool)
|
||||||
|
|
||||||
|
// PrefixFilter discards all entries whose mount points do not start with, or
|
||||||
|
// are equal to the path specified in prefix. The prefix path must be absolute,
|
||||||
|
// have all symlinks resolved, and cleaned (i.e. no extra slashes or dots).
|
||||||
|
//
|
||||||
|
// PrefixFilter treats prefix as a path, not a partial prefix, which means that
|
||||||
|
// given "/foo", "/foo/bar" and "/foobar" entries, PrefixFilter("/foo") returns
|
||||||
|
// "/foo" and "/foo/bar", and discards "/foobar".
|
||||||
|
func PrefixFilter(prefix string) FilterFunc {
|
||||||
|
return func(m *Info) (bool, bool) {
|
||||||
|
skip := !strings.HasPrefix(m.Mountpoint+"/", prefix+"/")
|
||||||
|
return skip, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SingleEntryFilter looks for a specific entry.
|
||||||
|
func SingleEntryFilter(mp string) FilterFunc {
|
||||||
|
return func(m *Info) (bool, bool) {
|
||||||
|
if m.Mountpoint == mp {
|
||||||
|
return false, true // don't skip, stop now
|
||||||
|
}
|
||||||
|
return true, false // skip, keep going
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsFilter returns all entries whose mount points
|
||||||
|
// can be parents of a path specified, discarding others.
|
||||||
|
//
|
||||||
|
// For example, given /var/lib/docker/something, entries
|
||||||
|
// like /var/lib/docker, /var and / are returned.
|
||||||
|
func ParentsFilter(path string) FilterFunc {
|
||||||
|
return func(m *Info) (bool, bool) {
|
||||||
|
skip := !strings.HasPrefix(path, m.Mountpoint)
|
||||||
|
return skip, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FSTypeFilter returns all entries that match provided fstype(s).
|
||||||
|
func FSTypeFilter(fstype ...string) FilterFunc {
|
||||||
|
return func(m *Info) (bool, bool) {
|
||||||
|
for _, t := range fstype {
|
||||||
|
if m.FSType == t {
|
||||||
|
return false, false // don't skip, keep going
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, false // skip, keep going
|
||||||
|
}
|
||||||
|
}
|
||||||
14
vendor/github.com/moby/sys/mountinfo/mountinfo_freebsdlike.go
generated
vendored
Normal file
14
vendor/github.com/moby/sys/mountinfo/mountinfo_freebsdlike.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//go:build freebsd || darwin
|
||||||
|
// +build freebsd darwin
|
||||||
|
|
||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
func getMountinfo(entry *unix.Statfs_t) *Info {
|
||||||
|
return &Info{
|
||||||
|
Mountpoint: unix.ByteSliceToString(entry.Mntonname[:]),
|
||||||
|
FSType: unix.ByteSliceToString(entry.Fstypename[:]),
|
||||||
|
Source: unix.ByteSliceToString(entry.Mntfromname[:]),
|
||||||
|
}
|
||||||
|
}
|
||||||
214
vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
generated
vendored
Normal file
214
vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go
generated
vendored
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetMountsFromReader retrieves a list of mounts from the
|
||||||
|
// reader provided, with an optional filter applied (use nil
|
||||||
|
// for no filter). This can be useful in tests or benchmarks
|
||||||
|
// that provide fake mountinfo data, or when a source other
|
||||||
|
// than /proc/self/mountinfo needs to be read from.
|
||||||
|
//
|
||||||
|
// This function is Linux-specific.
|
||||||
|
func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
|
out := []*Info{}
|
||||||
|
for s.Scan() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
/*
|
||||||
|
See http://man7.org/linux/man-pages/man5/proc.5.html
|
||||||
|
|
||||||
|
36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
|
||||||
|
(1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
|
||||||
|
|
||||||
|
(1) mount ID: unique identifier of the mount (may be reused after umount)
|
||||||
|
(2) parent ID: ID of parent (or of self for the top of the mount tree)
|
||||||
|
(3) major:minor: value of st_dev for files on filesystem
|
||||||
|
(4) root: root of the mount within the filesystem
|
||||||
|
(5) mount point: mount point relative to the process's root
|
||||||
|
(6) mount options: per mount options
|
||||||
|
(7) optional fields: zero or more fields of the form "tag[:value]"
|
||||||
|
(8) separator: marks the end of the optional fields
|
||||||
|
(9) filesystem type: name of filesystem of the form "type[.subtype]"
|
||||||
|
(10) mount source: filesystem specific information or "none"
|
||||||
|
(11) super options: per super block options
|
||||||
|
|
||||||
|
In other words, we have:
|
||||||
|
* 6 mandatory fields (1)..(6)
|
||||||
|
* 0 or more optional fields (7)
|
||||||
|
* a separator field (8)
|
||||||
|
* 3 mandatory fields (9)..(11)
|
||||||
|
*/
|
||||||
|
|
||||||
|
text := s.Text()
|
||||||
|
fields := strings.Split(text, " ")
|
||||||
|
numFields := len(fields)
|
||||||
|
if numFields < 10 {
|
||||||
|
// should be at least 10 fields
|
||||||
|
return nil, fmt.Errorf("parsing '%s' failed: not enough fields (%d)", text, numFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
// separator field
|
||||||
|
sepIdx := numFields - 4
|
||||||
|
// In Linux <= 3.9 mounting a cifs with spaces in a share
|
||||||
|
// name (like "//srv/My Docs") _may_ end up having a space
|
||||||
|
// in the last field of mountinfo (like "unc=//serv/My Docs").
|
||||||
|
// Since kernel 3.10-rc1, cifs option "unc=" is ignored,
|
||||||
|
// so spaces should not appear.
|
||||||
|
//
|
||||||
|
// Check for a separator, and work around the spaces bug
|
||||||
|
for fields[sepIdx] != "-" {
|
||||||
|
sepIdx--
|
||||||
|
if sepIdx == 5 {
|
||||||
|
return nil, fmt.Errorf("parsing '%s' failed: missing - separator", text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &Info{}
|
||||||
|
|
||||||
|
p.Mountpoint, err = unescape(fields[4])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing '%s' failed: mount point: %w", fields[4], err)
|
||||||
|
}
|
||||||
|
p.FSType, err = unescape(fields[sepIdx+1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing '%s' failed: fstype: %w", fields[sepIdx+1], err)
|
||||||
|
}
|
||||||
|
p.Source, err = unescape(fields[sepIdx+2])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing '%s' failed: source: %w", fields[sepIdx+2], err)
|
||||||
|
}
|
||||||
|
p.VFSOptions = fields[sepIdx+3]
|
||||||
|
|
||||||
|
// ignore any numbers parsing errors, as there should not be any
|
||||||
|
p.ID, _ = strconv.Atoi(fields[0])
|
||||||
|
p.Parent, _ = strconv.Atoi(fields[1])
|
||||||
|
mm := strings.SplitN(fields[2], ":", 3)
|
||||||
|
if len(mm) != 2 {
|
||||||
|
return nil, fmt.Errorf("parsing '%s' failed: unexpected major:minor pair %s", text, mm)
|
||||||
|
}
|
||||||
|
p.Major, _ = strconv.Atoi(mm[0])
|
||||||
|
p.Minor, _ = strconv.Atoi(mm[1])
|
||||||
|
|
||||||
|
p.Root, err = unescape(fields[3])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parsing '%s' failed: root: %w", fields[3], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Options = fields[5]
|
||||||
|
|
||||||
|
// zero or more optional fields
|
||||||
|
p.Optional = strings.Join(fields[6:sepIdx], " ")
|
||||||
|
|
||||||
|
// Run the filter after parsing all fields.
|
||||||
|
var skip, stop bool
|
||||||
|
if filter != nil {
|
||||||
|
skip, stop = filter(p)
|
||||||
|
if skip {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out = append(out, p)
|
||||||
|
if stop {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseMountTable(filter FilterFunc) ([]*Info, error) {
|
||||||
|
f, err := os.Open("/proc/self/mountinfo")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
return GetMountsFromReader(f, filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PidMountInfo retrieves the list of mounts from a given process' mount
|
||||||
|
// namespace. Unless there is a need to get mounts from a mount namespace
|
||||||
|
// different from that of a calling process, use GetMounts.
|
||||||
|
//
|
||||||
|
// This function is Linux-specific.
|
||||||
|
//
|
||||||
|
// Deprecated: this will be removed before v1; use GetMountsFromReader with
|
||||||
|
// opened /proc/<pid>/mountinfo as an argument instead.
|
||||||
|
func PidMountInfo(pid int) ([]*Info, error) {
|
||||||
|
f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
return GetMountsFromReader(f, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A few specific characters in mountinfo path entries (root and mountpoint)
|
||||||
|
// are escaped using a backslash followed by a character's ascii code in octal.
|
||||||
|
//
|
||||||
|
// space -- as \040
|
||||||
|
// tab (aka \t) -- as \011
|
||||||
|
// newline (aka \n) -- as \012
|
||||||
|
// backslash (aka \\) -- as \134
|
||||||
|
//
|
||||||
|
// This function converts path from mountinfo back, i.e. it unescapes the above sequences.
|
||||||
|
func unescape(path string) (string, error) {
|
||||||
|
// try to avoid copying
|
||||||
|
if strings.IndexByte(path, '\\') == -1 {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following code is UTF-8 transparent as it only looks for some
|
||||||
|
// specific characters (backslash and 0..7) with values < utf8.RuneSelf,
|
||||||
|
// and everything else is passed through as is.
|
||||||
|
buf := make([]byte, len(path))
|
||||||
|
bufLen := 0
|
||||||
|
for i := 0; i < len(path); i++ {
|
||||||
|
if path[i] != '\\' {
|
||||||
|
buf[bufLen] = path[i]
|
||||||
|
bufLen++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s := path[i:]
|
||||||
|
if len(s) < 4 {
|
||||||
|
// too short
|
||||||
|
return "", fmt.Errorf("bad escape sequence %q: too short", s)
|
||||||
|
}
|
||||||
|
c := s[1]
|
||||||
|
switch c {
|
||||||
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
|
v := c - '0'
|
||||||
|
for j := 2; j < 4; j++ { // one digit already; two more
|
||||||
|
if s[j] < '0' || s[j] > '7' {
|
||||||
|
return "", fmt.Errorf("bad escape sequence %q: not a digit", s[:3])
|
||||||
|
}
|
||||||
|
x := s[j] - '0'
|
||||||
|
v = (v << 3) | x
|
||||||
|
}
|
||||||
|
if v > 255 {
|
||||||
|
return "", fmt.Errorf("bad escape sequence %q: out of range" + s[:3])
|
||||||
|
}
|
||||||
|
buf[bufLen] = v
|
||||||
|
bufLen++
|
||||||
|
i += 3
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("bad escape sequence %q: not a digit" + s[:3])
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(buf[:bufLen]), nil
|
||||||
|
}
|
||||||
11
vendor/github.com/moby/sys/mountinfo/mountinfo_openbsd.go
generated
vendored
Normal file
11
vendor/github.com/moby/sys/mountinfo/mountinfo_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
func getMountinfo(entry *unix.Statfs_t) *Info {
|
||||||
|
return &Info{
|
||||||
|
Mountpoint: unix.ByteSliceToString(entry.F_mntonname[:]),
|
||||||
|
FSType: unix.ByteSliceToString(entry.F_fstypename[:]),
|
||||||
|
Source: unix.ByteSliceToString(entry.F_mntfromname[:]),
|
||||||
|
}
|
||||||
|
}
|
||||||
19
vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
generated
vendored
Normal file
19
vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//go:build !windows && !linux && !freebsd && !openbsd && !darwin
|
||||||
|
// +build !windows,!linux,!freebsd,!openbsd,!darwin
|
||||||
|
|
||||||
|
package mountinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errNotImplemented = fmt.Errorf("not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||||
|
|
||||||
|
func parseMountTable(_ FilterFunc) ([]*Info, error) {
|
||||||
|
return nil, errNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func mounted(path string) (bool, error) {
|
||||||
|
return false, errNotImplemented
|
||||||
|
}
|
||||||
10
vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go
generated
vendored
Normal file
10
vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package mountinfo
|
||||||
|
|
||||||
|
func parseMountTable(_ FilterFunc) ([]*Info, error) {
|
||||||
|
// Do NOT return an error!
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mounted(_ string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
76
vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
76
vendor/github.com/stretchr/testify/assert/assertion_compare.go
generated
vendored
@ -1,8 +1,10 @@
|
|||||||
package assert
|
package assert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CompareType int
|
type CompareType int
|
||||||
@ -30,6 +32,9 @@ var (
|
|||||||
float64Type = reflect.TypeOf(float64(1))
|
float64Type = reflect.TypeOf(float64(1))
|
||||||
|
|
||||||
stringType = reflect.TypeOf("")
|
stringType = reflect.TypeOf("")
|
||||||
|
|
||||||
|
timeType = reflect.TypeOf(time.Time{})
|
||||||
|
bytesType = reflect.TypeOf([]byte{})
|
||||||
)
|
)
|
||||||
|
|
||||||
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
||||||
@ -299,6 +304,47 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
|||||||
return compareLess, true
|
return compareLess, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Check for known struct types we can check for compare results.
|
||||||
|
case reflect.Struct:
|
||||||
|
{
|
||||||
|
// All structs enter here. We're not interested in most types.
|
||||||
|
if !canConvert(obj1Value, timeType) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// time.Time can compared!
|
||||||
|
timeObj1, ok := obj1.(time.Time)
|
||||||
|
if !ok {
|
||||||
|
timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeObj2, ok := obj2.(time.Time)
|
||||||
|
if !ok {
|
||||||
|
timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64)
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
{
|
||||||
|
// We only care about the []byte type.
|
||||||
|
if !canConvert(obj1Value, bytesType) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// []byte can be compared!
|
||||||
|
bytesObj1, ok := obj1.([]byte)
|
||||||
|
if !ok {
|
||||||
|
bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte)
|
||||||
|
|
||||||
|
}
|
||||||
|
bytesObj2, ok := obj2.([]byte)
|
||||||
|
if !ok {
|
||||||
|
bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return compareEqual, false
|
return compareEqual, false
|
||||||
@ -310,7 +356,10 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
|
|||||||
// assert.Greater(t, float64(2), float64(1))
|
// assert.Greater(t, float64(2), float64(1))
|
||||||
// assert.Greater(t, "b", "a")
|
// assert.Greater(t, "b", "a")
|
||||||
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs)
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
||||||
@ -320,7 +369,10 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface
|
|||||||
// assert.GreaterOrEqual(t, "b", "a")
|
// assert.GreaterOrEqual(t, "b", "a")
|
||||||
// assert.GreaterOrEqual(t, "b", "b")
|
// assert.GreaterOrEqual(t, "b", "b")
|
||||||
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs)
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Less asserts that the first element is less than the second
|
// Less asserts that the first element is less than the second
|
||||||
@ -329,7 +381,10 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in
|
|||||||
// assert.Less(t, float64(1), float64(2))
|
// assert.Less(t, float64(1), float64(2))
|
||||||
// assert.Less(t, "a", "b")
|
// assert.Less(t, "a", "b")
|
||||||
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs)
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LessOrEqual asserts that the first element is less than or equal to the second
|
// LessOrEqual asserts that the first element is less than or equal to the second
|
||||||
@ -339,7 +394,10 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{})
|
|||||||
// assert.LessOrEqual(t, "a", "b")
|
// assert.LessOrEqual(t, "a", "b")
|
||||||
// assert.LessOrEqual(t, "b", "b")
|
// assert.LessOrEqual(t, "b", "b")
|
||||||
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Positive asserts that the specified element is positive
|
// Positive asserts that the specified element is positive
|
||||||
@ -347,8 +405,11 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter
|
|||||||
// assert.Positive(t, 1)
|
// assert.Positive(t, 1)
|
||||||
// assert.Positive(t, 1.23)
|
// assert.Positive(t, 1.23)
|
||||||
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
zero := reflect.Zero(reflect.TypeOf(e))
|
zero := reflect.Zero(reflect.TypeOf(e))
|
||||||
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs)
|
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative asserts that the specified element is negative
|
// Negative asserts that the specified element is negative
|
||||||
@ -356,8 +417,11 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
|||||||
// assert.Negative(t, -1)
|
// assert.Negative(t, -1)
|
||||||
// assert.Negative(t, -1.23)
|
// assert.Negative(t, -1.23)
|
||||||
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
zero := reflect.Zero(reflect.TypeOf(e))
|
zero := reflect.Zero(reflect.TypeOf(e))
|
||||||
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs)
|
return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
|
func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool {
|
||||||
|
|||||||
16
vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
generated
vendored
Normal file
16
vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//go:build go1.17
|
||||||
|
// +build go1.17
|
||||||
|
|
||||||
|
// TODO: once support for Go 1.16 is dropped, this file can be
|
||||||
|
// merged/removed with assertion_compare_go1.17_test.go and
|
||||||
|
// assertion_compare_legacy.go
|
||||||
|
|
||||||
|
package assert
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
// Wrapper around reflect.Value.CanConvert, for compatibility
|
||||||
|
// reasons.
|
||||||
|
func canConvert(value reflect.Value, to reflect.Type) bool {
|
||||||
|
return value.CanConvert(to)
|
||||||
|
}
|
||||||
16
vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
generated
vendored
Normal file
16
vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//go:build !go1.17
|
||||||
|
// +build !go1.17
|
||||||
|
|
||||||
|
// TODO: once support for Go 1.16 is dropped, this file can be
|
||||||
|
// merged/removed with assertion_compare_go1.17_test.go and
|
||||||
|
// assertion_compare_can_convert.go
|
||||||
|
|
||||||
|
package assert
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
// Older versions of Go does not have the reflect.Value.CanConvert
|
||||||
|
// method.
|
||||||
|
func canConvert(value reflect.Value, to reflect.Type) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
22
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
22
vendor/github.com/stretchr/testify/assert/assertion_format.go
generated
vendored
@ -123,6 +123,18 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int
|
|||||||
return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
|
return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
|
||||||
|
// and that the error contains the specified substring.
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted")
|
||||||
|
func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
// ErrorIsf asserts that at least one of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool {
|
||||||
@ -724,6 +736,16 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
|
|||||||
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithinRangef asserts that a time is within a time range (inclusive).
|
||||||
|
//
|
||||||
|
// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
|
||||||
|
func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// YAMLEqf asserts that two YAML strings are equivalent.
|
// YAMLEqf asserts that two YAML strings are equivalent.
|
||||||
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
||||||
if h, ok := t.(tHelper); ok {
|
if h, ok := t.(tHelper); ok {
|
||||||
|
|||||||
44
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
44
vendor/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
@ -222,6 +222,30 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ..
|
|||||||
return ErrorAsf(a.t, err, target, msg, args...)
|
return ErrorAsf(a.t, err, target, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorContains asserts that a function returned an error (i.e. not `nil`)
|
||||||
|
// and that the error contains the specified substring.
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// a.ErrorContains(err, expectedErrorSubString)
|
||||||
|
func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return ErrorContains(a.t, theError, contains, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorContainsf asserts that a function returned an error (i.e. not `nil`)
|
||||||
|
// and that the error contains the specified substring.
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted")
|
||||||
|
func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return ErrorContainsf(a.t, theError, contains, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
// ErrorIs asserts that at least one of the errors in err's chain matches target.
|
||||||
// This is a wrapper for errors.Is.
|
// This is a wrapper for errors.Is.
|
||||||
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool {
|
||||||
@ -1437,6 +1461,26 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
|
|||||||
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
return WithinDurationf(a.t, expected, actual, delta, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithinRange asserts that a time is within a time range (inclusive).
|
||||||
|
//
|
||||||
|
// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
|
||||||
|
func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return WithinRange(a.t, actual, start, end, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithinRangef asserts that a time is within a time range (inclusive).
|
||||||
|
//
|
||||||
|
// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted")
|
||||||
|
func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return WithinRangef(a.t, actual, start, end, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// YAMLEq asserts that two YAML strings are equivalent.
|
// YAMLEq asserts that two YAML strings are equivalent.
|
||||||
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||||
if h, ok := a.t.(tHelper); ok {
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
|||||||
8
vendor/github.com/stretchr/testify/assert/assertion_order.go
generated
vendored
8
vendor/github.com/stretchr/testify/assert/assertion_order.go
generated
vendored
@ -50,7 +50,7 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareT
|
|||||||
// assert.IsIncreasing(t, []float{1, 2})
|
// assert.IsIncreasing(t, []float{1, 2})
|
||||||
// assert.IsIncreasing(t, []string{"a", "b"})
|
// assert.IsIncreasing(t, []string{"a", "b"})
|
||||||
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs)
|
return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNonIncreasing asserts that the collection is not increasing
|
// IsNonIncreasing asserts that the collection is not increasing
|
||||||
@ -59,7 +59,7 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
|
|||||||
// assert.IsNonIncreasing(t, []float{2, 1})
|
// assert.IsNonIncreasing(t, []float{2, 1})
|
||||||
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
// assert.IsNonIncreasing(t, []string{"b", "a"})
|
||||||
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs)
|
return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDecreasing asserts that the collection is decreasing
|
// IsDecreasing asserts that the collection is decreasing
|
||||||
@ -68,7 +68,7 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{})
|
|||||||
// assert.IsDecreasing(t, []float{2, 1})
|
// assert.IsDecreasing(t, []float{2, 1})
|
||||||
// assert.IsDecreasing(t, []string{"b", "a"})
|
// assert.IsDecreasing(t, []string{"b", "a"})
|
||||||
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs)
|
return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNonDecreasing asserts that the collection is not decreasing
|
// IsNonDecreasing asserts that the collection is not decreasing
|
||||||
@ -77,5 +77,5 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) boo
|
|||||||
// assert.IsNonDecreasing(t, []float{1, 2})
|
// assert.IsNonDecreasing(t, []float{1, 2})
|
||||||
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
// assert.IsNonDecreasing(t, []string{"a", "b"})
|
||||||
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs)
|
return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|||||||
176
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
176
vendor/github.com/stretchr/testify/assert/assertions.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -144,7 +145,8 @@ func CallerInfo() []string {
|
|||||||
if len(parts) > 1 {
|
if len(parts) > 1 {
|
||||||
dir := parts[len(parts)-2]
|
dir := parts[len(parts)-2]
|
||||||
if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
|
if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
|
||||||
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
path, _ := filepath.Abs(file)
|
||||||
|
callers = append(callers, fmt.Sprintf("%s:%d", path, line))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +565,7 @@ func isEmpty(object interface{}) bool {
|
|||||||
|
|
||||||
switch objValue.Kind() {
|
switch objValue.Kind() {
|
||||||
// collection types are empty when they have no element
|
// collection types are empty when they have no element
|
||||||
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
|
case reflect.Chan, reflect.Map, reflect.Slice:
|
||||||
return objValue.Len() == 0
|
return objValue.Len() == 0
|
||||||
// pointers are empty if nil or if the value they point to is empty
|
// pointers are empty if nil or if the value they point to is empty
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
@ -573,6 +575,7 @@ func isEmpty(object interface{}) bool {
|
|||||||
deref := objValue.Elem().Interface()
|
deref := objValue.Elem().Interface()
|
||||||
return isEmpty(deref)
|
return isEmpty(deref)
|
||||||
// for all other types, compare against the zero value
|
// for all other types, compare against the zero value
|
||||||
|
// array types are empty when they match their zero-initialized state
|
||||||
default:
|
default:
|
||||||
zero := reflect.Zero(objValue.Type())
|
zero := reflect.Zero(objValue.Type())
|
||||||
return reflect.DeepEqual(object, zero.Interface())
|
return reflect.DeepEqual(object, zero.Interface())
|
||||||
@ -718,10 +721,14 @@ func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...inte
|
|||||||
// return (false, false) if impossible.
|
// return (false, false) if impossible.
|
||||||
// return (true, false) if element was not found.
|
// return (true, false) if element was not found.
|
||||||
// return (true, true) if element was found.
|
// return (true, true) if element was found.
|
||||||
func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
func containsElement(list interface{}, element interface{}) (ok, found bool) {
|
||||||
|
|
||||||
listValue := reflect.ValueOf(list)
|
listValue := reflect.ValueOf(list)
|
||||||
listKind := reflect.TypeOf(list).Kind()
|
listType := reflect.TypeOf(list)
|
||||||
|
if listType == nil {
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
listKind := listType.Kind()
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
ok = false
|
ok = false
|
||||||
@ -764,7 +771,7 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
|
|||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, found := includeElement(s, contains)
|
ok, found := containsElement(s, contains)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...)
|
||||||
}
|
}
|
||||||
@ -787,7 +794,7 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{})
|
|||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, found := includeElement(s, contains)
|
ok, found := containsElement(s, contains)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
|
||||||
}
|
}
|
||||||
@ -811,7 +818,6 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
|||||||
return true // we consider nil to be equal to the nil set
|
return true // we consider nil to be equal to the nil set
|
||||||
}
|
}
|
||||||
|
|
||||||
subsetValue := reflect.ValueOf(subset)
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
ok = false
|
ok = false
|
||||||
@ -821,17 +827,35 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
|
|||||||
listKind := reflect.TypeOf(list).Kind()
|
listKind := reflect.TypeOf(list).Kind()
|
||||||
subsetKind := reflect.TypeOf(subset).Kind()
|
subsetKind := reflect.TypeOf(subset).Kind()
|
||||||
|
|
||||||
if listKind != reflect.Array && listKind != reflect.Slice {
|
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
|
||||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if subsetKind != reflect.Array && subsetKind != reflect.Slice {
|
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
|
||||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subsetValue := reflect.ValueOf(subset)
|
||||||
|
if subsetKind == reflect.Map && listKind == reflect.Map {
|
||||||
|
listValue := reflect.ValueOf(list)
|
||||||
|
subsetKeys := subsetValue.MapKeys()
|
||||||
|
|
||||||
|
for i := 0; i < len(subsetKeys); i++ {
|
||||||
|
subsetKey := subsetKeys[i]
|
||||||
|
subsetElement := subsetValue.MapIndex(subsetKey).Interface()
|
||||||
|
listElement := listValue.MapIndex(subsetKey).Interface()
|
||||||
|
|
||||||
|
if !ObjectsAreEqual(subsetElement, listElement) {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, subsetElement), msgAndArgs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < subsetValue.Len(); i++ {
|
for i := 0; i < subsetValue.Len(); i++ {
|
||||||
element := subsetValue.Index(i).Interface()
|
element := subsetValue.Index(i).Interface()
|
||||||
ok, found := includeElement(list, element)
|
ok, found := containsElement(list, element)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
||||||
}
|
}
|
||||||
@ -852,10 +876,9 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
|
|||||||
h.Helper()
|
h.Helper()
|
||||||
}
|
}
|
||||||
if subset == nil {
|
if subset == nil {
|
||||||
return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...)
|
return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
subsetValue := reflect.ValueOf(subset)
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
ok = false
|
ok = false
|
||||||
@ -865,17 +888,35 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
|
|||||||
listKind := reflect.TypeOf(list).Kind()
|
listKind := reflect.TypeOf(list).Kind()
|
||||||
subsetKind := reflect.TypeOf(subset).Kind()
|
subsetKind := reflect.TypeOf(subset).Kind()
|
||||||
|
|
||||||
if listKind != reflect.Array && listKind != reflect.Slice {
|
if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map {
|
||||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if subsetKind != reflect.Array && subsetKind != reflect.Slice {
|
if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map {
|
||||||
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subsetValue := reflect.ValueOf(subset)
|
||||||
|
if subsetKind == reflect.Map && listKind == reflect.Map {
|
||||||
|
listValue := reflect.ValueOf(list)
|
||||||
|
subsetKeys := subsetValue.MapKeys()
|
||||||
|
|
||||||
|
for i := 0; i < len(subsetKeys); i++ {
|
||||||
|
subsetKey := subsetKeys[i]
|
||||||
|
subsetElement := subsetValue.MapIndex(subsetKey).Interface()
|
||||||
|
listElement := listValue.MapIndex(subsetKey).Interface()
|
||||||
|
|
||||||
|
if !ObjectsAreEqual(subsetElement, listElement) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < subsetValue.Len(); i++ {
|
for i := 0; i < subsetValue.Len(); i++ {
|
||||||
element := subsetValue.Index(i).Interface()
|
element := subsetValue.Index(i).Interface()
|
||||||
ok, found := includeElement(list, element)
|
ok, found := containsElement(list, element)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...)
|
||||||
}
|
}
|
||||||
@ -1000,27 +1041,21 @@ func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
|
|||||||
type PanicTestFunc func()
|
type PanicTestFunc func()
|
||||||
|
|
||||||
// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
|
// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
|
||||||
func didPanic(f PanicTestFunc) (bool, interface{}, string) {
|
func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) {
|
||||||
|
didPanic = true
|
||||||
didPanic := false
|
|
||||||
var message interface{}
|
|
||||||
var stack string
|
|
||||||
func() {
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if message = recover(); message != nil {
|
message = recover()
|
||||||
didPanic = true
|
if didPanic {
|
||||||
stack = string(debug.Stack())
|
stack = string(debug.Stack())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// call the target function
|
// call the target function
|
||||||
f()
|
f()
|
||||||
|
didPanic = false
|
||||||
|
|
||||||
}()
|
return
|
||||||
|
|
||||||
return didPanic, message, stack
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||||
@ -1111,6 +1146,27 @@ func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration,
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithinRange asserts that a time is within a time range (inclusive).
|
||||||
|
//
|
||||||
|
// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second))
|
||||||
|
func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
if end.Before(start) {
|
||||||
|
return Fail(t, "Start should be before end", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual.Before(start) {
|
||||||
|
return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...)
|
||||||
|
} else if actual.After(end) {
|
||||||
|
return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func toFloat(x interface{}) (float64, bool) {
|
func toFloat(x interface{}) (float64, bool) {
|
||||||
var xf float64
|
var xf float64
|
||||||
xok := true
|
xok := true
|
||||||
@ -1161,11 +1217,15 @@ func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs
|
|||||||
bf, bok := toFloat(actual)
|
bf, bok := toFloat(actual)
|
||||||
|
|
||||||
if !aok || !bok {
|
if !aok || !bok {
|
||||||
return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
|
return Fail(t, "Parameters must be numerical", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if math.IsNaN(af) && math.IsNaN(bf) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if math.IsNaN(af) {
|
if math.IsNaN(af) {
|
||||||
return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...)
|
return Fail(t, "Expected must not be NaN", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if math.IsNaN(bf) {
|
if math.IsNaN(bf) {
|
||||||
@ -1188,7 +1248,7 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn
|
|||||||
if expected == nil || actual == nil ||
|
if expected == nil || actual == nil ||
|
||||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||||
return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
|
return Fail(t, "Parameters must be slice", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
actualSlice := reflect.ValueOf(actual)
|
actualSlice := reflect.ValueOf(actual)
|
||||||
@ -1250,8 +1310,12 @@ func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, m
|
|||||||
|
|
||||||
func calcRelativeError(expected, actual interface{}) (float64, error) {
|
func calcRelativeError(expected, actual interface{}) (float64, error) {
|
||||||
af, aok := toFloat(expected)
|
af, aok := toFloat(expected)
|
||||||
if !aok {
|
bf, bok := toFloat(actual)
|
||||||
return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
|
if !aok || !bok {
|
||||||
|
return 0, fmt.Errorf("Parameters must be numerical")
|
||||||
|
}
|
||||||
|
if math.IsNaN(af) && math.IsNaN(bf) {
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
if math.IsNaN(af) {
|
if math.IsNaN(af) {
|
||||||
return 0, errors.New("expected value must not be NaN")
|
return 0, errors.New("expected value must not be NaN")
|
||||||
@ -1259,10 +1323,6 @@ func calcRelativeError(expected, actual interface{}) (float64, error) {
|
|||||||
if af == 0 {
|
if af == 0 {
|
||||||
return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
|
return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
|
||||||
}
|
}
|
||||||
bf, bok := toFloat(actual)
|
|
||||||
if !bok {
|
|
||||||
return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
|
|
||||||
}
|
|
||||||
if math.IsNaN(bf) {
|
if math.IsNaN(bf) {
|
||||||
return 0, errors.New("actual value must not be NaN")
|
return 0, errors.New("actual value must not be NaN")
|
||||||
}
|
}
|
||||||
@ -1298,7 +1358,7 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
|
|||||||
if expected == nil || actual == nil ||
|
if expected == nil || actual == nil ||
|
||||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||||
return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
|
return Fail(t, "Parameters must be slice", msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
actualSlice := reflect.ValueOf(actual)
|
actualSlice := reflect.ValueOf(actual)
|
||||||
@ -1375,6 +1435,27 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrorContains asserts that a function returned an error (i.e. not `nil`)
|
||||||
|
// and that the error contains the specified substring.
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// assert.ErrorContains(t, err, expectedErrorSubString)
|
||||||
|
func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
if !Error(t, theError, msgAndArgs...) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := theError.Error()
|
||||||
|
if !strings.Contains(actual, contains) {
|
||||||
|
return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// matchRegexp return true if a specified regexp matches a string.
|
// matchRegexp return true if a specified regexp matches a string.
|
||||||
func matchRegexp(rx interface{}, str interface{}) bool {
|
func matchRegexp(rx interface{}, str interface{}) bool {
|
||||||
|
|
||||||
@ -1588,12 +1669,17 @@ func diff(expected interface{}, actual interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var e, a string
|
var e, a string
|
||||||
if et != reflect.TypeOf("") {
|
|
||||||
e = spewConfig.Sdump(expected)
|
switch et {
|
||||||
a = spewConfig.Sdump(actual)
|
case reflect.TypeOf(""):
|
||||||
} else {
|
|
||||||
e = reflect.ValueOf(expected).String()
|
e = reflect.ValueOf(expected).String()
|
||||||
a = reflect.ValueOf(actual).String()
|
a = reflect.ValueOf(actual).String()
|
||||||
|
case reflect.TypeOf(time.Time{}):
|
||||||
|
e = spewConfigStringerEnabled.Sdump(expected)
|
||||||
|
a = spewConfigStringerEnabled.Sdump(actual)
|
||||||
|
default:
|
||||||
|
e = spewConfig.Sdump(expected)
|
||||||
|
a = spewConfig.Sdump(actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
||||||
@ -1625,6 +1711,14 @@ var spewConfig = spew.ConfigState{
|
|||||||
MaxDepth: 10,
|
MaxDepth: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var spewConfigStringerEnabled = spew.ConfigState{
|
||||||
|
Indent: " ",
|
||||||
|
DisablePointerAddresses: true,
|
||||||
|
DisableCapacities: true,
|
||||||
|
SortKeys: true,
|
||||||
|
MaxDepth: 10,
|
||||||
|
}
|
||||||
|
|
||||||
type tHelper interface {
|
type tHelper interface {
|
||||||
Helper()
|
Helper()
|
||||||
}
|
}
|
||||||
|
|||||||
78
vendor/gopkg.in/yaml.v3/decode.go
generated
vendored
78
vendor/gopkg.in/yaml.v3/decode.go
generated
vendored
@ -100,7 +100,10 @@ func (p *parser) peek() yaml_event_type_t {
|
|||||||
if p.event.typ != yaml_NO_EVENT {
|
if p.event.typ != yaml_NO_EVENT {
|
||||||
return p.event.typ
|
return p.event.typ
|
||||||
}
|
}
|
||||||
if !yaml_parser_parse(&p.parser, &p.event) {
|
// It's curious choice from the underlying API to generally return a
|
||||||
|
// positive result on success, but on this case return true in an error
|
||||||
|
// scenario. This was the source of bugs in the past (issue #666).
|
||||||
|
if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR {
|
||||||
p.fail()
|
p.fail()
|
||||||
}
|
}
|
||||||
return p.event.typ
|
return p.event.typ
|
||||||
@ -320,6 +323,8 @@ type decoder struct {
|
|||||||
decodeCount int
|
decodeCount int
|
||||||
aliasCount int
|
aliasCount int
|
||||||
aliasDepth int
|
aliasDepth int
|
||||||
|
|
||||||
|
mergedFields map[interface{}]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -808,6 +813,11 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mergedFields := d.mergedFields
|
||||||
|
d.mergedFields = nil
|
||||||
|
|
||||||
|
var mergeNode *Node
|
||||||
|
|
||||||
mapIsNew := false
|
mapIsNew := false
|
||||||
if out.IsNil() {
|
if out.IsNil() {
|
||||||
out.Set(reflect.MakeMap(outt))
|
out.Set(reflect.MakeMap(outt))
|
||||||
@ -815,11 +825,18 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
|
|||||||
}
|
}
|
||||||
for i := 0; i < l; i += 2 {
|
for i := 0; i < l; i += 2 {
|
||||||
if isMerge(n.Content[i]) {
|
if isMerge(n.Content[i]) {
|
||||||
d.merge(n.Content[i+1], out)
|
mergeNode = n.Content[i+1]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
k := reflect.New(kt).Elem()
|
k := reflect.New(kt).Elem()
|
||||||
if d.unmarshal(n.Content[i], k) {
|
if d.unmarshal(n.Content[i], k) {
|
||||||
|
if mergedFields != nil {
|
||||||
|
ki := k.Interface()
|
||||||
|
if mergedFields[ki] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mergedFields[ki] = true
|
||||||
|
}
|
||||||
kkind := k.Kind()
|
kkind := k.Kind()
|
||||||
if kkind == reflect.Interface {
|
if kkind == reflect.Interface {
|
||||||
kkind = k.Elem().Kind()
|
kkind = k.Elem().Kind()
|
||||||
@ -833,6 +850,12 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.mergedFields = mergedFields
|
||||||
|
if mergeNode != nil {
|
||||||
|
d.merge(n, mergeNode, out)
|
||||||
|
}
|
||||||
|
|
||||||
d.stringMapType = stringMapType
|
d.stringMapType = stringMapType
|
||||||
d.generalMapType = generalMapType
|
d.generalMapType = generalMapType
|
||||||
return true
|
return true
|
||||||
@ -844,7 +867,8 @@ func isStringMap(n *Node) bool {
|
|||||||
}
|
}
|
||||||
l := len(n.Content)
|
l := len(n.Content)
|
||||||
for i := 0; i < l; i += 2 {
|
for i := 0; i < l; i += 2 {
|
||||||
if n.Content[i].ShortTag() != strTag {
|
shortTag := n.Content[i].ShortTag()
|
||||||
|
if shortTag != strTag && shortTag != mergeTag {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -861,7 +885,6 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
|
|||||||
var elemType reflect.Type
|
var elemType reflect.Type
|
||||||
if sinfo.InlineMap != -1 {
|
if sinfo.InlineMap != -1 {
|
||||||
inlineMap = out.Field(sinfo.InlineMap)
|
inlineMap = out.Field(sinfo.InlineMap)
|
||||||
inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
|
|
||||||
elemType = inlineMap.Type().Elem()
|
elemType = inlineMap.Type().Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,6 +893,9 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
|
|||||||
d.prepare(n, field)
|
d.prepare(n, field)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mergedFields := d.mergedFields
|
||||||
|
d.mergedFields = nil
|
||||||
|
var mergeNode *Node
|
||||||
var doneFields []bool
|
var doneFields []bool
|
||||||
if d.uniqueKeys {
|
if d.uniqueKeys {
|
||||||
doneFields = make([]bool, len(sinfo.FieldsList))
|
doneFields = make([]bool, len(sinfo.FieldsList))
|
||||||
@ -879,13 +905,20 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
|
|||||||
for i := 0; i < l; i += 2 {
|
for i := 0; i < l; i += 2 {
|
||||||
ni := n.Content[i]
|
ni := n.Content[i]
|
||||||
if isMerge(ni) {
|
if isMerge(ni) {
|
||||||
d.merge(n.Content[i+1], out)
|
mergeNode = n.Content[i+1]
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !d.unmarshal(ni, name) {
|
if !d.unmarshal(ni, name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if info, ok := sinfo.FieldsMap[name.String()]; ok {
|
sname := name.String()
|
||||||
|
if mergedFields != nil {
|
||||||
|
if mergedFields[sname] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mergedFields[sname] = true
|
||||||
|
}
|
||||||
|
if info, ok := sinfo.FieldsMap[sname]; ok {
|
||||||
if d.uniqueKeys {
|
if d.uniqueKeys {
|
||||||
if doneFields[info.Id] {
|
if doneFields[info.Id] {
|
||||||
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
|
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
|
||||||
@ -911,6 +944,11 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
|
|||||||
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
|
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.mergedFields = mergedFields
|
||||||
|
if mergeNode != nil {
|
||||||
|
d.merge(n, mergeNode, out)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,19 +956,29 @@ func failWantMap() {
|
|||||||
failf("map merge requires map or sequence of maps as the value")
|
failf("map merge requires map or sequence of maps as the value")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) merge(n *Node, out reflect.Value) {
|
func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) {
|
||||||
switch n.Kind {
|
mergedFields := d.mergedFields
|
||||||
|
if mergedFields == nil {
|
||||||
|
d.mergedFields = make(map[interface{}]bool)
|
||||||
|
for i := 0; i < len(parent.Content); i += 2 {
|
||||||
|
k := reflect.New(ifaceType).Elem()
|
||||||
|
if d.unmarshal(parent.Content[i], k) {
|
||||||
|
d.mergedFields[k.Interface()] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch merge.Kind {
|
||||||
case MappingNode:
|
case MappingNode:
|
||||||
d.unmarshal(n, out)
|
d.unmarshal(merge, out)
|
||||||
case AliasNode:
|
case AliasNode:
|
||||||
if n.Alias != nil && n.Alias.Kind != MappingNode {
|
if merge.Alias != nil && merge.Alias.Kind != MappingNode {
|
||||||
failWantMap()
|
failWantMap()
|
||||||
}
|
}
|
||||||
d.unmarshal(n, out)
|
d.unmarshal(merge, out)
|
||||||
case SequenceNode:
|
case SequenceNode:
|
||||||
// Step backwards as earlier nodes take precedence.
|
for i := 0; i < len(merge.Content); i++ {
|
||||||
for i := len(n.Content) - 1; i >= 0; i-- {
|
ni := merge.Content[i]
|
||||||
ni := n.Content[i]
|
|
||||||
if ni.Kind == AliasNode {
|
if ni.Kind == AliasNode {
|
||||||
if ni.Alias != nil && ni.Alias.Kind != MappingNode {
|
if ni.Alias != nil && ni.Alias.Kind != MappingNode {
|
||||||
failWantMap()
|
failWantMap()
|
||||||
@ -943,6 +991,8 @@ func (d *decoder) merge(n *Node, out reflect.Value) {
|
|||||||
default:
|
default:
|
||||||
failWantMap()
|
failWantMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.mergedFields = mergedFields
|
||||||
}
|
}
|
||||||
|
|
||||||
func isMerge(n *Node) bool {
|
func isMerge(n *Node) bool {
|
||||||
|
|||||||
11
vendor/gopkg.in/yaml.v3/parserc.go
generated
vendored
11
vendor/gopkg.in/yaml.v3/parserc.go
generated
vendored
@ -687,6 +687,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
|
|||||||
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||||
if first {
|
if first {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
|
if token == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
parser.marks = append(parser.marks, token.start_mark)
|
parser.marks = append(parser.marks, token.start_mark)
|
||||||
skip_token(parser)
|
skip_token(parser)
|
||||||
}
|
}
|
||||||
@ -786,7 +789,7 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
|
if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,6 +816,9 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
|
|||||||
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||||
if first {
|
if first {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
|
if token == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
parser.marks = append(parser.marks, token.start_mark)
|
parser.marks = append(parser.marks, token.start_mark)
|
||||||
skip_token(parser)
|
skip_token(parser)
|
||||||
}
|
}
|
||||||
@ -922,6 +928,9 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
|
|||||||
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||||
if first {
|
if first {
|
||||||
token := peek_token(parser)
|
token := peek_token(parser)
|
||||||
|
if token == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
parser.marks = append(parser.marks, token.start_mark)
|
parser.marks = append(parser.marks, token.start_mark)
|
||||||
skip_token(parser)
|
skip_token(parser)
|
||||||
}
|
}
|
||||||
|
|||||||
19
vendor/k8s.io/klog/v2/OWNERS
generated
vendored
19
vendor/k8s.io/klog/v2/OWNERS
generated
vendored
@ -1,19 +1,14 @@
|
|||||||
# See the OWNERS docs at https://go.k8s.io/owners
|
# See the OWNERS docs at https://go.k8s.io/owners
|
||||||
reviewers:
|
reviewers:
|
||||||
- jayunit100
|
- harshanarayana
|
||||||
- hoegaarden
|
|
||||||
- andyxning
|
|
||||||
- neolit123
|
|
||||||
- pohly
|
- pohly
|
||||||
- yagonobre
|
|
||||||
- vincepri
|
|
||||||
- detiber
|
|
||||||
approvers:
|
approvers:
|
||||||
- dims
|
- dims
|
||||||
- thockin
|
- thockin
|
||||||
- justinsb
|
|
||||||
- tallclair
|
|
||||||
- piosz
|
|
||||||
- brancz
|
|
||||||
- lavalamp
|
|
||||||
- serathius
|
- serathius
|
||||||
|
emeritus_approvers:
|
||||||
|
- brancz
|
||||||
|
- justinsb
|
||||||
|
- lavalamp
|
||||||
|
- piosz
|
||||||
|
- tallclair
|
||||||
|
|||||||
17
vendor/k8s.io/klog/v2/README.md
generated
vendored
17
vendor/k8s.io/klog/v2/README.md
generated
vendored
@ -23,6 +23,20 @@ Historical context is available here:
|
|||||||
* https://groups.google.com/forum/#!msg/kubernetes-sig-architecture/wCWiWf3Juzs/hXRVBH90CgAJ
|
* https://groups.google.com/forum/#!msg/kubernetes-sig-architecture/wCWiWf3Juzs/hXRVBH90CgAJ
|
||||||
* https://groups.google.com/forum/#!msg/kubernetes-dev/7vnijOMhLS0/1oRiNtigBgAJ
|
* https://groups.google.com/forum/#!msg/kubernetes-dev/7vnijOMhLS0/1oRiNtigBgAJ
|
||||||
|
|
||||||
|
## Release versioning
|
||||||
|
|
||||||
|
Semantic versioning is used in this repository. It contains several Go modules
|
||||||
|
with different levels of stability:
|
||||||
|
- `k8s.io/klog/v2` - stable API, `vX.Y.Z` tags
|
||||||
|
- `examples` - no stable API, no tags, no intention to ever stabilize
|
||||||
|
|
||||||
|
Exempt from the API stability guarantee are items (packages, functions, etc.)
|
||||||
|
which are marked explicitly as `EXPERIMENTAL` in their docs comment. Those
|
||||||
|
may still change in incompatible ways or get removed entirely. This can only
|
||||||
|
be used for code that is used in tests to avoid situations where non-test
|
||||||
|
code from two different Kubernetes dependencies depends on incompatible
|
||||||
|
releases of klog because an experimental API was changed.
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
How to use klog
|
How to use klog
|
||||||
@ -32,6 +46,7 @@ How to use klog
|
|||||||
- You can now use `log_file` instead of `log_dir` for logging to a single file (See `examples/log_file/usage_log_file.go`)
|
- You can now use `log_file` instead of `log_dir` for logging to a single file (See `examples/log_file/usage_log_file.go`)
|
||||||
- If you want to redirect everything logged using klog somewhere else (say syslog!), you can use `klog.SetOutput()` method and supply a `io.Writer`. (See `examples/set_output/usage_set_output.go`)
|
- If you want to redirect everything logged using klog somewhere else (say syslog!), you can use `klog.SetOutput()` method and supply a `io.Writer`. (See `examples/set_output/usage_set_output.go`)
|
||||||
- For more logging conventions (See [Logging Conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md))
|
- For more logging conventions (See [Logging Conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md))
|
||||||
|
- See our documentation on [pkg.go.dev/k8s.io](https://pkg.go.dev/k8s.io/klog).
|
||||||
|
|
||||||
**NOTE**: please use the newer go versions that support semantic import versioning in modules, ideally go 1.11.4 or greater.
|
**NOTE**: please use the newer go versions that support semantic import versioning in modules, ideally go 1.11.4 or greater.
|
||||||
|
|
||||||
@ -85,7 +100,7 @@ The comment from glog.go introduces the ideas:
|
|||||||
|
|
||||||
glog.Fatalf("Initialization failed: %s", err)
|
glog.Fatalf("Initialization failed: %s", err)
|
||||||
|
|
||||||
See the documentation for the V function for an explanation
|
See the documentation of the V function for an explanation
|
||||||
of these examples:
|
of these examples:
|
||||||
|
|
||||||
if glog.V(2) {
|
if glog.V(2) {
|
||||||
|
|||||||
186
vendor/k8s.io/klog/v2/contextual.go
generated
vendored
Normal file
186
vendor/k8s.io/klog/v2/contextual.go
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file provides the implementation of
|
||||||
|
// https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/1602-structured-logging
|
||||||
|
//
|
||||||
|
// SetLogger and ClearLogger were originally added to klog.go and got moved
|
||||||
|
// here. Contextual logging adds a way to retrieve a Logger for direct logging
|
||||||
|
// without the logging calls in klog.go.
|
||||||
|
//
|
||||||
|
// The global variables are expected to be modified only during sequential
|
||||||
|
// parts of a program (init, serial tests) and therefore are not protected by
|
||||||
|
// mutex locking.
|
||||||
|
|
||||||
|
var (
|
||||||
|
// klogLogger is used as fallback for logging through the normal klog code
|
||||||
|
// when no Logger is set.
|
||||||
|
klogLogger logr.Logger = logr.New(&klogger{})
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetLogger sets a Logger implementation that will be used as backing
|
||||||
|
// implementation of the traditional klog log calls. klog will do its own
|
||||||
|
// verbosity checks before calling logger.V().Info. logger.Error is always
|
||||||
|
// called, regardless of the klog verbosity settings.
|
||||||
|
//
|
||||||
|
// If set, all log lines will be suppressed from the regular output, and
|
||||||
|
// redirected to the logr implementation.
|
||||||
|
// Use as:
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
// klog.SetLogger(zapr.NewLogger(zapLog))
|
||||||
|
//
|
||||||
|
// To remove a backing logr implemention, use ClearLogger. Setting an
|
||||||
|
// empty logger with SetLogger(logr.Logger{}) does not work.
|
||||||
|
//
|
||||||
|
// Modifying the logger is not thread-safe and should be done while no other
|
||||||
|
// goroutines invoke log calls, usually during program initialization.
|
||||||
|
func SetLogger(logger logr.Logger) {
|
||||||
|
SetLoggerWithOptions(logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLoggerWithOptions is a more flexible version of SetLogger. Without
|
||||||
|
// additional options, it behaves exactly like SetLogger. By passing
|
||||||
|
// ContextualLogger(true) as option, it can be used to set a logger that then
|
||||||
|
// will also get called directly by applications which retrieve it via
|
||||||
|
// FromContext, Background, or TODO.
|
||||||
|
//
|
||||||
|
// Supporting direct calls is recommended because it avoids the overhead of
|
||||||
|
// routing log entries through klogr into klog and then into the actual Logger
|
||||||
|
// backend.
|
||||||
|
func SetLoggerWithOptions(logger logr.Logger, opts ...LoggerOption) {
|
||||||
|
logging.logger = &logger
|
||||||
|
logging.loggerOptions = loggerOptions{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&logging.loggerOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextualLogger determines whether the logger passed to
|
||||||
|
// SetLoggerWithOptions may also get called directly. Such a logger cannot rely
|
||||||
|
// on verbosity checking in klog.
|
||||||
|
func ContextualLogger(enabled bool) LoggerOption {
|
||||||
|
return func(o *loggerOptions) {
|
||||||
|
o.contextualLogger = enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlushLogger provides a callback for flushing data buffered by the logger.
|
||||||
|
func FlushLogger(flush func()) LoggerOption {
|
||||||
|
return func(o *loggerOptions) {
|
||||||
|
o.flush = flush
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoggerOption implements the functional parameter paradigm for
|
||||||
|
// SetLoggerWithOptions.
|
||||||
|
type LoggerOption func(o *loggerOptions)
|
||||||
|
|
||||||
|
type loggerOptions struct {
|
||||||
|
contextualLogger bool
|
||||||
|
flush func()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearLogger removes a backing Logger implementation if one was set earlier
|
||||||
|
// with SetLogger.
|
||||||
|
//
|
||||||
|
// Modifying the logger is not thread-safe and should be done while no other
|
||||||
|
// goroutines invoke log calls, usually during program initialization.
|
||||||
|
func ClearLogger() {
|
||||||
|
logging.logger = nil
|
||||||
|
logging.loggerOptions = loggerOptions{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableContextualLogging controls whether contextual logging is enabled.
|
||||||
|
// By default it is enabled. When disabled, FromContext avoids looking up
|
||||||
|
// the logger in the context and always returns the global logger.
|
||||||
|
// LoggerWithValues, LoggerWithName, and NewContext become no-ops
|
||||||
|
// and return their input logger respectively context. This may be useful
|
||||||
|
// to avoid the additional overhead for contextual logging.
|
||||||
|
//
|
||||||
|
// This must be called during initialization before goroutines are started.
|
||||||
|
func EnableContextualLogging(enabled bool) {
|
||||||
|
logging.contextualLoggingEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext retrieves a logger set by the caller or, if not set,
|
||||||
|
// falls back to the program's global logger (a Logger instance or klog
|
||||||
|
// itself).
|
||||||
|
func FromContext(ctx context.Context) Logger {
|
||||||
|
if logging.contextualLoggingEnabled {
|
||||||
|
if logger, err := logr.FromContext(ctx); err == nil {
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Background()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO can be used as a last resort by code that has no means of
|
||||||
|
// receiving a logger from its caller. FromContext or an explicit logger
|
||||||
|
// parameter should be used instead.
|
||||||
|
func TODO() Logger {
|
||||||
|
return Background()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Background retrieves the fallback logger. It should not be called before
|
||||||
|
// that logger was initialized by the program and not by code that should
|
||||||
|
// better receive a logger via its parameters. TODO can be used as a temporary
|
||||||
|
// solution for such code.
|
||||||
|
func Background() Logger {
|
||||||
|
if logging.loggerOptions.contextualLogger {
|
||||||
|
// Is non-nil because logging.loggerOptions.contextualLogger is
|
||||||
|
// only true if a logger was set.
|
||||||
|
return *logging.logger
|
||||||
|
}
|
||||||
|
|
||||||
|
return klogLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoggerWithValues returns logger.WithValues(...kv) when
|
||||||
|
// contextual logging is enabled, otherwise the logger.
|
||||||
|
func LoggerWithValues(logger Logger, kv ...interface{}) Logger {
|
||||||
|
if logging.contextualLoggingEnabled {
|
||||||
|
return logger.WithValues(kv...)
|
||||||
|
}
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoggerWithName returns logger.WithName(name) when contextual logging is
|
||||||
|
// enabled, otherwise the logger.
|
||||||
|
func LoggerWithName(logger Logger, name string) Logger {
|
||||||
|
if logging.contextualLoggingEnabled {
|
||||||
|
return logger.WithName(name)
|
||||||
|
}
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext returns logr.NewContext(ctx, logger) when
|
||||||
|
// contextual logging is enabled, otherwise ctx.
|
||||||
|
func NewContext(ctx context.Context, logger Logger) context.Context {
|
||||||
|
if logging.contextualLoggingEnabled {
|
||||||
|
return logr.NewContext(ctx, logger)
|
||||||
|
}
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
69
vendor/k8s.io/klog/v2/exit.go
generated
vendored
Normal file
69
vendor/k8s.io/klog/v2/exit.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
|
||||||
|
//
|
||||||
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
// Copyright 2022 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 klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
|
||||||
|
// ExitFlushTimeout is the timeout that klog has traditionally used during
|
||||||
|
// calls like Fatal or Exit when flushing log data right before exiting.
|
||||||
|
// Applications that replace those calls and do not have some specific
|
||||||
|
// requirements like "exit immediately" can use this value as parameter
|
||||||
|
// for FlushAndExit.
|
||||||
|
//
|
||||||
|
// Can be set for testing purpose or to change the application's
|
||||||
|
// default.
|
||||||
|
ExitFlushTimeout = 10 * time.Second
|
||||||
|
|
||||||
|
// OsExit is the function called by FlushAndExit to terminate the program.
|
||||||
|
//
|
||||||
|
// Can be set for testing purpose or to change the application's
|
||||||
|
// default behavior. Note that the function should not simply return
|
||||||
|
// because callers of functions like Fatal will not expect that.
|
||||||
|
OsExit = os.Exit
|
||||||
|
)
|
||||||
|
|
||||||
|
// FlushAndExit flushes log data for a certain amount of time and then calls
|
||||||
|
// os.Exit. Combined with some logging call it provides a replacement for
|
||||||
|
// traditional calls like Fatal or Exit.
|
||||||
|
func FlushAndExit(flushTimeout time.Duration, exitCode int) {
|
||||||
|
timeoutFlush(flushTimeout)
|
||||||
|
OsExit(exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeoutFlush calls Flush and returns when it completes or after timeout
|
||||||
|
// elapses, whichever happens first. This is needed because the hooks invoked
|
||||||
|
// by Flush may deadlock when klog.Fatal is called from a hook that holds
|
||||||
|
// a lock. Flushing also might take too long.
|
||||||
|
func timeoutFlush(timeout time.Duration) {
|
||||||
|
done := make(chan bool, 1)
|
||||||
|
go func() {
|
||||||
|
Flush() // calls logging.lockAndFlushAll()
|
||||||
|
done <- true
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-time.After(timeout):
|
||||||
|
fmt.Fprintln(os.Stderr, "klog: Flush took longer than", timeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
38
vendor/k8s.io/klog/v2/imports.go
generated
vendored
Normal file
38
vendor/k8s.io/klog/v2/imports.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The reason for providing these aliases is to allow code to work with logr
|
||||||
|
// without directly importing it.
|
||||||
|
|
||||||
|
// Logger in this package is exactly the same as logr.Logger.
|
||||||
|
type Logger = logr.Logger
|
||||||
|
|
||||||
|
// LogSink in this package is exactly the same as logr.LogSink.
|
||||||
|
type LogSink = logr.LogSink
|
||||||
|
|
||||||
|
// Runtimeinfo in this package is exactly the same as logr.RuntimeInfo.
|
||||||
|
type RuntimeInfo = logr.RuntimeInfo
|
||||||
|
|
||||||
|
var (
|
||||||
|
// New is an alias for logr.New.
|
||||||
|
New = logr.New
|
||||||
|
)
|
||||||
159
vendor/k8s.io/klog/v2/internal/buffer/buffer.go
generated
vendored
Normal file
159
vendor/k8s.io/klog/v2/internal/buffer/buffer.go
generated
vendored
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
// Copyright 2022 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 buffer provides a cache for byte.Buffer instances that can be reused
|
||||||
|
// to avoid frequent allocation and deallocation. It also has utility code
|
||||||
|
// for log header formatting that use these buffers.
|
||||||
|
package buffer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2/internal/severity"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Pid is inserted into log headers. Can be overridden for tests.
|
||||||
|
Pid = os.Getpid()
|
||||||
|
)
|
||||||
|
|
||||||
|
// Buffer holds a single byte.Buffer for reuse. The zero value is ready for
|
||||||
|
// use. It also provides some helper methods for output formatting.
|
||||||
|
type Buffer struct {
|
||||||
|
bytes.Buffer
|
||||||
|
Tmp [64]byte // temporary byte array for creating headers.
|
||||||
|
next *Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffers manages the reuse of individual buffer instances. It is thread-safe.
|
||||||
|
type Buffers struct {
|
||||||
|
// mu protects the free list. It is separate from the main mutex
|
||||||
|
// so buffers can be grabbed and printed to without holding the main lock,
|
||||||
|
// for better parallelization.
|
||||||
|
mu sync.Mutex
|
||||||
|
|
||||||
|
// freeList is a list of byte buffers, maintained under mu.
|
||||||
|
freeList *Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBuffer returns a new, ready-to-use buffer.
|
||||||
|
func (bl *Buffers) GetBuffer() *Buffer {
|
||||||
|
bl.mu.Lock()
|
||||||
|
b := bl.freeList
|
||||||
|
if b != nil {
|
||||||
|
bl.freeList = b.next
|
||||||
|
}
|
||||||
|
bl.mu.Unlock()
|
||||||
|
if b == nil {
|
||||||
|
b = new(Buffer)
|
||||||
|
} else {
|
||||||
|
b.next = nil
|
||||||
|
b.Reset()
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutBuffer returns a buffer to the free list.
|
||||||
|
func (bl *Buffers) PutBuffer(b *Buffer) {
|
||||||
|
if b.Len() >= 256 {
|
||||||
|
// Let big buffers die a natural death.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bl.mu.Lock()
|
||||||
|
b.next = bl.freeList
|
||||||
|
bl.freeList = b
|
||||||
|
bl.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some custom tiny helper functions to print the log header efficiently.
|
||||||
|
|
||||||
|
const digits = "0123456789"
|
||||||
|
|
||||||
|
// twoDigits formats a zero-prefixed two-digit integer at buf.Tmp[i].
|
||||||
|
func (buf *Buffer) twoDigits(i, d int) {
|
||||||
|
buf.Tmp[i+1] = digits[d%10]
|
||||||
|
d /= 10
|
||||||
|
buf.Tmp[i] = digits[d%10]
|
||||||
|
}
|
||||||
|
|
||||||
|
// nDigits formats an n-digit integer at buf.Tmp[i],
|
||||||
|
// padding with pad on the left.
|
||||||
|
// It assumes d >= 0.
|
||||||
|
func (buf *Buffer) nDigits(n, i, d int, pad byte) {
|
||||||
|
j := n - 1
|
||||||
|
for ; j >= 0 && d > 0; j-- {
|
||||||
|
buf.Tmp[i+j] = digits[d%10]
|
||||||
|
d /= 10
|
||||||
|
}
|
||||||
|
for ; j >= 0; j-- {
|
||||||
|
buf.Tmp[i+j] = pad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// someDigits formats a zero-prefixed variable-width integer at buf.Tmp[i].
|
||||||
|
func (buf *Buffer) someDigits(i, d int) int {
|
||||||
|
// Print into the top, then copy down. We know there's space for at least
|
||||||
|
// a 10-digit number.
|
||||||
|
j := len(buf.Tmp)
|
||||||
|
for {
|
||||||
|
j--
|
||||||
|
buf.Tmp[j] = digits[d%10]
|
||||||
|
d /= 10
|
||||||
|
if d == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return copy(buf.Tmp[i:], buf.Tmp[j:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatHeader formats a log header using the provided file name and line number.
|
||||||
|
func (buf *Buffer) FormatHeader(s severity.Severity, file string, line int, now time.Time) {
|
||||||
|
if line < 0 {
|
||||||
|
line = 0 // not a real line number, but acceptable to someDigits
|
||||||
|
}
|
||||||
|
if s > severity.FatalLog {
|
||||||
|
s = severity.InfoLog // for safety.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
|
||||||
|
// It's worth about 3X. Fprintf is hard.
|
||||||
|
_, month, day := now.Date()
|
||||||
|
hour, minute, second := now.Clock()
|
||||||
|
// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
|
||||||
|
buf.Tmp[0] = severity.Char[s]
|
||||||
|
buf.twoDigits(1, int(month))
|
||||||
|
buf.twoDigits(3, day)
|
||||||
|
buf.Tmp[5] = ' '
|
||||||
|
buf.twoDigits(6, hour)
|
||||||
|
buf.Tmp[8] = ':'
|
||||||
|
buf.twoDigits(9, minute)
|
||||||
|
buf.Tmp[11] = ':'
|
||||||
|
buf.twoDigits(12, second)
|
||||||
|
buf.Tmp[14] = '.'
|
||||||
|
buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
|
||||||
|
buf.Tmp[21] = ' '
|
||||||
|
buf.nDigits(7, 22, Pid, ' ') // TODO: should be TID
|
||||||
|
buf.Tmp[29] = ' '
|
||||||
|
buf.Write(buf.Tmp[:30])
|
||||||
|
buf.WriteString(file)
|
||||||
|
buf.Tmp[0] = ':'
|
||||||
|
n := buf.someDigits(1, line)
|
||||||
|
buf.Tmp[n+1] = ']'
|
||||||
|
buf.Tmp[n+2] = ' '
|
||||||
|
buf.Write(buf.Tmp[:n+3])
|
||||||
|
}
|
||||||
7
vendor/k8s.io/klog/v2/internal/clock/README.md
generated
vendored
Normal file
7
vendor/k8s.io/klog/v2/internal/clock/README.md
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Clock
|
||||||
|
|
||||||
|
This package provides an interface for time-based operations. It allows
|
||||||
|
mocking time for testing.
|
||||||
|
|
||||||
|
This is a copy of k8s.io/utils/clock. We have to copy it to avoid a circular
|
||||||
|
dependency (k8s.io/klog -> k8s.io/utils -> k8s.io/klog).
|
||||||
178
vendor/k8s.io/klog/v2/internal/clock/clock.go
generated
vendored
Normal file
178
vendor/k8s.io/klog/v2/internal/clock/clock.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
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 clock
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// PassiveClock allows for injecting fake or real clocks into code
|
||||||
|
// that needs to read the current time but does not support scheduling
|
||||||
|
// activity in the future.
|
||||||
|
type PassiveClock interface {
|
||||||
|
Now() time.Time
|
||||||
|
Since(time.Time) time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clock allows for injecting fake or real clocks into code that
|
||||||
|
// needs to do arbitrary things based on time.
|
||||||
|
type Clock interface {
|
||||||
|
PassiveClock
|
||||||
|
// After returns the channel of a new Timer.
|
||||||
|
// This method does not allow to free/GC the backing timer before it fires. Use
|
||||||
|
// NewTimer instead.
|
||||||
|
After(d time.Duration) <-chan time.Time
|
||||||
|
// NewTimer returns a new Timer.
|
||||||
|
NewTimer(d time.Duration) Timer
|
||||||
|
// Sleep sleeps for the provided duration d.
|
||||||
|
// Consider making the sleep interruptible by using 'select' on a context channel and a timer channel.
|
||||||
|
Sleep(d time.Duration)
|
||||||
|
// Tick returns the channel of a new Ticker.
|
||||||
|
// This method does not allow to free/GC the backing ticker. Use
|
||||||
|
// NewTicker from WithTicker instead.
|
||||||
|
Tick(d time.Duration) <-chan time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTicker allows for injecting fake or real clocks into code that
|
||||||
|
// needs to do arbitrary things based on time.
|
||||||
|
type WithTicker interface {
|
||||||
|
Clock
|
||||||
|
// NewTicker returns a new Ticker.
|
||||||
|
NewTicker(time.Duration) Ticker
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDelayedExecution allows for injecting fake or real clocks into
|
||||||
|
// code that needs to make use of AfterFunc functionality.
|
||||||
|
type WithDelayedExecution interface {
|
||||||
|
Clock
|
||||||
|
// AfterFunc executes f in its own goroutine after waiting
|
||||||
|
// for d duration and returns a Timer whose channel can be
|
||||||
|
// closed by calling Stop() on the Timer.
|
||||||
|
AfterFunc(d time.Duration, f func()) Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTickerAndDelayedExecution allows for injecting fake or real clocks
|
||||||
|
// into code that needs Ticker and AfterFunc functionality
|
||||||
|
type WithTickerAndDelayedExecution interface {
|
||||||
|
WithTicker
|
||||||
|
// AfterFunc executes f in its own goroutine after waiting
|
||||||
|
// for d duration and returns a Timer whose channel can be
|
||||||
|
// closed by calling Stop() on the Timer.
|
||||||
|
AfterFunc(d time.Duration, f func()) Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ticker defines the Ticker interface.
|
||||||
|
type Ticker interface {
|
||||||
|
C() <-chan time.Time
|
||||||
|
Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = WithTicker(RealClock{})
|
||||||
|
|
||||||
|
// RealClock really calls time.Now()
|
||||||
|
type RealClock struct{}
|
||||||
|
|
||||||
|
// Now returns the current time.
|
||||||
|
func (RealClock) Now() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since returns time since the specified timestamp.
|
||||||
|
func (RealClock) Since(ts time.Time) time.Duration {
|
||||||
|
return time.Since(ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// After is the same as time.After(d).
|
||||||
|
// This method does not allow to free/GC the backing timer before it fires. Use
|
||||||
|
// NewTimer instead.
|
||||||
|
func (RealClock) After(d time.Duration) <-chan time.Time {
|
||||||
|
return time.After(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTimer is the same as time.NewTimer(d)
|
||||||
|
func (RealClock) NewTimer(d time.Duration) Timer {
|
||||||
|
return &realTimer{
|
||||||
|
timer: time.NewTimer(d),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterFunc is the same as time.AfterFunc(d, f).
|
||||||
|
func (RealClock) AfterFunc(d time.Duration, f func()) Timer {
|
||||||
|
return &realTimer{
|
||||||
|
timer: time.AfterFunc(d, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tick is the same as time.Tick(d)
|
||||||
|
// This method does not allow to free/GC the backing ticker. Use
|
||||||
|
// NewTicker instead.
|
||||||
|
func (RealClock) Tick(d time.Duration) <-chan time.Time {
|
||||||
|
return time.Tick(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTicker returns a new Ticker.
|
||||||
|
func (RealClock) NewTicker(d time.Duration) Ticker {
|
||||||
|
return &realTicker{
|
||||||
|
ticker: time.NewTicker(d),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sleep is the same as time.Sleep(d)
|
||||||
|
// Consider making the sleep interruptible by using 'select' on a context channel and a timer channel.
|
||||||
|
func (RealClock) Sleep(d time.Duration) {
|
||||||
|
time.Sleep(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer allows for injecting fake or real timers into code that
|
||||||
|
// needs to do arbitrary things based on time.
|
||||||
|
type Timer interface {
|
||||||
|
C() <-chan time.Time
|
||||||
|
Stop() bool
|
||||||
|
Reset(d time.Duration) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Timer(&realTimer{})
|
||||||
|
|
||||||
|
// realTimer is backed by an actual time.Timer.
|
||||||
|
type realTimer struct {
|
||||||
|
timer *time.Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// C returns the underlying timer's channel.
|
||||||
|
func (r *realTimer) C() <-chan time.Time {
|
||||||
|
return r.timer.C
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop calls Stop() on the underlying timer.
|
||||||
|
func (r *realTimer) Stop() bool {
|
||||||
|
return r.timer.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset calls Reset() on the underlying timer.
|
||||||
|
func (r *realTimer) Reset(d time.Duration) bool {
|
||||||
|
return r.timer.Reset(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
type realTicker struct {
|
||||||
|
ticker *time.Ticker
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *realTicker) C() <-chan time.Time {
|
||||||
|
return r.ticker.C
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *realTicker) Stop() {
|
||||||
|
r.ticker.Stop()
|
||||||
|
}
|
||||||
42
vendor/k8s.io/klog/v2/internal/dbg/dbg.go
generated
vendored
Normal file
42
vendor/k8s.io/klog/v2/internal/dbg/dbg.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
|
||||||
|
//
|
||||||
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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 dbg provides some helper code for call traces.
|
||||||
|
package dbg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stacks is a wrapper for runtime.Stack that attempts to recover the data for
|
||||||
|
// all goroutines or the calling one.
|
||||||
|
func Stacks(all bool) []byte {
|
||||||
|
// We don't know how big the traces are, so grow a few times if they don't fit. Start large, though.
|
||||||
|
n := 10000
|
||||||
|
if all {
|
||||||
|
n = 100000
|
||||||
|
}
|
||||||
|
var trace []byte
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
trace = make([]byte, n)
|
||||||
|
nbytes := runtime.Stack(trace, all)
|
||||||
|
if nbytes < len(trace) {
|
||||||
|
return trace[:nbytes]
|
||||||
|
}
|
||||||
|
n *= 2
|
||||||
|
}
|
||||||
|
return trace
|
||||||
|
}
|
||||||
253
vendor/k8s.io/klog/v2/internal/serialize/keyvalues.go
generated
vendored
Normal file
253
vendor/k8s.io/klog/v2/internal/serialize/keyvalues.go
generated
vendored
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 serialize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithValues implements LogSink.WithValues. The old key/value pairs are
|
||||||
|
// assumed to be well-formed, the new ones are checked and padded if
|
||||||
|
// necessary. It returns a new slice.
|
||||||
|
func WithValues(oldKV, newKV []interface{}) []interface{} {
|
||||||
|
if len(newKV) == 0 {
|
||||||
|
return oldKV
|
||||||
|
}
|
||||||
|
newLen := len(oldKV) + len(newKV)
|
||||||
|
hasMissingValue := newLen%2 != 0
|
||||||
|
if hasMissingValue {
|
||||||
|
newLen++
|
||||||
|
}
|
||||||
|
// The new LogSink must have its own slice.
|
||||||
|
kv := make([]interface{}, 0, newLen)
|
||||||
|
kv = append(kv, oldKV...)
|
||||||
|
kv = append(kv, newKV...)
|
||||||
|
if hasMissingValue {
|
||||||
|
kv = append(kv, missingValue)
|
||||||
|
}
|
||||||
|
return kv
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeKVs deduplicates elements provided in two key/value slices.
|
||||||
|
//
|
||||||
|
// Keys in each slice are expected to be unique, so duplicates can only occur
|
||||||
|
// when the first and second slice contain the same key. When that happens, the
|
||||||
|
// key/value pair from the second slice is used. The first slice must be well-formed
|
||||||
|
// (= even key/value pairs). The second one may have a missing value, in which
|
||||||
|
// case the special "missing value" is added to the result.
|
||||||
|
func MergeKVs(first, second []interface{}) []interface{} {
|
||||||
|
maxLength := len(first) + (len(second)+1)/2*2
|
||||||
|
if maxLength == 0 {
|
||||||
|
// Nothing to do at all.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(first) == 0 && len(second)%2 == 0 {
|
||||||
|
// Nothing to be overridden, second slice is well-formed
|
||||||
|
// and can be used directly.
|
||||||
|
return second
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine which keys are in the second slice so that we can skip
|
||||||
|
// them when iterating over the first one. The code intentionally
|
||||||
|
// favors performance over completeness: we assume that keys are string
|
||||||
|
// constants and thus compare equal when the string values are equal. A
|
||||||
|
// string constant being overridden by, for example, a fmt.Stringer is
|
||||||
|
// not handled.
|
||||||
|
overrides := map[interface{}]bool{}
|
||||||
|
for i := 0; i < len(second); i += 2 {
|
||||||
|
overrides[second[i]] = true
|
||||||
|
}
|
||||||
|
merged := make([]interface{}, 0, maxLength)
|
||||||
|
for i := 0; i+1 < len(first); i += 2 {
|
||||||
|
key := first[i]
|
||||||
|
if overrides[key] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
merged = append(merged, key, first[i+1])
|
||||||
|
}
|
||||||
|
merged = append(merged, second...)
|
||||||
|
if len(merged)%2 != 0 {
|
||||||
|
merged = append(merged, missingValue)
|
||||||
|
}
|
||||||
|
return merged
|
||||||
|
}
|
||||||
|
|
||||||
|
const missingValue = "(MISSING)"
|
||||||
|
|
||||||
|
// KVListFormat serializes all key/value pairs into the provided buffer.
|
||||||
|
// A space gets inserted before the first pair and between each pair.
|
||||||
|
func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
|
||||||
|
for i := 0; i < len(keysAndValues); i += 2 {
|
||||||
|
var v interface{}
|
||||||
|
k := keysAndValues[i]
|
||||||
|
if i+1 < len(keysAndValues) {
|
||||||
|
v = keysAndValues[i+1]
|
||||||
|
} else {
|
||||||
|
v = missingValue
|
||||||
|
}
|
||||||
|
b.WriteByte(' ')
|
||||||
|
// Keys are assumed to be well-formed according to
|
||||||
|
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments
|
||||||
|
// for the sake of performance. Keys with spaces,
|
||||||
|
// special characters, etc. will break parsing.
|
||||||
|
if sK, ok := k.(string); ok {
|
||||||
|
// Avoid one allocation when the key is a string, which
|
||||||
|
// normally it should be.
|
||||||
|
b.WriteString(sK)
|
||||||
|
} else {
|
||||||
|
b.WriteString(fmt.Sprintf("%s", k))
|
||||||
|
}
|
||||||
|
|
||||||
|
// The type checks are sorted so that more frequently used ones
|
||||||
|
// come first because that is then faster in the common
|
||||||
|
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
|
||||||
|
// than plain strings
|
||||||
|
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
|
||||||
|
switch v := v.(type) {
|
||||||
|
case fmt.Stringer:
|
||||||
|
writeStringValue(b, true, StringerToString(v))
|
||||||
|
case string:
|
||||||
|
writeStringValue(b, true, v)
|
||||||
|
case error:
|
||||||
|
writeStringValue(b, true, ErrorToString(v))
|
||||||
|
case logr.Marshaler:
|
||||||
|
value := MarshalerToValue(v)
|
||||||
|
// A marshaler that returns a string is useful for
|
||||||
|
// delayed formatting of complex values. We treat this
|
||||||
|
// case like a normal string. This is useful for
|
||||||
|
// multi-line support.
|
||||||
|
//
|
||||||
|
// We could do this by recursively formatting a value,
|
||||||
|
// but that comes with the risk of infinite recursion
|
||||||
|
// if a marshaler returns itself. Instead we call it
|
||||||
|
// only once and rely on it returning the intended
|
||||||
|
// value directly.
|
||||||
|
switch value := value.(type) {
|
||||||
|
case string:
|
||||||
|
writeStringValue(b, true, value)
|
||||||
|
default:
|
||||||
|
writeStringValue(b, false, fmt.Sprintf("%+v", value))
|
||||||
|
}
|
||||||
|
case []byte:
|
||||||
|
// In https://github.com/kubernetes/klog/pull/237 it was decided
|
||||||
|
// to format byte slices with "%+q". The advantages of that are:
|
||||||
|
// - readable output if the bytes happen to be printable
|
||||||
|
// - non-printable bytes get represented as unicode escape
|
||||||
|
// sequences (\uxxxx)
|
||||||
|
//
|
||||||
|
// The downsides are that we cannot use the faster
|
||||||
|
// strconv.Quote here and that multi-line output is not
|
||||||
|
// supported. If developers know that a byte array is
|
||||||
|
// printable and they want multi-line output, they can
|
||||||
|
// convert the value to string before logging it.
|
||||||
|
b.WriteByte('=')
|
||||||
|
b.WriteString(fmt.Sprintf("%+q", v))
|
||||||
|
default:
|
||||||
|
writeStringValue(b, false, fmt.Sprintf("%+v", v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringerToString converts a Stringer to a string,
|
||||||
|
// handling panics if they occur.
|
||||||
|
func StringerToString(s fmt.Stringer) (ret string) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
ret = fmt.Sprintf("<panic: %s>", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ret = s.String()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalerToValue invokes a marshaler and catches
|
||||||
|
// panics.
|
||||||
|
func MarshalerToValue(m logr.Marshaler) (ret interface{}) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
ret = fmt.Sprintf("<panic: %s>", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ret = m.MarshalLog()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorToString converts an error to a string,
|
||||||
|
// handling panics if they occur.
|
||||||
|
func ErrorToString(err error) (ret string) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
ret = fmt.Sprintf("<panic: %s>", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
ret = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeStringValue(b *bytes.Buffer, quote bool, v string) {
|
||||||
|
data := []byte(v)
|
||||||
|
index := bytes.IndexByte(data, '\n')
|
||||||
|
if index == -1 {
|
||||||
|
b.WriteByte('=')
|
||||||
|
if quote {
|
||||||
|
// Simple string, quote quotation marks and non-printable characters.
|
||||||
|
b.WriteString(strconv.Quote(v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Non-string with no line breaks.
|
||||||
|
b.WriteString(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complex multi-line string, show as-is with indention like this:
|
||||||
|
// I... "hello world" key=<
|
||||||
|
// <tab>line 1
|
||||||
|
// <tab>line 2
|
||||||
|
// >
|
||||||
|
//
|
||||||
|
// Tabs indent the lines of the value while the end of string delimiter
|
||||||
|
// is indented with a space. That has two purposes:
|
||||||
|
// - visual difference between the two for a human reader because indention
|
||||||
|
// will be different
|
||||||
|
// - no ambiguity when some value line starts with the end delimiter
|
||||||
|
//
|
||||||
|
// One downside is that the output cannot distinguish between strings that
|
||||||
|
// end with a line break and those that don't because the end delimiter
|
||||||
|
// will always be on the next line.
|
||||||
|
b.WriteString("=<\n")
|
||||||
|
for index != -1 {
|
||||||
|
b.WriteByte('\t')
|
||||||
|
b.Write(data[0 : index+1])
|
||||||
|
data = data[index+1:]
|
||||||
|
index = bytes.IndexByte(data, '\n')
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
// String ended with line break, don't add another.
|
||||||
|
b.WriteString(" >")
|
||||||
|
} else {
|
||||||
|
// No line break at end of last line, write rest of string and
|
||||||
|
// add one.
|
||||||
|
b.WriteByte('\t')
|
||||||
|
b.Write(data)
|
||||||
|
b.WriteString("\n >")
|
||||||
|
}
|
||||||
|
}
|
||||||
58
vendor/k8s.io/klog/v2/internal/severity/severity.go
generated
vendored
Normal file
58
vendor/k8s.io/klog/v2/internal/severity/severity.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
// Copyright 2022 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 severity provides definitions for klog severity (info, warning, ...)
|
||||||
|
package severity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// severity identifies the sort of log: info, warning etc. The binding to flag.Value
|
||||||
|
// is handled in klog.go
|
||||||
|
type Severity int32 // sync/atomic int32
|
||||||
|
|
||||||
|
// These constants identify the log levels in order of increasing severity.
|
||||||
|
// A message written to a high-severity log file is also written to each
|
||||||
|
// lower-severity log file.
|
||||||
|
const (
|
||||||
|
InfoLog Severity = iota
|
||||||
|
WarningLog
|
||||||
|
ErrorLog
|
||||||
|
FatalLog
|
||||||
|
NumSeverity = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// Char contains one shortcut letter per severity level.
|
||||||
|
const Char = "IWEF"
|
||||||
|
|
||||||
|
// Name contains one name per severity level.
|
||||||
|
var Name = []string{
|
||||||
|
InfoLog: "INFO",
|
||||||
|
WarningLog: "WARNING",
|
||||||
|
ErrorLog: "ERROR",
|
||||||
|
FatalLog: "FATAL",
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByName looks up a severity level by name.
|
||||||
|
func ByName(s string) (Severity, bool) {
|
||||||
|
s = strings.ToUpper(s)
|
||||||
|
for i, name := range Name {
|
||||||
|
if name == s {
|
||||||
|
return Severity(i), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
158
vendor/k8s.io/klog/v2/k8s_references.go
generated
vendored
Normal file
158
vendor/k8s.io/klog/v2/k8s_references.go
generated
vendored
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ObjectRef references a kubernetes object
|
||||||
|
type ObjectRef struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ref ObjectRef) String() string {
|
||||||
|
if ref.Namespace != "" {
|
||||||
|
return fmt.Sprintf("%s/%s", ref.Namespace, ref.Name)
|
||||||
|
}
|
||||||
|
return ref.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalLog ensures that loggers with support for structured output will log
|
||||||
|
// as a struct by removing the String method via a custom type.
|
||||||
|
func (ref ObjectRef) MarshalLog() interface{} {
|
||||||
|
type or ObjectRef
|
||||||
|
return or(ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ logr.Marshaler = ObjectRef{}
|
||||||
|
|
||||||
|
// KMetadata is a subset of the kubernetes k8s.io/apimachinery/pkg/apis/meta/v1.Object interface
|
||||||
|
// this interface may expand in the future, but will always be a subset of the
|
||||||
|
// kubernetes k8s.io/apimachinery/pkg/apis/meta/v1.Object interface
|
||||||
|
type KMetadata interface {
|
||||||
|
GetName() string
|
||||||
|
GetNamespace() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// KObj returns ObjectRef from ObjectMeta
|
||||||
|
func KObj(obj KMetadata) ObjectRef {
|
||||||
|
if obj == nil {
|
||||||
|
return ObjectRef{}
|
||||||
|
}
|
||||||
|
if val := reflect.ValueOf(obj); val.Kind() == reflect.Ptr && val.IsNil() {
|
||||||
|
return ObjectRef{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ObjectRef{
|
||||||
|
Name: obj.GetName(),
|
||||||
|
Namespace: obj.GetNamespace(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KRef returns ObjectRef from name and namespace
|
||||||
|
func KRef(namespace, name string) ObjectRef {
|
||||||
|
return ObjectRef{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// KObjs returns slice of ObjectRef from an slice of ObjectMeta
|
||||||
|
//
|
||||||
|
// DEPRECATED: Use KObjSlice instead, it has better performance.
|
||||||
|
func KObjs(arg interface{}) []ObjectRef {
|
||||||
|
s := reflect.ValueOf(arg)
|
||||||
|
if s.Kind() != reflect.Slice {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
objectRefs := make([]ObjectRef, 0, s.Len())
|
||||||
|
for i := 0; i < s.Len(); i++ {
|
||||||
|
if v, ok := s.Index(i).Interface().(KMetadata); ok {
|
||||||
|
objectRefs = append(objectRefs, KObj(v))
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return objectRefs
|
||||||
|
}
|
||||||
|
|
||||||
|
// KObjSlice takes a slice of objects that implement the KMetadata interface
|
||||||
|
// and returns an object that gets logged as a slice of ObjectRef values or a
|
||||||
|
// string containing those values, depending on whether the logger prefers text
|
||||||
|
// output or structured output.
|
||||||
|
//
|
||||||
|
// An error string is logged when KObjSlice is not passed a suitable slice.
|
||||||
|
//
|
||||||
|
// Processing of the argument is delayed until the value actually gets logged,
|
||||||
|
// in contrast to KObjs where that overhead is incurred regardless of whether
|
||||||
|
// the result is needed.
|
||||||
|
func KObjSlice(arg interface{}) interface{} {
|
||||||
|
return kobjSlice{arg: arg}
|
||||||
|
}
|
||||||
|
|
||||||
|
type kobjSlice struct {
|
||||||
|
arg interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ fmt.Stringer = kobjSlice{}
|
||||||
|
var _ logr.Marshaler = kobjSlice{}
|
||||||
|
|
||||||
|
func (ks kobjSlice) String() string {
|
||||||
|
objectRefs, err := ks.process()
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v", objectRefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks kobjSlice) MarshalLog() interface{} {
|
||||||
|
objectRefs, err := ks.process()
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return objectRefs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks kobjSlice) process() ([]interface{}, error) {
|
||||||
|
s := reflect.ValueOf(ks.arg)
|
||||||
|
switch s.Kind() {
|
||||||
|
case reflect.Invalid:
|
||||||
|
// nil parameter, print as nil.
|
||||||
|
return nil, nil
|
||||||
|
case reflect.Slice:
|
||||||
|
// Okay, handle below.
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("<KObjSlice needs a slice, got type %T>", ks.arg)
|
||||||
|
}
|
||||||
|
objectRefs := make([]interface{}, 0, s.Len())
|
||||||
|
for i := 0; i < s.Len(); i++ {
|
||||||
|
item := s.Index(i).Interface()
|
||||||
|
if item == nil {
|
||||||
|
objectRefs = append(objectRefs, nil)
|
||||||
|
} else if v, ok := item.(KMetadata); ok {
|
||||||
|
objectRefs = append(objectRefs, KObj(v))
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("<KObjSlice needs a slice of values implementing KMetadata, got type %T>", item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return objectRefs, nil
|
||||||
|
}
|
||||||
1014
vendor/k8s.io/klog/v2/klog.go
generated
vendored
1014
vendor/k8s.io/klog/v2/klog.go
generated
vendored
File diff suppressed because it is too large
Load Diff
34
vendor/k8s.io/klog/v2/klog_file.go
generated
vendored
34
vendor/k8s.io/klog/v2/klog_file.go
generated
vendored
@ -22,9 +22,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -57,38 +55,6 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserName() string {
|
|
||||||
userNameOnce.Do(func() {
|
|
||||||
// On Windows, the Go 'user' package requires netapi32.dll.
|
|
||||||
// This affects Windows Nano Server:
|
|
||||||
// https://github.com/golang/go/issues/21867
|
|
||||||
// Fallback to using environment variables.
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
u := os.Getenv("USERNAME")
|
|
||||||
if len(u) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Sanitize the USERNAME since it may contain filepath separators.
|
|
||||||
u = strings.Replace(u, `\`, "_", -1)
|
|
||||||
|
|
||||||
// user.Current().Username normally produces something like 'USERDOMAIN\USERNAME'
|
|
||||||
d := os.Getenv("USERDOMAIN")
|
|
||||||
if len(d) != 0 {
|
|
||||||
userName = d + "_" + u
|
|
||||||
} else {
|
|
||||||
userName = u
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
current, err := user.Current()
|
|
||||||
if err == nil {
|
|
||||||
userName = current.Username
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return userName
|
|
||||||
}
|
|
||||||
|
|
||||||
// shortHostname returns its argument, truncating at the first period.
|
// shortHostname returns its argument, truncating at the first period.
|
||||||
// For instance, given "www.google.com" it returns "www".
|
// For instance, given "www.google.com" it returns "www".
|
||||||
func shortHostname(hostname string) string {
|
func shortHostname(hostname string) string {
|
||||||
|
|||||||
19
vendor/k8s.io/klog/v2/klog_file_others.go
generated
vendored
Normal file
19
vendor/k8s.io/klog/v2/klog_file_others.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getUserName() string {
|
||||||
|
userNameOnce.Do(func() {
|
||||||
|
current, err := user.Current()
|
||||||
|
if err == nil {
|
||||||
|
userName = current.Username
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return userName
|
||||||
|
}
|
||||||
34
vendor/k8s.io/klog/v2/klog_file_windows.go
generated
vendored
Normal file
34
vendor/k8s.io/klog/v2/klog_file_windows.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getUserName() string {
|
||||||
|
userNameOnce.Do(func() {
|
||||||
|
// On Windows, the Go 'user' package requires netapi32.dll.
|
||||||
|
// This affects Windows Nano Server:
|
||||||
|
// https://github.com/golang/go/issues/21867
|
||||||
|
// Fallback to using environment variables.
|
||||||
|
u := os.Getenv("USERNAME")
|
||||||
|
if len(u) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Sanitize the USERNAME since it may contain filepath separators.
|
||||||
|
u = strings.Replace(u, `\`, "_", -1)
|
||||||
|
|
||||||
|
// user.Current().Username normally produces something like 'USERDOMAIN\USERNAME'
|
||||||
|
d := os.Getenv("USERDOMAIN")
|
||||||
|
if len(d) != 0 {
|
||||||
|
userName = d + "_" + u
|
||||||
|
} else {
|
||||||
|
userName = u
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return userName
|
||||||
|
}
|
||||||
87
vendor/k8s.io/klog/v2/klogr.go
generated
vendored
Normal file
87
vendor/k8s.io/klog/v2/klogr.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2/internal/serialize"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewKlogr returns a logger that is functionally identical to
|
||||||
|
// klogr.NewWithOptions(klogr.FormatKlog), i.e. it passes through to klog. The
|
||||||
|
// difference is that it uses a simpler implementation.
|
||||||
|
func NewKlogr() Logger {
|
||||||
|
return New(&klogger{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// klogger is a subset of klogr/klogr.go. It had to be copied to break an
|
||||||
|
// import cycle (klogr wants to use klog, and klog wants to use klogr).
|
||||||
|
type klogger struct {
|
||||||
|
level int
|
||||||
|
callDepth int
|
||||||
|
prefix string
|
||||||
|
values []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *klogger) Init(info logr.RuntimeInfo) {
|
||||||
|
l.callDepth += info.CallDepth
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l klogger) Info(level int, msg string, kvList ...interface{}) {
|
||||||
|
merged := serialize.MergeKVs(l.values, kvList)
|
||||||
|
if l.prefix != "" {
|
||||||
|
msg = l.prefix + ": " + msg
|
||||||
|
}
|
||||||
|
V(Level(level)).InfoSDepth(l.callDepth+1, msg, merged...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l klogger) Enabled(level int) bool {
|
||||||
|
return V(Level(level)).Enabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l klogger) Error(err error, msg string, kvList ...interface{}) {
|
||||||
|
merged := serialize.MergeKVs(l.values, kvList)
|
||||||
|
if l.prefix != "" {
|
||||||
|
msg = l.prefix + ": " + msg
|
||||||
|
}
|
||||||
|
ErrorSDepth(l.callDepth+1, err, msg, merged...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithName returns a new logr.Logger with the specified name appended. klogr
|
||||||
|
// uses '/' characters to separate name elements. Callers should not pass '/'
|
||||||
|
// in the provided name string, but this library does not actually enforce that.
|
||||||
|
func (l klogger) WithName(name string) logr.LogSink {
|
||||||
|
if len(l.prefix) > 0 {
|
||||||
|
l.prefix = l.prefix + "/"
|
||||||
|
}
|
||||||
|
l.prefix += name
|
||||||
|
return &l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l klogger) WithValues(kvList ...interface{}) logr.LogSink {
|
||||||
|
l.values = serialize.WithValues(l.values, kvList)
|
||||||
|
return &l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l klogger) WithCallDepth(depth int) logr.LogSink {
|
||||||
|
l.callDepth += depth
|
||||||
|
return &l
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ logr.LogSink = &klogger{}
|
||||||
|
var _ logr.CallDepthLogSink = &klogger{}
|
||||||
1
vendor/k8s.io/mount-utils/OWNERS
generated
vendored
1
vendor/k8s.io/mount-utils/OWNERS
generated
vendored
@ -11,6 +11,5 @@ approvers:
|
|||||||
- jingxu97
|
- jingxu97
|
||||||
- saad-ali
|
- saad-ali
|
||||||
- jsafrane
|
- jsafrane
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
- sig/storage
|
- sig/storage
|
||||||
|
|||||||
1
vendor/k8s.io/mount-utils/README.md
generated
vendored
1
vendor/k8s.io/mount-utils/README.md
generated
vendored
@ -28,3 +28,4 @@ Code of Conduct](code-of-conduct.md).
|
|||||||
### Contibution Guidelines
|
### Contibution Guidelines
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
||||||
|
|
||||||
|
|||||||
18
vendor/k8s.io/mount-utils/fake_mounter.go
generated
vendored
18
vendor/k8s.io/mount-utils/fake_mounter.go
generated
vendored
@ -34,6 +34,7 @@ type FakeMounter struct {
|
|||||||
// any golang's DATA RACE warnings.
|
// any golang's DATA RACE warnings.
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
UnmountFunc UnmountFunc
|
UnmountFunc UnmountFunc
|
||||||
|
skipMountPointCheck bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmountFunc is a function callback to be executed during the Unmount() call.
|
// UnmountFunc is a function callback to be executed during the Unmount() call.
|
||||||
@ -64,6 +65,11 @@ func NewFakeMounter(mps []MountPoint) *FakeMounter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FakeMounter) WithSkipMountPointCheck() *FakeMounter {
|
||||||
|
f.skipMountPointCheck = true
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
// ResetLog clears all the log entries in FakeMounter
|
// ResetLog clears all the log entries in FakeMounter
|
||||||
func (f *FakeMounter) ResetLog() {
|
func (f *FakeMounter) ResetLog() {
|
||||||
f.mutex.Lock()
|
f.mutex.Lock()
|
||||||
@ -212,6 +218,18 @@ func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FakeMounter) CanSafelySkipMountPointCheck() bool {
|
||||||
|
return f.skipMountPointCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeMounter) IsMountPoint(file string) (bool, error) {
|
||||||
|
notMnt, err := f.IsLikelyNotMountPoint(file)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return !notMnt, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetMountRefs finds all mount references to the path, returns a
|
// GetMountRefs finds all mount references to the path, returns a
|
||||||
// list of paths.
|
// list of paths.
|
||||||
func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||||
|
|||||||
88
vendor/k8s.io/mount-utils/mount.go
generated
vendored
88
vendor/k8s.io/mount-utils/mount.go
generated
vendored
@ -21,7 +21,6 @@ package mount
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -66,6 +65,18 @@ type Interface interface {
|
|||||||
// care about such situations, this is a faster alternative to calling List()
|
// care about such situations, this is a faster alternative to calling List()
|
||||||
// and scanning that output.
|
// and scanning that output.
|
||||||
IsLikelyNotMountPoint(file string) (bool, error)
|
IsLikelyNotMountPoint(file string) (bool, error)
|
||||||
|
// CanSafelySkipMountPointCheck indicates whether this mounter returns errors on
|
||||||
|
// operations for targets that are not mount points. If this returns true, no such
|
||||||
|
// errors will be returned.
|
||||||
|
CanSafelySkipMountPointCheck() bool
|
||||||
|
// IsMountPoint determines if a directory is a mountpoint.
|
||||||
|
// It should return ErrNotExist when the directory does not exist.
|
||||||
|
// IsMountPoint is more expensive than IsLikelyNotMountPoint.
|
||||||
|
// IsMountPoint detects bind mounts in linux.
|
||||||
|
// IsMountPoint may enumerate all the mountpoints using List() and
|
||||||
|
// the list of mountpoints may be large, then it uses
|
||||||
|
// isMountPointMatch to evaluate whether the directory is a mountpoint.
|
||||||
|
IsMountPoint(file string) (bool, error)
|
||||||
// GetMountRefs finds all mount references to pathname, returning a slice of
|
// GetMountRefs finds all mount references to pathname, returning a slice of
|
||||||
// paths. Pathname can be a mountpoint path or a normal directory
|
// paths. Pathname can be a mountpoint path or a normal directory
|
||||||
// (for bind mount). On Linux, pathname is excluded from the slice.
|
// (for bind mount). On Linux, pathname is excluded from the slice.
|
||||||
@ -154,7 +165,15 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string,
|
|||||||
// be used by callers that pass sensitive material (like passwords) as mount
|
// be used by callers that pass sensitive material (like passwords) as mount
|
||||||
// options.
|
// options.
|
||||||
func (mounter *SafeFormatAndMount) FormatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
|
func (mounter *SafeFormatAndMount) FormatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
|
||||||
return mounter.formatAndMountSensitive(source, target, fstype, options, sensitiveOptions)
|
return mounter.FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, nil /* formatOptions */)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatAndMountSensitiveWithFormatOptions behaves exactly the same as
|
||||||
|
// FormatAndMountSensitive, but allows for options to be passed when the disk
|
||||||
|
// is formatted. These options are NOT validated in any way and should never
|
||||||
|
// come directly from untrusted user input as that would be an injection risk.
|
||||||
|
func (mounter *SafeFormatAndMount) FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
|
||||||
|
return mounter.formatAndMountSensitive(source, target, fstype, options, sensitiveOptions, formatOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getMountRefsByDev finds all references to the device provided
|
// getMountRefsByDev finds all references to the device provided
|
||||||
@ -187,6 +206,24 @@ func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
|
|||||||
return refs, nil
|
return refs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNotMountPoint determines if a directory is a mountpoint.
|
||||||
|
// It should return ErrNotExist when the directory does not exist.
|
||||||
|
// IsNotMountPoint is more expensive than IsLikelyNotMountPoint
|
||||||
|
// and depends on IsMountPoint.
|
||||||
|
//
|
||||||
|
// If an error occurs, it returns true (assuming it is not a mountpoint)
|
||||||
|
// when ErrNotExist is returned for callers similar to IsLikelyNotMountPoint.
|
||||||
|
//
|
||||||
|
// Deprecated: This function is kept to keep changes backward compatible with
|
||||||
|
// previous library version. Callers should prefer mounter.IsMountPoint.
|
||||||
|
func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
||||||
|
isMnt, err := mounter.IsMountPoint(file)
|
||||||
|
if err != nil {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
return !isMnt, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetDeviceNameFromMount given a mnt point, find the device from /proc/mounts
|
// GetDeviceNameFromMount given a mnt point, find the device from /proc/mounts
|
||||||
// returns the device name, reference count, and error code.
|
// returns the device name, reference count, and error code.
|
||||||
func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, error) {
|
func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, error) {
|
||||||
@ -220,55 +257,10 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
|
|||||||
return device, refCount, nil
|
return device, refCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotMountPoint determines if a directory is a mountpoint.
|
|
||||||
// It should return ErrNotExist when the directory does not exist.
|
|
||||||
// IsNotMountPoint is more expensive than IsLikelyNotMountPoint.
|
|
||||||
// IsNotMountPoint detects bind mounts in linux.
|
|
||||||
// IsNotMountPoint enumerates all the mountpoints using List() and
|
|
||||||
// the list of mountpoints may be large, then it uses
|
|
||||||
// isMountPointMatch to evaluate whether the directory is a mountpoint.
|
|
||||||
func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
|
||||||
// IsLikelyNotMountPoint provides a quick check
|
|
||||||
// to determine whether file IS A mountpoint.
|
|
||||||
notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
|
|
||||||
if notMntErr != nil && os.IsPermission(notMntErr) {
|
|
||||||
// We were not allowed to do the simple stat() check, e.g. on NFS with
|
|
||||||
// root_squash. Fall back to /proc/mounts check below.
|
|
||||||
notMnt = true
|
|
||||||
notMntErr = nil
|
|
||||||
}
|
|
||||||
if notMntErr != nil {
|
|
||||||
return notMnt, notMntErr
|
|
||||||
}
|
|
||||||
// identified as mountpoint, so return this fact.
|
|
||||||
if notMnt == false {
|
|
||||||
return notMnt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts.
|
|
||||||
resolvedFile, err := filepath.EvalSymlinks(file)
|
|
||||||
if err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// check all mountpoints since IsLikelyNotMountPoint
|
|
||||||
// is not reliable for some mountpoint types.
|
|
||||||
mountPoints, mountPointsErr := mounter.List()
|
|
||||||
if mountPointsErr != nil {
|
|
||||||
return notMnt, mountPointsErr
|
|
||||||
}
|
|
||||||
for _, mp := range mountPoints {
|
|
||||||
if isMountPointMatch(mp, resolvedFile) {
|
|
||||||
notMnt = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return notMnt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeBindOpts detects whether a bind mount is being requested and makes the remount options to
|
// MakeBindOpts detects whether a bind mount is being requested and makes the remount options to
|
||||||
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
|
// use in case of bind mount, due to the fact that bind mount doesn't respect mount options.
|
||||||
// The list equals:
|
// The list equals:
|
||||||
|
//
|
||||||
// options - 'bind' + 'remount' (no duplicate)
|
// options - 'bind' + 'remount' (no duplicate)
|
||||||
func MakeBindOpts(options []string) (bool, []string, []string) {
|
func MakeBindOpts(options []string) (bool, []string, []string) {
|
||||||
bind, bindOpts, bindRemountOpts, _ := MakeBindOptsSensitive(options, nil /* sensitiveOptions */)
|
bind, bindOpts, bindRemountOpts, _ := MakeBindOptsSensitive(options, nil /* sensitiveOptions */)
|
||||||
|
|||||||
66
vendor/k8s.io/mount-utils/mount_helper_common.go
generated
vendored
66
vendor/k8s.io/mount-utils/mount_helper_common.go
generated
vendored
@ -31,7 +31,7 @@ import (
|
|||||||
func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool) error {
|
func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool) error {
|
||||||
pathExists, pathErr := PathExists(mountPath)
|
pathExists, pathErr := PathExists(mountPath)
|
||||||
if !pathExists && pathErr == nil {
|
if !pathExists && pathErr == nil {
|
||||||
klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath)
|
klog.Warningf("Warning: mount cleanup skipped because path does not exist: %v", mountPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
corruptedMnt := IsCorruptedMnt(pathErr)
|
corruptedMnt := IsCorruptedMnt(pathErr)
|
||||||
@ -44,36 +44,41 @@ func CleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointC
|
|||||||
func CleanupMountWithForce(mountPath string, mounter MounterForceUnmounter, extensiveMountPointCheck bool, umountTimeout time.Duration) error {
|
func CleanupMountWithForce(mountPath string, mounter MounterForceUnmounter, extensiveMountPointCheck bool, umountTimeout time.Duration) error {
|
||||||
pathExists, pathErr := PathExists(mountPath)
|
pathExists, pathErr := PathExists(mountPath)
|
||||||
if !pathExists && pathErr == nil {
|
if !pathExists && pathErr == nil {
|
||||||
klog.Warningf("Warning: Unmount skipped because path does not exist: %v", mountPath)
|
klog.Warningf("Warning: mount cleanup skipped because path does not exist: %v", mountPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
corruptedMnt := IsCorruptedMnt(pathErr)
|
corruptedMnt := IsCorruptedMnt(pathErr)
|
||||||
if pathErr != nil && !corruptedMnt {
|
if pathErr != nil && !corruptedMnt {
|
||||||
return fmt.Errorf("Error checking path: %v", pathErr)
|
return fmt.Errorf("Error checking path: %v", pathErr)
|
||||||
}
|
}
|
||||||
var notMnt bool
|
|
||||||
var err error
|
if corruptedMnt || mounter.CanSafelySkipMountPointCheck() {
|
||||||
if !corruptedMnt {
|
klog.V(4).Infof("unmounting %q (corruptedMount: %t, mounterCanSkipMountPointChecks: %t)",
|
||||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
mountPath, corruptedMnt, mounter.CanSafelySkipMountPointCheck())
|
||||||
// if mountPath was not a mount point - we would have attempted to remove mountPath
|
if err := mounter.UnmountWithForce(mountPath, umountTimeout); err != nil {
|
||||||
// and hence return errors if any.
|
return err
|
||||||
|
}
|
||||||
|
return removePath(mountPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
notMnt, err := removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||||
|
// if mountPath is not a mount point, it's just been removed or there was an error
|
||||||
if err != nil || notMnt {
|
if err != nil || notMnt {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Unmount the mount path
|
|
||||||
klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath)
|
klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath)
|
||||||
if err := mounter.UnmountWithForce(mountPath, umountTimeout); err != nil {
|
if err := mounter.UnmountWithForce(mountPath, umountTimeout); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||||
// mountPath is not a mount point we should return whatever error we saw
|
// if mountPath is not a mount point, it's either just been removed or there was an error
|
||||||
if notMnt {
|
if notMnt {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return fmt.Errorf("Failed to unmount path %v", mountPath)
|
// mountPath is still a mount point
|
||||||
|
return fmt.Errorf("failed to cleanup mount point %v", mountPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// doCleanupMountPoint unmounts the given path and
|
// doCleanupMountPoint unmounts the given path and
|
||||||
@ -82,31 +87,35 @@ func CleanupMountWithForce(mountPath string, mounter MounterForceUnmounter, exte
|
|||||||
// IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
|
// IsNotMountPoint will be called instead of IsLikelyNotMountPoint.
|
||||||
// IsNotMountPoint is more expensive but properly handles bind mounts within the same fs.
|
// IsNotMountPoint is more expensive but properly handles bind mounts within the same fs.
|
||||||
// if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, and the mount point check
|
// if corruptedMnt is true, it means that the mountPath is a corrupted mountpoint, and the mount point check
|
||||||
// will be skipped
|
// will be skipped. The mount point check will also be skipped if the mounter supports it.
|
||||||
func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool, corruptedMnt bool) error {
|
func doCleanupMountPoint(mountPath string, mounter Interface, extensiveMountPointCheck bool, corruptedMnt bool) error {
|
||||||
var notMnt bool
|
if corruptedMnt || mounter.CanSafelySkipMountPointCheck() {
|
||||||
var err error
|
klog.V(4).Infof("unmounting %q (corruptedMount: %t, mounterCanSkipMountPointChecks: %t)",
|
||||||
if !corruptedMnt {
|
mountPath, corruptedMnt, mounter.CanSafelySkipMountPointCheck())
|
||||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
if err := mounter.Unmount(mountPath); err != nil {
|
||||||
// if mountPath was not a mount point - we would have attempted to remove mountPath
|
return err
|
||||||
// and hence return errors if any.
|
}
|
||||||
|
return removePath(mountPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
notMnt, err := removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||||
|
// if mountPath is not a mount point, it's just been removed or there was an error
|
||||||
if err != nil || notMnt {
|
if err != nil || notMnt {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Unmount the mount path
|
|
||||||
klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath)
|
klog.V(4).Infof("%q is a mountpoint, unmounting", mountPath)
|
||||||
if err := mounter.Unmount(mountPath); err != nil {
|
if err := mounter.Unmount(mountPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
notMnt, err = removePathIfNotMountPoint(mountPath, mounter, extensiveMountPointCheck)
|
||||||
// mountPath is not a mount point we should return whatever error we saw
|
// if mountPath is not a mount point, it's either just been removed or there was an error
|
||||||
if notMnt {
|
if notMnt {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return fmt.Errorf("Failed to unmount path %v", mountPath)
|
// mountPath is still a mount point
|
||||||
|
return fmt.Errorf("failed to cleanup mount point %v", mountPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// removePathIfNotMountPoint verifies if given mountPath is a mount point if not it attempts
|
// removePathIfNotMountPoint verifies if given mountPath is a mount point if not it attempts
|
||||||
@ -135,3 +144,14 @@ func removePathIfNotMountPoint(mountPath string, mounter Interface, extensiveMou
|
|||||||
}
|
}
|
||||||
return notMnt, nil
|
return notMnt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removePath attempts to remove the directory. Returns nil if the directory was removed or does not exist.
|
||||||
|
func removePath(mountPath string) error {
|
||||||
|
klog.V(4).Infof("Warning: deleting path %q", mountPath)
|
||||||
|
err := os.Remove(mountPath)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
klog.V(4).Infof("%q does not exist", mountPath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
18
vendor/k8s.io/mount-utils/mount_helper_unix.go
generated
vendored
18
vendor/k8s.io/mount-utils/mount_helper_unix.go
generated
vendored
@ -136,7 +136,7 @@ func ParseMountInfo(filename string) ([]MountInfo, error) {
|
|||||||
Minor: minor,
|
Minor: minor,
|
||||||
Root: fields[3],
|
Root: fields[3],
|
||||||
MountPoint: fields[4],
|
MountPoint: fields[4],
|
||||||
MountOptions: strings.Split(fields[5], ","),
|
MountOptions: splitMountOptions(fields[5]),
|
||||||
}
|
}
|
||||||
// All fields until "-" are "optional fields".
|
// All fields until "-" are "optional fields".
|
||||||
i := 6
|
i := 6
|
||||||
@ -150,12 +150,26 @@ func ParseMountInfo(filename string) ([]MountInfo, error) {
|
|||||||
}
|
}
|
||||||
info.FsType = fields[i]
|
info.FsType = fields[i]
|
||||||
info.Source = fields[i+1]
|
info.Source = fields[i+1]
|
||||||
info.SuperOptions = strings.Split(fields[i+2], ",")
|
info.SuperOptions = splitMountOptions(fields[i+2])
|
||||||
infos = append(infos, info)
|
infos = append(infos, info)
|
||||||
}
|
}
|
||||||
return infos, nil
|
return infos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// splitMountOptions parses comma-separated list of mount options into an array.
|
||||||
|
// It respects double quotes - commas in them are not considered as the option separator.
|
||||||
|
func splitMountOptions(s string) []string {
|
||||||
|
inQuotes := false
|
||||||
|
list := strings.FieldsFunc(s, func(r rune) bool {
|
||||||
|
if r == '"' {
|
||||||
|
inQuotes = !inQuotes
|
||||||
|
}
|
||||||
|
// Report a new field only when outside of double quotes.
|
||||||
|
return r == ',' && !inQuotes
|
||||||
|
})
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
// isMountPointMatch returns true if the path in mp is the same as dir.
|
// isMountPointMatch returns true if the path in mp is the same as dir.
|
||||||
// Handles case where mountpoint dir has been renamed due to stale NFS mount.
|
// Handles case where mountpoint dir has been renamed due to stale NFS mount.
|
||||||
func isMountPointMatch(mp MountPoint, dir string) bool {
|
func isMountPointMatch(mp MountPoint, dir string) bool {
|
||||||
|
|||||||
159
vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
159
vendor/k8s.io/mount-utils/mount_linux.go
generated
vendored
@ -21,7 +21,10 @@ package mount
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -30,6 +33,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/moby/sys/mountinfo"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
utilexec "k8s.io/utils/exec"
|
utilexec "k8s.io/utils/exec"
|
||||||
utilio "k8s.io/utils/io"
|
utilio "k8s.io/utils/io"
|
||||||
@ -48,6 +53,8 @@ const (
|
|||||||
fsckErrorsUncorrected = 4
|
fsckErrorsUncorrected = 4
|
||||||
// Error thrown by exec cmd.Run() when process spawned by cmd.Start() completes before cmd.Wait() is called (see - k/k issue #103753)
|
// Error thrown by exec cmd.Run() when process spawned by cmd.Start() completes before cmd.Wait() is called (see - k/k issue #103753)
|
||||||
errNoChildProcesses = "wait: no child processes"
|
errNoChildProcesses = "wait: no child processes"
|
||||||
|
// Error returned by some `umount` implementations when the specified path is not a mount point
|
||||||
|
errNotMounted = "not mounted"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mounter provides the default implementation of mount.Interface
|
// Mounter provides the default implementation of mount.Interface
|
||||||
@ -55,7 +62,9 @@ const (
|
|||||||
// kubelet is running in the host's root mount namespace.
|
// kubelet is running in the host's root mount namespace.
|
||||||
type Mounter struct {
|
type Mounter struct {
|
||||||
mounterPath string
|
mounterPath string
|
||||||
withSystemd bool
|
withSystemd *bool
|
||||||
|
trySystemd bool
|
||||||
|
withSafeNotMountedBehavior bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ MounterForceUnmounter = &Mounter{}
|
var _ MounterForceUnmounter = &Mounter{}
|
||||||
@ -66,10 +75,38 @@ var _ MounterForceUnmounter = &Mounter{}
|
|||||||
func New(mounterPath string) Interface {
|
func New(mounterPath string) Interface {
|
||||||
return &Mounter{
|
return &Mounter{
|
||||||
mounterPath: mounterPath,
|
mounterPath: mounterPath,
|
||||||
withSystemd: detectSystemd(),
|
trySystemd: true,
|
||||||
|
withSafeNotMountedBehavior: detectSafeNotMountedBehavior(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewWithoutSystemd returns a Linux specific mount.Interface for the current
|
||||||
|
// system. It provides options to override the default mounter behavior.
|
||||||
|
// mounterPath allows using an alternative to `/bin/mount` for mounting. Any
|
||||||
|
// detection for systemd functionality is disabled with this Mounter.
|
||||||
|
func NewWithoutSystemd(mounterPath string) Interface {
|
||||||
|
return &Mounter{
|
||||||
|
mounterPath: mounterPath,
|
||||||
|
trySystemd: false,
|
||||||
|
withSafeNotMountedBehavior: detectSafeNotMountedBehavior(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasSystemd validates that the withSystemd bool is set, if it is not,
|
||||||
|
// detectSystemd will be called once for this Mounter instance.
|
||||||
|
func (mounter *Mounter) hasSystemd() bool {
|
||||||
|
if !mounter.trySystemd {
|
||||||
|
mounter.withSystemd = &mounter.trySystemd
|
||||||
|
}
|
||||||
|
|
||||||
|
if mounter.withSystemd == nil {
|
||||||
|
withSystemd := detectSystemd()
|
||||||
|
mounter.withSystemd = &withSystemd
|
||||||
|
}
|
||||||
|
|
||||||
|
return *mounter.withSystemd
|
||||||
|
}
|
||||||
|
|
||||||
// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must
|
// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must
|
||||||
// be an empty string in case it's not required, e.g. for remount, or for auto filesystem
|
// be an empty string in case it's not required, e.g. for remount, or for auto filesystem
|
||||||
// type, where kernel handles fstype for you. The mount 'options' is a list of options,
|
// type, where kernel handles fstype for you. The mount 'options' is a list of options,
|
||||||
@ -90,11 +127,11 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
|||||||
mounterPath := ""
|
mounterPath := ""
|
||||||
bind, bindOpts, bindRemountOpts, bindRemountOptsSensitive := MakeBindOptsSensitive(options, sensitiveOptions)
|
bind, bindOpts, bindRemountOpts, bindRemountOptsSensitive := MakeBindOptsSensitive(options, sensitiveOptions)
|
||||||
if bind {
|
if bind {
|
||||||
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, nil /* mountFlags */, true)
|
err := mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, true)
|
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, nil /* mountFlags */, mounter.trySystemd)
|
||||||
}
|
}
|
||||||
// The list of filesystems that require containerized mounter on GCI image cluster
|
// The list of filesystems that require containerized mounter on GCI image cluster
|
||||||
fsTypesNeedMounter := map[string]struct{}{
|
fsTypesNeedMounter := map[string]struct{}{
|
||||||
@ -106,7 +143,7 @@ func (mounter *Mounter) MountSensitive(source string, target string, fstype stri
|
|||||||
if _, ok := fsTypesNeedMounter[fstype]; ok {
|
if _, ok := fsTypesNeedMounter[fstype]; ok {
|
||||||
mounterPath = mounter.mounterPath
|
mounterPath = mounter.mounterPath
|
||||||
}
|
}
|
||||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options, sensitiveOptions, nil /* mountFlags */, true)
|
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, options, sensitiveOptions, nil /* mountFlags */, mounter.trySystemd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MountSensitiveWithoutSystemd is the same as MountSensitive() but disable using systemd mount.
|
// MountSensitiveWithoutSystemd is the same as MountSensitive() but disable using systemd mount.
|
||||||
@ -149,7 +186,7 @@ func (mounter *Mounter) doMount(mounterPath string, mountCmd string, source stri
|
|||||||
mountCmd = mounterPath
|
mountCmd = mounterPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if mounter.withSystemd && systemdMountRequired {
|
if systemdMountRequired && mounter.hasSystemd() {
|
||||||
// Try to run mount via systemd-run --scope. This will escape the
|
// Try to run mount via systemd-run --scope. This will escape the
|
||||||
// service where kubelet runs and any fuse daemons will be started in a
|
// service where kubelet runs and any fuse daemons will be started in a
|
||||||
// specific scope. kubelet service than can be restarted without killing
|
// specific scope. kubelet service than can be restarted without killing
|
||||||
@ -223,6 +260,36 @@ func detectSystemd() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// detectSafeNotMountedBehavior returns true if the umount implementation replies "not mounted"
|
||||||
|
// when the specified path is not mounted. When not sure (permission errors, ...), it returns false.
|
||||||
|
// When possible, we will trust umount's message and avoid doing our own mount point checks.
|
||||||
|
// More info: https://github.com/util-linux/util-linux/blob/v2.2/mount/umount.c#L179
|
||||||
|
func detectSafeNotMountedBehavior() bool {
|
||||||
|
return detectSafeNotMountedBehaviorWithExec(utilexec.New())
|
||||||
|
}
|
||||||
|
|
||||||
|
// detectSafeNotMountedBehaviorWithExec is for testing with FakeExec.
|
||||||
|
func detectSafeNotMountedBehaviorWithExec(exec utilexec.Interface) bool {
|
||||||
|
// create a temp dir and try to umount it
|
||||||
|
path, err := ioutil.TempDir("", "kubelet-detect-safe-umount")
|
||||||
|
if err != nil {
|
||||||
|
klog.V(4).Infof("Cannot create temp dir to detect safe 'not mounted' behavior: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(path)
|
||||||
|
cmd := exec.Command("umount", path)
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(string(output), errNotMounted) {
|
||||||
|
klog.V(4).Infof("Detected umount with safe 'not mounted' behavior")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
klog.V(4).Infof("'umount %s' failed with: %v, output: %s", path, err, string(output))
|
||||||
|
}
|
||||||
|
klog.V(4).Infof("Detected umount with unsafe 'not mounted' behavior")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// MakeMountArgs makes the arguments to the mount(8) command.
|
// MakeMountArgs makes the arguments to the mount(8) command.
|
||||||
// options MUST not contain sensitive material (like passwords).
|
// options MUST not contain sensitive material (like passwords).
|
||||||
func MakeMountArgs(source, target, fstype string, options []string) (mountArgs []string) {
|
func MakeMountArgs(source, target, fstype string, options []string) (mountArgs []string) {
|
||||||
@ -290,6 +357,7 @@ func AddSystemdScopeSensitive(systemdRunPath, mountName, command string, args []
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unmount unmounts the target.
|
// Unmount unmounts the target.
|
||||||
|
// If the mounter has safe "not mounted" behavior, no error will be returned when the target is not a mount point.
|
||||||
func (mounter *Mounter) Unmount(target string) error {
|
func (mounter *Mounter) Unmount(target string) error {
|
||||||
klog.V(4).Infof("Unmounting %s", target)
|
klog.V(4).Infof("Unmounting %s", target)
|
||||||
command := exec.Command("umount", target)
|
command := exec.Command("umount", target)
|
||||||
@ -303,6 +371,10 @@ func (mounter *Mounter) Unmount(target string) error {
|
|||||||
// Rewrite err with the actual exit error of the process.
|
// Rewrite err with the actual exit error of the process.
|
||||||
err = &exec.ExitError{ProcessState: command.ProcessState}
|
err = &exec.ExitError{ProcessState: command.ProcessState}
|
||||||
}
|
}
|
||||||
|
if mounter.withSafeNotMountedBehavior && strings.Contains(string(output), errNotMounted) {
|
||||||
|
klog.V(4).Infof("ignoring 'not mounted' error for %s", target)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fmt.Errorf("unmount failed: %v\nUnmounting arguments: %s\nOutput: %s", err, target, string(output))
|
return fmt.Errorf("unmount failed: %v\nUnmounting arguments: %s\nOutput: %s", err, target, string(output))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -311,7 +383,7 @@ func (mounter *Mounter) Unmount(target string) error {
|
|||||||
// UnmountWithForce unmounts given target but will retry unmounting with force option
|
// UnmountWithForce unmounts given target but will retry unmounting with force option
|
||||||
// after given timeout.
|
// after given timeout.
|
||||||
func (mounter *Mounter) UnmountWithForce(target string, umountTimeout time.Duration) error {
|
func (mounter *Mounter) UnmountWithForce(target string, umountTimeout time.Duration) error {
|
||||||
err := tryUnmount(target, umountTimeout)
|
err := tryUnmount(mounter, target, umountTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == context.DeadlineExceeded {
|
if err == context.DeadlineExceeded {
|
||||||
klog.V(2).Infof("Timed out waiting for unmount of %s, trying with -f", target)
|
klog.V(2).Infof("Timed out waiting for unmount of %s, trying with -f", target)
|
||||||
@ -351,6 +423,11 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanSafelySkipMountPointCheck relies on the detected behavior of umount when given a target that is not a mount point.
|
||||||
|
func (mounter *Mounter) CanSafelySkipMountPointCheck() bool {
|
||||||
|
return mounter.withSafeNotMountedBehavior
|
||||||
|
}
|
||||||
|
|
||||||
// GetMountRefs finds all mount references to pathname, returns a
|
// GetMountRefs finds all mount references to pathname, returns a
|
||||||
// list of paths. Path could be a mountpoint or a normal
|
// list of paths. Path could be a mountpoint or a normal
|
||||||
// directory (for bind mount).
|
// directory (for bind mount).
|
||||||
@ -387,13 +464,15 @@ func (mounter *SafeFormatAndMount) checkAndRepairFilesystem(source string) error
|
|||||||
return NewMountError(HasFilesystemErrors, "'fsck' found errors on device %s but could not correct them: %s", source, string(out))
|
return NewMountError(HasFilesystemErrors, "'fsck' found errors on device %s but could not correct them: %s", source, string(out))
|
||||||
case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
|
case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
|
||||||
klog.Infof("`fsck` error %s", string(out))
|
klog.Infof("`fsck` error %s", string(out))
|
||||||
|
default:
|
||||||
|
klog.Warningf("fsck on device %s failed with error %v, output: %v", source, err, string(out))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatAndMount uses unix utils to format and mount the given disk
|
// formatAndMount uses unix utils to format and mount the given disk
|
||||||
func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
|
func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
|
||||||
readOnly := false
|
readOnly := false
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
if option == "ro" {
|
if option == "ro" {
|
||||||
@ -445,6 +524,7 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
|||||||
source,
|
source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
args = append(formatOptions, args...)
|
||||||
|
|
||||||
klog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
|
klog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
|
||||||
output, err := mounter.Exec.Command("mkfs."+fstype, args...).CombinedOutput()
|
output, err := mounter.Exec.Command("mkfs."+fstype, args...).CombinedOutput()
|
||||||
@ -637,8 +717,65 @@ func SearchMountPoints(hostSource, mountInfoPath string) ([]string, error) {
|
|||||||
return refs, nil
|
return refs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMountPoint determines if a file is a mountpoint.
|
||||||
|
// It first detects bind & any other mountpoints using
|
||||||
|
// MountedFast function. If the MountedFast function returns
|
||||||
|
// sure as true and err as nil, then a mountpoint is detected
|
||||||
|
// successfully. When an error is returned by MountedFast, the
|
||||||
|
// following is true:
|
||||||
|
// 1. All errors are returned with IsMountPoint as false
|
||||||
|
// except os.IsPermission.
|
||||||
|
// 2. When os.IsPermission is returned by MountedFast, List()
|
||||||
|
// is called to confirm if the given file is a mountpoint are not.
|
||||||
|
//
|
||||||
|
// os.ErrNotExist should always be returned if a file does not exist
|
||||||
|
// as callers have in past relied on this error and not fallback.
|
||||||
|
//
|
||||||
|
// When MountedFast returns sure as false and err as nil (eg: in
|
||||||
|
// case of bindmounts on kernel version 5.10- ); mounter.List()
|
||||||
|
// endpoint is called to enumerate all the mountpoints and check if
|
||||||
|
// it is mountpoint match or not.
|
||||||
|
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||||
|
isMnt, sure, isMntErr := mountinfo.MountedFast(file)
|
||||||
|
if sure && isMntErr == nil {
|
||||||
|
return isMnt, nil
|
||||||
|
}
|
||||||
|
if isMntErr != nil {
|
||||||
|
if errors.Is(isMntErr, fs.ErrNotExist) {
|
||||||
|
return false, fs.ErrNotExist
|
||||||
|
}
|
||||||
|
// We were not allowed to do the simple stat() check, e.g. on NFS with
|
||||||
|
// root_squash. Fall back to /proc/mounts check below when
|
||||||
|
// fs.ErrPermission is returned.
|
||||||
|
if !errors.Is(isMntErr, fs.ErrPermission) {
|
||||||
|
return false, isMntErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts.
|
||||||
|
resolvedFile, err := filepath.EvalSymlinks(file)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(isMntErr, fs.ErrNotExist) {
|
||||||
|
return false, fs.ErrNotExist
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check all mountpoints since MountedFast is not sure.
|
||||||
|
// is not reliable for some mountpoint types.
|
||||||
|
mountPoints, mountPointsErr := mounter.List()
|
||||||
|
if mountPointsErr != nil {
|
||||||
|
return false, mountPointsErr
|
||||||
|
}
|
||||||
|
for _, mp := range mountPoints {
|
||||||
|
if isMountPointMatch(mp, resolvedFile) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
// tryUnmount calls plain "umount" and waits for unmountTimeout for it to finish.
|
// tryUnmount calls plain "umount" and waits for unmountTimeout for it to finish.
|
||||||
func tryUnmount(path string, unmountTimeout time.Duration) error {
|
func tryUnmount(mounter *Mounter, path string, unmountTimeout time.Duration) error {
|
||||||
klog.V(4).Infof("Unmounting %s", path)
|
klog.V(4).Infof("Unmounting %s", path)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), unmountTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), unmountTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -653,6 +790,10 @@ func tryUnmount(path string, unmountTimeout time.Duration) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cmderr != nil {
|
if cmderr != nil {
|
||||||
|
if mounter.withSafeNotMountedBehavior && strings.Contains(string(out), errNotMounted) {
|
||||||
|
klog.V(4).Infof("ignoring 'not mounted' error for %s", path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fmt.Errorf("unmount failed: %v\nUnmounting arguments: %s\nOutput: %s", cmderr, path, string(out))
|
return fmt.Errorf("unmount failed: %v\nUnmounting arguments: %s\nOutput: %s", cmderr, path, string(out))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
19
vendor/k8s.io/mount-utils/mount_unsupported.go
generated
vendored
19
vendor/k8s.io/mount-utils/mount_unsupported.go
generated
vendored
@ -74,15 +74,32 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||||||
return true, errUnsupported
|
return true, errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanSafelySkipMountPointCheck always returns false on unsupported platforms
|
||||||
|
func (mounter *Mounter) CanSafelySkipMountPointCheck() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMountPoint determines if a directory is a mountpoint.
|
||||||
|
// It always returns an error on unsupported platforms.
|
||||||
|
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||||
|
return false, errUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
// GetMountRefs always returns an error on unsupported platforms
|
// GetMountRefs always returns an error on unsupported platforms
|
||||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||||
return nil, errUnsupported
|
return nil, errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
|
func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
|
||||||
return mounter.Interface.Mount(source, target, fstype, options)
|
return mounter.Interface.Mount(source, target, fstype, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
|
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
|
||||||
return true, errUnsupported
|
return true, errUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMountPoint determines if a directory is a mountpoint.
|
||||||
|
// It always returns an error on unsupported platforms.
|
||||||
|
func (mounter *SafeFormatAndMount) IsMountPoint(file string) (bool, error) {
|
||||||
|
return false, errUnsupported
|
||||||
|
}
|
||||||
|
|||||||
22
vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
22
vendor/k8s.io/mount-utils/mount_windows.go
generated
vendored
@ -244,6 +244,20 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanSafelySkipMountPointCheck always returns false on Windows
|
||||||
|
func (mounter *Mounter) CanSafelySkipMountPointCheck() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMountPoint: determines if a directory is a mountpoint.
|
||||||
|
func (mounter *Mounter) IsMountPoint(file string) (bool, error) {
|
||||||
|
isNotMnt, err := mounter.IsLikelyNotMountPoint(file)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return !isNotMnt, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetMountRefs : empty implementation here since there is no place to query all mount points on Windows
|
// GetMountRefs : empty implementation here since there is no place to query all mount points on Windows
|
||||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||||
windowsPath := NormalizeWindowsPath(pathname)
|
windowsPath := NormalizeWindowsPath(pathname)
|
||||||
@ -259,7 +273,7 @@ func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
|||||||
return []string{pathname}, nil
|
return []string{pathname}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
|
func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
|
||||||
// Try to mount the disk
|
// Try to mount the disk
|
||||||
klog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target)
|
klog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target)
|
||||||
|
|
||||||
@ -274,8 +288,12 @@ func (mounter *SafeFormatAndMount) formatAndMountSensitive(source string, target
|
|||||||
}
|
}
|
||||||
|
|
||||||
// format disk if it is unformatted(raw)
|
// format disk if it is unformatted(raw)
|
||||||
|
formatOptionsUnwrapped := ""
|
||||||
|
if len(formatOptions) > 0 {
|
||||||
|
formatOptionsUnwrapped = " " + strings.Join(formatOptions, " ")
|
||||||
|
}
|
||||||
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle GPT -PassThru"+
|
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle GPT -PassThru"+
|
||||||
" | New-Partition -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype)
|
" | New-Partition -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false%s", source, fstype, formatOptionsUnwrapped)
|
||||||
if output, err := mounter.Exec.Command("powershell", "/c", cmd).CombinedOutput(); err != nil {
|
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))
|
return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output))
|
||||||
}
|
}
|
||||||
|
|||||||
81
vendor/k8s.io/mount-utils/resizefs_linux.go
generated
vendored
81
vendor/k8s.io/mount-utils/resizefs_linux.go
generated
vendored
@ -28,6 +28,10 @@ import (
|
|||||||
utilexec "k8s.io/utils/exec"
|
utilexec "k8s.io/utils/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
blockDev = "blockdev"
|
||||||
|
)
|
||||||
|
|
||||||
// ResizeFs Provides support for resizing file systems
|
// ResizeFs Provides support for resizing file systems
|
||||||
type ResizeFs struct {
|
type ResizeFs struct {
|
||||||
exec utilexec.Interface
|
exec utilexec.Interface
|
||||||
@ -104,6 +108,17 @@ func (resizefs *ResizeFs) btrfsResize(deviceMountPath string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (resizefs *ResizeFs) NeedResize(devicePath string, deviceMountPath string) (bool, error) {
|
func (resizefs *ResizeFs) NeedResize(devicePath string, deviceMountPath string) (bool, error) {
|
||||||
|
// Do nothing if device is mounted as readonly
|
||||||
|
readonly, err := resizefs.getDeviceRO(devicePath)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if readonly {
|
||||||
|
klog.V(3).Infof("ResizeFs.needResize - no resize possible since filesystem %s is readonly", devicePath)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
deviceSize, err := resizefs.getDeviceSize(devicePath)
|
deviceSize, err := resizefs.getDeviceSize(devicePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -129,6 +144,9 @@ func (resizefs *ResizeFs) NeedResize(devicePath string, deviceMountPath string)
|
|||||||
case "xfs":
|
case "xfs":
|
||||||
blockSize, fsSize, err = resizefs.getXFSSize(deviceMountPath)
|
blockSize, fsSize, err = resizefs.getXFSSize(deviceMountPath)
|
||||||
klog.V(5).Infof("Xfs size: filesystem size=%d, block size=%d, err=%v", fsSize, blockSize, err)
|
klog.V(5).Infof("Xfs size: filesystem size=%d, block size=%d, err=%v", fsSize, blockSize, err)
|
||||||
|
case "btrfs":
|
||||||
|
blockSize, fsSize, err = resizefs.getBtrfsSize(devicePath)
|
||||||
|
klog.V(5).Infof("Btrfs size: filesystem size=%d, block size=%d, err=%v", fsSize, blockSize, err)
|
||||||
default:
|
default:
|
||||||
klog.Errorf("Not able to parse given filesystem info. fsType: %s, will not resize", format)
|
klog.Errorf("Not able to parse given filesystem info. fsType: %s, will not resize", format)
|
||||||
return false, fmt.Errorf("Could not parse fs info on given filesystem format: %s. Supported fs types are: xfs, ext3, ext4", format)
|
return false, fmt.Errorf("Could not parse fs info on given filesystem format: %s. Supported fs types are: xfs, ext3, ext4", format)
|
||||||
@ -144,7 +162,7 @@ func (resizefs *ResizeFs) NeedResize(devicePath string, deviceMountPath string)
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
func (resizefs *ResizeFs) getDeviceSize(devicePath string) (uint64, error) {
|
func (resizefs *ResizeFs) getDeviceSize(devicePath string) (uint64, error) {
|
||||||
output, err := resizefs.exec.Command("blockdev", "--getsize64", devicePath).CombinedOutput()
|
output, err := resizefs.exec.Command(blockDev, "--getsize64", devicePath).CombinedOutput()
|
||||||
outStr := strings.TrimSpace(string(output))
|
outStr := strings.TrimSpace(string(output))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("failed to read size of device %s: %s: %s", devicePath, err, outStr)
|
return 0, fmt.Errorf("failed to read size of device %s: %s: %s", devicePath, err, outStr)
|
||||||
@ -156,6 +174,22 @@ func (resizefs *ResizeFs) getDeviceSize(devicePath string) (uint64, error) {
|
|||||||
return size, nil
|
return size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (resizefs *ResizeFs) getDeviceRO(devicePath string) (bool, error) {
|
||||||
|
output, err := resizefs.exec.Command(blockDev, "--getro", devicePath).CombinedOutput()
|
||||||
|
outStr := strings.TrimSpace(string(output))
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to get readonly bit from device %s: %s: %s", devicePath, err, outStr)
|
||||||
|
}
|
||||||
|
switch outStr {
|
||||||
|
case "0":
|
||||||
|
return false, nil
|
||||||
|
case "1":
|
||||||
|
return true, nil
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("Failed readonly device check. Expected 1 or 0, got '%s'", outStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (resizefs *ResizeFs) getExtSize(devicePath string) (uint64, uint64, error) {
|
func (resizefs *ResizeFs) getExtSize(devicePath string) (uint64, uint64, error) {
|
||||||
output, err := resizefs.exec.Command("dumpe2fs", "-h", devicePath).CombinedOutput()
|
output, err := resizefs.exec.Command("dumpe2fs", "-h", devicePath).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -190,6 +224,51 @@ func (resizefs *ResizeFs) getXFSSize(devicePath string) (uint64, uint64, error)
|
|||||||
return blockSize, blockSize * blockCount, nil
|
return blockSize, blockSize * blockCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (resizefs *ResizeFs) getBtrfsSize(devicePath string) (uint64, uint64, error) {
|
||||||
|
output, err := resizefs.exec.Command("btrfs", "inspect-internal", "dump-super", "-f", devicePath).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("failed to read size of filesystem on %s: %s: %s", devicePath, err, string(output))
|
||||||
|
}
|
||||||
|
|
||||||
|
blockSize, totalBytes, _ := resizefs.parseBtrfsInfoOutput(string(output), "sectorsize", "total_bytes")
|
||||||
|
|
||||||
|
if blockSize == 0 {
|
||||||
|
return 0, 0, fmt.Errorf("could not find block size of device %s", devicePath)
|
||||||
|
}
|
||||||
|
if totalBytes == 0 {
|
||||||
|
return 0, 0, fmt.Errorf("could not find total size of device %s", devicePath)
|
||||||
|
}
|
||||||
|
return blockSize, totalBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (resizefs *ResizeFs) parseBtrfsInfoOutput(cmdOutput string, blockSizeKey string, totalBytesKey string) (uint64, uint64, error) {
|
||||||
|
lines := strings.Split(cmdOutput, "\n")
|
||||||
|
var blockSize, blockCount uint64
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
tokens := strings.Fields(line)
|
||||||
|
if len(tokens) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key, value := strings.ToLower(strings.TrimSpace(tokens[0])), strings.ToLower(strings.TrimSpace(tokens[1]))
|
||||||
|
|
||||||
|
if key == blockSizeKey {
|
||||||
|
blockSize, err = strconv.ParseUint(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("failed to parse block size %s: %s", value, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if key == totalBytesKey {
|
||||||
|
blockCount, err = strconv.ParseUint(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("failed to parse total size %s: %s", value, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return blockSize, blockCount, err
|
||||||
|
}
|
||||||
|
|
||||||
func (resizefs *ResizeFs) parseFsInfoOutput(cmdOutput string, spliter string, blockSizeKey string, blockCountKey string) (uint64, uint64, error) {
|
func (resizefs *ResizeFs) parseFsInfoOutput(cmdOutput string, spliter string, blockSizeKey string, blockCountKey string) (uint64, uint64, error) {
|
||||||
lines := strings.Split(cmdOutput, "\n")
|
lines := strings.Split(cmdOutput, "\n")
|
||||||
var blockSize, blockCount uint64
|
var blockSize, blockCount uint64
|
||||||
|
|||||||
5
vendor/k8s.io/mount-utils/resizefs_unsupported.go
generated
vendored
5
vendor/k8s.io/mount-utils/resizefs_unsupported.go
generated
vendored
@ -39,3 +39,8 @@ func NewResizeFs(exec utilexec.Interface) *ResizeFs {
|
|||||||
func (resizefs *ResizeFs) Resize(devicePath string, deviceMountPath string) (bool, error) {
|
func (resizefs *ResizeFs) Resize(devicePath string, deviceMountPath string) (bool, error) {
|
||||||
return false, fmt.Errorf("Resize is not supported for this build")
|
return false, fmt.Errorf("Resize is not supported for this build")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NeedResize check whether mounted volume needs resize
|
||||||
|
func (resizefs *ResizeFs) NeedResize(devicePath string, deviceMountPath string) (bool, error) {
|
||||||
|
return false, fmt.Errorf("NeedResize is not supported for this build")
|
||||||
|
}
|
||||||
|
|||||||
10
vendor/k8s.io/utils/clock/clock.go
generated
vendored
10
vendor/k8s.io/utils/clock/clock.go
generated
vendored
@ -63,6 +63,16 @@ type WithDelayedExecution interface {
|
|||||||
AfterFunc(d time.Duration, f func()) Timer
|
AfterFunc(d time.Duration, f func()) Timer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithTickerAndDelayedExecution allows for injecting fake or real clocks
|
||||||
|
// into code that needs Ticker and AfterFunc functionality
|
||||||
|
type WithTickerAndDelayedExecution interface {
|
||||||
|
WithTicker
|
||||||
|
// AfterFunc executes f in its own goroutine after waiting
|
||||||
|
// for d duration and returns a Timer whose channel can be
|
||||||
|
// closed by calling Stop() on the Timer.
|
||||||
|
AfterFunc(d time.Duration, f func()) Timer
|
||||||
|
}
|
||||||
|
|
||||||
// Ticker defines the Ticker interface.
|
// Ticker defines the Ticker interface.
|
||||||
type Ticker interface {
|
type Ticker interface {
|
||||||
C() <-chan time.Time
|
C() <-chan time.Time
|
||||||
|
|||||||
9
vendor/k8s.io/utils/clock/testing/fake_clock.go
generated
vendored
9
vendor/k8s.io/utils/clock/testing/fake_clock.go
generated
vendored
@ -239,7 +239,8 @@ func (f *FakeClock) Sleep(d time.Duration) {
|
|||||||
|
|
||||||
// IntervalClock implements clock.PassiveClock, but each invocation of Now steps the clock forward the specified duration.
|
// IntervalClock implements clock.PassiveClock, but each invocation of Now steps the clock forward the specified duration.
|
||||||
// IntervalClock technically implements the other methods of clock.Clock, but each implementation is just a panic.
|
// IntervalClock technically implements the other methods of clock.Clock, but each implementation is just a panic.
|
||||||
// See SimpleIntervalClock for an alternative that only has the methods of PassiveClock.
|
//
|
||||||
|
// Deprecated: See SimpleIntervalClock for an alternative that only has the methods of PassiveClock.
|
||||||
type IntervalClock struct {
|
type IntervalClock struct {
|
||||||
Time time.Time
|
Time time.Time
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
@ -282,9 +283,9 @@ func (*IntervalClock) Tick(d time.Duration) <-chan time.Time {
|
|||||||
|
|
||||||
// NewTicker has no implementation yet and is omitted.
|
// NewTicker has no implementation yet and is omitted.
|
||||||
// TODO: make interval clock use FakeClock so this can be implemented.
|
// TODO: make interval clock use FakeClock so this can be implemented.
|
||||||
//func (*IntervalClock) NewTicker(d time.Duration) clock.Ticker {
|
func (*IntervalClock) NewTicker(d time.Duration) clock.Ticker {
|
||||||
// panic("IntervalClock doesn't implement NewTicker")
|
panic("IntervalClock doesn't implement NewTicker")
|
||||||
//}
|
}
|
||||||
|
|
||||||
// Sleep is unimplemented, will panic.
|
// Sleep is unimplemented, will panic.
|
||||||
func (*IntervalClock) Sleep(d time.Duration) {
|
func (*IntervalClock) Sleep(d time.Duration) {
|
||||||
|
|||||||
10
vendor/k8s.io/utils/exec/exec.go
generated
vendored
10
vendor/k8s.io/utils/exec/exec.go
generated
vendored
@ -19,6 +19,7 @@ package exec
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
osexec "os/exec"
|
osexec "os/exec"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@ -98,17 +99,18 @@ func New() Interface {
|
|||||||
|
|
||||||
// Command is part of the Interface interface.
|
// Command is part of the Interface interface.
|
||||||
func (executor *executor) Command(cmd string, args ...string) Cmd {
|
func (executor *executor) Command(cmd string, args ...string) Cmd {
|
||||||
return (*cmdWrapper)(osexec.Command(cmd, args...))
|
return (*cmdWrapper)(maskErrDotCmd(osexec.Command(cmd, args...)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandContext is part of the Interface interface.
|
// CommandContext is part of the Interface interface.
|
||||||
func (executor *executor) CommandContext(ctx context.Context, cmd string, args ...string) Cmd {
|
func (executor *executor) CommandContext(ctx context.Context, cmd string, args ...string) Cmd {
|
||||||
return (*cmdWrapper)(osexec.CommandContext(ctx, cmd, args...))
|
return (*cmdWrapper)(maskErrDotCmd(osexec.CommandContext(ctx, cmd, args...)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookPath is part of the Interface interface
|
// LookPath is part of the Interface interface
|
||||||
func (executor *executor) LookPath(file string) (string, error) {
|
func (executor *executor) LookPath(file string) (string, error) {
|
||||||
return osexec.LookPath(file)
|
path, err := osexec.LookPath(file)
|
||||||
|
return path, handleError(maskErrDot(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps exec.Cmd so we can capture errors.
|
// Wraps exec.Cmd so we can capture errors.
|
||||||
@ -198,6 +200,8 @@ func handleError(err error) error {
|
|||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case *osexec.ExitError:
|
case *osexec.ExitError:
|
||||||
return &ExitErrorWrapper{e}
|
return &ExitErrorWrapper{e}
|
||||||
|
case *fs.PathError:
|
||||||
|
return ErrExecutableNotFound
|
||||||
case *osexec.Error:
|
case *osexec.Error:
|
||||||
if e.Err == osexec.ErrNotFound {
|
if e.Err == osexec.ErrNotFound {
|
||||||
return ErrExecutableNotFound
|
return ErrExecutableNotFound
|
||||||
|
|||||||
32
vendor/k8s.io/utils/exec/fixup_go118.go
generated
vendored
Normal file
32
vendor/k8s.io/utils/exec/fixup_go118.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//go:build !go1.19
|
||||||
|
// +build !go1.19
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2022 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 exec
|
||||||
|
|
||||||
|
import (
|
||||||
|
osexec "os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func maskErrDotCmd(cmd *osexec.Cmd) *osexec.Cmd {
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func maskErrDot(err error) error {
|
||||||
|
return err
|
||||||
|
}
|
||||||
40
vendor/k8s.io/utils/exec/fixup_go119.go
generated
vendored
Normal file
40
vendor/k8s.io/utils/exec/fixup_go119.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//go:build go1.19
|
||||||
|
// +build go1.19
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2022 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 exec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
osexec "os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// maskErrDotCmd reverts the behavior of osexec.Cmd to what it was before go1.19
|
||||||
|
// specifically set the Err field to nil (LookPath returns a new error when the file
|
||||||
|
// is resolved to the current directory.
|
||||||
|
func maskErrDotCmd(cmd *osexec.Cmd) *osexec.Cmd {
|
||||||
|
cmd.Err = maskErrDot(cmd.Err)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func maskErrDot(err error) error {
|
||||||
|
if err != nil && errors.Is(err, osexec.ErrDot) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
1
vendor/k8s.io/utils/nsenter/nsenter.go
generated
vendored
1
vendor/k8s.io/utils/nsenter/nsenter.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
1
vendor/k8s.io/utils/nsenter/nsenter_unsupported.go
generated
vendored
1
vendor/k8s.io/utils/nsenter/nsenter_unsupported.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
169
vendor/k8s.io/utils/pointer/pointer.go
generated
vendored
169
vendor/k8s.io/utils/pointer/pointer.go
generated
vendored
@ -19,6 +19,7 @@ package pointer
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AllPtrFieldsNil tests whether all pointer fields in a struct are nil. This is useful when,
|
// AllPtrFieldsNil tests whether all pointer fields in a struct are nil. This is useful when,
|
||||||
@ -51,6 +52,9 @@ func Int(i int) *int {
|
|||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IntPtr is a function variable referring to Int.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Int instead.
|
||||||
var IntPtr = Int // for back-compat
|
var IntPtr = Int // for back-compat
|
||||||
|
|
||||||
// IntDeref dereferences the int ptr and returns it if not nil, or else
|
// IntDeref dereferences the int ptr and returns it if not nil, or else
|
||||||
@ -62,6 +66,9 @@ func IntDeref(ptr *int, def int) int {
|
|||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IntPtrDerefOr is a function variable referring to IntDeref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use IntDeref instead.
|
||||||
var IntPtrDerefOr = IntDeref // for back-compat
|
var IntPtrDerefOr = IntDeref // for back-compat
|
||||||
|
|
||||||
// Int32 returns a pointer to an int32.
|
// Int32 returns a pointer to an int32.
|
||||||
@ -69,6 +76,9 @@ func Int32(i int32) *int32 {
|
|||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Int32Ptr is a function variable referring to Int32.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Int32 instead.
|
||||||
var Int32Ptr = Int32 // for back-compat
|
var Int32Ptr = Int32 // for back-compat
|
||||||
|
|
||||||
// Int32Deref dereferences the int32 ptr and returns it if not nil, or else
|
// Int32Deref dereferences the int32 ptr and returns it if not nil, or else
|
||||||
@ -80,6 +90,9 @@ func Int32Deref(ptr *int32, def int32) int32 {
|
|||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Int32PtrDerefOr is a function variable referring to Int32Deref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Int32Deref instead.
|
||||||
var Int32PtrDerefOr = Int32Deref // for back-compat
|
var Int32PtrDerefOr = Int32Deref // for back-compat
|
||||||
|
|
||||||
// Int32Equal returns true if both arguments are nil or both arguments
|
// Int32Equal returns true if both arguments are nil or both arguments
|
||||||
@ -94,11 +107,74 @@ func Int32Equal(a, b *int32) bool {
|
|||||||
return *a == *b
|
return *a == *b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uint returns a pointer to an uint
|
||||||
|
func Uint(i uint) *uint {
|
||||||
|
return &i
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintPtr is a function variable referring to Uint.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Uint instead.
|
||||||
|
var UintPtr = Uint // for back-compat
|
||||||
|
|
||||||
|
// UintDeref dereferences the uint ptr and returns it if not nil, or else
|
||||||
|
// returns def.
|
||||||
|
func UintDeref(ptr *uint, def uint) uint {
|
||||||
|
if ptr != nil {
|
||||||
|
return *ptr
|
||||||
|
}
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintPtrDerefOr is a function variable referring to UintDeref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use UintDeref instead.
|
||||||
|
var UintPtrDerefOr = UintDeref // for back-compat
|
||||||
|
|
||||||
|
// Uint32 returns a pointer to an uint32.
|
||||||
|
func Uint32(i uint32) *uint32 {
|
||||||
|
return &i
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint32Ptr is a function variable referring to Uint32.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Uint32 instead.
|
||||||
|
var Uint32Ptr = Uint32 // for back-compat
|
||||||
|
|
||||||
|
// Uint32Deref dereferences the uint32 ptr and returns it if not nil, or else
|
||||||
|
// returns def.
|
||||||
|
func Uint32Deref(ptr *uint32, def uint32) uint32 {
|
||||||
|
if ptr != nil {
|
||||||
|
return *ptr
|
||||||
|
}
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint32PtrDerefOr is a function variable referring to Uint32Deref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Uint32Deref instead.
|
||||||
|
var Uint32PtrDerefOr = Uint32Deref // for back-compat
|
||||||
|
|
||||||
|
// Uint32Equal returns true if both arguments are nil or both arguments
|
||||||
|
// dereference to the same value.
|
||||||
|
func Uint32Equal(a, b *uint32) bool {
|
||||||
|
if (a == nil) != (b == nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return *a == *b
|
||||||
|
}
|
||||||
|
|
||||||
// Int64 returns a pointer to an int64.
|
// Int64 returns a pointer to an int64.
|
||||||
func Int64(i int64) *int64 {
|
func Int64(i int64) *int64 {
|
||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Int64Ptr is a function variable referring to Int64.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Int64 instead.
|
||||||
var Int64Ptr = Int64 // for back-compat
|
var Int64Ptr = Int64 // for back-compat
|
||||||
|
|
||||||
// Int64Deref dereferences the int64 ptr and returns it if not nil, or else
|
// Int64Deref dereferences the int64 ptr and returns it if not nil, or else
|
||||||
@ -110,6 +186,9 @@ func Int64Deref(ptr *int64, def int64) int64 {
|
|||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Int64PtrDerefOr is a function variable referring to Int64Deref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Int64Deref instead.
|
||||||
var Int64PtrDerefOr = Int64Deref // for back-compat
|
var Int64PtrDerefOr = Int64Deref // for back-compat
|
||||||
|
|
||||||
// Int64Equal returns true if both arguments are nil or both arguments
|
// Int64Equal returns true if both arguments are nil or both arguments
|
||||||
@ -124,11 +203,50 @@ func Int64Equal(a, b *int64) bool {
|
|||||||
return *a == *b
|
return *a == *b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uint64 returns a pointer to an uint64.
|
||||||
|
func Uint64(i uint64) *uint64 {
|
||||||
|
return &i
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64Ptr is a function variable referring to Uint64.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Uint64 instead.
|
||||||
|
var Uint64Ptr = Uint64 // for back-compat
|
||||||
|
|
||||||
|
// Uint64Deref dereferences the uint64 ptr and returns it if not nil, or else
|
||||||
|
// returns def.
|
||||||
|
func Uint64Deref(ptr *uint64, def uint64) uint64 {
|
||||||
|
if ptr != nil {
|
||||||
|
return *ptr
|
||||||
|
}
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64PtrDerefOr is a function variable referring to Uint64Deref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Uint64Deref instead.
|
||||||
|
var Uint64PtrDerefOr = Uint64Deref // for back-compat
|
||||||
|
|
||||||
|
// Uint64Equal returns true if both arguments are nil or both arguments
|
||||||
|
// dereference to the same value.
|
||||||
|
func Uint64Equal(a, b *uint64) bool {
|
||||||
|
if (a == nil) != (b == nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return *a == *b
|
||||||
|
}
|
||||||
|
|
||||||
// Bool returns a pointer to a bool.
|
// Bool returns a pointer to a bool.
|
||||||
func Bool(b bool) *bool {
|
func Bool(b bool) *bool {
|
||||||
return &b
|
return &b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoolPtr is a function variable referring to Bool.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Bool instead.
|
||||||
var BoolPtr = Bool // for back-compat
|
var BoolPtr = Bool // for back-compat
|
||||||
|
|
||||||
// BoolDeref dereferences the bool ptr and returns it if not nil, or else
|
// BoolDeref dereferences the bool ptr and returns it if not nil, or else
|
||||||
@ -140,6 +258,9 @@ func BoolDeref(ptr *bool, def bool) bool {
|
|||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoolPtrDerefOr is a function variable referring to BoolDeref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use BoolDeref instead.
|
||||||
var BoolPtrDerefOr = BoolDeref // for back-compat
|
var BoolPtrDerefOr = BoolDeref // for back-compat
|
||||||
|
|
||||||
// BoolEqual returns true if both arguments are nil or both arguments
|
// BoolEqual returns true if both arguments are nil or both arguments
|
||||||
@ -159,6 +280,9 @@ func String(s string) *string {
|
|||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringPtr is a function variable referring to String.
|
||||||
|
//
|
||||||
|
// Deprecated: Use String instead.
|
||||||
var StringPtr = String // for back-compat
|
var StringPtr = String // for back-compat
|
||||||
|
|
||||||
// StringDeref dereferences the string ptr and returns it if not nil, or else
|
// StringDeref dereferences the string ptr and returns it if not nil, or else
|
||||||
@ -170,6 +294,9 @@ func StringDeref(ptr *string, def string) string {
|
|||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringPtrDerefOr is a function variable referring to StringDeref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use StringDeref instead.
|
||||||
var StringPtrDerefOr = StringDeref // for back-compat
|
var StringPtrDerefOr = StringDeref // for back-compat
|
||||||
|
|
||||||
// StringEqual returns true if both arguments are nil or both arguments
|
// StringEqual returns true if both arguments are nil or both arguments
|
||||||
@ -184,11 +311,14 @@ func StringEqual(a, b *string) bool {
|
|||||||
return *a == *b
|
return *a == *b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float32 returns a pointer to the a float32.
|
// Float32 returns a pointer to a float32.
|
||||||
func Float32(i float32) *float32 {
|
func Float32(i float32) *float32 {
|
||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Float32Ptr is a function variable referring to Float32.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Float32 instead.
|
||||||
var Float32Ptr = Float32
|
var Float32Ptr = Float32
|
||||||
|
|
||||||
// Float32Deref dereferences the float32 ptr and returns it if not nil, or else
|
// Float32Deref dereferences the float32 ptr and returns it if not nil, or else
|
||||||
@ -200,6 +330,9 @@ func Float32Deref(ptr *float32, def float32) float32 {
|
|||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Float32PtrDerefOr is a function variable referring to Float32Deref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Float32Deref instead.
|
||||||
var Float32PtrDerefOr = Float32Deref // for back-compat
|
var Float32PtrDerefOr = Float32Deref // for back-compat
|
||||||
|
|
||||||
// Float32Equal returns true if both arguments are nil or both arguments
|
// Float32Equal returns true if both arguments are nil or both arguments
|
||||||
@ -214,11 +347,14 @@ func Float32Equal(a, b *float32) bool {
|
|||||||
return *a == *b
|
return *a == *b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float64 returns a pointer to the a float64.
|
// Float64 returns a pointer to a float64.
|
||||||
func Float64(i float64) *float64 {
|
func Float64(i float64) *float64 {
|
||||||
return &i
|
return &i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Float64Ptr is a function variable referring to Float64.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Float64 instead.
|
||||||
var Float64Ptr = Float64
|
var Float64Ptr = Float64
|
||||||
|
|
||||||
// Float64Deref dereferences the float64 ptr and returns it if not nil, or else
|
// Float64Deref dereferences the float64 ptr and returns it if not nil, or else
|
||||||
@ -230,6 +366,9 @@ func Float64Deref(ptr *float64, def float64) float64 {
|
|||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Float64PtrDerefOr is a function variable referring to Float64Deref.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Float64Deref instead.
|
||||||
var Float64PtrDerefOr = Float64Deref // for back-compat
|
var Float64PtrDerefOr = Float64Deref // for back-compat
|
||||||
|
|
||||||
// Float64Equal returns true if both arguments are nil or both arguments
|
// Float64Equal returns true if both arguments are nil or both arguments
|
||||||
@ -243,3 +382,29 @@ func Float64Equal(a, b *float64) bool {
|
|||||||
}
|
}
|
||||||
return *a == *b
|
return *a == *b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Duration returns a pointer to a time.Duration.
|
||||||
|
func Duration(d time.Duration) *time.Duration {
|
||||||
|
return &d
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationDeref dereferences the time.Duration ptr and returns it if not nil, or else
|
||||||
|
// returns def.
|
||||||
|
func DurationDeref(ptr *time.Duration, def time.Duration) time.Duration {
|
||||||
|
if ptr != nil {
|
||||||
|
return *ptr
|
||||||
|
}
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationEqual returns true if both arguments are nil or both arguments
|
||||||
|
// dereference to the same value.
|
||||||
|
func DurationEqual(a, b *time.Duration) bool {
|
||||||
|
if (a == nil) != (b == nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return *a == *b
|
||||||
|
}
|
||||||
|
|||||||
24
vendor/k8s.io/utils/trace/trace.go
generated
vendored
24
vendor/k8s.io/utils/trace/trace.go
generated
vendored
@ -21,6 +21,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
@ -93,13 +94,16 @@ func (s traceStep) writeItem(b *bytes.Buffer, formatter string, startTime time.T
|
|||||||
// Trace keeps track of a set of "steps" and allows us to log a specific
|
// 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
|
// step if it took longer than its share of the total allowed time
|
||||||
type Trace struct {
|
type Trace struct {
|
||||||
|
// constant fields
|
||||||
name string
|
name string
|
||||||
fields []Field
|
fields []Field
|
||||||
threshold *time.Duration
|
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
|
parentTrace *Trace
|
||||||
|
// fields guarded by a lock
|
||||||
|
lock sync.RWMutex
|
||||||
|
threshold *time.Duration
|
||||||
endTime *time.Time
|
endTime *time.Time
|
||||||
traceItems []traceItem
|
traceItems []traceItem
|
||||||
parentTrace *Trace
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Trace) time() time.Time {
|
func (t *Trace) time() time.Time {
|
||||||
@ -138,6 +142,8 @@ func New(name string, fields ...Field) *Trace {
|
|||||||
// how long it took. The Fields add key value pairs to provide additional details about the trace
|
// how long it took. The Fields add key value pairs to provide additional details about the trace
|
||||||
// step.
|
// step.
|
||||||
func (t *Trace) Step(msg string, fields ...Field) {
|
func (t *Trace) Step(msg string, fields ...Field) {
|
||||||
|
t.lock.Lock()
|
||||||
|
defer t.lock.Unlock()
|
||||||
if t.traceItems == nil {
|
if t.traceItems == nil {
|
||||||
// traces almost always have less than 6 steps, do this to avoid more than a single allocation
|
// traces almost always have less than 6 steps, do this to avoid more than a single allocation
|
||||||
t.traceItems = make([]traceItem, 0, 6)
|
t.traceItems = make([]traceItem, 0, 6)
|
||||||
@ -153,7 +159,9 @@ func (t *Trace) Nest(msg string, fields ...Field) *Trace {
|
|||||||
newTrace := New(msg, fields...)
|
newTrace := New(msg, fields...)
|
||||||
if t != nil {
|
if t != nil {
|
||||||
newTrace.parentTrace = t
|
newTrace.parentTrace = t
|
||||||
|
t.lock.Lock()
|
||||||
t.traceItems = append(t.traceItems, newTrace)
|
t.traceItems = append(t.traceItems, newTrace)
|
||||||
|
t.lock.Unlock()
|
||||||
}
|
}
|
||||||
return newTrace
|
return newTrace
|
||||||
}
|
}
|
||||||
@ -163,7 +171,9 @@ func (t *Trace) Nest(msg string, fields ...Field) *Trace {
|
|||||||
// is logged.
|
// is logged.
|
||||||
func (t *Trace) Log() {
|
func (t *Trace) Log() {
|
||||||
endTime := time.Now()
|
endTime := time.Now()
|
||||||
|
t.lock.Lock()
|
||||||
t.endTime = &endTime
|
t.endTime = &endTime
|
||||||
|
t.lock.Unlock()
|
||||||
// an explicit logging request should dump all the steps out at the higher level
|
// 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
|
if t.parentTrace == nil { // We don't start logging until Log or LogIfLong is called on the root trace
|
||||||
t.logTrace()
|
t.logTrace()
|
||||||
@ -178,13 +188,17 @@ func (t *Trace) Log() {
|
|||||||
// If the Trace is nested it is not immediately logged. Instead, it is logged when the trace it
|
// If the Trace is nested it is not immediately logged. Instead, it is logged when the trace it
|
||||||
// is nested within is logged.
|
// is nested within is logged.
|
||||||
func (t *Trace) LogIfLong(threshold time.Duration) {
|
func (t *Trace) LogIfLong(threshold time.Duration) {
|
||||||
|
t.lock.Lock()
|
||||||
t.threshold = &threshold
|
t.threshold = &threshold
|
||||||
|
t.lock.Unlock()
|
||||||
t.Log()
|
t.Log()
|
||||||
}
|
}
|
||||||
|
|
||||||
// logTopLevelTraces finds all traces in a hierarchy of nested traces that should be logged but do not have any
|
// 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.
|
// parents that will be logged, due to threshold limits, and logs them as top level traces.
|
||||||
func (t *Trace) logTrace() {
|
func (t *Trace) logTrace() {
|
||||||
|
t.lock.RLock()
|
||||||
|
defer t.lock.RUnlock()
|
||||||
if t.durationIsWithinThreshold() {
|
if t.durationIsWithinThreshold() {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
traceNum := rand.Int31()
|
traceNum := rand.Int31()
|
||||||
@ -244,10 +258,14 @@ func (t *Trace) calculateStepThreshold() *time.Duration {
|
|||||||
traceThreshold := *t.threshold
|
traceThreshold := *t.threshold
|
||||||
for _, s := range t.traceItems {
|
for _, s := range t.traceItems {
|
||||||
nestedTrace, ok := s.(*Trace)
|
nestedTrace, ok := s.(*Trace)
|
||||||
if ok && nestedTrace.threshold != nil {
|
if ok {
|
||||||
|
nestedTrace.lock.RLock()
|
||||||
|
if nestedTrace.threshold != nil {
|
||||||
traceThreshold = traceThreshold - *nestedTrace.threshold
|
traceThreshold = traceThreshold - *nestedTrace.threshold
|
||||||
lenTrace--
|
lenTrace--
|
||||||
}
|
}
|
||||||
|
nestedTrace.lock.RUnlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the limit threshold is used when the threshold(
|
// the limit threshold is used when the threshold(
|
||||||
|
|||||||
26
vendor/modules.txt
vendored
26
vendor/modules.txt
vendored
@ -57,7 +57,7 @@ github.com/felixge/httpsnoop
|
|||||||
# github.com/fsnotify/fsnotify v1.4.9
|
# github.com/fsnotify/fsnotify v1.4.9
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/fsnotify/fsnotify
|
github.com/fsnotify/fsnotify
|
||||||
# github.com/go-logr/logr v1.2.0
|
# github.com/go-logr/logr v1.2.3
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
github.com/go-logr/logr
|
github.com/go-logr/logr
|
||||||
# github.com/gogo/protobuf v1.3.2
|
# github.com/gogo/protobuf v1.3.2
|
||||||
@ -124,6 +124,9 @@ github.com/matttproud/golang_protobuf_extensions/pbutil
|
|||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/moby/spdystream
|
github.com/moby/spdystream
|
||||||
github.com/moby/spdystream/spdy
|
github.com/moby/spdystream/spdy
|
||||||
|
# github.com/moby/sys/mountinfo v0.6.2
|
||||||
|
## explicit; go 1.16
|
||||||
|
github.com/moby/sys/mountinfo
|
||||||
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
|
# github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
|
||||||
## explicit
|
## explicit
|
||||||
github.com/modern-go/concurrent
|
github.com/modern-go/concurrent
|
||||||
@ -218,7 +221,7 @@ github.com/spf13/cobra
|
|||||||
# github.com/spf13/pflag v1.0.5
|
# github.com/spf13/pflag v1.0.5
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
# github.com/stretchr/testify v1.7.0
|
# github.com/stretchr/testify v1.8.0
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/stretchr/testify/assert
|
github.com/stretchr/testify/assert
|
||||||
# go.opentelemetry.io/contrib v0.20.0
|
# go.opentelemetry.io/contrib v0.20.0
|
||||||
@ -459,7 +462,7 @@ gopkg.in/tomb.v1
|
|||||||
# gopkg.in/yaml.v2 v2.4.0
|
# gopkg.in/yaml.v2 v2.4.0
|
||||||
## explicit; go 1.15
|
## explicit; go 1.15
|
||||||
gopkg.in/yaml.v2
|
gopkg.in/yaml.v2
|
||||||
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
# gopkg.in/yaml.v3 v3.0.1
|
||||||
## explicit
|
## explicit
|
||||||
gopkg.in/yaml.v3
|
gopkg.in/yaml.v3
|
||||||
# k8s.io/api v0.23.3 => k8s.io/api v0.23.3
|
# k8s.io/api v0.23.3 => k8s.io/api v0.23.3
|
||||||
@ -866,9 +869,14 @@ k8s.io/component-base/version
|
|||||||
k8s.io/component-helpers/node/util/sysctl
|
k8s.io/component-helpers/node/util/sysctl
|
||||||
k8s.io/component-helpers/scheduling/corev1
|
k8s.io/component-helpers/scheduling/corev1
|
||||||
k8s.io/component-helpers/scheduling/corev1/nodeaffinity
|
k8s.io/component-helpers/scheduling/corev1/nodeaffinity
|
||||||
# k8s.io/klog/v2 v2.30.0
|
# k8s.io/klog/v2 v2.80.1
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
k8s.io/klog/v2
|
k8s.io/klog/v2
|
||||||
|
k8s.io/klog/v2/internal/buffer
|
||||||
|
k8s.io/klog/v2/internal/clock
|
||||||
|
k8s.io/klog/v2/internal/dbg
|
||||||
|
k8s.io/klog/v2/internal/serialize
|
||||||
|
k8s.io/klog/v2/internal/severity
|
||||||
# k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
# k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
k8s.io/kube-openapi/pkg/schemaconv
|
k8s.io/kube-openapi/pkg/schemaconv
|
||||||
@ -943,11 +951,11 @@ k8s.io/kubernetes/test/e2e/storage/podlogs
|
|||||||
k8s.io/kubernetes/test/e2e/storage/utils
|
k8s.io/kubernetes/test/e2e/storage/utils
|
||||||
k8s.io/kubernetes/test/utils
|
k8s.io/kubernetes/test/utils
|
||||||
k8s.io/kubernetes/test/utils/image
|
k8s.io/kubernetes/test/utils/image
|
||||||
# k8s.io/mount-utils v0.23.3 => k8s.io/mount-utils v0.23.3
|
# k8s.io/mount-utils v0.23.3 => k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2
|
||||||
## explicit; go 1.16
|
## explicit; go 1.19
|
||||||
k8s.io/mount-utils
|
k8s.io/mount-utils
|
||||||
# k8s.io/utils v0.0.0-20211116205334-6203023598ed
|
# k8s.io/utils v0.0.0-20221107191617-1a15be271d1d
|
||||||
## explicit; go 1.12
|
## explicit; go 1.18
|
||||||
k8s.io/utils/buffer
|
k8s.io/utils/buffer
|
||||||
k8s.io/utils/clock
|
k8s.io/utils/clock
|
||||||
k8s.io/utils/clock/testing
|
k8s.io/utils/clock/testing
|
||||||
@ -1003,7 +1011,7 @@ sigs.k8s.io/yaml
|
|||||||
# k8s.io/kubelet => k8s.io/kubelet v0.23.3
|
# k8s.io/kubelet => k8s.io/kubelet v0.23.3
|
||||||
# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.3
|
# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.3
|
||||||
# k8s.io/metrics => k8s.io/metrics v0.23.3
|
# k8s.io/metrics => k8s.io/metrics v0.23.3
|
||||||
# k8s.io/mount-utils => k8s.io/mount-utils v0.23.3
|
# k8s.io/mount-utils => k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2
|
||||||
# k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.3
|
# k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.3
|
||||||
# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.3
|
# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.3
|
||||||
# k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.3
|
# k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.3
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user