Browse Source

Add ignored prefix to the configurable keys and filter by dashboard name instead of slug

Brendan Abolivier 6 years ago
parent
commit
d59b526e1e
Signed by: Brendan Abolivier <contact@brendanabolivier.com> GPG key ID: 8EF1500759F70623
5 changed files with 91 additions and 14 deletions
  1. 4
    0
      config.example.yaml
  2. 5
    2
      src/config/config.go
  3. 19
    0
      src/grafana/dashboards.go
  4. 10
    8
      src/puller/puller.go
  5. 53
    4
      src/pusher/webhook.go

+ 4
- 0
config.example.yaml View File

@@ -5,6 +5,10 @@ grafana:
5 5
     # Grafana API key. This is generated by Grafana, as explained at
6 6
     # http://docs.grafana.org/http_api/auth/#create-api-token
7 7
     api_key: apiauthkey
8
+    # If set, all dashboards with a name starting with this prefix will be
9
+    # ignored by both the puller and the pusher. This setting is
10
+    # case-insensitive and optional.
11
+    ignore_prefix: test
8 12
 
9 13
 # Settings to interact with the Git repository. Currently only SSH repos are
10 14
 # supported.

+ 5
- 2
src/config/config.go View File

@@ -2,6 +2,7 @@ package config
2 2
 
3 3
 import (
4 4
 	"io/ioutil"
5
+	"strings"
5 6
 
6 7
 	"gopkg.in/yaml.v2"
7 8
 )
@@ -16,8 +17,9 @@ type Config struct {
16 17
 
17 18
 // GrafanaSettings contains the data required to talk to the Grafana HTTP API.
18 19
 type GrafanaSettings struct {
19
-	BaseURL string `yaml:"base_url"`
20
-	APIKey  string `yaml:"api_key"`
20
+	BaseURL      string `yaml:"base_url"`
21
+	APIKey       string `yaml:"api_key"`
22
+	IgnorePrefix string `yaml:"ignore_prefix,omitempty"`
21 23
 }
22 24
 
23 25
 // GitSettings contains the data required to interact with the Git repository.
@@ -57,5 +59,6 @@ func Load(filename string) (cfg *Config, err error) {
57 59
 
58 60
 	cfg = new(Config)
59 61
 	err = yaml.Unmarshal(rawCfg, cfg)
62
+	cfg.Grafana.IgnorePrefix = strings.ToLower(cfg.Grafana.IgnorePrefix)
60 63
 	return
61 64
 }

+ 19
- 0
src/grafana/dashboards.go View File

@@ -37,6 +37,7 @@ type dbCreateOrUpdateResponse struct {
37 37
 // current version.
38 38
 type Dashboard struct {
39 39
 	RawJSON []byte
40
+	Name    string
40 41
 	Slug    string
41 42
 	Version int
42 43
 }
@@ -63,6 +64,24 @@ func (d *Dashboard) UnmarshalJSON(b []byte) (err error) {
63 64
 	d.Version = body.Meta.Version
64 65
 	d.RawJSON = body.Dashboard
65 66
 
67
+	// Define the dashboard's name from the previously extracted JSON description
68
+	err = d.setDashboardNameFromRawJSON()
69
+	return
70
+}
71
+
72
+// setDashboardNameFromJSON finds a dashboard's name from the content of its
73
+// RawJSON field
74
+func (d *Dashboard) setDashboardNameFromRawJSON() (err error) {
75
+	// Define the necessary structure to catch the dashboard's name
76
+	var dashboard struct {
77
+		Name string `json:"title"`
78
+	}
79
+
80
+	// Unmarshal the JSON content into the structure and set the dashboard's
81
+	// name
82
+	err = json.Unmarshal(d.RawJSON, &dashboard)
83
+	d.Name = dashboard.Name
84
+
66 85
 	return
67 86
 }
68 87
 

+ 10
- 8
src/puller/puller.go View File

@@ -21,9 +21,9 @@ type diffVersion struct {
21 21
 }
22 22
 
23 23
 // PullGrafanaAndCommit pulls all the dashboards from Grafana except the ones
24
-// which name/slug starts with "test", then commits each of them to Git except
25
-// for those that have a newer or equal version number already versionned in
26
-// the repo.
24
+// which name starts with "test", then commits each of them to Git except for
25
+// those that have a newer or equal version number already versionned in the
26
+// repo.
27 27
 func PullGrafanaAndCommit(client *grafana.Client, cfg *config.Config) error {
28 28
 	// Clone or pull the repo
29 29
 	repo, err := git.Sync(cfg.Git)
@@ -52,17 +52,19 @@ func PullGrafanaAndCommit(client *grafana.Client, cfg *config.Config) error {
52 52
 
53 53
 	// Iterate over the dashboards URIs
54 54
 	for _, uri := range uris {
55
-		// Don't process any dashboard which name/slug starts with "test"
56
-		if strings.HasPrefix(uri, "db/test") {
57
-			continue
58
-		}
59
-
60 55
 		// Retrieve the dashboard JSON
61 56
 		dashboard, err := client.GetDashboard(uri)
62 57
 		if err != nil {
63 58
 			return err
64 59
 		}
65 60
 
61
+		if len(cfg.Grafana.IgnorePrefix) > 0 {
62
+			lowerCasedName := strings.ToLower(dashboard.Name)
63
+			if strings.HasPrefix(lowerCasedName, cfg.Grafana.IgnorePrefix) {
64
+				continue
65
+			}
66
+		}
67
+
66 68
 		// Check if there's a version for this dashboard in the data loaded from
67 69
 		// the "versions.json" file. If there's a version and it's older (lower
68 70
 		// version number) than the version we just retrieved from the Grafana

+ 53
- 4
src/pusher/webhook.go View File

@@ -1,6 +1,7 @@
1 1
 package main
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"io/ioutil"
5 6
 	"strings"
6 7
 
@@ -58,16 +59,28 @@ func HandlePush(payload interface{}, header webhooks.Header) {
58 59
 			continue
59 60
 		}
60 61
 
61
-		// Push all added files, except the ones which name starts with "test"
62
+		// Push all added files, except the ones describing a dashboard which
63
+		// name starts with a the prefix specified in the configuration file.
62 64
 		for _, addedFile := range commit.Added {
63
-			if !strings.HasPrefix(addedFile, "test") {
65
+			ignored, err := isIgnored(addedFile)
66
+			if err != nil {
67
+				panic(err)
68
+			}
69
+
70
+			if !ignored {
64 71
 				filesToPush[addedFile] = true
65 72
 			}
66 73
 		}
67 74
 
68
-		// Push all modified files, except the ones which name starts with "test"
75
+		// Push all modified files, except the ones describing a dashboard which
76
+		// name starts with a the prefix specified in the configuration file.
69 77
 		for _, modifiedFile := range commit.Modified {
70
-			if !strings.HasPrefix(addedFile, "test") {
78
+			ignored, err := isIgnored(modifiedFile)
79
+			if err != nil {
80
+				panic(err)
81
+			}
82
+
83
+			if !ignored {
71 84
 				filesToPush[modifiedFile] = true
72 85
 			}
73 86
 		}
@@ -106,3 +119,39 @@ func pushFile(filename string) error {
106 119
 
107 120
 	return grafanaClient.CreateOrUpdateDashboard(slug, fileContent)
108 121
 }
122
+
123
+// isIgnored checks whether the file must be ignored, by checking if there's an
124
+// prefix for ignored files set in the configuration file, and if the dashboard
125
+// described in the file has a name that starts with this prefix. Returns an
126
+// error if there was an issue reading or decoding the file.
127
+// TODO: Optimise this part of the workflow, as all files get open twice (here
128
+// and in pushFile)
129
+func isIgnored(filename string) (bool, error) {
130
+	// If there's no prefix set, no file is ignored
131
+	if len(cfg.Grafana.IgnorePrefix) == 0 {
132
+		return false, nil
133
+	}
134
+
135
+	// Read the file's content
136
+	fileContent, err := ioutil.ReadFile(filename)
137
+	if err != nil {
138
+		return false, err
139
+	}
140
+
141
+	// Parse the file's content to find the dashboard's name
142
+	var dashboardName struct {
143
+		Name string `json:"title"`
144
+	}
145
+	if err = json.Unmarshal(fileContent, &dashboardName); err != nil {
146
+		return false, err
147
+	}
148
+
149
+	// Compare the lower case dashboar name to the prefix (which has already
150
+	// been lower cased when loading the configuration file)
151
+	lowerCaseName := strings.ToLower(dashboardName.Name)
152
+	if strings.HasPrefix(lowerCaseName, cfg.Grafana.IgnorePrefix) {
153
+		return true, nil
154
+	}
155
+
156
+	return false, nil
157
+}