Unify configuration file format #181

Open
opened 2015-10-18 21:37:56 -06:00 by serpi90 · 41 comments
serpi90 commented 2015-10-18 21:37:56 -06:00 (Migrated from github.com)

Could you consider a standard file format for the configuration files, it's kind of a mess sometimes.

It could be either XML, JSON, Yaml or any standard format.

If you choose XML, please define schemas (XSD) for validation (it ensures a correct file format, and you can define default values there). And you can use the Xerces library for writing / parsing.

Could you consider a standard file format for the configuration files, it's kind of a mess sometimes. It could be either XML, JSON, Yaml or any standard format. If you choose XML, please define schemas (XSD) for validation (it ensures a correct file format, and you can define default values there). And you can use the Xerces library for writing / parsing.
RElesgoe commented 2015-10-18 22:47:49 -06:00 (Migrated from github.com)

That's a good idea. Right now, the files are in a human friendly format. XML format is more for computers so we should also have gui program that can modify these files

That's a good idea. Right now, the files are in a human friendly format. XML format is more for computers so we should also have gui program that can modify these files
HarpyWar commented 2015-10-18 23:23:37 -06:00 (Migrated from github.com)

json may be preferred. It's readable both for a human and a computer.

PvPGN is a server side app and I don't think that we need a special GUI tool for that (but it would be nice if someone create a web app to control a server that can include a visual config editor).

json may be preferred. It's readable both for a human and a computer. PvPGN is a server side app and I don't think that we need a special GUI tool for that (but it would be nice if someone create a web app to control a server that can include a visual config editor).
anonprophet commented 2015-10-18 23:28:45 -06:00 (Migrated from github.com)

+1 json

+1 json
Kelwing commented 2015-10-19 06:45:38 -06:00 (Migrated from github.com)

I agree with JSON, and suggest jsoncpp for the parsing library.

I agree with JSON, and suggest jsoncpp for the parsing library.
cen1 commented 2015-10-19 15:16:30 -06:00 (Migrated from github.com)

The more important issue here is that we need to open a port and implement a small http server into pvpgn if you want it to be configurable from the web. It needs to be able to handle a REST API. Configuration should be represented as a class so it can be easily serializable. A quick look at boost serialization library seems to be able to do both: serialize and deserialize. If that actually works you could push whole JSON config from the web and apply it (deserialize it) into pvpgn config object.

This is how java folks do it and these are considered best practices. I never did such a thing in c++ tho and since c++ lacks reflection it should first be investigated. Perhaps write a simple class and try to serialize and deserialize it from/into json.

All config files could also be joint into one since you can do trees with json to easily separate different pvpgn subsystems.

A lot of stuff to think about here.

The more important issue here is that we need to open a port and implement a small http server into pvpgn if you want it to be configurable from the web. It needs to be able to handle a REST API. Configuration should be represented as a class so it can be easily serializable. A quick look at boost serialization library seems to be able to do both: serialize and deserialize. If that actually works you could push whole JSON config from the web and apply it (deserialize it) into pvpgn config object. This is how java folks do it and these are considered best practices. I never did such a thing in c++ tho and since c++ lacks reflection it should first be investigated. Perhaps write a simple class and try to serialize and deserialize it from/into json. All config files could also be joint into one since you can do trees with json to easily separate different pvpgn subsystems. A lot of stuff to think about here.
Kelwing commented 2015-10-19 17:28:29 -06:00 (Migrated from github.com)

No one here mentioned a web conf interface. We can do JSON through a config file. It's very simple to write an interface using jsoncpp to deserialize JSON. As far as a web interface, it could be implemented quickly and easily using libmicrohttpd, but its entirely not necessary. You can just edit JSON config files using a text editor.

No one here mentioned a web conf interface. We can do JSON through a config file. It's very simple to write an interface using jsoncpp to deserialize JSON. As far as a web interface, it could be implemented quickly and easily using libmicrohttpd, but its entirely not necessary. You can just edit JSON config files using a text editor.
Kelwing commented 2015-10-19 17:30:25 -06:00 (Migrated from github.com)
jsoncpp is extremely well documented: http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
cen1 commented 2015-10-19 23:16:50 -06:00 (Migrated from github.com)

Do you know if it's possible to serialize and deserialize this way? http://stackoverflow.com/questions/17549906/c-json-serialization
The idea is not to do it by hand but it seems not to be possible in c++ due to missing reflection. If we used some kind of a map then I think it would be possible but that is a tradeoff then because you are not using the class itself and rely on string keys.
I've been doing too much java with jackson library lately which can do this automatically so I'm curious to see if it would be possible in c++. :)

Do you know if it's possible to serialize and deserialize this way? http://stackoverflow.com/questions/17549906/c-json-serialization The idea is not to do it by hand but it seems not to be possible in c++ due to missing reflection. If we used some kind of a map then I think it would be possible but that is a tradeoff then because you are not using the class itself and rely on string keys. I've been doing too much java with jackson library lately which can do this automatically so I'm curious to see if it would be possible in c++. :)
HarpyWar commented 2015-10-20 03:28:54 -06:00 (Migrated from github.com)

Now we have a lot of different formats and each configuration file has own file reader/writer wrapper (tournaments, icons, topics, bnmaps and others).
Benefits from json will be in put in one place reader/writer of all configuration files. And other parts of code can use this internal config layer to access config items.

By a web app I meant user friendly interface to stop/start server, several config sections. For instance to upload banners and edit their rotate options, add icons, edit normal config values and then serialize it into json files.

Small http web server looks interesting but it may be very hard to implement and it adds a new complexity.
I thought about real-time control features and it may be done with a persistent connected external bot that can have REST API interface to send text commands to a server. A bot can be written on Java by someone.
Sometimes real-time changes is preferred instead of direct changes in a database. For instance it can be built-in into a web site with a feature to change a user password (otherwise password may not be changed or with a delay due to pvpgn cache layer if we change it in a database).

Now we have a lot of different formats and each configuration file has own file reader/writer wrapper (tournaments, icons, topics, bnmaps and others). Benefits from json will be in put in one place reader/writer of all configuration files. And other parts of code can use this internal config layer to access config items. By a web app I meant user friendly interface to stop/start server, several config sections. For instance to upload banners and edit their rotate options, add icons, edit normal config values and then serialize it into json files. Small http web server looks interesting but it may be very hard to implement and it adds a new complexity. I thought about real-time control features and it may be done with a persistent connected external bot that can have REST API interface to send text commands to a server. A bot can be written on Java by someone. Sometimes real-time changes is preferred instead of direct changes in a database. For instance it can be built-in into a web site with a feature to change a user password (otherwise password may not be changed or with a delay due to pvpgn cache layer if we change it in a database).
cen1 commented 2015-10-20 05:46:40 -06:00 (Migrated from github.com)

User's password is not a configuration matter, that is a separate thing that has to do with database persistence. It can already be changed live using a chat bot and /chpass (that's how we do it in production actually). If something can't be changed live with a bnet command then yes, we need a new protocol but that should be separate from configuration. It can still be a REST API though. A client in the middle seems like unnecessary complication.. if you can receive commands from a local client you might as well receive them from the web.

Changing config live is actually doable, just with some caveats.

  1. Frontend sends new JSON config to REST API using http POST
  2. Pvpgn deserializes JSON into config object
  3. You reload the config using the new object and switch the pointer to it. Added benefit if you keep the old config object in memory so you can simply switch back to it if the new config is bad.

Obviously, not all config can be changed like that on live system. Some attributes would have to be protected from being modified live.

I suggest we write some proof of concept code first before a single line of code is changed just to see how things would actually work. I will hack something together myself.

User's password is not a configuration matter, that is a separate thing that has to do with database persistence. It can already be changed live using a chat bot and /chpass (that's how we do it in production actually). If something can't be changed live with a bnet command then yes, we need a new protocol but that should be separate from configuration. It can still be a REST API though. A client in the middle seems like unnecessary complication.. if you can receive commands from a local client you might as well receive them from the web. Changing config live is actually doable, just with some caveats. 1. Frontend sends new JSON config to REST API using http POST 2. Pvpgn deserializes JSON into config object 3. You reload the config using the new object and switch the pointer to it. Added benefit if you keep the old config object in memory so you can simply switch back to it if the new config is bad. Obviously, not all config can be changed like that on live system. Some attributes would have to be protected from being modified live. I suggest we write some proof of concept code first before a single line of code is changed just to see how things would actually work. I will hack something together myself.
RElesgoe commented 2015-10-20 22:52:25 -06:00 (Migrated from github.com)

I'm looking at JsonCPP right now and it seems like it will work out but I'm concerned about generating an amalgamated source since it requires Python. Is it possible to generate an amalgamated source and upload the files to this repository so that everyone doesn't have to generate it themselves?

I'm looking at JsonCPP right now and it seems like it will work out but I'm concerned about generating an amalgamated source since it requires Python. Is it possible to generate an amalgamated source and upload the files to this repository so that everyone doesn't have to generate it themselves?
Neubivljiv commented 2015-10-21 03:51:49 -06:00 (Migrated from github.com)

It's a good idea to use a universal and readable format configuration.
As for me, it is not necessary (because it's mainly configured only once).
For web applications, plain text could be easily parsed (even better if it's json).
I already did this for ghost bot for web application, where it's possible to edit huge configs in plain text (each line is parsed and created input/dropdown field for HTML output). I also added auto backup for original config so you can always undo configuration.
About REST API I would suggest to use sockets, so you can easily connect via php or any other third party application for remote control (we already did this for ghost++ where bot streams live games to user chat web application via sockets). Also, remote control is very easy to buildin.
If you ask me, avoid Java for many reasons.

Here is few screenshots of old GamePanel for Ghost bots, and Steam games (we are using this for a years):
game_panel_01
game_panel_02
game_panel_03
chat log (can load huge log file very fast because it partially reads file).

This can be easily done for PVPGN, but I already tried and build small interface for start/stop server. Than I added option to user can login/change password/register via web. But it's not working, because PVPGN server won't check every time user login (I need to restart server after each registration or pw change), so currently I gave up.

It's a good idea to use a universal and readable format configuration. As for me, it is not necessary (because it's mainly configured only once). For web applications, plain text could be easily parsed (even better if it's json). I already did this for ghost bot for web application, where it's possible to edit huge configs in plain text (each line is parsed and created input/dropdown field for HTML output). I also added auto backup for original config so you can always undo configuration. About REST API I would suggest to use sockets, so you can easily connect via php or any other third party application for remote control (we already did this for ghost++ where bot streams live games to user chat web application via sockets). Also, remote control is very easy to buildin. If you ask me, avoid Java for many reasons. Here is few screenshots of old GamePanel for Ghost bots, and Steam games (we are using this for a years): ![game_panel_01](https://cloud.githubusercontent.com/assets/339178/10633141/24a6d6a2-77e9-11e5-9aef-497dc99b1cd2.jpg) ![game_panel_02](https://cloud.githubusercontent.com/assets/339178/10633143/24a7a348-77e9-11e5-833f-16e54b66157d.jpg) ![game_panel_03](https://cloud.githubusercontent.com/assets/339178/10633142/24a70578-77e9-11e5-90c0-79af4d18e50a.jpg) chat log (can load huge log file very fast because it partially reads file). This can be easily done for PVPGN, but I already tried and build small interface for start/stop server. Than I added option to user can login/change password/register via web. But it's not working, because PVPGN server won't check every time user login (I need to restart server after each registration or pw change), so currently I gave up.
cen1 commented 2015-10-21 04:28:54 -06:00 (Migrated from github.com)

One big problem with JSON which we did not talk about yet is that you can't have comments or documentation in it. At the moment we have huge amount of helpful documentation and tips about each variable and all this has to go away if we use JSON.

@Neubivljiv Sockets are fine for simple tasks but using a small http server gives you standard protocol support (http with all the headers) and return codes. If you use sockets you either need to reinvent the wheel or you end up with some custom protocol.

One big problem with JSON which we did not talk about yet is that you can't have comments or documentation in it. At the moment we have huge amount of helpful documentation and tips about each variable and all this has to go away if we use JSON. @Neubivljiv Sockets are fine for simple tasks but using a small http server gives you standard protocol support (http with all the headers) and return codes. If you use sockets you either need to reinvent the wheel or you end up with some custom protocol.
Neubivljiv commented 2015-10-21 04:51:43 -06:00 (Migrated from github.com)

Well, why not using JSON data as a comment?

{
"_info": "This is a comma delimited list of hostnames that the server should listen on. It might be useful to make an internal-only server on a gateway machine for example...",
"servaddrs" : ":"
},
{
"_info" : "W3 Play Game router address. Just put your server address in here or use 0.0.0.0:6200 for server to bind to all interfaces, but make sure you set up w3trans if you do.",
"w3routeaddr" : "0.0.0.0:6200"
}

Well, why not using JSON data as a comment? > { > "_info": "This is a comma delimited list of hostnames that the server should listen on. It might be useful to make an internal-only server on a gateway machine for example...", > "servaddrs" : ":" > }, > { > "_info" : "W3 Play Game router address. Just put your server address in here or use 0.0.0.0:6200 for server to bind to all interfaces, but make sure you set up w3trans if you do.", > "w3routeaddr" : "0.0.0.0:6200" > }
Kelwing commented 2015-10-21 06:45:04 -06:00 (Migrated from github.com)

@xboi209 On Linux, most if not all distributions have it as a binary package, so you can just use the system package instead of including the source files directly in our code. Once you have the system library installed, its as simple as
#include <json/json.h>

Windows is another issue, however.

@xboi209 On Linux, most if not all distributions have it as a binary package, so you can just use the system package instead of including the source files directly in our code. Once you have the system library installed, its as simple as `#include <json/json.h>` Windows is another issue, however.
cen1 commented 2015-10-21 07:47:09 -06:00 (Migrated from github.com)

@Neubivljiv I guess. It's not very nice but it would allow us to also push comments to the frontend which we would need anyway.

@Neubivljiv I guess. It's not very nice but it would allow us to also push comments to the frontend which we would need anyway.
RElesgoe commented 2015-10-21 09:02:20 -06:00 (Migrated from github.com)

@Kelwing Yeah we will need to support Windows. Maybe there's a pre-compiled DLL somewhere like zlib

@Kelwing Yeah we will need to support Windows. Maybe there's a pre-compiled DLL somewhere like zlib
Kelwing commented 2015-10-21 09:11:30 -06:00 (Migrated from github.com)

I know it supports compilation under Visual Studio, I just haven't done it myself yet.

I know it supports compilation under Visual Studio, I just haven't done it myself yet.
RElesgoe commented 2015-10-21 09:28:24 -06:00 (Migrated from github.com)

The readme suggests to create an amalgamated source if you're going to integrate it into a project, which will require Python.

The readme suggests to create an amalgamated source if you're going to integrate it into a project, which will require Python.
Kelwing commented 2015-10-21 09:36:08 -06:00 (Migrated from github.com)

Right, be we only need to do that once. I can do that on my laptop if we need. I have Python on it.

Right, be we only need to do that once. I can do that on my laptop if we need. I have Python on it.
Kelwing commented 2015-10-21 09:39:46 -06:00 (Migrated from github.com)

Here is a gzip'd tarball with the amalgamated source:
https://kelnet.org/owncloud/index.php/s/LDngqOoFgurtqBy

Here is a gzip'd tarball with the amalgamated source: https://kelnet.org/owncloud/index.php/s/LDngqOoFgurtqBy
cen1 commented 2015-10-31 17:47:16 -06:00 (Migrated from github.com)

After a few hours of research and playing with different libraries I managed to hack together a simple proof of concept code. It can be found in my repo together with VS 2015 project and all libs and binaries (so you don't have to compile anything yourself). Just change include paths (from my absolutes) plus some file paths in code and you are good to go:
https://github.com/cen1/pvpgn-conf-poc

The example code shows:
-a simple REST API using a http server from Poco library. It is really straightforward, you just initiate HttpServer, give it a request handler and then you can register REST endpoints by checking the URI path that was requested
-config object serialization and deserialization using cereal library. You simply define a template class and tell which attributes to serialize and it does it automatically. No parsing by hand! Pure awesomeness if you ask me. :)

Result:
example

In the following days I'll clean up the code and abstract it a bit, it should be done by the end of it. I'll also include AngularJS frontend example to show how easily we can bind frontend forms with received data and send it back to the server as a single json object.

I am willing to spend a few hours a week to work on the actual implementation but feedback is welcome first.

After a few hours of research and playing with different libraries I managed to hack together a simple proof of concept code. It can be found in my repo together with VS 2015 project and all libs and binaries (so you don't have to compile anything yourself). Just change include paths (from my absolutes) plus some file paths in code and you are good to go: https://github.com/cen1/pvpgn-conf-poc The example code shows: -a simple REST API using a http server from Poco library. It is really straightforward, you just initiate HttpServer, give it a request handler and then you can register REST endpoints by checking the URI path that was requested -config object serialization and deserialization using cereal library. You simply define a template class and tell which attributes to serialize and it does it automatically. No parsing by hand! Pure awesomeness if you ask me. :) Result: ![example](https://cloud.githubusercontent.com/assets/1158861/10866517/c14cb33c-8031-11e5-987e-cac6c2ca2c57.png) In the following days I'll clean up the code and abstract it a bit, it should be done by the end of it. I'll also include AngularJS frontend example to show how easily we can bind frontend forms with received data and send it back to the server as a single json object. I am willing to spend a few hours a week to work on the actual implementation but feedback is welcome first.
RElesgoe commented 2016-05-24 05:07:35 -06:00 (Migrated from github.com)

I've decided to use JSON for Modern C++ for this task.

I've decided to use [JSON for Modern C++](https://github.com/nlohmann/json) for this task.
xpeh-owns commented 2018-01-27 21:16:31 -07:00 (Migrated from github.com)

If you decide to JSON over XML, use hjson or json5 format since json is not very user friendly to edit.

If you decide to JSON over XML, use hjson or json5 format since json is not very user friendly to edit.
RElesgoe commented 2018-01-27 21:40:46 -07:00 (Migrated from github.com)

I believe that standard JSON should be used since it's more widely adopted.

I believe that standard JSON should be used since it's more widely adopted.
xpeh-owns commented 2018-01-27 21:42:40 -07:00 (Migrated from github.com)

JSON extension have advantages:

  • comments. Who needs config files without comments?
  • trailing comma
  • some more...
JSON extension have advantages: - **comments**. Who needs config files without comments? - trailing comma - some more...
serpi90 commented 2018-01-27 21:45:39 -07:00 (Migrated from github.com)

If you want to use a non standard format, just use the current one as it works.
Configuration parameters description should be on a document, a CONFIGURATION.md detailing the configuration files. And/Or using JSON data as comments as said before.

If you want to use a non standard format, just use the current one as it works. Configuration parameters description should be on a document, a CONFIGURATION.md detailing the configuration files. And/Or using JSON data as comments as said before.
xpeh-owns commented 2018-01-27 21:47:40 -07:00 (Migrated from github.com)

@serpi90 old conf files worked too...

@serpi90 old conf files worked too...
serpi90 commented 2018-01-27 21:48:07 -07:00 (Migrated from github.com)

@xpeh-owns that was what i meant

@xpeh-owns that was what i meant
RElesgoe commented 2018-01-27 21:48:23 -07:00 (Migrated from github.com)

Documentation files would be better suited instead of comments since you could format information in a clean and organized way.
Standard JSON syntax does lack some features, but if we're looking at JSON extensions, we might as well also consider entirely different formats such as YAML.

Documentation files would be better suited instead of comments since you could format information in a clean and organized way. Standard JSON syntax does lack some features, but if we're looking at JSON extensions, we might as well also consider entirely different formats such as YAML.
xpeh-owns commented 2018-01-27 21:50:41 -07:00 (Migrated from github.com)

@serpi90 ah ok :)

@RElesgoe don't know yaml, but you can google json5 and hjson - they are backwards compatible and almost as simple as json.
And if you introduce new config formats, shouldn't it be an experimental version of pvpng?

@serpi90 ah ok :) @RElesgoe don't know yaml, but you can google json5 and hjson - they are backwards compatible and almost as simple as json. And if you introduce new config formats, shouldn't it be an experimental version of pvpng?
xpeh-owns commented 2018-01-27 21:58:24 -07:00 (Migrated from github.com)

So I think xml/json should be useful for nested configs, i.e. not for flat key-value config like bnetd.conf.

  • versioncheck.conf
    should it be in json format? Probably I can covert it into json and make a script that converts it to conf till json configs would be added. It has very weird format with no syntax highlight.
So I think xml/json should be useful for nested configs, i.e. not for flat key-value config like bnetd.conf. - **versioncheck.conf** should it be in json format? Probably I can covert it into json and make a script that converts it to `conf` till json configs would be added. It has very weird format with no syntax highlight.
xpeh-owns commented 2018-01-27 21:59:20 -07:00 (Migrated from github.com)

@RElesgoe comments are not only for documentation, it's also a possibility to temporarily disable an entry. I can't imagine a config without such a feature.

What's config encoding currently?

@RElesgoe comments are not only for documentation, it's also a possibility to temporarily disable an entry. I can't imagine a config without such a feature. What's config encoding currently?
serpi90 commented 2018-01-27 22:01:48 -07:00 (Migrated from github.com)
{  
  "configuration":{  
    "some":"strff"
  }
}

you can comment like this:

{  
  "#configuration":{  
    "some":"strff"
  }
}
```json { "configuration":{ "some":"strff" } } ``` you can comment like this: ```json { "#configuration":{ "some":"strff" } } ```
xpeh-owns commented 2018-01-27 22:05:52 -07:00 (Migrated from github.com)

@serpi90 but if your config format support comments you have syntax highlihting. Even in notepad++ you can comment out selected text with a shortcut.

@serpi90 but if your config format support comments you have syntax highlihting. Even in notepad++ you can comment out selected text with a shortcut.
RElesgoe commented 2018-01-27 22:25:34 -07:00 (Migrated from github.com)

@xpeh-owns versioncheck.conf will be converted to JSON soon, but if you'd like to convert it for me, I'd be happy to accept contributions. I would like the format to be like this: https://gist.github.com/RElesgoe/ecbcfb1af96953c8ffeb169ad6d38921

Changes to PvPGN in this repository is often going to be not thoroughly tested, this whole repository is practically experimental.

The encoding for all files should be UTF-8 without BOM.

@xpeh-owns versioncheck.conf will be converted to JSON soon, but if you'd like to convert it for me, I'd be happy to accept contributions. I would like the format to be like this: https://gist.github.com/RElesgoe/ecbcfb1af96953c8ffeb169ad6d38921 Changes to PvPGN in this repository is often going to be not thoroughly tested, this whole repository is practically experimental. The encoding for all files should be UTF-8 without BOM.
xpeh-owns commented 2018-01-27 22:39:58 -07:00 (Migrated from github.com)

Well, do you have stable releases at all? I assume people don't want to change their configs or even db structure because some of developers want to test some feature.

Another feature of json extensions is hex notation for integer.

Well, do you have stable releases at all? I assume people don't want to change their configs or even db structure because some of developers want to test some feature. Another feature of json extensions is hex notation for integer.
RElesgoe commented 2018-01-27 22:47:32 -07:00 (Migrated from github.com)

There aren't regular stable releases since development is irregular, but you can look here: https://github.com/pvpgn/pvpgn-server/releases
The code that I'm writing to load JSON configuration files should work well as far as I know. It might be beneficial to write a script that can convert between the old and new formats.

There aren't regular stable releases since development is irregular, but you can look here: https://github.com/pvpgn/pvpgn-server/releases The code that I'm writing to load JSON configuration files should work well as far as I know. It might be beneficial to write a script that can convert between the old and new formats.
xpeh-owns commented 2018-01-27 22:49:41 -07:00 (Migrated from github.com)

Another feature of json extensions is hex notation for integer so I could write "hash": 0xb52bad87, and have syntax highlighting instead of "hash": "0xb52bad87",

They must not be regular, they just had to be stable.

Another feature of json extensions is hex notation for integer so I could write `"hash": 0xb52bad87,` and have syntax highlighting instead of `"hash": "0xb52bad87",` They must not be regular, they just had to be stable.
xpeh-owns commented 2018-01-28 17:00:44 -07:00 (Migrated from github.com)

Got some results on converting versioncheck. How to upload?

Got some results on converting versioncheck. How to upload?
RElesgoe commented 2018-01-28 17:01:56 -07:00 (Migrated from github.com)
Use https://gist.github.com
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Techwizz/pvpgn-server#181
No description provided.