Repository: NetApp/harvest
Pull request #538 (2021-10-01 18:01:55)

feat: Harvest should support label sets


Patch:
diff --git a/cmd/collectors/zapi/collector/zapi.go b/cmd/collectors/zapi/collector/zapi.go
index 9152aa52..c63149a8 100644
--- a/cmd/collectors/zapi/collector/zapi.go
+++ b/cmd/collectors/zapi/collector/zapi.go
@@ -198,6 +198,11 @@ func (me *Zapi) InitMatrix() error {
 
 	// Add system (cluster) name
 	me.Matrix.SetGlobalLabel("cluster", me.Client.Name())
+	if me.Params.HasChildS("labels") {
+		for _, l := range me.Params.GetChildS("labels").GetChildren() {
+			me.Matrix.SetGlobalLabel(l.GetNameS(), l.GetContentS())
+		}
+	}
 	// For 7mode cluster is same as node
 	if !me.Client.IsClustered() {
 		me.Matrix.SetGlobalLabel("node", me.Client.Name())
diff --git a/cmd/poller/poller.go b/cmd/poller/poller.go
index c14ccda6..317eed6d 100644
--- a/cmd/poller/poller.go
+++ b/cmd/poller/poller.go
@@ -708,7 +708,13 @@ func Union2(hNode *node.Node, poller *conf.Poller) {
 					case "!!seq":
 						// the poller node that's missing is a sequence so add all the children of the sequence
 						for _, seqNode := range valNode.Content {
-							newNode.NewChildS(seqNode.Value, seqNode.Value)
+							if seqNode.Tag == "!!str" {
+								newNode.NewChildS(seqNode.Value, seqNode.Value)
+							} else if seqNode.Tag == "!!map" {
+								for ci := 0; ci < len(seqNode.Content); ci += 2 {
+									newNode.NewChildS(seqNode.Content[ci].Value, seqNode.Content[ci+1].Value)
+								}
+							}
 						}
 					}
 					hNode.AddChild(newNode)
diff --git a/pkg/conf/conf.go b/pkg/conf/conf.go
index dffc170a..3070a9f7 100644
--- a/pkg/conf/conf.go
+++ b/pkg/conf/conf.go
@@ -60,8 +60,8 @@ var Config = HarvestConfig{}
 var configRead = false
 var ValidatePortInUse = false
 
-// Used by testing code to reload a new config
-func loadHarvestConfig(configPath string) error {
+// TestLoadHarvestConfig is used by testing code to reload a new config
+func TestLoadHarvestConfig(configPath string) error {
 	configRead = false
 	return LoadHarvestConfig(configPath)
 }
@@ -416,22 +416,23 @@ type Collector struct {
 }
 
 type Poller struct {
-	Datacenter     *string      `yaml:"datacenter,omitempty"`
-	Addr           *string      `yaml:"addr,omitempty"`
-	AuthStyle      *string      `yaml:"auth_style,omitempty"`
-	Username       *string      `yaml:"username,omitempty"`
-	Password       string       `yaml:"password,omitempty"`
-	UseInsecureTls *bool        `yaml:"use_insecure_tls,omitempty"`
-	SslCert        *string      `yaml:"ssl_cert,omitempty"`
-	SslKey         *string      `yaml:"ssl_key,omitempty"`
-	LogMaxBytes    *int64       `yaml:"log_max_bytes,omitempty"`
-	LogMaxFiles    *int         `yaml:"log_max_files,omitempty"`
-	Exporters      *[]string    `yaml:"exporters,omitempty"`
-	Collectors     *[]Collector `yaml:"collectors,omitempty"`
-	IsKfs          *bool        `yaml:"is_kfs,omitempty"`
-	PollerSchedule *string      `yaml:"poller_schedule,omitempty"`
-	ClientTimeout  *string      `yaml:"client_timeout,omitempty"`
-	LogSet         *[]string    `yaml:"log,omitempty"`
+	Datacenter     *string               `yaml:"datacenter,omitempty"`
+	Addr           *string               `yaml:"addr,omitempty"`
+	AuthStyle      *string               `yaml:"auth_style,omitempty"`
+	Username       *string               `yaml:"username,omitempty"`
+	Password       string                `yaml:"password,omitempty"`
+	UseInsecureTls *bool                 `yaml:"use_insecure_tls,omitempty"`
+	SslCert        *string               `yaml:"ssl_cert,omitempty"`
+	SslKey         *string               `yaml:"ssl_key,omitempty"`
+	LogMaxBytes    *int64                `yaml:"log_max_bytes,omitempty"`
+	LogMaxFiles    *int                  `yaml:"log_max_files,omitempty"`
+	Exporters      *[]string             `yaml:"exporters,omitempty"`
+	Collectors     *[]Collector          `yaml:"collectors,omitempty"`
+	IsKfs          *bool                 `yaml:"is_kfs,omitempty"`
+	PollerSchedule *string               `yaml:"poller_schedule,omitempty"`
+	ClientTimeout  *string               `yaml:"client_timeout,omitempty"`
+	LogSet         *[]string             `yaml:"log,omitempty"`
+	Labels         *[]*map[string]string `yaml:"labels,omitempty"`
 }
 
 func (p *Poller) Union(defaults *Poller) {


Test patch:
diff --git a/cmd/poller/poller_test.go b/cmd/poller/poller_test.go
index 7de0c30a..edb1ebb9 100644
--- a/cmd/poller/poller_test.go
+++ b/cmd/poller/poller_test.go
@@ -1,6 +1,10 @@
 package main
 
-import "testing"
+import (
+	"goharvest2/pkg/conf"
+	"goharvest2/pkg/tree/node"
+	"testing"
+)
 
 func TestPingParsing(t *testing.T) {
 	poller := Poller{}
@@ -52,3 +56,36 @@ round-trip min/avg/max = 0.088/0.088/0.088 ms`,
 		})
 	}
 }
+
+func TestUnion2(t *testing.T) {
+	configPath := "../../cmd/tools/doctor/testdata/testConfig.yml"
+	n := node.NewS("foople")
+	err := conf.TestLoadHarvestConfig(configPath)
+	if err != nil {
+		panic(err)
+	}
+	p, err := conf.GetPoller2(configPath, "infinity2")
+	Union2(n, p)
+	labels := n.GetChildS("labels")
+	if labels == nil {
+		t.Errorf("got nil, want labels")
+	}
+	type label struct {
+		key string
+		val string
+	}
+	wants := []label{
+		{key: "org", val: "abc"},
+		{key: "site", val: "RTP"},
+		{key: "floor", val: "3"},
+	}
+	for i, c := range labels.Children {
+		want := wants[i]
+		if want.key != c.GetNameS() {
+			t.Errorf("got key=%s, want=%s", c.GetNameS(), want.key)
+		}
+		if want.val != c.GetContentS() {
+			t.Errorf("got key=%s, want=%s", c.GetContentS(), want.val)
+		}
+	}
+}
diff --git a/cmd/tools/doctor/testdata/testConfig.yml b/cmd/tools/doctor/testdata/testConfig.yml
index 5beb35b6..54af274f 100644
--- a/cmd/tools/doctor/testdata/testConfig.yml
+++ b/cmd/tools/doctor/testdata/testConfig.yml
@@ -112,6 +112,10 @@ Pollers:
     datacenter: DC-01
     addr: 10.0.0.2
     collectors: [ Zapi ]
+    labels:
+      - org: abc
+      - site: RTP
+      - floor: 3
 
   unix-01:
     datacenter: local
diff --git a/pkg/conf/conf_test.go b/pkg/conf/conf_test.go
index 2d12d4ce..e4ab692b 100644
--- a/pkg/conf/conf_test.go
+++ b/pkg/conf/conf_test.go
@@ -52,7 +52,7 @@ func TestGetPrometheusExporterPortsIssue284(t *testing.T) {
 }
 
 func loadTestData(yml string) {
-	err := loadHarvestConfig(yml)
+	err := TestLoadHarvestConfig(yml)
 	if err != nil {
 		panic(err)
 	}
@@ -225,7 +225,7 @@ func TestCollectorConfig(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			err := loadHarvestConfig(tt.path)
+			err := TestLoadHarvestConfig(tt.path)
 			if err != nil {
 				panic(err)
 			}