storage.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package storage
  2. import (
  3. "os"
  4. "time"
  5. "github.com/pkg/errors"
  6. )
  7. // DirDelim is the delimiter used to model a directory structure in an object store bucket.
  8. const DirDelim = "/"
  9. // DoesNotExistError is used as a generic error to return when a target path does not
  10. // exist in storage. Equivalent to os.ErrorNotExist such that it will work with os.IsNotExist(err)
  11. var DoesNotExistError = os.ErrNotExist
  12. // StorageInfo is a data object containing basic information about the path in storage.
  13. type StorageInfo struct {
  14. Name string // base name of the file
  15. Size int64 // length in bytes for regular files
  16. ModTime time.Time // modification time
  17. }
  18. // Storage provides an API for storing binary data
  19. type Storage interface {
  20. // StorageType returns a string identifier for the type of storage used by the implementation.
  21. StorageType() StorageType
  22. // FullPath returns the storage working path combined with the path provided
  23. FullPath(path string) string
  24. // Stat returns the StorageStats for the specific path.
  25. Stat(path string) (*StorageInfo, error)
  26. // Read uses the relative path of the storage combined with the provided path to
  27. // read the contents.
  28. Read(path string) ([]byte, error)
  29. // Write uses the relative path of the storage combined with the provided path
  30. // to write a new file or overwrite an existing file.
  31. Write(path string, data []byte) error
  32. // Remove uses the relative path of the storage combined with the provided path to
  33. // remove a file from storage permanently.
  34. Remove(path string) error
  35. // Exists uses the relative path of the storage combined with the provided path to
  36. // determine if the file exists.
  37. Exists(path string) (bool, error)
  38. // List uses the relative path of the storage combined with the provided path to return
  39. // storage information for the files.
  40. List(path string) ([]*StorageInfo, error)
  41. }
  42. // Validate uses the provided storage implementation to write a test file to the store, followed by a removal.
  43. func Validate(storage Storage) error {
  44. const testPath = "tmp/test.txt"
  45. const testContent = "test"
  46. // attempt to read a path
  47. _, err := storage.Exists(testPath)
  48. if err != nil {
  49. return errors.Wrap(err, "Failed to check if path exists")
  50. }
  51. // attempt to write a path
  52. err = storage.Write(testPath, []byte(testContent))
  53. if err != nil {
  54. return errors.Wrap(err, "Failed to write data to storage")
  55. }
  56. // attempt to read the path
  57. data, err := storage.Read(testPath)
  58. if err != nil {
  59. return errors.Wrap(err, "Failed to read data from storage")
  60. }
  61. if string(data) != testContent {
  62. return errors.New("Failed to read the expected data from storage")
  63. }
  64. // delete the path
  65. err = storage.Remove(testPath)
  66. if err != nil {
  67. return errors.Wrap(err, "Failed to remove data from storage")
  68. }
  69. return nil
  70. }
  71. // IsNotExist returns true if the error provided from a storage object is DoesNotExist
  72. func IsNotExist(err error) bool {
  73. if err == nil {
  74. return false
  75. }
  76. return err.Error() == DoesNotExistError.Error()
  77. }