imguploader.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package imguploader
  2. import (
  3. "context"
  4. "fmt"
  5. "regexp"
  6. "github.com/grafana/grafana/pkg/infra/log"
  7. "github.com/grafana/grafana/pkg/setting"
  8. )
  9. type ImageUploader interface {
  10. Upload(ctx context.Context, path string) (string, error)
  11. }
  12. type NopImageUploader struct {
  13. }
  14. func (NopImageUploader) Upload(ctx context.Context, path string) (string, error) {
  15. return "", nil
  16. }
  17. var (
  18. logger = log.New("imguploader")
  19. )
  20. func NewImageUploader() (ImageUploader, error) {
  21. switch setting.ImageUploadProvider {
  22. case "s3":
  23. s3sec, err := setting.Raw.GetSection("external_image_storage.s3")
  24. if err != nil {
  25. return nil, err
  26. }
  27. bucket := s3sec.Key("bucket").MustString("")
  28. region := s3sec.Key("region").MustString("")
  29. path := s3sec.Key("path").MustString("")
  30. bucketUrl := s3sec.Key("bucket_url").MustString("")
  31. accessKey := s3sec.Key("access_key").MustString("")
  32. secretKey := s3sec.Key("secret_key").MustString("")
  33. if path != "" && path[len(path)-1:] != "/" {
  34. path += "/"
  35. }
  36. if bucket == "" || region == "" {
  37. info, err := getRegionAndBucketFromUrl(bucketUrl)
  38. if err != nil {
  39. return nil, err
  40. }
  41. bucket = info.bucket
  42. region = info.region
  43. }
  44. return NewS3Uploader(region, bucket, path, "public-read", accessKey, secretKey), nil
  45. case "webdav":
  46. webdavSec, err := setting.Raw.GetSection("external_image_storage.webdav")
  47. if err != nil {
  48. return nil, err
  49. }
  50. url := webdavSec.Key("url").String()
  51. if url == "" {
  52. return nil, fmt.Errorf("Could not find url key for image.uploader.webdav")
  53. }
  54. public_url := webdavSec.Key("public_url").String()
  55. username := webdavSec.Key("username").String()
  56. password := webdavSec.Key("password").String()
  57. return NewWebdavImageUploader(url, username, password, public_url)
  58. case "gcs":
  59. gcssec, err := setting.Raw.GetSection("external_image_storage.gcs")
  60. if err != nil {
  61. return nil, err
  62. }
  63. keyFile := gcssec.Key("key_file").MustString("")
  64. bucketName := gcssec.Key("bucket").MustString("")
  65. path := gcssec.Key("path").MustString("")
  66. return NewGCSUploader(keyFile, bucketName, path), nil
  67. case "azure_blob":
  68. azureBlobSec, err := setting.Raw.GetSection("external_image_storage.azure_blob")
  69. if err != nil {
  70. return nil, err
  71. }
  72. account_name := azureBlobSec.Key("account_name").MustString("")
  73. account_key := azureBlobSec.Key("account_key").MustString("")
  74. container_name := azureBlobSec.Key("container_name").MustString("")
  75. return NewAzureBlobUploader(account_name, account_key, container_name), nil
  76. case "local":
  77. return NewLocalImageUploader()
  78. }
  79. if setting.ImageUploadProvider != "" {
  80. logger.Error("The external image storage configuration is invalid", "unsupported provider", setting.ImageUploadProvider)
  81. }
  82. return NopImageUploader{}, nil
  83. }
  84. type s3Info struct {
  85. region string
  86. bucket string
  87. }
  88. func getRegionAndBucketFromUrl(url string) (*s3Info, error) {
  89. info := &s3Info{}
  90. urlRegex := regexp.MustCompile(`https?:\/\/(.*)\.s3(-([^.]+))?\.amazonaws\.com\/?`)
  91. matches := urlRegex.FindStringSubmatch(url)
  92. if len(matches) > 0 {
  93. info.bucket = matches[1]
  94. if matches[3] != "" {
  95. info.region = matches[3]
  96. } else {
  97. info.region = "us-east-1"
  98. }
  99. return info, nil
  100. }
  101. urlRegex2 := regexp.MustCompile(`https?:\/\/s3(-([^.]+))?\.amazonaws\.com\/(.*)?`)
  102. matches2 := urlRegex2.FindStringSubmatch(url)
  103. if len(matches2) > 0 {
  104. info.bucket = matches2[3]
  105. if matches2[2] != "" {
  106. info.region = matches2[2]
  107. } else {
  108. info.region = "us-east-1"
  109. }
  110. return info, nil
  111. }
  112. return nil, fmt.Errorf("Could not find bucket setting for image.uploader.s3")
  113. }