@@ -97,6 +97,12 @@ func newConfig() *codersdk.DeploymentConfig {
97
97
},
98
98
},
99
99
},
100
+ GitAuth : & codersdk.DeploymentConfigField [[]codersdk.GitAuthConfig ]{
101
+ Name : "Git Auth" ,
102
+ Usage : "Automatically authenticate Git inside workspaces." ,
103
+ Flag : "gitauth" ,
104
+ Default : []codersdk.GitAuthConfig {},
105
+ },
100
106
Prometheus : & codersdk.PrometheusConfig {
101
107
Enable : & codersdk.DeploymentConfigField [bool ]{
102
108
Name : "Prometheus Enable" ,
@@ -407,6 +413,9 @@ func setConfig(prefix string, vip *viper.Viper, target interface{}) {
407
413
value = append (value , strings .Split (entry , "," )... )
408
414
}
409
415
val .FieldByName ("Value" ).Set (reflect .ValueOf (value ))
416
+ case []codersdk.GitAuthConfig :
417
+ values := readSliceFromViper [codersdk.GitAuthConfig ](vip , prefix , value )
418
+ val .FieldByName ("Value" ).Set (reflect .ValueOf (values ))
410
419
default :
411
420
panic (fmt .Sprintf ("unsupported type %T" , value ))
412
421
}
@@ -437,6 +446,44 @@ func setConfig(prefix string, vip *viper.Viper, target interface{}) {
437
446
}
438
447
}
439
448
449
+ // readSliceFromViper reads a typed mapping from the key provided.
450
+ // This enables environment variables like CODER_GITAUTH_<index>_CLIENT_ID.
451
+ func readSliceFromViper [T any ](vip * viper.Viper , key string , value any ) []T {
452
+ elementType := reflect .TypeOf (value ).Elem ()
453
+ returnValues := make ([]T , 0 )
454
+ for entry := 0 ; true ; entry ++ {
455
+ // Only create an instance when the entry exists in viper...
456
+ // otherwise we risk
457
+ var instance * reflect.Value
458
+ for i := 0 ; i < elementType .NumField (); i ++ {
459
+ fve := elementType .Field (i )
460
+ prop := fve .Tag .Get ("json" )
461
+ // For fields that are omitted in JSON, we use a YAML tag.
462
+ if prop == "-" {
463
+ prop = fve .Tag .Get ("yaml" )
464
+ }
465
+ value := vip .Get (fmt .Sprintf ("%s.%d.%s" , key , entry , prop ))
466
+ if value == nil {
467
+ continue
468
+ }
469
+ if instance == nil {
470
+ newType := reflect .Indirect (reflect .New (elementType ))
471
+ instance = & newType
472
+ }
473
+ instance .Field (i ).Set (reflect .ValueOf (value ))
474
+ }
475
+ if instance == nil {
476
+ break
477
+ }
478
+ value , ok := instance .Interface ().(T )
479
+ if ! ok {
480
+ continue
481
+ }
482
+ returnValues = append (returnValues , value )
483
+ }
484
+ return returnValues
485
+ }
486
+
440
487
func NewViper () * viper.Viper {
441
488
dc := newConfig ()
442
489
vip := viper .New ()
@@ -516,6 +563,8 @@ func setFlags(prefix string, flagset *pflag.FlagSet, vip *viper.Viper, target in
516
563
_ = flagset .DurationP (flg , shorthand , vip .GetDuration (prefix ), usage )
517
564
case []string :
518
565
_ = flagset .StringSliceP (flg , shorthand , vip .GetStringSlice (prefix ), usage )
566
+ case []codersdk.GitAuthConfig :
567
+ // Ignore this one!
519
568
default :
520
569
panic (fmt .Sprintf ("unsupported type %T" , typ ))
521
570
}
0 commit comments