bucketstorage.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package storage
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/pkg/errors"
  6. "gopkg.in/yaml.v2"
  7. )
  8. // StorageProvider is the type of provider used for storage if not leveraging a file implementation.
  9. type StorageProvider string
  10. const (
  11. S3 StorageProvider = "S3"
  12. GCS StorageProvider = "GCS"
  13. AZURE StorageProvider = "AZURE"
  14. )
  15. // StorageConfig is the configuration type used as the "parent" configuration. It contains a type, which will
  16. // specify the bucket storage implementation, and a configuration object specific to that storage implementation.
  17. type StorageConfig struct {
  18. Type StorageProvider `yaml:"type"`
  19. Config interface{} `yaml:"config"`
  20. Prefix string `yaml:"prefix"`
  21. }
  22. // NewBucketStorage initializes and returns new Storage implementation leveraging the storage provider
  23. // configuration. This configuration type uses the layout provided in thanos: https://thanos.io/tip/thanos/storage.md/
  24. func NewBucketStorage(config []byte) (Storage, error) {
  25. storageConfig := &StorageConfig{}
  26. if err := yaml.UnmarshalStrict(config, storageConfig); err != nil {
  27. return nil, errors.Wrap(err, "parsing config YAML file")
  28. }
  29. // Because the Config property is specific to the storage implementation, we'll marshal back into yaml, and allow
  30. // the specific implementation to unmarshal back into a concrete configuration type.
  31. config, err := yaml.Marshal(storageConfig.Config)
  32. if err != nil {
  33. return nil, errors.Wrap(err, "marshal content of storage configuration")
  34. }
  35. var storage Storage
  36. switch strings.ToUpper(string(storageConfig.Type)) {
  37. case string(S3):
  38. storage, err = NewS3Storage(config)
  39. case string(GCS):
  40. storage, err = NewGCSStorage(config)
  41. case string(AZURE):
  42. storage, err = NewAzureStorage(config)
  43. default:
  44. return nil, errors.Errorf("storage with type %s is not supported", storageConfig.Type)
  45. }
  46. if err != nil {
  47. return nil, errors.Wrap(err, fmt.Sprintf("create %s client", storageConfig.Type))
  48. }
  49. if storageConfig.Prefix != "" {
  50. return NewPrefixedBucketStorage(storage, storageConfig.Prefix)
  51. }
  52. return storage, nil
  53. }
  54. // trimLeading removes a leading / from the file name
  55. func trimLeading(file string) string {
  56. if len(file) == 0 {
  57. return file
  58. }
  59. if file[0] == '/' {
  60. return file[1:]
  61. }
  62. return file
  63. }
  64. // trimName removes the leading directory prefix
  65. func trimName(file string) string {
  66. slashIndex := strings.LastIndex(file, "/")
  67. if slashIndex < 0 {
  68. return file
  69. }
  70. name := file[slashIndex+1:]
  71. return name
  72. }