Skip to content

Commit

Permalink
feat: adding the bucket and policy rest template (#3374)
Browse files Browse the repository at this point in the history
* feat: add the bucket and policy rest template to the data protection dashboard (#3414)

---------

Co-authored-by: Chris Grindstaff <[email protected]>
  • Loading branch information
Hardikl and cgrinds authored Jan 13, 2025
1 parent f5efb21 commit d4a0c8b
Show file tree
Hide file tree
Showing 23 changed files with 3,803 additions and 1,867 deletions.
82 changes: 82 additions & 0 deletions cmd/collectors/commonutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/netapp/harvest/v2/third_party/tidwall/gjson"
"log/slog"
"os"
"regexp"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -543,3 +544,84 @@ func PopulateIfgroupMetrics(portIfgroupMap map[string]string, portDataMap map[st
}
return nil
}

func HandleDuration(value string) float64 {
// Example: duration: PT8H35M42S
timeDurationRegex := `^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:.\d+)?)S)?$`

regexTimeDuration := regexp.MustCompile(timeDurationRegex)
if match := regexTimeDuration.MatchString(value); match {
// example: PT8H35M42S ==> 30942
matches := regexTimeDuration.FindStringSubmatch(value)
if matches == nil {
return 0
}

seconds := 0.0

// years
// months

// days
if matches[3] != "" {
f, err := strconv.ParseFloat(matches[3], 64)
if err != nil {
fmt.Printf("%v", err)
return 0
}
seconds += f * 24 * 60 * 60
}

// hours
if matches[4] != "" {
f, err := strconv.ParseFloat(matches[4], 64)
if err != nil {
fmt.Printf("%v", err)
return 0
}
seconds += f * 60 * 60
}

// minutes
if matches[5] != "" {
f, err := strconv.ParseFloat(matches[5], 64)
if err != nil {
fmt.Printf("%v", err)
return 0
}
seconds += f * 60
}

// seconds & milliseconds
if matches[6] != "" {
f, err := strconv.ParseFloat(matches[6], 64)
if err != nil {
fmt.Printf("%v", err)
return 0
}
seconds += f
}
return seconds
}

return 0
}

// Example: timestamp: 2020-12-02T18:36:19-08:00
var regexTimeStamp = regexp.MustCompile(
`[+-]?\d{4}(-[01]\d(-[0-3]\d(T[0-2]\d:[0-5]\d:?([0-5]\d(\.\d+)?)?[+-][0-2]\d:[0-5]\d?)?)?)?`)

func HandleTimestamp(value string) float64 {
var timestamp time.Time
var err error

if match := regexTimeStamp.MatchString(value); match {
// example: 2020-12-02T18:36:19-08:00 ==> 1606962979
if timestamp, err = time.Parse(time.RFC3339, value); err != nil {
fmt.Printf("%v", err)
return 0
}
return float64(timestamp.Unix())
}
return 0
}
62 changes: 62 additions & 0 deletions cmd/collectors/commonutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,65 @@ func Test_SplitVscanName(t *testing.T) {
})
}
}

func Test_HandleDuration(t *testing.T) {

type test struct {
timeFieldValue string
want float64
}

var tests = []test{
{
timeFieldValue: "PT54S",
want: 54,
},
{
timeFieldValue: "PT48M",
want: 2880,
},
{
timeFieldValue: "P428DT22H45M19S",
want: 37061119,
},
{
timeFieldValue: "PT8H35M42S",
want: 30942,
},
}

for _, tt := range tests {
t.Run(tt.timeFieldValue, func(t *testing.T) {
if got := HandleDuration(tt.timeFieldValue); got != tt.want {
t.Errorf("actual value = %v, want %v", got, tt.want)
}
})
}
}

func Test_HandleTimestamp(t *testing.T) {

type test struct {
timeFieldValue string
want float64
}

var tests = []test{
{
timeFieldValue: "2020-12-02T18:36:19-08:00",
want: 1606962979,
},
{
timeFieldValue: "2022-01-31T04:05:02-05:00",
want: 1643619902,
},
}

for _, tt := range tests {
t.Run(tt.timeFieldValue, func(t *testing.T) {
if got := HandleTimestamp(tt.timeFieldValue); got != tt.want {
t.Errorf("actual value = %v, want %v", got, tt.want)
}
})
}
}
53 changes: 53 additions & 0 deletions cmd/collectors/rest/plugins/clusterschedule/clusterschedule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package clusterschedule

import (
"github.com/netapp/harvest/v2/cmd/poller/plugin"
"github.com/netapp/harvest/v2/pkg/matrix"
"github.com/netapp/harvest/v2/pkg/util"
"github.com/netapp/harvest/v2/third_party/tidwall/gjson"
"strings"
)

type ClusterScheule struct {
*plugin.AbstractPlugin
}

func New(p *plugin.AbstractPlugin) plugin.Plugin {
return &ClusterScheule{AbstractPlugin: p}
}

func (c *ClusterScheule) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) {
for _, instance := range dataMap[c.Object].GetInstances() {
if cron := instance.GetLabel("cron"); cron != "" {
updateDetailsJSON := gjson.Result{Type: gjson.JSON, Raw: cron}
var minStr, hourStr, dayStr, monthStr, weekDayStr string
var cronVal []string

minStr = list(updateDetailsJSON.Get("minutes"))
hourStr = list(updateDetailsJSON.Get("hours"))
dayStr = list(updateDetailsJSON.Get("days"))
monthStr = list(updateDetailsJSON.Get("months"))
weekDayStr = list(updateDetailsJSON.Get("weekdays"))
cronVal = append(cronVal, minStr, hourStr, dayStr, monthStr, weekDayStr)
cronData := strings.Join(cronVal, " ")
instance.SetLabel("cron", cronData)
instance.SetLabel("schedule", cronData)
}
if interval := instance.GetLabel("interval"); interval != "" {
instance.SetLabel("schedule", interval)
}
}
return nil, nil, nil
}

func list(get gjson.Result) string {
if !get.IsArray() {
return "*"
}
array := get.Array()
items := make([]string, 0, len(array))
for _, e := range array {
items = append(items, e.ClonedString())
}
return strings.Join(items, ",")
}
49 changes: 49 additions & 0 deletions cmd/collectors/rest/plugins/snapshotpolicy/snapshotpolicy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright NetApp Inc, 2024 All rights reserved
*/

package snapshotpolicy

import (
"github.com/netapp/harvest/v2/cmd/poller/plugin"
"github.com/netapp/harvest/v2/pkg/matrix"
"github.com/netapp/harvest/v2/pkg/util"
"github.com/netapp/harvest/v2/third_party/tidwall/gjson"
"slices"
"strconv"
"strings"
)

type SnapshotPolicy struct {
*plugin.AbstractPlugin
}

func New(p *plugin.AbstractPlugin) plugin.Plugin {
return &SnapshotPolicy{AbstractPlugin: p}
}

func (m *SnapshotPolicy) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, *util.Metadata, error) {
// Purge and reset data
data := dataMap[m.Object]

for _, instance := range data.GetInstances() {
copies := instance.GetLabel("copies")
copiesJSON := gjson.Result{Type: gjson.JSON, Raw: "[" + copies + "]"}
var copiesValue int
var schedules []string
for _, copiesData := range copiesJSON.Array() {
count := copiesData.Get("count").ClonedString()
countVal, _ := strconv.Atoi(count)
schedule := copiesData.Get("schedule.name").ClonedString()
schedules = append(schedules, schedule+":"+count)
copiesValue += countVal
}

slices.Sort(schedules)

instance.SetLabel("schedules", strings.Join(schedules, ","))
instance.SetLabel("copies", strconv.Itoa(copiesValue))
}

return nil, nil, nil
}
10 changes: 8 additions & 2 deletions cmd/collectors/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/aggregate"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/certificate"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/cluster"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/clusterschedule"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/clustersoftware"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/disk"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/health"
Expand All @@ -19,6 +20,7 @@ import (
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/securityaccount"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/shelf"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/snapmirror"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/snapshotpolicy"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/svm"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/systemnode"
"github.com/netapp/harvest/v2/cmd/collectors/rest/plugins/volume"
Expand Down Expand Up @@ -472,6 +474,8 @@ func (r *Rest) LoadPlugin(kind string, abc *plugin.AbstractPlugin) plugin.Plugin
return aggregate.New(abc)
case "Cluster":
return cluster.New(abc)
case "ClusterSchedule":
return clusterschedule.New(abc)
case "ClusterSoftware":
return clustersoftware.New(abc)
case "Disk":
Expand All @@ -496,6 +500,8 @@ func (r *Rest) LoadPlugin(kind string, abc *plugin.AbstractPlugin) plugin.Plugin
return collectors.NewSensor(abc)
case "Shelf":
return shelf.New(abc)
case "SnapshotPolicy":
return snapshotpolicy.New(abc)
case "SecurityAccount":
return securityaccount.New(abc)
case "QosPolicyFixed":
Expand Down Expand Up @@ -628,9 +634,9 @@ func (r *Rest) HandleResults(mat *matrix.Matrix, result []gjson.Result, prop *pr
var floatValue float64
switch metric.MetricType {
case "duration":
floatValue = HandleDuration(f.ClonedString())
floatValue = collectors.HandleDuration(f.ClonedString())
case "timestamp":
floatValue = HandleTimestamp(f.ClonedString())
floatValue = collectors.HandleTimestamp(f.ClonedString())
case "":
floatValue = f.Float()
default:
Expand Down
Loading

0 comments on commit d4a0c8b

Please sign in to comment.