Configuratively is a file based database for storing your environment and application configuration. It is easy to get started and supports a variety of use cases to fit your project.
- Files are stored as JSON
- Configuration can be retrieved with any of the following:
- Self-Hosted RESTful API.
- Command-Line interface.
- C# Library.
- Mapped queries to model hierarchies to override configuration values.
Configuratively is written in C# and runs on the .NET platform but with an aim to work with coreclr for cross-platform availability.
Both the web service and command-line interfaces are bundled within the same application for simplicity. To start using Configuratively:
- Download the latest release.
- Use the example to create your own configuration repository.
- Run the
configuratively.exe
without parameters to host the webserver which defaults tohttp://localhost:9000
. - Use the
export
argument from the command-line to compile your configuration to a JSON file.
When using the web server you can change the host uri and configuration folder location within configuratively.exe.config
.
Configuratively has two main components: JSON files which live within a file system hierarchy and a mapping file which tells the executable how to read it. We will start by modelling a simple domain using the mapping file which you can store anywhere but we will store at the root of the filesystem.
{
"entities": [
{ "name": "environments", "regex": "^environments" },
{ "name": "packages", "regex": "^packages" }
],
"queries": [
{ "uriTemplate": "{environments}/{packages}" }
]
}
Entities relate to the domain model of your configuration, and they map a virtual name to a physical location using a regex expression. This gives you flexiblity about how you want to structure your model. Configuratively will automatically allow you to reach entities based on this configuration using convention based routes. For example an environment config located at /environments/test.json
will be accessible via the route /environments/test
. We will cover routes later on.
Queries allow you to specify cross cutting hierachies against your model. The uriTemplate is actually a dynamic route which lets you override configuration values using a last entity wins. Given the route /test/web
any settings in web will override settings with the same name in test. Using these uriTemplates you can fit your deployment models without physically changing the repository.
Now lets add configuration files for a test environment, a web package and a service package.
{
"name": "test",
"settings": {
"debug": false
}
}
{
"name": "webservice",
"settings" : {
"debug" : true
}
}
{
"name" : "service",
"settings" : { }
}
name is a human readable identifier for each entity and should be unique within the entity folder it lives in. This is the name you will use in the route when accessing the configuration. The debug setting is described in both the test and web configuration, lets try out some routes.
> $result = Get-Configuration -repositoryPath C:\simplerepo -routes '/environments/test'
> $result.settings.debug
false
> $result = Get-Configuration -repositoryPath C:\simplerepo -routes '/test/service'
> $result.settings.debug
false
> $result = Get-Configuration -repositoryPath C:\simplerepo -routes '/test/web'
> $result.settings.debug
true
The service package does not override the debug value and so inherits it from its environment parent, whilst the web package has overridden it.
You can specify multiple parents for a configuration file to build complex domains and normalise your repository data.
{
"links" : [ "templates/packages/default.json" ],
"name" : "service",
"settings" : { }
}
{
"name" : "service",
"settings" : { "debug" : true }
}
Now calling the route /environment/service
will return a debug value of true. We could add default as a link to the web.json and reduce the duplication within there too.
We use the wonderful Nancy framework to service configuration using HTTP. In addition we use topshelf as a container which will allow you to run it either as a console application or as a windows service. The command line reference for the executable can be found on their wiki. We'll cover the basics here.
configuratively.exe run
configuratively.exe install
configuratively.exe run -username safeuser -password safepassword
You can configure the location of the configuration repository, mapping file and http endpoint by editing configuratively.exe.config
.
<appSettings>
<add key="hostUri" value="http://localhost:9000" />
<add key="repoPath" value="C:\classic-scenario"/>
<add key="mappingFile" value="simple-mapping.cfg" />
</appSettings>
Once the service is running you get the JSON configuration over HTTP. The endpoints covering the simple example are:
GET http://localhost:9000/environments/test
GET http://localhost:9000/packages/service
GET http://localhost:9000/test/web
If you want to pre-generate the configuration files to support a custom method of delivery to your applications you can do that too. The same configuratively.exe
has a built in command-line generator and comes bundled with a powershell module.
Routes are described using a comma separated list in the form of route1=output1.json,route2=output2.json
and you can generate as many as you like. When generating a lot of configuration its better to send multiple routes in at the same time to save on the executables start-up time.
> Save-Configuration -repositoryPath C:\repository -routes "test/web=web.json,environments/test=test.json"
web.json
test.json
You can also build the configuration repository within your application.
var reader = new ConfigurationReader(new ConfigSettings(repositoryPath, mappingFilePath));
string jsonConfiguration = reader.Get("environments/dev");
You can use any JSON parser to deserialize this into a dynamic or typed object. Internally we use Newtonsoft.Json.
We use and develop Configuratively for our own use, but we would love to help make it work for you too.
- Submit a pull request for a new feature or bugfix.
- Submit a failing test for a bug.
- Make a feature request by raising an issue.
- Let us know about any bugs.
- Tell us how you're using Configuratively!
You can reach us @naeemkhedarun and @James_Dawson.