Insolar configurations unify configuring for all Insolar applications: Assured Ledger, Insolar Observer, Insolar MainNet, Insolar Explorer and more.
Configurations are consolidated into a single configuration library that is a wrapper for Viper.
Configurations are used by Insolar applications as a dependency.
Insolar is extensively documented. If you need more information on what is Insolar, visit Insolar Docs.
- .yaml format of configuration files.
- No default configuration paths. A path should be explicitly set by the "--config/-c" flag. Optionally, you can override this by implementing ConfigPathGetter (look at
configurator_test.go
for details). - Environment values override file values.
- Option to use only ENV, without a configuration file at all.
- Option to write the config file content to the log file at an app launch.
- Hiding sensitive data via the
insconfigsecret
tag. - No default values in a configuration file. All values should be set explicitly, otherwise the library returns an error.
- No unnecessary field or parameters both in a configuration file and ENV, otherwise the library returns an error. Consider as unecessary: fields in a config struct unused in a configuration file, old or obsolete parameters in a configuration file that are not currently used, unused parameters in ENV.
- Support of custom flags, go flags and pflags.
- No overriding configutation files by flags.
- Option to generate an empty .yaml file with field descriptions.
- Automatic adding of the
--config
flag. - [work in progress] Automatic of the
--gen-config
flag. - No overriding app configuration on the fly.
- Support of custom Viper decode hooks.
Consider the example in ./example/example.go
.
Run the example:
run ./example/example.go --config="./example/example_config.yaml"
In addition:
-
Test the code snippets below by replacing the contents of
func main()
inexample.go
with them. -
Modify the snippets appropriately to include them directly into your code. Pay attention to variable and configuration field contents.
Tip: Don't forget to add github.com/soverenio/insconfig
to the import section.
Note: EnvPrefix
value shouldn't have any delimiters: EnvPrefix: "incorrect example"
has incorrect syntax, while EnvPrefix: "correctexample"
has correct syntax.
If you don't use any flags and DefaultPathGetter, which adds the --config
flag so you can start right away, consider this example for func main()
:
mconf := &Config{}
params := insconfig.Params{
EnvPrefix: "example",
ConfigPathGetter: &insconfig.DefaultPathGetter{},
}
insConfigurator := insconfig.New(params)
if err := insConfigurator.Load(mconf); err != nil {
panic(err)
}
insConfigurator.ToYaml(mconf)
fmt.Println(insConfigurator.ToYaml(mconf))
var flag_example_1 = flag.String("flag_example_1", "example_value", "flag_example_1_desc")
mconf := Config{}
params := insconfig.Params{
EnvPrefix: "example",
ConfigPathGetter: &insconfig.FlagPathGetter{
GoFlags: flag.CommandLine,
},
}
insConfigurator := insconfig.New(params)
_ = insConfigurator.Load(&mconf)
fmt.Println(*flag_example_1)
fmt.Println(insConfigurator.ToYaml(mconf))
Custom spf13/pflags
var flag_example_1 = pflag.String("flag_example_1", "", "flag_example_1_desc")
mconf := Config{}
params := insconfig.Params{
EnvPrefix: "example",
ConfigPathGetter: &insconfig.PFlagPathGetter{
PFlags: pflag.CommandLine,
},
}
insConfigurator := insconfig.New(params)
_ = insConfigurator.Load(&mconf)
fmt.Println(flag_example_1)
fmt.Println(insConfigurator.ToYaml(mconf))
Custom spf13/cobra flags.
Note: Cobra doesn't provide tools that manage flags parsing, so you need to add the --config
flag yourself.
// To set your path from flag to insconfig you need to implement simple ConfigPathGetter interface and return path
type stringPathGetter struct {
Path string
}
func (g *stringPathGetter) GetConfigPath() string {
return g.Path
}
func main() {
var configPath string
rootCmd := &cobra.Command{
Use: "your_command_name",
}
rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "", "path to config file")
_ = rootCmd.MarkPersistentFlagRequired("config")
err := rootCmd.Execute()
if err != nil {
panic(err)
}
cfg := Config{}
params := insconfig.Params{
EnvPrefix: "example",
ConfigPathGetter: &stringPathGetter{Path: configPath},
FileNotRequired: true,
}
insConfigurator := insconfig.New(params)
err = insConfigurator.Load(&cfg)
if err != nil {
panic(err)
}
println(insConfigurator.ToYaml(cfg))
}
Tip: You can use tags to enrich a field with a comment, and it will end up in your template.
If you want to create a config file example and you have a ready config structure, consider this example:
type Config struct {
...
Field Type `insonfig:"Commentary for this field"`
}
...
cfg := Config{
...
Field: "default_value",
}
insconfig.NewYamlTemplaterStruct(cfg).TemplateTo(os.StdOut)
As you see, default value for a field can be provided via instance of config structure.
Generating a configuration template with hidden fields
If you have some sensitive data, you may want to hide it in a config. You can use the insconfigsecret
tag to hide such data.
type Config struct {
...
Pass string `insconfigsecret:""`
}
...
insconfig.NewYamlDumper(Config).DumpTo(os.StdOut)
You can use maps in a configuration file, althought with some limitations:
- Only String type keys are allowed
- A map cannot be nested and has to be used on the first level
- Nested maps (directly or in a struct) are not allowed
Feel free to submit issues, fork the repository and send pull requests!
To make the process smooth for both reviewers and contributors, familiarize yourself with the following guidelines:
- Open source contributor guide.
- Style guide: Effective Go.
- List of shorthands for Go code review comments.
When submitting an issue, include a complete test function that reproduces it.
Thank you for your intention to contribute to the Insolar Mainnet project. As a company developing open-source code, we highly appreciate external contributions to our project.
If you have any additional questions, join our developers chat on Telegram.
Our social media:
This project is licensed under the terms of the MIT License.