github.com/wtfutil/wtf@v0.43.0/modules/grafana/client.go (about)

     1  package grafana
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"net/http"
     9  	"sort"
    10  
    11  	"github.com/wtfutil/wtf/utils"
    12  )
    13  
    14  type AlertState int
    15  
    16  const (
    17  	Alerting AlertState = iota
    18  	Pending
    19  	NoData
    20  	Paused
    21  	Ok
    22  )
    23  
    24  var toString = map[AlertState]string{
    25  	Alerting: "alerting",
    26  	Pending:  "pending",
    27  	NoData:   "no_data",
    28  	Paused:   "paused",
    29  	Ok:       "ok",
    30  }
    31  
    32  var toID = map[string]AlertState{
    33  	"alerting": Alerting,
    34  	"pending":  Pending,
    35  	"no_data":  NoData,
    36  	"paused":   Paused,
    37  	"ok":       Ok,
    38  }
    39  
    40  // MarshalJSON marshals the enum as a quoted json string
    41  func (s AlertState) MarshalJSON() ([]byte, error) {
    42  	buffer := bytes.NewBufferString(`"`)
    43  	buffer.WriteString(toString[s])
    44  	buffer.WriteString(`"`)
    45  	return buffer.Bytes(), nil
    46  }
    47  
    48  // UnmarshalJSON unmashals a quoted json string to the enum value
    49  func (s *AlertState) UnmarshalJSON(b []byte) error {
    50  	var j string
    51  	err := json.Unmarshal(b, &j)
    52  	if err != nil {
    53  		return err
    54  	}
    55  	// if we somehow get an invalid value we'll end up in the alerting state
    56  	*s = toID[j]
    57  	return nil
    58  }
    59  
    60  type Alert struct {
    61  	Name  string     `json:"name"`
    62  	State AlertState `json:"state"`
    63  	URL   string     `json:"url"`
    64  }
    65  
    66  type Client struct {
    67  	apiKey  string
    68  	baseURI string
    69  }
    70  
    71  func NewClient(settings *Settings) *Client {
    72  	return &Client{
    73  		apiKey:  settings.apiKey,
    74  		baseURI: settings.baseURI,
    75  	}
    76  }
    77  
    78  func (client *Client) Alerts() ([]Alert, error) {
    79  	// query the alerts API of Grafana https://grafana.com/docs/grafana/latest/http_api/alerting/
    80  	req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/alerts", client.baseURI), http.NoBody)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	if client.apiKey != "" {
    86  		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", client.apiKey))
    87  	}
    88  
    89  	res, err := http.DefaultClient.Do(req)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	defer func() { _ = res.Body.Close() }()
    94  
    95  	if res.StatusCode != 200 {
    96  		msg := struct {
    97  			Msg string `json:"message"`
    98  		}{}
    99  		err = utils.ParseJSON(&msg, res.Body)
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  		return nil, errors.New(msg.Msg)
   104  	}
   105  
   106  	var out []Alert
   107  	err = utils.ParseJSON(&out, res.Body)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	sort.SliceStable(out, func(i, j int) bool {
   113  		return out[i].State < out[j].State
   114  	})
   115  
   116  	return out, nil
   117  }