|
package main |
|
|
|
import ( |
|
"errors" |
|
"flag" |
|
"fmt" |
|
"os" |
|
|
|
"github.com/devans10/pugo/pure1" |
|
) |
|
|
|
type config struct { |
|
appID string |
|
pemFile string |
|
|
|
start int |
|
end int |
|
resolution int |
|
metricName string |
|
aggregation string |
|
resourceName string |
|
} |
|
|
|
const ( |
|
june26 = 1687782856000 |
|
july26 = 1690374856000 |
|
resolution = 1800000000000 |
|
) |
|
|
|
func main() { |
|
cfg := &config{} |
|
|
|
flag.StringVar(&cfg.appID, "app-id", "", "The application ID you generated in Pure1") |
|
flag.StringVar(&cfg.pemFile, "private-key", "", "The path to your private rsa key") |
|
flag.IntVar(&cfg.start, "from", june26, "Start time in epoch") |
|
flag.IntVar(&cfg.end, "to", july26, "End time in epoch") |
|
flag.IntVar(&cfg.resolution, "resolution", resolution, "Data resolution (duration between data points)") |
|
flag.StringVar(&cfg.aggregation, "aggregation", "avg", "avg or max") |
|
flag.StringVar(&cfg.metricName, "metric", "", "The name of the metric to fetch") |
|
flag.StringVar(&cfg.resourceName, "resource", "", "The name of the resource (array, volume) to fetch metrics about") |
|
|
|
flag.Parse() |
|
|
|
if err := validate(cfg); err != nil { |
|
fmt.Println(err) |
|
os.Exit(1) |
|
} |
|
|
|
privateKey, err := os.ReadFile(cfg.pemFile) |
|
if err != nil { |
|
fmt.Println(err) |
|
os.Exit(1) |
|
} |
|
|
|
restVersion := "1.0" |
|
|
|
client, err := pure1.NewClient(cfg.appID, privateKey, restVersion) |
|
if err != nil { |
|
fmt.Println(err) |
|
os.Exit(1) |
|
} |
|
|
|
params := map[string]string{ |
|
// "names": "'array_effective_used_space'", // this gives me nothing and i have no idea why |
|
"names": "'array_total_capacity','array_unique_space','array_effective_used_space','array_shared_space','array_volume_space'", |
|
} |
|
|
|
if cfg.metricName != "" { |
|
params = map[string]string{ |
|
"names": fmt.Sprintf("'%s'", cfg.metricName), |
|
} |
|
} |
|
|
|
params["resource_names"] = fmt.Sprintf("'%s'", cfg.resourceName) |
|
|
|
// could get usage by array or by volume, array probably more useful |
|
// "Effective used is a metric utilized in billing for the ES2 program" |
|
// "All arrays in a license must run Purity v6.1.9 to generate this report." |
|
// is that billing and license not on? is that why i see nothing? |
|
|
|
// aggregation := "'avg'" // avg or max |
|
// start := 1687782856000 // 26 june 2023 <- get this wrong and this will 400, even though this array is quite old so def exists |
|
// end := 1690374856000 // 26 july 2023 |
|
// resolution := 1800000000000 // <- really not sure what this means but when i increase the number i get fewer results and when the number is not big enough i get an error |
|
|
|
agg := fmt.Sprintf("'%s'", cfg.aggregation) // this is so annoying |
|
|
|
allMetrics, err := client.Metrics.GetMetricHistory(agg, cfg.start, cfg.end, cfg.resolution, params) |
|
if err != nil { |
|
fmt.Println(err) |
|
os.Exit(1) |
|
} |
|
|
|
fmt.Println("Metrics for resource: " + cfg.resourceName) |
|
fmt.Println("") |
|
|
|
if len(allMetrics) == 0 { |
|
fmt.Println("no metrics found") |
|
os.Exit(0) |
|
} |
|
|
|
for _, metric := range allMetrics { |
|
fmt.Println(metric.Name) |
|
// fmt.Println(metric.Resources[0]) |
|
fmt.Println("Unit: " + metric.Unit) |
|
|
|
data := metric.Data |
|
|
|
if len(data) == 0 { |
|
fmt.Println("Data: []") |
|
fmt.Println("") |
|
|
|
continue |
|
} |
|
|
|
res := []string{} |
|
for _, dat := range data { |
|
d, ok := dat.([]interface{}) // this all feels very safe |
|
if !ok { |
|
fmt.Printf("could not cast metric data to slice of interface: %#v\n", dat) |
|
|
|
continue |
|
} |
|
|
|
for _, i := range d { |
|
num, ok := i.(float64) |
|
if !ok { |
|
fmt.Printf("could not cast metric data to float64: %#v\n", num) |
|
|
|
continue |
|
} |
|
|
|
res = append(res, fmt.Sprintf("%.0f", num)) |
|
} |
|
|
|
} |
|
|
|
fmt.Printf("Data %v\n", res) |
|
fmt.Println("") |
|
} |
|
} |
|
|
|
func validate(cfg *config) error { |
|
if cfg.appID == "" { |
|
return errors.New("app-id required") |
|
} |
|
|
|
if cfg.pemFile == "" { |
|
return errors.New("private-key required") |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// func array() { |
|
// arr, err := client.Arrays.GetArrays(nil) |
|
// if err != nil { |
|
// fmt.Println(err) |
|
// os.Exit(1) |
|
// } |
|
|
|
// array := arr[0] |
|
|
|
// fmt.Println("ID: ", array.ID) |
|
// fmt.Println("Name: ", array.Name) |
|
// fmt.Println("Model: ", array.Model) |
|
// fmt.Println("OS: ", array.OS) |
|
// fmt.Println("Version: ", array.Version) |
|
// fmt.Println("AsOf: ", array.AsOf) |
|
// } |
|
|
|
// type Metric struct { |
|
// ID string `json:"id,omitempty"` |
|
// Name string `json:"name,omitempty"` |
|
// AsOf int `json:"_as_of,omitempty"` |
|
// Availabilities []interface{} `json:"availabilities,omitempty"` |
|
// Data []interface{} `json:"data,omitempty"` |
|
// Description string `json:"description,omitempty"` |
|
// ResourceTypes interface{} `json:"resource_types,omitempty"` |
|
// Resources []interface{} `json:"resources,omitempty"` |
|
// Resolution int `json:"resolution,omitempty"` |
|
// Unit string `json:"unit,omitempty"` |
|
// } |