Skip to content

Instantly share code, notes, and snippets.

@eip
Created February 26, 2021 15:55
Show Gist options
  • Save eip/ebf848beb8a1d16a4949d44b23cd3355 to your computer and use it in GitHub Desktop.
Save eip/ebf848beb8a1d16a4949d44b23cd3355 to your computer and use it in GitHub Desktop.
Save Grafana Dashboards to files
// go build get_dashboards.go
// GF_HOST='localhost:3000' GF_API_KEY='#####' ./get_dashboards
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path"
"time"
)
type options struct {
APIKey string
Host string
Timeout time.Duration
}
type dashboard struct {
ID int `json:"id"`
UID string `json:"uid"`
URI string `json:"uri"`
Title string `json:"title"`
}
func getOptions() (opt *options, ok bool) {
opt = &options{Timeout: 10 * time.Second}
ok = true
if opt.APIKey = os.Getenv("GF_API_KEY"); opt.APIKey == "" {
ok = false
fmt.Println("Environment variable GF_API_KEY not defined")
}
if opt.Host = os.Getenv("GF_HOST"); opt.Host == "" {
ok = false
fmt.Println("Environment variable GF_HOST not defined")
}
return
}
func doRequest(ctx context.Context, opt *options, query string, params url.Values) ([]byte, int, error) {
u, _ := url.Parse(opt.Host)
u.Path = path.Join(u.Path, query)
if params != nil {
u.RawQuery = params.Encode()
}
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return nil, 0, err
}
req = req.WithContext(ctx)
req.Header.Set("Authorization", "Bearer "+opt.APIKey)
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
fmt.Printf("> get %s\n", req.URL)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, 0, err
}
data, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
return data, resp.StatusCode, err
}
func saveDashboard(db dashboard, data []byte) error {
var out bytes.Buffer
if err := json.Indent(&out, data, "", "\t"); err != nil {
return err
}
fn := path.Base(db.URI) + ".json"
fmt.Printf("writing %q dashboard to %s\n", db.Title, fn)
f, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return err
}
defer f.Close()
out.WriteTo(f)
return nil
}
func main() {
opt, ok := getOptions()
if !ok {
return
}
ctx, cancel := context.WithTimeout(context.Background(), opt.Timeout)
defer cancel()
fmt.Println("getting dashboard list...")
params := url.Values{}
params.Set("type", "dash-db")
data, status, err := doRequest(ctx, opt, "/api/search", params)
if err != nil {
fmt.Printf("%d: %v\n", status, err)
return
}
dbs := make([]dashboard, 32)
if err := json.Unmarshal(data, &dbs); err != nil {
fmt.Printf("%v\n", err)
return
}
for _, db := range dbs {
fmt.Println()
data, status, err := doRequest(ctx, opt, "/api/dashboards/uid/"+db.UID, nil)
if err != nil {
fmt.Printf("%d: %v\n", status, err)
break
}
if err := saveDashboard(db, data); err != nil {
fmt.Printf("%v\n", err)
return
}
}
fmt.Println("\ndone!")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment