Beispiel #1
0
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)
}
Beispiel #2
0
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)
	}
}
Beispiel #3
0
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)
	}
}
Beispiel #4
0
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)
	}
}
Beispiel #5
0
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
}
Beispiel #6
0
// 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
}
Beispiel #7
0
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)
		}
	}
}
Beispiel #8
0
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)
		}
	}
}
Beispiel #9
0
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)
		}
	}
}
Beispiel #10
0
// 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)
}