Skip to content

Commit f27c8c6

Browse files
authored
batch group requests (#14)
1 parent ded0bec commit f27c8c6

File tree

4 files changed

+116
-7
lines changed

4 files changed

+116
-7
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ require (
5353
gopkg.in/yaml.v3 v3.0.1 // indirect
5454
k8s.io/klog/v2 v2.90.1 // indirect
5555
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
56-
k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
56+
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
5757
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
5858
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
5959
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,8 @@ k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
531531
k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
532532
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
533533
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
534-
k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY=
535-
k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
534+
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
535+
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
536536
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
537537
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
538538
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

providers/okta/okta.go

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,66 @@ func (c *Client) ListGroupUsers(ctx context.Context, groupId string, opts ...Lis
7676
return users, nil
7777
}
7878

79-
func (c *Client) GroupByName(ctx context.Context, groupName string) (*okta.Group, error) {
79+
func (c *Client) GroupByName(ctx context.Context, groupName string) (okta.Group, error) {
80+
8081
query := c.GroupAPI.ListGroups(ctx).Q(groupName)
8182
oktaGroups, _, err := query.Execute()
8283
if err != nil {
83-
return nil, fmt.Errorf("failed to query okta group: %w", err)
84+
return okta.Group{}, fmt.Errorf("failed to query okta group: %w", err)
8485
}
8586

8687
for _, group := range oktaGroups {
8788
if group.Profile != nil && group.Profile.Name != nil && *group.Profile.Name == groupName {
88-
return &group, nil
89+
return group, nil
90+
}
91+
}
92+
93+
return okta.Group{}, fmt.Errorf("unable to find okta group %q", groupName)
94+
}
95+
96+
func (c *Client) GroupsByName(ctx context.Context, groupNames []string, batchsize int) ([]okta.Group, error) {
97+
groups := []okta.Group{}
98+
99+
batches := buildFilterNameBatches(groupNames, batchsize)
100+
101+
for _, filter := range batches {
102+
// expanding stats to get the number of users in the group
103+
query := c.GroupAPI.ListGroups(ctx).Search(filter).Expand("stats")
104+
oktaGroups, resp, err := query.Execute()
105+
for {
106+
if err != nil {
107+
return nil, fmt.Errorf("failed to query okta group: %w", err)
108+
}
109+
110+
groups = append(groups, oktaGroups...)
111+
112+
if !resp.HasNextPage() {
113+
break
114+
}
115+
oktaGroups = []okta.Group{}
116+
resp, err = resp.Next(&oktaGroups)
117+
}
118+
}
119+
return groups, nil
120+
}
121+
122+
func buildFilterNameBatches(groupNames []string, batchsize int) []string {
123+
batches := []string{}
124+
for i := 0; i < len(groupNames); i += batchsize {
125+
end := i + batchsize
126+
if end > len(groupNames) {
127+
end = len(groupNames)
89128
}
129+
batches = append(batches, toFilterString(groupNames[i:end]))
90130
}
131+
return batches
132+
}
91133

92-
return nil, fmt.Errorf("unable to find okta group %q", groupName)
134+
func toFilterString(groupNames []string) string {
135+
if len(groupNames) == 0 {
136+
return ""
137+
}
138+
return fmt.Sprintf("profile.name eq \"%s\"", strings.Join(groupNames, "\" or profile.name eq \""))
93139
}
94140

95141
func jwkFromBytes(bytes []byte) (*jose.JSONWebKey, error) {

providers/okta/okta_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package okta
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestToFilterStringWithGroupNames(t *testing.T) {
10+
11+
tests := []struct {
12+
name string
13+
input []string
14+
output string
15+
}{
16+
{
17+
name: "single group name",
18+
input: []string{"group1"},
19+
output: "profile.name eq \"group1\"",
20+
},
21+
{
22+
name: "multiple group names",
23+
input: []string{"group1", "group2"},
24+
output: "profile.name eq \"group1\" or profile.name eq \"group2\"",
25+
},
26+
}
27+
28+
for _, test := range tests {
29+
t.Run(test.name, func(t *testing.T) {
30+
result := toFilterString(test.input)
31+
assert.Equal(t, test.output, result, "Expected filter string does not match the result")
32+
})
33+
}
34+
}
35+
36+
func TestBuildFilterNameBatches(t *testing.T) {
37+
tests := []struct {
38+
name string
39+
input []string
40+
batchSize int
41+
expected []string
42+
}{
43+
{
44+
name: "single batch",
45+
input: []string{"group1", "group2", "group3"},
46+
batchSize: 3,
47+
expected: []string{"profile.name eq \"group1\" or profile.name eq \"group2\" or profile.name eq \"group3\""},
48+
},
49+
{
50+
name: "multiple batches",
51+
input: []string{"group1", "group2", "group3", "group4", "group5"},
52+
batchSize: 2,
53+
expected: []string{"profile.name eq \"group1\" or profile.name eq \"group2\"", "profile.name eq \"group3\" or profile.name eq \"group4\"", "profile.name eq \"group5\""},
54+
},
55+
}
56+
57+
for _, test := range tests {
58+
t.Run(test.name, func(t *testing.T) {
59+
result := buildFilterNameBatches(test.input, test.batchSize)
60+
assert.Equal(t, test.expected, result, "Expected batches do not match the result")
61+
})
62+
}
63+
}

0 commit comments

Comments
 (0)