add grafana package & temporary debug checks
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
1247fc3fcb
commit
2d08f75545
9 changed files with 373 additions and 0 deletions
60
pkg/grafana/dashboard.go
Normal file
60
pkg/grafana/dashboard.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package grafana
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DashboardVersion struct {
|
||||
ID uint `json:"id"`
|
||||
DashboardID uint `json:"dashboardId"`
|
||||
ParentVersion uint `json:"parentVersion"`
|
||||
RestoredFrom uint `json:"restoredFrom"`
|
||||
Version uint `json:"version"`
|
||||
Created time.Time `json:"created"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func queryParams(params ...QueryParam) url.Values {
|
||||
u := url.URL{}
|
||||
q := u.Query()
|
||||
for _, p := range params {
|
||||
p(&q)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func (c *Client) GetDashboardVersionsByDashboardID(ctx context.Context, dashboardID uint, params ...QueryParam) ([]DashboardVersion, error) {
|
||||
var (
|
||||
raw []byte
|
||||
code int
|
||||
err error
|
||||
)
|
||||
|
||||
if raw, code, err = c.get(ctx, fmt.Sprintf("api/dashboards/id/%d/versions", dashboardID), queryParams(params...)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, fmt.Errorf("HTTP error %d: returns %s", code, raw)
|
||||
}
|
||||
var versions []DashboardVersion
|
||||
err = json.Unmarshal(raw, &versions)
|
||||
|
||||
return versions, err
|
||||
}
|
||||
|
||||
func (c *Client) SearchDashboards(ctx context.Context, query string, starred bool, tags ...string) ([]FoundBoard, error) {
|
||||
params := []SearchParam{
|
||||
SearchType(SearchTypeDashboard),
|
||||
SearchQuery(query),
|
||||
SearchStarred(starred),
|
||||
}
|
||||
for _, tag := range tags {
|
||||
params = append(params, SearchTag(tag))
|
||||
}
|
||||
return c.Search(ctx, params...)
|
||||
}
|
80
pkg/grafana/requests.go
Normal file
80
pkg/grafana/requests.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
package grafana
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var DefaultHTTPClient = http.DefaultClient
|
||||
|
||||
type Client struct {
|
||||
baseURL string
|
||||
key string
|
||||
basicAuth bool
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewClient(apiURL, authString string, client *http.Client) (*Client, error) {
|
||||
basicAuth := strings.Contains(authString, ":")
|
||||
baseURL, err := url.Parse(apiURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var key string
|
||||
if len(authString) > 0 {
|
||||
if !basicAuth {
|
||||
key = fmt.Sprintf("Bearer %s", authString)
|
||||
} else {
|
||||
parts := strings.SplitN(authString, ":", 2)
|
||||
baseURL.User = url.UserPassword(parts[0], parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
return &Client{
|
||||
baseURL: baseURL.String(),
|
||||
basicAuth: basicAuth,
|
||||
key: key,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) doRequest(ctx context.Context, method, query string, params url.Values, buf io.Reader) ([]byte, int, error) {
|
||||
u, _ := url.Parse(c.baseURL)
|
||||
u.Path = path.Join(u.Path, query)
|
||||
if params != nil {
|
||||
u.RawQuery = params.Encode()
|
||||
}
|
||||
req, err := http.NewRequest(method, u.String(), buf)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
if !c.basicAuth && len(c.key) > 0 {
|
||||
req.Header.Set("Authorization", c.key)
|
||||
}
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", "grafana-backuper")
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
return data, resp.StatusCode, err
|
||||
}
|
||||
|
||||
func (c *Client) get(ctx context.Context, query string, params url.Values) ([]byte, int, error) {
|
||||
return c.doRequest(ctx, "GET", query, params, nil)
|
||||
}
|
||||
|
||||
func (c *Client) post(ctx context.Context, query string, params url.Values, body []byte) ([]byte, int, error) {
|
||||
return c.doRequest(ctx, "POST", query, params, bytes.NewBuffer(body))
|
||||
}
|
89
pkg/grafana/search.go
Normal file
89
pkg/grafana/search.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
package grafana
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
SearchTypeFolder SearchParamType = "dash-folder"
|
||||
SearchTypeDashboard SearchParamType = "dash-db"
|
||||
)
|
||||
|
||||
type FoundBoard struct {
|
||||
ID uint `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
Title string `json:"title"`
|
||||
URI string `json:"uri"`
|
||||
URL string `json:"url"`
|
||||
Slug string `json:"slug"`
|
||||
Type string `json:"type"`
|
||||
Tags []string `json:"tags"`
|
||||
IsStarred bool `json:"isStarred"`
|
||||
FolderID int `json:"folderId"`
|
||||
FolderUID string `json:"folderUid"`
|
||||
FolderTitle string `json:"folderTitle"`
|
||||
FolderURL string `json:"folderUrl"`
|
||||
}
|
||||
|
||||
type (
|
||||
// SearchParam is a type for specifying Search params.
|
||||
SearchParam func(*url.Values)
|
||||
// SearchParamType is a type accepted by SearchType func.
|
||||
SearchParamType string
|
||||
// QueryParam is a type for specifying arbitrary API parameters
|
||||
QueryParam func(*url.Values)
|
||||
)
|
||||
|
||||
func (c *Client) Search(ctx context.Context, params ...SearchParam) ([]FoundBoard, error) {
|
||||
var (
|
||||
raw []byte
|
||||
boards []FoundBoard
|
||||
code int
|
||||
err error
|
||||
)
|
||||
u := url.URL{}
|
||||
q := u.Query()
|
||||
for _, p := range params {
|
||||
p(&q)
|
||||
}
|
||||
if raw, code, err = c.get(ctx, "api/search", q); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, fmt.Errorf("HTTP error %d: returns %s", code, raw)
|
||||
}
|
||||
err = json.Unmarshal(raw, &boards)
|
||||
return boards, err
|
||||
}
|
||||
|
||||
func SearchQuery(query string) SearchParam {
|
||||
return func(v *url.Values) {
|
||||
if query != "" {
|
||||
v.Set("query", query)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SearchStarred(starred bool) SearchParam {
|
||||
return func(v *url.Values) {
|
||||
v.Set("starred", strconv.FormatBool(starred))
|
||||
}
|
||||
}
|
||||
|
||||
func SearchTag(tag string) SearchParam {
|
||||
return func(v *url.Values) {
|
||||
if tag != "" {
|
||||
v.Add("tag", tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SearchType(searchType SearchParamType) SearchParam {
|
||||
return func(v *url.Values) {
|
||||
v.Set("type", string(searchType))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue