Skip to content

Instantly share code, notes, and snippets.

@Callisto13
Last active July 27, 2023 10:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Callisto13/0464ba4ce05a8e77399612a489d928f4 to your computer and use it in GitHub Desktop.
Save Callisto13/0464ba4ce05a8e77399612a489d928f4 to your computer and use it in GitHub Desktop.
Pure1 API test

Using this with the Pure1 API

These are linux instructions, bluescreens you are on your own.

  1. Create a private key openssl genrsa -out private.pem
  2. Create a public key openssl rsa -in private.pem -outform PEM -pubout -out public.pem
  3. Log into PureOne, go to Administration, API Registration and fill in the details: paste in your public key and select Viewer role
  4. Copy the generated Application ID
  5. Execute the binary: ./pure1 --app-id APP_ID --private-key PATH_TO_KEY --resource RESOURCE_NAME
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"`
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment