Created
February 26, 2021 15:55
-
-
Save eip/ebf848beb8a1d16a4949d44b23cd3355 to your computer and use it in GitHub Desktop.
Save Grafana Dashboards to files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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