diff --git a/pkg/app/server.go b/pkg/app/server.go index 09ce7cad82..f00d9198f1 100644 --- a/pkg/app/server.go +++ b/pkg/app/server.go @@ -204,7 +204,7 @@ func RunKubeStateMetrics(ctx context.Context, opts *options.Options) error { namespaces := opts.Namespaces.GetNamespaces() nsFieldSelector := namespaces.GetExcludeNSFieldSelector(opts.NamespacesDenylist) - nodeFieldSelector := opts.Node.GetNodeFieldSelector() + nodeFieldSelector := opts.Node.GetNodeFieldSelector(opts.NoNodeScrape) merged, err := storeBuilder.MergeFieldSelectors([]string{nsFieldSelector, nodeFieldSelector}) if err != nil { return err diff --git a/pkg/options/options.go b/pkg/options/options.go index 2a60f89cad..78a10d64c9 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -46,6 +46,7 @@ type Options struct { Namespaces NamespaceList `yaml:"namespaces"` NamespacesDenylist NamespaceList `yaml:"namespaces_denylist"` Node NodeType `yaml:"node"` + NoNodeScrape bool `yaml:"no_node_scrape"` Pod string `yaml:"pod"` Port int `yaml:"port"` Resources ResourceSet `yaml:"resources"` @@ -120,6 +121,7 @@ func (o *Options) AddFlags(cmd *cobra.Command) { o.cmd.Flags().BoolVar(&o.CustomResourcesOnly, "custom-resource-state-only", false, "Only provide Custom Resource State metrics (experimental)") o.cmd.Flags().BoolVar(&o.EnableGZIPEncoding, "enable-gzip-encoding", false, "Gzip responses when requested by clients via 'Accept-Encoding: gzip' header.") + o.cmd.Flags().BoolVar(&o.NoNodeScrape, "enable-no-node-scrape", false, "This configuration is used in conjunction with node configuration. When this configuration is true, node configuration is empty and the metric of no scheduled pods is scraped. This is experimental.") o.cmd.Flags().BoolVarP(&o.Help, "help", "h", false, "Print Help text") o.cmd.Flags().BoolVarP(&o.UseAPIServerCache, "use-apiserver-cache", "", false, "Sets resourceVersion=0 for ListWatch requests, using cached resources from the apiserver instead of an etcd quorum read.") o.cmd.Flags().Int32Var(&o.Shard, "shard", int32(0), "The instances shard nominal (zero indexed) within the total number of shards. (default 0)") diff --git a/pkg/options/types.go b/pkg/options/types.go index ac0c11275e..a5a1c9ce21 100644 --- a/pkg/options/types.go +++ b/pkg/options/types.go @@ -108,10 +108,13 @@ func (r *ResourceSet) Type() string { type NodeType string // GetNodeFieldSelector returns a nodename field selector. -func (n *NodeType) GetNodeFieldSelector() string { +func (n *NodeType) GetNodeFieldSelector(b bool) string { if string(*n) != "" { return fields.OneTermEqualSelector("spec.nodeName", string(*n)).String() } + if b { + return fields.OneTermEqualSelector("spec.nodeName", "").String() + } return EmptyFieldSelector() } diff --git a/pkg/options/types_test.go b/pkg/options/types_test.go index a1b43a2c0b..96ec0675bc 100644 --- a/pkg/options/types_test.go +++ b/pkg/options/types_test.go @@ -175,7 +175,25 @@ func TestNodeFieldSelector(t *testing.T) { for _, test := range tests { node := test.Node - actual := node.GetNodeFieldSelector() + actual := node.GetNodeFieldSelector(false) + if !reflect.DeepEqual(actual, test.Wanted) { + t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual) + } + } + tests1 := []struct { + Desc string + Node NodeType + Wanted string + }{ + { + Desc: "empty node name", + Node: "", + Wanted: "spec.nodeName=", + }, + } + for _, test := range tests1 { + node := test.Node + actual := node.GetNodeFieldSelector(true) if !reflect.DeepEqual(actual, test.Wanted) { t.Errorf("Test error for Desc: %s. Want: %+v. Got: %+v.", test.Desc, test.Wanted, actual) } @@ -238,7 +256,7 @@ func TestMergeFieldSelectors(t *testing.T) { ns := test.Namespaces deniedNS := test.DeniedNamespaces selector1 := ns.GetExcludeNSFieldSelector(deniedNS) - selector2 := test.Node.GetNodeFieldSelector() + selector2 := test.Node.GetNodeFieldSelector(false) actual, err := MergeFieldSelectors([]string{selector1, selector2}) if err != nil { t.Errorf("Test error for Desc: %s. Can't merge field selector %v.", test.Desc, err)