From 08f37087b7a20f744890c6ca398c0137af5423ff Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Mon, 11 Sep 2017 15:40:51 +0200 Subject: [PATCH] state/remote: The "gcs" client has been superseeded by the "gcs" backend. --- state/remote/gcs.go | 175 --------------------------------------- state/remote/gcs_test.go | 69 --------------- state/remote/remote.go | 1 - 3 files changed, 245 deletions(-) delete mode 100644 state/remote/gcs.go delete mode 100644 state/remote/gcs_test.go diff --git a/state/remote/gcs.go b/state/remote/gcs.go deleted file mode 100644 index 8ea682fef7c1..000000000000 --- a/state/remote/gcs.go +++ /dev/null @@ -1,175 +0,0 @@ -package remote - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "log" - "net/http" - "os" - "runtime" - "strings" - - "github.com/hashicorp/terraform/helper/pathorcontents" - "github.com/hashicorp/terraform/terraform" - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "golang.org/x/oauth2/jwt" - "google.golang.org/api/googleapi" - "google.golang.org/api/storage/v1" -) - -// accountFile represents the structure of the credentials JSON -type accountFile struct { - PrivateKeyId string `json:"private_key_id"` - PrivateKey string `json:"private_key"` - ClientEmail string `json:"client_email"` - ClientId string `json:"client_id"` -} - -func parseJSON(result interface{}, contents string) error { - r := strings.NewReader(contents) - dec := json.NewDecoder(r) - - return dec.Decode(result) -} - -type GCSClient struct { - bucket string - path string - clientStorage *storage.Service - context context.Context -} - -func gcsFactory(conf map[string]string) (Client, error) { - var account accountFile - var client *http.Client - clientScopes := []string{ - "https://www.googleapis.com/auth/devstorage.full_control", - } - - bucketName, ok := conf["bucket"] - if !ok { - return nil, fmt.Errorf("missing 'bucket' configuration") - } - - pathName, ok := conf["path"] - if !ok { - return nil, fmt.Errorf("missing 'path' configuration") - } - - credentials, ok := conf["credentials"] - if !ok { - credentials = os.Getenv("GOOGLE_CREDENTIALS") - } - - if credentials != "" { - contents, _, err := pathorcontents.Read(credentials) - if err != nil { - return nil, fmt.Errorf("Error loading credentials: %s", err) - } - - // Assume account_file is a JSON string - if err := parseJSON(&account, contents); err != nil { - return nil, fmt.Errorf("Error parsing credentials '%s': %s", contents, err) - } - - // Get the token for use in our requests - log.Printf("[INFO] Requesting Google token...") - log.Printf("[INFO] -- Email: %s", account.ClientEmail) - log.Printf("[INFO] -- Scopes: %s", clientScopes) - log.Printf("[INFO] -- Private Key Length: %d", len(account.PrivateKey)) - - conf := jwt.Config{ - Email: account.ClientEmail, - PrivateKey: []byte(account.PrivateKey), - Scopes: clientScopes, - TokenURL: "https://accounts.google.com/o/oauth2/token", - } - - client = conf.Client(oauth2.NoContext) - - } else { - log.Printf("[INFO] Authenticating using DefaultClient") - err := error(nil) - client, err = google.DefaultClient(oauth2.NoContext, clientScopes...) - if err != nil { - return nil, err - } - } - versionString := terraform.Version - userAgent := fmt.Sprintf( - "(%s %s) Terraform/%s", runtime.GOOS, runtime.GOARCH, versionString) - - log.Printf("[INFO] Instantiating Google Storage Client...") - clientStorage, err := storage.New(client) - if err != nil { - return nil, err - } - clientStorage.UserAgent = userAgent - - return &GCSClient{ - clientStorage: clientStorage, - bucket: bucketName, - path: pathName, - }, nil - -} - -func (c *GCSClient) Get() (*Payload, error) { - // Read the object from bucket. - log.Printf("[INFO] Reading %s/%s", c.bucket, c.path) - - resp, err := c.clientStorage.Objects.Get(c.bucket, c.path).Download() - if err != nil { - if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 { - log.Printf("[INFO] %s/%s not found", c.bucket, c.path) - - return nil, nil - } - - return nil, fmt.Errorf("[WARN] Error retrieving object %s/%s: %s", c.bucket, c.path, err) - } - defer resp.Body.Close() - - var buf []byte - w := bytes.NewBuffer(buf) - n, err := io.Copy(w, resp.Body) - if err != nil { - log.Fatalf("[WARN] error buffering %q: %v", c.path, err) - } - log.Printf("[INFO] Downloaded %d bytes", n) - - payload := &Payload{ - Data: w.Bytes(), - } - - // If there was no data, then return nil - if len(payload.Data) == 0 { - return nil, nil - } - - return payload, nil -} - -func (c *GCSClient) Put(data []byte) error { - log.Printf("[INFO] Writing %s/%s", c.bucket, c.path) - - r := bytes.NewReader(data) - _, err := c.clientStorage.Objects.Insert(c.bucket, &storage.Object{Name: c.path}).Media(r).Do() - if err != nil { - return err - } - - return nil -} - -func (c *GCSClient) Delete() error { - log.Printf("[INFO] Deleting %s/%s", c.bucket, c.path) - - err := c.clientStorage.Objects.Delete(c.bucket, c.path).Do() - return err - -} diff --git a/state/remote/gcs_test.go b/state/remote/gcs_test.go deleted file mode 100644 index 40209391718c..000000000000 --- a/state/remote/gcs_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package remote - -import ( - "fmt" - "os" - "testing" - "time" - - storage "google.golang.org/api/storage/v1" -) - -func TestGCSClient_impl(t *testing.T) { - var _ Client = new(GCSClient) -} - -func TestGCSClient(t *testing.T) { - // This test creates a bucket in GCS and populates it. - // It may incur costs, so it will only run if GCS credential environment - // variables are present. - - projectID := os.Getenv("GOOGLE_PROJECT") - if projectID == "" { - t.Skipf("skipping; GOOGLE_PROJECT must be set") - } - - bucketName := fmt.Sprintf("terraform-remote-gcs-test-%x", time.Now().Unix()) - keyName := "testState" - testData := []byte(`testing data`) - - config := make(map[string]string) - config["bucket"] = bucketName - config["path"] = keyName - - client, err := gcsFactory(config) - if err != nil { - t.Fatalf("Error for valid config: %v", err) - } - - gcsClient := client.(*GCSClient) - nativeClient := gcsClient.clientStorage - - // Be clear about what we're doing in case the user needs to clean - // this up later. - if _, err := nativeClient.Buckets.Get(bucketName).Do(); err == nil { - fmt.Printf("Bucket %s already exists - skipping buckets.insert call.", bucketName) - } else { - // Create a bucket. - if res, err := nativeClient.Buckets.Insert(projectID, &storage.Bucket{Name: bucketName}).Do(); err == nil { - fmt.Printf("Created bucket %v at location %v\n\n", res.Name, res.SelfLink) - } else { - t.Skipf("Failed to create test GCS bucket, so skipping") - } - } - - // Ensure we can perform a PUT request with the encryption header - err = gcsClient.Put(testData) - if err != nil { - t.Logf("WARNING: Failed to send test data to GCS bucket. (error was %s)", err) - } - - defer func() { - // Delete the test bucket in the project - if err := gcsClient.clientStorage.Buckets.Delete(bucketName).Do(); err != nil { - t.Logf("WARNING: Failed to delete the test GCS bucket. It has been left in your GCE account and may incur storage charges. (error was %s)", err) - } - }() - - testClient(t, client) -} diff --git a/state/remote/remote.go b/state/remote/remote.go index 132b77f703f3..15fcafbc6844 100644 --- a/state/remote/remote.go +++ b/state/remote/remote.go @@ -47,7 +47,6 @@ func NewClient(t string, conf map[string]string) (Client, error) { var BuiltinClients = map[string]Factory{ "artifactory": artifactoryFactory, "etcd": etcdFactory, - "gcs": gcsFactory, "http": httpFactory, "local": fileFactory, "manta": mantaFactory,