diff --git a/dashboard.go b/dashboard.go index 2d6418f..a6863b3 100644 --- a/dashboard.go +++ b/dashboard.go @@ -7,19 +7,23 @@ import ( "fmt" "io/ioutil" "log" + "net/url" "os" ) type DashboardMeta struct { - IsStarred bool `json:"isStarred"` - Slug string `json:"slug"` - Folder int64 `json:"folderId"` + IsStarred bool `json:"isStarred"` + Slug string `json:"slug"` + Folder int64 `json:"folderId"` + FolderTitle string `json:"folderTitle"` } +// DashboardSaveResponse grafana response for create dashboard type DashboardSaveResponse struct { Slug string `json:"slug"` - Id int64 `json:"id"` - Uid string `json:"uid"` + ID int64 `json:"id"` + UID string `json:"uid"` + URL string `json:"url"` Status string `json:"status"` Version int64 `json:"version"` } @@ -31,6 +35,24 @@ type Dashboard struct { Overwrite bool `json:overwrite` } +// Dashboards represent json returned by search API +type Dashboards struct { + ID int64 `json:"id"` + UID string `json:"uid"` + Title string `json:"title"` + URI string `json:"uri"` + URL string `json:"url"` + Starred bool `json:"isStarred"` + FolderID int64 `json:"folderId"` + FolderUID string `json:"folderUid"` + FolderTitle string `json:"folderTitle"` +} + +// DashboardDeleteResponse grafana response for delete dashboard +type DashboardDeleteResponse struct { + Title string `json:title` +} + // Deprecated: use NewDashboard instead func (c *Client) SaveDashboard(model map[string]interface{}, overwrite bool) (*DashboardSaveResponse, error) { wrapper := map[string]interface{}{ @@ -93,6 +115,68 @@ func (c *Client) NewDashboard(dashboard Dashboard) (*DashboardSaveResponse, erro return result, err } +// SearchDashboard search a dashboard in Grafana +func (c *Client) SearchDashboard(query string, folderID string) ([]Dashboards, error) { + dashboards := make([]Dashboards, 0) + path := "/api/search" + + params := url.Values{} + params.Add("type", "dash-db") + params.Add("query", query) + params.Add("folderIds", folderID) + + req, err := c.newRequest("GET", path, params, nil) + if err != nil { + return dashboards, err + } + resp, err := c.Do(req) + if err != nil { + return dashboards, err + } + if resp.StatusCode != 200 { + return dashboards, errors.New(resp.Status) + } + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return dashboards, err + } + + err = json.Unmarshal(data, &dashboards) + + return dashboards, err +} + +// GetDashboard get a dashboard by UID +func (c *Client) GetDashboard(uid string) (*Dashboard, error) { + path := fmt.Sprintf("/api/dashboards/uid/%s", uid) + req, err := c.newRequest("GET", path, nil, nil) + if err != nil { + return nil, err + } + + resp, err := c.Do(req) + if err != nil { + return nil, err + } + if resp.StatusCode != 200 { + return nil, errors.New(resp.Status) + } + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + result := &Dashboard{} + err = json.Unmarshal(data, &result) + result.Folder = result.Meta.Folder + if os.Getenv("GF_LOG") != "" { + log.Printf("got back dashboard response %s", data) + } + return result, err +} + +// Deprecated: use GetDashboard instead func (c *Client) Dashboard(slug string) (*Dashboard, error) { path := fmt.Sprintf("/api/dashboards/db/%s", slug) req, err := c.newRequest("GET", path, nil, nil) @@ -122,20 +206,29 @@ func (c *Client) Dashboard(slug string) (*Dashboard, error) { return result, err } -func (c *Client) DeleteDashboard(slug string) error { - path := fmt.Sprintf("/api/dashboards/db/%s", slug) +// DeleteDashboard deletes a grafana dashoboard +func (c *Client) DeleteDashboard(uid string) (string, error) { + deleted := &DashboardDeleteResponse{} + path := fmt.Sprintf("/api/dashboards/uid/%s", uid) req, err := c.newRequest("DELETE", path, nil, nil) if err != nil { - return err + return "", err } resp, err := c.Do(req) if err != nil { - return err + return "", err } if resp.StatusCode != 200 { - return errors.New(resp.Status) + return "", errors.New(resp.Status) } - - return nil + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + err = json.Unmarshal(data, &deleted) + if err != nil { + return "", err + } + return deleted.Title, nil } diff --git a/folder.go b/folder.go index 55613c6..30f2f5c 100644 --- a/folder.go +++ b/folder.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io/ioutil" + "net/url" ) type Folder struct { @@ -57,6 +58,87 @@ func (c *Client) Folder(id int64) (*Folder, error) { return folder, err } +// SearchFolder search a folder in Grafana +func (c *Client) SearchFolder(query string) ([]Folder, error) { + folders := make([]Folder, 0) + path := "/api/search" + + params := url.Values{} + params.Add("type", "dash-folder") + params.Add("query", query) + + req, err := c.newRequest("GET", path, params, nil) + if err != nil { + return folders, err + } + resp, err := c.Do(req) + if err != nil { + return folders, err + } + if resp.StatusCode != 200 { + return folders, errors.New(resp.Status) + } + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return folders, err + } + err = json.Unmarshal(data, &folders) + return folders, err +} + +func (c *Client) FolderByUID(uid string) (*Folder, error) { + folder := &Folder{} + req, err := c.newRequest("GET", fmt.Sprintf("/api/folders/%s", uid), nil, nil) + if err != nil { + return folder, err + } + resp, err := c.Do(req) + if err != nil { + return folder, err + } + if resp.StatusCode != 200 { + return folder, errors.New(resp.Status) + } + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return folder, err + } + err = json.Unmarshal(data, &folder) + return folder, err +} + +// NewFolderWithUID allows to create a new folder by specifying a custom +// UID. It is duplicated in order to maintain compatibility with existent tools +func (c *Client) NewFolderWithUID(title, uid string) (Folder, error) { + folder := Folder{} + dataMap := map[string]string{ + "title": title, + "uid": uid, + } + data, err := json.Marshal(dataMap) + req, err := c.newRequest("POST", "/api/folders", nil, bytes.NewBuffer(data)) + if err != nil { + return folder, err + } + resp, err := c.Do(req) + if err != nil { + return folder, err + } + if resp.StatusCode != 200 { + data, _ = ioutil.ReadAll(resp.Body) + return folder, fmt.Errorf("status: %s body: %s", resp.Status, data) + } + data, err = ioutil.ReadAll(resp.Body) + if err != nil { + return folder, err + } + err = json.Unmarshal(data, &folder) + if err != nil { + return folder, err + } + return folder, err +} + func (c *Client) NewFolder(title string) (Folder, error) { folder := Folder{} dataMap := map[string]string{