Skip to content
This repository has been archived by the owner on Jun 27, 2021. It is now read-only.

Commit

Permalink
Implement import functionality for group_members (#10)
Browse files Browse the repository at this point in the history
* Implement import functionality for group_members

* Use retries

* Rename to group_email and use that as the id

There is some confusion when using the Google
group id. Using the email is the easiest option.
I renamed the field so it is obvious.
  • Loading branch information
psalaberria002 authored and DeviaVir committed Mar 23, 2018
1 parent 2e482b8 commit 4616e40
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 27 deletions.
2 changes: 1 addition & 1 deletion examples/group-members/team.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ resource "gsuite_group" "testing_team" {
}

resource "gsuite_group_members" "testing_team_members" {
group = "${gsuite_group.testing_team.id}"
group_email = "${gsuite_group.testing_team.email}"

member {
email = "[email protected]",
Expand Down
78 changes: 52 additions & 26 deletions gsuite/resource_group_members.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ import (

func resourceGroupMembers() *schema.Resource {
return &schema.Resource{
Create: resourceGroupMembersCreate,
Read: resourceGroupMembersRead,
Update: resourceGroupMembersUpdate,
Delete: resourceGroupMembersDelete,
Create: resourceGroupMembersCreate,
Read: resourceGroupMembersRead,
Update: resourceGroupMembersUpdate,
Delete: resourceGroupMembersDelete,
Importer: &schema.ResourceImporter{
State: resourceGroupMembersImporter,
},

Schema: map[string]*schema.Schema{
"group": {
"group_email": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"member": {
Type: schema.TypeSet,
Expand All @@ -35,13 +39,15 @@ func resourceGroupMembers() *schema.Resource {
func resourceGroupMembersRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

members, err := getApiMembers(d.Id(), config)
groupEmail := d.Id()

members, err := getApiMembers(groupEmail, config)

if err != nil {
return err
}

d.Set("group", d.Id())
d.Set("group_email", groupEmail)
d.Set("member", membersToCfg(members))
return nil
}
Expand Down Expand Up @@ -112,24 +118,24 @@ func resourceMembers(d *schema.ResourceData) (members []map[string]interface{})

func createOrUpdateGroupMembers(d *schema.ResourceData, meta interface{}) (string, error) {
config := meta.(*Config)
gid := d.Get("group").(string)
groupEmail := d.Get("group_email").(string)

// Get members from config
cfgMembers := resourceMembers(d)

// Get members from API
apiMembers, err := getApiMembers(gid, config)
apiMembers, err := getApiMembers(groupEmail, config)
if err != nil {
return gid, fmt.Errorf("Error updating memberships: %v", err)
return groupEmail, fmt.Errorf("Error updating memberships: %v", err)
}
// This call removes any members that aren't defined in cfgMembers,
// and adds all of those that are
err = reconcileMembers(d, cfgMembers, membersToCfg(apiMembers), config, gid)
err = reconcileMembers(d, cfgMembers, membersToCfg(apiMembers), config, groupEmail)
if err != nil {
return gid, fmt.Errorf("Error updating memberships: %v", err)
return groupEmail, fmt.Errorf("Error updating memberships: %v", err)
}

return gid, nil
return groupEmail, nil
}

// This function ensures that the members of a group exactly match that
Expand Down Expand Up @@ -177,7 +183,7 @@ func reconcileMembers(d *schema.ResourceData, cfgMembers, apiMembers []map[strin
var err error
err = retry(func() error {
updatedGroupMember, err = config.directory.Members.Patch(
d.Get("group").(string),
d.Get("group_email").(string),
cfgMember["email"].(string),
groupMember).Do()
return err
Expand Down Expand Up @@ -206,7 +212,7 @@ func reconcileMembers(d *schema.ResourceData, cfgMembers, apiMembers []map[strin
}

// Retrieve a group's members from the API
func getApiMembers(gid string, config *Config) ([]*directory.Member, error) {
func getApiMembers(groupEmail string, config *Config) ([]*directory.Member, error) {
// Get members from the API
groupMembers := make([]*directory.Member, 0)
token := ""
Expand All @@ -215,7 +221,7 @@ func getApiMembers(gid string, config *Config) ([]*directory.Member, error) {
for paginate := true; paginate; {

err = retry(func() error {
membersResponse, err = config.directory.Members.List(gid).PageToken(token).Do()
membersResponse, err = config.directory.Members.List(groupEmail).PageToken(token).Do()
return err
})

Expand All @@ -231,7 +237,7 @@ func getApiMembers(gid string, config *Config) ([]*directory.Member, error) {
return groupMembers, nil
}

func upsertMember(email, gid, role string, config *Config) error {
func upsertMember(email, groupEmail, role string, config *Config) error {
groupMember := &directory.Member{
Role: role,
Email: email,
Expand Down Expand Up @@ -260,15 +266,15 @@ func upsertMember(email, gid, role string, config *Config) error {
var currentMember *directory.Member
var err error
err = retry(func() error {
currentMember, err = config.directory.Members.Get(gid, email).Do()
currentMember, err = config.directory.Members.Get(groupEmail, email).Do()
return err
})

// Based on the err return, either add as a new member, or update
if err != nil {
var createdGroupMember *directory.Member
err = retry(func() error {
createdGroupMember, err = config.directory.Members.Insert(gid, groupMember).Do()
createdGroupMember, err = config.directory.Members.Insert(groupEmail, groupMember).Do()
return err
})
if err != nil {
Expand All @@ -278,7 +284,7 @@ func upsertMember(email, gid, role string, config *Config) error {
} else {
var updatedGroupMember *directory.Member
err = retry(func() error {
updatedGroupMember, err = config.directory.Members.Update(gid, email, groupMember).Do()
updatedGroupMember, err = config.directory.Members.Update(groupEmail, email, groupMember).Do()
return err
})
if err != nil {
Expand All @@ -294,15 +300,15 @@ func upsertMember(email, gid, role string, config *Config) error {
var hasMemberResponse *directory.MembersHasMember
var err error
err = retry(func() error {
hasMemberResponse, err = config.directory.Members.HasMember(gid, email).Do()
hasMemberResponse, err = config.directory.Members.HasMember(groupEmail, email).Do()
if err == nil {
return err
}

// When a user does not exist, the API returns a 400 "memberKey, required"
// Returning a friendly message
if gerr, ok := err.(*googleapi.Error); ok && (gerr.Errors[0].Reason == "required" && gerr.Code == 400) {
return fmt.Errorf("Error adding groupMember %s. Please make sure the user exists beforehand.", email)
return fmt.Errorf("Error adding groupMember %s. Please make sure the user exists beforehand.", email)
}
return err
})
Expand All @@ -313,7 +319,7 @@ func upsertMember(email, gid, role string, config *Config) error {
if hasMemberResponse.IsMember == true {
var updatedGroupMember *directory.Member
err = retry(func() error {
updatedGroupMember, err = config.directory.Members.Update(gid, email, groupMember).Do()
updatedGroupMember, err = config.directory.Members.Update(groupEmail, email, groupMember).Do()
return err
})
if err != nil {
Expand All @@ -323,7 +329,7 @@ func upsertMember(email, gid, role string, config *Config) error {
} else {
var createdGroupMember *directory.Member
err = retry(func() error {
createdGroupMember, err = config.directory.Members.Insert(gid, groupMember).Do()
createdGroupMember, err = config.directory.Members.Insert(groupEmail, groupMember).Do()
return err
})
if err != nil {
Expand All @@ -336,9 +342,9 @@ func upsertMember(email, gid, role string, config *Config) error {
return nil
}

func deleteMember(email, gid string, config *Config) (err error) {
func deleteMember(email, groupEmail string, config *Config) (err error) {
err = retry(func() error {
err = config.directory.Members.Delete(gid, email).Do()
err = config.directory.Members.Delete(groupEmail, email).Do()
return err
})

Expand All @@ -347,3 +353,23 @@ func deleteMember(email, gid string, config *Config) (err error) {
}
return nil
}

// Allow importing using any groupKey (id, email, alias)
func resourceGroupMembersImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)

var group *directory.Group
var err error
err = retry(func() error {
group, err = config.directory.Groups.Get(d.Id()).Do()
return err
})

if err != nil {
return nil, fmt.Errorf("Error fetching group. Make sure the group exists: %s ", err)
}

d.SetId(group.Email)

return []*schema.ResourceData{d}, nil
}

0 comments on commit 4616e40

Please sign in to comment.