Skip to content

Commit 7c37706

Browse files
authored
remove use of ldclient (#438)
We had partially switched to using ld client for requests, but it's easier for us to maintain one client, so I'm removing it and using the main http client for consistency. Other - add a helper for all api paths - update to latest ldapi client `v15`, and latest api version `20220603` - disable `nilnil` in linter
1 parent 05f3582 commit 7c37706

File tree

718 files changed

+147048
-78177
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

718 files changed

+147048
-78177
lines changed

.golangci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ linters:
3838
- gocritic
3939
- depguard
4040
- tagalign
41+
- nilnil
4142
fast: false
4243

4344
linter-settings:

go.mod

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ require (
77
github.com/go-git/go-git/v5 v5.11.0
88
github.com/hashicorp/go-retryablehttp v0.7.5
99
github.com/iancoleman/strcase v0.3.0
10-
github.com/launchdarkly/api-client-go/v7 v7.1.1
1110
github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f
1211
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00
1312
github.com/olekukonko/tablewriter v0.0.5
@@ -19,6 +18,8 @@ require (
1918
golang.org/x/tools v0.19.0
2019
)
2120

21+
require github.com/launchdarkly/api-client-go/v15 v15.0.0
22+
2223
require (
2324
dario.cat/mergo v1.0.0 // indirect
2425
github.com/Microsoft/go-winio v0.6.1 // indirect
@@ -31,7 +32,7 @@ require (
3132
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
3233
github.com/go-git/go-billy/v5 v5.5.0 // indirect
3334
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
34-
github.com/golang/protobuf v1.5.3 // indirect
35+
github.com/golang/protobuf v1.5.4 // indirect
3536
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
3637
github.com/hashicorp/hcl v1.0.0 // indirect
3738
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -58,10 +59,10 @@ require (
5859
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
5960
golang.org/x/mod v0.16.0 // indirect
6061
golang.org/x/net v0.22.0 // indirect
61-
golang.org/x/oauth2 v0.15.0 // indirect
62+
golang.org/x/oauth2 v0.18.0 // indirect
6263
golang.org/x/sys v0.18.0 // indirect
6364
golang.org/x/text v0.14.0 // indirect
64-
google.golang.org/appengine v1.6.7 // indirect
65+
google.golang.org/appengine v1.6.8 // indirect
6566
google.golang.org/protobuf v1.33.0 // indirect
6667
gopkg.in/ini.v1 v1.67.0 // indirect
6768
gopkg.in/warnings.v0 v0.1.2 // indirect

go.sum

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
110110
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
111111
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
112112
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
113-
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
114-
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
113+
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
114+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
115+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
115116
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
116117
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
117118
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -162,8 +163,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
162163
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
163164
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
164165
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
165-
github.com/launchdarkly/api-client-go/v7 v7.1.1 h1:3VBkFt9xHljMw5KDlVFDUogxfH78Y7GLVu8irBC8Gy8=
166-
github.com/launchdarkly/api-client-go/v7 v7.1.1/go.mod h1:GVl1inKsWoKX3yLgdqrjxWw8k4ih0HlSmdnrhi5NNDs=
166+
github.com/launchdarkly/api-client-go/v15 v15.0.0 h1:tA1oYCrId9L9vE8nFtAtlqkYkjPtnlXeXFMqvuezDtA=
167+
github.com/launchdarkly/api-client-go/v15 v15.0.0/go.mod h1:7dpsX/epfhhRbCv5sEIxKng0xxYbzRYXlp0oJB3+XrQ=
167168
github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f h1:jfiPiz2hE/7mHv2NOS4cm07sSJCsKlbxmR7pzPhhvpU=
168169
github.com/launchdarkly/json-patch v0.0.0-20180720210516-dd68d883319f/go.mod h1:CHbYdMs8UjvNnS2fatlQvi4UYnBTRYGxRHc/0kQupSQ=
169170
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
@@ -330,8 +331,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
330331
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
331332
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
332333
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
333-
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
334-
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
334+
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
335+
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
335336
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
336337
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
337338
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -395,6 +396,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
395396
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
396397
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
397398
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
399+
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
398400
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
399401
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
400402
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
@@ -473,8 +475,8 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
473475
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
474476
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
475477
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
476-
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
477-
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
478+
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
479+
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
478480
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
479481
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
480482
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=

internal/ld/ld.go

Lines changed: 90 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package ld
22

33
import (
44
"bytes"
5-
"context"
65
"encoding/csv"
76
"encoding/json"
87
"errors"
@@ -21,14 +20,13 @@ import (
2120
h "github.com/hashicorp/go-retryablehttp"
2221
"github.com/olekukonko/tablewriter"
2322

24-
ldapi "github.com/launchdarkly/api-client-go/v7"
23+
ldapi "github.com/launchdarkly/api-client-go/v15"
2524
jsonpatch "github.com/launchdarkly/json-patch"
2625
"github.com/launchdarkly/ld-find-code-refs/v2/internal/log"
2726
"github.com/launchdarkly/ld-find-code-refs/v2/internal/validation"
2827
)
2928

3029
type ApiClient struct {
31-
ldClient *ldapi.APIClient
3230
httpClient *h.Client
3331
Options ApiOptions
3432
}
@@ -42,10 +40,10 @@ type ApiOptions struct {
4240
}
4341

4442
const (
45-
apiVersion = "20210729"
43+
apiVersion = "20220603"
4644
apiVersionHeader = "LD-API-Version"
4745
v2ApiPath = "/api/v2"
48-
reposPath = v2ApiPath + "/code-refs/repositories"
46+
reposPath = "/code-refs/repositories"
4947
)
5048

5149
type ConfigurationError struct {
@@ -113,62 +111,113 @@ func InitApiClient(options ApiOptions) ApiClient {
113111
client.Backoff = RateLimitBackoff(time.Now, h.LinearJitterBackoff)
114112

115113
return ApiClient{
116-
ldClient: ldapi.NewAPIClient(&ldapi.Configuration{
117-
HTTPClient: client.StandardClient(),
118-
UserAgent: options.UserAgent,
119-
Servers: []ldapi.ServerConfiguration{{
120-
URL: options.BaseUri,
121-
}},
122-
DefaultHeader: map[string]string{
123-
apiVersionHeader: apiVersion,
124-
},
125-
}),
126114
httpClient: client,
127115
Options: options,
128116
}
129117
}
130118

119+
// path should have leading slash
120+
func (c ApiClient) getPath(path string) string {
121+
return fmt.Sprintf("%s%s%s", c.Options.BaseUri, v2ApiPath, path)
122+
}
123+
131124
func (c ApiClient) GetFlagKeyList(projKey string) ([]string, error) {
132-
auth := map[string]ldapi.APIKey{
133-
"ApiKey": {Key: c.Options.ApiKey},
125+
env, err := c.getProjectEnvironment(projKey)
126+
if err != nil {
127+
return nil, err
134128
}
135-
ctx := context.WithValue(context.Background(), ldapi.ContextAPIKeys, auth)
136129

137-
project, _, err := c.ldClient.ProjectsApi.GetProject(ctx, projKey).Execute() //nolint:bodyclose
130+
params := url.Values{}
131+
if env != nil {
132+
params.Add("env", env.Key)
133+
}
134+
activeFlags, err := c.getFlags(projKey, params)
138135
if err != nil {
139136
return nil, err
140137
}
141138

142-
flagReq := c.ldClient.FeatureFlagsApi.GetFeatureFlags(ctx, projKey).Summary(true)
143-
archiveReq := c.ldClient.FeatureFlagsApi.GetFeatureFlags(ctx, projKey).Summary(true).Filter("state:archived")
139+
params.Add("filter", "state:archived")
140+
archivedFlags, err := c.getFlags(projKey, params)
141+
if err != nil {
142+
return nil, err
143+
}
144+
flags := make([]ldapi.FeatureFlag, 0, len(activeFlags)+len(archivedFlags))
145+
flags = append(flags, activeFlags...)
146+
flags = append(flags, archivedFlags...)
144147

145-
if len(project.Environments) > 0 {
146-
// The first environment allows filtering when retrieving flags.
147-
firstEnv := project.Environments[0]
148-
flagReq = flagReq.Env(firstEnv.Key)
149-
archiveReq = archiveReq.Env(firstEnv.Key)
148+
flagKeys := make([]string, 0, len(flags))
149+
for _, flag := range flags {
150+
flagKeys = append(flagKeys, flag.Key)
150151
}
151152

152-
flags, _, err := flagReq.Execute() //nolint:bodyclose
153+
return flagKeys, nil
154+
}
155+
156+
// Get the first environment we can find for a project
157+
func (c ApiClient) getProjectEnvironment(projKey string) (*ldapi.Environment, error) {
158+
urlStr := c.getPath(fmt.Sprintf("/projects/%s/environments", projKey))
159+
req, err := h.NewRequest(http.MethodGet, urlStr, nil)
153160
if err != nil {
154161
return nil, err
155162
}
156163

157-
archivedFlags, _, err := archiveReq.Execute() //nolint:bodyclose
164+
params := url.Values{}
165+
params.Add("limit", "1")
166+
req.URL.RawQuery = params.Encode()
167+
168+
res, err := c.do(req)
158169
if err != nil {
159170
return nil, err
160171
}
161172

162-
flagKeys := make([]string, 0, len(flags.Items))
163-
for _, flag := range append(flags.Items, archivedFlags.Items...) {
164-
flagKeys = append(flagKeys, flag.Key)
173+
resBytes, err := io.ReadAll(res.Body)
174+
if res != nil {
175+
defer res.Body.Close()
176+
}
177+
if err != nil {
178+
return nil, err
165179
}
166180

167-
return flagKeys, nil
181+
var collection ldapi.Environments
182+
if err := json.Unmarshal(resBytes, &collection); err != nil {
183+
return nil, err
184+
}
185+
if len(collection.Items) == 0 {
186+
return nil, nil
187+
}
188+
189+
env := collection.Items[0]
190+
191+
return &env, nil
168192
}
169193

170-
func (c ApiClient) repoUrl() string {
171-
return fmt.Sprintf("%s%s", c.Options.BaseUri, reposPath)
194+
func (c ApiClient) getFlags(projKey string, params url.Values) ([]ldapi.FeatureFlag, error) {
195+
url := c.getPath(fmt.Sprintf("/flags/%s", projKey))
196+
req, err := h.NewRequest(http.MethodGet, url, nil)
197+
if err != nil {
198+
return nil, err
199+
}
200+
req.URL.RawQuery = params.Encode()
201+
202+
res, err := c.do(req)
203+
if err != nil {
204+
return nil, err
205+
}
206+
207+
resBytes, err := io.ReadAll(res.Body)
208+
if res != nil {
209+
defer res.Body.Close()
210+
}
211+
if err != nil {
212+
return nil, err
213+
}
214+
215+
var flags ldapi.FeatureFlags
216+
if err := json.Unmarshal(resBytes, &flags); err != nil {
217+
return nil, err
218+
}
219+
220+
return flags.Items, nil
172221
}
173222

174223
func (c ApiClient) patchCodeReferenceRepository(currentRepo, repo RepoParams) error {
@@ -187,7 +236,7 @@ func (c ApiClient) patchCodeReferenceRepository(currentRepo, repo RepoParams) er
187236
return err
188237
}
189238

190-
req, err := h.NewRequest("PATCH", fmt.Sprintf("%s/%s", c.repoUrl(), repo.Name), bytes.NewBuffer(patch))
239+
req, err := h.NewRequest("PATCH", c.getPath(fmt.Sprintf("%s/%s", reposPath, repo.Name)), bytes.NewBuffer(patch))
191240
if err != nil {
192241
return err
193242
}
@@ -202,7 +251,7 @@ func (c ApiClient) patchCodeReferenceRepository(currentRepo, repo RepoParams) er
202251
}
203252

204253
func (c ApiClient) getCodeReferenceRepository(name string) (*RepoRep, error) {
205-
req, err := h.NewRequest("GET", fmt.Sprintf("%s/%s", c.repoUrl(), name), nil)
254+
req, err := h.NewRequest("GET", c.getPath(fmt.Sprintf("%s/%s", reposPath, name)), nil)
206255
if err != nil {
207256
return nil, err
208257
}
@@ -228,7 +277,7 @@ func (c ApiClient) getCodeReferenceRepository(name string) (*RepoRep, error) {
228277
}
229278

230279
func (c ApiClient) GetCodeReferenceRepositoryBranches(repoName string) ([]BranchRep, error) {
231-
req, err := h.NewRequest("GET", fmt.Sprintf("%s/%s/branches", c.repoUrl(), repoName), nil)
280+
req, err := h.NewRequest("GET", c.getPath(fmt.Sprintf("%s/%s/branches", reposPath, repoName)), nil)
232281
if err != nil {
233282
return nil, err
234283
}
@@ -259,7 +308,7 @@ func (c ApiClient) postCodeReferenceRepository(repo RepoParams) error {
259308
return err
260309
}
261310

262-
req, err := h.NewRequest("POST", c.repoUrl(), bytes.NewBuffer(repoBytes))
311+
req, err := h.NewRequest("POST", c.getPath(reposPath), bytes.NewBuffer(repoBytes))
263312
if err != nil {
264313
return err
265314
}
@@ -330,7 +379,7 @@ func (c ApiClient) PutCodeReferenceBranch(branch BranchRep, repoName string) err
330379
if err != nil {
331380
return err
332381
}
333-
putUrl := fmt.Sprintf("%s%s/%s/branches/%s", c.Options.BaseUri, reposPath, repoName, url.PathEscape(branch.Name))
382+
putUrl := c.getPath(fmt.Sprintf("%s/%s/branches/%s", reposPath, repoName, url.PathEscape(branch.Name)))
334383
req, err := h.NewRequest("PUT", putUrl, bytes.NewBuffer(branchBytes))
335384
if err != nil {
336385
return err
@@ -350,7 +399,7 @@ func (c ApiClient) PostExtinctionEvents(extinctions []ExtinctionRep, repoName, b
350399
if err != nil {
351400
return err
352401
}
353-
url := fmt.Sprintf("%s%s/%s/branches/%s/extinction-events", c.Options.BaseUri, reposPath, repoName, url.PathEscape(branchName))
402+
url := c.getPath(fmt.Sprintf("%s/%s/branches/%s/extinction-events", reposPath, repoName, url.PathEscape(branchName)))
354403
req, err := h.NewRequest("POST", url, bytes.NewBuffer(data))
355404
if err != nil {
356405
return err
@@ -370,7 +419,7 @@ func (c ApiClient) PostDeleteBranchesTask(repoName string, branches []string) er
370419
if err != nil {
371420
return err
372421
}
373-
url := fmt.Sprintf("%s%s/%s/branch-delete-tasks", c.Options.BaseUri, reposPath, repoName)
422+
url := c.getPath(fmt.Sprintf("%s/%s/branch-delete-tasks", reposPath, repoName))
374423
req, err := h.NewRequest("POST", url, bytes.NewBuffer(body))
375424
if err != nil {
376425
return err

vendor/github.com/launchdarkly/api-client-go/v7/.gitignore renamed to vendor/github.com/launchdarkly/api-client-go/v15/.gitignore

File renamed without changes.

vendor/github.com/launchdarkly/api-client-go/v7/.openapi-generator-ignore renamed to vendor/github.com/launchdarkly/api-client-go/v15/.openapi-generator-ignore

File renamed without changes.

vendor/github.com/launchdarkly/api-client-go/v7/.travis.yml renamed to vendor/github.com/launchdarkly/api-client-go/v15/.travis.yml

File renamed without changes.

vendor/github.com/launchdarkly/api-client-go/v7/LICENSE.txt renamed to vendor/github.com/launchdarkly/api-client-go/v15/LICENSE.txt

File renamed without changes.

0 commit comments

Comments
 (0)