Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.

Commit 60683a5

Browse files
authored
Refactoring configuration editor (#17)
1 parent d69b722 commit 60683a5

16 files changed

+820
-197
lines changed

docker-compose.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ services:
55
image: grafana/grafana:8.1.2
66
container_name: grafana_stage_one
77
environment:
8-
- GF_SECURITY_ADMIN_PASSWORD=demo
9-
- GF_PATHS_PROVISIONING=/usr/share/grafana/custom/
108
- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=novatec-dashboardsync-datasource
119
- SSH_KNOWN_HOSTS=github.com
1210
- GF_ALLOWED_ORIGINS="http://localhost:3000"
1311
volumes:
1412
- ${PLUGIN_REPO}:/var/lib/grafana/plugins/
15-
- ${GIT_SSH_KEY}:/usr/share/grafana/.ssh
1613
ports:
1714
- 3001:3000
1815

@@ -21,14 +18,11 @@ services:
2118
image: grafana/grafana:8.1.2
2219
container_name: grafana_stage_two
2320
environment:
24-
- GF_SECURITY_ADMIN_PASSWORD=demo
25-
- GF_PATHS_PROVISIONING=/usr/share/grafana/custom/
2621
- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=novatec-dashboardsync-datasource
2722
- SSH_KNOWN_HOSTS=github.com
2823
- GF_ALLOWED_ORIGINS="http://localhost:3000"
2924
volumes:
3025
- ${PLUGIN_REPO}:/var/lib/grafana/plugins/
31-
- ${GIT_SSH_KEY}:/usr/share/grafana/.ssh
3226
ports:
3327
- 3002:3000
3428

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"@grafana/data": "latest",
1717
"@grafana/toolkit": "latest",
1818
"@grafana/runtime": "latest",
19-
"@grafana/ui": "latest",
19+
"@grafana/ui": "7.5.11",
2020
"@types/lodash": "latest"
2121
},
2222
"resolutions": {

pkg/plugin/git_api.go

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package plugin
22

33
import (
4+
"io/ioutil"
5+
"strings"
6+
"time"
7+
48
"github.com/go-git/go-git/v5/plumbing/object"
59
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
610
ssh2 "golang.org/x/crypto/ssh"
@@ -10,41 +14,37 @@ import (
1014
object2 "gopkg.in/src-d/go-git.v4/plumbing/object"
1115
"gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
1216
"gopkg.in/src-d/go-git.v4/storage/memory"
13-
"io/ioutil"
14-
"os"
15-
"strings"
16-
"time"
1717
)
1818

1919
// GitApi access to git api
2020
type GitApi struct {
21-
gitUrl string
22-
authenticator *ssh.PublicKeys
23-
inMemoryStore memory.Storage
21+
gitUrl string
22+
authenticator *ssh.PublicKeys
23+
inMemoryStore memory.Storage
2424
inMemoryFileSystem billy.Filesystem
2525
}
2626

2727
// NewGitApi creates a new NewGitApi instance
28-
func NewGitApi(gitUrl string, privateKeyFilePath string) GitApi {
29-
authenticator, err := createAuthenticator(privateKeyFilePath)
28+
func NewGitApi(gitUrl string, privateKey []byte) GitApi {
29+
authenticator, err := createAuthenticator(privateKey)
3030
if err != nil {
3131
log.DefaultLogger.Error("authentication failed", "error", err.Error())
3232
}
3333
inMemoryStore, inMemoryFileSystem := createInMemory()
34-
gitApi := GitApi {gitUrl,authenticator, *inMemoryStore, inMemoryFileSystem}
34+
gitApi := GitApi{gitUrl, authenticator, *inMemoryStore, inMemoryFileSystem}
3535

3636
return gitApi
3737
}
3838

3939
// helper function to create the git authenticator
40-
func createAuthenticator(privateKeyFilePath string) (*ssh.PublicKeys, error) {
40+
func createAuthenticator(privateKey []byte) (*ssh.PublicKeys, error) {
4141
// git authentication with ssh
42-
_, err := os.Stat(privateKeyFilePath)
43-
if err != nil {
44-
log.DefaultLogger.Error("read file %s failed", privateKeyFilePath, err.Error())
45-
return nil, err
46-
}
47-
authenticator, err:= ssh.NewPublicKeysFromFile("git", privateKeyFilePath, "")
42+
// _, err := os.Stat(privateKeyFilePath)
43+
// if err != nil {
44+
// log.DefaultLogger.Error("read file failed", privateKeyFilePath, err.Error())
45+
// return nil, err
46+
// }
47+
authenticator, err := ssh.NewPublicKeys("git", privateKey, "")
4848
if err != nil {
4949
log.DefaultLogger.Error("generate public keys failed", "error", err.Error())
5050
return nil, err
@@ -57,7 +57,7 @@ func createAuthenticator(privateKeyFilePath string) (*ssh.PublicKeys, error) {
5757
}
5858

5959
// helper function to create the in memory storage and filesystem
60-
func createInMemory() (*memory.Storage, billy.Filesystem){
60+
func createInMemory() (*memory.Storage, billy.Filesystem) {
6161
// prepare in memory
6262
store := memory.NewStorage()
6363
var fs billy.Filesystem
@@ -67,14 +67,14 @@ func createInMemory() (*memory.Storage, billy.Filesystem){
6767
}
6868

6969
// CloneRepo clones the gitApi.gitUrls repository
70-
func (gitApi GitApi) CloneRepo() (*git.Repository, error){
70+
func (gitApi GitApi) CloneRepo() (*git.Repository, error) {
7171
// git clone
7272
r, err := git.Clone(&gitApi.inMemoryStore, gitApi.inMemoryFileSystem, &git.CloneOptions{
73-
URL: gitApi.gitUrl,
73+
URL: gitApi.gitUrl,
7474
Auth: gitApi.authenticator,
7575
})
7676
if err != nil {
77-
log.DefaultLogger.Error("clone error" , "error", err)
77+
log.DefaultLogger.Error("clone error", "error", err)
7878
return nil, err
7979
} else {
8080
log.DefaultLogger.Info("repo cloned")
@@ -89,7 +89,7 @@ func (gitApi GitApi) FetchRepo(repository git.Repository) {
8989
log.DefaultLogger.Info("fetching repo")
9090
err := repository.Fetch(&git.FetchOptions{
9191
RemoteName: "origin",
92-
Auth: gitApi.authenticator,
92+
Auth: gitApi.authenticator,
9393
})
9494
if strings.Contains(err.Error(), "already up-to-date") {
9595
log.DefaultLogger.Info("fetching completed", "message", err.Error())
@@ -116,21 +116,21 @@ func (gitApi GitApi) CommitWorktree(repository git.Repository, tag string) {
116116
// get worktree and commit
117117
w, err := repository.Worktree()
118118
if err != nil {
119-
log.DefaultLogger.Error("worktree error" , "error", err)
119+
log.DefaultLogger.Error("worktree error", "error", err)
120120
return
121121
} else {
122122
w.Add("./")
123123
wStatus, _ := w.Status()
124-
log.DefaultLogger.Debug("worktree status" , "status", wStatus)
124+
log.DefaultLogger.Debug("worktree status", "status", wStatus)
125125

126-
_, err := w.Commit("Synchronized Dashboards with tag <" + tag + ">", &git.CommitOptions{
126+
_, err := w.Commit("Synchronized Dashboards with tag <"+tag+">", &git.CommitOptions{
127127
Author: (*object2.Signature)(&object.Signature{
128-
Name: "grafana-dashboard-sync-plugin",
129-
When: time.Now(),
128+
Name: "grafana-dashboard-sync-plugin",
129+
When: time.Now(),
130130
}),
131131
})
132132
if err != nil {
133-
log.DefaultLogger.Error("worktree commit error" , "error", err.Error())
133+
log.DefaultLogger.Error("worktree commit error", "error", err.Error())
134134
return
135135
}
136136
}
@@ -141,7 +141,7 @@ func (gitApi GitApi) PushRepo(repository git.Repository) {
141141
// push repo
142142
err := repository.Push(&git.PushOptions{
143143
RemoteName: "origin",
144-
Auth: gitApi.authenticator,
144+
Auth: gitApi.authenticator,
145145
})
146146
if err != nil {
147147
log.DefaultLogger.Error("push error", "error", err.Error())
@@ -153,12 +153,12 @@ func (gitApi GitApi) PullRepo(repository git.Repository) {
153153
// pull repo
154154
w, err := repository.Worktree()
155155
if err != nil {
156-
log.DefaultLogger.Error("worktree error" , "error", err)
156+
log.DefaultLogger.Error("worktree error", "error", err)
157157
} else {
158158
log.DefaultLogger.Debug("Pulling from Repo")
159159
err := w.Pull(&git.PullOptions{
160160
RemoteName: "origin",
161-
Auth: gitApi.authenticator,
161+
Auth: gitApi.authenticator,
162162
})
163163
if err != nil {
164164
if strings.Contains(err.Error(), "already up-to-date") {
@@ -175,7 +175,7 @@ func (gitApi GitApi) GetFileContent() map[string]map[string][]byte {
175175
// read current in memory filesystem to get dirs
176176
filesOrDirs, err := gitApi.inMemoryFileSystem.ReadDir("./")
177177
if err != nil {
178-
log.DefaultLogger.Error("inMemoryFileSystem error" , "error", err)
178+
log.DefaultLogger.Error("inMemoryFileSystem error", "error", err)
179179
return nil
180180
}
181181

@@ -225,4 +225,4 @@ func (gitApi GitApi) GetFileContent() map[string]map[string][]byte {
225225
}
226226
}
227227
return fileMap
228-
}
228+
}

pkg/plugin/plugin.go

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package plugin
33
import (
44
"context"
55
"encoding/json"
6+
67
"github.com/grafana/grafana-plugin-sdk-go/backend"
78
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
89
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
@@ -39,14 +40,34 @@ func (d *SampleDatasource) Dispose() {
3940
// Clean up datasource instance resources.
4041
}
4142

43+
type PullConfiguration struct {
44+
Enable bool `json:"enable"`
45+
GitBranch string `json:"gitBranch"`
46+
SyncInterval int64 `json:"syncInterval"`
47+
Filter string `json:"filter"`
48+
}
49+
50+
type PushConfiguration struct {
51+
PullConfiguration
52+
TagPattern string `json:"tagPattern"`
53+
PushTags bool `json:"pushTags"`
54+
}
55+
56+
type SynchronizeOptions struct {
57+
GrafanaUrl string `json:"grafanaUrl"`
58+
GitUrl string `json:"gitUrl"`
59+
PushConfiguration PushConfiguration `json:"pushConfiguration"`
60+
PullConfiguration PullConfiguration `json:"pullConfiguration"`
61+
}
62+
4263
// CheckHealth handles health checks sent from Grafana to the plugin.
4364
// The main use case for these health checks is the test button on the
4465
// datasource configuration page which allows users to verify that
4566
// a datasource is working as expected.
4667
func (d *SampleDatasource) CheckHealth(_ context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
4768
log.DefaultLogger.Debug("Backend called with following request", "request", req)
4869

49-
uiProperties := make(map[string]string)
70+
var uiProperties SynchronizeOptions
5071
_ = json.Unmarshal(req.PluginContext.DataSourceInstanceSettings.JSONData, &uiProperties)
5172
uiSecureProperties := req.PluginContext.DataSourceInstanceSettings.DecryptedSecureJSONData
5273

@@ -62,41 +83,37 @@ func (d *SampleDatasource) CheckHealth(_ context.Context, req *backend.CheckHeal
6283

6384
// TODO: Set workflow cron job?
6485

65-
token := uiSecureProperties["token"]
66-
grafanaUrl := uiProperties["grafanaURL"]
67-
pushGitURL := uiProperties["gitPushURL"]
68-
pullGitURL := uiProperties["gitPullURL"]
69-
privateKeyFilePath := uiSecureProperties["privateKeyFilePath"]
70-
dashboardTag := uiProperties["tag"]
71-
push := uiProperties["push"]
72-
pull := uiProperties["pull"]
86+
grafanaUrl := uiProperties.GrafanaUrl
87+
token := uiSecureProperties["grafanaApiToken"]
88+
89+
gitUrl := uiProperties.GitUrl
90+
dashboardTag := uiProperties.PushConfiguration.TagPattern
91+
privateKey := []byte(uiSecureProperties["privateSshKey"])
92+
93+
// privateKeyFilePath := uiSecureProperties["privateKeyFilePath"]
7394

7495
grafanaApi := NewGrafanaApi(grafanaUrl, token)
7596

76-
if pull == "true" {
77-
log.DefaultLogger.Info("Pull from git repo", "url", pullGitURL)
97+
gitApi := NewGitApi(uiProperties.GitUrl, privateKey)
98+
log.DefaultLogger.Info("Using Git repository from: %s", uiProperties.GitUrl)
99+
100+
repository, err := gitApi.CloneRepo()
101+
if err != nil {
102+
return nil, err
103+
}
104+
gitApi.FetchRepo(*repository)
105+
106+
if uiProperties.PullConfiguration.Enable {
107+
log.DefaultLogger.Info("Pull from git repo", "url", gitUrl)
78108

79-
gitApi := NewGitApi(pullGitURL, privateKeyFilePath)
80-
repository, err := gitApi.CloneRepo()
81-
if err != nil {
82-
return nil, err
83-
}
84-
gitApi.FetchRepo(*repository)
85109
gitApi.PullRepo(*repository)
86110
fileMap := gitApi.GetFileContent()
87111
grafanaApi.CreateDashboardObjects(fileMap)
88112
log.DefaultLogger.Info("Dashboards created")
89113
}
90114

91-
if push == "true" {
92-
log.DefaultLogger.Info("Push to git repo", "url", pushGitURL)
93-
94-
gitApi := NewGitApi(pushGitURL, privateKeyFilePath)
95-
repository, err := gitApi.CloneRepo()
96-
if err != nil {
97-
return nil, err
98-
}
99-
gitApi.FetchRepo(*repository)
115+
if uiProperties.PushConfiguration.Enable {
116+
log.DefaultLogger.Info("Push to git repo", "url", gitUrl)
100117

101118
dashboards, err := grafanaApi.SearchDashboardsWithTag(dashboardTag)
102119
if err != nil {
@@ -145,4 +162,4 @@ func (d *SampleDatasource) CheckHealth(_ context.Context, req *backend.CheckHeal
145162
Status: status,
146163
Message: message,
147164
}, nil
148-
}
165+
}

0 commit comments

Comments
 (0)