dashboard.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. package cmd
  2. import (
  3. "encoding/json"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "github.com/codegangsta/cli"
  9. "github.com/grafana/grafana/pkg/bus"
  10. "github.com/grafana/grafana/pkg/log"
  11. m "github.com/grafana/grafana/pkg/models"
  12. )
  13. var (
  14. ImportDashboard = cli.Command{
  15. Name: "dashboards:import",
  16. Usage: "imports dashboards in JSON from a directory",
  17. Description: "Starts Grafana import process",
  18. Action: runImport,
  19. Flags: []cli.Flag{
  20. cli.StringFlag{
  21. Name: "dir",
  22. Usage: "path to folder containing json dashboards",
  23. },
  24. },
  25. }
  26. ExportDashboard = cli.Command{
  27. Name: "dashboards:export",
  28. Usage: "exports dashboards in JSON from a directory",
  29. Description: "Starts Grafana export process",
  30. Action: runExport,
  31. Flags: []cli.Flag{
  32. cli.StringFlag{
  33. Name: "dir",
  34. Usage: "path to folder containing json dashboards",
  35. },
  36. },
  37. }
  38. )
  39. func runImport(c *cli.Context) {
  40. dir := c.String("dir")
  41. if len(dir) == 0 {
  42. log.ConsoleFatalf("Missing command flag --dir")
  43. }
  44. file, err := os.Stat(dir)
  45. if os.IsNotExist(err) {
  46. log.ConsoleFatalf("Directory does not exist: %v", dir)
  47. }
  48. if !file.IsDir() {
  49. log.ConsoleFatalf("%v is not a directory", dir)
  50. }
  51. if !c.Args().Present() {
  52. log.ConsoleFatal("Organization name arg is required")
  53. }
  54. orgName := c.Args().First()
  55. initRuntime(c)
  56. orgQuery := m.GetOrgByNameQuery{Name: orgName}
  57. if err := bus.Dispatch(&orgQuery); err != nil {
  58. log.ConsoleFatalf("Failed to find account", err)
  59. }
  60. orgId := orgQuery.Result.Id
  61. visitor := func(path string, f os.FileInfo, err error) error {
  62. if err != nil {
  63. return err
  64. }
  65. if f.IsDir() {
  66. return nil
  67. }
  68. if strings.HasSuffix(f.Name(), ".json") {
  69. if err := importDashboard(path, orgId); err != nil {
  70. log.ConsoleFatalf("Failed to import dashboard file: %v, err: %v", path, err)
  71. }
  72. }
  73. return nil
  74. }
  75. if err := filepath.Walk(dir, visitor); err != nil {
  76. log.ConsoleFatalf("Failed to scan dir for json files: %v", err)
  77. }
  78. }
  79. func importDashboard(path string, orgId int64) error {
  80. log.ConsoleInfof("Importing %v", path)
  81. reader, err := os.Open(path)
  82. if err != nil {
  83. return err
  84. }
  85. defer reader.Close()
  86. dash := m.NewDashboard("temp")
  87. jsonParser := json.NewDecoder(reader)
  88. if err := jsonParser.Decode(&dash.Data); err != nil {
  89. return err
  90. }
  91. dash.Data["id"] = nil
  92. cmd := m.SaveDashboardCommand{
  93. OrgId: orgId,
  94. Dashboard: dash.Data,
  95. }
  96. if err := bus.Dispatch(&cmd); err != nil {
  97. return err
  98. }
  99. return nil
  100. }
  101. func runExport(c *cli.Context) {
  102. initRuntime(c)
  103. if !c.Args().Present() {
  104. log.ConsoleFatal("Account name arg is required")
  105. }
  106. name := c.Args().First()
  107. orgQuery := m.GetOrgByNameQuery{Name: name}
  108. if err := bus.Dispatch(&orgQuery); err != nil {
  109. log.ConsoleFatalf("Failed to find organization: %s", err)
  110. }
  111. orgId := orgQuery.Result.Id
  112. dir := c.String("dir")
  113. dash := c.Args().Get(1)
  114. query := m.SearchDashboardsQuery{OrgId: orgId, Title: dash}
  115. err := bus.Dispatch(&query)
  116. if err != nil {
  117. log.ConsoleFatalf("Failed to find dashboards: %s", err)
  118. return
  119. }
  120. if dir == "" && len(query.Result) > 1 {
  121. log.ConsoleFatalf("Dashboard title '%s' returned too many results. "+
  122. "Use --dir <dir> or a more specific title", dash)
  123. return
  124. }
  125. for _, v := range query.Result {
  126. f := os.Stdout
  127. if dir != "" {
  128. dest := filepath.Join(dir, v.Slug+".json")
  129. f, err = os.Create(dest)
  130. if err != nil {
  131. log.ConsoleFatalf("Unable to create file: %s", err)
  132. }
  133. log.ConsoleInfof("Exporting '%s' dashboard to %s", v.Title, dest)
  134. }
  135. exportDashboard(f, orgId, v.Slug)
  136. if dir != "" {
  137. if err := f.Sync(); err != nil {
  138. log.ConsoleFatalf("Unable to sync file: %s", err)
  139. }
  140. if err := f.Close(); err != nil {
  141. log.ConsoleFatalf("Unable to close file: %s", err)
  142. }
  143. }
  144. }
  145. if dir != "" {
  146. log.ConsoleInfof("Exported %d dashboards to %s", len(query.Result), dir)
  147. }
  148. }
  149. func exportDashboard(w io.Writer, orgId int64, slug string) {
  150. query := m.GetDashboardQuery{Slug: slug, OrgId: orgId}
  151. err := bus.Dispatch(&query)
  152. if err != nil {
  153. log.ConsoleFatalf("Failed to find dashboard: %s", err)
  154. return
  155. }
  156. out, err := json.MarshalIndent(query.Result.Data, "", " ")
  157. if err != nil {
  158. log.ConsoleFatalf("Failed to marshal dashboard: %s", err)
  159. return
  160. }
  161. n, err := w.Write(out)
  162. if err != nil {
  163. log.ConsoleFatalf("Failed to write dashboard: %s", err)
  164. return
  165. }
  166. if n != len(out) {
  167. log.ConsoleFatalf("Failed to write dashboard: wrote %d expected %d", n, len(out))
  168. return
  169. }
  170. }