Add 'google_folder_iam_binding' and 'google_folder_iam_member' resources (#1076)

This commit is contained in:
Kit Ewbank 2018-02-13 15:49:51 -05:00 committed by Nathan McKinley
parent 509614e404
commit 21e0075f6f
8 changed files with 678 additions and 16 deletions

View File

@ -2,11 +2,13 @@ package google
import (
"fmt"
"strings"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudresourcemanager/v1"
resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1"
"strings"
"google.golang.org/api/googleapi"
)
var IamFolderSchema = map[string]*schema.Schema{
@ -35,19 +37,7 @@ func FolderIdParseFunc(d *schema.ResourceData, _ *Config) error {
}
func (u *FolderIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
p, err := u.Config.clientResourceManagerV2Beta1.Folders.GetIamPolicy(u.folderId,
&resourceManagerV2Beta1.GetIamPolicyRequest{}).Do()
if err != nil {
return nil, fmt.Errorf("Error retrieving IAM policy for %s: %s", u.DescribeResource(), err)
}
v1Policy, err := v2BetaPolicyToV1(p)
if err != nil {
return nil, err
}
return v1Policy, nil
return getFolderIamPolicyByFolderName(u.folderId, u.Config)
}
func (u *FolderIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
@ -105,3 +95,42 @@ func v2BetaPolicyToV1(in *resourceManagerV2Beta1.Policy) (*cloudresourcemanager.
}
return out, nil
}
// Retrieve the existing IAM Policy for a folder
func getFolderIamPolicyByFolderName(folderName string, config *Config) (*cloudresourcemanager.Policy, error) {
p, err := config.clientResourceManagerV2Beta1.Folders.GetIamPolicy(folderName,
&resourceManagerV2Beta1.GetIamPolicyRequest{}).Do()
if err != nil {
return nil, fmt.Errorf("Error retrieving IAM policy for folder %q: %s", folderName, err)
}
v1Policy, err := v2BetaPolicyToV1(p)
if err != nil {
return nil, err
}
return v1Policy, nil
}
func getFolderIamPolicyByParentAndDisplayName(parent, displayName string, config *Config) (*cloudresourcemanager.Policy, error) {
queryString := fmt.Sprintf("lifecycleState=ACTIVE AND parent=%s AND displayName=%s", parent, displayName)
searchRequest := &resourceManagerV2Beta1.SearchFoldersRequest{
Query: queryString,
}
searchResponse, err := config.clientResourceManagerV2Beta1.Folders.Search(searchRequest).Do()
if err != nil {
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
return nil, fmt.Errorf("Folder Not Found: %s,%s", parent, displayName)
}
return nil, fmt.Errorf("Error reading folders: %s", err)
}
folders := searchResponse.Folders
if len(folders) != 1 {
return nil, fmt.Errorf("More than one folder found")
}
return getFolderIamPolicyByFolderName(folders[0].Name, config)
}

View File

@ -142,6 +142,8 @@ func Provider() terraform.ResourceProvider {
"google_dns_record_set": resourceDnsRecordSet(),
"google_endpoints_service": resourceEndpointsService(),
"google_folder": resourceGoogleFolder(),
"google_folder_iam_binding": ResourceIamBindingWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
"google_folder_iam_member": ResourceIamMemberWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
"google_folder_iam_policy": ResourceIamPolicyWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
"google_folder_organization_policy": resourceGoogleFolderOrganizationPolicy(),
"google_logging_billing_account_sink": resourceLoggingBillingAccountSink(),

View File

@ -0,0 +1,323 @@
package google
import (
"fmt"
"sort"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"google.golang.org/api/cloudresourcemanager/v1"
)
// Test that an IAM binding can be applied to a folder
func TestAccGoogleFolderIamBinding_basic(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply an IAM binding
{
Config: testAccGoogleFolderAssociateBindingBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
},
})
}
// Test that multiple IAM bindings can be applied to a folder, one at a time
func TestAccGoogleFolderIamBinding_multiple(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply an IAM binding
{
Config: testAccGoogleFolderAssociateBindingBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
// Apply another IAM binding
{
Config: testAccGoogleFolderAssociateBindingMultiple(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.multiple", &cloudresourcemanager.Binding{
Role: "roles/viewer",
Members: []string{"user:paddy@hashicorp.com"},
}, org, fname),
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.multiple", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
},
})
}
// Test that multiple IAM bindings can be applied to a folder all at once
func TestAccGoogleFolderIamBinding_multipleAtOnce(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply an IAM binding
{
Config: testAccGoogleFolderAssociateBindingMultiple(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.multiple", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
},
})
}
// Test that an IAM binding can be updated once applied to a folder
func TestAccGoogleFolderIamBinding_update(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply an IAM binding
{
Config: testAccGoogleFolderAssociateBindingBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
// Apply an updated IAM binding
{
Config: testAccGoogleFolderAssociateBindingUpdated(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.updated", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com", "user:paddy@hashicorp.com"},
}, org, fname),
),
},
// Drop the original member
{
Config: testAccGoogleFolderAssociateBindingDropMemberFromBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.dropped", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:paddy@hashicorp.com"},
}, org, fname),
),
},
},
})
}
// Test that an IAM binding can be removed from a folder
func TestAccGoogleFolderIamBinding_remove(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply multiple IAM bindings
{
Config: testAccGoogleFolderAssociateBindingMultiple(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.multiple", &cloudresourcemanager.Binding{
Role: "roles/viewer",
Members: []string{"user:paddy@hashicorp.com"},
}, org, fname),
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_binding.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
// Remove the bindings
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
},
})
}
func testAccCheckGoogleFolderIamBindingExists(key string, expected *cloudresourcemanager.Binding, org, fname string) resource.TestCheckFunc {
return func(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)
folderPolicy, err := getFolderIamPolicyByParentAndDisplayName("organizations/"+org, fname, config)
if err != nil {
return fmt.Errorf("Failed to retrieve IAM policy for folder %q: %s", fname, err)
}
var result *cloudresourcemanager.Binding
for _, binding := range folderPolicy.Bindings {
if binding.Role == expected.Role {
result = binding
break
}
}
if result == nil {
return fmt.Errorf("IAM policy for folder %q had no role %q, got %#v", fname, expected.Role, folderPolicy.Bindings)
}
if len(result.Members) != len(expected.Members) {
return fmt.Errorf("Got %v as members for role %q of folder %q, expected %v", result.Members, expected.Role, fname, expected.Members)
}
sort.Strings(result.Members)
sort.Strings(expected.Members)
for pos, exp := range expected.Members {
if result.Members[pos] != exp {
return fmt.Errorf("Expected members for role %q of folder %q to be %v, got %v", expected.Role, fname, expected.Members, result.Members)
}
}
return nil
}
}
func testAccGoogleFolderIamBasic(org, fname string) string {
return fmt.Sprintf(`
resource "google_folder" "acceptance" {
parent = "organizations/%s"
display_name = "%s"
}
`, org, fname)
}
func testAccGoogleFolderAssociateBindingBasic(org, fname string) string {
return fmt.Sprintf(`
resource "google_folder" "acceptance" {
parent = "organizations/%s"
display_name = "%s"
}
resource "google_folder_iam_binding" "acceptance" {
folder = "${google_folder.acceptance.name}"
members = ["user:admin@hashicorptest.com"]
role = "roles/compute.instanceAdmin"
}
`, org, fname)
}
func testAccGoogleFolderAssociateBindingMultiple(org, fname string) string {
return fmt.Sprintf(`
resource "google_folder" "acceptance" {
parent = "organizations/%s"
display_name = "%s"
}
resource "google_folder_iam_binding" "acceptance" {
folder = "${google_folder.acceptance.name}"
members = ["user:admin@hashicorptest.com"]
role = "roles/compute.instanceAdmin"
}
resource "google_folder_iam_binding" "multiple" {
folder = "${google_folder.acceptance.name}"
members = ["user:paddy@hashicorp.com"]
role = "roles/viewer"
}
`, org, fname)
}
func testAccGoogleFolderAssociateBindingUpdated(org, fname string) string {
return fmt.Sprintf(`
resource "google_folder" "acceptance" {
parent = "organizations/%s"
display_name = "%s"
}
resource "google_folder_iam_binding" "acceptance" {
folder = "${google_folder.acceptance.name}"
members = ["user:admin@hashicorptest.com", "user:paddy@hashicorp.com"]
role = "roles/compute.instanceAdmin"
}
`, org, fname)
}
func testAccGoogleFolderAssociateBindingDropMemberFromBasic(org, fname string) string {
return fmt.Sprintf(`
resource "google_folder" "acceptance" {
parent = "organizations/%s"
display_name = "%s"
}
resource "google_folder_iam_binding" "dropped" {
folder = "${google_folder.acceptance.name}"
members = ["user:paddy@hashicorp.com"]
role = "roles/compute.instanceAdmin"
}
`, org, fname)
}

View File

@ -0,0 +1,156 @@
package google
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"google.golang.org/api/cloudresourcemanager/v1"
)
// Test that an IAM binding can be applied to a folder
func TestAccGoogleFolderIamMember_basic(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply an IAM binding
{
Config: testAccGoogleFolderAssociateMemberBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_member.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
},
})
}
// Test that multiple IAM bindings can be applied to a folder
func TestAccGoogleFolderIamMember_multiple(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply an IAM binding
{
Config: testAccGoogleFolderAssociateMemberBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_member.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com"},
}, org, fname),
),
},
// Apply another IAM binding
{
Config: testAccGoogleFolderAssociateMemberMultiple(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_member.multiple", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com", "user:paddy@hashicorp.com"},
}, org, fname),
),
},
},
})
}
// Test that an IAM binding can be removed from a folder
func TestAccGoogleFolderIamMember_remove(t *testing.T) {
t.Parallel()
org := getTestOrgFromEnv(t)
fname := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// Create a new folder
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
// Apply multiple IAM bindings
{
Config: testAccGoogleFolderAssociateMemberMultiple(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleFolderIamBindingExists("google_folder_iam_member.acceptance", &cloudresourcemanager.Binding{
Role: "roles/compute.instanceAdmin",
Members: []string{"user:admin@hashicorptest.com", "user:paddy@hashicorp.com"},
}, org, fname),
),
},
// Remove the bindings
{
Config: testAccGoogleFolderIamBasic(org, fname),
Check: resource.ComposeTestCheckFunc(
testAccGoogleFolderExistingPolicy(org, fname),
),
},
},
})
}
func testAccGoogleFolderAssociateMemberBasic(org, fname string) string {
return fmt.Sprintf(`
resource "google_folder" "acceptance" {
parent = "organizations/%s"
display_name = "%s"
}
resource "google_folder_iam_member" "acceptance" {
folder = "${google_folder.acceptance.name}"
member = "user:admin@hashicorptest.com"
role = "roles/compute.instanceAdmin"
}
`, org, fname)
}
func testAccGoogleFolderAssociateMemberMultiple(org, fname string) string {
return fmt.Sprintf(`
resource "google_folder" "acceptance" {
parent = "organizations/%s"
display_name = "%s"
}
resource "google_folder_iam_member" "acceptance" {
folder = "${google_folder.acceptance.name}"
member = "user:admin@hashicorptest.com"
role = "roles/compute.instanceAdmin"
}
resource "google_folder_iam_member" "multiple" {
folder = "${google_folder.acceptance.name}"
member = "user:paddy@hashicorp.com"
role = "roles/compute.instanceAdmin"
}
`, org, fname)
}

View File

@ -3,12 +3,13 @@ package google
import (
"bytes"
"fmt"
"reflect"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1"
"reflect"
"testing"
)
func TestAccGoogleFolderIamPolicy_basic(t *testing.T) {
@ -145,6 +146,22 @@ func testAccCheckGoogleFolderIamPolicy(n string, policy *resourceManagerV2Beta1.
}
}
// Confirm that a folder has an IAM policy with at least 1 binding
func testAccGoogleFolderExistingPolicy(org, fname string) resource.TestCheckFunc {
return func(s *terraform.State) error {
c := testAccProvider.Meta().(*Config)
var err error
originalPolicy, err = getFolderIamPolicyByParentAndDisplayName("organizations/"+org, fname, c)
if err != nil {
return fmt.Errorf("Failed to retrieve IAM Policy for folder %q: %s", fname, err)
}
if len(originalPolicy.Bindings) == 0 {
return fmt.Errorf("Refuse to run test against folder with zero IAM Bindings. This is likely an error in the test code that is not properly identifying the IAM policy of a folder.")
}
return nil
}
}
func testAccGoogleFolderIamPolicy_basic(folder, parent string, policy *resourceManagerV2Beta1.Policy) string {
var bindingBuffer bytes.Buffer

View File

@ -0,0 +1,66 @@
---
layout: "google"
page_title: "Google: google_folder_iam_binding"
sidebar_current: "docs-google-folder-iam-binding"
description: |-
Allows management of a single binding with an IAM policy for a Google Cloud Platform folder.
---
# google\_folder\_iam\_binding
Allows creation and management of a single binding within IAM policy for
an existing Google Cloud Platform folder.
~> **Note:** This resource _must not_ be used in conjunction with
`google_folder_iam_policy` or they will fight over what your policy
should be.
## Example Usage
```hcl
resource "google_folder" "department1" {
display_name = "Department 1"
parent = "organizations/1234567"
}
resource "google_folder_iam_binding" "admin" {
folder = "${google_folder.department1.name}"
role = "roles/editor"
members = [
"user:jane@example.com",
]
}
```
## Argument Reference
The following arguments are supported:
* `folder` - (Required) The resource name of the folder the policy is attached to. Its format is folders/{folder_id}.
* `members` (Required) - An array of identites that will be granted the privilege in the `role`.
Each entry can have one of the following values:
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com.
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
* **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com.
* **domain:{domain}**: A Google Apps domain name that represents all the users of that domain. For example, google.com or example.com.
* `role` - (Required) The role that should be applied. Only one
`google_folder_iam_binding` can be used per role. Note that custom roles must be of the format
`[projects|organizations]/{parent-name}/roles/{role-name}`.
## Attributes Reference
In addition to the arguments listed above, the following computed attributes are
exported:
* `etag` - (Computed) The etag of the folder's IAM policy.
## Import
IAM binding imports use space-delimited identifiers; first the resource in question and then the role. These bindings can be imported using the `folder` and role, e.g.
```
$ terraform import google_folder_iam_binding.viewer "folder-name roles/viewer"
```

View File

@ -0,0 +1,63 @@
---
layout: "google"
page_title: "Google: google_folder_iam_member"
sidebar_current: "docs-google-folder-iam-member"
description: |-
Allows management of a single member for a single binding on the IAM policy for a Google Cloud Platform folder.
---
# google\_folder\_iam\_member
Allows creation and management of a single member for a single binding within
the IAM policy for an existing Google Cloud Platform folder.
~> **Note:** This resource _must not_ be used in conjunction with
`google_folder_iam_policy` or they will fight over what your policy
should be. Similarly, roles controlled by `google_folder_iam_binding`
should not be assigned to using `google_folder_iam_member`.
## Example Usage
```hcl
resource "google_folder" "department1" {
display_name = "Department 1"
parent = "organizations/1234567"
}
resource "google_folder_iam_member" "admin" {
folder = "${google_folder.department1.name}"
role = "roles/editor"
member = "user:jane@example.com"
}
```
## Argument Reference
The following arguments are supported:
* `folder` - (Required) The resource name of the folder the policy is attached to. Its format is folders/{folder_id}.
* `member` - (Required) The identity that will be granted the privilege in the `role`.
This field can have one of the following values:
* **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com.
* **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com.
* **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com.
* **domain:{domain}**: A Google Apps domain name that represents all the users of that domain. For example, google.com or example.com.
* `role` - (Required) The role that should be applied. Note that custom roles must be of the format
`[projects|organizations]/{parent-name}/roles/{role-name}`.
## Attributes Reference
In addition to the arguments listed above, the following computed attributes are
exported:
* `etag` - (Computed) The etag of the folder's IAM policy.
## Import
IAM member imports use space-delimited identifiers; the resource in question, the role, and the account. This member resource can be imported using the `folder`, role, and account e.g.
```
$ terraform import google_folder_iam_member.my_project "folder-name roles/viewer foo@example.com"
```

View File

@ -122,6 +122,12 @@
<li<%= sidebar_current("docs-google-folder-x") %>>
<a href="/docs/providers/google/r/google_folder.html">google_folder</a>
</li>
<li<%= sidebar_current("docs-google-folder-iam-binding") %>>
<a href="/docs/providers/google/r/google_folder_iam_binding.html">google_folder_iam_binding</a>
</li>
<li<%= sidebar_current("docs-google-folder-iam-member") %>>
<a href="/docs/providers/google/r/google_folder_iam_member.html">google_folder_iam_member</a>
</li>
<li<%= sidebar_current("docs-google-folder-iam-policy") %>>
<a href="/docs/providers/google/r/google_folder_iam_policy.html">google_folder_iam_policy</a>
</li>