cloud: delete deprecated context, pubsub and container funcs

The pubsub and container packages now use Client types which must be
used in place of the legacy top-level functions.

The WithContext and NewContext functions were only needed for this
legacy API pattern; the new Client pattern can use regular contexts from
the golang.org/x/net/context package directly.

Fixes #297

Change-Id: I84f2dc0d7cc70fef4c29c6ab89be2196ba8c2243
Reviewed-on: https://code-review.googlesource.com/5420
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Dave Day <djd@golang.org>
diff --git a/container/legacy.go b/container/legacy.go
deleted file mode 100644
index f30a25b..0000000
--- a/container/legacy.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package container
-
-import (
-	"errors"
-	"net/http"
-
-	"cloud.google.com/go/internal"
-	"golang.org/x/net/context"
-	raw "google.golang.org/api/container/v1"
-)
-
-// Cluster returns metadata about the specified cluster.
-//
-// Deprecated: please use Client.Cluster instead.
-func Cluster(ctx context.Context, zone, name string) (*Resource, error) {
-	s := rawService(ctx)
-	resp, err := s.Projects.Zones.Clusters.Get(internal.ProjID(ctx), zone, name).Do()
-	if err != nil {
-		return nil, err
-	}
-	return resourceFromRaw(resp), nil
-}
-
-// CreateCluster creates a new cluster with the provided metadata
-// in the specified zone.
-//
-// Deprecated: please use Client.CreateCluster instead.
-func CreateCluster(ctx context.Context, zone string, resource *Resource) (*Resource, error) {
-	panic("not implemented")
-}
-
-// DeleteCluster deletes a cluster.
-//
-// Deprecated: please use Client.DeleteCluster instead.
-func DeleteCluster(ctx context.Context, zone, name string) error {
-	s := rawService(ctx)
-	_, err := s.Projects.Zones.Clusters.Delete(internal.ProjID(ctx), zone, name).Do()
-	return err
-}
-
-// Operations returns a list of operations from the specified zone.
-// If no zone is specified, it looks up for all of the operations
-// that are running under the user's project.
-//
-// Deprecated: please use Client.Operations instead.
-func Operations(ctx context.Context, zone string) ([]*Op, error) {
-	s := rawService(ctx)
-	if zone == "" {
-		resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), "-").Do()
-		if err != nil {
-			return nil, err
-		}
-		return opsFromRaw(resp.Operations), nil
-	}
-	resp, err := s.Projects.Zones.Operations.List(internal.ProjID(ctx), zone).Do()
-	if err != nil {
-		return nil, err
-	}
-	return opsFromRaw(resp.Operations), nil
-}
-
-// Operation returns an operation.
-//
-// Deprecated: please use Client.Operation instead.
-func Operation(ctx context.Context, zone, name string) (*Op, error) {
-	s := rawService(ctx)
-	resp, err := s.Projects.Zones.Operations.Get(internal.ProjID(ctx), zone, name).Do()
-	if err != nil {
-		return nil, err
-	}
-	if resp.StatusMessage != "" {
-		return nil, errors.New(resp.StatusMessage)
-	}
-	return opFromRaw(resp), nil
-}
-
-func rawService(ctx context.Context) *raw.Service {
-	return internal.Service(ctx, "container", func(hc *http.Client) interface{} {
-		svc, _ := raw.New(hc)
-		return svc
-	}).(*raw.Service)
-}
diff --git a/example_test.go b/example_test.go
deleted file mode 100644
index 30d7496..0000000
--- a/example_test.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cloud_test
-
-import (
-	"io/ioutil"
-	"log"
-
-	"cloud.google.com/go/pubsub"
-	"golang.org/x/net/context"
-	"golang.org/x/oauth2/google"
-	"google.golang.org/api/option"
-)
-
-func Example_createClientWithApplicationDefaultCredentials(ctx context.Context) *pubsub.Client {
-	// Create a pubsub Client to demonstrate using Application Default
-	// Credentials for authentication.
-	//
-	// Application Default Credentials provide a simple way to get
-	// authorization credentials for use in calling Google APIs.  They are
-	// best suited for cases when the call needs to have the same identity
-	// and authorization level for the application independent of the user.
-	// This is the recommended approach to authorize calls to Google Cloud
-	// APIs, particularly when you're building an application that is
-	// deployed to Google App Engine or Google Compute Engine virtual
-	// machines.
-	// See
-	// https://developers.google.com/identity/protocols/application-default-credentials
-	// for more information.
-	//
-	// The same approach may be used to construct Clients from other
-	// packages, e.g. bigtable, datastore.
-	client, err := pubsub.NewClient(ctx, "project-id")
-	if err != nil {
-		log.Fatal("new client:", err)
-	}
-
-	return client
-}
-
-func Example_createClientWithTokenSource(ctx context.Context) *pubsub.Client {
-	jsonKey, err := ioutil.ReadFile("/path/to/json/keyfile.json")
-	if err != nil {
-		log.Fatal(err)
-	}
-	conf, err := google.JWTConfigFromJSON(
-		jsonKey,
-		pubsub.ScopeCloudPlatform,
-		pubsub.ScopePubSub,
-	)
-
-	if err != nil {
-		log.Fatal(err)
-	}
-	ts := conf.TokenSource(ctx)
-
-	// Create a pubsub Client to demonstrate using an OAuth2 token source
-	// for authentication.  The same approach may be used to construct
-	// Clients from other packages, e.g. bigtable, datastore.
-	client, err := pubsub.NewClient(ctx, "project-id", option.WithTokenSource(ts))
-	if err != nil {
-		log.Fatal("new client:", err)
-	}
-
-	return client
-}
diff --git a/internal/cloud.go b/internal/cloud.go
index 5942880..8e0c8f8 100644
--- a/internal/cloud.go
+++ b/internal/cloud.go
@@ -20,63 +20,16 @@
 import (
 	"fmt"
 	"net/http"
-	"sync"
-
-	"golang.org/x/net/context"
 )
 
-type contextKey struct{}
-
-func WithContext(parent context.Context, projID string, c *http.Client) context.Context {
-	if c == nil {
-		panic("nil *http.Client passed to WithContext")
-	}
-	if projID == "" {
-		panic("empty project ID passed to WithContext")
-	}
-	return context.WithValue(parent, contextKey{}, &cloudContext{
-		ProjectID:  projID,
-		HTTPClient: c,
-	})
-}
-
 const userAgent = "gcloud-golang/0.1"
 
-type cloudContext struct {
-	ProjectID  string
-	HTTPClient *http.Client
-
-	mu  sync.Mutex             // guards svc
-	svc map[string]interface{} // e.g. "storage" => *rawStorage.Service
-}
-
-// Service returns the result of the fill function if it's never been
-// called before for the given name (which is assumed to be an API
-// service name, like "datastore"). If it has already been cached, the fill
-// func is not run.
-// It's safe for concurrent use by multiple goroutines.
-func Service(ctx context.Context, name string, fill func(*http.Client) interface{}) interface{} {
-	return cc(ctx).service(name, fill)
-}
-
-func (c *cloudContext) service(name string, fill func(*http.Client) interface{}) interface{} {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-
-	if c.svc == nil {
-		c.svc = make(map[string]interface{})
-	} else if v, ok := c.svc[name]; ok {
-		return v
-	}
-	v := fill(c.HTTPClient)
-	c.svc[name] = v
-	return v
-}
-
-// Transport is an http.RoundTripper that appends
-// Google Cloud client's user-agent to the original
-// request's user-agent header.
+// Transport is an http.RoundTripper that appends Google Cloud client's
+// user-agent to the original request's user-agent header.
 type Transport struct {
+	// TODO(bradfitz): delete internal.Transport. It's too wrappy for what it does.
+	// Do User-Agent some other way.
+
 	// Base is the actual http.RoundTripper
 	// requests will use. It must not be nil.
 	Base http.RoundTripper
@@ -109,20 +62,3 @@
 	}
 	return r2
 }
-
-func ProjID(ctx context.Context) string {
-	return cc(ctx).ProjectID
-}
-
-func HTTPClient(ctx context.Context) *http.Client {
-	return cc(ctx).HTTPClient
-}
-
-// cc returns the internal *cloudContext (cc) state for a context.Context.
-// It panics if the user did it wrong.
-func cc(ctx context.Context) *cloudContext {
-	if c, ok := ctx.Value(contextKey{}).(*cloudContext); ok {
-		return c
-	}
-	panic("invalid context.Context type; it should be created with cloud.NewContext")
-}
diff --git a/pubsub/legacy.go b/pubsub/legacy.go
deleted file mode 100644
index 75bcbbe..0000000
--- a/pubsub/legacy.go
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package pubsub
-
-import (
-	"encoding/base64"
-	"errors"
-	"fmt"
-	"net/http"
-	"os"
-	"time"
-
-	"cloud.google.com/go/internal"
-	"golang.org/x/net/context"
-	"google.golang.org/api/googleapi"
-	raw "google.golang.org/api/pubsub/v1"
-)
-
-// batchLimit is maximun size of a single batch.
-const batchLimit = 1000
-
-// CreateTopic creates a new topic with the specified name on the backend.
-//
-// Deprecated: Use Client.NewTopic instead.
-//
-// It will return an error if topic already exists.
-func CreateTopic(ctx context.Context, name string) error {
-	_, err := rawService(ctx).Projects.Topics.Create(fullTopicName(internal.ProjID(ctx), name), &raw.Topic{}).Do()
-	return err
-}
-
-// DeleteTopic deletes the specified topic.
-//
-// Deprecated: Use Topic.Delete instead.
-func DeleteTopic(ctx context.Context, name string) error {
-	_, err := rawService(ctx).Projects.Topics.Delete(fullTopicName(internal.ProjID(ctx), name)).Do()
-	return err
-}
-
-// TopicExists returns true if a topic exists with the specified name.
-//
-// Deprecated: Use Topic.Exists instead.
-func TopicExists(ctx context.Context, name string) (bool, error) {
-	_, err := rawService(ctx).Projects.Topics.Get(fullTopicName(internal.ProjID(ctx), name)).Do()
-	if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
-		return false, nil
-	}
-	if err != nil {
-		return false, err
-	}
-	return true, nil
-}
-
-// DeleteSub deletes the subscription.
-//
-// Deprecated: Use Subscription.Delete instead.
-func DeleteSub(ctx context.Context, name string) error {
-	_, err := rawService(ctx).Projects.Subscriptions.Delete(fullSubName(internal.ProjID(ctx), name)).Do()
-	return err
-}
-
-// SubExists returns true if subscription exists.
-//
-// Deprecated: Use Subscription.Exists instead.
-func SubExists(ctx context.Context, name string) (bool, error) {
-	_, err := rawService(ctx).Projects.Subscriptions.Get(fullSubName(internal.ProjID(ctx), name)).Do()
-	if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
-		return false, nil
-	}
-	if err != nil {
-		return false, err
-	}
-	return true, nil
-}
-
-// CreateSub creates a Pub/Sub subscription on the backend.
-//
-// Deprecated: Use Client.NewSubscription instead.
-//
-// A subscription should subscribe to an existing topic.
-//
-// The messages that haven't acknowledged will be pushed back to the
-// subscription again when the default acknowledgement deadline is
-// reached. You can override the default deadline by providing a
-// non-zero deadline. Deadline must not be specified to
-// precision greater than one second.
-//
-// As new messages are being queued on the subscription, you
-// may recieve push notifications regarding to the new arrivals.
-// To receive notifications of new messages in the queue,
-// specify an endpoint callback URL.
-// If endpoint is an empty string the backend will not notify the
-// client of new messages.
-//
-// If the subscription already exists an error will be returned.
-func CreateSub(ctx context.Context, name string, topic string, deadline time.Duration, endpoint string) error {
-	sub := &raw.Subscription{
-		Topic: fullTopicName(internal.ProjID(ctx), topic),
-	}
-	if int64(deadline) > 0 {
-		if !isSec(deadline) {
-			return errors.New("pubsub: deadline must not be specified to precision greater than one second")
-		}
-		sub.AckDeadlineSeconds = int64(deadline / time.Second)
-	}
-	if endpoint != "" {
-		sub.PushConfig = &raw.PushConfig{PushEndpoint: endpoint}
-	}
-	_, err := rawService(ctx).Projects.Subscriptions.Create(fullSubName(internal.ProjID(ctx), name), sub).Do()
-	return err
-}
-
-// Pull pulls up to n messages from the subscription. n must not be larger than 100.
-//
-// Deprecated: Use Subscription.Pull instead
-func Pull(ctx context.Context, sub string, n int) ([]*Message, error) {
-	return pull(ctx, sub, n, true)
-}
-
-// PullWait pulls up to n messages from the subscription. If there are no
-// messages in the queue, it will wait until at least one message is
-// available or a timeout occurs. n must not be larger than 100.
-//
-// Deprecated: Use Subscription.Pull instead
-func PullWait(ctx context.Context, sub string, n int) ([]*Message, error) {
-	return pull(ctx, sub, n, false)
-}
-
-func pull(ctx context.Context, sub string, n int, retImmediately bool) ([]*Message, error) {
-	if n < 1 || n > batchLimit {
-		return nil, fmt.Errorf("pubsub: cannot pull less than one, more than %d messages, but %d was given", batchLimit, n)
-	}
-	resp, err := rawService(ctx).Projects.Subscriptions.Pull(fullSubName(internal.ProjID(ctx), sub), &raw.PullRequest{
-		ReturnImmediately: retImmediately,
-		MaxMessages:       int64(n),
-	}).Do()
-	if err != nil {
-		return nil, err
-	}
-	msgs := make([]*Message, len(resp.ReceivedMessages))
-	for i := 0; i < len(resp.ReceivedMessages); i++ {
-		msg, err := toMessage(resp.ReceivedMessages[i])
-		if err != nil {
-			return nil, fmt.Errorf("pubsub: cannot decode the retrieved message at index: %d, PullResponse: %+v", i, resp.ReceivedMessages[i])
-		}
-		msgs[i] = msg
-	}
-	return msgs, nil
-}
-
-// ModifyAckDeadline modifies the acknowledgement deadline
-// for the messages retrieved from the specified subscription.
-// Deadline must not be specified to precision greater than one second.
-//
-// Deprecated: Use Subscription.Pull instead, which automatically extends ack deadlines.
-func ModifyAckDeadline(ctx context.Context, sub string, id string, deadline time.Duration) error {
-	if !isSec(deadline) {
-		return errors.New("pubsub: deadline must not be specified to precision greater than one second")
-	}
-	_, err := rawService(ctx).Projects.Subscriptions.ModifyAckDeadline(fullSubName(internal.ProjID(ctx), sub), &raw.ModifyAckDeadlineRequest{
-		AckDeadlineSeconds: int64(deadline / time.Second),
-		AckIds:             []string{id},
-	}).Do()
-	return err
-}
-
-// Ack acknowledges one or more Pub/Sub messages on the
-// specified subscription.
-//
-// Deprecated: Call Message.Done on a Message returned by Iterator.Next instead.
-func Ack(ctx context.Context, sub string, id ...string) error {
-	for idx, ackID := range id {
-		if ackID == "" {
-			return fmt.Errorf("pubsub: empty ackID detected at index %d", idx)
-		}
-	}
-	_, err := rawService(ctx).Projects.Subscriptions.Acknowledge(fullSubName(internal.ProjID(ctx), sub), &raw.AcknowledgeRequest{
-		AckIds: id,
-	}).Do()
-	return err
-}
-
-func isSec(dur time.Duration) bool {
-	return dur%time.Second == 0
-}
-
-// Publish publishes messages to the topic's subscribers. It returns
-// message IDs upon success.
-//
-// Deprecated: Use Topic.Publish instead.
-func Publish(ctx context.Context, topic string, msgs ...*Message) ([]string, error) {
-	var rawMsgs []*raw.PubsubMessage
-	if len(msgs) == 0 {
-		return nil, errors.New("pubsub: no messages to publish")
-	}
-	if len(msgs) > batchLimit {
-		return nil, fmt.Errorf("pubsub: %d messages given, but maximum batch size is %d", len(msgs), batchLimit)
-	}
-	rawMsgs = make([]*raw.PubsubMessage, len(msgs))
-	for i, msg := range msgs {
-		rawMsgs[i] = &raw.PubsubMessage{
-			Data:       base64.StdEncoding.EncodeToString(msg.Data),
-			Attributes: msg.Attributes,
-		}
-	}
-	resp, err := rawService(ctx).Projects.Topics.Publish(fullTopicName(internal.ProjID(ctx), topic), &raw.PublishRequest{
-		Messages: rawMsgs,
-	}).Do()
-	if err != nil {
-		return nil, err
-	}
-	return resp.MessageIds, nil
-}
-
-// ModifyPushEndpoint modifies the URL endpoint to modify the resource
-// to handle push notifications coming from the Pub/Sub backend
-// for the specified subscription.
-//
-// Deprecated: Use Subscription.ModifyPushConfig instead.
-func ModifyPushEndpoint(ctx context.Context, sub, endpoint string) error {
-	_, err := rawService(ctx).Projects.Subscriptions.ModifyPushConfig(fullSubName(internal.ProjID(ctx), sub), &raw.ModifyPushConfigRequest{
-		PushConfig: &raw.PushConfig{
-			PushEndpoint: endpoint,
-		},
-	}).Do()
-	return err
-}
-
-// fullSubName returns the fully qualified name for a subscription.
-// E.g. /subscriptions/project-id/subscription-name.
-func fullSubName(proj, name string) string {
-	return fmt.Sprintf("projects/%s/subscriptions/%s", proj, name)
-}
-
-func rawService(ctx context.Context) *raw.Service {
-	baseAddr := func() string {
-		// Environment variables for gcloud emulator:
-		// https://cloud.google.com/sdk/gcloud/reference/beta/emulators/pubsub/
-		if host := os.Getenv("PUBSUB_EMULATOR_HOST"); host != "" {
-			return "http://" + host + "/"
-		}
-		return prodAddr
-	}
-	return internal.Service(ctx, "pubsub", func(hc *http.Client) interface{} {
-		svc, _ := raw.New(hc)
-		svc.BasePath = baseAddr()
-		return svc
-	}).(*raw.Service)
-}
-
-// fullTopicName returns the fully qualified name for a topic.
-// E.g. /topics/project-id/topic-name.
-func fullTopicName(proj, name string) string {
-	return fmt.Sprintf("projects/%s/topics/%s", proj, name)
-}