-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcmd_group_export.go
117 lines (105 loc) · 2.63 KB
/
cmd_group_export.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
import (
"encoding/csv"
"fmt"
"os"
"strings"
"sync"
"github.com/urfave/cli"
"golang.org/x/net/context"
admin "google.golang.org/api/admin/directory/v1"
"google.golang.org/api/option"
)
func cmdExportGroupMemberships(c *cli.Context) error {
client := sharedAuthClient(c)
srv, err := admin.NewService(context.Background(), option.WithHTTPClient(client))
if err != nil {
return fmt.Errorf("unable to retrieve directory Client %v", err)
}
done := showSpinnerWhile(c)
call := srv.Groups.List().
Customer(myAccoutsCustomerID).
MaxResults(int64(ifZero(c.Int("limit"), 100))).
OrderBy("email")
if domain := c.GlobalString("domain"); len(domain) > 0 {
call = call.Domain(domain)
}
r, err := call.Do()
if err != nil {
return fmt.Errorf("unable to retrieve groups in domain: %v", err)
}
type entry struct {
groupKey string
members []*admin.Member
}
entries := make(chan entry)
wg := new(sync.WaitGroup)
for _, g := range r.Groups {
wg.Add(1)
// concurrently fetch members of a group
go func(groupKey string) {
if c.GlobalBool("v") {
fmt.Println("fetching members of", groupKey, "...")
}
usersList := []*admin.Member{}
// email is default
r, err := srv.Members.List(groupKey).Do()
if err != nil {
fmt.Printf("unable to retrieve members of group [%s] : %v\n", groupKey, err)
}
for _, u := range r.Members {
if len(u.Email) > 0 {
// hide some internals
u.Etag = ""
u.Id = ""
u.Kind = ""
usersList = append(usersList, u)
}
}
entries <- entry{groupKey: groupKey, members: usersList}
wg.Done()
}(g.Email)
}
groupToMembersMap := map[string][]*admin.Member{}
// collect results
go func() {
for each := range entries {
if c.GlobalBool("v") {
fmt.Println("... collect members of", each.groupKey)
}
groupToMembersMap[each.groupKey] = each.members
}
}()
// wait for all group queries
wg.Wait()
// no more results
close(entries)
// end spinner
done()
if optionJSON(c, groupToMembersMap) {
return nil
}
if c.Bool("csv") {
writeGroupToMembersCSV(groupToMembersMap)
return nil
}
// simple print
for k, v := range groupToMembersMap {
fmt.Printf("[%s]\n", k)
for _, o := range v {
fmt.Printf("%s\n", o.Email)
}
}
return nil
}
// rows with {group.email},{role.name},{member.email}
func writeGroupToMembersCSV(groupToMembersMap map[string][]*admin.Member) {
w := csv.NewWriter(os.Stdout)
w.Write([]string{"group", "role", "member"}) // header
for group, members := range groupToMembersMap {
for _, member := range members {
w.Write([]string{group, strings.ToLower(member.Role), member.Email})
}
}
w.Flush()
}