storage.go 3.3 KB

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