@@ -19,7 +19,11 @@ import (
19
19
"go.k6.io/k6/cmd/state"
20
20
"go.k6.io/k6/errext"
21
21
"go.k6.io/k6/errext/exitcodes"
22
+ "go.k6.io/k6/ext"
22
23
"go.k6.io/k6/internal/log"
24
+ "go.k6.io/k6/secretsource"
25
+
26
+ _ "go.k6.io/k6/internal/secretsource" // import it to register internal secret sources
23
27
)
24
28
25
29
const waitLoggerCloseTimeout = time .Second * 5
@@ -162,6 +166,10 @@ func rootCmdPersistentFlagSet(gs *state.GlobalState) *pflag.FlagSet {
162
166
// `gs.DefaultFlags.<value>`, so that the `k6 --help` message is
163
167
// not messed up...
164
168
169
+ // TODO(@mstoykov): likely needs work - no env variables and such. No config.json.
170
+ flags .StringArrayVar (& gs .Flags .SecretSource , "secret-source" , gs .Flags .SecretSource ,
171
+ "setting secret sources for k6 file[=./path.fileformat]," )
172
+
165
173
flags .StringVar (& gs .Flags .LogOutput , "log-output" , gs .Flags .LogOutput ,
166
174
"change the output for k6 logs, possible values are stderr,stdout,none,loki[=host:port],file[=./path.fileformat]" )
167
175
flags .Lookup ("log-output" ).DefValue = gs .DefaultFlags .LogOutput
@@ -257,6 +265,22 @@ func (c *rootCommand) setupLoggers(stop <-chan struct{}) error {
257
265
c .globalState .Logger .Debug ("Logger format: TEXT" )
258
266
}
259
267
268
+ secretsources , err := createSecretSources (c .globalState )
269
+ if err != nil {
270
+ return err
271
+ }
272
+ // it is important that we add this hook first as hooks are executed in order of addition
273
+ // and this means no other hook will get secrets
274
+ var secretsHook logrus.Hook
275
+ c .globalState .SecretsManager , secretsHook , err = secretsource .NewSecretsManager (secretsources )
276
+ if err != nil {
277
+ return err
278
+ }
279
+ if len (secretsources ) != 0 {
280
+ // don't actually filter anything if there will be no secrets
281
+ c .globalState .Logger .AddHook (secretsHook )
282
+ }
283
+
260
284
cancel := func () {} // noop as default
261
285
if hook != nil {
262
286
ctx := context .Background ()
@@ -289,3 +313,49 @@ func (c *rootCommand) setLoggerHook(ctx context.Context, h log.AsyncHook) {
289
313
c .globalState .Logger .AddHook (h )
290
314
c .globalState .Logger .SetOutput (io .Discard ) // don't output to anywhere else
291
315
}
316
+
317
+ func createSecretSources (gs * state.GlobalState ) (map [string ]secretsource.SecretSource , error ) {
318
+ baseParams := secretsource.Params {
319
+ Logger : gs .Logger ,
320
+ Environment : gs .Env ,
321
+ FS : gs .FS ,
322
+ Usage : gs .Usage ,
323
+ }
324
+
325
+ result := make (map [string ]secretsource.SecretSource )
326
+ for _ , line := range gs .Flags .SecretSource {
327
+ t , config , ok := strings .Cut (line , "=" )
328
+ if ! ok {
329
+ return nil , fmt .Errorf ("couldn't parse secret source configuration %q" , line )
330
+ }
331
+ secretSources := ext .Get (ext .SecretSourceExtension )
332
+ found , ok := secretSources [t ]
333
+ if ! ok {
334
+ return nil , fmt .Errorf ("no secret source for type %q for configuration %q" , t , line )
335
+ }
336
+ c := found .Module .(secretsource.Constructor ) //nolint:forcetypeassert
337
+ params := baseParams
338
+ params .ConfigArgument = config
339
+ // TODO(@mstoykov): make it not configurable just from cmd line
340
+ // params.JSONConfig = test.derivedConfig.Collectors[outputType]
341
+
342
+ secretSource , err := c (params )
343
+ if err != nil {
344
+ return nil , err
345
+ }
346
+ name := secretSource .Name ()
347
+ _ , alreadRegistered := result [name ]
348
+ if alreadRegistered {
349
+ return nil , fmt .Errorf ("secret source for name %q already registered before configuration %q" , t , line )
350
+ }
351
+ result [name ] = secretSource
352
+ }
353
+
354
+ if len (result ) == 1 {
355
+ for _ , l := range result {
356
+ result ["default" ] = l
357
+ }
358
+ }
359
+
360
+ return result , nil
361
+ }
0 commit comments