Tool to help you manage your Grafana dashboards using Git.

git.go 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package git
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "strings"
  6. "time"
  7. "gopkg.in/src-d/go-git.v4"
  8. "gopkg.in/src-d/go-git.v4/plumbing"
  9. "gopkg.in/src-d/go-git.v4/plumbing/object"
  10. "golang.org/x/crypto/ssh"
  11. gitssh "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
  12. )
  13. func Sync(repo string, clonePath string, privateKeyPath string) (r *git.Repository, err error) {
  14. auth, err := getAuth(privateKeyPath)
  15. if err != nil {
  16. return
  17. }
  18. exists, err := dirExists(clonePath)
  19. if err != nil {
  20. return
  21. }
  22. if exists {
  23. r, err = pull(clonePath, auth)
  24. } else {
  25. r, err = clone(repo, clonePath, auth)
  26. }
  27. return
  28. }
  29. func getAuth(privateKeyPath string) (*gitssh.PublicKeys, error) {
  30. privateKey, err := ioutil.ReadFile(privateKeyPath)
  31. if err != nil {
  32. return nil, err
  33. }
  34. signer, err := ssh.ParsePrivateKey(privateKey)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return &gitssh.PublicKeys{User: "git", Signer: signer}, nil
  39. }
  40. func clone(repo string, clonePath string, auth *gitssh.PublicKeys) (*git.Repository, error) {
  41. return git.PlainClone(clonePath, false, &git.CloneOptions{
  42. URL: repo,
  43. Auth: auth,
  44. })
  45. }
  46. func pull(clonePath string, auth *gitssh.PublicKeys) (*git.Repository, error) {
  47. r, err := git.PlainOpen(clonePath)
  48. if err != nil {
  49. return nil, err
  50. }
  51. w, err := r.Worktree()
  52. if err != nil {
  53. return nil, err
  54. }
  55. err = w.Pull(&git.PullOptions{
  56. RemoteName: "origin",
  57. Auth: auth,
  58. })
  59. if err == git.NoErrAlreadyUpToDate {
  60. return r, nil
  61. }
  62. // go-git doesn't have an error variable for "non-fast-forward update", so
  63. // this is the only way to detect it
  64. if strings.HasPrefix("non-fast-forward update", err.Error()) {
  65. return r, nil
  66. }
  67. return r, err
  68. }
  69. func dirExists(path string) (bool, error) {
  70. _, err := os.Stat(path)
  71. if os.IsNotExist(err) {
  72. return false, nil
  73. }
  74. return true, err
  75. }
  76. func Commit(message string, w *git.Worktree) (plumbing.Hash, error) {
  77. return w.Commit(message, &git.CommitOptions{
  78. Author: &object.Signature{
  79. Name: "Grafana Dashboard Manager",
  80. Email: "grafana@cozycloud.cc",
  81. When: time.Now(),
  82. },
  83. })
  84. }
  85. func Push(r *git.Repository, keyPath string) error {
  86. auth, err := getAuth(keyPath)
  87. if err != nil {
  88. return err
  89. }
  90. err = r.Push(&git.PushOptions{
  91. Auth: auth,
  92. })
  93. if err == git.NoErrAlreadyUpToDate {
  94. return nil
  95. }
  96. return err
  97. }