Skip to content

Commit 915cde7

Browse files
fix: batch + retry enterprise cost center resources
1 parent e99ab58 commit 915cde7

File tree

1 file changed

+119
-27
lines changed

1 file changed

+119
-27
lines changed

github/resource_github_enterprise_cost_center_resources.go

Lines changed: 119 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,12 @@ func resourceGithubEnterpriseCostCenterResourcesUpdate(d *schema.ResourceData, m
130130
toAddOrgs, toRemoveOrgs := diffStringSlices(currentOrgs, desiredOrgs)
131131
toAddRepos, toRemoveRepos := diffStringSlices(currentRepos, desiredRepos)
132132

133-
if len(toRemoveUsers)+len(toRemoveOrgs)+len(toRemoveRepos) > 0 {
134-
log.Printf("[INFO] Removing enterprise cost center resources: %s/%s", enterpriseSlug, costCenterID)
135-
err := resource.RetryContext(ctx, 30*time.Second, func() *resource.RetryError {
136-
_, err := enterpriseCostCenterRemoveResources(ctx, client, enterpriseSlug, costCenterID, enterpriseCostCenterResourcesRequest{
137-
Users: toRemoveUsers,
138-
Organizations: toRemoveOrgs,
139-
Repositories: toRemoveRepos,
140-
})
133+
const maxResourcesPerRequest = 50
134+
const costCenterResourcesRetryTimeout = 5 * time.Minute
135+
136+
retryRemove := func(req enterpriseCostCenterResourcesRequest) error {
137+
return resource.RetryContext(ctx, costCenterResourcesRetryTimeout, func() *resource.RetryError {
138+
_, err := enterpriseCostCenterRemoveResources(ctx, client, enterpriseSlug, costCenterID, req)
141139
if err == nil {
142140
return nil
143141
}
@@ -146,19 +144,11 @@ func resourceGithubEnterpriseCostCenterResourcesUpdate(d *schema.ResourceData, m
146144
}
147145
return resource.NonRetryableError(err)
148146
})
149-
if err != nil {
150-
return err
151-
}
152147
}
153148

154-
if len(toAddUsers)+len(toAddOrgs)+len(toAddRepos) > 0 {
155-
log.Printf("[INFO] Assigning enterprise cost center resources: %s/%s", enterpriseSlug, costCenterID)
156-
err := resource.RetryContext(ctx, 30*time.Second, func() *resource.RetryError {
157-
_, err := enterpriseCostCenterAssignResources(ctx, client, enterpriseSlug, costCenterID, enterpriseCostCenterResourcesRequest{
158-
Users: toAddUsers,
159-
Organizations: toAddOrgs,
160-
Repositories: toAddRepos,
161-
})
149+
retryAssign := func(req enterpriseCostCenterResourcesRequest) error {
150+
return resource.RetryContext(ctx, costCenterResourcesRetryTimeout, func() *resource.RetryError {
151+
_, err := enterpriseCostCenterAssignResources(ctx, client, enterpriseSlug, costCenterID, req)
162152
if err == nil {
163153
return nil
164154
}
@@ -167,8 +157,63 @@ func resourceGithubEnterpriseCostCenterResourcesUpdate(d *schema.ResourceData, m
167157
}
168158
return resource.NonRetryableError(err)
169159
})
170-
if err != nil {
171-
return err
160+
}
161+
162+
chunk := func(items []string, size int) [][]string {
163+
if len(items) == 0 {
164+
return nil
165+
}
166+
if size <= 0 {
167+
size = len(items)
168+
}
169+
chunks := make([][]string, 0, (len(items)+size-1)/size)
170+
for start := 0; start < len(items); start += size {
171+
end := start + size
172+
if end > len(items) {
173+
end = len(items)
174+
}
175+
chunks = append(chunks, items[start:end])
176+
}
177+
return chunks
178+
}
179+
180+
if len(toRemoveUsers)+len(toRemoveOrgs)+len(toRemoveRepos) > 0 {
181+
log.Printf("[INFO] Removing enterprise cost center resources: %s/%s", enterpriseSlug, costCenterID)
182+
183+
for _, batch := range chunk(toRemoveUsers, maxResourcesPerRequest) {
184+
if err := retryRemove(enterpriseCostCenterResourcesRequest{Users: batch}); err != nil {
185+
return err
186+
}
187+
}
188+
for _, batch := range chunk(toRemoveOrgs, maxResourcesPerRequest) {
189+
if err := retryRemove(enterpriseCostCenterResourcesRequest{Organizations: batch}); err != nil {
190+
return err
191+
}
192+
}
193+
for _, batch := range chunk(toRemoveRepos, maxResourcesPerRequest) {
194+
if err := retryRemove(enterpriseCostCenterResourcesRequest{Repositories: batch}); err != nil {
195+
return err
196+
}
197+
}
198+
}
199+
200+
if len(toAddUsers)+len(toAddOrgs)+len(toAddRepos) > 0 {
201+
log.Printf("[INFO] Assigning enterprise cost center resources: %s/%s", enterpriseSlug, costCenterID)
202+
203+
for _, batch := range chunk(toAddUsers, maxResourcesPerRequest) {
204+
if err := retryAssign(enterpriseCostCenterResourcesRequest{Users: batch}); err != nil {
205+
return err
206+
}
207+
}
208+
for _, batch := range chunk(toAddOrgs, maxResourcesPerRequest) {
209+
if err := retryAssign(enterpriseCostCenterResourcesRequest{Organizations: batch}); err != nil {
210+
return err
211+
}
212+
}
213+
for _, batch := range chunk(toAddRepos, maxResourcesPerRequest) {
214+
if err := retryAssign(enterpriseCostCenterResourcesRequest{Repositories: batch}); err != nil {
215+
return err
216+
}
172217
}
173218
}
174219

@@ -202,12 +247,59 @@ func resourceGithubEnterpriseCostCenterResourcesDelete(d *schema.ResourceData, m
202247
return nil
203248
}
204249

205-
_, err = enterpriseCostCenterRemoveResources(ctx, client, enterpriseSlug, costCenterID, enterpriseCostCenterResourcesRequest{
206-
Users: users,
207-
Organizations: orgs,
208-
Repositories: repos,
209-
})
210-
return err
250+
const maxResourcesPerRequest = 50
251+
const costCenterResourcesRetryTimeout = 5 * time.Minute
252+
253+
retryRemove := func(req enterpriseCostCenterResourcesRequest) error {
254+
return resource.RetryContext(ctx, costCenterResourcesRetryTimeout, func() *resource.RetryError {
255+
_, err := enterpriseCostCenterRemoveResources(ctx, client, enterpriseSlug, costCenterID, req)
256+
if err == nil {
257+
return nil
258+
}
259+
if isRetryableGithubResponseError(err) {
260+
return resource.RetryableError(err)
261+
}
262+
return resource.NonRetryableError(err)
263+
})
264+
}
265+
266+
chunk := func(items []string, size int) [][]string {
267+
if len(items) == 0 {
268+
return nil
269+
}
270+
if size <= 0 {
271+
size = len(items)
272+
}
273+
chunks := make([][]string, 0, (len(items)+size-1)/size)
274+
for start := 0; start < len(items); start += size {
275+
end := start + size
276+
if end > len(items) {
277+
end = len(items)
278+
}
279+
chunks = append(chunks, items[start:end])
280+
}
281+
return chunks
282+
}
283+
284+
log.Printf("[INFO] Removing all enterprise cost center resources: %s/%s", enterpriseSlug, costCenterID)
285+
286+
for _, batch := range chunk(users, maxResourcesPerRequest) {
287+
if err := retryRemove(enterpriseCostCenterResourcesRequest{Users: batch}); err != nil {
288+
return err
289+
}
290+
}
291+
for _, batch := range chunk(orgs, maxResourcesPerRequest) {
292+
if err := retryRemove(enterpriseCostCenterResourcesRequest{Organizations: batch}); err != nil {
293+
return err
294+
}
295+
}
296+
for _, batch := range chunk(repos, maxResourcesPerRequest) {
297+
if err := retryRemove(enterpriseCostCenterResourcesRequest{Repositories: batch}); err != nil {
298+
return err
299+
}
300+
}
301+
302+
return nil
211303
}
212304

213305
func resourceGithubEnterpriseCostCenterResourcesImport(d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) {

0 commit comments

Comments
 (0)