From a9d0e53f5cc28785d36fdbfffe91e8f29ba76df5 Mon Sep 17 00:00:00 2001 From: DerekFrank Date: Mon, 6 Oct 2025 15:20:29 -0700 Subject: [PATCH 1/2] refactor: use common sidecar flags functionality --- cmd/csi-snapshotter/main.go | 88 +++++++++---------------------------- 1 file changed, 21 insertions(+), 67 deletions(-) diff --git a/cmd/csi-snapshotter/main.go b/cmd/csi-snapshotter/main.go index 78e9c8204..3d0ee64d1 100644 --- a/cmd/csi-snapshotter/main.go +++ b/cmd/csi-snapshotter/main.go @@ -38,12 +38,12 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/workqueue" klog "k8s.io/klog/v2" "github.com/container-storage-interface/spec/lib/go/csi" "github.com/kubernetes-csi/csi-lib-utils/connection" + libconfig "github.com/kubernetes-csi/csi-lib-utils/config" "github.com/kubernetes-csi/csi-lib-utils/leaderelection" "github.com/kubernetes-csi/csi-lib-utils/metrics" csirpc "github.com/kubernetes-csi/csi-lib-utils/rpc" @@ -74,28 +74,13 @@ const ( // Command line flags var ( - kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig file. Required only when running out of cluster.") - csiAddress = flag.String("csi-address", "/run/csi/socket", "Address of the CSI driver socket.") resyncPeriod = flag.Duration("resync-period", 15*time.Minute, "Resync interval of the controller. Default is 15 minutes") snapshotNamePrefix = flag.String("snapshot-name-prefix", "snapshot", "Prefix to apply to the name of a created snapshot") snapshotNameUUIDLength = flag.Int("snapshot-name-uuid-length", -1, "Length in characters for the generated uuid of a created snapshot. Defaults behavior is to NOT truncate.") - showVersion = flag.Bool("version", false, "Show version.") threads = flag.Int("worker-threads", 10, "Number of worker threads.") csiTimeout = flag.Duration("timeout", defaultCSITimeout, "The timeout for any RPCs to the CSI driver. Default is 1 minute.") extraCreateMetadata = flag.Bool("extra-create-metadata", false, "If set, add snapshot metadata to plugin snapshot requests as parameters.") - leaderElection = flag.Bool("leader-election", false, "Enables leader election.") - leaderElectionNamespace = flag.String("leader-election-namespace", "", "The namespace where the leader election resource exists. Defaults to the pod namespace if not set.") - leaderElectionLeaseDuration = flag.Duration("leader-election-lease-duration", 15*time.Second, "Duration, in seconds, that non-leader candidates will wait to force acquire leadership. Defaults to 15 seconds.") - leaderElectionRenewDeadline = flag.Duration("leader-election-renew-deadline", 10*time.Second, "Duration, in seconds, that the acting leader will retry refreshing leadership before giving up. Defaults to 10 seconds.") - leaderElectionRetryPeriod = flag.Duration("leader-election-retry-period", 5*time.Second, "Duration, in seconds, the LeaderElector clients should wait between tries of actions. Defaults to 5 seconds.") - - kubeAPIQPS = flag.Float64("kube-api-qps", 5, "QPS to use while communicating with the kubernetes apiserver. Defaults to 5.0.") - kubeAPIBurst = flag.Int("kube-api-burst", 10, "Burst to use while communicating with the kubernetes apiserver. Defaults to 10.") - - metricsAddress = flag.String("metrics-address", "", "(deprecated) The TCP network address where the prometheus metrics endpoint will listen (example: `:8080`). The default is empty string, which means metrics endpoint is disabled. Only one of `--metrics-address` and `--http-endpoint` can be set.") - httpEndpoint = flag.String("http-endpoint", "", "The TCP network address where the HTTP server for diagnostics, including metrics and leader election health check, will listen (example: `:8080`). The default is empty string, which means the server is disabled. Only one of `--metrics-address` and `--http-endpoint` can be set.") - metricsPath = flag.String("metrics-path", "/metrics", "The HTTP path where prometheus metrics will be exposed. Default is `/metrics`.") retryIntervalStart = flag.Duration("retry-interval-start", time.Second, "Initial retry interval of failed volume snapshot creation or deletion. It doubles with each failure, up to retry-interval-max. Default is 1 second.") retryIntervalMax = flag.Duration("retry-interval-max", 5*time.Minute, "Maximum retry interval of failed volume snapshot creation or deletion. Default is 5 minutes.") enableNodeDeployment = flag.Bool("node-deployment", false, "Enables deploying the sidecar controller together with a CSI driver on nodes to manage snapshots for node-local volumes.") @@ -118,6 +103,7 @@ func main() { c := logsapi.NewLoggingConfiguration() logsapi.AddGoFlags(c, flag.CommandLine) logs.InitLogs() + standardflags.RegisterCommonFlags(flag.CommandLine) standardflags.AddAutomaxprocs(klog.Infof) flag.Parse() if err := logsapi.ValidateAndApply(c, fg); err != nil { @@ -129,28 +115,25 @@ func main() { klog.Fatal("Error while parsing feature gates: ", err) } - if *showVersion { + if standardflags.Configuration.ShowVersion { fmt.Println(os.Args[0], version) os.Exit(0) } klog.InfoS("Version", "version", version) // If distributed snapshotting is enabled and leaderElection is also set to true, return - if *enableNodeDeployment && *leaderElection { + if *enableNodeDeployment && standardflags.Configuration.LeaderElection { klog.Error("Leader election cannot happen when node-deployment is set to true") os.Exit(1) } // Create the client config. Use kubeconfig if given, otherwise assume in-cluster. - config, err := buildConfig(*kubeconfig) + config, err := libconfig.BuildConfig(standardflags.Configuration.KubeConfig, standardflags.Configuration) if err != nil { klog.Error(err.Error()) os.Exit(1) } - config.QPS = (float32)(*kubeAPIQPS) - config.Burst = *kubeAPIBurst - coreConfig := rest.CopyConfig(config) coreConfig.ContentType = runtime.ContentTypeProtobuf kubeClient, err := kubernetes.NewForConfig(coreConfig) @@ -184,13 +167,13 @@ func main() { // Add Snapshot types to the default Kubernetes so events can be logged for them snapshotscheme.AddToScheme(scheme.Scheme) - if *metricsAddress != "" && *httpEndpoint != "" { + if standardflags.Configuration.MetricsAddress != "" && standardflags.Configuration.HttpEndpoint != "" { klog.Error("only one of `--metrics-address` and `--http-endpoint` can be set.") os.Exit(1) } - addr := *metricsAddress + addr := standardflags.Configuration.MetricsAddress if addr == "" { - addr = *httpEndpoint + addr = standardflags.Configuration.HttpEndpoint } // Connect to CSI. @@ -198,7 +181,7 @@ func main() { ctx := context.Background() csiConn, err := connection.Connect( ctx, - *csiAddress, + standardflags.Configuration.CSIAddress, metricsManager, connection.OnConnectionLoss(connection.ExitOnConnectionLoss())) if err != nil { @@ -226,13 +209,13 @@ func main() { // Prepare http endpoint for metrics + leader election healthz mux := http.NewServeMux() if addr != "" { - metricsManager.RegisterToServer(mux, *metricsPath) + metricsManager.RegisterToServer(mux, standardflags.Configuration.MetricsPath) metricsManager.SetDriverName(driverName) go func() { klog.Infof("ServeMux listening at %q", addr) err := http.ListenAndServe(addr, mux) if err != nil { - klog.Fatalf("Failed to start HTTP server at specified address (%q) and metrics path (%q): %s", addr, *metricsPath, err) + klog.Fatalf("Failed to start HTTP server at specified address (%q) and metrics path (%q): %s", addr, standardflags.Configuration.MetricsPath, err) } }() } @@ -261,7 +244,7 @@ func main() { os.Exit(1) } - klog.V(2).Infof("Start NewCSISnapshotSideCarController with snapshotter [%s] kubeconfig [%s] csiTimeout [%+v] csiAddress [%s] resyncPeriod [%+v] snapshotNamePrefix [%s] snapshotNameUUIDLength [%d]", driverName, *kubeconfig, *csiTimeout, *csiAddress, *resyncPeriod, *snapshotNamePrefix, snapshotNameUUIDLength) + klog.V(2).Infof("Start NewCSISnapshotSideCarController with snapshotter [%s] kubeconfig [%s] csiTimeout [%+v] csiAddress [%s] resyncPeriod [%+v] snapshotNamePrefix [%s] snapshotNameUUIDLength [%d]", driverName, standardflags.Configuration.KubeConfig, *csiTimeout, standardflags.Configuration.CSIAddress, *resyncPeriod, *snapshotNamePrefix, snapshotNameUUIDLength) snapShotter := snapshotter.NewSnapshotter(csiConn) var groupSnapshotter group_snapshotter.GroupSnapshotter @@ -354,44 +337,15 @@ func main() { } } - if !*leaderElection { - run(context.TODO()) - } else { - lockName := fmt.Sprintf("%s-%s", prefix, strings.Replace(driverName, "/", "-", -1)) - // Create a new clientset for leader election to prevent throttling - // due to snapshot sidecar - leClientset, err := kubernetes.NewForConfig(config) - if err != nil { - klog.Fatalf("failed to create leaderelection client: %v", err) - } - le := leaderelection.NewLeaderElection(leClientset, lockName, run) - if *httpEndpoint != "" { - le.PrepareHealthCheck(mux, leaderelection.DefaultHealthCheckTimeout) - } - - if *leaderElectionNamespace != "" { - le.WithNamespace(*leaderElectionNamespace) - } - - le.WithLeaseDuration(*leaderElectionLeaseDuration) - le.WithRenewDeadline(*leaderElectionRenewDeadline) - le.WithRetryPeriod(*leaderElectionRetryPeriod) - if utilfeature.DefaultFeatureGate.Enabled(features.ReleaseLeaderElectionOnExit) { - le.WithReleaseOnCancel(true) - le.WithContext(ctx) - } - - if err := le.Run(); err != nil { - klog.Fatalf("failed to initialize leader election: %v", err) - } - } -} - -func buildConfig(kubeconfig string) (*rest.Config, error) { - if kubeconfig != "" { - return clientcmd.BuildConfigFromFlags("", kubeconfig) - } - return rest.InClusterConfig() + leaderelection.RunWithLeaderElection( + ctx, + config, + standardflags.Configuration, + run, + fmt.Sprintf("%s-%s", prefix, strings.Replace(driverName, "/", "-", -1)), + mux, + utilfeature.DefaultFeatureGate.Enabled(features.ReleaseLeaderElectionOnExit), + ) } func supportsControllerCreateSnapshot(ctx context.Context, conn *grpc.ClientConn) (bool, error) { From d7210adf7acd12e7eb52e239ab1b428ba948b7b0 Mon Sep 17 00:00:00 2001 From: DerekFrank Date: Mon, 3 Nov 2025 13:50:00 -0800 Subject: [PATCH 2/2] updating csi-lib-utils to v0.23 --- go.mod | 14 ++-- go.sum | 4 +- .../csi-lib-utils/config/config.go | 39 +++++++++ .../leaderelection/leader_election.go | 64 +++++++++++++- .../csi-lib-utils/standardflags/flags.go | 83 +++++++++++++++++++ vendor/modules.txt | 13 +-- 6 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 vendor/github.com/kubernetes-csi/csi-lib-utils/config/config.go create mode 100644 vendor/github.com/kubernetes-csi/csi-lib-utils/standardflags/flags.go diff --git a/go.mod b/go.mod index e0201f8ec..2168912b5 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/kubernetes-csi/external-snapshotter/v8 -go 1.24.0 - -toolchain go1.24.6 +go 1.24.6 require ( github.com/container-storage-interface/spec v1.11.0 @@ -10,7 +8,7 @@ require ( github.com/fsnotify/fsnotify v1.9.0 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.7.0 - github.com/kubernetes-csi/csi-lib-utils v0.22.0 + github.com/kubernetes-csi/csi-lib-utils v0.23.0 github.com/kubernetes-csi/csi-test/v5 v5.3.1 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 @@ -19,12 +17,12 @@ require ( github.com/prometheus/common v0.62.0 google.golang.org/grpc v1.72.1 google.golang.org/protobuf v1.36.5 - k8s.io/api v0.34.0 + k8s.io/api v0.34.1 k8s.io/apiextensions-apiserver v0.34.0 - k8s.io/apimachinery v0.34.0 + k8s.io/apimachinery v0.34.1 k8s.io/apiserver v0.34.0 - k8s.io/client-go v0.34.0 - k8s.io/component-base v0.34.0 + k8s.io/client-go v0.34.1 + k8s.io/component-base v0.34.1 k8s.io/component-helpers v0.34.0 k8s.io/klog/v2 v2.130.1 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 diff --git a/go.sum b/go.sum index fde3607a5..a3b0d31b4 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kubernetes-csi/csi-lib-utils v0.22.0 h1:EUAs1+uHGps3OtVj4XVx16urhpI02eu+Z8Vps6plpHY= -github.com/kubernetes-csi/csi-lib-utils v0.22.0/go.mod h1:f+PalKyS4Ujsjb9+m6Rj0W6c28y3nfea3paQ/VqjI28= +github.com/kubernetes-csi/csi-lib-utils v0.23.0 h1:070SC4ubEvJpQak0ibxgv7l5dUoDVdqKyktam6zkm4s= +github.com/kubernetes-csi/csi-lib-utils v0.23.0/go.mod h1:H5+JRXAvb7lpC4nrddI7sfQfaXA1O8Tek3uNrTIx1/g= github.com/kubernetes-csi/csi-test/v5 v5.3.1 h1:Wiukp1In+kif+BFo6q2ExjgB+MbrAz4jZWzGfijypuY= github.com/kubernetes-csi/csi-test/v5 v5.3.1/go.mod h1:7hA2cSYJ6T8CraEZPA6zqkLZwemjBD54XAnPsPC3VpA= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= diff --git a/vendor/github.com/kubernetes-csi/csi-lib-utils/config/config.go b/vendor/github.com/kubernetes-csi/csi-lib-utils/config/config.go new file mode 100644 index 000000000..f29f85e2e --- /dev/null +++ b/vendor/github.com/kubernetes-csi/csi-lib-utils/config/config.go @@ -0,0 +1,39 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package config + +import ( + "github.com/kubernetes-csi/csi-lib-utils/standardflags" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +func BuildConfig(kubeconfig string, opts standardflags.SidecarConfiguration) (*rest.Config, error) { + config, err := buildConfig(kubeconfig) + if err != nil { + return config, err + } + config.QPS = float32(opts.KubeAPIQPS) + config.Burst = opts.KubeAPIBurst + return config, nil +} + +func buildConfig(kubeconfig string) (*rest.Config, error) { + if kubeconfig != "" { + return clientcmd.BuildConfigFromFlags("", kubeconfig) + } + return rest.InClusterConfig() +} diff --git a/vendor/github.com/kubernetes-csi/csi-lib-utils/leaderelection/leader_election.go b/vendor/github.com/kubernetes-csi/csi-lib-utils/leaderelection/leader_election.go index 4045127c5..b67de54f0 100644 --- a/vendor/github.com/kubernetes-csi/csi-lib-utils/leaderelection/leader_election.go +++ b/vendor/github.com/kubernetes-csi/csi-lib-utils/leaderelection/leader_election.go @@ -25,10 +25,12 @@ import ( "strings" "time" + "github.com/kubernetes-csi/csi-lib-utils/standardflags" v1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/leaderelection" "k8s.io/client-go/tools/leaderelection/resourcelock" "k8s.io/client-go/tools/record" @@ -77,6 +79,8 @@ type leaderElection struct { ctx context.Context clientset kubernetes.Interface + + labels map[string]string } // NewLeaderElection returns the default & preferred leader election type @@ -122,6 +126,11 @@ func (l *leaderElection) WithReleaseOnCancel(releaseOnCancel bool) { l.releaseOnCancel = releaseOnCancel } +// WithLabels adds labels to the lease object when this instance becomes leader +func (l *leaderElection) WithLabels(labels map[string]string) { + l.labels = labels +} + // WithContext Add context func (l *leaderElection) WithContext(ctx context.Context) { l.ctx = ctx @@ -176,8 +185,7 @@ func (l *leaderElection) Run() error { Identity: sanitizeName(l.identity), EventRecorder: eventRecorder, } - - lock, err := resourcelock.New(l.resourceLock, l.namespace, sanitizeName(l.lockName), l.clientset.CoreV1(), l.clientset.CoordinationV1(), rlConfig) + lock, err := resourcelock.NewWithLabels(l.resourceLock, l.namespace, sanitizeName(l.lockName), l.clientset.CoreV1(), l.clientset.CoordinationV1(), rlConfig, l.labels) if err != nil { return err } @@ -209,6 +217,58 @@ func (l *leaderElection) Run() error { return nil // should never reach here } +func RunWithLeaderElection( + ctx context.Context, + config *rest.Config, + opts standardflags.SidecarConfiguration, + run func(context.Context), + driverName string, + mux *http.ServeMux, + releaseOnExit bool) { + + logger := klog.FromContext(ctx) + + if !opts.LeaderElection { + run(ctx) + } else { + // Create a new clientset for leader election. When the attacher + // gets busy and its client gets throttled, the leader election + // can proceed without issues. + leClientset, err := kubernetes.NewForConfig(config) + if err != nil { + logger.Error(err, "Failed to create leaderelection client") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + + // Name of config map with leader election lock + le := NewLeaderElection(leClientset, driverName, run) + if opts.HttpEndpoint != "" { + le.PrepareHealthCheck(mux, DefaultHealthCheckTimeout) + } + + if opts.LeaderElectionNamespace != "" { + le.WithNamespace(opts.LeaderElectionNamespace) + } + + if opts.LeaderElectionLabels != nil { + le.WithLabels(opts.LeaderElectionLabels) + } + + le.WithLeaseDuration(opts.LeaderElectionLeaseDuration) + le.WithRenewDeadline(opts.LeaderElectionRenewDeadline) + le.WithRetryPeriod(opts.LeaderElectionRetryPeriod) + if releaseOnExit { + le.WithReleaseOnCancel(true) + le.WithContext(ctx) + } + + if err := le.Run(); err != nil { + logger.Error(err, "Failed to initialize leader election") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + } +} + func defaultLeaderElectionIdentity() (string, error) { return os.Hostname() } diff --git a/vendor/github.com/kubernetes-csi/csi-lib-utils/standardflags/flags.go b/vendor/github.com/kubernetes-csi/csi-lib-utils/standardflags/flags.go new file mode 100644 index 000000000..54a2d12e3 --- /dev/null +++ b/vendor/github.com/kubernetes-csi/csi-lib-utils/standardflags/flags.go @@ -0,0 +1,83 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package standardflags + +import ( + "flag" + "fmt" + "strings" + "time" +) + +type SidecarConfiguration struct { + ShowVersion bool + + KubeConfig string + CSIAddress string + + LeaderElection bool + LeaderElectionNamespace string + LeaderElectionLeaseDuration time.Duration + LeaderElectionRenewDeadline time.Duration + LeaderElectionRetryPeriod time.Duration + LeaderElectionLabels stringMap + + KubeAPIQPS float64 + KubeAPIBurst int + + HttpEndpoint string + MetricsAddress string + MetricsPath string +} + +var Configuration = SidecarConfiguration{} + +func RegisterCommonFlags(flags *flag.FlagSet) { + flags.BoolVar(&Configuration.ShowVersion, "version", false, "Show version.") + flags.StringVar(&Configuration.KubeConfig, "kubeconfig", "", "Absolute path to the kubeconfig file. Required only when running out of cluster.") + flags.StringVar(&Configuration.CSIAddress, "csi-address", "/run/csi/socket", "The gRPC endpoint for Target CSI Volume.") + flags.BoolVar(&Configuration.LeaderElection, "leader-election", false, "Enable leader election.") + flags.StringVar(&Configuration.LeaderElectionNamespace, "leader-election-namespace", "", "Namespace where the leader election resource lives. Defaults to the pod namespace if not set.") + flags.DurationVar(&Configuration.LeaderElectionLeaseDuration, "leader-election-lease-duration", 15*time.Second, "Duration, in seconds, that non-leader candidates will wait to force acquire leadership. Defaults to 15 seconds.") + flags.DurationVar(&Configuration.LeaderElectionRenewDeadline, "leader-election-renew-deadline", 10*time.Second, "Duration, in seconds, that the acting leader will retry refreshing leadership before giving up. Defaults to 10 seconds.") + flags.DurationVar(&Configuration.LeaderElectionRetryPeriod, "leader-election-retry-period", 5*time.Second, "Duration, in seconds, the LeaderElector clients should wait between tries of actions. Defaults to 5 seconds.") + flags.Var(&Configuration.LeaderElectionLabels, "leader-election-labels", "List of labels to add to lease when given replica becomes leader. Formatted as a comma seperated list of key:value labels. Example: 'my-label:my-value,my-second-label:my-second-value'") + flags.Float64Var(&Configuration.KubeAPIQPS, "kube-api-qps", 5, "QPS to use while communicating with the kubernetes apiserver. Defaults to 5.0.") + flags.IntVar(&Configuration.KubeAPIBurst, "kube-api-burst", 10, "Burst to use while communicating with the kubernetes apiserver. Defaults to 10.") + flags.StringVar(&Configuration.HttpEndpoint, "http-endpoint", "", "The TCP network address where the HTTP server for diagnostics, including metrics and leader election health check, will listen (example: `:8080`). The default is empty string, which means the server is disabled. Only one of `--metrics-address` and `--http-endpoint` can be set.") + flags.StringVar(&Configuration.MetricsAddress, "metrics-address", "", "(deprecated) The TCP network address where the prometheus metrics endpoint will listen (example: `:8080`). The default is empty string, which means metrics endpoint is disabled. Only one of `--metrics-address` and `--http-endpoint` can be set.") + flag.StringVar(&Configuration.MetricsPath, "metrics-path", "/metrics", "The HTTP path where prometheus metrics will be exposed. Default is `/metrics`.") +} + +type stringMap map[string]string + +func (sm *stringMap) String() string { + return fmt.Sprintf("%s", *sm) +} + +func (sm *stringMap) Set(value string) error { + outMap := *sm + items := strings.Split(value, ",") + for _, i := range items { + label := strings.Split(i, ":") + if len(label) != 2 { + return fmt.Errorf("malformed item in list of labels: %s", i) + } + outMap[label[0]] = label[1] + } + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 057e98f32..5bc76d69d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -143,8 +143,9 @@ github.com/josharian/intern # github.com/json-iterator/go v1.1.12 ## explicit; go 1.12 github.com/json-iterator/go -# github.com/kubernetes-csi/csi-lib-utils v0.22.0 -## explicit; go 1.24.0 +# github.com/kubernetes-csi/csi-lib-utils v0.23.0 +## explicit; go 1.24.6 +github.com/kubernetes-csi/csi-lib-utils/config github.com/kubernetes-csi/csi-lib-utils/connection github.com/kubernetes-csi/csi-lib-utils/leaderelection github.com/kubernetes-csi/csi-lib-utils/metrics @@ -542,7 +543,7 @@ gopkg.in/inf.v0 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# k8s.io/api v0.34.0 => k8s.io/api v0.34.0 +# k8s.io/api v0.34.1 => k8s.io/api v0.34.0 ## explicit; go 1.24.0 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 @@ -609,7 +610,7 @@ k8s.io/api/storagemigration/v1alpha1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1 -# k8s.io/apimachinery v0.34.0 => k8s.io/apimachinery v0.34.0 +# k8s.io/apimachinery v0.34.1 => k8s.io/apimachinery v0.34.0 ## explicit; go 1.24.0 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -810,7 +811,7 @@ k8s.io/apiserver/pkg/util/x509metrics k8s.io/apiserver/pkg/validation k8s.io/apiserver/pkg/warning k8s.io/apiserver/plugin/pkg/authenticator/token/webhook -# k8s.io/client-go v0.34.0 => k8s.io/client-go v0.34.0 +# k8s.io/client-go v0.34.1 => k8s.io/client-go v0.34.0 ## explicit; go 1.24.0 k8s.io/client-go/applyconfigurations k8s.io/client-go/applyconfigurations/admissionregistration/v1 @@ -1147,7 +1148,7 @@ k8s.io/client-go/util/homedir k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue -# k8s.io/component-base v0.34.0 => k8s.io/component-base v0.34.0 +# k8s.io/component-base v0.34.1 => k8s.io/component-base v0.34.0 ## explicit; go 1.24.0 k8s.io/component-base/cli/flag k8s.io/component-base/compatibility