-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hilbert YAML configuration parser and Hilbert Server/Client-side tools #34
Conversation
FIX: many fixes CHG/ADD: changes and additions to the class hierarchie, e.g.: * DockerMachie variant for PowerOnMethod * expect default values for optional fields!
NOTE: due to @porst17's comment #32 (comment) ADD: minor comments (TODOs for later)
…Scalar and BaseString CHG: only keep the processed data is there was no error TODO: check that every validator follows this! REN: Abstract -> AbstractValidator
Changed API: version is implicitly globally available, use of classmethod: `Validator.parse(input, parent=...)` Filled in Validators with actual checks (URI verification, ssh alias, docker-compose config etc) Added CLI with subcommands to hilbert-cli-config.py (arghandler & argparse) Added pickling with `dill/pickle` NOTE: all validators can be tested separately now! Infrastructure: Added unit-tests using py.test Added `Makefile check` to run unit-tests Added doxygen/epydoc/pylint/pep8 execution to the Makefile
…ith `Application::name`
NOTE: the resulting .data.pickle should be generated under python2 (to be understood also by python3)
* Station:type may be: standalone, server and default: standard + Station:client_settings is not required for standalone stations! TODO: implement the above + add to the design document * Profiles and Groups may not to be displayed on UI: no need in name/icon/description... Q: Tags are to be implemented via UI - outside of the general configuration file, right?
helpers, loader, validators + main tool: hilbert Changes to the subcommand names in hilbert
NOTE: it requires ../config/*.py Also a few fixes in subcommand's argument handling (e.g. input sources & default values)
…ded configuration
For instance: * printing * show * config library package may be anywhere (see adding path to /config/ in config/tests/test_validate.py and /tools/hilbert.py) Update: tests/data/Hilbert.yml.data.pickle contains Hilbert top class TODO: Validator.parse should return Validator (or throw an exception)
NOTE: use .parse instead of .validate on temporary objects
…sub-commands to the hilbert tool CHG: improved Version Validator (keep semantic Version object, but show a version string) ADD: switched to logging instead of printing
server-side hilbert tool: - poweron/shutdown <StationID> [<args>] - deploy <StationID> - start/finish <StationID> [<ServiceID/ApplicationID>] - app_switch <StationID> <new ApplicationID>
NOTE: see the legend to "General Hilbert Architecture" in the "Management back-end" google.document
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pull request was supposed to be about config validation. Now it is also about the new CLI, so you are mixing different things again. The whole pull request is huge, making it hard to focus my comments on one particular issue. I will start commenting on the new cli.
@elondaits Please add your thought on the cli.
def cmd_poweron(parser, context, args): | ||
log.debug("Running '{}'" . format('cmd_poweron')) | ||
|
||
parser.add_argument('-s', '--station', required=True, help="specify the station") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have an additional parameter -s
when hilbert poweron
should just expect a station as argument by default, e.g. hilbert [global-options] poweron [subcommand-options] station_id
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry - for later
def cmd_shutdown(parser, context, args): | ||
log.debug("Running '{}'" . format('cmd_shutdown')) | ||
|
||
parser.add_argument('-s', '--station', required=True, help="specify the station") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just hilbert shutdown station_id
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
later
def cmd_deploy(parser, context, args): | ||
log.debug("Running '{}'" . format('cmd_deploy')) | ||
|
||
parser.add_argument('-s', '--station', required=True, help="specify the station") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hilbert deploy station_id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
later
def cmd_start(parser, context, args): | ||
log.debug("Running '{}'" . format('cmd_deploy')) | ||
|
||
parser.add_argument('-s', '--station', required=True, help="specify the station") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hilbert start station_id app_or_service_id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
later
def cmd_finish(parser, context, args): | ||
log.debug("Running '{}'" . format('cmd_finish')) | ||
|
||
parser.add_argument('-s', '--station', required=True, help="specify the station") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hilbert finish station_id app_or_service_id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
later
def cmd_query(parser, context, args): | ||
log.debug("Running '{}'" . format('cfg_query')) | ||
|
||
parser.add_argument('-o', '--object', required=False, default='all', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Streamline the CLI: hilbert cfg_query [config_object]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry - this is for later
# 2 input sources: .YAML or .PICKLE | ||
handler.add_argument('-if', '--inputfile', required=False, | ||
help="specify input .YAML file (default: 'Hilbert.yml')") | ||
handler.add_argument('-id', '--inputdump', required=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-id
does not make sense for the `cfg_verify´ subcommand, so it should not be a global option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are --inputfile
and --inputdump
a relic of the config validation cli? It suggests that the config is the only valid form of input to hilbert
, but I assume that other kinds of input might be necessary in the future. It would be better to call it --configfile
and --configdump
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High level representations of data (e.g. a JSON file or SQL file) are also called dumps... in fact, if you have a database in binary format the dump is a SQL text file... so calling the "compiled" representation a dump is confusing.
In NORMAL operation the UI will be using one cfg, and the cli should use the same... and we said the UI server should restart if the cfg changes... so users should be careful not to use the cli with the wrong cfg. Having the option of running the "pickle" file or the YAML one seems error prone and "dangerous" in this way. I recommend the YAML and pickle dates be compared, if the YAML is newer it's automatically compiled to .pickle in the same location. If not, the pickle is used directly.
... But really... it's an optimization already where the program doesn't even do anything. We shouldn't optimize before we even have code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS: If the CLI runs one command with one cfg and one command with another it can be dangerous as well... it's not just a matter of UI vs CLI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS2: Pickle files will break if there are changes to the classes that you serialized... so you should ignore pickle files written by a different version of hilbert (ANY level of changes, even a patch). At the minimum you should add a key to the pickle file that corresponds to the version of hilbert or something like that...
@@ -0,0 +1,589 @@ | |||
#!/usr/bin/env python2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to be able to actually call the hilbert
command instead of calling
python[3] tools/hilbert.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure. you can do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well just like any script: e.g ./hilbert.py
- it will use Python2 by default.
I can add a link named hilbert
if .py
should be avoided?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .py
exposes the implementation detail that the script is written in python (at least it suggests that). The user interface should not expose such things. Please add the link.
return cfg.query(obj) | ||
|
||
|
||
@subcmd('cfg_query', help='Load Configuration and query some part of it') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like Load Configuration
is done by any subcommand except version
(which is not really a subcommand and could also be replace by a global switch --version
). If it is a common thing, it should be part of the global hilbert documentation and not of the subcommand documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
return load_yaml_file(f) # TODO: check that this is a dictionary! | ||
|
||
|
||
@subcmd('version', help='Display version info') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be replaced by global option --version
similar to git --version
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i will add that later, Ok?
I'll check it later today.
|
The tests are not well structured. Each test should test something specific, so it needs a descriptive name and a descriptive comment. Also tests should not print anything... they're run from the test runner which is the only one that indicates whether things run OK or not. They're not for debugging, rather for indicating there's something wrong. Also, you should test that the code you wrote is doing what it's supposed to do... assume that third party libraries were already tested and work OK (i.e. no need to test the semantic versioning class). The test where you load the cfg and then the pickle version of the cfg (produced by dumping your binary representation of the loaded cfg) is tautological... any errors in loading the cfg are there in the pickle as well, so knowing they're the same doesn't give you any reassurances that things are working. Anyway I'm not sure if @porst17 would want to block the pull request because of these issues, or if we can fix them later. Although I recommend developing the tests alongside the code (not necessarily TDD, but close) because it helps to verify the interfaces are decent, that one can understand the code and that it doesn't have errors. Adding testing at the end is much more painful and we'll have a lot to do next year with the hardware and dockering the apps. |
Finally: That our code supports both Python2 and Python3 is worse, not better. Because we're giving ourselves a bigger problem, twice the amount of testing, and all the incompatibility problems (things we can't do in 2 or that we can't do in 3) instead of half of them. Just choose one... use 3 if it's the same. |
|
Yes. BTW: what about redirecting all of logging output into a separate log file and showing it in case of non-zero exit code?
I think previously there were commands like I also think that Note that OMD server expects that there is a single top application running on a station at any moment and sending heartbeats... Hence I would suggest to implement |
I don't mean to discuss important aspects of the system's working in this issue. I mentioned app_start because just two days ago you had this:
... I just suggested changing "start" to "app_start" and "poweron" to "start" to simplify the syntax, not change the whole logic of the system. But if there is a command to "start a service/application on a station" it's logical that there is one to stop it. Just that. |
I see. Sorry for confusion! @elondaits Please check the updated Hilbert CLI. |
NOTE: output to docs/
NOTE: run `make tox` (or simply `tox`), provided Python2.7 and Python3.4 are available
Added remote execution via ssh/scp + Dummy client script
Usage output: hilbert-station - Station part for Linux systems Usage: hilbert-station -h Display this help message. hilbert-station -v Increase verbosity hilbert-station -q Decrease verbosity hilbert-station -p Pedantic mode hilbert-station -V Display version info. hilbert-station start Start everything hilbert-station stop Stop everything and shutdown hilbert-station prepare <new_cfg> Install a new local configuration hilbert-station app_switch <app_id> Change the currently running top application to specified one hilbert-station dm_start <vm_name> Start a VM using docker-machine
= changes in config/hilbert_cli_config.py: * _execute, + Host::ssh/Host::scp + Station::type: StationType: [hidden, server, standard?, standalone?] * fixes / logging = extended Hilbert::parse testing (test_validate.py): singleHostHilbert.yml
Added locking, SubCommands use legacy client scripts Updated client scripts: prepare/default/finishall/luncher seem to work TODO: check.fix topswitch.sh!
Feature/hilbert client scripts
NOTE: temporary include docker-compose.yml for completeness
hilbert Server-side tool: - Better general Logging in * disabled checking docker-compose-file during verification as it takes too long at HITS :-( * removed general timeout option to _execute Client tool: + More locations for Lockfile (special lock group on Fedora...) * Try sudo if simple shutdown fails... TODO: - repair x11vnc, - fix OGL.tgz generation (for NVIdia OpenGL) - When should we generate OGL.tgz?
Updates and Fixes due to (initial) testing installation and its presentation
Note: remaining implementation-related issues will be collected in (#14) |
This is the first iteration of implementing Configuration Design.
Major Parts:
hilbert
(server part)hilbert-station
(client part)make epydoc
/make apidocs
make check
$HOME/.ssh/config
to execute remote actions viassh
. Currently it expects client tool:hilbert-station
to be available remotely.hilbert-station
(currently requires legacy scripts and older config files)-v
adds verbosity whereas iterated-q
removes verbosity. Default: WARNING level.pytest
(maybe alsotox
/unittest
later on). Currently for (Danger of silent overrides due to YAML #27):tests/test_loadwarnings.py
,VersionValidator
:tests/test_version.py
and whole configuration validator (Hilbert
) + (Configuration design: Wrong format: list vs mapping #17):tests/test_validate.py