prefixedbucketstorage.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package storage
  2. // Partially forked from Thanos prefixed bucket for prefix handling
  3. // Licensed under the Apache License 2.0
  4. // https://github.com/thanos-io/objstore/blob/main/prefixed_bucket.go
  5. import (
  6. "fmt"
  7. "io"
  8. "strings"
  9. "github.com/pkg/errors"
  10. )
  11. type PrefixedBucketStorage struct {
  12. storage Storage
  13. prefix string
  14. }
  15. func NewPrefixedBucketStorage(storage Storage, prefix string) (Storage, error) {
  16. if validPrefix(prefix) {
  17. return &PrefixedBucketStorage{
  18. storage: storage,
  19. prefix: strings.Trim(prefix, DirDelim),
  20. }, nil
  21. }
  22. return storage, errors.Errorf("failed to create prefixed storage: invalid prefix '%s'", prefix)
  23. }
  24. func validPrefix(prefix string) bool {
  25. prefix = strings.Replace(prefix, "/", "", -1)
  26. return len(prefix) > 0
  27. }
  28. func conditionalPrefix(prefix, name string) string {
  29. if len(name) > 0 && !strings.HasPrefix(name, prefix) {
  30. return withPrefix(prefix, name)
  31. }
  32. return name
  33. }
  34. func withPrefix(prefix, name string) string {
  35. return prefix + DirDelim + name
  36. }
  37. // String returns the string representation of the prefixed bucket storage.
  38. func (pbs *PrefixedBucketStorage) String() string {
  39. if stringer, ok := pbs.storage.(fmt.Stringer); ok {
  40. return stringer.String()
  41. }
  42. return ""
  43. }
  44. func (pbs *PrefixedBucketStorage) StorageType() StorageType {
  45. return pbs.storage.StorageType()
  46. }
  47. // FullPath returns the storage working path combined with the path provided.
  48. func (pbs *PrefixedBucketStorage) FullPath(name string) string {
  49. return pbs.storage.FullPath(conditionalPrefix(pbs.prefix, name))
  50. }
  51. // Exists checks if the given object exists.
  52. func (pbs *PrefixedBucketStorage) Exists(name string) (bool, error) {
  53. return pbs.storage.Exists(conditionalPrefix(pbs.prefix, name))
  54. }
  55. // List returns storage information for files on the provided path.
  56. func (pbs *PrefixedBucketStorage) List(path string) ([]*StorageInfo, error) {
  57. return pbs.storage.List(conditionalPrefix(pbs.prefix, path))
  58. }
  59. // ListDirectories returns storage information for only directories on the provided path.
  60. func (pbs *PrefixedBucketStorage) ListDirectories(path string) ([]*StorageInfo, error) {
  61. return pbs.storage.ListDirectories(conditionalPrefix(pbs.prefix, path))
  62. }
  63. // Read returns a reader for the given object name.
  64. func (pbs *PrefixedBucketStorage) Read(name string) ([]byte, error) {
  65. return pbs.storage.Read(conditionalPrefix(pbs.prefix, name))
  66. }
  67. // ReadStream returns a streaming reader for the given object name.
  68. func (pbs *PrefixedBucketStorage) ReadStream(name string) (io.ReadCloser, error) {
  69. return pbs.storage.ReadStream(conditionalPrefix(pbs.prefix, name))
  70. }
  71. // ReadToLocalFile streams the specified object at path to destPath on the local file system.
  72. func (pbs *PrefixedBucketStorage) ReadToLocalFile(path, destPath string) error {
  73. return pbs.storage.ReadToLocalFile(conditionalPrefix(pbs.prefix, path), destPath)
  74. }
  75. // Remove deletes the object with the given name.
  76. func (pbs *PrefixedBucketStorage) Remove(name string) error {
  77. return pbs.storage.Remove(conditionalPrefix(pbs.prefix, name))
  78. }
  79. // Stat returns information about the specified object.
  80. func (pbs *PrefixedBucketStorage) Stat(name string) (*StorageInfo, error) {
  81. return pbs.storage.Stat(conditionalPrefix(pbs.prefix, name))
  82. }
  83. // Write uploads the contents of the reader as an object into the bucket.
  84. func (pbs *PrefixedBucketStorage) Write(name string, data []byte) error {
  85. return pbs.storage.Write(conditionalPrefix(pbs.prefix, name), data)
  86. }