diff --git a/go.mod b/go.mod
index 519e5c169b..3589b279ae 100644
--- a/go.mod
+++ b/go.mod
@@ -7,8 +7,8 @@ require (
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.5.9
github.com/spf13/pflag v1.0.5
- github.com/stretchr/testify v1.8.1
- golang.org/x/time v0.3.0
+ github.com/stretchr/testify v1.8.0
+ golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
gopkg.in/gcfg.v1 v1.2.3
k8s.io/api v0.26.0
k8s.io/apimachinery v0.26.0
@@ -66,38 +66,38 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/client_golang v1.14.0 // indirect
- github.com/prometheus/client_model v0.3.0 // indirect
- github.com/prometheus/common v0.39.0 // indirect
- github.com/prometheus/procfs v0.8.0 // indirect
- github.com/spf13/cobra v1.6.1 // indirect
- github.com/stoewer/go-strcase v1.2.0 // indirect
- github.com/stretchr/objx v0.5.0 // indirect
- go.etcd.io/etcd/api/v3 v3.5.6 // indirect
- go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect
- go.etcd.io/etcd/client/v3 v3.5.6 // indirect
- go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.37.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.37.0 // indirect
- go.opentelemetry.io/otel v1.11.2 // indirect
- go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2 // indirect
- go.opentelemetry.io/otel/metric v0.34.0 // indirect
- go.opentelemetry.io/otel/sdk v1.11.2 // indirect
- go.opentelemetry.io/otel/trace v1.11.2 // indirect
- go.opentelemetry.io/proto/otlp v0.19.0 // indirect
- go.uber.org/atomic v1.10.0 // indirect
- go.uber.org/multierr v1.9.0 // indirect
- go.uber.org/zap v1.24.0 // indirect
- golang.org/x/crypto v0.4.0 // indirect
- golang.org/x/mod v0.6.0 // indirect
- golang.org/x/net v0.4.0 // indirect
- golang.org/x/oauth2 v0.3.0 // indirect
- golang.org/x/sync v0.1.0 // indirect
- golang.org/x/sys v0.3.0 // indirect
- golang.org/x/term v0.3.0 // indirect
- golang.org/x/text v0.5.0 // indirect
- golang.org/x/tools v0.2.0 // indirect
+ github.com/prometheus/client_golang v1.12.1 // indirect
+ github.com/prometheus/client_model v0.2.0 // indirect
+ github.com/prometheus/common v0.32.1 // indirect
+ github.com/prometheus/procfs v0.7.3 // indirect
+ github.com/spf13/cobra v1.4.0 // indirect
+ github.com/stretchr/objx v0.4.0 // indirect
+ go.etcd.io/etcd/api/v3 v3.5.4 // indirect
+ go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
+ go.etcd.io/etcd/client/v3 v3.5.4 // indirect
+ go.opentelemetry.io/contrib v0.20.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect
+ go.opentelemetry.io/otel v0.20.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
+ go.opentelemetry.io/otel/metric v0.20.0 // indirect
+ go.opentelemetry.io/otel/sdk v0.20.0 // indirect
+ go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect
+ go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
+ go.opentelemetry.io/otel/trace v0.20.0 // indirect
+ go.opentelemetry.io/proto/otlp v0.7.0 // indirect
+ go.uber.org/atomic v1.7.0 // indirect
+ go.uber.org/multierr v1.6.0 // indirect
+ go.uber.org/zap v1.19.0 // indirect
+ golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
+ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
+ golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
+ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
+ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
+ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
+ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
+ golang.org/x/text v0.3.7 // indirect
+ golang.org/x/tools v0.1.12 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 // indirect
google.golang.org/grpc v1.51.0 // indirect
@@ -107,12 +107,15 @@ require (
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/apiserver v0.26.0 // indirect
- k8s.io/component-helpers v0.26.0 // indirect
- k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect
- k8s.io/kms v0.26.0 // indirect
- k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 // indirect
+ k8s.io/apiserver v0.25.0 // indirect
+ k8s.io/component-helpers v0.25.0 // indirect
+ k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect
+ k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 // indirect
- sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
+ sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)
+
+// https://github.com/kubernetes/kubernetes/issues/112793
+// Remove after k8s.io/cloud-provider v0.25.3 will be released, updated upstream and rebased.
+replace k8s.io/cloud-provider v0.25.0 => github.com/openshift/kubernetes-cloud-provider v0.0.0-20221007081959-e07817829a38
diff --git a/go.sum b/go.sum
index 20f2b686d7..2a552c7bcc 100644
--- a/go.sum
+++ b/go.sum
@@ -48,10 +48,9 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
-github.com/aws/aws-sdk-go v1.44.159 h1:9odtuHAYQE9tQKyuX6ny1U1MHeH5/yzeCJi96g9H4DU=
-github.com/aws/aws-sdk-go v1.44.159/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.44.107 h1:VP7Rq3wzsOV7wrfHqjAAKRksD4We58PaoVSDPKhm8nw=
+github.com/aws/aws-sdk-go v1.44.107/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
+github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -277,8 +276,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
-github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY=
+github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
+github.com/openshift/kubernetes-cloud-provider v0.0.0-20221007081959-e07817829a38 h1:/4N1vluQjoe+C2ic9w2rc6nruPJR+FqP/G4QAX49PXg=
+github.com/openshift/kubernetes-cloud-provider v0.0.0-20221007081959-e07817829a38/go.mod h1:5iKXFWrW3xc/xYOh8WgzjDZ3pDQzUcPoEh4dxEsshgk=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -325,18 +328,16 @@ github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ai
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
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.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
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.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.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/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
@@ -386,9 +387,9 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
-go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
@@ -747,28 +748,27 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I=
-k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg=
-k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg=
-k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
-k8s.io/apiserver v0.26.0 h1:q+LqIK5EZwdznGZb8bq0+a+vCqdeEEe4Ux3zsOjbc4o=
-k8s.io/apiserver v0.26.0/go.mod h1:aWhlLD+mU+xRo+zhkvP/gFNbShI4wBDHS33o0+JGI84=
-k8s.io/client-go v0.26.0 h1:lT1D3OfO+wIi9UFolCrifbjUUgu7CpLca0AD8ghRLI8=
-k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg=
-k8s.io/cloud-provider v0.26.0 h1:kO2BIgCou71QNRHGkpFi/8lnas9UIr+fJz1l/nuiOMo=
-k8s.io/cloud-provider v0.26.0/go.mod h1:JwfUAH67C8f7t6tOC4v4ty+DuvIYVjNF6bGVYSDCqqs=
-k8s.io/code-generator v0.26.0 h1:ZDY+7Gic9p/lACgD1G72gQg2CvNGeAYZTPIncv+iALM=
-k8s.io/code-generator v0.26.0/go.mod h1:OMoJ5Dqx1wgaQzKgc+ZWaZPfGjdRq/Y3WubFrZmeI3I=
-k8s.io/component-base v0.26.0 h1:0IkChOCohtDHttmKuz+EP3j3+qKmV55rM9gIFTXA7Vs=
-k8s.io/component-base v0.26.0/go.mod h1:lqHwlfV1/haa14F/Z5Zizk5QmzaVf23nQzCwVOQpfC8=
-k8s.io/component-helpers v0.26.0 h1:KNgwqs3EUdK0HLfW4GhnbD+q/Zl9U021VfIU7qoVYFk=
-k8s.io/component-helpers v0.26.0/go.mod h1:jHN01qS/Jdj95WCbTe9S2VZ9yxpxXNY488WjF+yW4fo=
-k8s.io/controller-manager v0.26.0 h1:6xIWxs3+Xhj/hoyzELCk871PrIed4J4QqEh57LzQe+8=
-k8s.io/controller-manager v0.26.0/go.mod h1:GxUYtQDBE/RHh7AnZSZqwi2xBPIXlOaWsnDLflKGYrE=
-k8s.io/csi-translation-lib v0.26.0 h1:bCvlfw53Kmyn7cvXeYGe9aqqzR1b0xrGs2XEWHFW+es=
-k8s.io/csi-translation-lib v0.26.0/go.mod h1:zRKLRqER6rA8NCKQBhVIdkyDHKgNlu2BK1RKTHjcw+8=
-k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08=
-k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0=
+k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk=
+k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU=
+k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
+k8s.io/apiserver v0.25.0 h1:8kl2ifbNffD440MyvHtPaIz1mw4mGKVgWqM0nL+oyu4=
+k8s.io/apiserver v0.25.0/go.mod h1:BKwsE+PTC+aZK+6OJQDPr0v6uS91/HWxX7evElAH6xo=
+k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
+k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
+k8s.io/code-generator v0.25.0 h1:QP8fJuXu882ztf6dsqJsso/Btm94pMd68TAZC1rE6KI=
+k8s.io/code-generator v0.25.0/go.mod h1:B6jZgI3DvDFAualltPitbYMQ74NjaCFxum3YeKZZ+3w=
+k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y=
+k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk=
+k8s.io/component-helpers v0.25.0 h1:vNzYfqnVXj7f+CPksduKVv2Z9kC+IDsOs9yaOyxZrj0=
+k8s.io/component-helpers v0.25.0/go.mod h1:auaFj2bvb5Zmy0mLk4WJNmwP0w4e7Zk+/Tu9FFBGA20=
+k8s.io/controller-manager v0.25.0 h1:eaCajwXGkUG/Xcxv2aJ0eJgAaWIWdO3wDi4JQAx4znQ=
+k8s.io/controller-manager v0.25.0/go.mod h1:QElCivPrZ64NP1Y976pkgyViZUqn6UcvjlXHiAAUGd0=
+k8s.io/csi-translation-lib v0.25.0 h1:Jh3kn5p3kEGGA/q1fovTNIG9fypzt2c34sm+qij2W/8=
+k8s.io/csi-translation-lib v0.25.0/go.mod h1:Wb80CDywP4753F6wWkIyOuJIQtQAbhgw985veSgAn/4=
+k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 h1:TT1WdmqqXareKxZ/oNXEUSwKlLiHzPMyB0t8BaFeBYI=
+k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+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.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
@@ -785,8 +785,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 h1:LYqFq+6Cj2D0gFfrJvL7iElD4ET6ir3VDdhDdTK7rgc=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33/go.mod h1:soWkSNf2tZC7aMibXEqVhCd73GOY5fJikn8qbdzemB0=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
-sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
+sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
+sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/vendor/github.com/stretchr/objx/.travis.yml b/vendor/github.com/stretchr/objx/.travis.yml
deleted file mode 100644
index cde6eb2aff..0000000000
--- a/vendor/github.com/stretchr/objx/.travis.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-language: go
-go:
- - "1.10.x"
- - "1.11.x"
- - "1.12.x"
- - master
-
-matrix:
- allow_failures:
- - go: master
-fast_finish: true
-
-env:
- global:
- - CC_TEST_REPORTER_ID=68feaa3410049ce73e145287acbcdacc525087a30627f96f04e579e75bd71c00
-
-before_script:
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- - chmod +x ./cc-test-reporter
- - ./cc-test-reporter before-build
-
-install:
- - curl -sL https://taskfile.dev/install.sh | sh
-
-script:
- - diff -u <(echo -n) <(./bin/task lint)
- - ./bin/task test-coverage
-
-after_script:
- - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
diff --git a/vendor/github.com/stretchr/objx/accessors.go b/vendor/github.com/stretchr/objx/accessors.go
index 6763162811..4c60455886 100644
--- a/vendor/github.com/stretchr/objx/accessors.go
+++ b/vendor/github.com/stretchr/objx/accessors.go
@@ -1,6 +1,7 @@
package objx
import (
+ "reflect"
"regexp"
"strconv"
"strings"
@@ -16,11 +17,18 @@ const (
// arrayAccesRegexString is the regex used to extract the array number
// from the access path
arrayAccesRegexString = `^(.+)\[([0-9]+)\]$`
+
+ // mapAccessRegexString is the regex used to extract the map key
+ // from the access path
+ mapAccessRegexString = `^([^\[]*)\[([^\]]+)\](.*)$`
)
// arrayAccesRegex is the compiled arrayAccesRegexString
var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
+// mapAccessRegex is the compiled mapAccessRegexString
+var mapAccessRegex = regexp.MustCompile(mapAccessRegexString)
+
// Get gets the value using the specified selector and
// returns it inside a new Obj object.
//
@@ -70,15 +78,53 @@ func getIndex(s string) (int, string) {
return -1, s
}
+// getKey returns the key which is held in s by two brackets.
+// It also returns the next selector.
+func getKey(s string) (string, string) {
+ selSegs := strings.SplitN(s, PathSeparator, 2)
+ thisSel := selSegs[0]
+ nextSel := ""
+
+ if len(selSegs) > 1 {
+ nextSel = selSegs[1]
+ }
+
+ mapMatches := mapAccessRegex.FindStringSubmatch(s)
+ if len(mapMatches) > 0 {
+ if _, err := strconv.Atoi(mapMatches[2]); err != nil {
+ thisSel = mapMatches[1]
+ nextSel = "[" + mapMatches[2] + "]" + mapMatches[3]
+
+ if thisSel == "" {
+ thisSel = mapMatches[2]
+ nextSel = mapMatches[3]
+ }
+
+ if nextSel == "" {
+ selSegs = []string{"", ""}
+ } else if nextSel[0] == '.' {
+ nextSel = nextSel[1:]
+ }
+ }
+ }
+
+ return thisSel, nextSel
+}
+
// access accesses the object using the selector and performs the
// appropriate action.
func access(current interface{}, selector string, value interface{}, isSet bool) interface{} {
- selSegs := strings.SplitN(selector, PathSeparator, 2)
- thisSel := selSegs[0]
- index := -1
+ thisSel, nextSel := getKey(selector)
- if strings.Contains(thisSel, "[") {
+ indexes := []int{}
+ for strings.Contains(thisSel, "[") {
+ prevSel := thisSel
+ index := -1
index, thisSel = getIndex(thisSel)
+ indexes = append(indexes, index)
+ if prevSel == thisSel {
+ break
+ }
}
if curMap, ok := current.(Map); ok {
@@ -88,13 +134,17 @@ func access(current interface{}, selector string, value interface{}, isSet bool)
switch current.(type) {
case map[string]interface{}:
curMSI := current.(map[string]interface{})
- if len(selSegs) <= 1 && isSet {
+ if nextSel == "" && isSet {
curMSI[thisSel] = value
return nil
}
_, ok := curMSI[thisSel].(map[string]interface{})
- if (curMSI[thisSel] == nil || !ok) && index == -1 && isSet {
+ if !ok {
+ _, ok = curMSI[thisSel].(Map)
+ }
+
+ if (curMSI[thisSel] == nil || !ok) && len(indexes) == 0 && isSet {
curMSI[thisSel] = map[string]interface{}{}
}
@@ -102,18 +152,46 @@ func access(current interface{}, selector string, value interface{}, isSet bool)
default:
current = nil
}
+
// do we need to access the item of an array?
- if index > -1 {
- if array, ok := current.([]interface{}); ok {
- if index < len(array) {
- current = array[index]
- } else {
- current = nil
+ if len(indexes) > 0 {
+ num := len(indexes)
+ for num > 0 {
+ num--
+ index := indexes[num]
+ indexes = indexes[:num]
+ if array, ok := interSlice(current); ok {
+ if index < len(array) {
+ current = array[index]
+ } else {
+ current = nil
+ break
+ }
}
}
}
- if len(selSegs) > 1 {
- current = access(current, selSegs[1], value, isSet)
+
+ if nextSel != "" {
+ current = access(current, nextSel, value, isSet)
}
return current
}
+
+func interSlice(slice interface{}) ([]interface{}, bool) {
+ if array, ok := slice.([]interface{}); ok {
+ return array, ok
+ }
+
+ s := reflect.ValueOf(slice)
+ if s.Kind() != reflect.Slice {
+ return nil, false
+ }
+
+ ret := make([]interface{}, s.Len())
+
+ for i := 0; i < s.Len(); i++ {
+ ret[i] = s.Index(i).Interface()
+ }
+
+ return ret, true
+}
diff --git a/vendor/github.com/stretchr/objx/map.go b/vendor/github.com/stretchr/objx/map.go
index 95149c06a6..a64712a08b 100644
--- a/vendor/github.com/stretchr/objx/map.go
+++ b/vendor/github.com/stretchr/objx/map.go
@@ -92,6 +92,18 @@ func MustFromJSON(jsonString string) Map {
return o
}
+// MustFromJSONSlice creates a new slice of Map containing the data specified in the
+// jsonString. Works with jsons with a top level array
+//
+// Panics if the JSON is invalid.
+func MustFromJSONSlice(jsonString string) []Map {
+ slice, err := FromJSONSlice(jsonString)
+ if err != nil {
+ panic("objx: MustFromJSONSlice failed with error: " + err.Error())
+ }
+ return slice
+}
+
// FromJSON creates a new Map containing the data specified in the
// jsonString.
//
@@ -102,45 +114,20 @@ func FromJSON(jsonString string) (Map, error) {
if err != nil {
return Nil, err
}
- m.tryConvertFloat64()
return m, nil
}
-func (m Map) tryConvertFloat64() {
- for k, v := range m {
- switch v.(type) {
- case float64:
- f := v.(float64)
- if float64(int(f)) == f {
- m[k] = int(f)
- }
- case map[string]interface{}:
- t := New(v)
- t.tryConvertFloat64()
- m[k] = t
- case []interface{}:
- m[k] = tryConvertFloat64InSlice(v.([]interface{}))
- }
- }
-}
-
-func tryConvertFloat64InSlice(s []interface{}) []interface{} {
- for k, v := range s {
- switch v.(type) {
- case float64:
- f := v.(float64)
- if float64(int(f)) == f {
- s[k] = int(f)
- }
- case map[string]interface{}:
- t := New(v)
- t.tryConvertFloat64()
- s[k] = t
- case []interface{}:
- s[k] = tryConvertFloat64InSlice(v.([]interface{}))
- }
+// FromJSONSlice creates a new slice of Map containing the data specified in the
+// jsonString. Works with jsons with a top level array
+//
+// Returns an error if the JSON is invalid.
+func FromJSONSlice(jsonString string) ([]Map, error) {
+ var slice []Map
+ err := json.Unmarshal([]byte(jsonString), &slice)
+ if err != nil {
+ return nil, err
}
- return s
+ return slice, nil
}
// FromBase64 creates a new Obj containing the data specified
diff --git a/vendor/github.com/stretchr/objx/type_specific_codegen.go b/vendor/github.com/stretchr/objx/type_specific_codegen.go
index 9859b407f0..45850456e1 100644
--- a/vendor/github.com/stretchr/objx/type_specific_codegen.go
+++ b/vendor/github.com/stretchr/objx/type_specific_codegen.go
@@ -385,6 +385,11 @@ func (v *Value) Int(optionalDefault ...int) int {
if s, ok := v.data.(int); ok {
return s
}
+ if s, ok := v.data.(float64); ok {
+ if float64(int(s)) == s {
+ return int(s)
+ }
+ }
if len(optionalDefault) == 1 {
return optionalDefault[0]
}
@@ -395,6 +400,11 @@ func (v *Value) Int(optionalDefault ...int) int {
//
// Panics if the object is not a int.
func (v *Value) MustInt() int {
+ if s, ok := v.data.(float64); ok {
+ if float64(int(s)) == s {
+ return int(s)
+ }
+ }
return v.data.(int)
}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
index 3bb22a9718..95d8e59da6 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go
@@ -1,6 +1,7 @@
package assert
import (
+ "bytes"
"fmt"
"reflect"
"time"
@@ -32,7 +33,8 @@ var (
stringType = reflect.TypeOf("")
- timeType = reflect.TypeOf(time.Time{})
+ timeType = reflect.TypeOf(time.Time{})
+ bytesType = reflect.TypeOf([]byte{})
)
func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
@@ -323,6 +325,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) {
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
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go
index 27e2420ed2..7880b8f943 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_format.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -736,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...)...)
}
+// 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.
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
if h, ok := t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
index d9ea368d0a..339515b8bf 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -1461,6 +1461,26 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
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.
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
if h, ok := a.t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
index 0357b2231a..fa1245b189 100644
--- a/vendor/github.com/stretchr/testify/assert/assertions.go
+++ b/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -8,6 +8,7 @@ import (
"fmt"
"math"
"os"
+ "path/filepath"
"reflect"
"regexp"
"runtime"
@@ -144,7 +145,8 @@ func CallerInfo() []string {
if len(parts) > 1 {
dir := parts[len(parts)-2]
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,16 +565,17 @@ func isEmpty(object interface{}) bool {
switch objValue.Kind() {
// 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
- // 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:
if objValue.IsNil() {
return true
}
deref := objValue.Elem().Interface()
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:
zero := reflect.Zero(objValue.Type())
return reflect.DeepEqual(object, zero.Interface())
@@ -815,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
}
- subsetValue := reflect.ValueOf(subset)
defer func() {
if e := recover(); e != nil {
ok = false
@@ -825,14 +827,32 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok
listKind := reflect.TypeOf(list).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...)
}
- 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...)
}
+ 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++ {
element := subsetValue.Index(i).Interface()
ok, found := containsElement(list, element)
@@ -859,7 +879,6 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...)
}
- subsetValue := reflect.ValueOf(subset)
defer func() {
if e := recover(); e != nil {
ok = false
@@ -869,14 +888,32 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{})
listKind := reflect.TypeOf(list).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...)
}
- 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...)
}
+ 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++ {
element := subsetValue.Index(i).Interface()
ok, found := containsElement(list, element)
@@ -1109,6 +1146,27 @@ func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration,
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) {
var xf float64
xok := true
diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go
index 853da6cce2..f0af8246cf 100644
--- a/vendor/github.com/stretchr/testify/mock/mock.go
+++ b/vendor/github.com/stretchr/testify/mock/mock.go
@@ -70,6 +70,9 @@ type Call struct {
// if the PanicMsg is set to a non nil string the function call will panic
// irrespective of other settings
PanicMsg *string
+
+ // Calls which must be satisfied before this call can be
+ requires []*Call
}
func newCall(parent *Mock, methodName string, callerInfo []string, methodArguments ...interface{}) *Call {
@@ -199,6 +202,64 @@ func (c *Call) On(methodName string, arguments ...interface{}) *Call {
return c.Parent.On(methodName, arguments...)
}
+// Unset removes a mock handler from being called.
+// test.On("func", mock.Anything).Unset()
+func (c *Call) Unset() *Call {
+ var unlockOnce sync.Once
+
+ for _, arg := range c.Arguments {
+ if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
+ panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
+ }
+ }
+
+ c.lock()
+ defer unlockOnce.Do(c.unlock)
+
+ foundMatchingCall := false
+
+ for i, call := range c.Parent.ExpectedCalls {
+ if call.Method == c.Method {
+ _, diffCount := call.Arguments.Diff(c.Arguments)
+ if diffCount == 0 {
+ foundMatchingCall = true
+ // Remove from ExpectedCalls
+ c.Parent.ExpectedCalls = append(c.Parent.ExpectedCalls[:i], c.Parent.ExpectedCalls[i+1:]...)
+ }
+ }
+ }
+
+ if !foundMatchingCall {
+ unlockOnce.Do(c.unlock)
+ c.Parent.fail("\n\nmock: Could not find expected call\n-----------------------------\n\n%s\n\n",
+ callString(c.Method, c.Arguments, true),
+ )
+ }
+
+ return c
+}
+
+// NotBefore indicates that the mock should only be called after the referenced
+// calls have been called as expected. The referenced calls may be from the
+// same mock instance and/or other mock instances.
+//
+// Mock.On("Do").Return(nil).Notbefore(
+// Mock.On("Init").Return(nil)
+// )
+func (c *Call) NotBefore(calls ...*Call) *Call {
+ c.lock()
+ defer c.unlock()
+
+ for _, call := range calls {
+ if call.Parent == nil {
+ panic("not before calls must be created with Mock.On()")
+ }
+ }
+
+ c.requires = append(c.requires, calls...)
+ return c
+}
+
// Mock is the workhorse used to track activity on another object.
// For an example of its usage, refer to the "Example Usage" section at the top
// of this document.
@@ -232,7 +293,6 @@ func (m *Mock) String() string {
// TestData holds any data that might be useful for testing. Testify ignores
// this data completely allowing you to do whatever you like with it.
func (m *Mock) TestData() objx.Map {
-
if m.testData == nil {
m.testData = make(objx.Map)
}
@@ -354,7 +414,6 @@ func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call,
}
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
-
var argValsString string
if includeArgumentValues {
var argVals []string
@@ -378,10 +437,10 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
panic("Couldn't get the caller information")
}
functionPath := runtime.FuncForPC(pc).Name()
- //Next four lines are required to use GCCGO function naming conventions.
- //For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
- //uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
- //With GCCGO we need to remove interface information starting from pN
.
+ // Next four lines are required to use GCCGO function naming conventions.
+ // For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
+ // uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
+ // With GCCGO we need to remove interface information starting from pN.
re := regexp.MustCompile("\\.pN\\d+_")
if re.MatchString(functionPath) {
functionPath = re.Split(functionPath, -1)[0]
@@ -397,7 +456,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
// If Call.WaitFor is set, blocks until the channel is closed or receives a message.
func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Arguments {
m.mutex.Lock()
- //TODO: could combine expected and closes in single loop
+ // TODO: could combine expected and closes in single loop
found, call := m.findExpectedCall(methodName, arguments...)
if found < 0 {
@@ -427,6 +486,25 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen
}
}
+ for _, requirement := range call.requires {
+ if satisfied, _ := requirement.Parent.checkExpectation(requirement); !satisfied {
+ m.mutex.Unlock()
+ m.fail("mock: Unexpected Method Call\n-----------------------------\n\n%s\n\nMust not be called before%s:\n\n%s",
+ callString(call.Method, call.Arguments, true),
+ func() (s string) {
+ if requirement.totalCalls > 0 {
+ s = " another call of"
+ }
+ if call.Parent != requirement.Parent {
+ s += " method from another mock instance"
+ }
+ return
+ }(),
+ callString(requirement.Method, requirement.Arguments, true),
+ )
+ }
+ }
+
if call.Repeatability == 1 {
call.Repeatability = -1
} else if call.Repeatability > 1 {
@@ -484,9 +562,9 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
h.Helper()
}
for _, obj := range testObjects {
- if m, ok := obj.(Mock); ok {
+ if m, ok := obj.(*Mock); ok {
t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)")
- obj = &m
+ obj = m
}
m := obj.(assertExpectationser)
if !m.AssertExpectations(t) {
@@ -503,34 +581,36 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
+
m.mutex.Lock()
defer m.mutex.Unlock()
- var somethingMissing bool
var failedExpectations int
// iterate through each expectation
expectedCalls := m.expectedCalls()
for _, expectedCall := range expectedCalls {
- if !expectedCall.optional && !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) && expectedCall.totalCalls == 0 {
- somethingMissing = true
+ satisfied, reason := m.checkExpectation(expectedCall)
+ if !satisfied {
failedExpectations++
- t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
- } else {
- if expectedCall.Repeatability > 0 {
- somethingMissing = true
- failedExpectations++
- t.Logf("FAIL:\t%s(%s)\n\t\tat: %s", expectedCall.Method, expectedCall.Arguments.String(), expectedCall.callerInfo)
- } else {
- t.Logf("PASS:\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
- }
}
+ t.Logf(reason)
}
- if somethingMissing {
+ if failedExpectations != 0 {
t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(expectedCalls)-failedExpectations, len(expectedCalls), failedExpectations, assert.CallerInfo())
}
- return !somethingMissing
+ return failedExpectations == 0
+}
+
+func (m *Mock) checkExpectation(call *Call) (bool, string) {
+ if !call.optional && !m.methodWasCalled(call.Method, call.Arguments) && call.totalCalls == 0 {
+ return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo)
+ }
+ if call.Repeatability > 0 {
+ return false, fmt.Sprintf("FAIL:\t%s(%s)\n\t\tat: %s", call.Method, call.Arguments.String(), call.callerInfo)
+ }
+ return true, fmt.Sprintf("PASS:\t%s(%s)", call.Method, call.Arguments.String())
}
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
@@ -781,12 +861,12 @@ func (args Arguments) Is(objects ...interface{}) bool {
//
// Returns the diff string and number of differences found.
func (args Arguments) Diff(objects []interface{}) (string, int) {
- //TODO: could return string as error and nil for No difference
+ // TODO: could return string as error and nil for No difference
- var output = "\n"
+ output := "\n"
var differences int
- var maxArgCount = len(args)
+ maxArgCount := len(args)
if len(objects) > maxArgCount {
maxArgCount = len(objects)
}
@@ -812,21 +892,28 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
}
if matcher, ok := expected.(argumentMatcher); ok {
- if matcher.Matches(actual) {
+ var matches bool
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ actualFmt = fmt.Sprintf("panic in argument matcher: %v", r)
+ }
+ }()
+ matches = matcher.Matches(actual)
+ }()
+ if matches {
output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher)
} else {
differences++
output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher)
}
} else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
-
// type checking
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
// not match
differences++
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt)
}
-
} else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) {
t := expected.(*IsTypeArgument).t
if reflect.TypeOf(t) != reflect.TypeOf(actual) {
@@ -834,7 +921,6 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt)
}
} else {
-
// normal checking
if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
@@ -854,7 +940,6 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
}
return output, differences
-
}
// Assert compares the arguments with the specified objects and fails if
@@ -876,7 +961,6 @@ func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
t.Errorf("%sArguments do not match.", assert.CallerInfo())
return false
-
}
// String gets the argument at the specified index. Panics if there is no argument, or
@@ -885,7 +969,6 @@ func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
// If no index is provided, String() returns a complete string representation
// of the arguments.
func (args Arguments) String(indexOrNil ...int) string {
-
if len(indexOrNil) == 0 {
// normal String() method - return a string representation of the args
var argsStr []string
@@ -895,7 +978,7 @@ func (args Arguments) String(indexOrNil ...int) string {
return strings.Join(argsStr, ",")
} else if len(indexOrNil) == 1 {
// Index has been specified - get the argument at that index
- var index = indexOrNil[0]
+ index := indexOrNil[0]
var s string
var ok bool
if s, ok = args.Get(index).(string); !ok {
@@ -905,7 +988,6 @@ func (args Arguments) String(indexOrNil ...int) string {
}
panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil)))
-
}
// Int gets the argument at the specified index. Panics if there is no argument, or
diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go
index 59c48277ac..880853f5a2 100644
--- a/vendor/github.com/stretchr/testify/require/require.go
+++ b/vendor/github.com/stretchr/testify/require/require.go
@@ -1864,6 +1864,32 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim
t.FailNow()
}
+// 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 time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.WithinRange(t, actual, start, end, msgAndArgs...) {
+ return
+ }
+ t.FailNow()
+}
+
+// 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{}) {
+ if h, ok := t.(tHelper); ok {
+ h.Helper()
+ }
+ if assert.WithinRangef(t, actual, start, end, msg, args...) {
+ return
+ }
+ t.FailNow()
+}
+
// YAMLEq asserts that two YAML strings are equivalent.
func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) {
if h, ok := t.(tHelper); ok {
diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go
index 5bb07c89c6..960bf6f2ca 100644
--- a/vendor/github.com/stretchr/testify/require/require_forward.go
+++ b/vendor/github.com/stretchr/testify/require/require_forward.go
@@ -1462,6 +1462,26 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta
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{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ 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{}) {
+ if h, ok := a.t.(tHelper); ok {
+ h.Helper()
+ }
+ WithinRangef(a.t, actual, start, end, msg, args...)
+}
+
// YAMLEq asserts that two YAML strings are equivalent.
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
if h, ok := a.t.(tHelper); ok {
diff --git a/vendor/k8s.io/cloud-provider/app/controllermanager.go b/vendor/k8s.io/cloud-provider/app/controllermanager.go
index 84101fd30f..559beae3e2 100644
--- a/vendor/k8s.io/cloud-provider/app/controllermanager.go
+++ b/vendor/k8s.io/cloud-provider/app/controllermanager.go
@@ -460,6 +460,7 @@ func CreateControllerContext(s *cloudcontrollerconfig.CompletedConfig, clientBui
ResyncPeriod: ResyncPeriod(s),
ControllerManagerMetrics: controllersmetrics.NewControllerManagerMetrics("cloud-controller-manager"),
}
+ controllersmetrics.Register()
return ctx, nil
}
diff --git a/vendor/k8s.io/cloud-provider/controllers/service/controller.go b/vendor/k8s.io/cloud-provider/controllers/service/controller.go
index 4c9a45510b..d76a892a53 100644
--- a/vendor/k8s.io/cloud-provider/controllers/service/controller.go
+++ b/vendor/k8s.io/cloud-provider/controllers/service/controller.go
@@ -98,9 +98,6 @@ type Controller struct {
nodeSyncCh chan interface{}
// needFullSync indicates if the nodeSyncInternal will do a full node sync on all LB services.
needFullSync bool
- // lastSyncedNodes is used when reconciling node state and keeps track of the last synced set of
- // nodes. Access to this attribute by multiple go-routines is protected by nodeSyncLock
- lastSyncedNodes []*v1.Node
}
// New returns a new service controller to keep cloud provider service resources
@@ -135,8 +132,7 @@ func New(
nodeListerSynced: nodeInformer.Informer().HasSynced,
queue: workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(minRetryDelay, maxRetryDelay), "service"),
// nodeSyncCh has a size 1 buffer. Only one pending sync signal would be cached.
- nodeSyncCh: make(chan interface{}, 1),
- lastSyncedNodes: []*v1.Node{},
+ nodeSyncCh: make(chan interface{}, 1),
}
serviceInformer.Informer().AddEventHandlerWithResyncPeriod(
@@ -180,7 +176,7 @@ func New(
return
}
- if !shouldSyncUpdatedNode(oldNode, curNode) {
+ if !shouldSyncNode(oldNode, curNode) {
return
}
@@ -261,7 +257,7 @@ func (c *Controller) Run(ctx context.Context, workers int, controllerManagerMetr
func (c *Controller) triggerNodeSync() {
c.nodeSyncLock.Lock()
defer c.nodeSyncLock.Unlock()
- newHosts, err := listWithPredicates(c.nodeLister, allNodePredicates...)
+ newHosts, err := listWithPredicate(c.nodeLister, c.getNodeConditionPredicate())
if err != nil {
runtime.HandleError(fmt.Errorf("Failed to retrieve current set of nodes from node lister: %v", err))
// if node list cannot be retrieve, trigger full node sync to be safe.
@@ -457,7 +453,7 @@ func (c *Controller) syncLoadBalancerIfNeeded(ctx context.Context, service *v1.S
}
func (c *Controller) ensureLoadBalancer(ctx context.Context, service *v1.Service) (*v1.LoadBalancerStatus, error) {
- nodes, err := listWithPredicates(c.nodeLister, getNodePredicatesForService(service)...)
+ nodes, err := listWithPredicate(c.nodeLister, c.getNodeConditionPredicate())
if err != nil {
return nil, err
}
@@ -671,15 +667,6 @@ func portEqualForLB(x, y *v1.ServicePort) bool {
return true
}
-func serviceKeys(services []*v1.Service) sets.String {
- ret := sets.NewString()
- for _, service := range services {
- key, _ := cache.MetaNamespaceKeyFunc(service)
- ret.Insert(key)
- }
- return ret
-}
-
func nodeNames(nodes []*v1.Node) sets.String {
ret := sets.NewString()
for _, node := range nodes {
@@ -695,21 +682,58 @@ func nodeSlicesEqualForLB(x, y []*v1.Node) bool {
return nodeNames(x).Equal(nodeNames(y))
}
-func shouldSyncUpdatedNode(oldNode, newNode *v1.Node) bool {
- // Evaluate the individual node exclusion predicate before evaluating the
- // compounded result of all predicates. We don't sync ETP=local services
- // for changes on the readiness condition, hence if a node remains NotReady
- // and a user adds the exclusion label we will need to sync as to make sure
- // this change is reflected correctly on ETP=local services. The sync
- // function compares lastSyncedNodes with the new (existing) set of nodes
- // for each service, so services which are synced with the same set of nodes
- // should be skipped internally in the sync function. This is needed as to
- // trigger a global sync for all services and make sure no service gets
- // skipped due to a changing node predicate.
- if respectsPredicates(oldNode, nodeIncludedPredicate) != respectsPredicates(newNode, nodeIncludedPredicate) {
+func (c *Controller) getNodeConditionPredicate() NodeConditionPredicate {
+ return func(node *v1.Node) bool {
+ if _, hasExcludeBalancerLabel := node.Labels[v1.LabelNodeExcludeBalancers]; hasExcludeBalancerLabel {
+ return false
+ }
+
+ // Remove nodes that are about to be deleted by the cluster autoscaler.
+ for _, taint := range node.Spec.Taints {
+ if taint.Key == ToBeDeletedTaint {
+ klog.V(4).Infof("Ignoring node %v with autoscaler taint %+v", node.Name, taint)
+ return false
+ }
+ }
+
+ // If we have no info, don't accept
+ if len(node.Status.Conditions) == 0 {
+ return false
+ }
+ for _, cond := range node.Status.Conditions {
+ // We consider the node for load balancing only when its NodeReady condition status
+ // is ConditionTrue
+ if cond.Type == v1.NodeReady && cond.Status != v1.ConditionTrue {
+ klog.V(4).Infof("Ignoring node %v with %v condition status %v", node.Name, cond.Type, cond.Status)
+ return false
+ }
+ }
return true
}
- return respectsPredicates(oldNode, allNodePredicates...) != respectsPredicates(newNode, allNodePredicates...)
+}
+
+func shouldSyncNode(oldNode, newNode *v1.Node) bool {
+ if oldNode.Spec.Unschedulable != newNode.Spec.Unschedulable {
+ return true
+ }
+
+ if !reflect.DeepEqual(oldNode.Labels, newNode.Labels) {
+ return true
+ }
+
+ return nodeReadyConditionStatus(oldNode) != nodeReadyConditionStatus(newNode)
+}
+
+func nodeReadyConditionStatus(node *v1.Node) v1.ConditionStatus {
+ for _, condition := range node.Status.Conditions {
+ if condition.Type != v1.NodeReady {
+ continue
+ }
+
+ return condition.Status
+ }
+
+ return ""
}
// nodeSyncInternal handles updating the hosts pointed to by all load
@@ -751,29 +775,24 @@ func (c *Controller) nodeSyncInternal(ctx context.Context, workers int) {
numServices-len(c.servicesToUpdate), numServices)
}
-// nodeSyncService syncs the nodes for one load balancer type service. The return value
-// indicates if we should retry. Hence, this functions returns false if we've updated
-// load balancers and finished doing it successfully, or didn't try to at all because
-// there's no need. This function returns true if we tried to update load balancers and
-// failed, indicating to the caller that we should try again.
-func (c *Controller) nodeSyncService(svc *v1.Service, oldNodes, newNodes []*v1.Node) bool {
- retSuccess := false
- retNeedRetry := true
+// nodeSyncService syncs the nodes for one load balancer type service
+func (c *Controller) nodeSyncService(svc *v1.Service) bool {
if svc == nil || !wantsLoadBalancer(svc) {
- return retSuccess
- }
- newNodes = filterWithPredicates(newNodes, getNodePredicatesForService(svc)...)
- oldNodes = filterWithPredicates(oldNodes, getNodePredicatesForService(svc)...)
- if nodeNames(newNodes).Equal(nodeNames(oldNodes)) {
- return retSuccess
+ return false
}
klog.V(4).Infof("nodeSyncService started for service %s/%s", svc.Namespace, svc.Name)
- if err := c.lockedUpdateLoadBalancerHosts(svc, newNodes); err != nil {
+ hosts, err := listWithPredicate(c.nodeLister, c.getNodeConditionPredicate())
+ if err != nil {
+ runtime.HandleError(fmt.Errorf("failed to retrieve node list: %v", err))
+ return true
+ }
+
+ if err := c.lockedUpdateLoadBalancerHosts(svc, hosts); err != nil {
runtime.HandleError(fmt.Errorf("failed to update load balancer hosts for service %s/%s: %v", svc.Namespace, svc.Name, err))
- return retNeedRetry
+ return true
}
klog.V(4).Infof("nodeSyncService finished successfully for service %s/%s", svc.Namespace, svc.Name)
- return retSuccess
+ return false
}
// updateLoadBalancerHosts updates all existing load balancers so that
@@ -782,20 +801,11 @@ func (c *Controller) nodeSyncService(svc *v1.Service, oldNodes, newNodes []*v1.N
func (c *Controller) updateLoadBalancerHosts(ctx context.Context, services []*v1.Service, workers int) (servicesToRetry sets.String) {
klog.V(4).Infof("Running updateLoadBalancerHosts(len(services)==%d, workers==%d)", len(services), workers)
- // Include all nodes and let nodeSyncService filter and figure out if
- // the update is relevant for the service in question.
- nodes, err := listWithPredicates(c.nodeLister)
- if err != nil {
- runtime.HandleError(fmt.Errorf("failed to retrieve node list: %v", err))
- return serviceKeys(services)
- }
-
// lock for servicesToRetry
servicesToRetry = sets.NewString()
lock := sync.Mutex{}
-
doWork := func(piece int) {
- if shouldRetry := c.nodeSyncService(services[piece], c.lastSyncedNodes, nodes); !shouldRetry {
+ if shouldRetry := c.nodeSyncService(services[piece]); !shouldRetry {
return
}
lock.Lock()
@@ -805,7 +815,6 @@ func (c *Controller) updateLoadBalancerHosts(ctx context.Context, services []*v1
}
workqueue.ParallelizeUntil(ctx, workers, len(services), doWork)
- c.lastSyncedNodes = nodes
klog.V(4).Infof("Finished updateLoadBalancerHosts")
return servicesToRetry
}
@@ -981,75 +990,19 @@ func (c *Controller) patchStatus(service *v1.Service, previousStatus, newStatus
// some set of criteria defined by the function.
type NodeConditionPredicate func(node *v1.Node) bool
-var (
- allNodePredicates []NodeConditionPredicate = []NodeConditionPredicate{
- nodeIncludedPredicate,
- nodeUnTaintedPredicate,
- nodeReadyPredicate,
- }
- etpLocalNodePredicates []NodeConditionPredicate = []NodeConditionPredicate{
- nodeIncludedPredicate,
- nodeUnTaintedPredicate,
- }
-)
-
-func getNodePredicatesForService(service *v1.Service) []NodeConditionPredicate {
- if service.Spec.ExternalTrafficPolicy == v1.ServiceExternalTrafficPolicyTypeLocal {
- return etpLocalNodePredicates
- }
- return allNodePredicates
-}
-
-// We consider the node for load balancing only when the node is not labelled for exclusion.
-func nodeIncludedPredicate(node *v1.Node) bool {
- _, hasExcludeBalancerLabel := node.Labels[v1.LabelNodeExcludeBalancers]
- return !hasExcludeBalancerLabel
-}
-
-// We consider the node for load balancing only when its not tainted for deletion by the cluster autoscaler.
-func nodeUnTaintedPredicate(node *v1.Node) bool {
- for _, taint := range node.Spec.Taints {
- if taint.Key == ToBeDeletedTaint {
- return false
- }
- }
- return true
-}
-
-// We consider the node for load balancing only when its NodeReady condition status is ConditionTrue
-func nodeReadyPredicate(node *v1.Node) bool {
- for _, cond := range node.Status.Conditions {
- if cond.Type == v1.NodeReady {
- return cond.Status == v1.ConditionTrue
- }
- }
- return false
-}
-
-// listWithPredicate gets nodes that matches all predicate functions.
-func listWithPredicates(nodeLister corelisters.NodeLister, predicates ...NodeConditionPredicate) ([]*v1.Node, error) {
+// listWithPredicate gets nodes that matches predicate function.
+func listWithPredicate(nodeLister corelisters.NodeLister, predicate NodeConditionPredicate) ([]*v1.Node, error) {
nodes, err := nodeLister.List(labels.Everything())
if err != nil {
return nil, err
}
- return filterWithPredicates(nodes, predicates...), nil
-}
-func filterWithPredicates(nodes []*v1.Node, predicates ...NodeConditionPredicate) []*v1.Node {
var filtered []*v1.Node
for i := range nodes {
- if respectsPredicates(nodes[i], predicates...) {
+ if predicate(nodes[i]) {
filtered = append(filtered, nodes[i])
}
}
- return filtered
-}
-func respectsPredicates(node *v1.Node, predicates ...NodeConditionPredicate) bool {
- for _, p := range predicates {
- if !p(node) {
- return false
- }
- }
- return true
+ return filtered, nil
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index abfa0beaa3..ddeee9f69a 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -224,10 +224,10 @@ github.com/spf13/cobra
# github.com/spf13/pflag v1.0.5
## explicit; go 1.12
github.com/spf13/pflag
-# github.com/stretchr/objx v0.2.0
+# github.com/stretchr/objx v0.4.0
## explicit; go 1.12
github.com/stretchr/objx
-# github.com/stretchr/testify v1.7.2
+# github.com/stretchr/testify v1.8.0
## explicit; go 1.13
github.com/stretchr/testify/assert
github.com/stretchr/testify/mock
@@ -1057,7 +1057,7 @@ k8s.io/client-go/util/homedir
k8s.io/client-go/util/keyutil
k8s.io/client-go/util/retry
k8s.io/client-go/util/workqueue
-# k8s.io/cloud-provider v0.25.0
+# k8s.io/cloud-provider v0.25.0 => github.com/openshift/kubernetes-cloud-provider v0.0.0-20221007081959-e07817829a38
## explicit; go 1.19
k8s.io/cloud-provider
k8s.io/cloud-provider/api
@@ -1224,7 +1224,7 @@ k8s.io/utils/path
k8s.io/utils/pointer
k8s.io/utils/strings/slices
k8s.io/utils/trace
-# sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.32
+# sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33
## explicit; go 1.17
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client
diff --git a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go
index c191649a89..c55070ae63 100644
--- a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go
+++ b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go
@@ -24,6 +24,7 @@ import (
"math/rand"
"net"
"sync"
+ "sync/atomic"
"time"
"google.golang.org/grpc"
@@ -36,10 +37,13 @@ type Tunnel interface {
// Dial connects to the address on the named network, similar to
// what net.Dial does. The only supported protocol is tcp.
DialContext(requestCtx context.Context, protocol, address string) (net.Conn, error)
+ // Done returns a channel that is closed when the tunnel is no longer serving any connections,
+ // and can no longer be used.
+ Done() <-chan struct{}
}
type dialResult struct {
- err string
+ err *dialFailure
connid int64
}
@@ -50,17 +54,83 @@ type pendingDial struct {
cancelCh <-chan struct{}
}
+// TODO: Replace with a generic implementation once it is safe to assume the client is built with go1.18+
+type pendingDialManager struct {
+ pendingDials map[int64]pendingDial
+ mutex sync.RWMutex
+}
+
+func (p *pendingDialManager) add(dialID int64, pd pendingDial) {
+ p.mutex.Lock()
+ defer p.mutex.Unlock()
+ p.pendingDials[dialID] = pd
+}
+
+func (p *pendingDialManager) remove(dialID int64) {
+ p.mutex.Lock()
+ defer p.mutex.Unlock()
+ delete(p.pendingDials, dialID)
+}
+
+func (p *pendingDialManager) get(dialID int64) (pendingDial, bool) {
+ p.mutex.RLock()
+ defer p.mutex.RUnlock()
+ pd, ok := p.pendingDials[dialID]
+ return pd, ok
+}
+
+// TODO: Replace with a generic implementation once it is safe to assume the client is built with go1.18+
+type connectionManager struct {
+ conns map[int64]*conn
+ mutex sync.RWMutex
+}
+
+func (cm *connectionManager) add(connID int64, c *conn) {
+ cm.mutex.Lock()
+ defer cm.mutex.Unlock()
+ cm.conns[connID] = c
+}
+
+func (cm *connectionManager) remove(connID int64) {
+ cm.mutex.Lock()
+ defer cm.mutex.Unlock()
+ delete(cm.conns, connID)
+}
+
+func (cm *connectionManager) get(connID int64) (*conn, bool) {
+ cm.mutex.RLock()
+ defer cm.mutex.RUnlock()
+ c, ok := cm.conns[connID]
+ return c, ok
+}
+
+func (cm *connectionManager) closeAll() {
+ cm.mutex.Lock()
+ defer cm.mutex.Unlock()
+ for _, conn := range cm.conns {
+ close(conn.readCh)
+ }
+}
+
// grpcTunnel implements Tunnel
type grpcTunnel struct {
- stream client.ProxyService_ProxyClient
- pendingDial map[int64]pendingDial
- conns map[int64]*conn
- pendingDialLock sync.RWMutex
- connsLock sync.RWMutex
+ stream client.ProxyService_ProxyClient
+ clientConn clientConn
+ pendingDial pendingDialManager
+ conns connectionManager
// The tunnel will be closed if the caller fails to read via conn.Read()
// more than readTimeoutSeconds after a packet has been received.
readTimeoutSeconds int
+
+ // The done channel is closed after the tunnel has cleaned up all connections and is no longer
+ // serving.
+ done chan struct{}
+
+ // closing is an atomic bool represented as a 0 or 1, and set to true when the tunnel is being closed.
+ // closing should only be accessed through atomic methods.
+ // TODO: switch this to an atomic.Bool once the client is exclusively buit with go1.19+
+ closing uint32
}
type clientConn interface {
@@ -99,35 +169,39 @@ func CreateSingleUseGrpcTunnelWithContext(createCtx, tunnelCtx context.Context,
return nil, err
}
- tunnel := &grpcTunnel{
- stream: stream,
- pendingDial: make(map[int64]pendingDial),
- conns: make(map[int64]*conn),
- readTimeoutSeconds: 10,
- }
+ tunnel := newUnstartedTunnel(stream, c)
- go tunnel.serve(tunnelCtx, c)
+ go tunnel.serve(tunnelCtx)
return tunnel, nil
}
-func (t *grpcTunnel) serve(tunnelCtx context.Context, c clientConn) {
+func newUnstartedTunnel(stream client.ProxyService_ProxyClient, c clientConn) *grpcTunnel {
+ return &grpcTunnel{
+ stream: stream,
+ clientConn: c,
+ pendingDial: pendingDialManager{pendingDials: make(map[int64]pendingDial)},
+ conns: connectionManager{conns: make(map[int64]*conn)},
+ readTimeoutSeconds: 10,
+ done: make(chan struct{}),
+ }
+}
+
+func (t *grpcTunnel) serve(tunnelCtx context.Context) {
defer func() {
- c.Close()
+ t.clientConn.Close()
// A connection in t.conns after serve() returns means
// we never received a CLOSE_RSP for it, so we need to
// close any channels remaining for these connections.
- t.connsLock.Lock()
- for _, conn := range t.conns {
- close(conn.readCh)
- }
- t.connsLock.Unlock()
+ t.conns.closeAll()
+
+ close(t.done)
}()
for {
pkt, err := t.stream.Recv()
- if err == io.EOF {
+ if err == io.EOF || t.isClosing() {
return
}
if err != nil || pkt == nil {
@@ -140,78 +214,101 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context, c clientConn) {
switch pkt.Type {
case client.PacketType_DIAL_RSP:
resp := pkt.GetDialResponse()
- t.pendingDialLock.RLock()
- pendingDial, ok := t.pendingDial[resp.Random]
- t.pendingDialLock.RUnlock()
+ pendingDial, ok := t.pendingDial.get(resp.Random)
if !ok {
+ // If the DIAL_RSP does not match a pending dial, it means one of two things:
+ // 1. There was a second DIAL_RSP for the connection request (this is very unlikely but possible)
+ // 2. grpcTunnel.DialContext() returned early due to a dial timeout or the client canceling the context
+ //
+ // In either scenario, we should return here and close the tunnel as it is no longer needed.
klog.V(1).InfoS("DialResp not recognized; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random)
return
+ }
+
+ result := dialResult{connid: resp.ConnectID}
+ if resp.Error != "" {
+ result.err = &dialFailure{resp.Error, DialFailureEndpoint}
+ }
+ select {
+ // try to send to the result channel
+ case pendingDial.resultCh <- result:
+ // unblock if the cancel channel is closed
+ case <-pendingDial.cancelCh:
+ // Note: this condition can only be hit by a race condition where the
+ // DialContext() returns early (timeout) after the pendingDial is already
+ // fetched here, but before the result is sent.
+ klog.V(1).InfoS("Pending dial has been cancelled; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random)
+ return
+ case <-tunnelCtx.Done():
+ klog.V(1).InfoS("Tunnel has been closed; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random)
+ return
+ }
+
+ if resp.Error != "" {
+ // On dial error, avoid leaking serve goroutine.
+ return
+ }
+
+ case client.PacketType_DIAL_CLS:
+ resp := pkt.GetCloseDial()
+ pendingDial, ok := t.pendingDial.get(resp.Random)
+
+ if !ok {
+ // If the DIAL_CLS does not match a pending dial, it means one of two things:
+ // 1. There was a DIAL_CLS receieved after a DIAL_RSP (unlikely but possible)
+ // 2. grpcTunnel.DialContext() returned early due to a dial timeout or the client canceling the context
+ //
+ // In either scenario, we should return here and close the tunnel as it is no longer needed.
+ klog.V(1).InfoS("DIAL_CLS after dial finished", "dialID", resp.Random)
} else {
result := dialResult{
- err: resp.Error,
- connid: resp.ConnectID,
+ err: &dialFailure{"dial closed", DialFailureDialClosed},
}
select {
- // try to send to the result channel
case pendingDial.resultCh <- result:
- // unblock if the cancel channel is closed
case <-pendingDial.cancelCh:
- // If there are no readers of the pending dial channel above, it means one of two things:
- // 1. There was a second DIAL_RSP for the connection request (this is very unlikely but possible)
- // 2. grpcTunnel.DialContext() returned early due to a dial timeout or the client canceling the context
- //
- // In either scenario, we should return here as this tunnel is no longer needed.
- klog.V(1).InfoS("Pending dial has been cancelled; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random)
- return
+ // Note: this condition can only be hit by a race condition where the
+ // DialContext() returns early (timeout) after the pendingDial is already
+ // fetched here, but before the result is sent.
case <-tunnelCtx.Done():
- klog.V(1).InfoS("Tunnel has been closed; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random)
- return
}
}
-
- if resp.Error != "" {
- // On dial error, avoid leaking serve goroutine.
- return
- }
+ return // Stop serving & close the tunnel.
case client.PacketType_DATA:
resp := pkt.GetData()
// TODO: flow control
- t.connsLock.RLock()
- conn, ok := t.conns[resp.ConnectID]
- t.connsLock.RUnlock()
+ conn, ok := t.conns.get(resp.ConnectID)
- if ok {
- timer := time.NewTimer((time.Duration)(t.readTimeoutSeconds) * time.Second)
- select {
- case conn.readCh <- resp.Data:
- timer.Stop()
- case <-timer.C:
- klog.ErrorS(fmt.Errorf("timeout"), "readTimeout has been reached, the grpc connection to the proxy server will be closed", "connectionID", conn.connID, "readTimeoutSeconds", t.readTimeoutSeconds)
- return
- case <-tunnelCtx.Done():
- klog.V(1).InfoS("Tunnel has been closed, the grpc connection to the proxy server will be closed", "connectionID", conn.connID)
- }
- } else {
- klog.V(1).InfoS("connection not recognized", "connectionID", resp.ConnectID)
+ if !ok {
+ klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID)
+ continue
+ }
+ timer := time.NewTimer((time.Duration)(t.readTimeoutSeconds) * time.Second)
+ select {
+ case conn.readCh <- resp.Data:
+ timer.Stop()
+ case <-timer.C:
+ klog.ErrorS(fmt.Errorf("timeout"), "readTimeout has been reached, the grpc connection to the proxy server will be closed", "connectionID", conn.connID, "readTimeoutSeconds", t.readTimeoutSeconds)
+ return
+ case <-tunnelCtx.Done():
+ klog.V(1).InfoS("Tunnel has been closed, the grpc connection to the proxy server will be closed", "connectionID", conn.connID)
}
+
case client.PacketType_CLOSE_RSP:
resp := pkt.GetCloseResponse()
- t.connsLock.RLock()
- conn, ok := t.conns[resp.ConnectID]
- t.connsLock.RUnlock()
-
- if ok {
- close(conn.readCh)
- conn.closeCh <- resp.Error
- close(conn.closeCh)
- t.connsLock.Lock()
- delete(t.conns, resp.ConnectID)
- t.connsLock.Unlock()
- return
+ conn, ok := t.conns.get(resp.ConnectID)
+
+ if !ok {
+ klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID)
+ continue
}
- klog.V(1).InfoS("connection not recognized", "connectionID", resp.ConnectID)
+ close(conn.readCh)
+ conn.closeCh <- resp.Error
+ close(conn.closeCh)
+ t.conns.remove(resp.ConnectID)
+ return
}
}
}
@@ -219,6 +316,12 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context, c clientConn) {
// Dial connects to the address on the named network, similar to
// what net.Dial does. The only supported protocol is tcp.
func (t *grpcTunnel) DialContext(requestCtx context.Context, protocol, address string) (net.Conn, error) {
+ select {
+ case <-t.done:
+ return nil, errors.New("tunnel is closed")
+ default: // Tunnel is open, carry on.
+ }
+
if protocol != "tcp" {
return nil, errors.New("protocol not supported")
}
@@ -232,14 +335,8 @@ func (t *grpcTunnel) DialContext(requestCtx context.Context, protocol, address s
// This channel MUST NOT be buffered. The sender needs to know when we are not receiving things, so they can abort.
resCh := make(chan dialResult)
- t.pendingDialLock.Lock()
- t.pendingDial[random] = pendingDial{resultCh: resCh, cancelCh: cancelCh}
- t.pendingDialLock.Unlock()
- defer func() {
- t.pendingDialLock.Lock()
- delete(t.pendingDial, random)
- t.pendingDialLock.Unlock()
- }()
+ t.pendingDial.add(random, pendingDial{resultCh: resCh, cancelCh: cancelCh})
+ defer t.pendingDial.remove(random)
req := &client.Packet{
Type: client.PacketType_DIAL_REQ,
@@ -260,26 +357,98 @@ func (t *grpcTunnel) DialContext(requestCtx context.Context, protocol, address s
klog.V(5).Infoln("DIAL_REQ sent to proxy server")
- c := &conn{stream: t.stream, random: random}
+ c := &conn{
+ stream: t.stream,
+ random: random,
+ closeTunnel: t.closeTunnel,
+ }
select {
case res := <-resCh:
- if res.err != "" {
- return nil, errors.New(res.err)
+ if res.err != nil {
+ return nil, res.err
}
c.connID = res.connid
c.readCh = make(chan []byte, 10)
c.closeCh = make(chan string, 1)
- t.connsLock.Lock()
- t.conns[res.connid] = c
- t.connsLock.Unlock()
+ t.conns.add(res.connid, c)
case <-time.After(30 * time.Second):
klog.V(5).InfoS("Timed out waiting for DialResp", "dialID", random)
- return nil, errors.New("dial timeout, backstop")
+ go t.closeDial(random)
+ return nil, &dialFailure{"dial timeout, backstop", DialFailureTimeout}
case <-requestCtx.Done():
klog.V(5).InfoS("Context canceled waiting for DialResp", "ctxErr", requestCtx.Err(), "dialID", random)
- return nil, errors.New("dial timeout, context")
+ go t.closeDial(random)
+ return nil, &dialFailure{"dial timeout, context", DialFailureContext}
+ case <-t.done:
+ klog.V(5).InfoS("Tunnel closed while waiting for DialResp", "dialID", random)
+ return nil, &dialFailure{"tunnel closed", DialFailureTunnelClosed}
}
return c, nil
}
+
+func (t *grpcTunnel) Done() <-chan struct{} {
+ return t.done
+}
+
+// Send a best-effort DIAL_CLS request for the given dial ID.
+func (t *grpcTunnel) closeDial(dialID int64) {
+ req := &client.Packet{
+ Type: client.PacketType_DIAL_CLS,
+ Payload: &client.Packet_CloseDial{
+ CloseDial: &client.CloseDial{
+ Random: dialID,
+ },
+ },
+ }
+ if err := t.stream.Send(req); err != nil {
+ klog.V(5).InfoS("Failed to send DIAL_CLS", "err", err, "dialID", dialID)
+ }
+ t.closeTunnel()
+}
+
+func (t *grpcTunnel) closeTunnel() {
+ atomic.StoreUint32(&t.closing, 1)
+ t.clientConn.Close()
+}
+
+func (t *grpcTunnel) isClosing() bool {
+ return atomic.LoadUint32(&t.closing) != 0
+}
+
+func GetDialFailureReason(err error) (isDialFailure bool, reason DialFailureReason) {
+ var df *dialFailure
+ if errors.As(err, &df) {
+ return true, df.reason
+ }
+ return false, DialFailureUnknown
+}
+
+type dialFailure struct {
+ msg string
+ reason DialFailureReason
+}
+
+func (df *dialFailure) Error() string {
+ return df.msg
+}
+
+type DialFailureReason string
+
+const (
+ DialFailureUnknown DialFailureReason = "unknown"
+ // DialFailureTimeout indicates the hard 30 second timeout was hit.
+ DialFailureTimeout DialFailureReason = "timeout"
+ // DialFailureContext indicates that the context was cancelled or reached it's deadline before
+ // the dial response was returned.
+ DialFailureContext DialFailureReason = "context"
+ // DialFailureEndpoint indicates that the konnectivity-agent was unable to reach the backend endpoint.
+ DialFailureEndpoint DialFailureReason = "endpoint"
+ // DialFailureDialClosed indicates that the client received a CloseDial response, indicating the
+ // connection was closed before the dial could complete.
+ DialFailureDialClosed DialFailureReason = "dialclosed"
+ // DialFailureTunnelClosed indicates that the client connection was closed before the dial could
+ // complete.
+ DialFailureTunnelClosed DialFailureReason = "tunnelclosed"
+)
diff --git a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go
index 822831b10c..f76b1e37a4 100644
--- a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go
+++ b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go
@@ -41,6 +41,9 @@ type conn struct {
readCh chan []byte
closeCh chan string
rdata []byte
+
+ // closeTunnel is an optional callback to close the underlying grpc connection.
+ closeTunnel func()
}
var _ net.Conn = &conn{}
@@ -116,6 +119,10 @@ func (c *conn) SetWriteDeadline(t time.Time) error {
// proxy service to notify remote to drop the connection.
func (c *conn) Close() error {
klog.V(4).Infoln("closing connection")
+ if c.closeTunnel != nil {
+ defer c.closeTunnel()
+ }
+
var req *client.Packet
if c.connID != 0 {
req = &client.Packet{