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{