@@ -3,6 +3,8 @@ package client
33import (
44 "context"
55 "fmt"
6+ "net/http"
7+ "time"
68
79 "github.com/cloudquery/plugin-sdk/plugins/source"
810 "github.com/cloudquery/plugin-sdk/schema"
@@ -11,13 +13,21 @@ import (
1113 "github.com/rs/zerolog"
1214)
1315
16+ const (
17+ defaultMaxRetries = 5
18+ defaultBackoff = 60 * time .Second
19+ )
20+
1421type Client struct {
1522 * snyk.Client
1623
1724 OrganizationID string
1825 organizations []string
1926
2027 logger zerolog.Logger
28+
29+ maxRetries int
30+ backoff time.Duration // backoff duration between retries (jitter will be added)
2131}
2232
2333var _ schema.ClientMeta = (* Client )(nil )
@@ -30,14 +40,61 @@ func (c *Client) Logger() *zerolog.Logger {
3040 return & c .logger
3141}
3242
43+ type SnykLogger struct {
44+ logger zerolog.Logger
45+ }
46+
47+ func (l * SnykLogger ) Log (args ... any ) {
48+ if len (args ) == 1 {
49+ l .logger .Debug ().Interface ("msg" , args [0 ]).Msgf ("Log from Snyk SDK" )
50+ return
51+ }
52+ if len (args )% 2 != 0 {
53+ l .logger .Debug ().Interface ("args" , args ).Msgf ("Log from Snyk SDK" )
54+ return
55+ }
56+ m := l .logger .Debug ()
57+ for i := 0 ; i < len (args ); i += 2 {
58+ k , ok := args [i ].(string )
59+ if ! ok {
60+ m = m .Interface (fmt .Sprintf ("arg%02d" , i ), args [i ])
61+ m = m .Interface (fmt .Sprintf ("arg%02d" , i + 1 ), args [i + 1 ])
62+ continue
63+ }
64+ if i + 1 < len (args ) {
65+ m = m .Interface (k , args [i + 1 ])
66+ }
67+ }
68+ m .Msg ("Log from Snyk SDK" )
69+ }
70+
3371func Configure (ctx context.Context , logger zerolog.Logger , spec specs.Source , _ source.Options ) (schema.ClientMeta , error ) {
3472 snykSpec := new (Spec )
3573 err := spec .UnmarshalSpec (snykSpec )
3674 if err != nil {
3775 return nil , fmt .Errorf ("failed to unmarshal spec: %w" , err )
3876 }
77+ err = snykSpec .Validate ()
78+ if err != nil {
79+ return nil , fmt .Errorf ("failed to validate spec: %w" , err )
80+ }
81+
82+ snykLogger := SnykLogger {
83+ logger : logger ,
84+ }
85+ httpClient := http .DefaultClient
86+ httpClient .Timeout = 1 * time .Minute
87+ options := []snyk.ClientOption {
88+ snyk .WithHTTPClient (httpClient ),
89+ snyk .WithUserAgent ("cloudquery/snyk/" + spec .Version ),
90+ snyk .WithLogger (& snykLogger ),
91+ snyk .WithLogRequests (true ), // these will be filtered out by the logger if not in debug mode
92+ }
93+ if len (snykSpec .EndpointURL ) > 0 {
94+ options = append (options , snyk .WithBaseURL (snykSpec .EndpointURL ))
95+ }
3996
40- client , err := snykSpec . getClient ( spec . Version )
97+ client := snyk . NewClient ( snykSpec . APIKey , options ... )
4198 if err != nil {
4299 return nil , fmt .Errorf ("failed to create Snyk client: %w" , err )
43100 }
@@ -46,6 +103,8 @@ func Configure(ctx context.Context, logger zerolog.Logger, spec specs.Source, _
46103 Client : client ,
47104 logger : logger ,
48105 organizations : snykSpec .Organizations ,
106+ maxRetries : defaultMaxRetries ,
107+ backoff : defaultBackoff ,
49108 }
50109
51110 return c , c .initOrganizations (ctx )
0 commit comments