Skip to content

Commit 08cdc2f

Browse files
resolved ahrav comments
1 parent 8d6265f commit 08cdc2f

File tree

1 file changed

+71
-66
lines changed

1 file changed

+71
-66
lines changed

pkg/analyzer/analyzers/launchdarkly/requests.go

+71-66
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,41 @@
11
package launchdarkly
22

33
import (
4+
"context"
45
_ "embed"
56
"encoding/json"
67
"errors"
78
"fmt"
89
"io"
910
"net/http"
10-
"strings"
11+
"strconv"
1112
"sync"
1213
"time"
1314
)
1415

16+
const defaultTimeout = 5 * time.Second
17+
1518
var (
1619
baseURL = "https://app.launchdarkly.com/api"
1720

1821
endpoints = map[string]string{
22+
// user information APIs
1923
"callerIdentity": "/v2/caller-identity",
2024
"getToken": "/v2/tokens/%s", // require token id
2125
"getRole": "/v2/roles/%s", // require role id
22-
applicationKey: "/v2/applications",
23-
repositoryKey: "/v2/code-refs/repositories",
24-
projectKey: "/v2/projects",
25-
environmentKey: "/v2/projects/%s/environments", // require project key
26-
featureFlagsKey: "/v2/flags/%s", // require project key
27-
experimentKey: "/v2/projects/%s/environments/%s/experiments", // require project key and env key
28-
holdoutsKey: "/v2/projects/%s/environments/%s/holdouts", // require project key and env key
29-
membersKey: "/v2/members",
30-
destinationsKey: "/v2/destinations",
31-
templatesKey: "/v2/templates",
32-
teamsKey: "/v2/teams",
33-
webhooksKey: "/v2/webhooks",
26+
// resource APIs
27+
applicationKey: "/v2/applications",
28+
repositoryKey: "/v2/code-refs/repositories",
29+
projectKey: "/v2/projects",
30+
environmentKey: "/v2/projects/%s/environments", // require project key
31+
featureFlagsKey: "/v2/flags/%s", // require project key
32+
experimentKey: "/v2/projects/%s/environments/%s/experiments", // require project key and env key
33+
holdoutsKey: "/v2/projects/%s/environments/%s/holdouts", // require project key and env key
34+
membersKey: "/v2/members",
35+
destinationsKey: "/v2/destinations",
36+
templatesKey: "/v2/templates",
37+
teamsKey: "/v2/teams",
38+
webhooksKey: "/v2/webhooks",
3439
/*
3540
TODO:
3641
release piplelines: https://launchdarkly.com/docs/api/release-pipelines-beta/get-all-release-pipelines (Beta)
@@ -169,8 +174,11 @@ type webhooksResponse struct {
169174

170175
// makeLaunchDarklyRequest send the HTTP GET API request to passed url with passed token and return response body and status code
171176
func makeLaunchDarklyRequest(client *http.Client, endpoint, token string) ([]byte, int, error) {
177+
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
178+
defer cancel()
179+
172180
// create request
173-
req, err := http.NewRequest(http.MethodGet, baseURL+endpoint, http.NoBody)
181+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL+endpoint, http.NoBody)
174182
if err != nil {
175183
return nil, 0, err
176184
}
@@ -200,16 +208,15 @@ func makeLaunchDarklyRequest(client *http.Client, endpoint, token string) ([]byt
200208
func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo) error {
201209
var (
202210
wg sync.WaitGroup
203-
errChan = make(chan error)
204-
aggregatedErrs = make([]string, 0)
211+
aggregatedErrs = make([]error, 0)
205212
)
206213

207214
wg.Add(1)
208215
go func() {
209216
defer wg.Done()
210217

211218
if err := captureApplications(client, token, secretInfo); err != nil {
212-
errChan <- err
219+
aggregatedErrs = append(aggregatedErrs, err)
213220
}
214221
}()
215222

@@ -218,7 +225,7 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
218225
defer wg.Done()
219226

220227
if err := captureRepositories(client, token, secretInfo); err != nil {
221-
errChan <- err
228+
aggregatedErrs = append(aggregatedErrs, err)
222229
}
223230
}()
224231

@@ -227,7 +234,7 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
227234
defer wg.Done()
228235

229236
if err := captureProjects(client, token, secretInfo); err != nil {
230-
errChan <- err
237+
aggregatedErrs = append(aggregatedErrs, err)
231238
}
232239

233240
// for each project capture it's flags, environments and other sub resources
@@ -237,15 +244,15 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
237244
go func() {
238245
defer wg.Done()
239246
if err := captureProjectFeatureFlags(client, token, project, secretInfo); err != nil {
240-
errChan <- err
247+
aggregatedErrs = append(aggregatedErrs, err)
241248
}
242249
}()
243250

244251
wg.Add(1)
245252
go func() {
246253
defer wg.Done()
247254
if err := captureProjectEnv(client, token, project, secretInfo); err != nil {
248-
errChan <- err
255+
aggregatedErrs = append(aggregatedErrs, err)
249256
}
250257
}()
251258
}
@@ -256,7 +263,7 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
256263
defer wg.Done()
257264

258265
if err := captureMembers(client, token, secretInfo); err != nil {
259-
errChan <- err
266+
aggregatedErrs = append(aggregatedErrs, err)
260267
}
261268
}()
262269

@@ -265,7 +272,7 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
265272
defer wg.Done()
266273

267274
if err := captureDestinations(client, token, secretInfo); err != nil {
268-
errChan <- err
275+
aggregatedErrs = append(aggregatedErrs, err)
269276
}
270277
}()
271278

@@ -274,7 +281,7 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
274281
defer wg.Done()
275282

276283
if err := captureTemplates(client, token, secretInfo); err != nil {
277-
errChan <- err
284+
aggregatedErrs = append(aggregatedErrs, err)
278285
}
279286
}()
280287

@@ -283,7 +290,7 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
283290
defer wg.Done()
284291

285292
if err := captureTeams(client, token, secretInfo); err != nil {
286-
errChan <- err
293+
aggregatedErrs = append(aggregatedErrs, err)
287294
}
288295
}()
289296

@@ -292,20 +299,14 @@ func CaptureResources(client *http.Client, token string, secretInfo *SecretInfo)
292299
defer wg.Done()
293300

294301
if err := captureWebhooks(client, token, secretInfo); err != nil {
295-
errChan <- err
302+
aggregatedErrs = append(aggregatedErrs, err)
296303
}
297304
}()
298305

299306
wg.Wait()
300-
close(errChan)
301-
302-
// collect all errors
303-
for err := range errChan {
304-
aggregatedErrs = append(aggregatedErrs, err.Error())
305-
}
306307

307308
if len(aggregatedErrs) > 0 {
308-
return errors.New(strings.Join(aggregatedErrs, ", "))
309+
return errors.Join(aggregatedErrs...)
309310
}
310311

311312
return nil
@@ -331,12 +332,13 @@ func captureApplications(client *http.Client, token string, secretInfo *SecretIn
331332
ID: fmt.Sprintf("launchdarkly/app/%s", application.Key),
332333
Name: application.Name,
333334
Type: applicationKey,
335+
MetaData: map[string]string{
336+
"Maintainer Email": application.Maintainer.Email,
337+
"Kind": application.Kind,
338+
MetadataKey: application.Key,
339+
},
334340
}
335341

336-
resource.updateResourceMetadata("Maintainer Email", application.Maintainer.Email)
337-
resource.updateResourceMetadata("Kind", application.Kind)
338-
resource.updateResourceMetadata(MetadataKey, application.Key)
339-
340342
secretInfo.appendResource(resource)
341343
}
342344

@@ -368,12 +370,14 @@ func captureRepositories(client *http.Client, token string, secretInfo *SecretIn
368370
ID: fmt.Sprintf("%s/repo/%s/%d", repository.Type, repository.Name, repository.Version), // no unique id exist, so we make one
369371
Name: repository.Name,
370372
Type: repositoryKey,
373+
MetaData: map[string]string{
374+
"Default branch": repository.DefaultBranch,
375+
"Version": strconv.Itoa(repository.Version),
376+
"Source link": repository.SourceLink,
377+
MetadataKey: repositoryKey,
378+
},
371379
}
372380

373-
resource.updateResourceMetadata("Default branch", repository.DefaultBranch)
374-
resource.updateResourceMetadata("Version", fmt.Sprintf("%d", repository.Version))
375-
resource.updateResourceMetadata("Source link", repository.SourceLink)
376-
377381
secretInfo.appendResource(resource)
378382
}
379383

@@ -444,11 +448,12 @@ func captureProjectFeatureFlags(client *http.Client, token string, parent Resour
444448
ID: fmt.Sprintf("launchdarkly/proj/%s/flag/%s", projectKey, flag.Key),
445449
Name: flag.Name,
446450
Type: featureFlagsKey,
451+
MetaData: map[string]string{
452+
"Kind": flag.Kind,
453+
},
454+
ParentResource: &parent,
447455
}
448456

449-
resource.updateResourceMetadata("Kind", flag.Kind)
450-
resource.setParentResource(&resource, &parent)
451-
452457
secretInfo.appendResource(resource)
453458
}
454459

@@ -488,10 +493,9 @@ func captureProjectEnv(client *http.Client, token string, parent Resource, secre
488493
MetaData: map[string]string{
489494
MetadataKey: env.Key,
490495
},
496+
ParentResource: &parent,
491497
}
492498

493-
resource.setParentResource(&resource, &parent)
494-
495499
secretInfo.appendResource(resource)
496500

497501
// capture project env child resources
@@ -538,14 +542,12 @@ func captureProjectEnvExperiments(client *http.Client, token string, projectKey
538542
Name: exp.Name,
539543
Type: experimentKey,
540544
MetaData: map[string]string{
541-
MetadataKey: exp.Key,
545+
MetadataKey: exp.Key,
546+
"Maintiner ID": exp.MaintainerID,
542547
},
548+
ParentResource: &parent,
543549
}
544550

545-
resource.updateResourceMetadata(MetadataKey, exp.Key)
546-
resource.updateResourceMetadata("Maintainer ID", exp.MaintainerID)
547-
548-
resource.setParentResource(&resource, &parent)
549551
secretInfo.appendResource(resource)
550552
}
551553

@@ -585,13 +587,13 @@ func captureProjectHoldouts(client *http.Client, token string, projectKey string
585587
ID: fmt.Sprintf("launchdarkly/%s/env/%s/holdout/%s", projectKey, envKey, holdout.ID),
586588
Name: holdout.Name,
587589
Type: holdoutsKey,
590+
MetaData: map[string]string{
591+
"Status": holdout.Status,
592+
holdoutsKey: holdout.Key,
593+
},
594+
ParentResource: &parent,
588595
}
589596

590-
resource.updateResourceMetadata("Status", holdout.Status)
591-
resource.updateResourceMetadata(holdoutsKey, holdout.Key)
592-
593-
resource.setParentResource(&resource, &parent)
594-
595597
secretInfo.appendResource(resource)
596598
}
597599

@@ -623,11 +625,12 @@ func captureMembers(client *http.Client, token string, secretInfo *SecretInfo) e
623625
ID: fmt.Sprintf("launchdarkly/member/%s", member.ID),
624626
Name: member.FirstName + " " + member.LastName,
625627
Type: membersKey,
628+
MetaData: map[string]string{
629+
"Role": member.Role,
630+
"Email": member.Email,
631+
},
626632
}
627633

628-
resource.updateResourceMetadata("Role", member.Role)
629-
resource.updateResourceMetadata("Email", member.Email)
630-
631634
secretInfo.appendResource(resource)
632635
}
633636

@@ -659,11 +662,12 @@ func captureDestinations(client *http.Client, token string, secretInfo *SecretIn
659662
ID: fmt.Sprintf("launchdarkly/destination/%s", destination.ID),
660663
Name: destination.Name,
661664
Type: destinationsKey,
665+
MetaData: map[string]string{
666+
"Kind": destination.Kind,
667+
"Version": strconv.Itoa(destination.Version),
668+
},
662669
}
663670

664-
resource.updateResourceMetadata("Kind", destination.Kind)
665-
resource.updateResourceMetadata("Version", fmt.Sprintf("%d", destination.Version))
666-
667671
secretInfo.appendResource(resource)
668672
}
669673

@@ -728,12 +732,13 @@ func captureTeams(client *http.Client, token string, secretInfo *SecretInfo) err
728732
ID: fmt.Sprintf("launchdarkly/teams/%s", team.Key),
729733
Name: team.Name,
730734
Type: teamsKey,
735+
MetaData: map[string]string{
736+
"Total Roles Count": strconv.Itoa(team.Roles.TotalCount),
737+
"Total Memvers Count": strconv.Itoa(team.Members.TotalCount),
738+
"Total Projects Count": strconv.Itoa(team.Projects.TotalCount),
739+
},
731740
}
732741

733-
resource.updateResourceMetadata("Total Roles Count", fmt.Sprintf("%d", team.Roles.TotalCount))
734-
resource.updateResourceMetadata("Total Members Count", fmt.Sprintf("%d", team.Members.TotalCount))
735-
resource.updateResourceMetadata("Total Projects Count", fmt.Sprintf("%d", team.Projects.TotalCount))
736-
737742
secretInfo.appendResource(resource)
738743
}
739744

0 commit comments

Comments
 (0)