|  | @@ -5,6 +5,8 @@ import (
 | 
	
		
			
			| 5 | 5 |  	"fmt"
 | 
	
		
			
			| 6 | 6 |  )
 | 
	
		
			
			| 7 | 7 |  
 | 
	
		
			
			|  | 8 | +// dbSearchResponse represents an element of the response to a dashboard search
 | 
	
		
			
			|  | 9 | +// query
 | 
	
		
			
			| 8 | 10 |  type dbSearchResponse struct {
 | 
	
		
			
			| 9 | 11 |  	ID      int      `json:"id"`
 | 
	
		
			
			| 10 | 12 |  	Title   string   `json:"title"`
 | 
	
	
		
			
			|  | @@ -14,24 +16,36 @@ type dbSearchResponse struct {
 | 
	
		
			
			| 14 | 16 |  	Starred bool     `json:"isStarred"`
 | 
	
		
			
			| 15 | 17 |  }
 | 
	
		
			
			| 16 | 18 |  
 | 
	
		
			
			| 17 |  | -type dbUpdateRequest struct {
 | 
	
		
			
			|  | 19 | +// dbCreateOrUpdateRequest represents the request sent to create or update a
 | 
	
		
			
			|  | 20 | +// dashboard
 | 
	
		
			
			|  | 21 | +type dbCreateOrUpdateRequest struct {
 | 
	
		
			
			| 18 | 22 |  	Dashboard rawJSON `json:"dashboard"`
 | 
	
		
			
			| 19 | 23 |  	Overwrite bool    `json:"overwrite"`
 | 
	
		
			
			| 20 | 24 |  }
 | 
	
		
			
			| 21 | 25 |  
 | 
	
		
			
			| 22 |  | -type dbUpdateResponse struct {
 | 
	
		
			
			|  | 26 | +// dbCreateOrUpdateResponse represents the response sent by the Grafana API to
 | 
	
		
			
			|  | 27 | +// a dashboard creation or update. All fields described from the Grafana
 | 
	
		
			
			|  | 28 | +// documentation aren't located in this structure because there are some we
 | 
	
		
			
			|  | 29 | +// don't need.
 | 
	
		
			
			|  | 30 | +type dbCreateOrUpdateResponse struct {
 | 
	
		
			
			| 23 | 31 |  	Status  string `json:"success"`
 | 
	
		
			
			| 24 | 32 |  	Version int    `json:"version,omitempty"`
 | 
	
		
			
			| 25 | 33 |  	Message string `json:"message,omitempty"`
 | 
	
		
			
			| 26 | 34 |  }
 | 
	
		
			
			| 27 | 35 |  
 | 
	
		
			
			|  | 36 | +// Dashboard represents a Grafana dashboard, with its JSON definition, slug and
 | 
	
		
			
			|  | 37 | +// current version.
 | 
	
		
			
			| 28 | 38 |  type Dashboard struct {
 | 
	
		
			
			| 29 | 39 |  	RawJSON []byte
 | 
	
		
			
			| 30 | 40 |  	Slug    string
 | 
	
		
			
			| 31 | 41 |  	Version int
 | 
	
		
			
			| 32 | 42 |  }
 | 
	
		
			
			| 33 | 43 |  
 | 
	
		
			
			|  | 44 | +// UnmarshalJSON tells the JSON parser how to unmarshal JSON data into an
 | 
	
		
			
			|  | 45 | +// instance of the Dashboard structure.
 | 
	
		
			
			|  | 46 | +// Returns an error if there was an issue unmarshalling the JSON.
 | 
	
		
			
			| 34 | 47 |  func (d *Dashboard) UnmarshalJSON(b []byte) (err error) {
 | 
	
		
			
			|  | 48 | +	// Define the structure of what we want to parse
 | 
	
		
			
			| 35 | 49 |  	var body struct {
 | 
	
		
			
			| 36 | 50 |  		Dashboard rawJSON `json:"dashboard"`
 | 
	
		
			
			| 37 | 51 |  		Meta      struct {
 | 
	
	
		
			
			|  | @@ -40,9 +54,11 @@ func (d *Dashboard) UnmarshalJSON(b []byte) (err error) {
 | 
	
		
			
			| 40 | 54 |  		} `json:"meta"`
 | 
	
		
			
			| 41 | 55 |  	}
 | 
	
		
			
			| 42 | 56 |  
 | 
	
		
			
			|  | 57 | +	// Unmarshal the JSON into the newly defined structure
 | 
	
		
			
			| 43 | 58 |  	if err = json.Unmarshal(b, &body); err != nil {
 | 
	
		
			
			| 44 | 59 |  		return
 | 
	
		
			
			| 45 | 60 |  	}
 | 
	
		
			
			|  | 61 | +	// Define all fields with their corresponding value.
 | 
	
		
			
			| 46 | 62 |  	d.Slug = body.Meta.Slug
 | 
	
		
			
			| 47 | 63 |  	d.Version = body.Meta.Version
 | 
	
		
			
			| 48 | 64 |  	d.RawJSON = body.Dashboard
 | 
	
	
		
			
			|  | @@ -50,6 +66,10 @@ func (d *Dashboard) UnmarshalJSON(b []byte) (err error) {
 | 
	
		
			
			| 50 | 66 |  	return
 | 
	
		
			
			| 51 | 67 |  }
 | 
	
		
			
			| 52 | 68 |  
 | 
	
		
			
			|  | 69 | +// GetDashboardsURIs requests the Grafana API for the list of all dashboards,
 | 
	
		
			
			|  | 70 | +// then returns the dashboards' URIs. An URI will look like "db/[dashboard slug]".
 | 
	
		
			
			|  | 71 | +// Returns an error if there was an issue requesting the URIs or parsing the
 | 
	
		
			
			|  | 72 | +// response body.
 | 
	
		
			
			| 53 | 73 |  func (c *Client) GetDashboardsURIs() (URIs []string, err error) {
 | 
	
		
			
			| 54 | 74 |  	resp, err := c.request("GET", "search", nil)
 | 
	
		
			
			| 55 | 75 |  
 | 
	
	
		
			
			|  | @@ -66,6 +86,11 @@ func (c *Client) GetDashboardsURIs() (URIs []string, err error) {
 | 
	
		
			
			| 66 | 86 |  	return
 | 
	
		
			
			| 67 | 87 |  }
 | 
	
		
			
			| 68 | 88 |  
 | 
	
		
			
			|  | 89 | +// GetDashboard requests the Grafana API for a dashboard identified by a given
 | 
	
		
			
			|  | 90 | +// URI (using the same format as GetDashboardsURIs).
 | 
	
		
			
			|  | 91 | +// Returns the dashboard as an instance of the Dashboard structure.
 | 
	
		
			
			|  | 92 | +// Returns an error if there was an issue requesting the dashboard or parsing
 | 
	
		
			
			|  | 93 | +// the response body.
 | 
	
		
			
			| 69 | 94 |  func (c *Client) GetDashboard(URI string) (db *Dashboard, err error) {
 | 
	
		
			
			| 70 | 95 |  	body, err := c.request("GET", "dashboards/"+URI, nil)
 | 
	
		
			
			| 71 | 96 |  	if err != nil {
 | 
	
	
		
			
			|  | @@ -77,8 +102,18 @@ func (c *Client) GetDashboard(URI string) (db *Dashboard, err error) {
 | 
	
		
			
			| 77 | 102 |  	return
 | 
	
		
			
			| 78 | 103 |  }
 | 
	
		
			
			| 79 | 104 |  
 | 
	
		
			
			|  | 105 | +// CreateOrUpdateDashboard takes a given JSON content (as []byte) and create the
 | 
	
		
			
			|  | 106 | +// dashboard if it doesn't exist on the Grafana instance, else updates the
 | 
	
		
			
			|  | 107 | +// existing one. The Grafana API decides whether to create or update based on the
 | 
	
		
			
			|  | 108 | +// "id" attribute in the dashboard's JSON: If it's unkown or null, it's a
 | 
	
		
			
			|  | 109 | +// creation, else it's an update.
 | 
	
		
			
			|  | 110 | +// The slug is only used for error reporting, and can differ from the
 | 
	
		
			
			|  | 111 | +// dashboard's actual slug in its JSON content. However, it's recommended to use
 | 
	
		
			
			|  | 112 | +// the same in both places.
 | 
	
		
			
			|  | 113 | +// Returns an error if there was an issue generating the request body, performing
 | 
	
		
			
			|  | 114 | +// the request or decoding the response's body.
 | 
	
		
			
			| 80 | 115 |  func (c *Client) CreateOrUpdateDashboard(slug string, contentJSON []byte) (err error) {
 | 
	
		
			
			| 81 |  | -	reqBody := dbUpdateRequest{
 | 
	
		
			
			|  | 116 | +	reqBody := dbCreateOrUpdateRequest{
 | 
	
		
			
			| 82 | 117 |  		Dashboard: rawJSON(contentJSON),
 | 
	
		
			
			| 83 | 118 |  		Overwrite: true,
 | 
	
		
			
			| 84 | 119 |  	}
 | 
	
	
		
			
			|  | @@ -99,7 +134,7 @@ func (c *Client) CreateOrUpdateDashboard(slug string, contentJSON []byte) (err e
 | 
	
		
			
			| 99 | 134 |  		}
 | 
	
		
			
			| 100 | 135 |  	}
 | 
	
		
			
			| 101 | 136 |  
 | 
	
		
			
			| 102 |  | -	var respBody dbUpdateResponse
 | 
	
		
			
			|  | 137 | +	var respBody dbCreateOrUpdateResponse
 | 
	
		
			
			| 103 | 138 |  	if err = json.Unmarshal(respBodyJSON, &respBody); err != nil {
 | 
	
		
			
			| 104 | 139 |  		return
 | 
	
		
			
			| 105 | 140 |  	}
 |