Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Merge Release/24.02.0 to main #2701

Merged
merged 10 commits into from
Feb 21, 2024
208 changes: 207 additions & 1 deletion CHANGELOG.md

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions cmd/collectors/collectorstest.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package collectors
import (
"bytes"
"compress/gzip"
"fmt"
"github.com/netapp/harvest/v2/pkg/tree"
"github.com/netapp/harvest/v2/pkg/tree/node"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"io"
Expand Down Expand Up @@ -73,3 +76,18 @@ func JSONToGson(path string, flatten bool) []gjson.Result {
gsonCache[path] = result
return result
}

func Params(object string, path string) *node.Node {
yml := `
schedule:
- data: 9999h
objects:
%s: %s
`
yml = fmt.Sprintf(yml, object, path)
root, err := tree.LoadYaml([]byte(yml))
if err != nil {
panic(err)
}
return root
}
5 changes: 3 additions & 2 deletions cmd/collectors/rest/plugins/volume/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ func (v *Volume) updateVolumeLabels(data *matrix.Matrix, volumeMap map[string]vo
cloneSplitEstimateMetric := data.GetMetric("clone_split_estimate")
if cloneSplitEstimateMetric == nil {
if cloneSplitEstimateMetric, err = data.NewMetricFloat64("clone_split_estimate"); err != nil {
v.Logger.Error().Stack().Msg("error while creating clone split estimate metric")
v.Logger.Error().Err(err).Msg("error while creating clone split estimate metric")
return
}
}
for _, volume := range data.GetInstances() {
Expand Down Expand Up @@ -168,7 +169,7 @@ func (v *Volume) handleARWProtection(data *matrix.Matrix) {
// Set all global labels
v.arw.SetGlobalLabels(data.GetGlobalLabels())
arwStatusValue := "Active Mode"
// Case where cluster don't have any volumes, arwStatus show as 'Not Monitoring'
// Case where cluster doesn't have any volumes, arwStatus show as 'Not Monitoring'
if len(data.GetInstances()) == 0 {
arwStatusValue = "Not Monitoring"
}
Expand Down
20 changes: 1 addition & 19 deletions cmd/collectors/rest/rest_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package rest

import (
"fmt"
"github.com/netapp/harvest/v2/cmd/collectors"
"github.com/netapp/harvest/v2/cmd/poller/collector"
"github.com/netapp/harvest/v2/cmd/poller/options"
"github.com/netapp/harvest/v2/pkg/conf"
"github.com/netapp/harvest/v2/pkg/matrix"
"github.com/netapp/harvest/v2/pkg/tree"
"github.com/netapp/harvest/v2/pkg/tree/node"
"github.com/tidwall/gjson"
"os"
"strings"
Expand Down Expand Up @@ -156,26 +153,11 @@ func newRest(object string, path string) *Rest {
opts.Poller = pollerName
opts.HomePath = "testdata"
opts.IsTest = true
ac := collector.New("Rest", object, opts, params(object, path), nil)
ac := collector.New("Rest", object, opts, collectors.Params(object, path), nil)
r := Rest{}
err = r.Init(ac)
if err != nil {
panic(err)
}
return &r
}

func params(object string, path string) *node.Node {
yml := `
schedule:
- data: 9999h
objects:
%s: %s
`
yml = fmt.Sprintf(yml, object, path)
root, err := tree.LoadYaml([]byte(yml))
if err != nil {
panic(err)
}
return root
}
12 changes: 5 additions & 7 deletions cmd/collectors/restperf/restperf.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,23 +468,21 @@ func parseMetricResponses(instanceData gjson.Result, metric map[string]*rest2.Me
subLabelSlice := strings.Split(subLabelsS, ",")
var finalLabels []string
var finalValues []string
var vLen int
subCounters.ForEach(func(_, subCounter gjson.Result) bool {
label := strings.Clone(subCounter.Get("label").String())
subValues := subCounter.Get("values").String()
m := util.ArrayMetricToString(strings.Clone(subValues))
ms := strings.Split(m, ",")
for range ms {
finalLabels = append(finalLabels, label+arrayKeyToken+subLabelSlice[vLen])
vLen++
}
if vLen > len(subLabelSlice) {
if len(ms) > len(subLabelSlice) {
return false
}
for i := range ms {
finalLabels = append(finalLabels, subLabelSlice[i]+arrayKeyToken+label)
}
finalValues = append(finalValues, ms...)
return true
})
if vLen == len(subLabelSlice) {
if len(finalLabels) == len(finalValues) {
mr := metricResponse{
value: strings.Join(finalValues, ","),
label: strings.Join(finalLabels, ","),
Expand Down
2 changes: 1 addition & 1 deletion cmd/collectors/restperf/restperf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func Test_parseMetricResponse(t *testing.T) {
args: args{
instanceData: instanceData, metric: "rss_matrix",
}, want: &metricResponse{
label: "tx_frames#queue_0,tx_frames#queue_1,tx_frames#queue_2,tx_bytes#queue_0,tx_bytes#queue_1,tx_bytes#queue_2",
label: "queue_0#tx_frames,queue_1#tx_frames,queue_2#tx_frames,queue_0#tx_bytes,queue_1#tx_bytes,queue_2#tx_bytes",
value: "6177010,1605252882,0,3,1,4",
isArray: true,
},
Expand Down
2 changes: 2 additions & 0 deletions cmd/collectors/storagegrid/rest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const (
DefaultAPIVersion = "3"
)

var NewClientFunc = NewClient

type Client struct {
client *http.Client
request *http.Request
Expand Down
46 changes: 46 additions & 0 deletions cmd/collectors/storagegrid/rest/dummyclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package rest

import (
"bytes"

"github.com/netapp/harvest/v2/pkg/auth"
"github.com/netapp/harvest/v2/pkg/logging"
"net/http"
"time"
)

// NewDummyClient creates a new dummy client
func NewDummyClient() *Client {
httpClient := &http.Client{
Timeout: time.Second * 10,
}

httpRequest, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)

buffer := new(bytes.Buffer)

logger := logging.Get()

cluster := Cluster{
Name: "TestCluster",
Info: "TestInfo",
UUID: "TestUUID",
Version: [3]int{1, 2, 3},
}

client := &Client{
client: httpClient,
request: httpRequest,
buffer: buffer,
Logger: logger,
baseURL: "http://example.com",
Cluster: cluster,
token: "TestToken",
Timeout: time.Second * 10,
logRest: true,
APIPath: "/api/v1",
auth: &auth.Credentials{},
}

return client
}
20 changes: 18 additions & 2 deletions cmd/collectors/storagegrid/storagegrid.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,12 @@ func (s *StorageGrid) handleResults(result []gjson.Result) uint64 {

mat := s.Matrix[s.Object]

// Keep track of old instances
oldInstances := make(map[string]bool)
for key := range mat.GetInstances() {
oldInstances[key] = true
}

for _, instanceData := range result {
var (
instanceKey string
Expand Down Expand Up @@ -340,6 +346,8 @@ func (s *StorageGrid) handleResults(result []gjson.Result) uint64 {
}
}

delete(oldInstances, instanceKey)

for label, display := range s.Props.InstanceLabels {
value := instanceData.Get(label)
if value.Exists() {
Expand Down Expand Up @@ -393,18 +401,26 @@ func (s *StorageGrid) handleResults(result []gjson.Result) uint64 {
count++
}
}

}
// Remove instances not present in the new set
for key := range oldInstances {
mat.RemoveInstance(key)
s.Logger.Debug().Str("key", key).Msg("removed instance")
}
return count
}

func (s *StorageGrid) initClient() error {
var err error

if s.client, err = srest.NewClient(s.Options.Poller, s.Params.GetChildContentS("client_timeout"), s.Auth); err != nil {
if s.client, err = srest.NewClientFunc(s.Options.Poller, s.Params.GetChildContentS("client_timeout"), s.Auth); err != nil {
return err
}

if s.Options.IsTest {
return nil
}

if err = s.client.Init(5); err != nil {
return err
}
Expand Down
63 changes: 63 additions & 0 deletions cmd/collectors/storagegrid/storagegrid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package storagegrid

import (
"github.com/netapp/harvest/v2/cmd/collectors"
"github.com/netapp/harvest/v2/cmd/collectors/storagegrid/rest"
"github.com/netapp/harvest/v2/cmd/poller/collector"
"github.com/netapp/harvest/v2/cmd/poller/options"
"github.com/netapp/harvest/v2/pkg/auth"
"github.com/netapp/harvest/v2/pkg/conf"
"github.com/tidwall/gjson"
"os"
"testing"
)

const (
pollerName = "test"
)

// newStorageGrid initializes a new StorageGrid instance for testing
func newStorageGrid(object string, path string) (*StorageGrid, error) {
opts := options.New(options.WithConfPath("testdata/conf"))
opts.Poller = pollerName
opts.HomePath = "testdata"
opts.IsTest = true
r := StorageGrid{}
rest.NewClientFunc = func(_ string, _ string, _ *auth.Credentials) (*rest.Client, error) {
return rest.NewDummyClient(), nil
}
ac := collector.New("StorageGrid", object, opts, collectors.Params(object, path), nil)
err := r.Init(ac)
if err != nil {
return nil, err
}
return &r, nil
}

func Test_SGAddRemoveRestInstances(t *testing.T) {
conf.TestLoadHarvestConfig("testdata/config.yml")

sg, err := newStorageGrid("Tenant", "tenant.yaml")
if err != nil {
t.Fatalf("failed to create new StorageGrid: %v", err)
}

testFile(t, sg, "testdata/tenant.json", 9)
testFile(t, sg, "testdata/tenant_delete.json", 8)
testFile(t, sg, "testdata/tenant_add.json", 10)
}

func testFile(t *testing.T, sg *StorageGrid, filename string, expectedLen int) {
output, err := os.ReadFile(filename)
if err != nil {
t.Fatalf("failed to read file: %v", err)
}

data := gjson.Get(string(output), "data")
_ = sg.handleResults(data.Array())

got := len(sg.Matrix[sg.Object].GetInstances())
if got != expectedLen {
t.Errorf("length of matrix = %v, want %v", got, expectedLen)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

name: Tenant
query: grid/accounts-cache
object: tenant
api: v3

counters:
- ^^id => id
- ^name => tenant
- dataBytes => logical_used
- objectCount => objects
- policy.quotaObjectBytes => logical_quota

export_options:
instance_keys:
- id
- tenant
instance_labels:
- tenant
14 changes: 14 additions & 0 deletions cmd/collectors/storagegrid/testdata/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Exporters:
prometheus:
exporter: Prometheus
port: 12990

Defaults:
collectors:
- StorageGrid
exporters:
- prometheus

Pollers:
test:
addr: localhost
Loading
Loading