mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-04 17:51:11 +00:00
Add 'google_folder_iam_binding' and 'google_folder_iam_member' resources (#1076)
This commit is contained in:
parent
509614e404
commit
21e0075f6f
@ -2,11 +2,13 @@ package google
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"google.golang.org/api/cloudresourcemanager/v1"
|
"google.golang.org/api/cloudresourcemanager/v1"
|
||||||
resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1"
|
resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1"
|
||||||
"strings"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
var IamFolderSchema = map[string]*schema.Schema{
|
var IamFolderSchema = map[string]*schema.Schema{
|
||||||
@ -35,19 +37,7 @@ func FolderIdParseFunc(d *schema.ResourceData, _ *Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *FolderIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
|
func (u *FolderIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
|
||||||
p, err := u.Config.clientResourceManagerV2Beta1.Folders.GetIamPolicy(u.folderId,
|
return getFolderIamPolicyByFolderName(u.folderId, u.Config)
|
||||||
&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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *FolderIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
|
func (u *FolderIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error {
|
||||||
@ -105,3 +95,42 @@ func v2BetaPolicyToV1(in *resourceManagerV2Beta1.Policy) (*cloudresourcemanager.
|
|||||||
}
|
}
|
||||||
return out, nil
|
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)
|
||||||
|
}
|
||||||
|
@ -142,6 +142,8 @@ func Provider() terraform.ResourceProvider {
|
|||||||
"google_dns_record_set": resourceDnsRecordSet(),
|
"google_dns_record_set": resourceDnsRecordSet(),
|
||||||
"google_endpoints_service": resourceEndpointsService(),
|
"google_endpoints_service": resourceEndpointsService(),
|
||||||
"google_folder": resourceGoogleFolder(),
|
"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_iam_policy": ResourceIamPolicyWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
|
||||||
"google_folder_organization_policy": resourceGoogleFolderOrganizationPolicy(),
|
"google_folder_organization_policy": resourceGoogleFolderOrganizationPolicy(),
|
||||||
"google_logging_billing_account_sink": resourceLoggingBillingAccountSink(),
|
"google_logging_billing_account_sink": resourceLoggingBillingAccountSink(),
|
||||||
|
323
google/resource_google_folder_iam_binding_test.go
Normal file
323
google/resource_google_folder_iam_binding_test.go
Normal 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)
|
||||||
|
}
|
156
google/resource_google_folder_iam_member_test.go
Normal file
156
google/resource_google_folder_iam_member_test.go
Normal 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)
|
||||||
|
}
|
@ -3,12 +3,13 @@ package google
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/acctest"
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1"
|
resourceManagerV2Beta1 "google.golang.org/api/cloudresourcemanager/v2beta1"
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccGoogleFolderIamPolicy_basic(t *testing.T) {
|
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 {
|
func testAccGoogleFolderIamPolicy_basic(folder, parent string, policy *resourceManagerV2Beta1.Policy) string {
|
||||||
var bindingBuffer bytes.Buffer
|
var bindingBuffer bytes.Buffer
|
||||||
|
|
||||||
|
66
website/docs/r/google_folder_iam_binding.html.markdown
Normal file
66
website/docs/r/google_folder_iam_binding.html.markdown
Normal 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"
|
||||||
|
```
|
63
website/docs/r/google_folder_iam_member.html.markdown
Normal file
63
website/docs/r/google_folder_iam_member.html.markdown
Normal 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"
|
||||||
|
```
|
@ -122,6 +122,12 @@
|
|||||||
<li<%= sidebar_current("docs-google-folder-x") %>>
|
<li<%= sidebar_current("docs-google-folder-x") %>>
|
||||||
<a href="/docs/providers/google/r/google_folder.html">google_folder</a>
|
<a href="/docs/providers/google/r/google_folder.html">google_folder</a>
|
||||||
</li>
|
</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") %>>
|
<li<%= sidebar_current("docs-google-folder-iam-policy") %>>
|
||||||
<a href="/docs/providers/google/r/google_folder_iam_policy.html">google_folder_iam_policy</a>
|
<a href="/docs/providers/google/r/google_folder_iam_policy.html">google_folder_iam_policy</a>
|
||||||
</li>
|
</li>
|
||||||
|
Loading…
Reference in New Issue
Block a user