@@ -54,6 +54,9 @@ const (
5454 metadataKeyBC = "name"
5555 signOperation = "sign"
5656 bulkGetOperation = "bulkGet"
57+ copyOperation = "copy"
58+ renameOperation = "rename"
59+ moveOperation = "move"
5760)
5861
5962// GCPStorage allows saving data to GCP bucket storage.
@@ -87,6 +90,7 @@ type listPayload struct {
8790 MaxResults int32 `json:"maxResults"`
8891 Delimiter string `json:"delimiter"`
8992}
93+
9094type signResponse struct {
9195 SignURL string `json:"signURL"`
9296}
@@ -142,6 +146,9 @@ func (g *GCPStorage) Operations() []bindings.OperationKind {
142146 bindings .ListOperation ,
143147 signOperation ,
144148 bulkGetOperation ,
149+ copyOperation ,
150+ renameOperation ,
151+ moveOperation ,
145152 }
146153}
147154
@@ -161,6 +168,12 @@ func (g *GCPStorage) Invoke(ctx context.Context, req *bindings.InvokeRequest) (*
161168 return g .sign (ctx , req )
162169 case bulkGetOperation :
163170 return g .bulkGet (ctx , req )
171+ case copyOperation :
172+ return g .copy (ctx , req )
173+ case renameOperation :
174+ return g .rename (ctx , req )
175+ case moveOperation :
176+ return g .move (ctx , req )
164177 default :
165178 return nil , fmt .Errorf ("unsupported operation %s" , req .Operation )
166179 }
@@ -498,3 +511,110 @@ func (g *GCPStorage) bulkGet(ctx context.Context, req *bindings.InvokeRequest) (
498511 Data : jsonResponse ,
499512 }, nil
500513}
514+
515+ type movePayload struct {
516+ DestinationBucket string `json:"destinationBucket"`
517+ }
518+
519+ func (g * GCPStorage ) move (ctx context.Context , req * bindings.InvokeRequest ) (* bindings.InvokeResponse , error ) {
520+ var key string
521+ if val , ok := req .Metadata [metadataKey ]; ok && val != "" {
522+ key = val
523+ } else {
524+ return nil , errors .New ("gcp bucket binding error: can't read key value" )
525+ }
526+
527+ var payload movePayload
528+ err := json .Unmarshal (req .Data , & payload )
529+ if err != nil {
530+ return nil , errors .New ("gcp bucket binding error: invalid move payload" )
531+ }
532+
533+ if payload .DestinationBucket == "" {
534+ return nil , errors .New ("gcp bucket binding error: required 'destinationBucket' missing" )
535+ }
536+
537+ src := g .client .Bucket (g .metadata .Bucket ).Object (key )
538+ dst := g .client .Bucket (payload .DestinationBucket ).Object (key )
539+ if _ , err := dst .CopierFrom (src ).Run (ctx ); err != nil {
540+ return nil , fmt .Errorf ("gcp bucket binding error while copying object: %w" , err )
541+ }
542+
543+ if err := src .Delete (ctx ); err != nil {
544+ return nil , fmt .Errorf ("gcp bucket binding error while deleting object: %w" , err )
545+ }
546+
547+ return & bindings.InvokeResponse {
548+ Data : []byte (fmt .Sprintf ("object %s moved to %s" , key , payload .DestinationBucket )),
549+ }, nil
550+ }
551+
552+ type renamePayload struct {
553+ NewName string `json:"newName"`
554+ }
555+
556+ func (g * GCPStorage ) rename (ctx context.Context , req * bindings.InvokeRequest ) (* bindings.InvokeResponse , error ) {
557+ var key string
558+ if val , ok := req .Metadata [metadataKey ]; ok && val != "" {
559+ key = val
560+ } else {
561+ return nil , errors .New ("gcp bucket binding error: can't read key value" )
562+ }
563+
564+ var payload renamePayload
565+ err := json .Unmarshal (req .Data , & payload )
566+ if err != nil {
567+ return nil , errors .New ("gcp bucket binding error: invalid rename payload" )
568+ }
569+
570+ if payload .NewName == "" {
571+ return nil , errors .New ("gcp bucket binding error: required 'newName' missing" )
572+ }
573+
574+ src := g .client .Bucket (g .metadata .Bucket ).Object (key )
575+ dst := g .client .Bucket (g .metadata .Bucket ).Object (payload .NewName )
576+ if _ , err := dst .CopierFrom (src ).Run (ctx ); err != nil {
577+ return nil , fmt .Errorf ("gcp bucket binding error while copying object: %w" , err )
578+ }
579+
580+ if err := src .Delete (ctx ); err != nil {
581+ return nil , fmt .Errorf ("gcp bucket binding error while deleting object: %w" , err )
582+ }
583+
584+ return & bindings.InvokeResponse {
585+ Data : []byte (fmt .Sprintf ("object %s renamed to %s" , key , payload .NewName )),
586+ }, nil
587+ }
588+
589+ type copyPayload struct {
590+ DestinationBucket string `json:"destinationBucket"`
591+ }
592+
593+ func (g * GCPStorage ) copy (ctx context.Context , req * bindings.InvokeRequest ) (* bindings.InvokeResponse , error ) {
594+ var key string
595+ if val , ok := req .Metadata [metadataKey ]; ok && val != "" {
596+ key = val
597+ } else {
598+ return nil , errors .New ("gcp bucket binding error: can't read key value" )
599+ }
600+
601+ var payload copyPayload
602+ err := json .Unmarshal (req .Data , & payload )
603+ if err != nil {
604+ return nil , errors .New ("gcp bucket binding error: invalid copy payload" )
605+ }
606+
607+ if payload .DestinationBucket == "" {
608+ return nil , errors .New ("gcp bucket binding error: required 'destinationBucket' missing" )
609+ }
610+
611+ src := g .client .Bucket (g .metadata .Bucket ).Object (key )
612+ dst := g .client .Bucket (payload .DestinationBucket ).Object (key )
613+ if _ , err := dst .CopierFrom (src ).Run (ctx ); err != nil {
614+ return nil , fmt .Errorf ("gcp bucket binding error while copying object: %w" , err )
615+ }
616+
617+ return & bindings.InvokeResponse {
618+ Data : []byte (fmt .Sprintf ("object %s copied to %s" , key , payload .DestinationBucket )),
619+ }, nil
620+ }
0 commit comments