Skip to content

Commit

Permalink
modified: .gitignore
Browse files Browse the repository at this point in the history
        modified:   README.md
        new file:   example/generateSignedUrl/main.go
        new file:   example/upload/go_gcs.png
        new file:   example/upload/main.go
        new file:   example/upload/tes.txt
        new file:   gcs.go
        new file:   go.mod
        new file:   go.sum
  • Loading branch information
michaelwp committed Jun 23, 2024
1 parent 0a9bfa2 commit fb9af05
Show file tree
Hide file tree
Showing 9 changed files with 561 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@
# Go workspace file
go.work
go.work.sum

cred
.idea
.env
106 changes: 104 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,104 @@
# go-gcp-wrapper
A Google Cloud Storage wrapper, to simplify go application to interact with Google Cloud Storage
# go-gcs-wrapper
go-gcs-wrapper is a library that makes it easy for Go applications to interact with Google Cloud Storage.
It provides simple functions for tasks like uploading files and generating signed URLs for secure access.
This wrapper handles the complex details of the Google Cloud Storage API, allowing developers to use storage features
with less code and effort.

### installation
```shell
go get -d github.com/michaelwp/go-gcs-wrapper
```

### basic of use
- Upload file
```go
package main

import (
"context"
"github.com/joho/godotenv"
gogcswrapper "github.com/michaelwp/go-gcs-wrapper"
"log"
"os"
)

func init() {
err := godotenv.Load(".env")
if err != nil {
log.Fatal("Error loading .env file", err)
}
}

func main() {
projectId := os.Getenv("GOOGLE_APPLICATION_PROJECT_ID")
bucket := os.Getenv("GOOGLE_APPLICATION_BUCKET")
object := "go_gcs.png"
uploadObjPath := "upload_tes"
localObjPath := "."

ctx := context.Background()
gcs := gogcswrapper.NewGCS(ctx, projectId)

params := &gogcswrapper.UploadParams{
BucketAndObject: &gogcswrapper.BucketAndObject{
Bucket: bucket,
Object: object,
},
LocalObjPath: localObjPath,
UploadObjPath: uploadObjPath,
}

err := gcs.Upload(ctx, params)
if err != nil {
log.Fatal("error uploading file", err)
}
}
```

- Generate signed Url
```go
package main

import (
"context"
"fmt"
"github.com/joho/godotenv"
gogcswrapper "github.com/michaelwp/go-gcs-wrapper"
"log"
"os"
"time"
)

func init() {
err := godotenv.Load(".env")
if err != nil {
log.Fatal("Error loading .env file", err)
}
}

func main() {
projectId := os.Getenv("GOOGLE_APPLICATION_PROJECT_ID")
bucket := os.Getenv("GOOGLE_APPLICATION_BUCKET")
object := "go_gcs.png"
uploadObjPath := "upload_tes"

ctx := context.Background()
gcs := gogcswrapper.NewGCS(ctx, projectId)

params := &gogcswrapper.GenerateSignedURLParams{
BucketAndObject: &gogcswrapper.BucketAndObject{
Bucket: bucket,
Object: object,
},
UploadObjPath: uploadObjPath,
ExpirationTime: time.Now().Add(time.Minute * 10),
}

signedUrl, err := gcs.GenerateSignedURL(params)
if err != nil {
log.Fatal("error generating sign url", err)
}

fmt.Printf("Signed URL: %s\n", signedUrl)
}
```
50 changes: 50 additions & 0 deletions example/generateSignedUrl/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
author: Michael Putong @2024
This is an example on how to implement go-gcs-wrapper
to generate a Google Cloud Storage's signedUrl
visit the code repository in github.com/michaelwp/go-gcs-wrapper
*/
package main

import (
"context"
"fmt"
"github.com/joho/godotenv"
gogcswrapper "github.com/michaelwp/go-gcs-wrapper"
"log"
"os"
"time"
)

func init() {
err := godotenv.Load(".env")
if err != nil {
log.Fatal("Error loading .env file", err)
}
}

func main() {
projectId := os.Getenv("GOOGLE_APPLICATION_PROJECT_ID")
bucket := os.Getenv("GOOGLE_APPLICATION_BUCKET")
object := "go_gcs.png"
uploadObjPath := "upload_tes"

ctx := context.Background()
gcs := gogcswrapper.NewGCS(ctx, projectId)

params := &gogcswrapper.GenerateSignedURLParams{
BucketAndObject: &gogcswrapper.BucketAndObject{
Bucket: bucket,
Object: object,
},
UploadObjPath: uploadObjPath,
ExpirationTime: time.Now().Add(time.Minute * 10),
}

signedUrl, err := gcs.GenerateSignedURL(params)
if err != nil {
log.Fatal("error generating sign url", err)
}

fmt.Printf("Signed URL: %s\n", signedUrl)
}
Binary file added example/upload/go_gcs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions example/upload/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
author: Michael Putong @2024
This is an example on how to implement go-gcs-wrapper
to upload a file to Google Cloud Storage
visit the code repository in github.com/michaelwp/go-gcs-wrapper
*/

package main

import (
"context"
"github.com/joho/godotenv"
gogcswrapper "github.com/michaelwp/go-gcs-wrapper"
"log"
"os"
)

func init() {
err := godotenv.Load(".env")
if err != nil {
log.Fatal("Error loading .env file", err)
}
}

func main() {
projectId := os.Getenv("GOOGLE_APPLICATION_PROJECT_ID")
bucket := os.Getenv("GOOGLE_APPLICATION_BUCKET")
object := "go_gcs.png"
uploadObjPath := "upload_tes"
localObjPath := "."

ctx := context.Background()
gcs := gogcswrapper.NewGCS(ctx, projectId)

params := &gogcswrapper.UploadParams{
BucketAndObject: &gogcswrapper.BucketAndObject{
Bucket: bucket,
Object: object,
},
LocalObjPath: localObjPath,
UploadObjPath: uploadObjPath,
}

err := gcs.Upload(ctx, params)
if err != nil {
log.Fatal("error uploading file", err)
}
}
1 change: 1 addition & 0 deletions example/upload/tes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tes upload file to gcs
136 changes: 136 additions & 0 deletions gcs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
author: Michael Putong @2024
-----------------------------------------------------------------
This is a library that is wrapping the Google Cloud Storage Library
to simplify the interaction within Go application and Google Cloud Storage.
-----------------------------------------------------------------
This code is free to use, modify and distribute, although
the author is not responsible for any damage occurred in its use.
-----------------------------------------------------------------
visit the code repository in github.com/michaelwp/go-semaphore
*/

package go_gcs_wrapper

import (
"cloud.google.com/go/storage"
"context"
"fmt"
"io"
"log"
"os"
"time"
)

type Gcs interface {
Upload(ctx context.Context, params *UploadParams) error
GenerateSignedURL(params *GenerateSignedURLParams) (string, error)
}

type gcs struct {
StorageClient *storage.Client
ProjectId string
}

type BucketAndObject struct {
Bucket string
Object string
}

type UploadParams struct {
LocalObjPath string
UploadObjPath string
*BucketAndObject
}

type GenerateSignedURLParams struct {
*BucketAndObject
ExpirationTime time.Time
UploadObjPath string
}

func NewGCS(ctx context.Context, projectId string) Gcs {
client, err := storage.NewClient(ctx)
if err != nil {
log.Fatal("failed to create GCS client")
}
return &gcs{
StorageClient: client,
ProjectId: projectId,
}
}

func (g gcs) Upload(ctx context.Context, params *UploadParams) error {
// open the local file that is intended to be uploaded to GCS.
// ensure the file is closed at the end.
file, err := os.Open(params.LocalObjPath + "/" + params.Object)
if err != nil {
return fmt.Errorf("os.Open: %w", err)
}
defer func(f *os.File) {
err := f.Close()
if err != nil {
log.Printf("failed to close file: %v", err)
}
}(file)

// set the timeout to 1 minute
ctx, cancel := context.WithTimeout(ctx, time.Minute*1)
defer cancel()

object := g.StorageClient.
Bucket(params.Bucket).
Object(params.UploadObjPath + "/" + params.Object)

// set a generation-match precondition to avoid potential race
// conditions and data corruptions. The request to upload is aborted if the
// object's generation number does not match your precondition.
object = object.If(storage.Conditions{DoesNotExist: true})

// Upload an object with storage.Writer, and close it at the end.
writer := object.NewWriter(ctx)
defer func(w *storage.Writer) {
err := w.Close()
if err != nil {
log.Printf("failed to close writer: %v", err)
}
}(writer)

_, err = io.Copy(writer, file)
if err != nil {
return err
}

log.Printf("File %s successfully uploaded to %s/%s .\n",
params.Object, params.Bucket, params.UploadObjPath)

return nil
}

func (g gcs) GenerateSignedURL(params *GenerateSignedURLParams) (string, error) {
// Set up the signed URL options.
opts := &storage.SignedURLOptions{
Scheme: storage.SigningSchemeV4,
Method: "GET",
Expires: params.ExpirationTime,
}

// Signing a URL requires credentials authorized to sign a URL. You can pass
// these in through SignedURLOptions with one of the following options:
// a. a Google service account private key, obtainable from the Google Developers Console
// b. a Google Access ID with iam.serviceAccounts.signBlob permissions
// c. a SignBytes function implementing custom signing.
// In this example, none of these options are used, which means the SignedURL
// function attempts to use the same authentication that was used to instantiate
// the Storage client. This authentication must include a private key or have
// iam.serviceAccounts.signBlob permissions.
signedUrl, err := g.StorageClient.
Bucket(params.Bucket).
SignedURL(params.UploadObjPath+"/"+params.Object, opts)
if err != nil {
log.Fatalf("Failed to generate signed URL: %v", err)
}

log.Println("SignedURL generated successfully")
return signedUrl, nil
}
42 changes: 42 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module github.com/michaelwp/go-gcs-wrapper

go 1.22

require cloud.google.com/go/storage v1.42.0

require (
cloud.google.com/go v0.114.0 // indirect
cloud.google.com/go/auth v0.5.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/iam v1.1.8 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.4 // indirect
github.com/joho/godotenv v1.5.1 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/api v0.183.0 // indirect
google.golang.org/genproto v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/grpc v1.64.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
)
Loading

0 comments on commit fb9af05

Please sign in to comment.