diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-06-01 17:09:55 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-06-03 10:41:09 +0200 |
| commit | 5d2b332ab5b3b5c8a170f1854d31015dbe376458 (patch) | |
| tree | c906fc2ffef1818c752ff04bca32a2a2ed22cc53 /pkg | |
| parent | 66fd442d487da7e9853eb467ff908ff0c1971756 (diff) | |
pkg/gcs: add new package
Move GCS-related functionality from syz-gce
to a separate package.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/gcs/gcs.go | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/pkg/gcs/gcs.go b/pkg/gcs/gcs.go new file mode 100644 index 000000000..ac95ec420 --- /dev/null +++ b/pkg/gcs/gcs.go @@ -0,0 +1,107 @@ +// Copyright 2017 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// Package gcs provides wrappers around Google Cloud Storage (GCS) APIs. +// Package uses Application Default Credentials assuming that the program runs on GCE. +// +// See the following links for details and API reference: +// https://cloud.google.com/go/getting-started/using-cloud-storage +// https://godoc.org/cloud.google.com/go/storage +package gcs + +import ( + "context" + "fmt" + "io" + "os" + "strings" + "time" + + "cloud.google.com/go/storage" +) + +type Client struct { + client *storage.Client + ctx context.Context +} + +type File struct { + Updated time.Time + + ctx context.Context + handle *storage.ObjectHandle +} + +func (file *File) Reader() (io.ReadCloser, error) { + return file.handle.NewReader(file.ctx) +} + +func NewClient() (*Client, error) { + ctx := context.Background() + storageClient, err := storage.NewClient(ctx) + if err != nil { + return nil, err + } + client := &Client{ + client: storageClient, + ctx: ctx, + } + return client, nil +} + +func (client *Client) Read(gcsFile string) (*File, error) { + bucket, filename, err := split(gcsFile) + if err != nil { + return nil, err + } + bkt := client.client.Bucket(bucket) + f := bkt.Object(filename) + attrs, err := f.Attrs(client.ctx) + if err != nil { + return nil, fmt.Errorf("failed to read %v attributes: %v", gcsFile, err) + } + if !attrs.Deleted.IsZero() { + return nil, fmt.Errorf("file %v is deleted", gcsFile) + } + handle := f.If(storage.Conditions{ + GenerationMatch: attrs.Generation, + MetagenerationMatch: attrs.Metageneration, + }) + file := &File{ + Updated: attrs.Updated, + ctx: client.ctx, + handle: handle, + } + return file, nil +} + +func (client *Client) UploadFile(localFile, gcsFile string) error { + bucket, filename, err := split(gcsFile) + if err != nil { + return err + } + local, err := os.Open(localFile) + if err != nil { + return err + } + defer local.Close() + bkt := client.client.Bucket(bucket) + f := bkt.Object(filename) + w := f.NewWriter(client.ctx) + defer w.Close() + if _, err := io.Copy(w, local); err != nil { + return err + } + return nil +} + +func split(file string) (bucket, filename string, err error) { + if strings.HasPrefix(file, "gs://") { + file = file[5:] + } + pos := strings.IndexByte(file, '/') + if pos == -1 { + return "", "", fmt.Errorf("invalid GCS file name: %v", file) + } + return file[:pos], file[pos+1:], nil +} |
