github.com/lusis/distribution@v2.0.1+incompatible/registry/storage/driver/base/base.go (about)

     1  // Package base provides a base implementation of the storage driver that can
     2  // be used to implement common checks. The goal is to increase the amount of
     3  // code sharing.
     4  //
     5  // The canonical approach to use this class is to embed in the exported driver
     6  // struct such that calls are proxied through this implementation. First,
     7  // declare the internal driver, as follows:
     8  //
     9  // 	type driver struct { ... internal ...}
    10  //
    11  // The resulting type should implement StorageDriver such that it can be the
    12  // target of a Base struct. The exported type can then be declared as follows:
    13  //
    14  // 	type Driver struct {
    15  // 		Base
    16  // 	}
    17  //
    18  // Because Driver embeds Base, it effectively implements Base. If the driver
    19  // needs to intercept a call, before going to base, Driver should implement
    20  // that method. Effectively, Driver can intercept calls before coming in and
    21  // driver implements the actual logic.
    22  //
    23  // To further shield the embed from other packages, it is recommended to
    24  // employ a private embed struct:
    25  //
    26  // 	type baseEmbed struct {
    27  // 		base.Base
    28  // 	}
    29  //
    30  // Then, declare driver to embed baseEmbed, rather than Base directly:
    31  //
    32  // 	type Driver struct {
    33  // 		baseEmbed
    34  // 	}
    35  //
    36  // The type now implements StorageDriver, proxying through Base, without
    37  // exporting an unnecessary field.
    38  package base
    39  
    40  import (
    41  	"io"
    42  
    43  	"github.com/docker/distribution/context"
    44  	storagedriver "github.com/docker/distribution/registry/storage/driver"
    45  )
    46  
    47  // Base provides a wrapper around a storagedriver implementation that provides
    48  // common path and bounds checking.
    49  type Base struct {
    50  	storagedriver.StorageDriver
    51  }
    52  
    53  // GetContent wraps GetContent of underlying storage driver.
    54  func (base *Base) GetContent(path string) ([]byte, error) {
    55  	_, done := context.WithTrace(context.Background())
    56  	defer done("%s.GetContent(%q)", base.Name(), path)
    57  
    58  	if !storagedriver.PathRegexp.MatchString(path) {
    59  		return nil, storagedriver.InvalidPathError{Path: path}
    60  	}
    61  
    62  	return base.StorageDriver.GetContent(path)
    63  }
    64  
    65  // PutContent wraps PutContent of underlying storage driver.
    66  func (base *Base) PutContent(path string, content []byte) error {
    67  	_, done := context.WithTrace(context.Background())
    68  	defer done("%s.PutContent(%q)", base.Name(), path)
    69  
    70  	if !storagedriver.PathRegexp.MatchString(path) {
    71  		return storagedriver.InvalidPathError{Path: path}
    72  	}
    73  
    74  	return base.StorageDriver.PutContent(path, content)
    75  }
    76  
    77  // ReadStream wraps ReadStream of underlying storage driver.
    78  func (base *Base) ReadStream(path string, offset int64) (io.ReadCloser, error) {
    79  	_, done := context.WithTrace(context.Background())
    80  	defer done("%s.ReadStream(%q, %d)", base.Name(), path, offset)
    81  
    82  	if offset < 0 {
    83  		return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
    84  	}
    85  
    86  	if !storagedriver.PathRegexp.MatchString(path) {
    87  		return nil, storagedriver.InvalidPathError{Path: path}
    88  	}
    89  
    90  	return base.StorageDriver.ReadStream(path, offset)
    91  }
    92  
    93  // WriteStream wraps WriteStream of underlying storage driver.
    94  func (base *Base) WriteStream(path string, offset int64, reader io.Reader) (nn int64, err error) {
    95  	_, done := context.WithTrace(context.Background())
    96  	defer done("%s.WriteStream(%q, %d)", base.Name(), path, offset)
    97  
    98  	if offset < 0 {
    99  		return 0, storagedriver.InvalidOffsetError{Path: path, Offset: offset}
   100  	}
   101  
   102  	if !storagedriver.PathRegexp.MatchString(path) {
   103  		return 0, storagedriver.InvalidPathError{Path: path}
   104  	}
   105  
   106  	return base.StorageDriver.WriteStream(path, offset, reader)
   107  }
   108  
   109  // Stat wraps Stat of underlying storage driver.
   110  func (base *Base) Stat(path string) (storagedriver.FileInfo, error) {
   111  	_, done := context.WithTrace(context.Background())
   112  	defer done("%s.Stat(%q)", base.Name(), path)
   113  
   114  	if !storagedriver.PathRegexp.MatchString(path) {
   115  		return nil, storagedriver.InvalidPathError{Path: path}
   116  	}
   117  
   118  	return base.StorageDriver.Stat(path)
   119  }
   120  
   121  // List wraps List of underlying storage driver.
   122  func (base *Base) List(path string) ([]string, error) {
   123  	_, done := context.WithTrace(context.Background())
   124  	defer done("%s.List(%q)", base.Name(), path)
   125  
   126  	if !storagedriver.PathRegexp.MatchString(path) && path != "/" {
   127  		return nil, storagedriver.InvalidPathError{Path: path}
   128  	}
   129  
   130  	return base.StorageDriver.List(path)
   131  }
   132  
   133  // Move wraps Move of underlying storage driver.
   134  func (base *Base) Move(sourcePath string, destPath string) error {
   135  	_, done := context.WithTrace(context.Background())
   136  	defer done("%s.Move(%q, %q", base.Name(), sourcePath, destPath)
   137  
   138  	if !storagedriver.PathRegexp.MatchString(sourcePath) {
   139  		return storagedriver.InvalidPathError{Path: sourcePath}
   140  	} else if !storagedriver.PathRegexp.MatchString(destPath) {
   141  		return storagedriver.InvalidPathError{Path: destPath}
   142  	}
   143  
   144  	return base.StorageDriver.Move(sourcePath, destPath)
   145  }
   146  
   147  // Delete wraps Delete of underlying storage driver.
   148  func (base *Base) Delete(path string) error {
   149  	_, done := context.WithTrace(context.Background())
   150  	defer done("%s.Delete(%q)", base.Name(), path)
   151  
   152  	if !storagedriver.PathRegexp.MatchString(path) {
   153  		return storagedriver.InvalidPathError{Path: path}
   154  	}
   155  
   156  	return base.StorageDriver.Delete(path)
   157  }
   158  
   159  // URLFor wraps URLFor of underlying storage driver.
   160  func (base *Base) URLFor(path string, options map[string]interface{}) (string, error) {
   161  	_, done := context.WithTrace(context.Background())
   162  	defer done("%s.URLFor(%q)", base.Name(), path)
   163  
   164  	if !storagedriver.PathRegexp.MatchString(path) {
   165  		return "", storagedriver.InvalidPathError{Path: path}
   166  	}
   167  
   168  	return base.StorageDriver.URLFor(path, options)
   169  }