diff --git a/Makefile b/Makefile index 2eea9da..f5ed975 100644 --- a/Makefile +++ b/Makefile @@ -7,4 +7,10 @@ generate: mockgen --destination ./serverscom/testing/cloud_computing_instances_mock.go --package=serverscom_testing --source ${GO_CLIENT_PATH}/cloud_computing_instances.go mockgen --destination ./serverscom/testing/hosts_mock.go --package=serverscom_testing --source ${GO_CLIENT_PATH}/hosts.go mockgen --destination ./serverscom/testing/load_balancers_mock.go --package=serverscom_testing --source ${GO_CLIENT_PATH}/load_balancers.go - sed -i '' 's|github.com/serverscom/cloud-controller-manager/vendor/||' ./serverscom/testing/collection_mock.go ./serverscom/testing/cloud_computing_instances_mock.go ./serverscom/testing/hosts_mock.go ./serverscom/testing/load_balancers_mock.go + mockgen --destination ./serverscom/testing/kubernetes_clusters_mock.go --package=serverscom_testing --source ${GO_CLIENT_PATH}/kubernetes_clusters.go + sed -i '' 's|github.com/serverscom/cloud-controller-manager/vendor/||' \ + ./serverscom/testing/collection_mock.go \ + ./serverscom/testing/cloud_computing_instances_mock.go \ + ./serverscom/testing/hosts_mock.go \ + ./serverscom/testing/load_balancers_mock.go \ + ./serverscom/testing/kubernetes_clusters_mock.go diff --git a/go.mod b/go.mod index ebc2e1b..50d2c12 100644 --- a/go.mod +++ b/go.mod @@ -1,109 +1,120 @@ module github.com/serverscom/cloud-controller-manager -go 1.23.0 +go 1.26.0 require ( - github.com/onsi/gomega v1.36.2 - github.com/serverscom/serverscom-go-client v1.0.26 - github.com/spf13/pflag v1.0.5 - go.uber.org/mock v0.4.0 - k8s.io/api v0.31.1 - k8s.io/apimachinery v0.31.1 - k8s.io/cloud-provider v0.31.1 - k8s.io/component-base v0.31.1 - k8s.io/klog/v2 v2.130.1 + github.com/onsi/gomega v1.42.1 + github.com/serverscom/serverscom-go-client v1.1.2 + github.com/spf13/pflag v1.0.10 + go.uber.org/mock v0.6.0 + k8s.io/api v0.36.3 + k8s.io/apimachinery v0.36.3 + k8s.io/cloud-provider v0.36.3 + k8s.io/component-base v0.36.3 + k8s.io/klog/v2 v2.140.0 ) require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + cel.dev/expr v0.25.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect - github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/go-resty/resty/v2 v2.16.2 // indirect + github.com/go-openapi/jsonpointer v1.0.0 // indirect + github.com/go-openapi/jsonreference v1.0.0 // indirect + github.com/go-openapi/swag v0.28.0 // indirect + github.com/go-openapi/swag/cmdutils v0.28.0 // indirect + github.com/go-openapi/swag/conv v0.28.0 // indirect + github.com/go-openapi/swag/fileutils v0.28.0 // indirect + github.com/go-openapi/swag/jsonutils v0.28.0 // indirect + github.com/go-openapi/swag/loading v0.28.0 // indirect + github.com/go-openapi/swag/mangling v0.28.0 // indirect + github.com/go-openapi/swag/netutils v0.28.0 // indirect + github.com/go-openapi/swag/pools v0.28.0 // indirect + github.com/go-openapi/swag/stringutils v0.28.0 // indirect + github.com/go-openapi/swag/typeutils v0.28.0 // indirect + github.com/go-openapi/swag/yamlutils v0.28.0 // indirect + github.com/go-resty/resty/v2 v2.17.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/cel-go v0.20.1 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect + github.com/google/cel-go v0.26.0 // indirect + github.com/google/gnostic-models v0.7.1 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect - github.com/imdario/mergo v0.3.6 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.7 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/spf13/cobra v1.8.1 // indirect - github.com/stoewer/go-strcase v1.2.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.19.2 // indirect + github.com/spf13/cobra v1.10.2 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect - go.etcd.io/etcd/api/v3 v3.5.14 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect - go.etcd.io/etcd/client/v3 v3.5.14 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect - go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.etcd.io/etcd/api/v3 v3.6.8 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.8 // indirect + go.etcd.io/etcd/client/v3 v3.6.8 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect + go.opentelemetry.io/otel v1.41.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 // indirect + go.opentelemetry.io/otel/metric v1.41.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.41.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.24.0 // indirect - golang.org/x/time v0.6.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.36.1 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + go.uber.org/zap v1.27.1 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect + golang.org/x/crypto v0.55.0 // indirect + golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect + golang.org/x/net v0.58.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sync v0.22.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/term v0.45.0 // indirect + golang.org/x/text v0.41.0 // indirect + golang.org/x/time v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/grpc v1.79.3 // indirect + google.golang.org/protobuf v1.36.12 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiserver v0.31.1 // indirect - k8s.io/client-go v0.31.1 // indirect - k8s.io/component-helpers v0.31.1 // indirect - k8s.io/controller-manager v0.31.1 // indirect - k8s.io/kms v0.31.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + k8s.io/apiserver v0.36.3 // indirect + k8s.io/client-go v0.36.3 // indirect + k8s.io/component-helpers v0.36.3 // indirect + k8s.io/controller-manager v0.36.3 // indirect + k8s.io/kms v0.36.3 // indirect + k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad // indirect + k8s.io/streaming v0.36.3 // indirect + k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index 1bfdcaa..629a74a 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,24 @@ -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= +cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= +github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -28,290 +27,296 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= +github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.9.3 h1:oQBnFATpNdY8gJHTndDDv5Xl4QqNaz51G5LLEPhng3Q= +github.com/fxamacker/cbor/v2 v2.9.3/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg= -github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= +github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= +github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= +github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= +github.com/go-openapi/swag v0.28.0 h1:xkgbOSKj6DZziNpyqRRAOt3GJGtgjgsd2RoyT30VWuw= +github.com/go-openapi/swag v0.28.0/go.mod h1:4qYnT3Cqr1p1VknOdPo70evN4rgQnAg6jwApHyxSGIg= +github.com/go-openapi/swag/cmdutils v0.28.0 h1:7TOeNtkYru1SG8Y34tDh9WBbLsMqGnptuxWiHREPZ4Q= +github.com/go-openapi/swag/cmdutils v0.28.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= +github.com/go-openapi/swag/conv v0.28.0 h1:GtqqbyFe7vR5Y7ehxG9W6/OvrSFdf1OLeTGp40TqxH8= +github.com/go-openapi/swag/conv v0.28.0/go.mod h1:mbUE+mzctnhxi864m0Q07SpN8OowD9JhxmxuYvZZD/k= +github.com/go-openapi/swag/fileutils v0.28.0 h1:Z04XWQD7R8Eq+7GnOrjovBxPPmZzsS4gt2H2GPGIViU= +github.com/go-openapi/swag/fileutils v0.28.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8= +github.com/go-openapi/swag/jsonutils v0.28.0 h1:YIch6FwO7RXzeAnbO8Tu7dWBZeUEH+4nA0HXltVTnv4= +github.com/go-openapi/swag/jsonutils v0.28.0/go.mod h1:CYM3WlTUcagR2ZoHdz54di/cbBqt82tuxuXgAjxw+mg= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0 h1:qV+VVUAx5Oro8WjVWpZeql7YReTKhT4smR4zhcOQZr0= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY= +github.com/go-openapi/swag/loading v0.28.0 h1:td8QZdZC9MIYGGSnSPKShKiK22I2tU5UQvuUhIBPRLU= +github.com/go-openapi/swag/loading v0.28.0/go.mod h1:rXB0QiQX5mMveXEA7ouM4KiiM9jVJe4K6BVbwhD1M4k= +github.com/go-openapi/swag/mangling v0.28.0 h1:pH8eyeNO9SLYsTMWJrurnNfKmDa28XrlA+HePVD53VM= +github.com/go-openapi/swag/mangling v0.28.0/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w= +github.com/go-openapi/swag/netutils v0.28.0 h1:YXN6TALEi2pzts8/8GNm6T61HTAZsieukGZidap989k= +github.com/go-openapi/swag/netutils v0.28.0/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ= +github.com/go-openapi/swag/pools v0.28.0 h1:HPMZWSAfce3rdVTFcjFiCIBtDg9h4x2QlRrHipwhxeU= +github.com/go-openapi/swag/pools v0.28.0/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE= +github.com/go-openapi/swag/stringutils v0.28.0 h1:ixsc9iYgDPubHL/8nSkbnryEHpD2VRlBMLKpQyPXcDU= +github.com/go-openapi/swag/stringutils v0.28.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM= +github.com/go-openapi/swag/typeutils v0.28.0 h1:nRBKSBXjDgf01VDPB3fWeD9nQuhCOVeIYAkUx2tbkyY= +github.com/go-openapi/swag/typeutils v0.28.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ= +github.com/go-openapi/swag/yamlutils v0.28.0 h1:TV3JXH6DS46KUroDtMLAYHGkdWf5VDq3wVWFirmzROY= +github.com/go-openapi/swag/yamlutils v0.28.0/go.mod h1:x0q/yndZHEgk9Rx3DyDqzFUmHy55KTvIZldvF2dTJXs= +github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0= +github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo= +github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug= +github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= +github.com/go-resty/resty/v2 v2.17.2 h1:FQW5oHYcIlkCNrMD2lloGScxcHJ0gkjshV3qcQAyHQk= +github.com/go-resty/resty/v2 v2.17.2/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= -github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= +github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= +github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c= +github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= +github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM= -github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I= +github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= +github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/serverscom/serverscom-go-client v1.0.26 h1:w3ijfZPYs9ULe53gPnRpRNhBrI8D+UhfDEpp/a/Lyz8= -github.com/serverscom/serverscom-go-client v1.0.26/go.mod h1:/Nf+XygKOxm19Sl2gvMzT55O4X+tWDkj/UM4mjzfKgM= +github.com/serverscom/serverscom-go-client v1.1.2 h1:ddSKFrHRu38zdkk8OXg9Ugr5oTQX1ESfanTls8vb7vI= +github.com/serverscom/serverscom-go-client v1.1.2/go.mod h1:RVmx6+Dop/gvs7FETe6TrzdSEzQZGOzImyUTgUwsBoU= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk= +github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= -go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= -go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -go.etcd.io/etcd/client/v2 v2.305.13 h1:RWfV1SX5jTU0lbCvpVQe3iPQeAHETWdOTb6pxhd77C8= -go.etcd.io/etcd/client/v2 v2.305.13/go.mod h1:iQnL7fepbiomdXMb3om1rHq96htNNGv2sJkEcZGDRRg= -go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= -go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= -go.etcd.io/etcd/pkg/v3 v3.5.13 h1:st9bDWNsKkBNpP4PR1MvM/9NqUPfvYZx/YXegsYEH8M= -go.etcd.io/etcd/pkg/v3 v3.5.13/go.mod h1:N+4PLrp7agI/Viy+dUYpX7iRtSPvKq+w8Y14d1vX+m0= -go.etcd.io/etcd/raft/v3 v3.5.13 h1:7r/NKAOups1YnKcfro2RvGGo2PTuizF/xh26Z2CTAzA= -go.etcd.io/etcd/raft/v3 v3.5.13/go.mod h1:uUFibGLn2Ksm2URMxN1fICGhk8Wu96EfDQyuLhAcAmw= -go.etcd.io/etcd/server/v3 v3.5.13 h1:V6KG+yMfMSqWt+lGnhFpP5z5dRUj1BDRJ5k1fQ9DFok= -go.etcd.io/etcd/server/v3 v3.5.13/go.mod h1:K/8nbsGupHqmr5MkgaZpLlH1QdX1pcNQLAkODy44XcQ= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= +go.etcd.io/etcd/api/v3 v3.6.8 h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM= +go.etcd.io/etcd/api/v3 v3.6.8/go.mod h1:qyQj1HZPUV3B5cbAL8scG62+fyz5dSxxu0w8pn28N6Q= +go.etcd.io/etcd/client/pkg/v3 v3.6.8 h1:Qs/5C0LNFiqXxYf2GU8MVjYUEXJ6sZaYOz0zEqQgy50= +go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw= +go.etcd.io/etcd/client/v3 v3.6.8 h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY= +go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8= +go.etcd.io/etcd/pkg/v3 v3.6.8 h1:Xe+LIL974spy8b4nEx3H0KMr1ofq3r0kh6FbU3aw4es= +go.etcd.io/etcd/pkg/v3 v3.6.8/go.mod h1:TRibVNe+FqJIe1abOAA1PsuQ4wqO87ZaOoprg09Tn8c= +go.etcd.io/etcd/server/v3 v3.6.8 h1:U2strdSEy1U8qcSzRIdkYpvOPtBy/9i/IfaaCI9flZ4= +go.etcd.io/etcd/server/v3 v3.6.8/go.mod h1:88dCtwUnSirkUoJbflQxxWXqtBSZa6lSG0Kuej+dois= +go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ= +go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 h1:XmiuHzgJt067+a6kwyAzkhXooYVv3/TOw9cM2VfJgUM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0/go.mod h1:KDgtbWKTQs4bM+VPUr6WlL9m/WXcmkCcBlIzqxPGzmI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0= +go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c= +go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs= +go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ= +go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0= +go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= +golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0= +golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= -google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= +google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= -k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= -k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= -k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/apiserver v0.31.1 h1:Sars5ejQDCRBY5f7R3QFHdqN3s61nhkpaX8/k1iEw1c= -k8s.io/apiserver v0.31.1/go.mod h1:lzDhpeToamVZJmmFlaLwdYZwd7zB+WYRYIboqA1kGxM= -k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= -k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= -k8s.io/cloud-provider v0.31.1 h1:40b6AgDizwm5eWratZbqubTHMob25VWr6NX2Ei5TwZA= -k8s.io/cloud-provider v0.31.1/go.mod h1:xAdkE7fdZdu9rKLuOZUMBfagu7bM+bas3iPux/2nLGg= -k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8= -k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w= -k8s.io/component-helpers v0.31.1 h1:5hZUf3747atdgtR3gPntrG35rC2CkK7rYq2KUraz6Os= -k8s.io/component-helpers v0.31.1/go.mod h1:ye0Gi8KzFNTfpIuzvVDtxJQMP/0Owkukf1vGf22Hl6U= -k8s.io/controller-manager v0.31.1 h1:bwiy8y//EG5lJL2mdbOvZWrOgw2EXXIvwp95VYgoIis= -k8s.io/controller-manager v0.31.1/go.mod h1:O440MSE6EI1AEVhB2Fc8FYqv6r8BHrSXjm5aj3886No= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kms v0.31.1 h1:cGLyV3cIwb0ovpP/jtyIe2mEuQ/MkbhmeBF2IYCA9Io= -k8s.io/kms v0.31.1/go.mod h1:OZKwl1fan3n3N5FFxnW5C4V3ygrah/3YXeJWS3O6+94= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -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/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +k8s.io/api v0.36.3 h1:NxB+05W2UGqXWFXcLO0RB5cnqnUPP5v5sVlaOH0Iz4w= +k8s.io/api v0.36.3/go.mod h1:JzLQKqRHC5+I8RVj/lS3lCg0mg6nWI9Fo/Sk3ElxHzg= +k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM= +k8s.io/apimachinery v0.36.3/go.mod h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE= +k8s.io/apiserver v0.36.3 h1:MGSg2SkdfuytiDEcRylT5mQFmmSsbx90XFUO67Y4bsQ= +k8s.io/apiserver v0.36.3/go.mod h1:fVH7zv9EUNUA7Fl7LtDKh8aB9W7u1VQPSGtWV5SjUxg= +k8s.io/client-go v0.36.3 h1:M4JdVzXxYcZk4fGpfDdYnxSwhLKWCFoQsHW6t+z8Hfg= +k8s.io/client-go v0.36.3/go.mod h1:gcPwr0c87vjjG6HB6pWEqOeuYVoXSsREjzux2j6GF30= +k8s.io/cloud-provider v0.36.3 h1:M5Nu+Dms8w5WIWJ+kmazaXCpTy3sRPxxFkksTH23MmA= +k8s.io/cloud-provider v0.36.3/go.mod h1:OEXyTpOUQz+wrw8F3b+DwwDORz1FiR8+vvxk7UvEedM= +k8s.io/component-base v0.36.3 h1:vc/UFvPCkW0irPz84LAodAL1j3f4xktPM6dDJIEheAY= +k8s.io/component-base v0.36.3/go.mod h1:hZbNFG+gCMl9EbykDGEu73feKP9/Cq6JsV4pTo9GTO8= +k8s.io/component-helpers v0.36.3 h1:hya22S0Mto0SlHaiD4kMIi817f/tK7uTMsShxrDKQaY= +k8s.io/component-helpers v0.36.3/go.mod h1:QjREK1lOFXR+jxTqzrtHgOtzUc2s9sm8zuFSiK+TW+c= +k8s.io/controller-manager v0.36.3 h1:GUP9E6+1EUEzxZgceOw2I+jyuahrTluadj6ZoZ/1Sbw= +k8s.io/controller-manager v0.36.3/go.mod h1:zrjaNqXRz4vfK5TdOQZEfOiTofcyIKrt/Y+jKdwqLa4= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/kms v0.36.3 h1:uHY7Vfec0IhuTWjO6u/u/6hE1DcZmCB7Xm/6+GQxkNs= +k8s.io/kms v0.36.3/go.mod h1:g91diTD9h0oJCCHkTb00krlF+Qm5HTnkWLi9Q/TpRoc= +k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad h1:oXImqH8mQNk7PmvzKhmN3ddJoY6OnyM225MXwGHPm0A= +k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad/go.mod h1:0/mqHCVhlumdJ3BhCfnjSZQE037nAhNodh1/hK0T8/I= +k8s.io/streaming v0.36.3 h1:9rAaqBk0C0Pc7+/fqGekj07NV+/Xrew58p647A0JT8w= +k8s.io/streaming v0.36.3/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s= +k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 h1:jVkFFVfXdXP74B/zbO3hM3hpSFD0xvhQ5U686DPurkE= +k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3/go.mod h1:M2s5JB1lIYP3jzZdorPLHXIPJzt9vv2muW5a6L9DtNM= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v6 v6.4.2 h1:qdOxHwrl2Kaag1aQEarlYcOA9vSyGCp3CIki3aW8c4Q= +sigs.k8s.io/structured-merge-diff/v6 v6.4.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/serverscom/instances.go b/serverscom/instances.go index 2a84d1b..be9f46e 100644 --- a/serverscom/instances.go +++ b/serverscom/instances.go @@ -53,7 +53,8 @@ func (i *instances) NodeAddresses(ctx context.Context, nodeName types.NodeName) } func (i *instances) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) { - instanceType, instanceID, err := parseProviderID(providerID) + info, err := parseProviderID(providerID) + instanceType, instanceID := info.nodeType, info.instanceID if err != nil { return nil, err } @@ -88,6 +89,13 @@ func (i *instances) NodeAddressesByProviderID(ctx context.Context, providerID st PrivateIPv4Address: host.PrivateIPv4Address, PublicIPv4Address: host.PublicIPv4Address, }), nil + case kubernetesAutoscaleNodeType: + node, err := i.client.KubernetesClusters.GetNode(ctx, info.clusterID, instanceID) + if err != nil { + return nil, fmt.Errorf("can't get kubernetes autoscale node: %s", err.Error()) + } + + return collectKubernetesClusterNodeAddresses(node), nil default: return nil, fmt.Errorf("invalid instance type: %s", instanceType) } @@ -180,12 +188,12 @@ func (i *instances) InstanceType(ctx context.Context, nodeName types.NodeName) ( } func (i *instances) InstanceTypeByProviderID(ctx context.Context, providerID string) (string, error) { - instanceType, _, err := parseProviderID(providerID) + info, err := parseProviderID(providerID) if err != nil { return "", err } - return instanceType, nil + return info.nodeType, nil } func (i *instances) AddSSHKeyToAllInstances(_ context.Context, _ string, _ []byte) error { @@ -197,7 +205,8 @@ func (i *instances) CurrentNodeName(_ context.Context, hostname string) (types.N } func (i *instances) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) { - instanceType, instanceID, err := parseProviderID(providerID) + info, err := parseProviderID(providerID) + instanceType, instanceID := info.nodeType, info.instanceID if err != nil { return false, err } @@ -236,13 +245,26 @@ func (i *instances) InstanceExistsByProviderID(ctx context.Context, providerID s } return host != nil, nil + case kubernetesAutoscaleNodeType: + node, err := i.client.KubernetesClusters.GetNode(ctx, info.clusterID, instanceID) + if err != nil { + // a missing autoscale node is the normal outcome of a scale-down + if isNotFoundError(err) { + return false, nil + } + + return false, fmt.Errorf("can't get kubernetes autoscale node: %s", err.Error()) + } + + return node != nil, nil default: return false, fmt.Errorf("invalid instance type: %s", instanceType) } } func (i *instances) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) { - instanceType, instanceID, err := parseProviderID(providerID) + info, err := parseProviderID(providerID) + instanceType, instanceID := info.nodeType, info.instanceID if err != nil { return true, err } @@ -269,6 +291,13 @@ func (i *instances) InstanceShutdownByProviderID(ctx context.Context, providerID } return host.PowerStatus == "powered_off", nil + case kubernetesAutoscaleNodeType: + // autoscale nodes have no power state, so an existing one is never shut down + if _, err := i.client.KubernetesClusters.GetNode(ctx, info.clusterID, instanceID); err != nil { + return false, fmt.Errorf("can't get kubernetes autoscale node: %s", err.Error()) + } + + return false, nil default: return true, fmt.Errorf("invalid instance type: %s", instanceType) } diff --git a/serverscom/instances_test.go b/serverscom/instances_test.go index 150f080..cda3175 100644 --- a/serverscom/instances_test.go +++ b/serverscom/instances_test.go @@ -2,6 +2,7 @@ package serverscom import ( "context" + "errors" "testing" . "github.com/onsi/gomega" @@ -803,3 +804,291 @@ func TestInstances_InstanceShutdownByProviderIDWithKubernetesBaremetalNode(t *te g.Expect(err).To(BeNil()) g.Expect(isShutdown).To(Equal(false)) } + +func TestInstances_NodeAddressesByProviderIDWithAutoscaleNode(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + nodeName := "my-super-node1" + ctx := context.TODO() + + node := cli.KubernetesClusterNode{ + ID: "9V8Mjm2p", + ClusterID: "X4bR2mQ9", + Hostname: nodeName, + PrivateIPv4Address: "127.0.0.1", + PublicIPv4Address: "127.0.0.2", + } + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(&node, nil) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + addresses, err := instances.NodeAddressesByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).To(BeNil()) + g.Expect(addresses).NotTo(BeNil()) + g.Expect(len(addresses)).To(Equal(3)) + + g.Expect(addresses[0].Address).To(Equal(nodeName)) + g.Expect(addresses[0].Type).To(Equal(v1.NodeHostName)) + + g.Expect(addresses[1].Address).To(Equal("127.0.0.1")) + g.Expect(addresses[1].Type).To(Equal(v1.NodeInternalIP)) + + g.Expect(addresses[2].Address).To(Equal("127.0.0.2")) + g.Expect(addresses[2].Type).To(Equal(v1.NodeExternalIP)) +} + +func TestInstances_NodeAddressesByProviderIDWithAutoscaleNodeWithoutIPs(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + nodeName := "my-super-node1" + ctx := context.TODO() + + node := cli.KubernetesClusterNode{ + ID: "9V8Mjm2p", + ClusterID: "X4bR2mQ9", + Hostname: nodeName, + } + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(&node, nil) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + addresses, err := instances.NodeAddressesByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).To(BeNil()) + g.Expect(len(addresses)).To(Equal(1)) + + g.Expect(addresses[0].Address).To(Equal(nodeName)) + g.Expect(addresses[0].Type).To(Equal(v1.NodeHostName)) +} + +func TestInstances_NodeAddressesByProviderIDWithAutoscaleNodeMissingClusterID(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + // no API call is expected: an autoscale node can't be addressed without a cluster ID + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + addresses, err := instances.NodeAddressesByProviderID(ctx, "serverscom://kubernetes-autoscale-node/9V8Mjm2p") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal(`providerID "serverscom://kubernetes-autoscale-node/9V8Mjm2p" for node type kubernetes-autoscale-node is missing the cluster ID, expected serverscom://kubernetes-autoscale-node//`)) + g.Expect(addresses).To(BeNil()) +} + +func TestInstances_NodeAddressesByProviderIDWithUnknownType(t *testing.T) { + g := NewGomegaWithT(t) + + ctx := context.TODO() + + instances := newInstances(cli.NewClient("some")) + addresses, err := instances.NodeAddressesByProviderID(ctx, "serverscom://some-new-type/a") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal("invalid instance type: some-new-type")) + g.Expect(addresses).To(BeNil()) +} + +func TestInstances_InstanceTypeByProviderIDWithAutoscaleNode(t *testing.T) { + g := NewGomegaWithT(t) + + ctx := context.TODO() + + instances := newInstances(cli.NewClient("some")) + instanceType, err := instances.InstanceTypeByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).To(BeNil()) + g.Expect(instanceType).To(Equal(kubernetesAutoscaleNodeType)) +} + +func TestInstances_InstanceExistsByProviderIDWithAutoscaleNode(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + node := cli.KubernetesClusterNode{ + ID: "9V8Mjm2p", + ClusterID: "X4bR2mQ9", + Hostname: "my-super-node1", + } + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(&node, nil) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + exists, err := instances.InstanceExistsByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).To(BeNil()) + g.Expect(exists).To(Equal(true)) +} + +// A node removed by a scale-down must be reported as non-existent, not as an error, +// so that kubernetes can clean up the Node object. +func TestInstances_InstanceExistsByProviderIDWithAutoscaleNodeNotFound(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(nil, &cli.NotFoundError{}) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + exists, err := instances.InstanceExistsByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).To(BeNil()) + g.Expect(exists).To(Equal(false)) +} + +// Any other API error must be propagated without concluding anything about existence. +func TestInstances_InstanceExistsByProviderIDWithAutoscaleNodeError(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(nil, &cli.InternalServerError{Message: "some error"}) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + exists, err := instances.InstanceExistsByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(ContainSubstring("can't get kubernetes autoscale node:")) + g.Expect(exists).To(Equal(false)) +} + +func TestInstances_InstanceExistsByProviderIDWithAutoscaleNodeMissingClusterID(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + exists, err := instances.InstanceExistsByProviderID(ctx, "serverscom://kubernetes-autoscale-node/9V8Mjm2p") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal(`providerID "serverscom://kubernetes-autoscale-node/9V8Mjm2p" for node type kubernetes-autoscale-node is missing the cluster ID, expected serverscom://kubernetes-autoscale-node//`)) + g.Expect(exists).To(Equal(false)) +} + +func TestInstances_InstanceExistsByProviderIDWithUnknownType(t *testing.T) { + g := NewGomegaWithT(t) + + ctx := context.TODO() + + instances := newInstances(cli.NewClient("some")) + exists, err := instances.InstanceExistsByProviderID(ctx, "serverscom://some-new-type/a") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal("invalid instance type: some-new-type")) + g.Expect(exists).To(Equal(false)) +} + +// An autoscale node has no power state, so an existing one is never shut down. +func TestInstances_InstanceShutdownByProviderIDWithAutoscaleNode(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + node := cli.KubernetesClusterNode{ + ID: "9V8Mjm2p", + ClusterID: "X4bR2mQ9", + Hostname: "my-super-node1", + } + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(&node, nil) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + isShutdown, err := instances.InstanceShutdownByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).To(BeNil()) + g.Expect(isShutdown).To(Equal(false)) +} + +func TestInstances_InstanceShutdownByProviderIDWithAutoscaleNodeError(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(nil, errors.New("some error")) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + instances := newInstances(client) + isShutdown, err := instances.InstanceShutdownByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal("can't get kubernetes autoscale node: some error")) + g.Expect(isShutdown).To(Equal(false)) +} + +func TestInstances_InstanceShutdownByProviderIDWithUnknownType(t *testing.T) { + g := NewGomegaWithT(t) + + ctx := context.TODO() + + instances := newInstances(cli.NewClient("some")) + isShutdown, err := instances.InstanceShutdownByProviderID(ctx, "serverscom://some-new-type/a") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal("invalid instance type: some-new-type")) + g.Expect(isShutdown).To(Equal(true)) +} diff --git a/serverscom/testing/cloud_computing_instances_mock.go b/serverscom/testing/cloud_computing_instances_mock.go index 42c3178..cf3cfac 100644 --- a/serverscom/testing/cloud_computing_instances_mock.go +++ b/serverscom/testing/cloud_computing_instances_mock.go @@ -86,7 +86,7 @@ func (mr *MockCloudComputingInstancesServiceMockRecorder) Create(ctx, input any) } // CreatePTRRecord mocks base method. -func (m *MockCloudComputingInstancesService) CreatePTRRecord(ctx context.Context, cloudInstanceID string, input serverscom.PTRRecordCreateInput) (*serverscom.PTRRecord, error) { +func (m *MockCloudComputingInstancesService) CreatePTRRecord(ctx context.Context, cloudInstanceID string, input serverscom.CloudComputingInstancePTRRecordCreateInput) (*serverscom.PTRRecord, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreatePTRRecord", ctx, cloudInstanceID, input) ret0, _ := ret[0].(*serverscom.PTRRecord) @@ -187,6 +187,21 @@ func (mr *MockCloudComputingInstancesServiceMockRecorder) PowerOn(ctx, id any) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PowerOn", reflect.TypeOf((*MockCloudComputingInstancesService)(nil).PowerOn), ctx, id) } +// Reboot mocks base method. +func (m *MockCloudComputingInstancesService) Reboot(ctx context.Context, id string) (*serverscom.CloudComputingInstance, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Reboot", ctx, id) + ret0, _ := ret[0].(*serverscom.CloudComputingInstance) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Reboot indicates an expected call of Reboot. +func (mr *MockCloudComputingInstancesServiceMockRecorder) Reboot(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reboot", reflect.TypeOf((*MockCloudComputingInstancesService)(nil).Reboot), ctx, id) +} + // Reinstall mocks base method. func (m *MockCloudComputingInstancesService) Reinstall(ctx context.Context, id string, input serverscom.CloudComputingInstanceReinstallInput) (*serverscom.CloudComputingInstance, error) { m.ctrl.T.Helper() diff --git a/serverscom/testing/hosts_mock.go b/serverscom/testing/hosts_mock.go index 1f4f6d9..5072a57 100644 --- a/serverscom/testing/hosts_mock.go +++ b/serverscom/testing/hosts_mock.go @@ -71,6 +71,141 @@ func (mr *MockHostsServiceMockRecorder) ActivateDedicatedServerPubliIPv6Network( return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateDedicatedServerPubliIPv6Network", reflect.TypeOf((*MockHostsService)(nil).ActivateDedicatedServerPubliIPv6Network), ctx, id) } +// ActivateDisaggregatedPrivatePortsFeature mocks base method. +func (m *MockHostsService) ActivateDisaggregatedPrivatePortsFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivateDisaggregatedPrivatePortsFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivateDisaggregatedPrivatePortsFeature indicates an expected call of ActivateDisaggregatedPrivatePortsFeature. +func (mr *MockHostsServiceMockRecorder) ActivateDisaggregatedPrivatePortsFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateDisaggregatedPrivatePortsFeature", reflect.TypeOf((*MockHostsService)(nil).ActivateDisaggregatedPrivatePortsFeature), ctx, serverID) +} + +// ActivateDisaggregatedPublicPortsFeature mocks base method. +func (m *MockHostsService) ActivateDisaggregatedPublicPortsFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivateDisaggregatedPublicPortsFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivateDisaggregatedPublicPortsFeature indicates an expected call of ActivateDisaggregatedPublicPortsFeature. +func (mr *MockHostsServiceMockRecorder) ActivateDisaggregatedPublicPortsFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateDisaggregatedPublicPortsFeature", reflect.TypeOf((*MockHostsService)(nil).ActivateDisaggregatedPublicPortsFeature), ctx, serverID) +} + +// ActivateHostRescueModeFeature mocks base method. +func (m *MockHostsService) ActivateHostRescueModeFeature(ctx context.Context, serverID string, input serverscom.HostRescueModeFeatureInput) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivateHostRescueModeFeature", ctx, serverID, input) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivateHostRescueModeFeature indicates an expected call of ActivateHostRescueModeFeature. +func (mr *MockHostsServiceMockRecorder) ActivateHostRescueModeFeature(ctx, serverID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateHostRescueModeFeature", reflect.TypeOf((*MockHostsService)(nil).ActivateHostRescueModeFeature), ctx, serverID, input) +} + +// ActivateNoPrivateIpFeature mocks base method. +func (m *MockHostsService) ActivateNoPrivateIpFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivateNoPrivateIpFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivateNoPrivateIpFeature indicates an expected call of ActivateNoPrivateIpFeature. +func (mr *MockHostsServiceMockRecorder) ActivateNoPrivateIpFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateNoPrivateIpFeature", reflect.TypeOf((*MockHostsService)(nil).ActivateNoPrivateIpFeature), ctx, serverID) +} + +// ActivateNoPublicIpAddressFeature mocks base method. +func (m *MockHostsService) ActivateNoPublicIpAddressFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivateNoPublicIpAddressFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivateNoPublicIpAddressFeature indicates an expected call of ActivateNoPublicIpAddressFeature. +func (mr *MockHostsServiceMockRecorder) ActivateNoPublicIpAddressFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateNoPublicIpAddressFeature", reflect.TypeOf((*MockHostsService)(nil).ActivateNoPublicIpAddressFeature), ctx, serverID) +} + +// ActivateNoPublicNetworkFeature mocks base method. +func (m *MockHostsService) ActivateNoPublicNetworkFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivateNoPublicNetworkFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivateNoPublicNetworkFeature indicates an expected call of ActivateNoPublicNetworkFeature. +func (mr *MockHostsServiceMockRecorder) ActivateNoPublicNetworkFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateNoPublicNetworkFeature", reflect.TypeOf((*MockHostsService)(nil).ActivateNoPublicNetworkFeature), ctx, serverID) +} + +// ActivateOobPublicAccessFeature mocks base method. +func (m *MockHostsService) ActivateOobPublicAccessFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivateOobPublicAccessFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivateOobPublicAccessFeature indicates an expected call of ActivateOobPublicAccessFeature. +func (mr *MockHostsServiceMockRecorder) ActivateOobPublicAccessFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivateOobPublicAccessFeature", reflect.TypeOf((*MockHostsService)(nil).ActivateOobPublicAccessFeature), ctx, serverID) +} + +// ActivatePrivateIpxeBootFeature mocks base method. +func (m *MockHostsService) ActivatePrivateIpxeBootFeature(ctx context.Context, serverID string, input serverscom.PrivateIpxeBootFeatureInput) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivatePrivateIpxeBootFeature", ctx, serverID, input) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivatePrivateIpxeBootFeature indicates an expected call of ActivatePrivateIpxeBootFeature. +func (mr *MockHostsServiceMockRecorder) ActivatePrivateIpxeBootFeature(ctx, serverID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivatePrivateIpxeBootFeature", reflect.TypeOf((*MockHostsService)(nil).ActivatePrivateIpxeBootFeature), ctx, serverID, input) +} + +// ActivatePublicIpxeBootFeature mocks base method. +func (m *MockHostsService) ActivatePublicIpxeBootFeature(ctx context.Context, serverID string, input serverscom.PublicIpxeBootFeatureInput) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ActivatePublicIpxeBootFeature", ctx, serverID, input) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ActivatePublicIpxeBootFeature indicates an expected call of ActivatePublicIpxeBootFeature. +func (mr *MockHostsServiceMockRecorder) ActivatePublicIpxeBootFeature(ctx, serverID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActivatePublicIpxeBootFeature", reflect.TypeOf((*MockHostsService)(nil).ActivatePublicIpxeBootFeature), ctx, serverID, input) +} + // AddDedicatedServerPrivateIPv4Network mocks base method. func (m *MockHostsService) AddDedicatedServerPrivateIPv4Network(ctx context.Context, id string, input serverscom.NetworkInput) (*serverscom.Network, error) { m.ctrl.T.Helper() @@ -101,6 +236,36 @@ func (mr *MockHostsServiceMockRecorder) AddDedicatedServerPublicIPv4Network(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddDedicatedServerPublicIPv4Network", reflect.TypeOf((*MockHostsService)(nil).AddDedicatedServerPublicIPv4Network), ctx, id, input) } +// AddSBMServerPrivateIPv4Network mocks base method. +func (m *MockHostsService) AddSBMServerPrivateIPv4Network(ctx context.Context, id string, input serverscom.NetworkInput) (*serverscom.Network, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddSBMServerPrivateIPv4Network", ctx, id, input) + ret0, _ := ret[0].(*serverscom.Network) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AddSBMServerPrivateIPv4Network indicates an expected call of AddSBMServerPrivateIPv4Network. +func (mr *MockHostsServiceMockRecorder) AddSBMServerPrivateIPv4Network(ctx, id, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSBMServerPrivateIPv4Network", reflect.TypeOf((*MockHostsService)(nil).AddSBMServerPrivateIPv4Network), ctx, id, input) +} + +// AttachSSHKeysToDedicatedServer mocks base method. +func (m *MockHostsService) AttachSSHKeysToDedicatedServer(ctx context.Context, id string, input serverscom.SSHKeyAttachInput) ([]serverscom.SSHKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AttachSSHKeysToDedicatedServer", ctx, id, input) + ret0, _ := ret[0].([]serverscom.SSHKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AttachSSHKeysToDedicatedServer indicates an expected call of AttachSSHKeysToDedicatedServer. +func (mr *MockHostsServiceMockRecorder) AttachSSHKeysToDedicatedServer(ctx, id, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AttachSSHKeysToDedicatedServer", reflect.TypeOf((*MockHostsService)(nil).AttachSSHKeysToDedicatedServer), ctx, id, input) +} + // Collection mocks base method. func (m *MockHostsService) Collection() serverscom.Collection[serverscom.Host] { m.ctrl.T.Helper() @@ -175,6 +340,141 @@ func (mr *MockHostsServiceMockRecorder) CreateSBMServers(ctx, input any) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSBMServers", reflect.TypeOf((*MockHostsService)(nil).CreateSBMServers), ctx, input) } +// DeactivateDisaggregatedPrivatePortsFeature mocks base method. +func (m *MockHostsService) DeactivateDisaggregatedPrivatePortsFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivateDisaggregatedPrivatePortsFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivateDisaggregatedPrivatePortsFeature indicates an expected call of DeactivateDisaggregatedPrivatePortsFeature. +func (mr *MockHostsServiceMockRecorder) DeactivateDisaggregatedPrivatePortsFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivateDisaggregatedPrivatePortsFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivateDisaggregatedPrivatePortsFeature), ctx, serverID) +} + +// DeactivateDisaggregatedPublicPortsFeature mocks base method. +func (m *MockHostsService) DeactivateDisaggregatedPublicPortsFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivateDisaggregatedPublicPortsFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivateDisaggregatedPublicPortsFeature indicates an expected call of DeactivateDisaggregatedPublicPortsFeature. +func (mr *MockHostsServiceMockRecorder) DeactivateDisaggregatedPublicPortsFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivateDisaggregatedPublicPortsFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivateDisaggregatedPublicPortsFeature), ctx, serverID) +} + +// DeactivateHostRescueModeFeature mocks base method. +func (m *MockHostsService) DeactivateHostRescueModeFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivateHostRescueModeFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivateHostRescueModeFeature indicates an expected call of DeactivateHostRescueModeFeature. +func (mr *MockHostsServiceMockRecorder) DeactivateHostRescueModeFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivateHostRescueModeFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivateHostRescueModeFeature), ctx, serverID) +} + +// DeactivateNoPrivateIpFeature mocks base method. +func (m *MockHostsService) DeactivateNoPrivateIpFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivateNoPrivateIpFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivateNoPrivateIpFeature indicates an expected call of DeactivateNoPrivateIpFeature. +func (mr *MockHostsServiceMockRecorder) DeactivateNoPrivateIpFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivateNoPrivateIpFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivateNoPrivateIpFeature), ctx, serverID) +} + +// DeactivateNoPublicIpAddressFeature mocks base method. +func (m *MockHostsService) DeactivateNoPublicIpAddressFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivateNoPublicIpAddressFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivateNoPublicIpAddressFeature indicates an expected call of DeactivateNoPublicIpAddressFeature. +func (mr *MockHostsServiceMockRecorder) DeactivateNoPublicIpAddressFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivateNoPublicIpAddressFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivateNoPublicIpAddressFeature), ctx, serverID) +} + +// DeactivateNoPublicNetworkFeature mocks base method. +func (m *MockHostsService) DeactivateNoPublicNetworkFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivateNoPublicNetworkFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivateNoPublicNetworkFeature indicates an expected call of DeactivateNoPublicNetworkFeature. +func (mr *MockHostsServiceMockRecorder) DeactivateNoPublicNetworkFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivateNoPublicNetworkFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivateNoPublicNetworkFeature), ctx, serverID) +} + +// DeactivateOobPublicAccessFeature mocks base method. +func (m *MockHostsService) DeactivateOobPublicAccessFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivateOobPublicAccessFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivateOobPublicAccessFeature indicates an expected call of DeactivateOobPublicAccessFeature. +func (mr *MockHostsServiceMockRecorder) DeactivateOobPublicAccessFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivateOobPublicAccessFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivateOobPublicAccessFeature), ctx, serverID) +} + +// DeactivatePrivateIpxeBootFeature mocks base method. +func (m *MockHostsService) DeactivatePrivateIpxeBootFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivatePrivateIpxeBootFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivatePrivateIpxeBootFeature indicates an expected call of DeactivatePrivateIpxeBootFeature. +func (mr *MockHostsServiceMockRecorder) DeactivatePrivateIpxeBootFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivatePrivateIpxeBootFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivatePrivateIpxeBootFeature), ctx, serverID) +} + +// DeactivatePublicIpxeBootFeature mocks base method. +func (m *MockHostsService) DeactivatePublicIpxeBootFeature(ctx context.Context, serverID string) (*serverscom.DedicatedServerFeature, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeactivatePublicIpxeBootFeature", ctx, serverID) + ret0, _ := ret[0].(*serverscom.DedicatedServerFeature) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeactivatePublicIpxeBootFeature indicates an expected call of DeactivatePublicIpxeBootFeature. +func (mr *MockHostsServiceMockRecorder) DeactivatePublicIpxeBootFeature(ctx, serverID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeactivatePublicIpxeBootFeature", reflect.TypeOf((*MockHostsService)(nil).DeactivatePublicIpxeBootFeature), ctx, serverID) +} + // DedicatedServerConnections mocks base method. func (m *MockHostsService) DedicatedServerConnections(id string) serverscom.Collection[serverscom.HostConnection] { m.ctrl.T.Helper() @@ -317,6 +617,35 @@ func (mr *MockHostsServiceMockRecorder) DeletePTRRecordForSBMServer(ctx, serverI return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePTRRecordForSBMServer", reflect.TypeOf((*MockHostsService)(nil).DeletePTRRecordForSBMServer), ctx, serverID, ptrRecordID) } +// DeleteSBMServerNetwork mocks base method. +func (m *MockHostsService) DeleteSBMServerNetwork(ctx context.Context, serverID, networkID string) (*serverscom.Network, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteSBMServerNetwork", ctx, serverID, networkID) + ret0, _ := ret[0].(*serverscom.Network) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteSBMServerNetwork indicates an expected call of DeleteSBMServerNetwork. +func (mr *MockHostsServiceMockRecorder) DeleteSBMServerNetwork(ctx, serverID, networkID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSBMServerNetwork", reflect.TypeOf((*MockHostsService)(nil).DeleteSBMServerNetwork), ctx, serverID, networkID) +} + +// DetachSSHKeyFromDedicatedServer mocks base method. +func (m *MockHostsService) DetachSSHKeyFromDedicatedServer(ctx context.Context, serverID, fingerprint string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DetachSSHKeyFromDedicatedServer", ctx, serverID, fingerprint) + ret0, _ := ret[0].(error) + return ret0 +} + +// DetachSSHKeyFromDedicatedServer indicates an expected call of DetachSSHKeyFromDedicatedServer. +func (mr *MockHostsServiceMockRecorder) DetachSSHKeyFromDedicatedServer(ctx, serverID, fingerprint any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetachSSHKeyFromDedicatedServer", reflect.TypeOf((*MockHostsService)(nil).DetachSSHKeyFromDedicatedServer), ctx, serverID, fingerprint) +} + // GetDedicatedServer mocks base method. func (m *MockHostsService) GetDedicatedServer(ctx context.Context, id string) (*serverscom.DedicatedServer, error) { m.ctrl.T.Helper() @@ -377,6 +706,21 @@ func (mr *MockHostsServiceMockRecorder) GetDedicatedServerOOBCredentials(ctx, id return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDedicatedServerOOBCredentials", reflect.TypeOf((*MockHostsService)(nil).GetDedicatedServerOOBCredentials), ctx, id, params) } +// GetDedicatedServerSSHKey mocks base method. +func (m *MockHostsService) GetDedicatedServerSSHKey(ctx context.Context, serverID, fingerprint string) (*serverscom.SSHKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDedicatedServerSSHKey", ctx, serverID, fingerprint) + ret0, _ := ret[0].(*serverscom.SSHKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDedicatedServerSSHKey indicates an expected call of GetDedicatedServerSSHKey. +func (mr *MockHostsServiceMockRecorder) GetDedicatedServerSSHKey(ctx, serverID, fingerprint any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDedicatedServerSSHKey", reflect.TypeOf((*MockHostsService)(nil).GetDedicatedServerSSHKey), ctx, serverID, fingerprint) +} + // GetKubernetesBaremetalNode mocks base method. func (m *MockHostsService) GetKubernetesBaremetalNode(ctx context.Context, id string) (*serverscom.KubernetesBaremetalNode, error) { m.ctrl.T.Helper() @@ -407,6 +751,36 @@ func (mr *MockHostsServiceMockRecorder) GetSBMServer(ctx, id any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSBMServer", reflect.TypeOf((*MockHostsService)(nil).GetSBMServer), ctx, id) } +// GetSBMServerNetwork mocks base method. +func (m *MockHostsService) GetSBMServerNetwork(ctx context.Context, serverID, networkID string) (*serverscom.Network, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSBMServerNetwork", ctx, serverID, networkID) + ret0, _ := ret[0].(*serverscom.Network) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSBMServerNetwork indicates an expected call of GetSBMServerNetwork. +func (mr *MockHostsServiceMockRecorder) GetSBMServerNetwork(ctx, serverID, networkID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSBMServerNetwork", reflect.TypeOf((*MockHostsService)(nil).GetSBMServerNetwork), ctx, serverID, networkID) +} + +// GetSBMServerNetworkUsage mocks base method. +func (m *MockHostsService) GetSBMServerNetworkUsage(ctx context.Context, id string) (*serverscom.NetworkUsage, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSBMServerNetworkUsage", ctx, id) + ret0, _ := ret[0].(*serverscom.NetworkUsage) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSBMServerNetworkUsage indicates an expected call of GetSBMServerNetworkUsage. +func (mr *MockHostsServiceMockRecorder) GetSBMServerNetworkUsage(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSBMServerNetworkUsage", reflect.TypeOf((*MockHostsService)(nil).GetSBMServerNetworkUsage), ctx, id) +} + // KubernetesBaremetalNodeDriveSlots mocks base method. func (m *MockHostsService) KubernetesBaremetalNodeDriveSlots(id string) serverscom.Collection[serverscom.HostDriveSlot] { m.ctrl.T.Helper() @@ -450,6 +824,21 @@ func (mr *MockHostsServiceMockRecorder) KubernetesBaremetalNodePowerFeeds(ctx, i return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KubernetesBaremetalNodePowerFeeds", reflect.TypeOf((*MockHostsService)(nil).KubernetesBaremetalNodePowerFeeds), ctx, id) } +// ListDedicatedServerSSHKeys mocks base method. +func (m *MockHostsService) ListDedicatedServerSSHKeys(ctx context.Context, id string) ([]serverscom.SSHKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListDedicatedServerSSHKeys", ctx, id) + ret0, _ := ret[0].([]serverscom.SSHKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListDedicatedServerSSHKeys indicates an expected call of ListDedicatedServerSSHKeys. +func (mr *MockHostsServiceMockRecorder) ListDedicatedServerSSHKeys(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListDedicatedServerSSHKeys", reflect.TypeOf((*MockHostsService)(nil).ListDedicatedServerSSHKeys), ctx, id) +} + // ListDedicatedServers mocks base method. func (m *MockHostsService) ListDedicatedServers() serverscom.Collection[serverscom.DedicatedServer] { m.ctrl.T.Helper() @@ -672,6 +1061,20 @@ func (mr *MockHostsServiceMockRecorder) ReleaseSBMServer(ctx, id any) *gomock.Ca return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReleaseSBMServer", reflect.TypeOf((*MockHostsService)(nil).ReleaseSBMServer), ctx, id) } +// SBMServerNetworks mocks base method. +func (m *MockHostsService) SBMServerNetworks(id string) serverscom.Collection[serverscom.Network] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SBMServerNetworks", id) + ret0, _ := ret[0].(serverscom.Collection[serverscom.Network]) + return ret0 +} + +// SBMServerNetworks indicates an expected call of SBMServerNetworks. +func (mr *MockHostsServiceMockRecorder) SBMServerNetworks(id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SBMServerNetworks", reflect.TypeOf((*MockHostsService)(nil).SBMServerNetworks), id) +} + // SBMServerPTRRecords mocks base method. func (m *MockHostsService) SBMServerPTRRecords(id string) serverscom.Collection[serverscom.PTRRecord] { m.ctrl.T.Helper() diff --git a/serverscom/testing/kubernetes_clusters_mock.go b/serverscom/testing/kubernetes_clusters_mock.go new file mode 100644 index 0000000..f5d11d6 --- /dev/null +++ b/serverscom/testing/kubernetes_clusters_mock.go @@ -0,0 +1,203 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./vendor/github.com/serverscom/serverscom-go-client/pkg/kubernetes_clusters.go +// +// Generated by this command: +// +// mockgen --destination ./serverscom/testing/kubernetes_clusters_mock.go --package=serverscom_testing --source ./vendor/github.com/serverscom/serverscom-go-client/pkg/kubernetes_clusters.go +// + +// Package serverscom_testing is a generated GoMock package. +package serverscom_testing + +import ( + context "context" + reflect "reflect" + + serverscom "github.com/serverscom/serverscom-go-client/pkg" + gomock "go.uber.org/mock/gomock" +) + +// MockKubernetesClustersService is a mock of KubernetesClustersService interface. +type MockKubernetesClustersService struct { + ctrl *gomock.Controller + recorder *MockKubernetesClustersServiceMockRecorder + isgomock struct{} +} + +// MockKubernetesClustersServiceMockRecorder is the mock recorder for MockKubernetesClustersService. +type MockKubernetesClustersServiceMockRecorder struct { + mock *MockKubernetesClustersService +} + +// NewMockKubernetesClustersService creates a new mock instance. +func NewMockKubernetesClustersService(ctrl *gomock.Controller) *MockKubernetesClustersService { + mock := &MockKubernetesClustersService{ctrl: ctrl} + mock.recorder = &MockKubernetesClustersServiceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockKubernetesClustersService) EXPECT() *MockKubernetesClustersServiceMockRecorder { + return m.recorder +} + +// Collection mocks base method. +func (m *MockKubernetesClustersService) Collection() serverscom.Collection[serverscom.KubernetesCluster] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Collection") + ret0, _ := ret[0].(serverscom.Collection[serverscom.KubernetesCluster]) + return ret0 +} + +// Collection indicates an expected call of Collection. +func (mr *MockKubernetesClustersServiceMockRecorder) Collection() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Collection", reflect.TypeOf((*MockKubernetesClustersService)(nil).Collection)) +} + +// CreateNodeGroup mocks base method. +func (m *MockKubernetesClustersService) CreateNodeGroup(ctx context.Context, clusterID string, input serverscom.KubernetesClusterNodeGroupCreateInput) (*serverscom.KubernetesClusterNodeGroup, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateNodeGroup", ctx, clusterID, input) + ret0, _ := ret[0].(*serverscom.KubernetesClusterNodeGroup) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateNodeGroup indicates an expected call of CreateNodeGroup. +func (mr *MockKubernetesClustersServiceMockRecorder) CreateNodeGroup(ctx, clusterID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNodeGroup", reflect.TypeOf((*MockKubernetesClustersService)(nil).CreateNodeGroup), ctx, clusterID, input) +} + +// DeleteNodeGroup mocks base method. +func (m *MockKubernetesClustersService) DeleteNodeGroup(ctx context.Context, clusterID, nodeGroupID string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteNodeGroup", ctx, clusterID, nodeGroupID) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteNodeGroup indicates an expected call of DeleteNodeGroup. +func (mr *MockKubernetesClustersServiceMockRecorder) DeleteNodeGroup(ctx, clusterID, nodeGroupID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNodeGroup", reflect.TypeOf((*MockKubernetesClustersService)(nil).DeleteNodeGroup), ctx, clusterID, nodeGroupID) +} + +// Get mocks base method. +func (m *MockKubernetesClustersService) Get(ctx context.Context, id string) (*serverscom.KubernetesCluster, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", ctx, id) + ret0, _ := ret[0].(*serverscom.KubernetesCluster) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockKubernetesClustersServiceMockRecorder) Get(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockKubernetesClustersService)(nil).Get), ctx, id) +} + +// GetNode mocks base method. +func (m *MockKubernetesClustersService) GetNode(ctx context.Context, clusterID, nodeID string) (*serverscom.KubernetesClusterNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNode", ctx, clusterID, nodeID) + ret0, _ := ret[0].(*serverscom.KubernetesClusterNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetNode indicates an expected call of GetNode. +func (mr *MockKubernetesClustersServiceMockRecorder) GetNode(ctx, clusterID, nodeID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNode", reflect.TypeOf((*MockKubernetesClustersService)(nil).GetNode), ctx, clusterID, nodeID) +} + +// MoveNodes mocks base method. +func (m *MockKubernetesClustersService) MoveNodes(ctx context.Context, clusterID string, input serverscom.KubernetesClusterMoveNodesInput) ([]serverscom.KubernetesClusterNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MoveNodes", ctx, clusterID, input) + ret0, _ := ret[0].([]serverscom.KubernetesClusterNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// MoveNodes indicates an expected call of MoveNodes. +func (mr *MockKubernetesClustersServiceMockRecorder) MoveNodes(ctx, clusterID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MoveNodes", reflect.TypeOf((*MockKubernetesClustersService)(nil).MoveNodes), ctx, clusterID, input) +} + +// NodeGroups mocks base method. +func (m *MockKubernetesClustersService) NodeGroups(id string) serverscom.Collection[serverscom.KubernetesClusterNodeGroup] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NodeGroups", id) + ret0, _ := ret[0].(serverscom.Collection[serverscom.KubernetesClusterNodeGroup]) + return ret0 +} + +// NodeGroups indicates an expected call of NodeGroups. +func (mr *MockKubernetesClustersServiceMockRecorder) NodeGroups(id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeGroups", reflect.TypeOf((*MockKubernetesClustersService)(nil).NodeGroups), id) +} + +// Nodes mocks base method. +func (m *MockKubernetesClustersService) Nodes(id string) serverscom.Collection[serverscom.KubernetesClusterNode] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Nodes", id) + ret0, _ := ret[0].(serverscom.Collection[serverscom.KubernetesClusterNode]) + return ret0 +} + +// Nodes indicates an expected call of Nodes. +func (mr *MockKubernetesClustersServiceMockRecorder) Nodes(id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nodes", reflect.TypeOf((*MockKubernetesClustersService)(nil).Nodes), id) +} + +// Update mocks base method. +func (m *MockKubernetesClustersService) Update(ctx context.Context, id string, input serverscom.KubernetesClusterUpdateInput) (*serverscom.KubernetesCluster, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", ctx, id, input) + ret0, _ := ret[0].(*serverscom.KubernetesCluster) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockKubernetesClustersServiceMockRecorder) Update(ctx, id, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockKubernetesClustersService)(nil).Update), ctx, id, input) +} + +// UpdateNode mocks base method. +func (m *MockKubernetesClustersService) UpdateNode(ctx context.Context, clusterID, nodeID string, input serverscom.KubernetesClusterNodeUpdateInput) (*serverscom.KubernetesClusterNode, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateNode", ctx, clusterID, nodeID, input) + ret0, _ := ret[0].(*serverscom.KubernetesClusterNode) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateNode indicates an expected call of UpdateNode. +func (mr *MockKubernetesClustersServiceMockRecorder) UpdateNode(ctx, clusterID, nodeID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateNode", reflect.TypeOf((*MockKubernetesClustersService)(nil).UpdateNode), ctx, clusterID, nodeID, input) +} + +// UpdateNodeGroup mocks base method. +func (m *MockKubernetesClustersService) UpdateNodeGroup(ctx context.Context, clusterID, nodeGroupID string, input serverscom.KubernetesClusterNodeGroupUpdateInput) (*serverscom.KubernetesClusterNodeGroup, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateNodeGroup", ctx, clusterID, nodeGroupID, input) + ret0, _ := ret[0].(*serverscom.KubernetesClusterNodeGroup) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateNodeGroup indicates an expected call of UpdateNodeGroup. +func (mr *MockKubernetesClustersServiceMockRecorder) UpdateNodeGroup(ctx, clusterID, nodeGroupID, input any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateNodeGroup", reflect.TypeOf((*MockKubernetesClustersService)(nil).UpdateNodeGroup), ctx, clusterID, nodeGroupID, input) +} diff --git a/serverscom/utils.go b/serverscom/utils.go index 4e54d99..1742ac3 100644 --- a/serverscom/utils.go +++ b/serverscom/utils.go @@ -2,7 +2,7 @@ package serverscom import ( "fmt" - "regexp" + "slices" "sort" "strings" @@ -18,12 +18,26 @@ const ( cloudInstanceType = "cloud-instance" dedicatedServerType = "dedicated-server" kubernetesBaremetalNodeType = "kubernetes-baremetal-node" + kubernetesAutoscaleNodeType = "kubernetes-autoscale-node" searchPatternParamKey = "search_pattern" typeParamKey = "type" ) -var providerIDRE = regexp.MustCompile(`^` + providerName + `://([^/]+)/([^/]+)$`) +// providerIDInfo holds the parsed parts of a providerID. +// +// Two forms are supported: +// +// serverscom:/// — all node types except autoscale +// serverscom://kubernetes-autoscale-node// +// +// clusterID is set only for autoscale nodes: such a node is not a standalone +// resource and can only be addressed by the cluster ID + node ID pair. +type providerIDInfo struct { + nodeType string + clusterID string + instanceID string +} func isNotFoundError(err error) bool { switch err.(type) { @@ -34,21 +48,43 @@ func isNotFoundError(err error) bool { } } -func parseProviderID(providerID string) (string, string, error) { +func parseProviderID(providerID string) (providerIDInfo, error) { providerPrefix := providerName + "://" if !strings.HasPrefix(providerID, providerPrefix) { klog.Infof(" make sure your cluster configured for an external cloud provider") - return "", "", fmt.Errorf("missing prefix %s: %s", providerPrefix, providerID) + return providerIDInfo{}, fmt.Errorf("missing prefix %s: %s", providerPrefix, providerID) } - matches := providerIDRE.FindStringSubmatch(providerID) + parts := strings.Split(strings.TrimPrefix(providerID, providerPrefix), "/") - if len(matches) != 3 { - return "", "", fmt.Errorf("error splitting providerID: %s", providerID) + if slices.Contains(parts, "") { + return providerIDInfo{}, fmt.Errorf("error splitting providerID: %s", providerID) } - return strings.ReplaceAll(matches[1], "_", "-"), matches[2], nil + // the node type segment is normalized to dashes: API type strings are snake_case + // (e.g. "dedicated_server"), while the providerID node types are dashed + nodeType := strings.ReplaceAll(parts[0], "_", "-") + + switch len(parts) { + case 2: + if nodeType == kubernetesAutoscaleNodeType { + return providerIDInfo{}, fmt.Errorf( + "providerID %q for node type %s is missing the cluster ID, expected %s%s//", + providerID, kubernetesAutoscaleNodeType, providerPrefix, kubernetesAutoscaleNodeType) + } + + return providerIDInfo{nodeType: nodeType, instanceID: parts[1]}, nil + case 3: + // a cluster ID segment is only valid for autoscale nodes + if nodeType != kubernetesAutoscaleNodeType { + return providerIDInfo{}, fmt.Errorf("error splitting providerID: %s", providerID) + } + + return providerIDInfo{nodeType: nodeType, clusterID: parts[1], instanceID: parts[2]}, nil + default: + return providerIDInfo{}, fmt.Errorf("error splitting providerID: %s", providerID) + } } func collectCloudInstanceAddresses(cloudInstance *cli.CloudComputingInstance) []v1.NodeAddress { @@ -112,13 +148,41 @@ func collectHostAddresses(host *cli.Host) []v1.NodeAddress { return addresses } +// collectKubernetesClusterNodeAddresses collects addresses of a kubernetes cluster node. +// Unlike hosts, its IP fields are plain strings, so an absent address is an empty one. +func collectKubernetesClusterNodeAddresses(node *cli.KubernetesClusterNode) []v1.NodeAddress { + var addresses []v1.NodeAddress + + addresses = append(addresses, v1.NodeAddress{Address: node.Hostname, Type: v1.NodeHostName}) + + if node.PrivateIPv4Address != "" { + addresses = append( + addresses, + v1.NodeAddress{ + Address: node.PrivateIPv4Address, + Type: v1.NodeInternalIP, + }) + } + + if node.PublicIPv4Address != "" { + addresses = append( + addresses, + v1.NodeAddress{ + Address: node.PublicIPv4Address, + Type: v1.NodeExternalIP, + }) + } + + return addresses +} + func buildExternalID(instanceType, ID string) string { return fmt.Sprintf("%s/%s", instanceType, ID) } func getLoadBalancerName(srv *v1.Service, clusterName string) string { ret := "a" + string(srv.UID) - ret = strings.Replace(ret, "-", "", -1) + ret = strings.ReplaceAll(ret, "-", "") if len(ret) > 32 { ret = ret[:32] } diff --git a/serverscom/utils_test.go b/serverscom/utils_test.go new file mode 100644 index 0000000..db23d16 --- /dev/null +++ b/serverscom/utils_test.go @@ -0,0 +1,185 @@ +package serverscom + +import ( + "testing" + + . "github.com/onsi/gomega" + cli "github.com/serverscom/serverscom-go-client/pkg" + v1 "k8s.io/api/core/v1" +) + +func TestParseProviderID(t *testing.T) { + tests := []struct { + name string + providerID string + expected providerIDInfo + errMsg string + }{ + { + name: "cloud instance", + providerID: "serverscom://cloud-instance/G0aK9O7v", + expected: providerIDInfo{nodeType: cloudInstanceType, instanceID: "G0aK9O7v"}, + }, + { + name: "dedicated server", + providerID: "serverscom://dedicated-server/a", + expected: providerIDInfo{nodeType: dedicatedServerType, instanceID: "a"}, + }, + { + name: "kubernetes baremetal node", + providerID: "serverscom://kubernetes-baremetal-node/a", + expected: providerIDInfo{nodeType: kubernetesBaremetalNodeType, instanceID: "a"}, + }, + { + name: "underscores in node type are normalized", + providerID: "serverscom://kubernetes_baremetal_node/a", + expected: providerIDInfo{nodeType: kubernetesBaremetalNodeType, instanceID: "a"}, + }, + { + name: "autoscale node", + providerID: "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p", + expected: providerIDInfo{ + nodeType: kubernetesAutoscaleNodeType, + clusterID: "X4bR2mQ9", + instanceID: "9V8Mjm2p", + }, + }, + { + name: "autoscale node with underscores in node type", + providerID: "serverscom://kubernetes_autoscale_node/X4bR2mQ9/9V8Mjm2p", + expected: providerIDInfo{ + nodeType: kubernetesAutoscaleNodeType, + clusterID: "X4bR2mQ9", + instanceID: "9V8Mjm2p", + }, + }, + { + name: "unknown node type is passed through", + providerID: "serverscom://some-new-type/a", + expected: providerIDInfo{nodeType: "some-new-type", instanceID: "a"}, + }, + { + name: "autoscale node without cluster id", + providerID: "serverscom://kubernetes-autoscale-node/9V8Mjm2p", + errMsg: `providerID "serverscom://kubernetes-autoscale-node/9V8Mjm2p" for node type kubernetes-autoscale-node is missing the cluster ID, expected serverscom://kubernetes-autoscale-node//`, + }, + { + name: "four part form is rejected for non autoscale types", + providerID: "serverscom://cloud-instance/X4bR2mQ9/9V8Mjm2p", + errMsg: "error splitting providerID: serverscom://cloud-instance/X4bR2mQ9/9V8Mjm2p", + }, + { + name: "missing prefix", + providerID: "cloud-instance/a", + errMsg: "missing prefix serverscom://: cloud-instance/a", + }, + { + name: "wrong prefix", + providerID: "aws://cloud-instance/a", + errMsg: "missing prefix serverscom://: aws://cloud-instance/a", + }, + { + name: "node type only", + providerID: "serverscom://cloud-instance", + errMsg: "error splitting providerID: serverscom://cloud-instance", + }, + { + name: "too many segments", + providerID: "serverscom://kubernetes-autoscale-node/a/b/c", + errMsg: "error splitting providerID: serverscom://kubernetes-autoscale-node/a/b/c", + }, + { + name: "empty instance id", + providerID: "serverscom://cloud-instance/", + errMsg: "error splitting providerID: serverscom://cloud-instance/", + }, + { + name: "empty cluster id", + providerID: "serverscom://kubernetes-autoscale-node//9V8Mjm2p", + errMsg: "error splitting providerID: serverscom://kubernetes-autoscale-node//9V8Mjm2p", + }, + { + name: "empty node type", + providerID: "serverscom:///a", + errMsg: "error splitting providerID: serverscom:///a", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewGomegaWithT(t) + + info, err := parseProviderID(tt.providerID) + + if tt.errMsg != "" { + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal(tt.errMsg)) + g.Expect(info).To(Equal(providerIDInfo{})) + + return + } + + g.Expect(err).To(BeNil()) + g.Expect(info).To(Equal(tt.expected)) + }) + } +} + +func TestCollectKubernetesClusterNodeAddresses(t *testing.T) { + tests := []struct { + name string + node cli.KubernetesClusterNode + expected []v1.NodeAddress + }{ + { + name: "hostname and both addresses", + node: cli.KubernetesClusterNode{ + Hostname: "my-super-node1", + PrivateIPv4Address: "127.0.0.1", + PublicIPv4Address: "127.0.0.2", + }, + expected: []v1.NodeAddress{ + {Address: "my-super-node1", Type: v1.NodeHostName}, + {Address: "127.0.0.1", Type: v1.NodeInternalIP}, + {Address: "127.0.0.2", Type: v1.NodeExternalIP}, + }, + }, + { + name: "private address only", + node: cli.KubernetesClusterNode{ + Hostname: "my-super-node1", + PrivateIPv4Address: "127.0.0.1", + }, + expected: []v1.NodeAddress{ + {Address: "my-super-node1", Type: v1.NodeHostName}, + {Address: "127.0.0.1", Type: v1.NodeInternalIP}, + }, + }, + { + name: "public address only", + node: cli.KubernetesClusterNode{ + Hostname: "my-super-node1", + PublicIPv4Address: "127.0.0.2", + }, + expected: []v1.NodeAddress{ + {Address: "my-super-node1", Type: v1.NodeHostName}, + {Address: "127.0.0.2", Type: v1.NodeExternalIP}, + }, + }, + { + name: "hostname only", + node: cli.KubernetesClusterNode{Hostname: "my-super-node1"}, + expected: []v1.NodeAddress{ + {Address: "my-super-node1", Type: v1.NodeHostName}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewGomegaWithT(t) + + g.Expect(collectKubernetesClusterNodeAddresses(&tt.node)).To(Equal(tt.expected)) + }) + } +} diff --git a/serverscom/zones.go b/serverscom/zones.go index 0f19a83..a935bc7 100644 --- a/serverscom/zones.go +++ b/serverscom/zones.go @@ -23,7 +23,8 @@ func (z zones) GetZone(_ context.Context) (cloudprovider.Zone, error) { } func (z zones) GetZoneByProviderID(ctx context.Context, providerID string) (cloudprovider.Zone, error) { - instanceType, instanceID, err := parseProviderID(providerID) + info, err := parseProviderID(providerID) + instanceType, instanceID := info.nodeType, info.instanceID if err != nil { return cloudprovider.Zone{}, err } @@ -50,6 +51,13 @@ func (z zones) GetZoneByProviderID(ctx context.Context, providerID string) (clou } return cloudprovider.Zone{Region: host.LocationCode}, nil + case kubernetesAutoscaleNodeType: + node, err := z.client.KubernetesClusters.GetNode(ctx, info.clusterID, instanceID) + if err != nil { + return cloudprovider.Zone{}, fmt.Errorf("can't get kubernetes autoscale node: %s", err.Error()) + } + + return cloudprovider.Zone{Region: node.LocationCode}, nil default: return cloudprovider.Zone{}, fmt.Errorf("invalid instance type: %s", instanceType) } diff --git a/serverscom/zones_test.go b/serverscom/zones_test.go new file mode 100644 index 0000000..e4111ef --- /dev/null +++ b/serverscom/zones_test.go @@ -0,0 +1,97 @@ +package serverscom + +import ( + "context" + "errors" + "testing" + + . "github.com/onsi/gomega" + serverscom_testing "github.com/serverscom/cloud-controller-manager/serverscom/testing" + cli "github.com/serverscom/serverscom-go-client/pkg" + gomock "go.uber.org/mock/gomock" +) + +func TestZones_GetZoneByProviderIDWithAutoscaleNode(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + node := cli.KubernetesClusterNode{ + ID: "9V8Mjm2p", + ClusterID: "X4bR2mQ9", + Hostname: "my-super-node1", + LocationCode: "ams1", + } + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(&node, nil) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + zones := newZones(client, "default-zone") + zone, err := zones.GetZoneByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).To(BeNil()) + g.Expect(zone.Region).To(Equal("ams1")) +} + +func TestZones_GetZoneByProviderIDWithAutoscaleNodeError(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + clustersService.EXPECT().GetNode(ctx, "X4bR2mQ9", "9V8Mjm2p").Return(nil, errors.New("some error")) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + zones := newZones(client, "default-zone") + zone, err := zones.GetZoneByProviderID(ctx, "serverscom://kubernetes-autoscale-node/X4bR2mQ9/9V8Mjm2p") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal("can't get kubernetes autoscale node: some error")) + g.Expect(zone.Region).To(BeEmpty()) +} + +func TestZones_GetZoneByProviderIDWithAutoscaleNodeMissingClusterID(t *testing.T) { + g := NewGomegaWithT(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.TODO() + + // no API call is expected: the cluster ID is required to address the node + clustersService := serverscom_testing.NewMockKubernetesClustersService(ctrl) + + client := cli.NewClient("some") + client.KubernetesClusters = clustersService + + zones := newZones(client, "default-zone") + zone, err := zones.GetZoneByProviderID(ctx, "serverscom://kubernetes-autoscale-node/9V8Mjm2p") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal(`providerID "serverscom://kubernetes-autoscale-node/9V8Mjm2p" for node type kubernetes-autoscale-node is missing the cluster ID, expected serverscom://kubernetes-autoscale-node//`)) + g.Expect(zone.Region).To(BeEmpty()) +} + +func TestZones_GetZoneByProviderIDWithUnknownType(t *testing.T) { + g := NewGomegaWithT(t) + + ctx := context.TODO() + + zones := newZones(cli.NewClient("some"), "default-zone") + zone, err := zones.GetZoneByProviderID(ctx, "serverscom://some-new-type/a") + + g.Expect(err).NotTo(BeNil()) + g.Expect(err.Error()).To(Equal("invalid instance type: some-new-type")) + g.Expect(zone.Region).To(BeEmpty()) +}