diff --git a/google/bigtable_client_factory.go b/google/bigtable_client_factory.go new file mode 100644 index 00000000..7fe1a9ac --- /dev/null +++ b/google/bigtable_client_factory.go @@ -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)) +} diff --git a/google/config.go b/google/config.go index 71629644..0e382f14 100644 --- a/google/config.go +++ b/google/config.go @@ -1,6 +1,7 @@ package google import ( + "context" "encoding/json" "fmt" "log" @@ -11,6 +12,7 @@ import ( "github.com/hashicorp/terraform/helper/logging" "github.com/hashicorp/terraform/helper/pathorcontents" "github.com/hashicorp/terraform/terraform" + "golang.org/x/oauth2" "golang.org/x/oauth2/google" "golang.org/x/oauth2/jwt" @@ -45,6 +47,8 @@ type Config struct { clientIAM *iam.Service clientServiceMan *servicemanagement.APIService clientBigQuery *bigquery.Service + + bigtableClientFactory *BigtableClientFactory } func (c *Config) loadAndValidate() error { @@ -57,6 +61,7 @@ func (c *Config) loadAndValidate() error { } var client *http.Client + var tokenSource oauth2.TokenSource if 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 // authorized and authenticated on the behalf of // your service account. - client = conf.Client(oauth2.NoContext) + client = conf.Client(context.Background()) + tokenSource = conf.TokenSource(context.Background()) } else { log.Printf("[INFO] Authenticating using DefaultClient") 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 { return err } @@ -181,6 +192,11 @@ func (c *Config) loadAndValidate() error { } c.clientBigQuery.UserAgent = userAgent + c.bigtableClientFactory = &BigtableClientFactory{ + UserAgent: userAgent, + TokenSource: tokenSource, + } + return nil } diff --git a/google/provider.go b/google/provider.go index 94e76d08..5bff44c8 100644 --- a/google/provider.go +++ b/google/provider.go @@ -64,6 +64,8 @@ func Provider() terraform.ResourceProvider { ResourcesMap: map[string]*schema.Resource{ "google_bigquery_dataset": resourceBigQueryDataset(), "google_bigquery_table": resourceBigQueryTable(), + "google_bigtable_instance": resourceBigtableInstance(), + "google_bigtable_table": resourceBigtableTable(), "google_compute_autoscaler": resourceComputeAutoscaler(), "google_compute_address": resourceComputeAddress(), "google_compute_backend_bucket": resourceComputeBackendBucket(), diff --git a/google/resource_bigtable_instance.go b/google/resource_bigtable_instance.go new file mode 100644 index 00000000..5af20c46 --- /dev/null +++ b/google/resource_bigtable_instance.go @@ -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 + } +} diff --git a/google/resource_bigtable_instance_test.go b/google/resource_bigtable_instance_test.go new file mode 100644 index 00000000..4ada449e --- /dev/null +++ b/google/resource_bigtable_instance_test.go @@ -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) +} diff --git a/google/resource_bigtable_table.go b/google/resource_bigtable_table.go new file mode 100644 index 00000000..819204d1 --- /dev/null +++ b/google/resource_bigtable_table.go @@ -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 +} diff --git a/google/resource_bigtable_table_test.go b/google/resource_bigtable_table_test.go new file mode 100644 index 00000000..ff79ff98 --- /dev/null +++ b/google/resource_bigtable_table_test.go @@ -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) +} diff --git a/vendor/cloud.google.com/go/bigtable/admin.go b/vendor/cloud.google.com/go/bigtable/admin.go index 4838d350..a1f5f01c 100644 --- a/vendor/cloud.google.com/go/bigtable/admin.go +++ b/vendor/cloud.google.com/go/bigtable/admin.go @@ -369,3 +369,24 @@ func (iac *InstanceAdminClient) Instances(ctx context.Context) ([]*InstanceInfo, } 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 +} diff --git a/vendor/cloud.google.com/go/bigtable/bigtable.go b/vendor/cloud.google.com/go/bigtable/bigtable.go index 5c2129cb..316e3d3c 100644 --- a/vendor/cloud.google.com/go/bigtable/bigtable.go +++ b/vendor/cloud.google.com/go/bigtable/bigtable.go @@ -73,7 +73,7 @@ func (c *Client) Close() error { } 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) retryOptions = []gax.CallOption{ gax.WithDelayTimeoutSettings(100*time.Millisecond, 2000*time.Millisecond, 1.2), diff --git a/vendor/cloud.google.com/go/bigtable/filter.go b/vendor/cloud.google.com/go/bigtable/filter.go index fb85498c..a1cf748a 100644 --- a/vendor/cloud.google.com/go/bigtable/filter.go +++ b/vendor/cloud.google.com/go/bigtable/filter.go @@ -154,7 +154,7 @@ func (stripValueFilter) proto() *btpb.RowFilter { 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. // The timestamp will be truncated to millisecond granularity. func TimestampRangeFilter(startTime time.Time, endTime time.Time) Filter { @@ -168,7 +168,7 @@ func TimestampRangeFilter(startTime time.Time, endTime time.Time) Filter { 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. // The timestamp will be truncated to millisecond granularity. func TimestampRangeFilterMicros(startTime Timestamp, endTime Timestamp) Filter { @@ -187,10 +187,10 @@ func (trf timestampRangeFilter) String() string { func (trf timestampRangeFilter) proto() *btpb.RowFilter { return &btpb.RowFilter{ Filter: &btpb.RowFilter_TimestampRangeFilter{ - &btpb.TimestampRange{ - int64(trf.startTime.TruncateToMilliseconds()), - int64(trf.endTime.TruncateToMilliseconds()), - }, + &btpb.TimestampRange{ + int64(trf.startTime.TruncateToMilliseconds()), + int64(trf.endTime.TruncateToMilliseconds()), + }, }} } @@ -228,8 +228,8 @@ func ValueRangeFilter(start, end []byte) Filter { } type valueRangeFilter struct { - start []byte - end []byte + start []byte + end []byte } func (vrf valueRangeFilter) String() string { @@ -260,8 +260,8 @@ func ConditionFilter(predicateFilter, trueFilter, falseFilter Filter) Filter { type conditionFilter struct { predicateFilter Filter - trueFilter Filter - falseFilter Filter + trueFilter Filter + falseFilter Filter } func (cf conditionFilter) String() string { @@ -282,7 +282,7 @@ func (cf conditionFilter) proto() *btpb.RowFilter { cf.predicateFilter.proto(), tf, ff, - }}} + }}} } // TODO(dsymonds): More filters: sampling diff --git a/vendor/vendor.json b/vendor/vendor.json index 7be32401..546d75fb 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -3,10 +3,10 @@ "ignore": "appengine test github.com/hashicorp/nomad/", "package": [ { - "checksumSHA1": "fEobtlzPZ57VXi864qMmblI2gsA=", + "checksumSHA1": "NrTYYg3++pBxH1Z8xjVg6ssQTYY=", "path": "cloud.google.com/go/bigtable", - "revision": "69931d826ffbbcb4f8451b42d5cf7fc2ac6c7443", - "revisionTime": "2017-06-09T14:31:37Z" + "revision": "f6bedb5a8dbce75418580cedf5c2434c78d06cfa", + "revisionTime": "2017-06-27T21:12:08Z" }, { "checksumSHA1": "B1HkIrBavSgy6ntVyGr/eNUy44I=", diff --git a/website/docs/r/bigtable_instance.html.markdown b/website/docs/r/bigtable_instance.html.markdown new file mode 100644 index 00000000..43cc1b4c --- /dev/null +++ b/website/docs/r/bigtable_instance.html.markdown @@ -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. diff --git a/website/docs/r/bigtable_table.html.markdown b/website/docs/r/bigtable_table.html.markdown new file mode 100644 index 00000000..2a2a0945 --- /dev/null +++ b/website/docs/r/bigtable_table.html.markdown @@ -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. diff --git a/website/google.erb b/website/google.erb index 71f952da..42ad6aee 100644 --- a/website/google.erb +++ b/website/google.erb @@ -10,17 +10,6 @@ Google Provider - > - Google BigQuery Resources - - - > Google Cloud Platform Data Sources + > + Google BigQuery Resources + + + + > + Google Bigtable Resources + + + > Google Cloud Platform Resources