{"id":14008216,"url":"https://github.com/containous/staert","last_synced_at":"2025-07-24T03:32:09.720Z","repository":{"id":57480048,"uuid":"56225996","full_name":"containous/staert","owner":"containous","description":"Merge your configuration sources","archived":true,"fork":false,"pushed_at":"2019-09-14T16:58:46.000Z","size":94,"stargazers_count":106,"open_issues_count":4,"forks_count":21,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-08-10T11:02:44.909Z","etag":null,"topics":["cli","configuration","golang","kv-store","merge","toml"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/containous.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-14T09:47:19.000Z","updated_at":"2024-05-23T13:39:02.000Z","dependencies_parsed_at":"2022-09-26T17:41:35.694Z","dependency_job_id":null,"html_url":"https://github.com/containous/staert","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containous%2Fstaert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containous%2Fstaert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containous%2Fstaert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/containous%2Fstaert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/containous","download_url":"https://codeload.github.com/containous/staert/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227410513,"owners_count":17774762,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","configuration","golang","kv-store","merge","toml"],"created_at":"2024-08-10T11:01:25.580Z","updated_at":"2024-11-30T19:30:52.260Z","avatar_url":"https://github.com/containous.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Stært\n\n[![Travis branch](https://img.shields.io/travis/containous/staert/master.svg)](https://travis-ci.org/containous/staert)\n[![Coverage Status](https://coveralls.io/repos/github/containous/staert/badge.svg?branch=master)](https://coveralls.io/github/containous/staert?branch=master)\n[![license](https://img.shields.io/github/license/containous/staert.svg)](https://github.com/containous/staert/blob/master/LICENSE.md)\n\nStært is a Go library for loading and merging a program configuration structure from many sources.\n\n## Overview\n\nStært was born in order to merge two sources of configuration ([Flæg](https://github.com/containous/flaeg), [TOML](http://github.com/BurntSushi/toml)).\nNow it also supports [Key-Value Store](#kvstore).\n\nWe developed [Flæg](https://github.com/containous/flaeg) and Stært in order to simplify configuration maintenance on [Træfik](https://github.com/containous/traefik).\n\n## Features\n\n- Load your configuration structure from many sources\n- Keep your configuration structure values unchanged if no overwriting (support defaults values)\n- Three native sources :\n\t- Command line arguments using [Flæg](https://github.com/containous/flaeg) package\n\t- TOML config file using [TOML](http://github.com/BurntSushi/toml) package\n\t- [Key-Value Store](#kvstore) using [libkv](https://github.com/docker/libkv) and [mapstructure](https://github.com/mitchellh/mapstructure) packages\n- An interface to add your own sources\n- Handle pointers field :\n\t- You can give a structure of default values for pointers\n    - Same comportment as [Flæg](https://github.com/containous/flaeg)\n- Stært is command oriented\n    - It use `flaeg.Command`\n    - Same comportment as [Flæg](https://github.com/containous/flaeg) commands\n\t- Stært supports only one command (the root-command)\n\t- Flæg allows you to use many commands\n\t- Only Flæg will be used if a sub-command is called. (because the configuration type could be different from one command to another)\n\t- You can add meta-data `\"parseAllSources\" -\u003e \"true\"` to a sub-command if you want to parse all sources (it requires the same configuration type on the sub-command and the root-command)  \n\n## Getting Started\n\n### The configuration\n\nIt works on your own configuration structure, like this one :\n\n```go\npackage example\n\nimport (\n\t\"fmt\"\n\t\"github.com/containous/flaeg\"\n\t\"github.com/containous/staert\"\n\t\"os\"\n)\n\n// Configuration is a struct which contains all different type to field\ntype Configuration struct {\n\tIntField     int                      `description:\"An integer field\"`\n\tStringField  string                   `description:\"A string field\"`\n\tPointerField *PointerSubConfiguration `description:\"A pointer field\"`\n}\n\n// PointerSubConfiguration is a SubStructure Configuration\ntype PointerSubConfiguration struct {\n\tBoolField  bool    `description:\"A boolean field\"`\n\tFloatField float64 `description:\"A float field\"`\n}\n```\n\nLet's initialize it:\n\n```go\nfunc main() {\n\t// Init with default value\n\tconfig := \u0026Configuration{\n\t\tIntField:    1,\n\t\tStringField: \"init\",\n\t\tPointerField: \u0026PointerSubConfiguration{\n\t\t\tFloatField: 1.1,\n\t\t},\n\t}\n\t// Set default pointers value\n\tdefaultPointersConfig := \u0026Configuration{\n\t\tPointerField: \u0026PointerSubConfiguration{\n\t\t\tBoolField:  true,\n\t\t\tFloatField: 99.99,\n\t\t},\n\t}\n\t//...\n}\n```\n\n### The command\n\nStært uses `flaeg.Command` structure, like this:\n\n```go\n// Create command\ncommand := \u0026flaeg.Command{\n\tName:\"example\",\n\tDescription:\"This is an example of description\",\n\tConfig:config,\n\tDefaultPointersConfig:defaultPointersConfig,\n\tRun: func() error {\n\t\tfmt.Printf(\"Run example with the config :\\n%+v\\n\", config)\n\t\tfmt.Printf(\"PointerField contains:%+v\\n\", config.PointerField)\n\t\treturn nil\n\t}\n}\n```\n\n### Use stært with sources\n\nInitialize Stært:\n\n```go\ns := staert.NewStaert(command)\n```\n\nInitialize TOML source:\n\n```go\ntoml := staert.NewTomlSource(\"example\", []string{\"./toml/\", \"/any/other/path\"})\n```\n\nInitialize Flæg source:\n\n```go\nf := flaeg.New(command, os.Args[1:])\n```\n\n### Add sources\n\nAdd TOML and Flæg sources:\n\n```go\ns.AddSource(toml)\ns.AddSource(f)\n```\n\n**NB:** You can change order, so that, Flæg configuration will overwrite TOML one.\n\n### Load your configuration\n\nJust call `LoadConfig` function:\n\n```go\nloadedConfig, err := s.LoadConfig();\nif err != nil {\n\t// oops\n}\n// do what you want with `loadedConfig`\n// or call run function\n```\n\n### You can call Run\n\nRun function will call `run()` from the command:\n\n```go\nif err := s.Run(); err != nil {\n\t//OOPS\n}\n```\n\n**NB:** If you didn't call `LoadConfig()` before, your function `run()` will use your original configuration.\n\n### Let's run example\n\nTOML file `./toml/example.toml`:\n\n```toml\nIntField = 2\n[PointerField]\n```\n\nWe can run the example program using following CLI arguments:\n\n```\n$ ./example --stringfield=owerwrittenFromFlag --pointerfield.floatfield=55.55\nRun example with the config :\n\u0026{IntField:2 StringField:owerwrittenFromFlag PointerField:0xc82000ec80}\nPointerField contains:\u0026{BoolField:true FloatField:55.55}\n```\n\n### Full example\n\n[Tagoæl](https://github.com/debovema/tagoael) is a trivial example which shows how Stært can be use.\nThis funny GoLang program takes its configuration from both TOML and Flæg sources to display messages.\n\n```\n$ ./tagoael -h\ntagoæl is an enhanced Hello World program to display messages with\nan advanced configuration mechanism provided by Flæg \u0026 Stært.\n\nflæg:   https://github.com/containous/flaeg\nstært:  https://github.com/containous/staert\ntagoæl: https://github.com/debovema/tagoael\n\n\nUsage: tagoael [--flag=flag_argument] [-f[flag_argument]] ...     set flag_argument to flag(s)\n   or: tagoael [--flag[=true|false| ]] [-f[true|false| ]] ...     set true/false to boolean flag(s)\n\nFlags:\n        -c, --commandlineoverridesconfigfile               Whether configuration from command line overrides configuration from configuration file or not. (default \"true\")\n        --configfile                                       Configuration file to use (TOML). (default \"tagoael\")\n        -i, --displayindex                                 Whether to display index of each message (default \"false\")\n        -m, --messagetodisplay                             Message to display (default \"HELLO WOLRD\")\n        -n, --numbertodisplay                              Number of messages to display (default \"1000\")\n        -h, --help                                         Print Help (this message) and exit\n```\n\nThank you [@debovema](https://github.com/debovema) for this work :)\n\n## KvStore\n\nAs with Flæg and TOML sources, the configuration structure can be loaded from a Key-Value Store.\nThe package [libkv](https://github.com/docker/libkv) provides connection to many KV Store like `Consul`, `Etcd` or `Zookeeper`.\n\nThe whole configuration structure is stored, using architecture like this pattern:\n\n- Key: `\u003cprefix1\u003e/\u003cprefix2\u003e/.../\u003cfieldNameLevel1\u003e/\u003cfieldNameLevel2\u003e/.../\u003cfieldName\u003e`\n- Value: `\u003cvalue\u003e`\n\nIt handles:\n\n- All [mapstructure](https://github.com/mitchellh/mapstructure) features(`bool`, `int`, ... , Squashed Embedded Sub `struct`, Pointer).\n- Maps with pattern : `.../\u003cMapFieldName\u003e/\u003cmapKey\u003e` -\u003e `\u003cmapValue\u003e` (Struct as key not supported)\n- Slices (and Arrays) with pattern : `.../\u003cSliceFieldName\u003e/\u003cSliceIndex\u003e` -\u003e `\u003cvalue\u003e`\n\n**Note:** Hopefully, we provide the function `StoreConfig` to store your configuration structure ;)\n\n### KvSource\n\nKvSource implements Source:\n\n```go\ntype KvSource struct {\n\tstore.Store\n\tPrefix string // like this \"prefix\" (without the /)\n}\n```\n\n### Initialize\n\nIt can be initialized like this:\n\n```go\nkv, err := staert.NewKvSource(backend store.Backend, addrs []string, options *store.Config, prefix string)\n```\n\n### LoadConfig\n\nYou can directly load data from the KV Store into the config structure (given by reference)\n\n```go\nconfig := \u0026ConfigStruct{} // Here your configuration structure by reference\nerr := kv.Parse(config)\n// do what you want with `config`\n```\n\n### Add to Stært sources\n\nYou can add this source to Stært, as with other sources:\n\n```go\ns.AddSource(kv)\n```\n\n### StoreConfig\n\nYou can also store your whole configuration structure into the KV Store:\n\n```go\n// We assume that `config` is initialized\nerr := kv.StoreConfig(config)\n```\n\n## Contributing\n\n1. Fork it!\n2. Create your feature branch: `git checkout -b my-new-feature`\n3. Commit your changes: `git commit -am 'Add some feature'`\n4. Push to the branch: `git push origin my-new-feature`\n5. Submit a pull request :D\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainous%2Fstaert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcontainous%2Fstaert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainous%2Fstaert/lists"}