func maybeRemapCloudSQL(host string) (out string, err error) { if !strings.HasSuffix(host, cloudSQLSuffix) { return host, nil } inst := strings.TrimSuffix(host, cloudSQLSuffix) if !metadata.OnGCE() { return "", errors.New("CloudSQL support only available when running on Google Compute Engine.") } proj, err := metadata.ProjectID() if err != nil { return "", fmt.Errorf("Failed to lookup GCE project ID: %v", err) } admin, _ := sqladmin.New(oauth2.NewClient(context.Background(), google.ComputeTokenSource(""))) listRes, err := admin.Instances.List(proj).Do() if err != nil { return "", fmt.Errorf("error enumerating Cloud SQL instances: %v", err) } for _, it := range listRes.Items { if !strings.EqualFold(it.Instance, inst) { continue } js, _ := json.Marshal(it) log.Printf("Found Cloud SQL instance %s: %s", inst, js) for _, ipm := range it.IpAddresses { return ipm.IpAddress, nil } return "", fmt.Errorf("No external IP address for Cloud SQL instances %s", inst) } var found []string for _, it := range listRes.Items { found = append(found, it.Instance) } return "", fmt.Errorf("Cloud SQL instance %q not found. Found: %q", inst, found) }
func TestParent(t *testing.T) { c := context.Background() k := NewIncompleteKey(c, "foo", nil) par := NewKey(c, "foomum", "", 1248, nil) k.SetParent(par) if got := k.Parent(); got != par { t.Errorf("k.Parent() = %v; want %v", got, par) } }
func TestInterruptedTransferChunks(t *testing.T) { f, err := os.Open("googleapi.go") if err != nil { t.Fatalf("unable to open googleapi.go: %v", err) } defer f.Close() slurp, err := ioutil.ReadAll(f) if err != nil { t.Fatalf("unable to slurp file: %v", err) } st, err := f.Stat() if err != nil { t.Fatalf("unable to stat googleapi.go: %v", err) } tr := &interruptedTransport{ statusCode: 308, buf: make([]byte, 0, st.Size()), } oldChunkSize := chunkSize defer func() { chunkSize = oldChunkSize }() chunkSize = 100 // override to process small chunks for test. sleep = func(time.Duration) {} // override time.Sleep rx := &ResumableUpload{ Client: &http.Client{Transport: tr}, Media: f, MediaType: "text/plain", ContentLength: st.Size(), Callback: tr.ProgressUpdate, } res, err := rx.Upload(context.Background()) if err != nil || res == nil || res.StatusCode != http.StatusOK { if res == nil { t.Errorf("transferChunks not successful, res=nil: %v", err) } else { t.Errorf("transferChunks not successful, statusCode=%v: %v", res.StatusCode, err) } } if len(tr.buf) != len(slurp) || bytes.Compare(tr.buf, slurp) != 0 { t.Errorf("transfered file corrupted:\ngot %s\nwant %s", tr.buf, slurp) } w := "" for i := chunkSize; i <= st.Size(); i += chunkSize { w += fmt.Sprintf("%v, %v\n", i, st.Size()) } if st.Size()%chunkSize != 0 { w += fmt.Sprintf("%v, %v\n", st.Size(), st.Size()) } if tr.progressBuf != w { t.Errorf("progress update error, got %v, want %v", tr.progressBuf, w) } }
func TestNamespace(t *testing.T) { c := context.Background() k := NewIncompleteKey(c, "foo", nil) if got, want := k.Namespace(), ""; got != want { t.Errorf("No namespace, k.Namespace() = %q, want %q", got, want) } c = WithNamespace(c, "gopherspace") k = NewIncompleteKey(c, "foo", nil) if got, want := k.Namespace(), "gopherspace"; got != want { t.Errorf("No namespace, k.Namespace() = %q, want %q", got, want) } }
func ExampleWithTimeout() { // Pass a context with a timeout to tell a blocking function that it // should abandon its work after the timeout elapses. ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond) select { case <-time.After(200 * time.Millisecond): fmt.Println("overslept") case <-ctx.Done(): fmt.Println(ctx.Err()) // prints "context deadline exceeded" } // Output: // context deadline exceeded }
// NewServiceClient returns a Client for use when running on Google // Compute Engine. This client can access buckets owned by the same // project ID as the VM. func NewServiceClient() (*Client, error) { if !metadata.OnGCE() { return nil, errors.New("not running on Google Compute Engine") } scopes, _ := metadata.Scopes("default") haveScope := func(scope string) bool { for _, x := range scopes { if x == scope { return true } } return false } if !haveScope("https://www.googleapis.com/auth/devstorage.full_control") && !haveScope("https://www.googleapis.com/auth/devstorage.read_write") { return nil, errors.New("when this Google Compute Engine VM instance was created, it wasn't granted access to Cloud Storage") } client := oauth2.NewClient(context.Background(), google.ComputeTokenSource("")) service, _ := api.New(client) return &Client{client: client, service: service}, nil }
func TestCancelUpload(t *testing.T) { f, err := os.Open("googleapi.go") if err != nil { t.Fatalf("unable to open googleapi.go: %v", err) } defer f.Close() st, err := f.Stat() if err != nil { t.Fatalf("unable to stat googleapi.go: %v", err) } tr := &interruptedTransport{ statusCode: 308, buf: make([]byte, 0, st.Size()), } oldChunkSize := chunkSize defer func() { chunkSize = oldChunkSize }() chunkSize = 100 // override to process small chunks for test. sleep = func(time.Duration) {} // override time.Sleep rx := &ResumableUpload{ Client: &http.Client{Transport: tr}, Media: f, MediaType: "text/plain", ContentLength: st.Size(), Callback: tr.ProgressUpdate, } ctx, cancelFunc := context.WithCancel(context.Background()) cancelFunc() // stop the upload that hasn't started yet res, err := rx.Upload(ctx) if err == nil || res == nil || res.StatusCode != http.StatusRequestTimeout { if res == nil { t.Errorf("transferChunks not successful, got res=nil, err=%v, want StatusRequestTimeout", err) } else { t.Errorf("transferChunks not successful, got statusCode=%v, err=%v, want StatusRequestTimeout", res.StatusCode, err) } } }
func TestEqual(t *testing.T) { c := context.Background() cN := WithNamespace(c, "gopherspace") testCases := []struct { x, y *Key equal bool }{ { x: nil, y: nil, equal: true, }, { x: NewKey(c, "kindA", "", 0, nil), y: NewIncompleteKey(c, "kindA", nil), equal: true, }, { x: NewKey(c, "kindA", "nameA", 0, nil), y: NewKey(c, "kindA", "nameA", 0, nil), equal: true, }, { x: NewKey(cN, "kindA", "nameA", 0, nil), y: NewKey(cN, "kindA", "nameA", 0, nil), equal: true, }, { x: NewKey(c, "kindA", "", 1337, NewKey(c, "kindX", "nameX", 0, nil)), y: NewKey(c, "kindA", "", 1337, NewKey(c, "kindX", "nameX", 0, nil)), equal: true, }, { x: NewKey(c, "kindA", "nameA", 0, nil), y: NewKey(c, "kindB", "nameA", 0, nil), equal: false, }, { x: NewKey(c, "kindA", "nameA", 0, nil), y: NewKey(c, "kindA", "nameB", 0, nil), equal: false, }, { x: NewKey(c, "kindA", "nameA", 0, nil), y: NewKey(c, "kindA", "", 1337, nil), equal: false, }, { x: NewKey(c, "kindA", "nameA", 0, nil), y: NewKey(cN, "kindA", "nameA", 0, nil), equal: false, }, { x: NewKey(c, "kindA", "", 1337, NewKey(c, "kindX", "nameX", 0, nil)), y: NewKey(c, "kindA", "", 1337, NewKey(c, "kindY", "nameX", 0, nil)), equal: false, }, { x: NewKey(c, "kindA", "", 1337, NewKey(c, "kindX", "nameX", 0, nil)), y: NewKey(c, "kindA", "", 1337, nil), equal: false, }, } for _, tt := range testCases { if got := tt.x.Equal(tt.y); got != tt.equal { t.Errorf("Equal(%v, %v) = %t; want %t", tt.x, tt.y, got, tt.equal) } if got := tt.y.Equal(tt.x); got != tt.equal { t.Errorf("Equal(%v, %v) = %t; want %t", tt.y, tt.x, got, tt.equal) } } }
func TestEncoding(t *testing.T) { c := context.Background() cN := WithNamespace(c, "gopherspace") testCases := []struct { k *Key valid bool }{ { k: nil, valid: false, }, { k: NewKey(c, "", "", 0, nil), valid: false, }, { k: NewKey(c, "kindA", "", 0, nil), valid: true, }, { k: NewKey(cN, "kindA", "", 0, nil), valid: true, }, { k: NewKey(c, "kindA", "nameA", 0, nil), valid: true, }, { k: NewKey(c, "kindA", "", 1337, nil), valid: true, }, { k: NewKey(c, "kindA", "nameA", 1337, nil), valid: false, }, { k: NewKey(c, "kindA", "", 0, NewKey(c, "kindB", "nameB", 0, nil)), valid: true, }, { k: NewKey(c, "kindA", "", 0, NewKey(c, "kindB", "", 0, nil)), valid: false, }, { k: NewKey(c, "kindA", "", 0, NewKey(cN, "kindB", "nameB", 0, nil)), valid: false, }, } for _, tt := range testCases { if got := tt.k.valid(); got != tt.valid { t.Errorf("valid(%v) = %t; want %t", tt.k, got, tt.valid) } // Check encoding/decoding for valid keys. if !tt.valid { continue } enc := tt.k.Encode() dec, err := DecodeKey(enc) if err != nil { t.Errorf("DecodeKey(%q) from %v: %v", enc, tt.k, err) continue } if !tt.k.Equal(dec) { t.Errorf("Decoded key %v not equal to %v", dec, tt.k) } b, err := json.Marshal(tt.k) if err != nil { t.Errorf("json.Marshal(%v): %v", tt.k, err) continue } key := &Key{} if err := json.Unmarshal(b, key); err != nil { t.Errorf("json.Unmarshal(%s) for key %v: %v", b, tt.k, err) continue } if !tt.k.Equal(key) { t.Errorf("JSON decoded key %v not equal to %v", dec, tt.k) } buf := &bytes.Buffer{} gobEnc := gob.NewEncoder(buf) if err := gobEnc.Encode(tt.k); err != nil { t.Errorf("gobEnc.Encode(%v): %v", tt.k, err) continue } gobDec := gob.NewDecoder(buf) key = &Key{} if err := gobDec.Decode(key); err != nil { t.Errorf("gobDec.Decode() for key %v: %v", tt.k, err) } if !tt.k.Equal(key) { t.Errorf("gob decoded key %v not equal to %v", dec, tt.k) } } }
// NewContext returns a new context that uses the provided http.Client. // Provided http.Client is responsible to authorize and authenticate // the requests made to the Google Cloud APIs. // It mutates the client's original Transport to append the cloud // package's user-agent to the outgoing requests. // You can obtain the project ID from the Google Developers Console, // https://console.developers.google.com. func NewContext(projID string, c *http.Client) context.Context { if c == nil { panic("invalid nil *http.Client passed to NewContext") } return WithContext(context.Background(), projID, c) }