|
15 | 15 | package internal |
16 | 16 |
|
17 | 17 | import ( |
| 18 | + "bytes" |
| 19 | + "io" |
| 20 | + |
18 | 21 | . "github.com/StatCan/goofys/api/common" |
19 | 22 |
|
20 | 23 | "fmt" |
@@ -638,7 +641,64 @@ func (s *S3Backend) copyObjectMultipart(size int64, from string, to string, mpuI |
638 | 641 | return |
639 | 642 | } |
640 | 643 |
|
| 644 | +// CopyBlobV2 that does not use CopyObject since netapp does not support it |
| 645 | +// https://docs.netapp.com/us-en/ontap/s3-multiprotocol/index.html#s3-actions-and-functionality-not-currently-supported-by-s3-nas-buckets |
| 646 | + |
| 647 | +func (s *S3Backend) CopyBlobV2(param *CopyBlobInput) (*CopyBlobOutput, error) { |
| 648 | + s3Log.Debug("Entering CopyBlobV2. This is a temporary measure until CopyObject is supported by netapp s3 nas buckets") |
| 649 | + if param.Size == nil || param.ETag == nil || (param.Metadata == nil || param.StorageClass == nil) { |
| 650 | + params := &HeadBlobInput{Key: param.Source} |
| 651 | + resp, err := s.HeadBlob(params) |
| 652 | + if err != nil { |
| 653 | + return nil, err |
| 654 | + } |
| 655 | + if param.Metadata == nil { |
| 656 | + param.Metadata = resp.Metadata |
| 657 | + } |
| 658 | + } |
| 659 | + |
| 660 | + // Use Get and PutBlob implementations over copy object |
| 661 | + getParams := &GetBlobInput{ |
| 662 | + Key: param.Source, |
| 663 | + } |
| 664 | + getResp, err := s.GetBlob(getParams) |
| 665 | + if err != nil { |
| 666 | + return nil, err |
| 667 | + } |
| 668 | + |
| 669 | + // Ensure we close the body when done |
| 670 | + defer getResp.Body.Close() |
| 671 | + |
| 672 | + // Read the entire content into memory...Is there a better way to do this |
| 673 | + content, err := io.ReadAll(getResp.Body) |
| 674 | + if err != nil { |
| 675 | + return nil, err |
| 676 | + } |
| 677 | + // Create a ReadSeeker from the content |
| 678 | + contentReader := bytes.NewReader(content) |
| 679 | + |
| 680 | + putParams := &PutBlobInput{ |
| 681 | + Key: param.Destination, |
| 682 | + Body: contentReader, |
| 683 | + ContentType: getResp.ContentType, |
| 684 | + Metadata: param.Metadata, // can this be getResp.Metadata over param.Metadata? |
| 685 | + //param.Metadata, |
| 686 | + // dont need size or dirblob |
| 687 | + } |
| 688 | + |
| 689 | + putResp, err := s.PutBlob(putParams) |
| 690 | + if err != nil { |
| 691 | + return nil, err |
| 692 | + } |
| 693 | + s3Log.Debug("Exiting CopyBlobV2") |
| 694 | + return &CopyBlobOutput{putResp.RequestId}, nil |
| 695 | +} |
| 696 | + |
641 | 697 | func (s *S3Backend) CopyBlob(param *CopyBlobInput) (*CopyBlobOutput, error) { |
| 698 | + // Change to use CopyBlobV2, done here because changing references to `CopyBlob` requires more change than I'd like |
| 699 | + // When CopyObject is supported we just remove CopyBlobV2 and this return statement |
| 700 | + return s.CopyBlobV2(param) |
| 701 | + |
642 | 702 | metadataDirective := s3.MetadataDirectiveCopy |
643 | 703 | if param.Metadata != nil { |
644 | 704 | metadataDirective = s3.MetadataDirectiveReplace |
|
0 commit comments