forked from TrueCloudLab/distribution
Updates documentation to follow godoc conventions
This commit is contained in:
parent
ca0084fad1
commit
0e5d41ff9b
9 changed files with 84 additions and 64 deletions
|
@ -7,13 +7,14 @@ import (
|
||||||
"github.com/docker/docker-registry/storagedriver/ipc"
|
"github.com/docker/docker-registry/storagedriver/ipc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Internal mapping between storage driver names and their respective factories
|
// driverFactories stores an internal mapping between storage driver names and their respective
|
||||||
|
// factories
|
||||||
var driverFactories = make(map[string]StorageDriverFactory)
|
var driverFactories = make(map[string]StorageDriverFactory)
|
||||||
|
|
||||||
// Factory interface for the storagedriver.StorageDriver interface
|
// StorageDriverFactory is a factory interface for creating storagedriver.StorageDriver interfaces
|
||||||
// Storage drivers should call Register() with a factory to make the driver available by name
|
// Storage drivers should call Register() with a factory to make the driver available by name
|
||||||
type StorageDriverFactory interface {
|
type StorageDriverFactory interface {
|
||||||
// Creates and returns a new storagedriver.StorageDriver with the given parameters
|
// Create returns a new storagedriver.StorageDriver with the given parameters
|
||||||
// Parameters will vary by driver and may be ignored
|
// Parameters will vary by driver and may be ignored
|
||||||
// Each parameter key must only consist of lowercase letters and numbers
|
// Each parameter key must only consist of lowercase letters and numbers
|
||||||
Create(parameters map[string]string) (storagedriver.StorageDriver, error)
|
Create(parameters map[string]string) (storagedriver.StorageDriver, error)
|
||||||
|
@ -54,7 +55,7 @@ func Create(name string, parameters map[string]string) (storagedriver.StorageDri
|
||||||
return driverFactory.Create(parameters)
|
return driverFactory.Create(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returned when attempting to construct an unregistered storage driver
|
// InvalidStorageDriverError records an attempt to construct an unregistered storage driver
|
||||||
type InvalidStorageDriverError struct {
|
type InvalidStorageDriverError struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,20 +18,20 @@ func init() {
|
||||||
factory.Register(DriverName, &filesystemDriverFactory{})
|
factory.Register(DriverName, &filesystemDriverFactory{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the factory.StorageDriverFactory interface
|
// filesystemDriverFactory implements the factory.StorageDriverFactory interface
|
||||||
type filesystemDriverFactory struct{}
|
type filesystemDriverFactory struct{}
|
||||||
|
|
||||||
func (factory *filesystemDriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
|
func (factory *filesystemDriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
|
||||||
return FromParameters(parameters), nil
|
return FromParameters(parameters), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Storage Driver backed by a local filesystem
|
// FilesystemDriver is a storagedriver.StorageDriver implementation backed by a local filesystem
|
||||||
// All provided paths will be subpaths of the RootDirectory
|
// All provided paths will be subpaths of the RootDirectory
|
||||||
type FilesystemDriver struct {
|
type FilesystemDriver struct {
|
||||||
rootDirectory string
|
rootDirectory string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new FilesystemDriver with a given parameters map
|
// FromParameters constructs a new FilesystemDriver with a given parameters map
|
||||||
// Optional Parameters:
|
// Optional Parameters:
|
||||||
// - rootdirectory
|
// - rootdirectory
|
||||||
func FromParameters(parameters map[string]string) *FilesystemDriver {
|
func FromParameters(parameters map[string]string) *FilesystemDriver {
|
||||||
|
@ -45,11 +45,12 @@ func FromParameters(parameters map[string]string) *FilesystemDriver {
|
||||||
return New(rootDirectory)
|
return New(rootDirectory)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new FilesystemDriver with a given rootDirectory
|
// New constructs a new FilesystemDriver with a given rootDirectory
|
||||||
func New(rootDirectory string) *FilesystemDriver {
|
func New(rootDirectory string) *FilesystemDriver {
|
||||||
return &FilesystemDriver{rootDirectory}
|
return &FilesystemDriver{rootDirectory}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subPath returns the absolute path of a key within the FilesystemDriver's storage
|
||||||
func (d *FilesystemDriver) subPath(subPath string) string {
|
func (d *FilesystemDriver) subPath(subPath string) string {
|
||||||
return path.Join(d.rootDirectory, subPath)
|
return path.Join(d.rootDirectory, subPath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,25 +19,27 @@ func init() {
|
||||||
factory.Register(DriverName, &inMemoryDriverFactory{})
|
factory.Register(DriverName, &inMemoryDriverFactory{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the factory.StorageDriverFactory interface
|
// inMemoryDriverFacotry implements the factory.StorageDriverFactory interface
|
||||||
type inMemoryDriverFactory struct{}
|
type inMemoryDriverFactory struct{}
|
||||||
|
|
||||||
func (factory *inMemoryDriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
|
func (factory *inMemoryDriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
|
||||||
return New(), nil
|
return New(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InMemory Storage Driver backed by a map
|
// InMemoryDriver is a storagedriver.StorageDriver implementation backed by a local map
|
||||||
// Intended solely for example and testing purposes
|
// Intended solely for example and testing purposes
|
||||||
type InMemoryDriver struct {
|
type InMemoryDriver struct {
|
||||||
storage map[string][]byte
|
storage map[string][]byte
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new InMemoryDriver
|
// New constructs a new InMemoryDriver
|
||||||
func New() *InMemoryDriver {
|
func New() *InMemoryDriver {
|
||||||
return &InMemoryDriver{storage: make(map[string][]byte)}
|
return &InMemoryDriver{storage: make(map[string][]byte)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implement the storagedriver.StorageDriver interface
|
||||||
|
|
||||||
func (d *InMemoryDriver) GetContent(path string) ([]byte, error) {
|
func (d *InMemoryDriver) GetContent(path string) ([]byte, error) {
|
||||||
d.mutex.RLock()
|
d.mutex.RLock()
|
||||||
defer d.mutex.RUnlock()
|
defer d.mutex.RUnlock()
|
||||||
|
|
|
@ -15,7 +15,8 @@ import (
|
||||||
"github.com/docker/libchan/spdy"
|
"github.com/docker/libchan/spdy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Storage Driver implementation using a managed child process communicating over IPC
|
// StorageDriverClient is a storagedriver.StorageDriver implementation using a managed child process
|
||||||
|
// communicating over IPC using libchan with a unix domain socket
|
||||||
type StorageDriverClient struct {
|
type StorageDriverClient struct {
|
||||||
subprocess *exec.Cmd
|
subprocess *exec.Cmd
|
||||||
socket *os.File
|
socket *os.File
|
||||||
|
@ -23,8 +24,9 @@ type StorageDriverClient struct {
|
||||||
sender libchan.Sender
|
sender libchan.Sender
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new out-of-process storage driver using the driver name and configuration parameters
|
// NewDriverClient constructs a new out-of-process storage driver using the driver name and
|
||||||
// Must call Start() on this driver client before remote method calls can be made
|
// configuration parameters
|
||||||
|
// A user must call Start on this driver client before remote method calls can be made
|
||||||
//
|
//
|
||||||
// Looks for drivers in the following locations in order:
|
// Looks for drivers in the following locations in order:
|
||||||
// - Storage drivers directory (to be determined, yet not implemented)
|
// - Storage drivers directory (to be determined, yet not implemented)
|
||||||
|
@ -54,7 +56,8 @@ func NewDriverClient(name string, parameters map[string]string) (*StorageDriverC
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts the designated child process storage driver and binds a socket to this process for IPC
|
// Start starts the designated child process storage driver and binds a socket to this process for
|
||||||
|
// IPC method calls
|
||||||
func (driver *StorageDriverClient) Start() error {
|
func (driver *StorageDriverClient) Start() error {
|
||||||
fileDescriptors, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
|
fileDescriptors, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -102,8 +105,8 @@ func (driver *StorageDriverClient) Start() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stops the child process storage driver
|
// Stop stops the child process storage driver
|
||||||
// storagedriver.StorageDriver methods called after Stop() will fail
|
// storagedriver.StorageDriver methods called after Stop will fail
|
||||||
func (driver *StorageDriverClient) Stop() error {
|
func (driver *StorageDriverClient) Stop() error {
|
||||||
closeSenderErr := driver.sender.Close()
|
closeSenderErr := driver.sender.Close()
|
||||||
closeTransportErr := driver.transport.Close()
|
closeTransportErr := driver.transport.Close()
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/docker/libchan"
|
"github.com/docker/libchan"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines a remote method call request
|
// Request defines a remote method call request
|
||||||
// A return value struct is to be sent over the ResponseChannel
|
// A return value struct is to be sent over the ResponseChannel
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Type string
|
Type string
|
||||||
|
@ -18,8 +18,9 @@ type Request struct {
|
||||||
ResponseChannel libchan.Sender
|
ResponseChannel libchan.Sender
|
||||||
}
|
}
|
||||||
|
|
||||||
// A simple wrapper around an io.ReadCloser that implements the io.ReadWriteCloser interface
|
// noWriteReadWriteCloser is a simple wrapper around an io.ReadCloser that implements the
|
||||||
// Writes are disallowed and will return an error if ever called
|
// io.ReadWriteCloser interface
|
||||||
|
// Calls to Write are disallowed and will return an error
|
||||||
type noWriteReadWriteCloser struct {
|
type noWriteReadWriteCloser struct {
|
||||||
io.ReadCloser
|
io.ReadCloser
|
||||||
}
|
}
|
||||||
|
@ -28,7 +29,7 @@ func (r noWriteReadWriteCloser) Write(p []byte) (n int, err error) {
|
||||||
return 0, errors.New("Write unsupported")
|
return 0, errors.New("Write unsupported")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps an io.Reader as an io.ReadWriteCloser with a nop Close and unsupported Write method
|
// WrapReader wraps an io.Reader as an io.ReadWriteCloser with a nop Close and unsupported Write
|
||||||
// Has no effect when an io.ReadWriteCloser is passed in
|
// Has no effect when an io.ReadWriteCloser is passed in
|
||||||
func WrapReader(reader io.Reader) io.ReadWriteCloser {
|
func WrapReader(reader io.Reader) io.ReadWriteCloser {
|
||||||
if readWriteCloser, ok := reader.(io.ReadWriteCloser); ok {
|
if readWriteCloser, ok := reader.(io.ReadWriteCloser); ok {
|
||||||
|
@ -45,7 +46,7 @@ type responseError struct {
|
||||||
Message string
|
Message string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps an error in a serializable struct containing the error's type and message
|
// ResponseError wraps an error in a serializable struct containing the error's type and message
|
||||||
func ResponseError(err error) *responseError {
|
func ResponseError(err error) *responseError {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -62,35 +63,35 @@ func (err *responseError) Error() string {
|
||||||
|
|
||||||
// IPC method call response object definitions
|
// IPC method call response object definitions
|
||||||
|
|
||||||
// Response for a ReadStream request
|
// ReadStreamResponse is a response for a ReadStream request
|
||||||
type ReadStreamResponse struct {
|
type ReadStreamResponse struct {
|
||||||
Reader io.ReadWriteCloser
|
Reader io.ReadWriteCloser
|
||||||
Error *responseError
|
Error *responseError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response for a WriteStream request
|
// WriteStreamResponse is a response for a WriteStream request
|
||||||
type WriteStreamResponse struct {
|
type WriteStreamResponse struct {
|
||||||
Error *responseError
|
Error *responseError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response for a ResumeWritePosition request
|
// ResumeWritePositionResponse is a response for a ResumeWritePosition request
|
||||||
type ResumeWritePositionResponse struct {
|
type ResumeWritePositionResponse struct {
|
||||||
Position uint64
|
Position uint64
|
||||||
Error *responseError
|
Error *responseError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response for a List request
|
// ListResponse is a response for a List request
|
||||||
type ListResponse struct {
|
type ListResponse struct {
|
||||||
Keys []string
|
Keys []string
|
||||||
Error *responseError
|
Error *responseError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response for a Move request
|
// MoveResponse is a response for a Move request
|
||||||
type MoveResponse struct {
|
type MoveResponse struct {
|
||||||
Error *responseError
|
Error *responseError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Response for a Delete request
|
// DeleteResponse is a response for a Delete request
|
||||||
type DeleteResponse struct {
|
type DeleteResponse struct {
|
||||||
Error *responseError
|
Error *responseError
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,13 @@ import (
|
||||||
"github.com/docker/libchan/spdy"
|
"github.com/docker/libchan/spdy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Construct a new IPC server handling requests for the given storagedriver.StorageDriver
|
// StorageDriverServer runs a new IPC server handling requests for the given
|
||||||
// This explicitly uses file descriptor 3 for IPC communication, as storage drivers are spawned in client.go
|
// storagedriver.StorageDriver
|
||||||
|
// This explicitly uses file descriptor 3 for IPC communication, as storage drivers are spawned in
|
||||||
|
// client.go
|
||||||
//
|
//
|
||||||
// To create a new out-of-process driver, create a main package which calls StorageDriverServer with a storagedriver.StorageDriver
|
// To create a new out-of-process driver, create a main package which calls StorageDriverServer with
|
||||||
|
// a storagedriver.StorageDriver
|
||||||
func StorageDriverServer(driver storagedriver.StorageDriver) error {
|
func StorageDriverServer(driver storagedriver.StorageDriver) error {
|
||||||
childSocket := os.NewFile(3, "childSocket")
|
childSocket := os.NewFile(3, "childSocket")
|
||||||
defer childSocket.Close()
|
defer childSocket.Close()
|
||||||
|
@ -39,9 +42,10 @@ func StorageDriverServer(driver storagedriver.StorageDriver) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receives new storagedriver.StorageDriver method requests and creates a new goroutine to handle each request
|
// receive receives new storagedriver.StorageDriver method requests and creates a new goroutine to
|
||||||
//
|
// handle each request
|
||||||
// Requests are expected to be of type ipc.Request as the parameters are unknown until the request type is deserialized
|
// Requests are expected to be of type ipc.Request as the parameters are unknown until the request
|
||||||
|
// type is deserialized
|
||||||
func receive(driver storagedriver.StorageDriver, receiver libchan.Receiver) {
|
func receive(driver storagedriver.StorageDriver, receiver libchan.Receiver) {
|
||||||
for {
|
for {
|
||||||
var request Request
|
var request Request
|
||||||
|
@ -53,7 +57,7 @@ func receive(driver storagedriver.StorageDriver, receiver libchan.Receiver) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles storagedriver.StorageDriver method requests as defined in client.go
|
// handleRequest handles storagedriver.StorageDriver method requests as defined in client.go
|
||||||
// Responds to requests using the Request.ResponseChannel
|
// Responds to requests using the Request.ResponseChannel
|
||||||
func handleRequest(driver storagedriver.StorageDriver, request Request) {
|
func handleRequest(driver storagedriver.StorageDriver, request Request) {
|
||||||
switch request.Type {
|
switch request.Type {
|
||||||
|
|
|
@ -15,24 +15,25 @@ import (
|
||||||
|
|
||||||
const DriverName = "s3"
|
const DriverName = "s3"
|
||||||
|
|
||||||
// Chunks need to be at least 5MB to store with a multipart upload on S3
|
// minChunkSize defines the minimum multipart upload chunk size
|
||||||
|
// S3 API requires multipart upload chunks to be at least 5MB
|
||||||
const minChunkSize = uint64(5 * 1024 * 1024)
|
const minChunkSize = uint64(5 * 1024 * 1024)
|
||||||
|
|
||||||
// The largest amount of parts you can request from S3
|
// listPartsMax is the largest amount of parts you can request from S3
|
||||||
const listPartsMax = 1000
|
const listPartsMax = 1000
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
factory.Register(DriverName, &s3DriverFactory{})
|
factory.Register(DriverName, &s3DriverFactory{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the factory.StorageDriverFactory interface
|
// s3DriverFactory implements the factory.StorageDriverFactory interface
|
||||||
type s3DriverFactory struct{}
|
type s3DriverFactory struct{}
|
||||||
|
|
||||||
func (factory *s3DriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
|
func (factory *s3DriverFactory) Create(parameters map[string]string) (storagedriver.StorageDriver, error) {
|
||||||
return FromParameters(parameters)
|
return FromParameters(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Storage Driver backed by Amazon S3
|
// S3Driver is a storagedriver.StorageDriver implementation backed by Amazon S3
|
||||||
// Objects are stored at absolute keys in the provided bucket
|
// Objects are stored at absolute keys in the provided bucket
|
||||||
type S3Driver struct {
|
type S3Driver struct {
|
||||||
S3 *s3.S3
|
S3 *s3.S3
|
||||||
|
@ -40,7 +41,7 @@ type S3Driver struct {
|
||||||
Encrypt bool
|
Encrypt bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new S3Driver with a given parameters map
|
// FromParameters constructs a new S3Driver with a given parameters map
|
||||||
// Required parameters:
|
// Required parameters:
|
||||||
// - accesskey
|
// - accesskey
|
||||||
// - secretkey
|
// - secretkey
|
||||||
|
@ -84,7 +85,8 @@ func FromParameters(parameters map[string]string) (*S3Driver, error) {
|
||||||
return New(accessKey, secretKey, region, encryptBool, bucket)
|
return New(accessKey, secretKey, region, encryptBool, bucket)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new S3Driver with the given AWS credentials, region, encryption flag, and bucketName
|
// New constructs a new S3Driver with the given AWS credentials, region, encryption flag, and
|
||||||
|
// bucketName
|
||||||
func New(accessKey string, secretKey string, region aws.Region, encrypt bool, bucketName string) (*S3Driver, error) {
|
func New(accessKey string, secretKey string, region aws.Region, encrypt bool, bucketName string) (*S3Driver, error) {
|
||||||
auth := aws.Auth{AccessKey: accessKey, SecretKey: secretKey}
|
auth := aws.Auth{AccessKey: accessKey, SecretKey: secretKey}
|
||||||
s3obj := s3.New(auth, region)
|
s3obj := s3.New(auth, region)
|
||||||
|
@ -100,6 +102,8 @@ func New(accessKey string, secretKey string, region aws.Region, encrypt bool, bu
|
||||||
return &S3Driver{s3obj, bucket, encrypt}, nil
|
return &S3Driver{s3obj, bucket, encrypt}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implement the storagedriver.StorageDriver interface
|
||||||
|
|
||||||
func (d *S3Driver) GetContent(path string) ([]byte, error) {
|
func (d *S3Driver) GetContent(path string) ([]byte, error) {
|
||||||
return d.Bucket.Get(path)
|
return d.Bucket.Get(path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,41 +5,45 @@ import (
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defines methods that a Storage Driver must implement for a filesystem-like key/value object storage
|
// StorageDriver defines methods that a Storage Driver must implement for a filesystem-like
|
||||||
|
// key/value object storage
|
||||||
type StorageDriver interface {
|
type StorageDriver interface {
|
||||||
// Retrieve the content stored at "path" as a []byte
|
// GetContent retrieves the content stored at "path" as a []byte
|
||||||
// Should primarily be used for small objects
|
// Should primarily be used for small objects
|
||||||
GetContent(path string) ([]byte, error)
|
GetContent(path string) ([]byte, error)
|
||||||
|
|
||||||
// Store the []byte content at a location designated by "path"
|
// PutContent stores the []byte content at a location designated by "path"
|
||||||
// Should primarily be used for small objects
|
// Should primarily be used for small objects
|
||||||
PutContent(path string, content []byte) error
|
PutContent(path string, content []byte) error
|
||||||
|
|
||||||
// Retrieve an io.ReadCloser for the content stored at "path" with a given byte offset
|
// ReadStream retrieves an io.ReadCloser for the content stored at "path" with a given byte
|
||||||
|
// offset
|
||||||
// May be used to resume reading a stream by providing a nonzero offset
|
// May be used to resume reading a stream by providing a nonzero offset
|
||||||
ReadStream(path string, offset uint64) (io.ReadCloser, error)
|
ReadStream(path string, offset uint64) (io.ReadCloser, error)
|
||||||
|
|
||||||
// Store the contents of the provided io.ReadCloser at a location designated by "path"
|
// WriteStream stores the contents of the provided io.ReadCloser at a location designated by
|
||||||
|
// the given path
|
||||||
// The driver will know it has received the full contents when it has read "size" bytes
|
// The driver will know it has received the full contents when it has read "size" bytes
|
||||||
// May be used to resume writing a stream by providing a nonzero offset
|
// May be used to resume writing a stream by providing a nonzero offset
|
||||||
// The offset must be no larger than the number of bytes already written to this path
|
// The offset must be no larger than the number of bytes already written to this path
|
||||||
WriteStream(path string, offset, size uint64, readCloser io.ReadCloser) error
|
WriteStream(path string, offset, size uint64, readCloser io.ReadCloser) error
|
||||||
|
|
||||||
// Retrieve the byte offset at which it is safe to continue writing at "path"
|
// ResumeWritePosition retrieves the byte offset at which it is safe to continue writing at the
|
||||||
|
// given path
|
||||||
ResumeWritePosition(path string) (uint64, error)
|
ResumeWritePosition(path string) (uint64, error)
|
||||||
|
|
||||||
// Recursively lists the objects stored at a subpath of the given prefix
|
// List recursively lists the objects stored at a subpath of the given prefix
|
||||||
List(prefix string) ([]string, error)
|
List(prefix string) ([]string, error)
|
||||||
|
|
||||||
// Moves an object stored at sourcePath to destPath, removing the original object
|
// Move moves an object stored at sourcePath to destPath, removing the original object
|
||||||
// Note: This may be no more efficient than a copy followed by a delete for many implementations
|
// Note: This may be no more efficient than a copy followed by a delete for many implementations
|
||||||
Move(sourcePath string, destPath string) error
|
Move(sourcePath string, destPath string) error
|
||||||
|
|
||||||
// Recursively deletes all objects stored at "path" and its subpaths
|
// Delete recursively deletes all objects stored at "path" and its subpaths
|
||||||
Delete(path string) error
|
Delete(path string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returned when operating on a nonexistent path
|
// PathNotFoundError is returned when operating on a nonexistent path
|
||||||
type PathNotFoundError struct {
|
type PathNotFoundError struct {
|
||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
@ -48,7 +52,7 @@ func (err PathNotFoundError) Error() string {
|
||||||
return fmt.Sprintf("Path not found: %s", err.Path)
|
return fmt.Sprintf("Path not found: %s", err.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error returned when attempting to read or write from an invalid offset
|
// InvalidOffsetError is returned when attempting to read or write from an invalid offset
|
||||||
type InvalidOffsetError struct {
|
type InvalidOffsetError struct {
|
||||||
Path string
|
Path string
|
||||||
Offset uint64
|
Offset uint64
|
||||||
|
|
|
@ -17,9 +17,7 @@ import (
|
||||||
// Hook up gocheck into the "go test" runner
|
// Hook up gocheck into the "go test" runner
|
||||||
func Test(t *testing.T) { TestingT(t) }
|
func Test(t *testing.T) { TestingT(t) }
|
||||||
|
|
||||||
// Registers an in-process storage driver test suite with the go test runner
|
// RegisterInProcessSuite registers an in-process storage driver test suite with the go test runner
|
||||||
//
|
|
||||||
// If skipCheck returns a non-empty skip reason, the suite is skipped with the given reason
|
|
||||||
func RegisterInProcessSuite(driverConstructor DriverConstructor, skipCheck SkipCheck) {
|
func RegisterInProcessSuite(driverConstructor DriverConstructor, skipCheck SkipCheck) {
|
||||||
Suite(&DriverSuite{
|
Suite(&DriverSuite{
|
||||||
Constructor: driverConstructor,
|
Constructor: driverConstructor,
|
||||||
|
@ -27,9 +25,8 @@ func RegisterInProcessSuite(driverConstructor DriverConstructor, skipCheck SkipC
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a storage driver test suite which runs the named driver as a child process with the given parameters
|
// RegisterIPCSuite registers a storage driver test suite which runs the named driver as a child
|
||||||
//
|
// process with the given parameters
|
||||||
// If skipCheck returns a non-empty skip reason, the suite is skipped with the given reason
|
|
||||||
func RegisterIPCSuite(driverName string, ipcParams map[string]string, skipCheck SkipCheck) {
|
func RegisterIPCSuite(driverName string, ipcParams map[string]string, skipCheck SkipCheck) {
|
||||||
suite := &DriverSuite{
|
suite := &DriverSuite{
|
||||||
Constructor: func() (storagedriver.StorageDriver, error) {
|
Constructor: func() (storagedriver.StorageDriver, error) {
|
||||||
|
@ -56,13 +53,21 @@ func RegisterIPCSuite(driverName string, ipcParams map[string]string, skipCheck
|
||||||
Suite(suite)
|
Suite(suite)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkipCheck is a function used to determine if a test suite should be skipped
|
||||||
|
// If a SkipCheck returns a non-empty skip reason, the suite is skipped with the given reason
|
||||||
type SkipCheck func() (reason string)
|
type SkipCheck func() (reason string)
|
||||||
|
|
||||||
var NeverSkip = func() string { return "" }
|
// NeverSkip is a default SkipCheck which never skips the suite
|
||||||
|
var NeverSkip SkipCheck = func() string { return "" }
|
||||||
|
|
||||||
|
// DriverConstructor is a function which returns a new storagedriver.StorageDriver
|
||||||
type DriverConstructor func() (storagedriver.StorageDriver, error)
|
type DriverConstructor func() (storagedriver.StorageDriver, error)
|
||||||
|
|
||||||
|
// DriverTeardown is a function which cleans up a suite's storagedriver.StorageDriver
|
||||||
type DriverTeardown func() error
|
type DriverTeardown func() error
|
||||||
|
|
||||||
|
// DriverSuite is a gocheck test suite designed to test a storagedriver.StorageDriver
|
||||||
|
// The intended way to create a DriverSuite is with RegisterInProcessSuite or RegisterIPCSuite
|
||||||
type DriverSuite struct {
|
type DriverSuite struct {
|
||||||
Constructor DriverConstructor
|
Constructor DriverConstructor
|
||||||
Teardown DriverTeardown
|
Teardown DriverTeardown
|
||||||
|
@ -70,11 +75,6 @@ type DriverSuite struct {
|
||||||
storagedriver.StorageDriver
|
storagedriver.StorageDriver
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestDriverConfig struct {
|
|
||||||
name string
|
|
||||||
params map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *DriverSuite) SetUpSuite(c *C) {
|
func (suite *DriverSuite) SetUpSuite(c *C) {
|
||||||
if reason := suite.SkipCheck(); reason != "" {
|
if reason := suite.SkipCheck(); reason != "" {
|
||||||
c.Skip(reason)
|
c.Skip(reason)
|
||||||
|
|
Loading…
Reference in a new issue