diff --git a/bridge-history-api/internal/config/config.go b/bridge-history-api/internal/config/config.go index a7f848a33..4b738e63b 100644 --- a/bridge-history-api/internal/config/config.go +++ b/bridge-history-api/internal/config/config.go @@ -6,6 +6,7 @@ import ( "path/filepath" "scroll-tech/common/database" + "scroll-tech/common/utils" ) // FetcherConfig is the configuration of Layer1 or Layer2 fetcher. @@ -66,5 +67,11 @@ func NewConfig(file string) (*Config, error) { return nil, err } + // Override config with environment variables + err = utils.OverrideConfigWithEnv(cfg, "SCROLL_BRIDGE_HISTORY") + if err != nil { + return nil, err + } + return cfg, nil } diff --git a/common/utils/utils.go b/common/utils/utils.go index db3552179..94e2efdf6 100644 --- a/common/utils/utils.go +++ b/common/utils/utils.go @@ -9,10 +9,14 @@ import ( "math/big" "os" "path/filepath" + "reflect" + "strconv" + "strings" "time" "github.com/modern-go/reflect2" "github.com/scroll-tech/go-ethereum/core" + "github.com/scroll-tech/go-ethereum/log" ) // TryTimes try run several times until the function return true. @@ -78,3 +82,89 @@ func ReadGenesis(genesisPath string) (*core.Genesis, error) { } return genesis, file.Close() } + +// OverrideConfigWithEnv recursively overrides config values with environment variables +func OverrideConfigWithEnv(cfg interface{}, prefix string) error { + v := reflect.ValueOf(cfg) + if v.Kind() != reflect.Ptr || v.IsNil() { + return nil + } + v = v.Elem() + + t := v.Type() + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + fieldValue := v.Field(i) + + if !fieldValue.CanSet() { + continue + } + + tag := field.Tag.Get("json") + if tag == "" { + tag = strings.ToLower(field.Name) + } + + envKey := prefix + "_" + strings.ToUpper(tag) + + switch fieldValue.Kind() { + case reflect.Ptr: + if !fieldValue.IsNil() { + err := OverrideConfigWithEnv(fieldValue.Interface(), envKey) + if err != nil { + return err + } + } + case reflect.Struct: + err := OverrideConfigWithEnv(fieldValue.Addr().Interface(), envKey) + if err != nil { + return err + } + default: + if envValue, exists := os.LookupEnv(envKey); exists { + log.Info("Overriding config with env var", "key", envKey) + err := setField(fieldValue, envValue) + if err != nil { + return err + } + } + } + } + + return nil +} + +// setField sets the value of a field based on the environment variable value +func setField(field reflect.Value, value string) error { + switch field.Kind() { + case reflect.String: + field.SetString(value) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + intValue, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return err + } + field.SetInt(intValue) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + uintValue, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return err + } + field.SetUint(uintValue) + case reflect.Float32, reflect.Float64: + floatValue, err := strconv.ParseFloat(value, 64) + if err != nil { + return err + } + field.SetFloat(floatValue) + case reflect.Bool: + boolValue, err := strconv.ParseBool(value) + if err != nil { + return err + } + field.SetBool(boolValue) + default: + return fmt.Errorf("unsupported type: %v", field.Kind()) + } + return nil +} diff --git a/coordinator/internal/config/config.go b/coordinator/internal/config/config.go index cbe9ca02d..2f45d68ff 100644 --- a/coordinator/internal/config/config.go +++ b/coordinator/internal/config/config.go @@ -6,6 +6,7 @@ import ( "path/filepath" "scroll-tech/common/database" + "scroll-tech/common/utils" ) // ProverManager loads sequencer configuration items. @@ -72,5 +73,11 @@ func NewConfig(file string) (*Config, error) { return nil, err } + // Override config with environment variables + err = utils.OverrideConfigWithEnv(cfg, "SCROLL_COORDINATOR") + if err != nil { + return nil, err + } + return cfg, nil } diff --git a/rollup/internal/config/config.go b/rollup/internal/config/config.go index 0de9b5ce8..673f414f1 100644 --- a/rollup/internal/config/config.go +++ b/rollup/internal/config/config.go @@ -6,6 +6,7 @@ import ( "path/filepath" "scroll-tech/common/database" + "scroll-tech/common/utils" ) // Config load configuration items. @@ -28,5 +29,11 @@ func NewConfig(file string) (*Config, error) { return nil, err } + // Override config with environment variables + err = utils.OverrideConfigWithEnv(cfg, "SCROLL_ROLLUP") + if err != nil { + return nil, err + } + return cfg, nil }