diff --git a/mmv1/third_party/terraform/services/bigtable/iam_bigtable_instance.go b/mmv1/third_party/terraform/services/bigtable/iam_bigtable_instance.go index 6d084a9b75a8..9e7f93efc6cb 100644 --- a/mmv1/third_party/terraform/services/bigtable/iam_bigtable_instance.go +++ b/mmv1/third_party/terraform/services/bigtable/iam_bigtable_instance.go @@ -71,8 +71,11 @@ func BigtableInstanceIdParseFunc(d *schema.ResourceData, config *transport_tpg.C } func (u *BigtableInstanceIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) { - req := &bigtableadmin.GetIamPolicyRequest{} - + req := &bigtableadmin.GetIamPolicyRequest{ + Options: &bigtableadmin.GetPolicyOptions{ + RequestedPolicyVersion: tpgiamresource.IamPolicyVersion, + }, + } userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent) if err != nil { return nil, err diff --git a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_iam_test.go b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_iam_test.go index 8e2b4b331ca4..0d8ec23e5b9f 100644 --- a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_iam_test.go +++ b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance_iam_test.go @@ -2,6 +2,7 @@ package bigtable_test import ( "fmt" + "strconv" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -14,13 +15,17 @@ func TestAccBigtableInstanceIamBinding(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() - instance := "tf-bigtable-iam-" + acctest.RandString(t, 10) - cluster := "c-" + acctest.RandString(t, 10) - account := "tf-bigtable-iam-" + acctest.RandString(t, 10) - role := "roles/bigtable.user" + randomString := acctest.RandString(t, 10) + + context := map[string]interface{}{ + "instance": "tf-bigtable-iam-" + randomString, + "cluster": "c-" + randomString, + "account": "tf-bigtable-iam-" + randomString, + "role": "roles/bigtable.user", + } importId := fmt.Sprintf("projects/%s/instances/%s %s", - envvar.GetTestProjectFromEnv(), instance, role) + envvar.GetTestProjectFromEnv(), context["instance"].(string), context["role"].(string)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -28,10 +33,10 @@ func TestAccBigtableInstanceIamBinding(t *testing.T) { Steps: []resource.TestStep{ { // Test IAM Binding creation - Config: testAccBigtableInstanceIamBinding_basic(instance, cluster, account, role), + Config: testAccBigtableInstanceIamBinding_basic(context), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "google_bigtable_instance_iam_binding.binding", "role", role), + "google_bigtable_instance_iam_binding.binding", "role", context["role"].(string)), ), }, { @@ -42,7 +47,7 @@ func TestAccBigtableInstanceIamBinding(t *testing.T) { }, { // Test IAM Binding update - Config: testAccBigtableInstanceIamBinding_update(instance, cluster, account, role), + Config: testAccBigtableInstanceIamBinding_update(context), }, { ResourceName: "google_bigtable_instance_iam_binding.binding", @@ -59,16 +64,20 @@ func TestAccBigtableInstanceIamMember(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() - instance := "tf-bigtable-iam-" + acctest.RandString(t, 10) - cluster := "c-" + acctest.RandString(t, 10) - account := "tf-bigtable-iam-" + acctest.RandString(t, 10) - role := "roles/bigtable.user" + randomString := acctest.RandString(t, 10) + + context := map[string]interface{}{ + "instance": "tf-bigtable-iam-" + randomString, + "cluster": "c-" + randomString, + "account": "tf-bigtable-iam-" + randomString, + "role": "roles/bigtable.user", + } importId := fmt.Sprintf("projects/%s/instances/%s %s serviceAccount:%s", envvar.GetTestProjectFromEnv(), - instance, - role, - envvar.ServiceAccountCanonicalEmail(account)) + context["instance"].(string), + context["role"].(string), + envvar.ServiceAccountCanonicalEmail(context["account"].(string))) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -76,12 +85,12 @@ func TestAccBigtableInstanceIamMember(t *testing.T) { Steps: []resource.TestStep{ { // Test IAM Binding creation - Config: testAccBigtableInstanceIamMember(instance, cluster, account, role), + Config: testAccBigtableInstanceIamMember(context), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( - "google_bigtable_instance_iam_member.member", "role", role), + "google_bigtable_instance_iam_member.member", "role", context["role"].(string)), resource.TestCheckResourceAttr( - "google_bigtable_instance_iam_member.member", "member", "serviceAccount:"+envvar.ServiceAccountCanonicalEmail(account)), + "google_bigtable_instance_iam_member.member", "member", "serviceAccount:"+envvar.ServiceAccountCanonicalEmail(context["account"].(string))), ), }, { @@ -99,13 +108,17 @@ func TestAccBigtableInstanceIamPolicy(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() - instance := "tf-bigtable-iam-" + acctest.RandString(t, 10) - cluster := "c-" + acctest.RandString(t, 10) - account := "tf-bigtable-iam-" + acctest.RandString(t, 10) - role := "roles/bigtable.user" + randomString := acctest.RandString(t, 10) + + context := map[string]interface{}{ + "instance": "tf-bigtable-iam-" + randomString, + "cluster": "c-" + randomString, + "account": "tf-bigtable-iam-" + randomString, + "role": "roles/bigtable.user", + } importId := fmt.Sprintf("projects/%s/instances/%s", - envvar.GetTestProjectFromEnv(), instance) + envvar.GetTestProjectFromEnv(), context["instance"].(string)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -113,7 +126,7 @@ func TestAccBigtableInstanceIamPolicy(t *testing.T) { Steps: []resource.TestStep{ { // Test IAM Binding creation - Config: testAccBigtableInstanceIamPolicy(instance, cluster, account, role), + Config: testAccBigtableInstanceIamPolicy(context), Check: resource.TestCheckResourceAttrSet("data.google_bigtable_instance_iam_policy.policy", "policy_data"), }, { @@ -126,76 +139,258 @@ func TestAccBigtableInstanceIamPolicy(t *testing.T) { }) } -func testAccBigtableInstanceIamBinding_basic(instance, cluster, account, role string) string { - return fmt.Sprintf(testBigtableInstanceIam+` +func TestAccBigtableInstanceIamBinding_withCondition(t *testing.T) { + // bigtable instance does not use the shared HTTP client, this test creates an instance + acctest.SkipIfVcr(t) + t.Parallel() + + randomString := acctest.RandString(t, 10) + conditionExpression := "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + context := map[string]interface{}{ + "instance": "tf-bigtable-iam-" + randomString, + "cluster": "c-" + randomString, + "account": "tf-bigtable-iam-" + randomString, + "role": "roles/bigtable.user", + "condition_title": "expires_after_2019_12_31", + "condition_expr": strconv.Quote(conditionExpression), + "condition_desc": "Expiring at midnight of 2019-12-31", + } + + importIdWithCondition := fmt.Sprintf("projects/%s/instances/%s %s %s", + envvar.GetTestProjectFromEnv(), + context["instance"].(string), + context["role"].(string), + context["condition_title"].(string), + ) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBigtableInstanceIamBinding_withCondition(context), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_bigtable_instance_iam_binding.binding", "condition.#", "1"), + resource.TestCheckResourceAttr("google_bigtable_instance_iam_binding.binding", "condition.0.title", context["condition_title"].(string)), + resource.TestCheckResourceAttr("google_bigtable_instance_iam_binding.binding", "condition.0.expression", conditionExpression), + resource.TestCheckResourceAttr("google_bigtable_instance_iam_binding.binding", "condition.0.description", context["condition_desc"].(string)), + ), + }, + { + ResourceName: "google_bigtable_instance_iam_binding.binding", + ImportStateId: importIdWithCondition, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBigtableInstanceIamMember_withCondition(t *testing.T) { + // bigtable instance does not use the shared HTTP client, this test creates an instance + acctest.SkipIfVcr(t) + t.Parallel() + + randomString := acctest.RandString(t, 10) + + conditionExpression := "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + context := map[string]interface{}{ + "instance": "tf-bigtable-iam-" + randomString, + "cluster": "c-" + randomString, + "account": "tf-bigtable-iam-" + randomString, + "role": "roles/bigtable.user", + "condition_title": "expires_after_2019_12_31", + "condition_expr": strconv.Quote(conditionExpression), + "condition_desc": "Expiring at midnight of 2019-12-31", + } + + importIdWithCondition := fmt.Sprintf("projects/%s/instances/%s %s serviceAccount:%s %s", + envvar.GetTestProjectFromEnv(), + context["instance"].(string), + context["role"].(string), + envvar.ServiceAccountCanonicalEmail(context["account"].(string)), + context["condition_title"].(string), + ) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + // Test IAM Binding creation + Config: testAccBigtableInstanceIamMember_withCondition(context), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_bigtable_instance_iam_member.member", "condition.#", "1"), + resource.TestCheckResourceAttr("google_bigtable_instance_iam_member.member", "condition.0.title", context["condition_title"].(string)), + resource.TestCheckResourceAttr("google_bigtable_instance_iam_member.member", "condition.0.expression", conditionExpression), + resource.TestCheckResourceAttr("google_bigtable_instance_iam_member.member", "condition.0.description", context["condition_desc"].(string)), + ), + }, + { + ResourceName: "google_bigtable_instance_iam_member.member", + ImportStateId: importIdWithCondition, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBigtableInstanceIamPolicy_withCondition(t *testing.T) { + // bigtable instance does not use the shared HTTP client, this test creates an instance + acctest.SkipIfVcr(t) + t.Parallel() + + randomString := acctest.RandString(t, 10) + conditionExpression := "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + context := map[string]interface{}{ + "instance": "tf-bigtable-iam-" + randomString, + "cluster": "c-" + randomString, + "account": "tf-bigtable-iam-" + randomString, + "role": "roles/bigtable.user", + "condition_title": "expires_after_2019_12_31", + "condition_expr": strconv.Quote(conditionExpression), + "condition_desc": "Expiring at midnight of 2019-12-31", + } + + importId := fmt.Sprintf("projects/%s/instances/%s", + envvar.GetTestProjectFromEnv(), context["instance"].(string)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + // Test IAM Binding creation + Config: testAccBigtableInstanceIamPolicy_withCondition(context), + }, + { + ResourceName: "google_bigtable_instance_iam_policy.policy", + ImportStateId: importId, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccBigtableInstanceIamBinding_basic(context map[string]interface{}) string { + return testBigtableInstanceConfig(context) + acctest.Nprintf(` resource "google_service_account" "test-account1" { - account_id = "%s-1" + account_id = "%{account}-1" display_name = "Bigtable Instance IAM Testing Account" } resource "google_service_account" "test-account2" { - account_id = "%s-2" + account_id = "%{account}-2" display_name = "Bigtable instance Iam Testing Account" } resource "google_bigtable_instance_iam_binding" "binding" { instance = google_bigtable_instance.instance.name - role = "%s" + role = "%{role}" members = [ "serviceAccount:${google_service_account.test-account1.email}", ] } -`, instance, cluster, account, account, role) +`, context) } -func testAccBigtableInstanceIamBinding_update(instance, cluster, account, role string) string { - return fmt.Sprintf(testBigtableInstanceIam+` +func testAccBigtableInstanceIamBinding_update(context map[string]interface{}) string { + return testBigtableInstanceConfig(context) + acctest.Nprintf(` resource "google_service_account" "test-account1" { - account_id = "%s-1" + account_id = "%{account}-1" display_name = "Bigtable Instance IAM Testing Account" } resource "google_service_account" "test-account2" { - account_id = "%s-2" + account_id = "%{account}-2" display_name = "Bigtable Instance IAM Testing Account" } resource "google_bigtable_instance_iam_binding" "binding" { instance = google_bigtable_instance.instance.name - role = "%s" + role = "%{role}" members = [ "serviceAccount:${google_service_account.test-account1.email}", "serviceAccount:${google_service_account.test-account2.email}", ] } -`, instance, cluster, account, account, role) +`, context) +} + +func testAccBigtableInstanceIamBinding_withCondition(context map[string]interface{}) string { + return testBigtableInstanceConfig(context) + acctest.Nprintf(` +resource "google_service_account" "test-account1" { + account_id = "%{account}-1" + display_name = "Bigtable Instance IAM Testing Account" +} + +resource "google_service_account" "test-account2" { + account_id = "%{account}-2" + display_name = "Bigtable instance Iam Testing Account" +} + +resource "google_bigtable_instance_iam_binding" "binding" { + instance = google_bigtable_instance.instance.name + role = "%{role}" + members = [ + "serviceAccount:${google_service_account.test-account1.email}", + ] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = %{condition_expr} + } +} +`, context) +} + +func testAccBigtableInstanceIamMember(context map[string]interface{}) string { + return testBigtableInstanceConfig(context) + acctest.Nprintf(` +resource "google_service_account" "test-account" { + account_id = "%{account}" + display_name = "Bigtable Instance IAM Testing Account" +} + +resource "google_bigtable_instance_iam_member" "member" { + instance = google_bigtable_instance.instance.name + role = "%{role}" + member = "serviceAccount:${google_service_account.test-account.email}" +} +`, context) } -func testAccBigtableInstanceIamMember(instance, cluster, account, role string) string { - return fmt.Sprintf(testBigtableInstanceIam+` +func testAccBigtableInstanceIamMember_withCondition(context map[string]interface{}) string { + return testBigtableInstanceConfig(context) + acctest.Nprintf(` resource "google_service_account" "test-account" { - account_id = "%s" + account_id = "%{account}" display_name = "Bigtable Instance IAM Testing Account" } resource "google_bigtable_instance_iam_member" "member" { instance = google_bigtable_instance.instance.name - role = "%s" + role = "%{role}" member = "serviceAccount:${google_service_account.test-account.email}" + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = %{condition_expr} + } } -`, instance, cluster, account, role) +`, context) } -func testAccBigtableInstanceIamPolicy(instance, cluster, account, role string) string { - return fmt.Sprintf(testBigtableInstanceIam+` +func testAccBigtableInstanceIamPolicy(context map[string]interface{}) string { + return testBigtableInstanceConfig(context) + acctest.Nprintf(` resource "google_service_account" "test-account" { - account_id = "%s" + account_id = "%{account}" display_name = "Bigtable Instance IAM Testing Account" } data "google_iam_policy" "policy" { binding { - role = "%s" + role = "%{role}" members = ["serviceAccount:${google_service_account.test-account.email}"] } } @@ -208,21 +403,53 @@ resource "google_bigtable_instance_iam_policy" "policy" { data "google_bigtable_instance_iam_policy" "policy" { instance = google_bigtable_instance.instance.name } -`, instance, cluster, account, role) +`, context) +} + +func testAccBigtableInstanceIamPolicy_withCondition(context map[string]interface{}) string { + return testBigtableInstanceConfig(context) + acctest.Nprintf(` +resource "google_service_account" "test-account" { + account_id = "%{account}" + display_name = "Bigtable Instance IAM Testing Account" +} + +data "google_iam_policy" "policy" { + binding { + role = "%{role}" + members = ["serviceAccount:${google_service_account.test-account.email}"] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = %{condition_expr} + } + } +} + +resource "google_bigtable_instance_iam_policy" "policy" { + instance = google_bigtable_instance.instance.name + policy_data = data.google_iam_policy.policy.policy_data +} + +data "google_bigtable_instance_iam_policy" "policy" { + instance = google_bigtable_instance.instance.name +} +`, context) } // Smallest instance possible for testing -var testBigtableInstanceIam = ` +func testBigtableInstanceConfig(context map[string]interface{}) string { + return acctest.Nprintf(` resource "google_bigtable_instance" "instance" { - name = "%s" + name = "%{instance}" instance_type = "DEVELOPMENT" cluster { - cluster_id = "%s" + cluster_id = "%{cluster}" zone = "us-central1-b" storage_type = "HDD" } deletion_protection = false } -` +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/r/bigtable_instance_iam.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigtable_instance_iam.html.markdown index 17a16b9f22e6..31b63d392eda 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigtable_instance_iam.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigtable_instance_iam.html.markdown @@ -61,6 +61,9 @@ resource "google_bigtable_instance_iam_member" "editor" { The following arguments are supported: +* `project` - (Optional) The project in which the instance belongs. If it + is not provided, Terraform will use the provider default. + * `instance` - (Required) The name or relative resource id of the instance to manage IAM policies for. For `google_bigtable_instance_iam_member` or `google_bigtable_instance_iam_binding`: @@ -78,13 +81,19 @@ For `google_bigtable_instance_iam_member` or `google_bigtable_instance_iam_bindi `google_bigtable_instance_iam_binding` can be used per role. Note that custom roles must be of the format `[projects|organizations]/{parent-name}/roles/{role-name}`. Read more about roles [here](https://cloud.google.com/bigtable/docs/access-control#roles). -`google_bigtable_instance_iam_policy` only: -* `policy_data` - (Required) The policy data generated by a `google_iam_policy` data source. +* `condition` - (Optional) An [IAM Condition](https://cloud.google.com/iam/docs/conditions-overview) for a given binding. Structure is [documented below](#nested_condition). -- - - +The `condition` block supports: + +* `expression` - (Required) Textual representation of an expression in Common Expression Language syntax. + +* `title` - (Required) A title for the expression, i.e. a short string describing its purpose. + +* `description` - (Optional) An optional description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + +For `google_bigtable_instance_iam_policy` only: +* `policy_data` - (Required) The policy data generated by a `google_iam_policy` data source. -* `project` - (Optional) The project in which the instance belongs. If it - is not provided, Terraform will use the provider default. ## Attributes Reference