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
     # Grafana API key. This is generated by Grafana, as explained at
5
     # Grafana API key. This is generated by Grafana, as explained at
6
     # http://docs.grafana.org/http_api/auth/#create-api-token
6
     # http://docs.grafana.org/http_api/auth/#create-api-token
7
     api_key: apiauthkey
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
 # Settings to interact with the Git repository. Currently only SSH repos are
13
 # Settings to interact with the Git repository. Currently only SSH repos are
10
 # supported.
14
 # supported.

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

2
 
2
 
3
 import (
3
 import (
4
 	"io/ioutil"
4
 	"io/ioutil"
5
+	"strings"
5
 
6
 
6
 	"gopkg.in/yaml.v2"
7
 	"gopkg.in/yaml.v2"
7
 )
8
 )
16
 
17
 
17
 // GrafanaSettings contains the data required to talk to the Grafana HTTP API.
18
 // GrafanaSettings contains the data required to talk to the Grafana HTTP API.
18
 type GrafanaSettings struct {
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
 // GitSettings contains the data required to interact with the Git repository.
25
 // GitSettings contains the data required to interact with the Git repository.
57
 
59
 
58
 	cfg = new(Config)
60
 	cfg = new(Config)
59
 	err = yaml.Unmarshal(rawCfg, cfg)
61
 	err = yaml.Unmarshal(rawCfg, cfg)
62
+	cfg.Grafana.IgnorePrefix = strings.ToLower(cfg.Grafana.IgnorePrefix)
60
 	return
63
 	return
61
 }
64
 }

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

37
 // current version.
37
 // current version.
38
 type Dashboard struct {
38
 type Dashboard struct {
39
 	RawJSON []byte
39
 	RawJSON []byte
40
+	Name    string
40
 	Slug    string
41
 	Slug    string
41
 	Version int
42
 	Version int
42
 }
43
 }
63
 	d.Version = body.Meta.Version
64
 	d.Version = body.Meta.Version
64
 	d.RawJSON = body.Dashboard
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
 	return
85
 	return
67
 }
86
 }
68
 
87
 

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

21
 }
21
 }
22
 
22
 
23
 // PullGrafanaAndCommit pulls all the dashboards from Grafana except the ones
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
 func PullGrafanaAndCommit(client *grafana.Client, cfg *config.Config) error {
27
 func PullGrafanaAndCommit(client *grafana.Client, cfg *config.Config) error {
28
 	// Clone or pull the repo
28
 	// Clone or pull the repo
29
 	repo, err := git.Sync(cfg.Git)
29
 	repo, err := git.Sync(cfg.Git)
52
 
52
 
53
 	// Iterate over the dashboards URIs
53
 	// Iterate over the dashboards URIs
54
 	for _, uri := range uris {
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
 		// Retrieve the dashboard JSON
55
 		// Retrieve the dashboard JSON
61
 		dashboard, err := client.GetDashboard(uri)
56
 		dashboard, err := client.GetDashboard(uri)
62
 		if err != nil {
57
 		if err != nil {
63
 			return err
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
 		// Check if there's a version for this dashboard in the data loaded from
68
 		// Check if there's a version for this dashboard in the data loaded from
67
 		// the "versions.json" file. If there's a version and it's older (lower
69
 		// the "versions.json" file. If there's a version and it's older (lower
68
 		// version number) than the version we just retrieved from the Grafana
70
 		// version number) than the version we just retrieved from the Grafana

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

1
 package main
1
 package main
2
 
2
 
3
 import (
3
 import (
4
+	"encoding/json"
4
 	"io/ioutil"
5
 	"io/ioutil"
5
 	"strings"
6
 	"strings"
6
 
7
 
58
 			continue
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
 		for _, addedFile := range commit.Added {
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
 				filesToPush[addedFile] = true
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
 		for _, modifiedFile := range commit.Modified {
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
 				filesToPush[modifiedFile] = true
84
 				filesToPush[modifiedFile] = true
72
 			}
85
 			}
73
 		}
86
 		}
106
 
119
 
107
 	return grafanaClient.CreateOrUpdateDashboard(slug, fileContent)
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
+}