Skip to content

Commit

Permalink
Merge pull request #17 from netsage-project/feature/mocking
Browse files Browse the repository at this point in the history
 Refactoring
  • Loading branch information
safaci2000 committed Jun 4, 2021
2 parents a01d657 + 3f19a5c commit 0669fb4
Show file tree
Hide file tree
Showing 24 changed files with 289 additions and 178 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"mode": "debug",
"program": "${workspaceFolder}",
"args": [
"users",
"dash",
"list",
//"promote",
//"-u",
Expand Down
12 changes: 12 additions & 0 deletions api/common.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package api

import (
"context"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -74,3 +75,14 @@ func findAllFiles(folder string) []string {

return fileList
}

//getFolderNameIDMap helper function to build a mapping for name to folderID
func getFolderNameIDMap(client *sdk.Client, ctx context.Context) map[string]int {

folders, _ := client.GetAllFolders(ctx)
var folderMap map[string]int = make(map[string]int)
for _, folder := range folders {
folderMap[folder.Title] = folder.ID
}
return folderMap
}
50 changes: 50 additions & 0 deletions api/contract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package api

import (
"github.com/netsage-project/grafana-dashboard-manager/config"
"github.com/netsage-project/sdk"
"github.com/spf13/viper"
)

type ApiService interface {
//Dashboard
ListDashboards(filter Filter) []sdk.FoundBoard
ImportDashboards(filter Filter) []string
ExportDashboards(filter Filter)
DeleteAllDashboards(filter Filter) []string
//DataSources
ListDataSources(filter Filter) []sdk.Datasource
ImportDataSources(filter Filter) []string
ExportDataSources(filter Filter) []string
DeleteAllDataSources(filter Filter) []string
//Login
Login() *sdk.Client
AdminLogin() *sdk.Client
//User
ListUsers() []sdk.User
PromoteUser(userLogin string) (*sdk.StatusMessage, error)
}

type DashNGoImpl struct {
client *sdk.Client
adminClient *sdk.Client
grafanaConf *config.GrafanaConfig
configRef *viper.Viper
debug bool
}

func (s *DashNGoImpl) init() {
s.grafanaConf = config.GetDefaultGrafanaConfig()
s.configRef = config.Config()
s.client = s.Login()
s.adminClient = s.AdminLogin()
s.debug = s.configRef.GetBool("global.debug")

}

func NewApiService() ApiService {
d := &DashNGoImpl{}
d.init()
return d

}
67 changes: 25 additions & 42 deletions api/dashboards.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/spf13/viper"
"github.com/tidwall/pretty"

"github.com/netsage-project/sdk"
Expand All @@ -21,10 +19,10 @@ import (

//ListDashboards: List all dashboards optionally filtered by folder name. If folderFilters
// is blank, defaults to the configured Monitored folders
func ListDashboards(client *sdk.Client, filters *DashboardFilter) []sdk.FoundBoard {
func (s *DashNGoImpl) ListDashboards(filters Filter) []sdk.FoundBoard {
ctx := context.Background()
var boardsList []sdk.FoundBoard = make([]sdk.FoundBoard, 0)
boardLinks, err := client.SearchDashboards(ctx, "", false)
boardLinks, err := s.client.SearchDashboards(ctx, "", false)
if err != nil {
panic(err)
}
Expand All @@ -47,8 +45,8 @@ func ListDashboards(client *sdk.Client, filters *DashboardFilter) []sdk.FoundBoa
continue
}
updateSlug(&link)
if filters.DashFilter != "" {
if link.Slug == filters.DashFilter {
if filters.GetFilter("DashFilter") != "" {
if link.Slug == filters.GetFilter("DashFilter") {
validUid = true
} else {
validUid = false
Expand All @@ -70,7 +68,7 @@ func ListDashboards(client *sdk.Client, filters *DashboardFilter) []sdk.FoundBoa
}

//ImportDashboards saves all dashboards matching query to configured location
func ImportDashboards(client *sdk.Client, filter DashboardFilter, conf *viper.Viper) []string {
func (s *DashNGoImpl) ImportDashboards(filter Filter) []string {
var (
boardLinks []sdk.FoundBoard
rawBoard []byte
Expand All @@ -79,14 +77,14 @@ func ImportDashboards(client *sdk.Client, filter DashboardFilter, conf *viper.Vi
)
ctx := context.Background()

boardLinks = ListDashboards(client, &filter)
boardLinks = s.ListDashboards(filter)
var boards []string = make([]string, 0)
for _, link := range boardLinks {
if rawBoard, meta, err = client.GetRawDashboardByUID(ctx, link.UID); err != nil {
if rawBoard, meta, err = s.client.GetRawDashboardByUID(ctx, link.UID); err != nil {
fmt.Fprintf(os.Stderr, "%s for %s\n", err, link.URI)
continue
}
fileName := fmt.Sprintf("%s/%s.json", buildDashboardPath(conf, link.FolderTitle), meta.Slug)
fileName := fmt.Sprintf("%s/%s.json", buildDashboardPath(s.configRef, link.FolderTitle), meta.Slug)
if err = ioutil.WriteFile(fileName, pretty.Pretty(rawBoard), os.FileMode(int(0666))); err != nil {
fmt.Fprintf(os.Stderr, "%s for %s\n", err, meta.Slug)
} else {
Expand All @@ -97,24 +95,14 @@ func ImportDashboards(client *sdk.Client, filter DashboardFilter, conf *viper.Vi
return boards
}

//getFolderNameIDMap helper function to build a mapping for name to folderID
func getFolderNameIDMap(client *sdk.Client, ctx context.Context) map[string]int {

folders, _ := client.GetAllFolders(ctx)
var folderMap map[string]int = make(map[string]int, 0)
for _, folder := range folders {
folderMap[folder.Title] = folder.ID
}
return folderMap
}

//ExportDashboards finds all the dashboards in the configured location and exports them to grafana.
// if the folde doesn't exist, it'll be created.
func ExportDashboards(client *sdk.Client, filters DashboardFilter, conf *viper.Viper) {
filesInDir := findAllFiles(getResourcePath(conf, "dashboard"))
// if the folde doesn't exist, it'll be created.
func (s *DashNGoImpl) ExportDashboards(filters Filter) {
filesInDir := findAllFiles(getResourcePath(s.configRef, "dashboard"))
ctx := context.Background()
var rawBoard []byte
folderMap := getFolderNameIDMap(client, ctx)
folderMap := getFolderNameIDMap(s.client, ctx)
var err error
var folderName string = ""
var folderId int
Expand Down Expand Up @@ -142,19 +130,17 @@ func ExportDashboards(client *sdk.Client, filters DashboardFilter, conf *viper.V
folderId = sdk.DefaultFolderId
folderName = DefaultFolderName
}
validateMap := map[string]string{FolderFilter: folderName, DashFilter: baseFile}

if folderName == DefaultFolderName {
folderId = sdk.DefaultFolderId
} else {
if val, ok := folderMap[folderName]; ok {
folderId = val
} else {
createFolder := filters.ValidateFolder(folderName)
validUid := filters.ValidateDashboard(baseFile)

if createFolder && validUid {
if filters.Validate(validateMap) {
folder := sdk.Folder{Title: folderName}
folder, err = client.CreateFolder(ctx, folder)
folder, err = s.client.CreateFolder(ctx, folder)
if err != nil {
panic(err)
}
Expand All @@ -165,15 +151,18 @@ func ExportDashboards(client *sdk.Client, filters DashboardFilter, conf *viper.V
}

//If folder OR slug is filtered, then skip if it doesn't match
if !filters.Validate(folderName, baseFile) {
if !filters.Validate(validateMap) {
continue
}

title, err := jsonpath.Read(board, "$.title")
if err != nil {
log.Warn("Could not get dashboard title")
}

rawTitle := fmt.Sprintf("%v", title)
slugName := GetSlug(rawTitle)
if _, err = client.DeleteDashboard(ctx, slugName); err != nil {
if _, err = s.client.DeleteDashboard(ctx, slugName); err != nil {
log.Println(err)
continue
}
Expand All @@ -186,7 +175,7 @@ func ExportDashboards(client *sdk.Client, filters DashboardFilter, conf *viper.V
Dashboard: rawBoard,
}

_, err = client.SetRawDashboardWithParam(ctx, request)
_, err = s.client.SetRawDashboardWithParam(ctx, request)
if err != nil {
log.Printf("error on Exporting dashboard %s", rawTitle)
continue
Expand All @@ -197,14 +186,14 @@ func ExportDashboards(client *sdk.Client, filters DashboardFilter, conf *viper.V

//DeleteAllDashboards clears all current dashboards being monitored. Any folder not white listed
// will not be affected
func DeleteAllDashboards(client *sdk.Client, filter DashboardFilter) []string {
func (s *DashNGoImpl) DeleteAllDashboards(filter Filter) []string {
ctx := context.Background()
var dashboards []string = make([]string, 0)

items := ListDashboards(client, &filter)
items := s.ListDashboards(filter)
for _, item := range items {
if filter.Validate(item.FolderTitle, item.Slug) {
_, err := client.DeleteDashboardByUID(ctx, item.UID)
if filter.Validate(map[string]string{FolderFilter: item.FolderTitle, DashFilter: item.Slug}) {
_, err := s.client.DeleteDashboardByUID(ctx, item.UID)
if err == nil {
dashboards = append(dashboards, item.Title)
}
Expand All @@ -213,9 +202,3 @@ func DeleteAllDashboards(client *sdk.Client, filter DashboardFilter) []string {
return dashboards

}

var quoteRegex *regexp.Regexp

func init() {
quoteRegex, _ = regexp.Compile("['\"]+")
}
34 changes: 17 additions & 17 deletions api/datasources.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,19 @@ import (
"github.com/gosimple/slug"
"github.com/netsage-project/grafana-dashboard-manager/config"
"github.com/netsage-project/sdk"
"github.com/spf13/viper"
)

//ListDataSources: list all the currently configured datasources
func ListDataSources(client *sdk.Client, filter DatasourceFilter) []sdk.Datasource {
func (s *DashNGoImpl) ListDataSources(filter Filter) []sdk.Datasource {

ctx := context.Background()
ds, err := client.GetAllDatasources(ctx)
ds, err := s.client.GetAllDatasources(ctx)
if err != nil {
panic(err)
}
result := make([]sdk.Datasource, 0)
for _, item := range ds {
if filter.ValidateDatasource(GetSlug(item.Name)) {
if filter.Validate(map[string]string{Name: GetSlug(item.Name)}) {
result = append(result, item)
}
}
Expand All @@ -34,21 +33,21 @@ func ListDataSources(client *sdk.Client, filter DatasourceFilter) []sdk.Datasour

//ImportDataSources: will read in all the configured datasources.
//NOTE: credentials cannot be retrieved and need to be set via configuration
func ImportDataSources(client *sdk.Client, filter DatasourceFilter, conf *viper.Viper) []string {
func (s *DashNGoImpl) ImportDataSources(filter Filter) []string {
var (
datasources []sdk.Datasource
dsPacked []byte
meta sdk.BoardProperties
err error
dataFiles []string
)
datasources = ListDataSources(client, filter)
datasources = s.ListDataSources(filter)
for _, ds := range datasources {
if dsPacked, err = json.MarshalIndent(ds, "", " "); err != nil {
fmt.Fprintf(os.Stderr, "%s for %s\n", err, ds.Name)
continue
}
dsPath := buildDataSourcePath(conf, slug.Make(ds.Name))
dsPath := buildDataSourcePath(s.configRef, slug.Make(ds.Name))
if err = ioutil.WriteFile(dsPath, dsPacked, os.FileMode(int(0666))); err != nil {
fmt.Fprintf(os.Stderr, "%s for %s\n", err, meta.Slug)
} else {
Expand All @@ -59,33 +58,33 @@ func ImportDataSources(client *sdk.Client, filter DatasourceFilter, conf *viper.
}

//Removes all current datasources
func DeleteAllDataSources(client *sdk.Client, filter DatasourceFilter) []string {
func (s *DashNGoImpl) DeleteAllDataSources(filter Filter) []string {
ctx := context.Background()
var ds []string = make([]string, 0)
items := ListDataSources(client, filter)
items := s.ListDataSources(filter)
for _, item := range items {
client.DeleteDatasource(ctx, item.ID)
s.client.DeleteDatasource(ctx, item.ID)
ds = append(ds, item.Name)
}
return ds
}

//ExportDataSources: exports all datasources to grafana using the credentials configured in config file.
func ExportDataSources(client *sdk.Client, filter DatasourceFilter, conf *viper.Viper) []string {
func (s *DashNGoImpl) ExportDataSources(filter Filter) []string {
var datasources []sdk.Datasource
var status sdk.StatusMessage
var exported []string = make([]string, 0)

ctx := context.Background()
filesInDir, err := ioutil.ReadDir(getResourcePath(conf, "ds"))
datasources = ListDataSources(client, filter)
filesInDir, err := ioutil.ReadDir(getResourcePath(s.configRef, "ds"))
datasources = s.ListDataSources(filter)

var rawDS []byte
if err != nil {
fmt.Fprint(os.Stderr, err)
}
for _, file := range filesInDir {
fileLocation := fmt.Sprintf("%s/%s", getResourcePath(conf, "ds"), file.Name())
fileLocation := fmt.Sprintf("%s/%s", getResourcePath(s.configRef, "ds"), file.Name())
if strings.HasSuffix(file.Name(), ".json") {
if rawDS, err = ioutil.ReadFile(fileLocation); err != nil {
fmt.Fprint(os.Stderr, err)
Expand All @@ -97,7 +96,8 @@ func ExportDataSources(client *sdk.Client, filter DatasourceFilter, conf *viper.
fmt.Fprint(os.Stderr, err)
continue
}
if !filter.ValidateDatasource(GetSlug(newDS.Name)) {

if !filter.Validate(map[string]string{Name: GetSlug(newDS.Name)}) {
continue
}
dsConfig := config.GetDefaultGrafanaConfig()
Expand All @@ -122,13 +122,13 @@ func ExportDataSources(client *sdk.Client, filter DatasourceFilter, conf *viper.

for _, existingDS := range datasources {
if existingDS.Name == newDS.Name {
if status, err = client.DeleteDatasource(ctx, existingDS.ID); err != nil {
if status, err = s.client.DeleteDatasource(ctx, existingDS.ID); err != nil {
fmt.Fprintf(os.Stderr, "error on deleting datasource %s with %s", newDS.Name, err)
}
break
}
}
if status, err = client.CreateDatasource(ctx, newDS); err != nil {
if status, err = s.client.CreateDatasource(ctx, newDS); err != nil {
fmt.Fprintf(os.Stderr, "error on importing datasource %s with %s (%s)", newDS.Name, err, *status.Message)
} else {
exported = append(exported, fileLocation)
Expand Down
Loading

0 comments on commit 0669fb4

Please sign in to comment.