mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-01 16:21:06 +00:00
Bigtable instance support.
This commit is contained in:
parent
dae866228e
commit
53b91630f5
22
google/client_factory_bigtable.go
Normal file
22
google/client_factory_bigtable.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 ClientFactoryBigtable struct {
|
||||
UserAgent string
|
||||
TokenSource oauth2.TokenSource
|
||||
}
|
||||
|
||||
func (s *ClientFactoryBigtable) NewInstanceAdminClient(project string) (*bigtable.InstanceAdminClient, error) {
|
||||
return bigtable.NewInstanceAdminClient(context.Background(), project, option.WithTokenSource(s.TokenSource), option.WithUserAgent(s.UserAgent))
|
||||
}
|
||||
|
||||
func (s *ClientFactoryBigtable) 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
|
||||
|
||||
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
|
||||
|
||||
clientFactoryBigtable *ClientFactoryBigtable
|
||||
}
|
||||
|
||||
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)
|
||||
@ -87,6 +92,7 @@ func (c *Config) loadAndValidate() error {
|
||||
// your service account.
|
||||
client = conf.Client(oauth2.NoContext)
|
||||
|
||||
tokenSource = conf.TokenSource(context.Background())
|
||||
} else {
|
||||
log.Printf("[INFO] Authenticating using DefaultClient")
|
||||
err := error(nil)
|
||||
@ -94,6 +100,11 @@ func (c *Config) loadAndValidate() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tokenSource, err = google.DefaultTokenSource(oauth2.NoContext, clientScopes...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
client.Transport = logging.NewTransport("Google", client.Transport)
|
||||
@ -181,6 +192,12 @@ func (c *Config) loadAndValidate() error {
|
||||
}
|
||||
c.clientBigQuery.UserAgent = userAgent
|
||||
|
||||
log.Printf("[INFO] Instantiating Google Cloud Bigtable Client Factory...")
|
||||
c.clientFactoryBigtable = &ClientFactoryBigtable{
|
||||
UserAgent: userAgent,
|
||||
TokenSource: tokenSource,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,7 @@ func Provider() terraform.ResourceProvider {
|
||||
ResourcesMap: map[string]*schema.Resource{
|
||||
"google_bigquery_dataset": resourceBigQueryDataset(),
|
||||
"google_bigquery_table": resourceBigQueryTable(),
|
||||
"google_bigtable_instance": resourceBigtableInstance(),
|
||||
"google_compute_autoscaler": resourceComputeAutoscaler(),
|
||||
"google_compute_address": resourceComputeAddress(),
|
||||
"google_compute_backend_bucket": resourceComputeBackendBucket(),
|
||||
|
188
google/resource_bigtable_instance.go
Normal file
188
google/resource_bigtable_instance.go
Normal file
@ -0,0 +1,188 @@
|
||||
package google
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"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,
|
||||
},
|
||||
|
||||
"display_name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"cluster_id": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"num_nodes": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
// 30 is the maximum number of nodes without a quota increase.
|
||||
ValidateFunc: validation.IntBetween(3, 30),
|
||||
},
|
||||
|
||||
"storage_type": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validation.StringInSlice([]string{"SSD", "HDD"}, false),
|
||||
},
|
||||
|
||||
"zone": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"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
|
||||
}
|
||||
|
||||
clusterId := d.Get("cluster_id").(string)
|
||||
numNodes := int32(d.Get("num_nodes").(int))
|
||||
zone := d.Get("zone").(string)
|
||||
|
||||
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: clusterId,
|
||||
NumNodes: numNodes,
|
||||
StorageType: storageType,
|
||||
Zone: zone,
|
||||
}
|
||||
|
||||
c, err := config.clientFactoryBigtable.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.clientFactoryBigtable.NewInstanceAdminClient(project)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||
}
|
||||
|
||||
defer c.Close()
|
||||
|
||||
name := d.Id()
|
||||
instances, err := c.Instances(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving instances. %s", err)
|
||||
}
|
||||
|
||||
var instanceInfo *bigtable.InstanceInfo
|
||||
found := false
|
||||
for _, i := range instances {
|
||||
if i.Name == name {
|
||||
instanceInfo = i
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("Error retrieving instance. Could not find %s.", name)
|
||||
}
|
||||
|
||||
d.Set("name", instanceInfo.Name)
|
||||
d.Set("display_name", instanceInfo.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.clientFactoryBigtable.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
|
||||
}
|
118
google/resource_bigtable_instance_test.go
Normal file
118
google/resource_bigtable_instance_test.go
Normal file
@ -0,0 +1,118 @@
|
||||
package google
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"context"
|
||||
"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.clientFactoryBigtable.NewInstanceAdminClient(config.Project)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||
}
|
||||
|
||||
instances, err := c.Instances(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving instances. %s", err)
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, i := range instances {
|
||||
if i.Name == rs.Primary.Attributes["name"] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
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.clientFactoryBigtable.NewInstanceAdminClient(config.Project)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error starting instance admin client. %s", err)
|
||||
}
|
||||
|
||||
instances, err := c.Instances(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving instances. %s", err)
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, i := range instances {
|
||||
if i.Name == rs.Primary.Attributes["name"] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
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)
|
||||
}
|
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. Note: Many zones do not support Bigtable instances.
|
||||
|
||||
* `num_nodes` - (Required) The number of nodes in your Bigtable instance. Minimum of 3.
|
||||
|
||||
* `storage_type` - (Required) The storage type to use. One of `"SSD"` or `"HDD"`.
|
||||
|
||||
* `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.
|
Loading…
Reference in New Issue
Block a user