Repository: NetApp/harvest
Pull request #226 (2021-06-23 16:34:44)

[Merge to release] port range test cases


Patch:
diff --git a/cmd/tools/doctor/doctor.go b/cmd/tools/doctor/doctor.go
index 94f09cd2..718d8232 100644
--- a/cmd/tools/doctor/doctor.go
+++ b/cmd/tools/doctor/doctor.go
@@ -121,7 +121,8 @@ func checkUniquePromPorts(config conf.HarvestConfig) validation {
 	// map of portNum -> list of names
 	seen := make(map[int][]string)
 	for name, exporter := range *config.Exporters {
-		if exporter.Port == nil || exporter.Type == nil || *exporter.Type != "Prometheus" {
+		// ignore configuration with both port and portrange defined. PortRange takes precedence
+		if exporter.Port == nil || exporter.Type == nil || *exporter.Type != "Prometheus" || exporter.PortRange != nil {
 			continue
 		}
 		previous := seen[*exporter.Port]
@@ -129,6 +130,21 @@ func checkUniquePromPorts(config conf.HarvestConfig) validation {
 		seen[*exporter.Port] = previous
 	}
 
+	// Update PortRanges
+	for name, exporter := range *config.Exporters {
+		if exporter.PortRange == nil || exporter.Type == nil || *exporter.Type != "Prometheus" {
+			continue
+		}
+		portRange := exporter.PortRange
+		start := portRange.Min
+		end := portRange.Max
+		for i := start; i <= end; i++ {
+			previous := seen[i]
+			previous = append(previous, name)
+			seen[i] = previous
+		}
+	}
+
 	valid := validation{isValid: true}
 	for _, exporterNames := range seen {
 		if len(exporterNames) == 1 {
diff --git a/cmd/tools/generate/generate.go b/cmd/tools/generate/generate.go
index db83f282..71a20c46 100644
--- a/cmd/tools/generate/generate.go
+++ b/cmd/tools/generate/generate.go
@@ -61,7 +61,7 @@ func generateDockerCompose(path string) {
 	if err != nil {
 		panic(err)
 	}
-	conf.IsDocker = true
+	conf.ValidatePortInUse = true
 	for _, v := range conf.Config.PollersOrdered {
 		port, _ := conf.GetPrometheusExporterPorts(v)
 		pollerTemplate.Pollers = append(pollerTemplate.Pollers, PollerPort{v, port, absPath})
diff --git a/pkg/conf/conf.go b/pkg/conf/conf.go
index 4ded3b04..338118c8 100644
--- a/pkg/conf/conf.go
+++ b/pkg/conf/conf.go
@@ -56,7 +56,7 @@ func LoadConfig(configPath string) (*node.Node, error) {
 
 var Config = HarvestConfig{}
 var configRead = false
-var IsDocker = false
+var ValidatePortInUse = false
 
 func LoadHarvestConfig(configPath string) error {
 	if configRead {
@@ -192,7 +192,6 @@ func GetHarvestLogPath() string {
 
 /*
 GetPrometheusExporterPorts returns port configured in prometheus exporter for given poller
-If there are more than 1 exporter configured for a poller then return string will have ports as comma seperated
 */
 func GetPrometheusExporterPorts(pollerName string) (int, error) {
 	var port int
@@ -206,7 +205,7 @@ func GetPrometheusExporterPorts(pollerName string) (int, error) {
 	if exporters != nil && len(*exporters) > 0 {
 		for _, e := range *exporters {
 			exporter := (*Config.Exporters)[e]
-			if *exporter.Type == "Prometheus" {
+			if exporter.Type != nil && *exporter.Type == "Prometheus" {
 				isPrometheusExporterConfigured = true
 				if exporter.PortRange != nil {
 					ports := promPortRangeMapping[e]
@@ -222,6 +221,8 @@ func GetPrometheusExporterPorts(pollerName string) (int, error) {
 			}
 			continue
 		}
+	} else {
+		return 0, errors.New(errors.ERR_CONFIG, "Poller does not exist "+pollerName)
 	}
 	if port == 0 && isPrometheusExporterConfigured {
 		return port, errors.New(errors.ERR_CONFIG, "No free port found for poller "+pollerName)
@@ -242,11 +243,11 @@ func PortMapFromRange(address string, portRange *IntRange) PortMap {
 	end := portRange.Max
 	for i := start; i <= end; i++ {
 		portMap.portSet = append(portMap.portSet, i)
-		if IsDocker {
+		if ValidatePortInUse {
 			portMap.freePorts[i] = struct{}{}
 		}
 	}
-	if !IsDocker {
+	if !ValidatePortInUse {
 		portMap.freePorts = util.CheckFreePorts(address, portMap.portSet)
 	}
 	return portMap


Test patch:
diff --git a/cmd/tools/doctor/testdata/testConfig.yml b/cmd/tools/doctor/testdata/testConfig.yml
index 94f2f434..bf6cfd12 100644
--- a/cmd/tools/doctor/testdata/testConfig.yml
+++ b/cmd/tools/doctor/testdata/testConfig.yml
@@ -3,6 +3,10 @@ Tools:
   token: [ 'aaa-bbb-ccc-ddd' ]
 
 Exporters:
+  prometheusrange:
+    exporter: Prometheus
+    addr: 0.0.0.0
+    port_range: 2000-2000
   prometheus:
     exporter: Prometheus
     addr: 0.0.0.0
@@ -85,6 +89,25 @@ Pollers:
     addr: 10.0.0.2
     collectors: [ Zapi ]
 
+  unix-01:
+    datacenter: local
+    addr: localhost
+    collectors:
+      - Unix
+    exporters:
+      - prometheusrange
+
+  # add your Cdot / 7Mode pollers below, example:
+  cluster-02:
+    datacenter: DC-01
+    addr: 1.1.1.1
+    username: username
+    password: password
+    collectors:
+      - Zapi
+    exporters:
+      - prometheusrange
+
   sim-0001:
     is_kfs: true
 
diff --git a/pkg/conf/conf_test.go b/pkg/conf/conf_test.go
new file mode 100644
index 00000000..3869a2d6
--- /dev/null
+++ b/pkg/conf/conf_test.go
@@ -0,0 +1,43 @@
+package conf
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestGetPrometheusExporterPorts(t *testing.T) {
+	path := "../../cmd/tools/doctor/testdata/testConfig.yml"
+	err := LoadHarvestConfig(path)
+	// Test without checking
+	ValidatePortInUse = true
+	if err != nil {
+		panic(err)
+	}
+	type args struct {
+		pollerName string
+	}
+
+	type test struct {
+		name    string
+		args    args
+		wantErr bool
+	}
+	tests := []test{
+		{"success", args{pollerName: "unix-01"}, false},
+		{"failure_no_free_port", args{pollerName: "cluster-02"}, true},
+		{"failure_poller_name_does_not_exist", args{pollerName: "test1"}, true},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := GetPrometheusExporterPorts(tt.args.pollerName)
+			fmt.Println(got)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("GetPrometheusExporterPorts() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if err == nil && got == 0 {
+				t.Errorf("GetPrometheusExporterPorts() got = %v, want %s", got, "non zero value")
+			}
+		})
+	}
+}