diff --git a/go.mod b/go.mod new file mode 100644 index 000000000..6c8e1696b --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/cartesi/rollups-node + +go 1.21.1 diff --git a/internal/cmd/print_config/main.go b/internal/cmd/print_config/main.go new file mode 100644 index 000000000..d84b5075e --- /dev/null +++ b/internal/cmd/print_config/main.go @@ -0,0 +1,10 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package main + +import "github.com/cartesi/rollups-node/internal/pkg/config" + +func main() { + config.PrintDocumentation() +} diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go new file mode 100644 index 000000000..1e52aab4f --- /dev/null +++ b/internal/pkg/config/config.go @@ -0,0 +1,35 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +// This package loads the node config from enviroment variables +package config + +import ( + "fmt" + "os" +) + +// Prefix to all enviroment variables +const Prefix string = "CARTESI_" + +// Definition of config variables. +// For each variable declared below, there should be a entry in meta.go. + +var PrintConfig bool +var LogLevel string + +// Prints the documentation for each variable in Stdout +func PrintDocumentation() { + genDocumentation(os.Stdout) +} + +// Loads the config from the environment. +// If PrintConfig is true, prints the config to Stdout. +// This function calls os.Exit if there is an error. +func Load() { + err := loadFromEnv(os.Stdout) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/internal/pkg/config/meta.go b/internal/pkg/config/meta.go new file mode 100644 index 000000000..d3f1d49ee --- /dev/null +++ b/internal/pkg/config/meta.go @@ -0,0 +1,78 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package config + +import ( + "errors" + "fmt" + "io" + "os" + "slices" +) + +// Describes a config variable. +// This is useful for automatically generating documentation. +type MetaConfig struct { + key string + description string + defaultValue string + parse func(string) error +} + +func (c MetaConfig) getKey() string { + return Prefix + c.key +} + +// Meta config for each config variable +var configs []MetaConfig = []MetaConfig{ + { + "PRINT_CONFIG", + "If 'true' prints the config variables as they are parsed.\n" + + "Can be 'true' or 'false'.", + "true", + func(value string) error { + var err error + PrintConfig, err = parseBool(value) + return err + }, + }, + { + "LOG_LEVEL", + "Sets the log level of the node, can be 'trace', 'info', or 'warning'.", + "info", + func(value string) error { + valid := []string{"trace", "info", "warning"} + if !slices.Contains(valid, value) { + return errors.New("invalid value") + } + LogLevel = value + return nil + }, + }, +} + +func loadFromEnv(writer io.Writer) error { + for _, c := range configs { + value, exists := os.LookupEnv(c.getKey()) + if !exists { + value = c.defaultValue + } + err := c.parse(value) + if err != nil { + msg := "failed to parse %v=%v because of %v" + return errors.New(fmt.Sprintf(msg, c.getKey(), value, err)) + } + if PrintConfig { + fmt.Fprintf(writer, "%v=%v\n", c.getKey(), value) + } + } + return nil +} + +func genDocumentation(writer io.Writer) { + for _, c := range configs { + msg := "## %v\n%v\nDefault value: '%v'\n\n" + fmt.Fprintf(writer, msg, c.getKey(), c.description, c.defaultValue) + } +} diff --git a/internal/pkg/config/util.go b/internal/pkg/config/util.go new file mode 100644 index 000000000..6893e9add --- /dev/null +++ b/internal/pkg/config/util.go @@ -0,0 +1,18 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package config + +import "errors" + +// Reads a boolean value from the string +func parseBool(value string) (bool, error) { + switch value { + case "true": + return true, nil + case "false": + return false, nil + default: + return false, errors.New("invalid value") + } +}