github.com/pachyderm/pachyderm@v1.13.4/src/server/pfs/s3/object.go (about)

     1  package s3
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net/http"
     7  	"strings"
     8  
     9  	"github.com/gogo/protobuf/types"
    10  	pfsServer "github.com/pachyderm/pachyderm/src/server/pfs"
    11  	"github.com/pachyderm/pachyderm/src/server/pkg/errutil"
    12  	"github.com/pachyderm/s2"
    13  )
    14  
    15  func (c *controller) GetObject(r *http.Request, bucketName, file, version string) (*s2.GetObjectResult, error) {
    16  	c.logger.Debugf("GetObject: bucketName=%+v, file=%+v, version=%+v", bucketName, file, version)
    17  
    18  	pc, err := c.requestClient(r)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	if strings.HasSuffix(file, "/") {
    24  		return nil, invalidFilePathError(r)
    25  	}
    26  
    27  	bucket, err := c.driver.bucket(pc, r, bucketName)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	bucketCaps, err := c.driver.bucketCapabilities(pc, r, bucket)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	if !bucketCaps.readable {
    36  		return nil, s2.NoSuchKeyError(r)
    37  	}
    38  
    39  	if bucketCaps.historicVersions && version != "" {
    40  		commitInfo, err := pc.InspectCommit(bucket.Repo, version)
    41  		if err != nil {
    42  			return nil, maybeNotFoundError(r, err)
    43  		}
    44  		if commitInfo.Branch.Name != bucket.Commit {
    45  			return nil, s2.NoSuchVersionError(r)
    46  		}
    47  		bucket.Commit = commitInfo.Commit.ID
    48  	}
    49  
    50  	fileInfo, err := pc.InspectFile(bucket.Repo, bucket.Commit, file)
    51  	if err != nil {
    52  		return nil, maybeNotFoundError(r, err)
    53  	}
    54  
    55  	modTime, err := types.TimestampFromProto(fileInfo.Committed)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	content, err := pc.GetFileReadSeeker(bucket.Repo, bucket.Commit, file)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	result := s2.GetObjectResult{
    66  		ModTime:      modTime,
    67  		Content:      content,
    68  		ETag:         fmt.Sprintf("%x", fileInfo.Hash),
    69  		Version:      bucket.Commit,
    70  		DeleteMarker: false,
    71  	}
    72  
    73  	return &result, nil
    74  }
    75  
    76  func (c *controller) CopyObject(r *http.Request, srcBucketName, srcFile string, srcObj *s2.GetObjectResult, destBucketName, destFile string) (string, error) {
    77  	c.logger.Tracef("CopyObject: srcBucketName=%+v, srcFile=%+v, srcObj=%+v, destBucketName=%+v, destFile=%+v", srcBucketName, srcFile, srcObj, destBucketName, destFile)
    78  
    79  	pc, err := c.requestClient(r)
    80  	if err != nil {
    81  		return "", err
    82  	}
    83  
    84  	if strings.HasSuffix(destFile, "/") {
    85  		return "", invalidFilePathError(r)
    86  	}
    87  
    88  	srcBucket, err := c.driver.bucket(pc, r, srcBucketName)
    89  	if err != nil {
    90  		return "", err
    91  	}
    92  	// srcBucket capabilities were already verified, since s2 will call
    93  	// `GetObject` under the hood before calling `CopyObject`
    94  
    95  	destBucket, err := c.driver.bucket(pc, r, destBucketName)
    96  	if err != nil {
    97  		return "", err
    98  	}
    99  	destBucketCaps, err := c.driver.bucketCapabilities(pc, r, destBucket)
   100  	if err != nil {
   101  		return "", err
   102  	}
   103  	if !destBucketCaps.writable {
   104  		return "", s2.NotImplementedError(r)
   105  	}
   106  
   107  	if err = pc.CopyFile(srcBucket.Repo, srcBucket.Commit, srcFile, destBucket.Repo, destBucket.Commit, destFile, true); err != nil {
   108  		if errutil.IsWriteToOutputBranchError(err) {
   109  			return "", writeToOutputBranchError(r)
   110  		} else if errutil.IsNotADirectoryError(err) {
   111  			return "", invalidFileParentError(r)
   112  		} else if errutil.IsInvalidPathError(err) {
   113  			return "", invalidFilePathError(r)
   114  		}
   115  		return "", err
   116  	}
   117  
   118  	fileInfo, err := pc.InspectFile(destBucket.Repo, destBucket.Commit, destFile)
   119  	if err != nil && !pfsServer.IsOutputCommitNotFinishedErr(err) {
   120  		return "", err
   121  	}
   122  	var version string
   123  	if fileInfo != nil {
   124  		version = fileInfo.File.Commit.ID
   125  	}
   126  
   127  	return version, nil
   128  }
   129  
   130  func (c *controller) PutObject(r *http.Request, bucketName, file string, reader io.Reader) (*s2.PutObjectResult, error) {
   131  	c.logger.Debugf("PutObject: bucketName=%+v, file=%+v", bucketName, file)
   132  
   133  	pc, err := c.requestClient(r)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  
   138  	if strings.HasSuffix(file, "/") {
   139  		return nil, invalidFilePathError(r)
   140  	}
   141  
   142  	bucket, err := c.driver.bucket(pc, r, bucketName)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	bucketCaps, err := c.driver.bucketCapabilities(pc, r, bucket)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	if !bucketCaps.writable {
   151  		return nil, s2.NotImplementedError(r)
   152  	}
   153  
   154  	_, err = pc.PutFileOverwrite(bucket.Repo, bucket.Commit, file, reader, 0)
   155  	if err != nil {
   156  		if errutil.IsWriteToOutputBranchError(err) {
   157  			return nil, writeToOutputBranchError(r)
   158  		} else if errutil.IsNotADirectoryError(err) {
   159  			return nil, invalidFileParentError(r)
   160  		} else if errutil.IsInvalidPathError(err) {
   161  			return nil, invalidFilePathError(r)
   162  		}
   163  		return nil, err
   164  	}
   165  
   166  	fileInfo, err := pc.InspectFile(bucket.Repo, bucket.Commit, file)
   167  	if err != nil && !pfsServer.IsOutputCommitNotFinishedErr(err) {
   168  		return nil, err
   169  	}
   170  
   171  	result := s2.PutObjectResult{}
   172  	if fileInfo != nil {
   173  		result.ETag = fmt.Sprintf("%x", fileInfo.Hash)
   174  		result.Version = fileInfo.File.Commit.ID
   175  	}
   176  
   177  	return &result, nil
   178  }
   179  
   180  func (c *controller) DeleteObject(r *http.Request, bucketName, file, version string) (*s2.DeleteObjectResult, error) {
   181  	c.logger.Debugf("DeleteObject: bucketName=%+v, file=%+v, version=%+v", bucketName, file, version)
   182  
   183  	pc, err := c.requestClient(r)
   184  	if err != nil {
   185  		return nil, err
   186  	}
   187  
   188  	if strings.HasSuffix(file, "/") {
   189  		return nil, invalidFilePathError(r)
   190  	}
   191  	if version != "" {
   192  		return nil, s2.NotImplementedError(r)
   193  	}
   194  
   195  	bucket, err := c.driver.bucket(pc, r, bucketName)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  	bucketCaps, err := c.driver.bucketCapabilities(pc, r, bucket)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  	if !bucketCaps.writable {
   204  		return nil, s2.NotImplementedError(r)
   205  	}
   206  
   207  	if err = pc.DeleteFile(bucket.Repo, bucket.Commit, file); err != nil {
   208  		if errutil.IsWriteToOutputBranchError(err) {
   209  			return nil, writeToOutputBranchError(r)
   210  		}
   211  		return nil, maybeNotFoundError(r, err)
   212  	}
   213  
   214  	result := s2.DeleteObjectResult{
   215  		Version:      "",
   216  		DeleteMarker: false,
   217  	}
   218  
   219  	return &result, nil
   220  }