Skip to content

Commit

Permalink
add ability to update Bigtable instance cluster node count
Browse files Browse the repository at this point in the history
  • Loading branch information
mackenziestarr committed Aug 7, 2019
1 parent 076e0c3 commit 01ce85c
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 26 deletions.
59 changes: 51 additions & 8 deletions google/resource_bigtable_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func resourceBigtableInstance() *schema.Resource {
return &schema.Resource{
Create: resourceBigtableInstanceCreate,
Read: resourceBigtableInstanceRead,
Update: resourceBigtableInstanceUpdate,
Delete: resourceBigtableInstanceDestroy,

Schema: map[string]*schema.Schema{
Expand All @@ -25,10 +26,8 @@ func resourceBigtableInstance() *schema.Resource {
},

"cluster": {
Type: schema.TypeSet,
Type: schema.TypeList,
Required: true,
ForceNew: true,
MaxItems: 4,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cluster_id": {
Expand All @@ -44,7 +43,6 @@ func resourceBigtableInstance() *schema.Resource {
"num_nodes": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
ValidateFunc: validation.IntAtLeast(3),
},
"storage_type": {
Expand All @@ -57,11 +55,9 @@ func resourceBigtableInstance() *schema.Resource {
},
},
},

"display_name": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},

Expand Down Expand Up @@ -137,7 +133,7 @@ func resourceBigtableInstanceCreate(d *schema.ResourceData, meta interface{}) er
conf.InstanceType = bigtable.PRODUCTION
}

conf.Clusters = expandBigtableClusters(d.Get("cluster").(*schema.Set).List(), conf.InstanceID)
conf.Clusters = expandBigtableClusters(d.Get("cluster").([]interface{}), conf.InstanceID)

c, err := config.bigtableClientFactory.NewInstanceAdminClient(project)
if err != nil {
Expand Down Expand Up @@ -181,7 +177,8 @@ func resourceBigtableInstanceRead(d *schema.ResourceData, meta interface{}) erro

d.Set("project", project)

clusters := d.Get("cluster").(*schema.Set).List()
clusters := d.Get("cluster").([]interface{})

clusterState := []map[string]interface{}{}
for _, cl := range clusters {
cluster := cl.(map[string]interface{})
Expand All @@ -197,6 +194,7 @@ func resourceBigtableInstanceRead(d *schema.ResourceData, meta interface{}) erro
}

err = d.Set("cluster", clusterState)

if err != nil {
return fmt.Errorf("Error setting clusters in state: %s", err.Error())
}
Expand All @@ -207,6 +205,51 @@ func resourceBigtableInstanceRead(d *schema.ResourceData, meta interface{}) erro
return nil
}

func resourceBigtableInstanceUpdate(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()

if d.Get("instance_type").(string) == "DEVELOPMENT" {
return resourceBigtableInstanceRead(d, meta)
}

clusters, err := c.Clusters(ctx, d.Get("name").(string))
if err != nil {
return fmt.Errorf("Error retrieving clusters for instance %s", err.Error())
}

clusterMap := make(map[string]*bigtable.ClusterInfo, len(clusters))
for _, cluster := range clusters {
clusterMap[cluster.Name] = cluster
}

for _, cluster := range d.Get("cluster").([]interface{}) {
config := cluster.(map[string]interface{})
cluster_id := config["cluster_id"].(string)
if cluster, ok := clusterMap[cluster_id]; ok {
if cluster.ServeNodes != config["num_nodes"].(int) {
err = c.UpdateCluster(ctx, d.Get("name").(string), cluster.Name, int32(config["num_nodes"].(int)))
if err != nil {
return fmt.Errorf("Error updating cluster %s for instance %s", cluster.Name, d.Get("name").(string))
}
}
}
}

return resourceBigtableInstanceRead(d, meta)
}

func resourceBigtableInstanceDestroy(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
ctx := context.Background()
Expand Down
29 changes: 16 additions & 13 deletions google/resource_bigtable_instance_iam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func TestAccBigtableInstanceIamBinding(t *testing.T) {
t.Parallel()

instance := "tf-bigtable-iam-" + acctest.RandString(10)
cluster := "c-" + acctest.RandString(10)
account := "tf-bigtable-iam-" + acctest.RandString(10)
role := "roles/bigtable.user"

Expand All @@ -24,7 +25,7 @@ func TestAccBigtableInstanceIamBinding(t *testing.T) {
Steps: []resource.TestStep{
{
// Test IAM Binding creation
Config: testAccBigtableInstanceIamBinding_basic(instance, account, role),
Config: testAccBigtableInstanceIamBinding_basic(instance, cluster, account, role),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"google_bigtable_instance_iam_binding.binding", "role", role),
Expand All @@ -38,7 +39,7 @@ func TestAccBigtableInstanceIamBinding(t *testing.T) {
},
{
// Test IAM Binding update
Config: testAccBigtableInstanceIamBinding_update(instance, account, role),
Config: testAccBigtableInstanceIamBinding_update(instance, cluster, account, role),
},
{
ResourceName: "google_bigtable_instance_iam_binding.binding",
Expand All @@ -54,6 +55,7 @@ func TestAccBigtableInstanceIamMember(t *testing.T) {
t.Parallel()

instance := "tf-bigtable-iam-" + acctest.RandString(10)
cluster := "c-" + acctest.RandString(10)
account := "tf-bigtable-iam-" + acctest.RandString(10)
role := "roles/bigtable.user"

Expand All @@ -69,7 +71,7 @@ func TestAccBigtableInstanceIamMember(t *testing.T) {
Steps: []resource.TestStep{
{
// Test IAM Binding creation
Config: testAccBigtableInstanceIamMember(instance, account, role),
Config: testAccBigtableInstanceIamMember(instance, cluster, account, role),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"google_bigtable_instance_iam_member.member", "role", role),
Expand All @@ -91,6 +93,7 @@ func TestAccBigtableInstanceIamPolicy(t *testing.T) {
t.Parallel()

instance := "tf-bigtable-iam-" + acctest.RandString(10)
cluster := "c-" + acctest.RandString(10)
account := "tf-bigtable-iam-" + acctest.RandString(10)
role := "roles/bigtable.user"

Expand All @@ -103,7 +106,7 @@ func TestAccBigtableInstanceIamPolicy(t *testing.T) {
Steps: []resource.TestStep{
{
// Test IAM Binding creation
Config: testAccBigtableInstanceIamPolicy(instance, account, role),
Config: testAccBigtableInstanceIamPolicy(instance, cluster, account, role),
},
{
ResourceName: "google_bigtable_instance_iam_policy.policy",
Expand All @@ -115,7 +118,7 @@ func TestAccBigtableInstanceIamPolicy(t *testing.T) {
})
}

func testAccBigtableInstanceIamBinding_basic(instance, account, role string) string {
func testAccBigtableInstanceIamBinding_basic(instance, cluster, account, role string) string {
return fmt.Sprintf(testBigtableInstanceIam+`
resource "google_service_account" "test-account1" {
Expand All @@ -135,10 +138,10 @@ resource "google_bigtable_instance_iam_binding" "binding" {
"serviceAccount:${google_service_account.test-account1.email}",
]
}
`, instance, acctest.RandString(10), account, account, role)
`, instance, cluster, account, account, role)
}

func testAccBigtableInstanceIamBinding_update(instance, account, role string) string {
func testAccBigtableInstanceIamBinding_update(instance, cluster, account, role string) string {
return fmt.Sprintf(testBigtableInstanceIam+`
resource "google_service_account" "test-account1" {
account_id = "%s-1"
Expand All @@ -158,10 +161,10 @@ resource "google_bigtable_instance_iam_binding" "binding" {
"serviceAccount:${google_service_account.test-account2.email}",
]
}
`, instance, acctest.RandString(10), account, account, role)
`, instance, cluster, account, account, role)
}

func testAccBigtableInstanceIamMember(instance, account, role string) string {
func testAccBigtableInstanceIamMember(instance, cluster, account, role string) string {
return fmt.Sprintf(testBigtableInstanceIam+`
resource "google_service_account" "test-account" {
account_id = "%s"
Expand All @@ -173,10 +176,10 @@ resource "google_bigtable_instance_iam_member" "member" {
role = "%s"
member = "serviceAccount:${google_service_account.test-account.email}"
}
`, instance, acctest.RandString(10), account, role)
`, instance, cluster, account, role)
}

func testAccBigtableInstanceIamPolicy(instance, account, role string) string {
func testAccBigtableInstanceIamPolicy(instance, cluster, account, role string) string {
return fmt.Sprintf(testBigtableInstanceIam+`
resource "google_service_account" "test-account" {
account_id = "%s"
Expand All @@ -194,7 +197,7 @@ resource "google_bigtable_instance_iam_policy" "policy" {
instance = "${google_bigtable_instance.instance.name}"
policy_data = "${data.google_iam_policy.policy.policy_data}"
}
`, instance, acctest.RandString(10), account, role)
`, instance, cluster, account, role)
}

// Smallest instance possible for testing
Expand All @@ -204,7 +207,7 @@ resource "google_bigtable_instance" "instance" {
instance_type = "DEVELOPMENT"
cluster {
cluster_id = "c-%s"
cluster_id = "%s"
zone = "us-central1-b"
storage_type = "HDD"
}
Expand Down
27 changes: 22 additions & 5 deletions google/resource_bigtable_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func TestAccBigtableInstance_basic(t *testing.T) {
Config: testAccBigtableInstance(instanceName, 3),
Check: resource.ComposeTestCheckFunc(
testAccBigtableInstanceExists(
"google_bigtable_instance.instance"),
"google_bigtable_instance.instance", 3),
),
},
{
Config: testAccBigtableInstance(instanceName, 4),
Check: resource.ComposeTestCheckFunc(
testAccBigtableInstanceExists(
"google_bigtable_instance.instance"),
"google_bigtable_instance.instance", 4),
),
},
},
Expand All @@ -57,7 +57,7 @@ func TestAccBigtableInstance_cluster(t *testing.T) {
Config: testAccBigtableInstance_cluster(instanceName),
Check: resource.ComposeTestCheckFunc(
testAccBigtableInstanceExists(
"google_bigtable_instance.instance"),
"google_bigtable_instance.instance", 3),
),
},
},
Expand All @@ -78,7 +78,7 @@ func TestAccBigtableInstance_development(t *testing.T) {
Config: testAccBigtableInstance_development(instanceName),
Check: resource.ComposeTestCheckFunc(
testAccBigtableInstanceExists(
"google_bigtable_instance.instance"),
"google_bigtable_instance.instance", 0),
),
},
},
Expand Down Expand Up @@ -109,14 +109,16 @@ func testAccCheckBigtableInstanceDestroy(s *terraform.State) error {
return nil
}

func testAccBigtableInstanceExists(n string) resource.TestCheckFunc {
func testAccBigtableInstanceExists(n string, numNodes int) 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)
}

fmt.Println(s)

if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
Expand All @@ -133,6 +135,21 @@ func testAccBigtableInstanceExists(n string) resource.TestCheckFunc {
return fmt.Errorf("Error retrieving instance %s.", rs.Primary.Attributes["name"])
}

clusters, err := c.Clusters(ctx, rs.Primary.Attributes["name"])
if err != nil {
return fmt.Errorf("Error retrieving cluster list for instance %s.", rs.Primary.Attributes["name"])
}

for _, c := range clusters {
if c.ServeNodes != numNodes {
return fmt.Errorf("Expected cluster %s to have %d nodes but got %d nodes for instance %s.",
c.Name,
numNodes,
c.ServeNodes,
rs.Primary.Attributes["name"])
}
}

return nil
}
}
Expand Down

0 comments on commit 01ce85c

Please sign in to comment.