refactor(grafana): rework grafana package and make it more modular

This commit is contained in:
Tom Neuber 2024-06-23 02:37:22 +02:00
parent cfcf3c6c2b
commit 7ce90dacc4
Signed by: tom
GPG key ID: F17EFE4272D89FF6
12 changed files with 710 additions and 282 deletions

View file

@ -4,142 +4,141 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/url"
"time"
"git.ar21.de/yolokube/grafana-backuper/pkg/grafana/schema"
)
type BoardProperties struct {
IsStarred bool `json:"isStarred,omitempty"`
IsHome bool `json:"isHome,omitempty"`
IsSnapshot bool `json:"isSnapshot,omitempty"`
Type string `json:"type,omitempty"`
CanSave bool `json:"canSave"`
CanEdit bool `json:"canEdit"`
CanStar bool `json:"canStar"`
Slug string `json:"slug"`
Expires time.Time `json:"expires"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
UpdatedBy string `json:"updatedBy"`
CreatedBy string `json:"createdBy"`
Version int `json:"version"`
FolderID int `json:"folderId"`
FolderTitle string `json:"folderTitle"`
FolderURL string `json:"folderUrl"`
type DashboardMeta struct {
IsStarred bool
Type string
CanSave bool
CanEdit bool
CanAdmin bool
CanStar bool
CanDelete bool
Slug string
URL string
Expires time.Time
Created time.Time
Updated time.Time
UpdatedBy string
CreatedBy string
Version uint
HasACL bool
IsFolder bool
FolderID uint
FolderUID string
FolderTitle string
FolderURL string
Provisioned bool
ProvisionedExternalID string
AnnotationsPermissions AnnotationsPermissions
Dashboard any
}
type DashboardVersion struct {
ID uint `json:"id"`
DashboardID uint `json:"dashboardId"`
DashboardUID string `json:"uid"`
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"`
type AnnotationsPermissions struct {
Dashboard AnnotationPermissions
Organization AnnotationPermissions
}
func (c *Client) getRawDashboardByUID(ctx context.Context, path string) ([]byte, BoardProperties, error) {
raw, code, err := c.get(ctx, fmt.Sprintf("api/dashboards/%s", path), nil)
type AnnotationPermissions struct {
CanAdd bool
CanEdit bool
CanDelete bool
}
type DashboardClient struct {
client *Client
}
func (c *DashboardClient) Get(ctx context.Context, uid string) (*DashboardMeta, *Response, error) {
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/dashboards/uid/%s", uid), nil)
if err != nil {
return nil, BoardProperties{}, err
}
if code != 200 {
return raw, BoardProperties{}, fmt.Errorf("HTTP error %d: returns %s", code, raw)
return nil, nil, err
}
var result struct {
Meta BoardProperties `json:"meta"`
}
var body schema.DashboardMeta
dec := json.NewDecoder(bytes.NewReader(raw))
dec.UseNumber()
if err := dec.Decode(&result); err != nil {
return raw, BoardProperties{}, fmt.Errorf("failed unmarshalling dashboard from path %s: %v", path, err)
}
return raw, result.Meta, nil
}
func (c *Client) getRawDashboardFromVersion(ctx context.Context, path string) ([]byte, DashboardVersion, error) {
var versionInfo DashboardVersion
raw, code, err := c.get(ctx, fmt.Sprintf("api/dashboards/%s", path), nil)
resp, err := c.client.Do(req, &body)
if err != nil {
return nil, versionInfo, err
}
if code != 200 {
return raw, versionInfo, fmt.Errorf("HTTP error %d: returns %s", code, raw)
return nil, resp, err
}
dec := json.NewDecoder(bytes.NewReader(raw))
dec.UseNumber()
if err := dec.Decode(&versionInfo); err != nil {
return raw, versionInfo, fmt.Errorf("failed unmarshalling dashboard from path %s: %v", path, err)
}
return raw, versionInfo, nil
return DashboardMetaFromSchema(body), resp, nil
}
func queryParams(params ...QueryParam) url.Values {
u := url.URL{}
q := u.Query()
for _, p := range params {
p(&q)
}
return q
type DashboardCreateOpts struct {
Dashboard any
FolderID uint
FolderUID string
Message string
Overwrite bool
}
func (c *Client) GetDashboardVersionsByDashboardUID(ctx context.Context, uid string, params ...QueryParam) ([]DashboardVersion, error) {
var (
raw []byte
code int
err error
)
func (o DashboardCreateOpts) Validate() error {
if o.FolderUID == "" && o.FolderID == 0 {
return errors.New("folder ID or UID missing")
}
if o.Dashboard == nil {
return errors.New("dashboard is nil")
}
return nil
}
if raw, code, err = c.get(ctx, fmt.Sprintf("api/dashboards/uid/%s/versions", uid), queryParams(params...)); err != nil {
type DashboardCreateResponse struct {
DashboardID uint
DashboardUID string
URL string
Status string
Version uint
Slug string
}
func (c *DashboardClient) Create(
ctx context.Context,
opts DashboardCreateOpts,
) (*DashboardCreateResponse, *Response, error) {
if err := opts.Validate(); err != nil {
return nil, nil, err
}
var reqBody schema.DashboardCreateRequest
reqBody.Dashboard = opts.Dashboard
reqBody.Overwrite = opts.Overwrite
reqBody.Message = opts.Message
if opts.FolderUID != "" {
reqBody.FolderUID = opts.FolderUID
} else {
reqBody.FolderID = opts.FolderID
}
reqBodyData, err := json.Marshal(reqBody)
if err != nil {
return nil, nil, err
}
req, err := c.client.NewRequest(ctx, "POST", "/dashboards/db", bytes.NewReader(reqBodyData))
if err != nil {
return nil, nil, err
}
var respBody schema.DashboardCreateResponse
resp, err := c.client.Do(req, &respBody)
if err != nil {
return nil, resp, err
}
return DashboardCreateResponseFromSchema(respBody), resp, nil
}
func (c *DashboardClient) Delete(ctx context.Context, uid string) (*Response, error) {
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/dashboards/uid/%s", uid), nil)
if 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) GetRawDashboardByUID(ctx context.Context, uid string) ([]byte, BoardProperties, error) {
return c.getRawDashboardByUID(ctx, "uid/"+uid)
}
func (c *Client) GetRawDashboardByUIDAndVersion(ctx context.Context, uid string, version uint) ([]byte, DashboardVersion, error) {
return c.getRawDashboardFromVersion(ctx, "uid/"+uid+"/versions/"+fmt.Sprint(version))
}
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...)
}
func ConvertRawToIndent(raw []byte) (string, error) {
var buf bytes.Buffer
err := json.Indent(&buf, raw, "", " ")
if err != nil {
return "", fmt.Errorf("error pritty-printing raw json string: %v", err)
}
return buf.String(), nil
return c.client.Do(req, nil)
}