mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-01 16:21:06 +00:00
Merge pull request #177 from terraform-providers/bigtable-support
Add support for Google Cloud Bigtable.
This commit is contained in:
commit
95e72d513e
22
google/bigtable_client_factory.go
Normal file
22
google/bigtable_client_factory.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"cloud.google.com/go/bigtable"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"google.golang.org/api/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BigtableClientFactory struct {
|
||||||
|
UserAgent string
|
||||||
|
TokenSource oauth2.TokenSource
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s BigtableClientFactory) NewInstanceAdminClient(project string) (*bigtable.InstanceAdminClient, error) {
|
||||||
|
return bigtable.NewInstanceAdminClient(context.Background(), project, option.WithTokenSource(s.TokenSource), option.WithUserAgent(s.UserAgent))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s BigtableClientFactory) NewAdminClient(project, instance string) (*bigtable.AdminClient, error) {
|
||||||
|
return bigtable.NewAdminClient(context.Background(), project, instance, option.WithTokenSource(s.TokenSource), option.WithUserAgent(s.UserAgent))
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package google
|
package google
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform/helper/logging"
|
"github.com/hashicorp/terraform/helper/logging"
|
||||||
"github.com/hashicorp/terraform/helper/pathorcontents"
|
"github.com/hashicorp/terraform/helper/pathorcontents"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"golang.org/x/oauth2/jwt"
|
"golang.org/x/oauth2/jwt"
|
||||||
@ -45,6 +47,8 @@ type Config struct {
|
|||||||
clientIAM *iam.Service
|
clientIAM *iam.Service
|
||||||
clientServiceMan *servicemanagement.APIService
|
clientServiceMan *servicemanagement.APIService
|
||||||
clientBigQuery *bigquery.Service
|
clientBigQuery *bigquery.Service
|
||||||
|
|
||||||
|
bigtableClientFactory *BigtableClientFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) loadAndValidate() error {
|
func (c *Config) loadAndValidate() error {
|
||||||
@ -57,6 +61,7 @@ func (c *Config) loadAndValidate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var client *http.Client
|
var client *http.Client
|
||||||
|
var tokenSource oauth2.TokenSource
|
||||||
|
|
||||||
if c.Credentials != "" {
|
if c.Credentials != "" {
|
||||||
contents, _, err := pathorcontents.Read(c.Credentials)
|
contents, _, err := pathorcontents.Read(c.Credentials)
|
||||||
@ -85,12 +90,18 @@ func (c *Config) loadAndValidate() error {
|
|||||||
// Initiate an http.Client. The following GET request will be
|
// Initiate an http.Client. The following GET request will be
|
||||||
// authorized and authenticated on the behalf of
|
// authorized and authenticated on the behalf of
|
||||||
// your service account.
|
// your service account.
|
||||||
client = conf.Client(oauth2.NoContext)
|
client = conf.Client(context.Background())
|
||||||
|
|
||||||
|
tokenSource = conf.TokenSource(context.Background())
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[INFO] Authenticating using DefaultClient")
|
log.Printf("[INFO] Authenticating using DefaultClient")
|
||||||
err := error(nil)
|
err := error(nil)
|
||||||
client, err = google.DefaultClient(oauth2.NoContext, clientScopes...)
|
client, err = google.DefaultClient(context.Background(), clientScopes...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenSource, err = google.DefaultTokenSource(context.Background(), clientScopes...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -181,6 +192,11 @@ func (c *Config) loadAndValidate() error {
|
|||||||
}
|
}
|
||||||
c.clientBigQuery.UserAgent = userAgent
|
c.clientBigQuery.UserAgent = userAgent
|
||||||
|
|
||||||
|
c.bigtableClientFactory = &BigtableClientFactory{
|
||||||
|
UserAgent: userAgent,
|
||||||
|
TokenSource: tokenSource,
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ func Provider() terraform.ResourceProvider {
|
|||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
"google_bigquery_dataset": resourceBigQueryDataset(),
|
"google_bigquery_dataset": resourceBigQueryDataset(),
|
||||||
"google_bigquery_table": resourceBigQueryTable(),
|
"google_bigquery_table": resourceBigQueryTable(),
|
||||||
|
"google_bigtable_instance": resourceBigtableInstance(),
|
||||||
|
"google_bigtable_table": resourceBigtableTable(),
|
||||||
"google_compute_autoscaler": resourceComputeAutoscaler(),
|
"google_compute_autoscaler": resourceComputeAutoscaler(),
|
||||||
"google_compute_address": resourceComputeAddress(),
|
"google_compute_address": resourceComputeAddress(),
|
||||||
"google_compute_backend_bucket": resourceComputeBackendBucket(),
|
"google_compute_backend_bucket": resourceComputeBackendBucket(),
|
||||||
|
193
google/resource_bigtable_instance.go
Normal file
193
google/resource_bigtable_instance.go
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/helper/validation"
|
||||||
|
|
||||||
|
"cloud.google.com/go/bigtable"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceBigtableInstance() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceBigtableInstanceCreate,
|
||||||
|
Read: resourceBigtableInstanceRead,
|
||||||
|
Delete: resourceBigtableInstanceDestroy,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"cluster_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"zone": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"display_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"num_nodes": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Default: 3,
|
||||||
|
ValidateFunc: IntAtLeast(3),
|
||||||
|
},
|
||||||
|
|
||||||
|
"storage_type": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Default: "SSD",
|
||||||
|
ValidateFunc: validation.StringInSlice([]string{"SSD", "HDD"}, false),
|
||||||
|
},
|
||||||
|
|
||||||
|
"project": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceBigtableInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
displayName, ok := d.GetOk("display_name")
|
||||||
|
if !ok {
|
||||||
|
displayName = name
|
||||||
|
}
|
||||||
|
|
||||||
|
var storageType bigtable.StorageType
|
||||||
|
switch value := d.Get("storage_type"); value {
|
||||||
|
case "HDD":
|
||||||
|
storageType = bigtable.HDD
|
||||||
|
case "SSD":
|
||||||
|
storageType = bigtable.SSD
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceConf := &bigtable.InstanceConf{
|
||||||
|
InstanceId: name,
|
||||||
|
DisplayName: displayName.(string),
|
||||||
|
ClusterId: d.Get("cluster_id").(string),
|
||||||
|
NumNodes: int32(d.Get("num_nodes").(int)),
|
||||||
|
StorageType: storageType,
|
||||||
|
Zone: d.Get("zone").(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := config.bigtableClientFactory.NewInstanceAdminClient(project)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
err = c.CreateInstance(ctx, instanceConf)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating instance. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(name)
|
||||||
|
|
||||||
|
return resourceBigtableInstanceRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceBigtableInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := config.bigtableClientFactory.NewInstanceAdminClient(project)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
instance, err := c.InstanceInfo(ctx, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[WARN] Removing %s because it's gone", d.Id())
|
||||||
|
d.SetId("")
|
||||||
|
return fmt.Errorf("Error retrieving instance. Could not find %s. %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", instance.Name)
|
||||||
|
d.Set("display_name", instance.DisplayName)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceBigtableInstanceDestroy(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := config.bigtableClientFactory.NewInstanceAdminClient(project)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
name := d.Id()
|
||||||
|
err = c.DeleteInstance(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting instance. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntAtLeast returns a SchemaValidateFunc which tests if the provided value
|
||||||
|
// is of type int and is above min (inclusive)
|
||||||
|
func IntAtLeast(min int) schema.SchemaValidateFunc {
|
||||||
|
return func(i interface{}, k string) (s []string, es []error) {
|
||||||
|
v, ok := i.(int)
|
||||||
|
if !ok {
|
||||||
|
es = append(es, fmt.Errorf("expected type of %s to be int", k))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < min {
|
||||||
|
es = append(es, fmt.Errorf("expected %s to be at least %d, got %d", k, min, v))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
94
google/resource_bigtable_instance_test.go
Normal file
94
google/resource_bigtable_instance_test.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccBigtableInstance_basic(t *testing.T) {
|
||||||
|
instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckBigtableInstanceDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccBigtableInstance(instanceName),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccBigtableInstanceExists(
|
||||||
|
"google_bigtable_instance.instance"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckBigtableInstanceDestroy(s *terraform.State) error {
|
||||||
|
var ctx = context.Background()
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_bigtable_instance" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
c, err := config.bigtableClientFactory.NewInstanceAdminClient(config.Project)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.InstanceInfo(ctx, rs.Primary.Attributes["name"])
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Instance %s still exists.", rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigtableInstanceExists(n string) resource.TestCheckFunc {
|
||||||
|
var ctx = context.Background()
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
c, err := config.bigtableClientFactory.NewInstanceAdminClient(config.Project)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.InstanceInfo(ctx, rs.Primary.Attributes["name"])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving instance %s.", rs.Primary.Attributes["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigtableInstance(instanceName string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_bigtable_instance" "instance" {
|
||||||
|
name = "%s"
|
||||||
|
cluster_id = "%s"
|
||||||
|
zone = "us-central1-b"
|
||||||
|
num_nodes = 3
|
||||||
|
storage_type = "HDD"
|
||||||
|
}
|
||||||
|
`, instanceName, instanceName)
|
||||||
|
}
|
141
google/resource_bigtable_table.go
Normal file
141
google/resource_bigtable_table.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceBigtableTable() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceBigtableTableCreate,
|
||||||
|
Read: resourceBigtableTableRead,
|
||||||
|
Delete: resourceBigtableTableDestroy,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"instance_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"split_keys": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
|
||||||
|
"project": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceBigtableTableCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceName := d.Get("instance_name").(string)
|
||||||
|
c, err := config.bigtableClientFactory.NewAdminClient(project, instanceName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
if v, ok := d.GetOk("split_keys"); ok {
|
||||||
|
splitKeys := convertSchemaArrayToStringArray(v.([]interface{}))
|
||||||
|
// This method may return before the table's creation is complete - we may need to wait until
|
||||||
|
// it exists in the future.
|
||||||
|
err = c.CreatePresplitTable(ctx, name, splitKeys)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating presplit table. %s", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This method may return before the table's creation is complete - we may need to wait until
|
||||||
|
// it exists in the future.
|
||||||
|
err = c.CreateTable(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating table. %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(name)
|
||||||
|
|
||||||
|
return resourceBigtableTableRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceBigtableTableRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceName := d.Get("instance_name").(string)
|
||||||
|
c, err := config.bigtableClientFactory.NewAdminClient(project, instanceName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
name := d.Id()
|
||||||
|
_, err = c.TableInfo(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[WARN] Removing %s because it's gone", name)
|
||||||
|
d.SetId("")
|
||||||
|
return fmt.Errorf("Error retrieving table. Could not find %s in %s. %s", name, instanceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceBigtableTableDestroy(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceName := d.Get("instance_name").(string)
|
||||||
|
c, err := config.bigtableClientFactory.NewAdminClient(project, instanceName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
err = c.DeleteTable(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting table. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
139
google/resource_bigtable_table_test.go
Normal file
139
google/resource_bigtable_table_test.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccBigtableTable_basic(t *testing.T) {
|
||||||
|
instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||||
|
tableName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckBigtableTableDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccBigtableTable(instanceName, tableName),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccBigtableTableExists(
|
||||||
|
"google_bigtable_table.table"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccBigtableTable_splitKeys(t *testing.T) {
|
||||||
|
instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||||
|
tableName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckBigtableTableDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccBigtableTable_splitKeys(instanceName, tableName),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccBigtableTableExists(
|
||||||
|
"google_bigtable_table.table"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckBigtableTableDestroy(s *terraform.State) error {
|
||||||
|
var ctx = context.Background()
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_bigtable_table" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
c, err := config.bigtableClientFactory.NewAdminClient(config.Project, rs.Primary.Attributes["instance_name"])
|
||||||
|
if err != nil {
|
||||||
|
// The instance is already gone
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.TableInfo(ctx, rs.Primary.Attributes["name"])
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Table still present. Found %s in %s.", rs.Primary.Attributes["name"], rs.Primary.Attributes["instance_name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigtableTableExists(n string) resource.TestCheckFunc {
|
||||||
|
var ctx = context.Background()
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
c, err := config.bigtableClientFactory.NewAdminClient(config.Project, rs.Primary.Attributes["instance_name"])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error starting admin client. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.TableInfo(ctx, rs.Primary.Attributes["name"])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving table. Could not find %s in %s.", rs.Primary.Attributes["name"], rs.Primary.Attributes["instance_name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigtableTable(instanceName, tableName string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_bigtable_instance" "instance" {
|
||||||
|
name = "%s"
|
||||||
|
cluster_id = "%s"
|
||||||
|
zone = "us-central1-b"
|
||||||
|
num_nodes = 3
|
||||||
|
storage_type = "HDD"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_bigtable_table" "table" {
|
||||||
|
name = "%s"
|
||||||
|
instance_name = "${google_bigtable_instance.instance.name}"
|
||||||
|
}
|
||||||
|
`, instanceName, instanceName, tableName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccBigtableTable_splitKeys(instanceName, tableName string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_bigtable_instance" "instance" {
|
||||||
|
name = "%s"
|
||||||
|
cluster_id = "%s"
|
||||||
|
zone = "us-central1-b"
|
||||||
|
num_nodes = 3
|
||||||
|
storage_type = "HDD"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_bigtable_table" "table" {
|
||||||
|
name = "%s"
|
||||||
|
instance_name = "${google_bigtable_instance.instance.name}"
|
||||||
|
split_keys = ["a", "b", "c"]
|
||||||
|
}
|
||||||
|
`, instanceName, instanceName, tableName)
|
||||||
|
}
|
21
vendor/cloud.google.com/go/bigtable/admin.go
generated
vendored
21
vendor/cloud.google.com/go/bigtable/admin.go
generated
vendored
@ -369,3 +369,24 @@ func (iac *InstanceAdminClient) Instances(ctx context.Context) ([]*InstanceInfo,
|
|||||||
}
|
}
|
||||||
return is, nil
|
return is, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InstanceInfo returns information about an instance.
|
||||||
|
func (iac *InstanceAdminClient) InstanceInfo(ctx context.Context, instanceId string) (*InstanceInfo, error) {
|
||||||
|
ctx = mergeOutgoingMetadata(ctx, iac.md)
|
||||||
|
req := &btapb.GetInstanceRequest{
|
||||||
|
Name: "projects/" + iac.project + "/instances/" + instanceId,
|
||||||
|
}
|
||||||
|
res, err := iac.iClient.GetInstance(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := instanceNameRegexp.FindStringSubmatch(res.Name)
|
||||||
|
if m == nil {
|
||||||
|
return nil, fmt.Errorf("malformed instance name %q", res.Name)
|
||||||
|
}
|
||||||
|
return &InstanceInfo{
|
||||||
|
Name: m[2],
|
||||||
|
DisplayName: res.DisplayName,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
2
vendor/cloud.google.com/go/bigtable/bigtable.go
generated
vendored
2
vendor/cloud.google.com/go/bigtable/bigtable.go
generated
vendored
@ -73,7 +73,7 @@ func (c *Client) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
idempotentRetryCodes = []codes.Code{codes.DeadlineExceeded, codes.Unavailable, codes.Aborted, codes.Internal}
|
idempotentRetryCodes = []codes.Code{codes.DeadlineExceeded, codes.Unavailable, codes.Aborted}
|
||||||
isIdempotentRetryCode = make(map[codes.Code]bool)
|
isIdempotentRetryCode = make(map[codes.Code]bool)
|
||||||
retryOptions = []gax.CallOption{
|
retryOptions = []gax.CallOption{
|
||||||
gax.WithDelayTimeoutSettings(100*time.Millisecond, 2000*time.Millisecond, 1.2),
|
gax.WithDelayTimeoutSettings(100*time.Millisecond, 2000*time.Millisecond, 1.2),
|
||||||
|
4
vendor/cloud.google.com/go/bigtable/filter.go
generated
vendored
4
vendor/cloud.google.com/go/bigtable/filter.go
generated
vendored
@ -154,7 +154,7 @@ func (stripValueFilter) proto() *btpb.RowFilter {
|
|||||||
return &btpb.RowFilter{Filter: &btpb.RowFilter_StripValueTransformer{true}}
|
return &btpb.RowFilter{Filter: &btpb.RowFilter_StripValueTransformer{true}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimestampRangeFilter returns a filter that matches any rows whose timestamp is within the given time bounds. A zero
|
// TimestampRangeFilter returns a filter that matches any cells whose timestamp is within the given time bounds. A zero
|
||||||
// time means no bound.
|
// time means no bound.
|
||||||
// The timestamp will be truncated to millisecond granularity.
|
// The timestamp will be truncated to millisecond granularity.
|
||||||
func TimestampRangeFilter(startTime time.Time, endTime time.Time) Filter {
|
func TimestampRangeFilter(startTime time.Time, endTime time.Time) Filter {
|
||||||
@ -168,7 +168,7 @@ func TimestampRangeFilter(startTime time.Time, endTime time.Time) Filter {
|
|||||||
return trf
|
return trf
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimestampRangeFilterMicros returns a filter that matches any rows whose timestamp is within the given time bounds,
|
// TimestampRangeFilterMicros returns a filter that matches any cells whose timestamp is within the given time bounds,
|
||||||
// specified in units of microseconds since 1 January 1970. A zero value for the end time is interpreted as no bound.
|
// specified in units of microseconds since 1 January 1970. A zero value for the end time is interpreted as no bound.
|
||||||
// The timestamp will be truncated to millisecond granularity.
|
// The timestamp will be truncated to millisecond granularity.
|
||||||
func TimestampRangeFilterMicros(startTime Timestamp, endTime Timestamp) Filter {
|
func TimestampRangeFilterMicros(startTime Timestamp, endTime Timestamp) Filter {
|
||||||
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -3,10 +3,10 @@
|
|||||||
"ignore": "appengine test github.com/hashicorp/nomad/",
|
"ignore": "appengine test github.com/hashicorp/nomad/",
|
||||||
"package": [
|
"package": [
|
||||||
{
|
{
|
||||||
"checksumSHA1": "fEobtlzPZ57VXi864qMmblI2gsA=",
|
"checksumSHA1": "NrTYYg3++pBxH1Z8xjVg6ssQTYY=",
|
||||||
"path": "cloud.google.com/go/bigtable",
|
"path": "cloud.google.com/go/bigtable",
|
||||||
"revision": "69931d826ffbbcb4f8451b42d5cf7fc2ac6c7443",
|
"revision": "f6bedb5a8dbce75418580cedf5c2434c78d06cfa",
|
||||||
"revisionTime": "2017-06-09T14:31:37Z"
|
"revisionTime": "2017-06-27T21:12:08Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "B1HkIrBavSgy6ntVyGr/eNUy44I=",
|
"checksumSHA1": "B1HkIrBavSgy6ntVyGr/eNUy44I=",
|
||||||
|
49
website/docs/r/bigtable_instance.html.markdown
Normal file
49
website/docs/r/bigtable_instance.html.markdown
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
layout: "google"
|
||||||
|
page_title: "Google: google_bigtable_instance"
|
||||||
|
sidebar_current: "docs-google-bigtable-instance"
|
||||||
|
description: |-
|
||||||
|
Creates a Google Bigtable instance.
|
||||||
|
---
|
||||||
|
|
||||||
|
# google_bigtable_instance
|
||||||
|
|
||||||
|
Creates a Google Bigtable instance. For more information see
|
||||||
|
[the official documentation](https://cloud.google.com/bigtable/) and
|
||||||
|
[API](https://cloud.google.com/bigtable/docs/go/reference).
|
||||||
|
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "google_bigtable_instance" "instance" {
|
||||||
|
name = "tf-instance"
|
||||||
|
cluster_id = "tf-instance-cluster"
|
||||||
|
zone = "us-central1-b"
|
||||||
|
num_nodes = 3
|
||||||
|
storage_type = "HDD"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The name of the Bigtable instance.
|
||||||
|
|
||||||
|
* `cluster_id` - (Required) The name of the Bigtable instance's cluster.
|
||||||
|
|
||||||
|
* `zone` - (Required) The zone to create the Bigtable instance in. Zones that support Bigtable instances are noted on the [Cloud Locations page](https://cloud.google.com/about/locations/).
|
||||||
|
|
||||||
|
* `num_nodes` - (Optional) The number of nodes in your Bigtable instance. Minimum of `3`. Defaults to `3`.
|
||||||
|
|
||||||
|
* `storage_type` - (Optional) The storage type to use. One of `"SSD"` or `"HDD"`. Defaults to `SSD`.
|
||||||
|
|
||||||
|
* `project` - (Optional) The project in which the resource belongs. If it
|
||||||
|
is not provided, the provider project is used.
|
||||||
|
|
||||||
|
* `display_name` - (Optional) The human-readable display name of the Bigtable instance. Defaults to the instance `name`.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
Only the arguments listed above are exposed as attributes.
|
49
website/docs/r/bigtable_table.html.markdown
Normal file
49
website/docs/r/bigtable_table.html.markdown
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
layout: "google"
|
||||||
|
page_title: "Google: google_bigtable_table"
|
||||||
|
sidebar_current: "docs-google-bigtable-table"
|
||||||
|
description: |-
|
||||||
|
Creates a Google Bigtable table inside an instance.
|
||||||
|
---
|
||||||
|
|
||||||
|
# google_bigtable_table
|
||||||
|
|
||||||
|
Creates a Google Bigtable table inside an instance. For more information see
|
||||||
|
[the official documentation](https://cloud.google.com/bigtable/) and
|
||||||
|
[API](https://cloud.google.com/bigtable/docs/go/reference).
|
||||||
|
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "google_bigtable_instance" "instance" {
|
||||||
|
name = "tf-instance"
|
||||||
|
cluster_id = "tf-instance-cluster"
|
||||||
|
zone = "us-central1-b"
|
||||||
|
num_nodes = 3
|
||||||
|
storage_type = "HDD"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_bigtable_table" "table" {
|
||||||
|
name = "tf-table"
|
||||||
|
instance_name = "${google_bigtable_instance.instance.name}"
|
||||||
|
split_keys = ["a", "b", "c"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The name of the table.
|
||||||
|
|
||||||
|
* `instance_name` - (Required) The name of the Bigtable instance.
|
||||||
|
|
||||||
|
* `split_keys` - (Optional) A list of predefined keys to split the table on.
|
||||||
|
|
||||||
|
* `project` - (Optional) The project in which the resource belongs. If it
|
||||||
|
is not provided, the provider project is used.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
Only the arguments listed above are exposed as attributes.
|
@ -10,17 +10,6 @@
|
|||||||
<a href="/docs/providers/google/index.html">Google Provider</a>
|
<a href="/docs/providers/google/index.html">Google Provider</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-google-bigquery") %>>
|
|
||||||
<a href="#">Google BigQuery Resources</a>
|
|
||||||
<ul class="nav nav-visible">
|
|
||||||
<li<%= sidebar_current("docs-google-bigquery-dataset") %>>
|
|
||||||
<a href="/docs/providers/google/r/bigquery_dataset.html">google_bigquery_dataset</a>
|
|
||||||
<li<%= sidebar_current("docs-google-bigquery-table") %>>
|
|
||||||
<a href="/docs/providers/google/r/bigquery_table.html">google_bigquery_table</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-google-datasource") %>>
|
<li<%= sidebar_current("docs-google-datasource") %>>
|
||||||
<a href="#">Google Cloud Platform Data Sources</a>
|
<a href="#">Google Cloud Platform Data Sources</a>
|
||||||
<ul class="nav nav-visible">
|
<ul class="nav nav-visible">
|
||||||
@ -45,6 +34,28 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-google-bigquery") %>>
|
||||||
|
<a href="#">Google BigQuery Resources</a>
|
||||||
|
<ul class="nav nav-visible">
|
||||||
|
<li<%= sidebar_current("docs-google-bigquery-dataset") %>>
|
||||||
|
<a href="/docs/providers/google/r/bigquery_dataset.html">google_bigquery_dataset</a>
|
||||||
|
<li<%= sidebar_current("docs-google-bigquery-table") %>>
|
||||||
|
<a href="/docs/providers/google/r/bigquery_table.html">google_bigquery_table</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-google-bigtable") %>>
|
||||||
|
<a href="#">Google Bigtable Resources</a>
|
||||||
|
<ul class="nav nav-visible">
|
||||||
|
<li<%= sidebar_current("docs-google-bigtable-instance") %>>
|
||||||
|
<a href="/docs/providers/google/r/bigtable_instance.html">google_bigtable_instance</a>
|
||||||
|
<li<%= sidebar_current("docs-google-bigtable-table") %>>
|
||||||
|
<a href="/docs/providers/google/r/bigtable_table.html">google_bigtable_table</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-google-(project|service)") %>>
|
<li<%= sidebar_current("docs-google-(project|service)") %>>
|
||||||
<a href="#">Google Cloud Platform Resources</a>
|
<a href="#">Google Cloud Platform Resources</a>
|
||||||
<ul class="nav nav-visible">
|
<ul class="nav nav-visible">
|
||||||
|
Loading…
Reference in New Issue
Block a user