From fbceb1d987b2551e4198d1344d657a8fa78f0508 Mon Sep 17 00:00:00 2001 From: Maksym Postument <777rip777@gmail.com> Date: Sat, 17 Apr 2021 07:41:26 +0300 Subject: [PATCH] Added folder name to push and pull command (#13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added parameter folderName * ✨ Added folderName or Id for pull command * 📝 readme update --- README.MD | 48 +++++++++++++++++++++++++++++++++++++------- cmd/root.go | 44 +++++++++++++++++++++++++++++++++++----- go.mod | 4 ++-- go.sum | 4 ++-- grafana/dashboard.go | 14 +++++++++++-- grafana/folder.go | 17 ++++++++++++++++ 6 files changed, 113 insertions(+), 18 deletions(-) diff --git a/README.MD b/README.MD index 77082af..b769855 100644 --- a/README.MD +++ b/README.MD @@ -10,14 +10,17 @@ Keep your grafana dashboards in sync. - [Getting Started](#getting-started) - [Pull](#pull) - [Save all dashboards to directory](#save-all-dashboards-to-directory) + - [Save all dashboards from specific folder to local directory using folder name](#save-all-dashboards-from-specific-folder-to-local-directory-using-folder-name) + - [Save all dashboards from specific folder to local directory using folder id](#save-all-dashboards-from-specific-folder-to-local-directory-using-folder-id) - [Save dashboards with specific tags to directory](#save-dashboards-with-specific-tags-to-directory) - [Save folders configuration to directory](#save-folders-configuration-to-directory) - [Save notifications configuration to directory](#save-notifications-configuration-to-directory) - [Save datasources configuration to directory](#save-datasources-configuration-to-directory) - [Push](#push) - [Push dashboards to grafana](#push-dashboards-to-grafana) + - [Push dashboards to grafana in custom folder by folder name](#push-dashboards-to-grafana-in-custom-folder-by-folder-name) + - [Push folders to grafana in custom folder by folder id](#push-folders-to-grafana-in-custom-folder-by-folder-id) - [Push folders to grafana](#push-folders-to-grafana) - - [Push folders to grafana in custom folder](#push-folders-to-grafana-in-custom-folder) - [Push notifications to grafana](#push-notifications-to-grafana) - [Push datasources to grafana](#push-datasources-to-grafana) - [Global parameters](#global-parameters) @@ -34,10 +37,34 @@ Download the latest binary from [releases](https://github.com/mpostument/grafana #### Save all dashboards to directory -`grafana-sync pull-dashboards --directory="dashboards` +`grafana-sync pull-dashboards --directory="dashboards"` Example: `grafana-sync pull-dashboards --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="dashboards" --url http://127.0.0.1:3000` +#### Save all dashboards from specific folder to local directory using folder name + +Specify folder name in pull command +`grafana-sync pull-dashboards --folderName= --directory="dashboards"` +Example: + `grafana-sync pull-dashboards --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="folders" --url http://127.0.0.1:3000 --folderName="TestFolder"` + +#### Save all dashboards from specific folder to local directory using folder id + +Find grafana folder Id by opening /api/folders in browser. +Example: +`http://127.0.0.1:3000/api/folders` + +Find required folderId in output + +```json +[{"id":1,"uid":"RcuWg5UMz","title":"TestFolder"}] +``` + +Specify folder id in pull command +`grafana-sync pull-dashboards --folderId=` +Example: + `grafana-sync pull-folders --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="folders" --url http://127.0.0.1:3000 --folderId=1` + #### Save dashboards with specific tags to directory `grafana-sync pull-dashboards --tag=export` @@ -70,13 +97,14 @@ Example: Example: `grafana-sync push-dashboards --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="dashboards" --url http://127.0.0.1:3000` -#### Push folders to grafana +#### Push dashboards to grafana in custom folder by folder name -`grafana-sync push-folders` +Specify folder name in push command +`grafana-sync push-dashboards --folderName=` Example: - `grafana-sync push-folders --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="folders" --url http://127.0.0.1:3000` + `grafana-sync push-dashboards --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="folders" --url http://127.0.0.1:3000 --folderName="TestFolder"` -#### Push folders to grafana in custom folder +#### Push folders to grafana in custom folder by folder id Find grafana folder Id by opening /api/folders in browser. Example: @@ -89,10 +117,16 @@ Find required folderId in output ``` Specify folder id in push command -`grafana-sync push-folders --folderId=` +`grafana-sync push-dashboards --folderId=` Example: `grafana-sync push-folders --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="folders" --url http://127.0.0.1:3000 --folderId=1` +#### Push folders to grafana + +`grafana-sync push-folders` +Example: + `grafana-sync push-folders --apikey="eyJrIjoiOWJYTktGNFlCbFVMOG1LY3d6ekN4Mmw4MFgyYU44a1UiLCJuIjoiY29icmEiLCJpZCI6MX0=" --directory="folders" --url http://127.0.0.1:3000` + #### Push notifications to grafana `grafana-sync push-notifications` diff --git a/cmd/root.go b/cmd/root.go index 68fabf7..9e541ef 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -30,9 +30,10 @@ import ( var cfgFile string var rootCmd = &cobra.Command{ - Use: "grafana-sync", - Short: "Root command for grafana interaction", - Long: `Root command for grafana interaction.`, + Use: "grafana-sync", + Short: "Root command for grafana interaction", + Long: `Root command for grafana interaction.`, + Version: "1.4.0", } var pullDashboardsCmd = &cobra.Command{ @@ -42,11 +43,26 @@ var pullDashboardsCmd = &cobra.Command{ Directory name specified by flag --directory. If flag --tags is used, additional directory will be created with tag name creating structure like directory/tag`, Run: func(cmd *cobra.Command, args []string) { + var ( + folderId int + err error + ) url, _ := cmd.Flags().GetString("url") apiKey := viper.GetString("apikey") directory, _ := cmd.Flags().GetString("directory") tag, _ := cmd.Flags().GetString("tag") - if err := grafana.PullDashboard(url, apiKey, directory, tag); err != nil { + folderName, _ := cmd.Flags().GetString("folderName") + + if folderName != "" { + folderId, err = grafana.FindFolderId(url, apiKey, folderName) + if err != nil { + log.Fatalln(err) + } + } else { + folderId, _ = cmd.Flags().GetInt("folderId") + } + + if err := grafana.PullDashboard(url, apiKey, directory, tag, folderId); err != nil { log.Fatalln("Pull dashboards command failed", err) } }, @@ -57,10 +73,24 @@ var pushDashboardsCmd = &cobra.Command{ Short: "Push grafana dashboards from directory", Long: `Read json with dashboards description and publish to grafana.`, Run: func(cmd *cobra.Command, args []string) { + var ( + folderId int + err error + ) url, _ := cmd.Flags().GetString("url") apiKey, _ := cmd.Flags().GetString("apikey") directory, _ := cmd.Flags().GetString("directory") - folderId, _ := cmd.Flags().GetInt("folderId") + folderName, _ := cmd.Flags().GetString("folderName") + + if folderName != "" { + folderId, err = grafana.FindFolderId(url, apiKey, folderName) + if err != nil { + log.Fatalln(err) + } + } else { + folderId, _ = cmd.Flags().GetInt("folderId") + } + if err := grafana.PushDashboard(url, apiKey, directory, folderId); err != nil { log.Fatalln("Push dashboards command failed", err) } @@ -170,6 +200,10 @@ func init() { rootCmd.PersistentFlags().StringP("apikey", "a", "", "Grafana api key") pullDataSourcesCmd.PersistentFlags().StringP("tag", "t", "", "Dashboard tag to read") pushDashboardsCmd.PersistentFlags().IntP("folderId", "f", 0, "Directory Id to which push dashboards") + pushDashboardsCmd.PersistentFlags().StringP("folderName", "n", "", "Directory name to which push dashboards") + + pullDashboardsCmd.PersistentFlags().IntP("folderId", "f", -1, "Directory Id from which pull dashboards") + pullDashboardsCmd.PersistentFlags().StringP("folderName", "n", "", "Directory name from which pull dashboards") if err := viper.BindPFlag("apikey", rootCmd.PersistentFlags().Lookup("apikey")); err != nil { log.Println(err) diff --git a/go.mod b/go.mod index 4679533..b50c545 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/mpostument/grafana-sync -go 1.15 +go 1.16 require ( - github.com/grafana-tools/sdk v0.0.0-20210304215344-87b5b481d75a + github.com/grafana-tools/sdk v0.0.0-20210402150123-f7c763c3738c github.com/mitchellh/go-homedir v1.1.0 github.com/spf13/cobra v1.1.3 github.com/spf13/viper v1.7.1 diff --git a/go.sum b/go.sum index bbab1f0..fd411d9 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosimple/slug v1.1.1 h1:fRu/digW+NMwBIP+RmviTK97Ho/bEj/C9swrCspN3D4= github.com/gosimple/slug v1.1.1/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0= -github.com/grafana-tools/sdk v0.0.0-20210304215344-87b5b481d75a h1:eii+WU42hYYH/OWIKfC45tjFuZRlVY07LdwT4E33dKA= -github.com/grafana-tools/sdk v0.0.0-20210304215344-87b5b481d75a/go.mod h1:uby+6hPUCRVNG/iAZKCOlaq5YhyK0oKMRke+FDesZdw= +github.com/grafana-tools/sdk v0.0.0-20210402150123-f7c763c3738c h1:PxbQpT+CoC6wo0Nc8z7KAzeDu455FfLnqsZXRBpFWOA= +github.com/grafana-tools/sdk v0.0.0-20210402150123-f7c763c3738c/go.mod h1:uby+6hPUCRVNG/iAZKCOlaq5YhyK0oKMRke+FDesZdw= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= diff --git a/grafana/dashboard.go b/grafana/dashboard.go index db9aaa2..da09263 100644 --- a/grafana/dashboard.go +++ b/grafana/dashboard.go @@ -12,18 +12,28 @@ import ( "github.com/grafana-tools/sdk" ) -func PullDashboard(grafanaURL string, apiKey string, directory string, tag string) error { +func PullDashboard(grafanaURL string, apiKey string, directory string, tag string, folderID int) error { var ( boardLinks []sdk.FoundBoard rawBoard sdk.Board meta sdk.BoardProperties err error ) + ctx := context.Background() c := sdk.NewClient(grafanaURL, apiKey, sdk.DefaultHTTPClient) - if boardLinks, err = c.Search(ctx, sdk.SearchTag(tag), sdk.SearchType(sdk.SearchTypeDashboard)); err != nil { + searchParams := []sdk.SearchParam{sdk.SearchType(sdk.SearchTypeDashboard)} + if folderID != -1 { + searchParams = append(searchParams, sdk.SearchFolderID(folderID)) + } + + if tag != "" { + searchParams = append(searchParams, sdk.SearchTag(tag)) + } + + if boardLinks, err = c.Search(ctx, searchParams...); err != nil { return err } diff --git a/grafana/folder.go b/grafana/folder.go index 9a341dc..5de41d5 100644 --- a/grafana/folder.go +++ b/grafana/folder.go @@ -68,3 +68,20 @@ func PushFolder(grafanaURL string, apiKey string, directory string) error { } return nil } + +func FindFolderId(grafanaURL string, apiKey string, folderName string) (int, error) { + ctx := context.Background() + c := sdk.NewClient(grafanaURL, apiKey, sdk.DefaultHTTPClient) + + allFolders, err := c.GetAllFolders(ctx) + + if err != nil { + return 0, err + } + for _, folder := range allFolders { + if folder.Title == folderName { + return folder.ID, nil + } + } + return 0, nil +}