Consistent IAM resource imports. (#835)

Add consistency for for IAM imports.
- Adds imports for projects, folders, crypto keys, organizations, and key rings.
- Anything else with IAM can implement a simple method and begin working immediately.
- Add tests for all the IAM imports.
- Import documentation for IAM resources.
This commit is contained in:
Nathan McKinley 2017-12-11 10:24:53 -08:00 committed by GitHub
parent bf235ebc04
commit ced8cb506c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 513 additions and 12 deletions

View File

@ -34,6 +34,14 @@ type ResourceIamUpdater interface {
type newResourceIamUpdaterFunc func(d *schema.ResourceData, config *Config) (ResourceIamUpdater, error)
type iamPolicyModifyFunc func(p *cloudresourcemanager.Policy) error
// This method parses identifiers specific to the resource (d.GetId()) into the ResourceData
// object, so that it can be given to the resource's Read method. Externally, this is wrapped
// into schema.StateFunc functions - one each for a _member, a _binding, and a _policy. Any
// GCP resource supporting IAM policy might support one, two, or all of these. Any GCP resource
// for which an implementation of this interface exists could support any of the three.
type resourceIdParserFunc func(d *schema.ResourceData, config *Config) error
func iamPolicyReadModifyWrite(updater ResourceIamUpdater, modify iamPolicyModifyFunc) error {
mutexKey := updater.GetMutexKey()
mutexKV.Lock(mutexKey)

View File

@ -28,6 +28,11 @@ func NewFolderIamUpdater(d *schema.ResourceData, config *Config) (ResourceIamUpd
}, nil
}
func FolderIdParseFunc(d *schema.ResourceData, _ *Config) error {
d.Set("folder", d.Id())
return nil
}
func (u *FolderIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
p, err := u.Config.clientResourceManagerV2Beta1.Folders.GetIamPolicy(u.folderId,
&resourceManagerV2Beta1.GetIamPolicyRequest{}).Do()

View File

@ -34,6 +34,11 @@ func NewKmsCryptoKeyIamUpdater(d *schema.ResourceData, config *Config) (Resource
}, nil
}
func CryptoIdParseFunc(d *schema.ResourceData, _ *Config) error {
d.Set("crypto_key_id", d.Id())
return nil
}
func (u *KmsCryptoKeyIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
p, err := u.Config.clientKms.Projects.Locations.KeyRings.CryptoKeys.GetIamPolicy(u.resourceId).Do()

View File

@ -34,6 +34,11 @@ func NewKmsKeyRingIamUpdater(d *schema.ResourceData, config *Config) (ResourceIa
}, nil
}
func KeyRingIdParseFunc(d *schema.ResourceData, _ *Config) error {
d.Set("key_ring_id", d.Id())
return nil
}
func resourceManagerToKmsPolicy(p *cloudresourcemanager.Policy) (policy *cloudkms.Policy, err error) {
policy = &cloudkms.Policy{}

View File

@ -26,6 +26,11 @@ func NewOrganizationIamUpdater(d *schema.ResourceData, config *Config) (Resource
}, nil
}
func OrgIdParseFunc(d *schema.ResourceData, _ *Config) error {
d.Set("org_id", d.Id())
return nil
}
func (u *OrganizationIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
p, err := u.Config.clientResourceManager.Organizations.GetIamPolicy("organizations/"+u.resourceId, &cloudresourcemanager.GetIamPolicyRequest{}).Do()
if err != nil {

View File

@ -31,6 +31,11 @@ func NewProjectIamUpdater(d *schema.ResourceData, config *Config) (ResourceIamUp
}, nil
}
func ProjectIdParseFunc(d *schema.ResourceData, _ *Config) error {
d.Set("project", d.Id())
return nil
}
func (u *ProjectIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
p, err := u.Config.clientResourceManager.Projects.GetIamPolicy(u.resourceId,
&cloudresourcemanager.GetIamPolicyRequest{}).Do()

View File

@ -0,0 +1,75 @@
package google
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccKmsCryptoKeyIamMember_importBasic(t *testing.T) {
t.Parallel()
orgId := getTestOrgFromEnv(t)
projectId := acctest.RandomWithPrefix("tf-test")
billingAccount := getTestBillingAccountFromEnv(t)
account := acctest.RandomWithPrefix("tf-test")
roleId := "roles/cloudkms.cryptoKeyEncrypter"
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
keyRingId := &kmsKeyRingId{
Project: projectId,
Location: DEFAULT_KMS_TEST_LOCATION,
Name: keyRingName,
}
cryptoKeyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleKmsCryptoKeyIamMember_basic(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId),
},
resource.TestStep{
ResourceName: "google_kms_crypto_key_iam_member.foo",
ImportStateId: fmt.Sprintf("%s/%s %s serviceAccount:%s@%s.iam.gserviceaccount.com", keyRingId.terraformId(), cryptoKeyName, roleId, account, projectId),
ImportState: true,
},
},
})
}
func TestAccKmsCryptoKeyIamBinding_importBasic(t *testing.T) {
t.Parallel()
orgId := getTestOrgFromEnv(t)
projectId := acctest.RandomWithPrefix("tf-test")
billingAccount := getTestBillingAccountFromEnv(t)
account := acctest.RandomWithPrefix("tf-test")
roleId := "roles/cloudkms.cryptoKeyEncrypter"
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
keyRingId := &kmsKeyRingId{
Project: projectId,
Location: DEFAULT_KMS_TEST_LOCATION,
Name: keyRingName,
}
cryptoKeyName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleKmsCryptoKeyIamBinding_basic(projectId, orgId, billingAccount, account, keyRingName, cryptoKeyName, roleId),
},
resource.TestStep{
ResourceName: "google_kms_crypto_key_iam_binding.foo",
ImportStateId: fmt.Sprintf("%s/%s %s", keyRingId.terraformId(), cryptoKeyName, roleId),
ImportState: true,
},
},
})
}

View File

@ -0,0 +1,104 @@
package google
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccKmsKeyRingIamMember_importBasic(t *testing.T) {
t.Parallel()
orgId := getTestOrgFromEnv(t)
projectId := acctest.RandomWithPrefix("tf-test")
billingAccount := getTestBillingAccountFromEnv(t)
account := acctest.RandomWithPrefix("tf-test")
roleId := "roles/cloudkms.cryptoKeyEncrypter"
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
keyRingId := &kmsKeyRingId{
Project: projectId,
Location: DEFAULT_KMS_TEST_LOCATION,
Name: keyRingName,
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleKmsKeyRingIamMember_basic(projectId, orgId, billingAccount, account, keyRingName, roleId),
},
resource.TestStep{
ResourceName: "google_kms_key_ring_iam_member.foo",
ImportStateId: fmt.Sprintf("%s %s serviceAccount:%s@%s.iam.gserviceaccount.com", keyRingId.terraformId(), roleId, account, projectId),
ImportState: true,
},
},
})
}
func TestAccKmsKeyRingIamPolicy_importBasic(t *testing.T) {
t.Parallel()
orgId := getTestOrgFromEnv(t)
projectId := acctest.RandomWithPrefix("tf-test")
billingAccount := getTestBillingAccountFromEnv(t)
account := acctest.RandomWithPrefix("tf-test")
roleId := "roles/cloudkms.cryptoKeyEncrypter"
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
keyRingId := &kmsKeyRingId{
Project: projectId,
Location: DEFAULT_KMS_TEST_LOCATION,
Name: keyRingName,
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleKmsKeyRingIamPolicy_basic(projectId, orgId, billingAccount, account, keyRingName, roleId),
},
resource.TestStep{
ResourceName: "google_kms_key_ring_iam_policy.foo",
ImportStateId: keyRingId.terraformId(),
ImportState: true,
},
},
})
}
func TestAccKmsKeyRingIamBinding_importBasic(t *testing.T) {
t.Parallel()
orgId := getTestOrgFromEnv(t)
projectId := acctest.RandomWithPrefix("tf-test")
billingAccount := getTestBillingAccountFromEnv(t)
account := acctest.RandomWithPrefix("tf-test")
roleId := "roles/cloudkms.cryptoKeyEncrypter"
keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
keyRingId := &kmsKeyRingId{
Project: projectId,
Location: DEFAULT_KMS_TEST_LOCATION,
Name: keyRingName,
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleKmsKeyRingIamBinding_basic(projectId, orgId, billingAccount, account, keyRingName, roleId),
},
resource.TestStep{
ResourceName: "google_kms_key_ring_iam_binding.foo",
ImportStateId: fmt.Sprintf("%s %s", keyRingId.terraformId(), roleId),
ImportState: true,
},
},
})
}

View File

@ -0,0 +1,57 @@
package google
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccGoogleOrganizationIamMember_importBasic(t *testing.T) {
t.Parallel()
orgId := getTestOrgFromEnv(t)
account := acctest.RandomWithPrefix("tf-test")
projectId := getTestProjectFromEnv()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleOrganizationIamMember_basic(account, orgId),
},
resource.TestStep{
ResourceName: "google_organization_iam_member.foo",
ImportStateId: fmt.Sprintf("%s roles/browser serviceAccount:%s@%s.iam.gserviceaccount.com", orgId, account, projectId),
ImportState: true,
},
},
})
}
func TestAccGoogleOrganizationIamBinding_importBasic(t *testing.T) {
t.Parallel()
orgId := getTestOrgFromEnv(t)
account := acctest.RandomWithPrefix("tf-test")
roleId := "tfIamTest" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleOrganizationIamBinding_basic(account, roleId, orgId),
},
resource.TestStep{
ResourceName: "google_organization_iam_binding.foo",
ImportStateId: fmt.Sprintf("%s organizations/%s/roles/%s", orgId, orgId, roleId),
ImportState: true,
},
},
})
}

View File

@ -0,0 +1,57 @@
package google
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccGoogleProjectIamMember_importBasic(t *testing.T) {
t.Parallel()
resourceName := "google_project_iam_member.acceptance"
org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleProjectAssociateMemberBasic(pid, "Acceptance", org),
},
resource.TestStep{
ResourceName: resourceName,
ImportStateId: fmt.Sprintf("%s %s %s", pid, "roles/compute.instanceAdmin", "user:admin@hashicorptest.com"),
ImportState: true,
},
},
})
}
func TestAccGoogleProjectIamBinding_importBasic(t *testing.T) {
t.Parallel()
resourceName := "google_project_iam_binding.acceptance"
org := getTestOrgFromEnv(t)
pid := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGoogleProjectAssociateBindingBasic(pid, "Acceptance", org),
},
resource.TestStep{
ResourceName: resourceName,
ImportStateId: fmt.Sprintf("%s %s", pid, "roles/compute.instanceAdmin"),
ImportState: true,
},
},
})
}

View File

@ -129,32 +129,32 @@ func Provider() terraform.ResourceProvider {
"google_dns_managed_zone": resourceDnsManagedZone(),
"google_dns_record_set": resourceDnsRecordSet(),
"google_folder": resourceGoogleFolder(),
"google_folder_iam_policy": ResourceIamPolicy(IamFolderSchema, NewFolderIamUpdater),
"google_folder_iam_policy": ResourceIamPolicyWithImport(IamFolderSchema, NewFolderIamUpdater, FolderIdParseFunc),
"google_folder_organization_policy": resourceGoogleFolderOrganizationPolicy(),
"google_logging_billing_account_sink": resourceLoggingBillingAccountSink(),
"google_logging_folder_sink": resourceLoggingFolderSink(),
"google_logging_project_sink": resourceLoggingProjectSink(),
"google_kms_key_ring": resourceKmsKeyRing(),
"google_kms_key_ring_iam_binding": ResourceIamBinding(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater),
"google_kms_key_ring_iam_member": ResourceIamMember(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater),
"google_kms_key_ring_iam_policy": ResourceIamPolicy(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater),
"google_kms_key_ring_iam_binding": ResourceIamBindingWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc),
"google_kms_key_ring_iam_member": ResourceIamMemberWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc),
"google_kms_key_ring_iam_policy": ResourceIamPolicyWithImport(IamKmsKeyRingSchema, NewKmsKeyRingIamUpdater, KeyRingIdParseFunc),
"google_kms_crypto_key": resourceKmsCryptoKey(),
"google_kms_crypto_key_iam_binding": ResourceIamBinding(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater),
"google_kms_crypto_key_iam_member": ResourceIamMember(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater),
"google_kms_crypto_key_iam_binding": ResourceIamBindingWithImport(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
"google_kms_crypto_key_iam_member": ResourceIamMemberWithImport(IamKmsCryptoKeySchema, NewKmsCryptoKeyIamUpdater, CryptoIdParseFunc),
"google_sourcerepo_repository": resourceSourceRepoRepository(),
"google_spanner_instance": resourceSpannerInstance(),
"google_spanner_database": resourceSpannerDatabase(),
"google_sql_database": resourceSqlDatabase(),
"google_sql_database_instance": resourceSqlDatabaseInstance(),
"google_sql_user": resourceSqlUser(),
"google_organization_iam_binding": ResourceIamBinding(IamOrganizationSchema, NewOrganizationIamUpdater),
"google_organization_iam_binding": ResourceIamBindingWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc),
"google_organization_iam_custom_role": resourceGoogleOrganizationIamCustomRole(),
"google_organization_iam_member": ResourceIamMember(IamOrganizationSchema, NewOrganizationIamUpdater),
"google_organization_iam_member": ResourceIamMemberWithImport(IamOrganizationSchema, NewOrganizationIamUpdater, OrgIdParseFunc),
"google_organization_policy": resourceGoogleOrganizationPolicy(),
"google_project": resourceGoogleProject(),
"google_project_iam_policy": resourceGoogleProjectIamPolicy(),
"google_project_iam_binding": ResourceIamBinding(IamProjectSchema, NewProjectIamUpdater),
"google_project_iam_member": ResourceIamMember(IamProjectSchema, NewProjectIamUpdater),
"google_project_iam_binding": ResourceIamBindingWithImport(IamProjectSchema, NewProjectIamUpdater, ProjectIdParseFunc),
"google_project_iam_member": ResourceIamMemberWithImport(IamProjectSchema, NewProjectIamUpdater, ProjectIdParseFunc),
"google_project_service": resourceGoogleProjectService(),
"google_project_iam_custom_role": resourceGoogleProjectIamCustomRole(),
"google_project_services": resourceGoogleProjectServices(),

View File

@ -17,6 +17,9 @@ func resourceGoogleProjectIamPolicy() *schema.Resource {
Read: resourceGoogleProjectIamPolicyRead,
Update: resourceGoogleProjectIamPolicyUpdate,
Delete: resourceGoogleProjectIamPolicyDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"project": &schema.Schema{

View File

@ -1,9 +1,12 @@
package google
import (
"errors"
"fmt"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudresourcemanager/v1"
"log"
"strings"
)
var iamBindingSchema = map[string]*schema.Schema{
@ -31,11 +34,18 @@ func ResourceIamBinding(parentSpecificSchema map[string]*schema.Schema, newUpdat
Read: resourceIamBindingRead(newUpdaterFunc),
Update: resourceIamBindingUpdate(newUpdaterFunc),
Delete: resourceIamBindingDelete(newUpdaterFunc),
Schema: mergeSchemas(iamBindingSchema, parentSpecificSchema),
}
}
func ResourceIamBindingWithImport(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceIamUpdaterFunc, resourceIdParser resourceIdParserFunc) *schema.Resource {
r := ResourceIamBinding(parentSpecificSchema, newUpdaterFunc)
r.Importer = &schema.ResourceImporter{
State: iamBindingImport(resourceIdParser),
}
return r
}
func resourceIamBindingCreate(newUpdaterFunc newResourceIamUpdaterFunc) schema.CreateFunc {
return func(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
@ -96,6 +106,38 @@ func resourceIamBindingRead(newUpdaterFunc newResourceIamUpdaterFunc) schema.Rea
}
}
func iamBindingImport(resourceIdParser resourceIdParserFunc) schema.StateFunc {
return func(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
if resourceIdParser == nil {
return nil, errors.New("Import not supported for this IAM resource.")
}
config := m.(*Config)
s := strings.Split(d.Id(), " ")
if len(s) != 2 {
d.SetId("")
return nil, fmt.Errorf("Wrong number of parts to Binding id %s; expected 'resource_name role'.", s)
}
id, role := s[0], s[1]
d.SetId(id)
d.Set("role", role)
err := resourceIdParser(d, config)
if err != nil {
return nil, err
}
// It is possible to return multiple bindings, since we can learn about all the bindings
// for this resource here. Unfortunately, `terraform import` has some messy behavior here -
// there's no way to know at this point which resource is being imported, so it's not possible
// to order this list in a useful way. In the event of a complex set of bindings, the user
// will have a terribly confusing set of imported resources and no way to know what matches
// up to what. And since the only users who will do a terraform import on their IAM bindings
// are users who aren't too familiar with Google Cloud IAM (because a "create" for bindings or
// members is idempotent), it's reasonable to expect that the user will be very alarmed by the
// plan that terraform will output which mentions destroying a dozen-plus IAM bindings. With
// that in mind, we return only the binding that matters.
return []*schema.ResourceData{d}, nil
}
}
func resourceIamBindingUpdate(newUpdaterFunc newResourceIamUpdaterFunc) schema.UpdateFunc {
return func(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

View File

@ -1,9 +1,12 @@
package google
import (
"errors"
"fmt"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudresourcemanager/v1"
"log"
"strings"
)
var IamMemberBaseSchema = map[string]*schema.Schema{
@ -23,6 +26,29 @@ var IamMemberBaseSchema = map[string]*schema.Schema{
},
}
func iamMemberImport(resourceIdParser resourceIdParserFunc) schema.StateFunc {
return func(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
if resourceIdParser == nil {
return nil, errors.New("Import not supported for this IAM resource.")
}
config := m.(*Config)
s := strings.Split(d.Id(), " ")
if len(s) != 3 {
d.SetId("")
return nil, fmt.Errorf("Wrong number of parts to Member id %s; expected 'resource_name role username'.", s)
}
id, role, member := s[0], s[1], s[2]
d.SetId(id)
d.Set("role", role)
d.Set("member", member)
err := resourceIdParser(d, config)
if err != nil {
return nil, err
}
return []*schema.ResourceData{d}, nil
}
}
func ResourceIamMember(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceIamUpdaterFunc) *schema.Resource {
return &schema.Resource{
Create: resourceIamMemberCreate(newUpdaterFunc),
@ -33,6 +59,14 @@ func ResourceIamMember(parentSpecificSchema map[string]*schema.Schema, newUpdate
}
}
func ResourceIamMemberWithImport(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceIamUpdaterFunc, resourceIdParser resourceIdParserFunc) *schema.Resource {
r := ResourceIamMember(parentSpecificSchema, newUpdaterFunc)
r.Importer = &schema.ResourceImporter{
State: iamMemberImport(resourceIdParser),
}
return r
}
func getResourceIamMember(d *schema.ResourceData) *cloudresourcemanager.Binding {
return &cloudresourcemanager.Binding{
Members: []string{d.Get("member").(string)},

View File

@ -4,6 +4,7 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"encoding/json"
"errors"
"fmt"
"google.golang.org/api/cloudresourcemanager/v1"
)
@ -21,6 +22,20 @@ var IamPolicyBaseSchema = map[string]*schema.Schema{
},
}
func iamPolicyImport(resourceIdParser resourceIdParserFunc) schema.StateFunc {
return func(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
if resourceIdParser == nil {
return nil, errors.New("Import not supported for this IAM resource.")
}
config := m.(*Config)
err := resourceIdParser(d, config)
if err != nil {
return nil, err
}
return []*schema.ResourceData{d}, nil
}
}
func ResourceIamPolicy(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceIamUpdaterFunc) *schema.Resource {
return &schema.Resource{
Create: ResourceIamPolicyCreate(newUpdaterFunc),
@ -32,6 +47,14 @@ func ResourceIamPolicy(parentSpecificSchema map[string]*schema.Schema, newUpdate
}
}
func ResourceIamPolicyWithImport(parentSpecificSchema map[string]*schema.Schema, newUpdaterFunc newResourceIamUpdaterFunc, resourceIdParser resourceIdParserFunc) *schema.Resource {
r := ResourceIamPolicy(parentSpecificSchema, newUpdaterFunc)
r.Importer = &schema.ResourceImporter{
State: iamPolicyImport(resourceIdParser),
}
return r
}
func ResourceIamPolicyCreate(newUpdaterFunc newResourceIamUpdaterFunc) schema.CreateFunc {
return func(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

View File

@ -45,3 +45,10 @@ exported:
* `etag` - (Computed) The etag of the crypto key'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 `crypto_key_id` and role, e.g.
```
$ terraform import google_kms_crypto_key_binding.my_binding "your-project-id/location-name/key-name roles/viewer"
```

View File

@ -45,3 +45,11 @@ In addition to the arguments listed above, the following computed attributes are
exported:
* `etag` - (Computed) The etag of the project'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 `crypto_key_id`, role, and account e.g.
```
$ terraform import google_kms_crypto_key_iam_member.member "your-project-id/location-name/key-name roles/viewer foo@example.com"
```

View File

@ -90,3 +90,23 @@ In addition to the arguments listed above, the following computed attributes are
exported:
* `etag` - (Computed) The etag of the key ring'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 `key_ring_id`, role, and account e.g.
```
$ terraform import google_kms_key_ring_iam_member.key_ring_iam "your-project-id/location-name/key-ring-name roles/viewer foo@example.com"
```
IAM binging imports use space-delimited identifiers; the resource in question and the role. This binding resource can be imported using the `key_ring_id`, role, and account e.g.
```
$ terraform import google_kms_key_ring_iam_binding.key_ring_iam "your-project-id/location-name/key-ring-name roles/viewer"
```
IAM policy imports use the identifier of the resource in question. This policy resource can be imported using the `key_ring_id`, role, and account e.g.
```
$ terraform import google_kms_key_ring_iam_policy.key_ring_iam your-project-id/location-name/key-ring-name
```

View File

@ -46,3 +46,10 @@ exported:
* `etag` - (Computed) The etag of the organization'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 `org_id` and role, e.g.
```
$ terraform import google_organization_iam_binding.my_org "your-org-id roles/viewer"
```

View File

@ -41,3 +41,11 @@ In addition to the arguments listed above, the following computed attributes are
exported:
* `etag` - (Computed) The etag of the organization'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 `org_id`, role, and account e.g.
```
$ terraform import google_organization_iam_member.my_org "your-org-id roles/viewer foo@example.com"
```

View File

@ -54,3 +54,10 @@ exported:
* `etag` - (Computed) The etag of the project'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 `project_id` and role, e.g.
```
$ terraform import google_project_iam_binding.my_project "your-project-id roles/viewer"
```

View File

@ -50,3 +50,11 @@ In addition to the arguments listed above, the following computed attributes are
exported:
* `etag` - (Computed) The etag of the project'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 `project_id`, role, and account e.g.
```
$ terraform import google_project_iam_member.my_project "your-project-id roles/viewer foo@example.com"
```

View File

@ -38,7 +38,7 @@ data "google_iam_policy" "admin" {
The following arguments are supported:
* `project` - (Required) The project ID.
Changing this forces a new project to be created.
Changing this forces a new resource to be created.
* `policy_data` - (Required) The `google_iam_policy` data source that represents
the IAM policy that will be applied to the project. The policy will be
@ -73,3 +73,11 @@ exported:
* `restore_policy` - (DEPRECATED) (Computed) The IAM policy that will be restored when a
non-authoritative policy resource is deleted.
## Import
IAM policy imports use the identifier of the resource in question. This policy resource can be imported using the `project_id` e.g.
```
$ terraform import google_project_iam_policy.my_project your-project-id
```