bucketstorage.go 2.5 KB

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