[katello-devel] Foreman CLI - design proposal the Ruby way
Martin Bacovsky
mbacovsk at redhat.com
Fri May 3 07:18:52 UTC 2013
Hi,
as Tomas announced a couple of days ago, here is my proposal for CLI
design implemented in Ruby.
For better reading experience and code to play with check
https://github.com/mbacovsky/foreman_cli_draft
Comments and questions are wellcome!
Regards,
Martin
Foreman CLI design draft
========================
This is my attempt to create outline of CLI client for the Foreman. The
Foreman project has Ruby as its main langauage, so I choosed to explore
the options Ruby world is offering to complete this task.
My initial requirements are as follows:
- [x] implemented in Ruby
- [x] Git-like subcomands in CLI app
- [x] system shell autocompletion of commands and options
- [x] shell-like environment with autocompletion and history where the
commands can be run directly
- [x] commands extensible via plugins
- [x] some way to wrap current Katello CLI commands and make it
possible to have one CLI client for both
- [x] simillar UX as from katello CLI
All the requirements were addressed by the design. Though there is
plenty of room for clean up and optimisation, the draft can serve as a
proof of concept.
Design
------
![Design draft](design.png)
As the diagram shows, the CLI consist of almost generic framework
(shell-like environment, autocompletion, command help text, option
evaluation and command invocation) and set of plugins defining the
actual commands. This setup is flexible and allows us to easily install
different sets of commands for different products. The plugins are
independant and can implement any action as an command, so that besides
commands calling Foreman API you can have commands calling varius admin
tasks on the server, etc.
For real implementation of the plugins there would need to be some
decision taken on how to approach the development of the actual commands.
For *Katello* commands, there can be great deal of work done
automatically (using Katello CLI autocompletion feature and templates).
However calling Katello CLI via system call is not ideal solution and
should be replaced by direct calls to Katello API in the future.
For *Foreman* Commands development I can see three options
- generate and sync some generic CLI commands (apipie approach) with
option to inherit and redefine individual commands
- manually create everything (Katello CLI approach)
- dynamic creation on the fly with option to exclude and manually
define specific commands
Sample working implementation you can find in this repo.
- [kartit]
(https://github.com/mbacovsky/foreman_cli_draft/tree/master/kartit) gem
contains generic CLI client
- [kartit-foreman]
(https://github.com/mbacovsky/foreman_cli_draft/tree/master/kartit-foreman)
gem contains Foreman related commands definition
- [kartit-katello]
(https://github.com/mbacovsky/foreman_cli_draft/tree/master/kartit-katello)
gem contains Katello related commands definition
Pros and Cons
--------------
- [+] same implementation language as the rest of the project
- [+] generic CLI, easy to extend by adding gems with commands
- [+] lightweight design
- [-] calling katello via *system* or need to create native Katello plugin
Technologies
------------
### CLI Framework
There is plenty of CLI framework gems with varying features and quality
on the Internet. I took into consideration [Thor][thor] for its wide
spread, [Boson][boson] for its features being very close to our
requirements and [Clamp][clamp] for its simplicity.
To compare them I played with each of them for a while - _Thor_ has well
docummented features and good suport in the community. However the
codebase was for me quite cryptic and really dificult to understand and
extend. It seems good when you need what is built in. If you need
something extra adding is time consuming or requires skills beyond mine.
_Boson_ has good documentation, nice set of plugins available, live
upstream and what makes it special for us is built in shell with
autocompletion. What put it out of the game is lack of subcommands.
_Clamp_ has very similar features as Thor has but it has minimalistic,
clean and straghtforward codebase. It uses one class per command which
can come handy if you need similar behavior for subset of commands. It
was quite easy to add autocompletion and shell. And yes it is the winner
for my CLI draft.
### Shell
For shell there is not so much options. There is IRB and similar like
Ripl but I started with minimalistic and Readline. It went quite smooth
so I kept it and didn't tried the others
### Autocompletion
I wanted to have one solution for Bash and shell autocompletion and
started with simple method recursively looking for endings in command
tree. Simple bash wrapper call made it ready for use in bash. In
shell-like env based on Readline I had dificulties with the fact that
readline support autocompletion based on last word and there is no
apparent way to take the context into account. I found some workaround
but still looking for cleaner solution. Maybe Ripl + Bond are worth trying
### Input/Output
I didn't focus much on processing of input and output in the commands
yet. For Foreman commands I'd like to keep it as similar to Katello
output as possible. There are gems like highline and
[table_print][table-p] that could make it easy.
Usage
-----
And here follows short demo of the features this CLI draft offers
### Help
$ kartit -u admin -p admin -h
Usage:
kartit [OPTIONS] SUBCOMMAND [ARGS] ...
Subcommands:
shell Interactive Shell
architecture Manipulate Foreman's architectures.
environment Manipulate Katello's environments.
ping Get the status of the katello server
Options:
-v, --verbose be verbose
-u, --username USERNAME username to access the remote system
-p, --password PASSWORD password to access the remote system
--version show version
--autocomplete LINE Get list of possible endings
-h, --help print help
$ kartit -u admin -p admin architecture -h
Usage:
kartit architecture [OPTIONS] SUBCOMMAND [ARGS] ...
Subcommands:
list List foreman's architectures.
Options:
-h, --help print help
### Foreman call
As it was said above output formating for foreman commands is still
missing and will be added later
$ kartit -u admin -p admin architecture list
[
[0] {
"architecture" => {
"name" => "i386",
"id" => 5,
"created_at" => "2012-06-27T17:21:16Z",
"operatingsystem_ids" => [],
"updated_at" => "2012-06-27T17:21:16Z"
}
},
[1] {
"architecture" => {
"name" => "ppc",
"id" => 9,
"created_at" => "2012-07-31T12:19:26Z",
"operatingsystem_ids" => [],
"updated_at" => "2012-07-31T12:19:26Z"
}
},
[2] {
"architecture" => {
"name" => "x86_64",
"id" => 14,
"created_at" => "2012-08-06T15:51:21Z",
"operatingsystem_ids" => [],
"updated_at" => "2012-08-06T15:51:21Z"
}
}
]
### Katello call
$ kartit -u admin -p admin environment list --org ACME_Corporation
katello -u admin -p admin environment list --org ACME_Corporation
------------------------------------------------------------------------------------------------------------
Environment List
ID Name Label Description Org Prior Environment
------------------------------------------------------------------------------------------------------------
1 Library Library None ACME_Corporation None
2 Dev Dev None ACME_Corporation Library
3 Prod Prod None ACME_Corporation Dev
### Autocompletion
$ kartit architecture
-h --help list
$ kartit architecture list -
-h --help
### Shell
$ kartit -u admin -p admin shell
kartit> -h
Usage:
kartit [OPTIONS] SUBCOMMAND [ARGS] ...
Subcommands:
shell Interactive Shell
architecture Manipulate Foreman's architectures.
environment Manipulate Katello's environments.
ping Get the status of the katello server
Options:
-v, --verbose be verbose
-u, --username USERNAME username to access the remote system
-p, --password PASSWORD password to access the remote system
--version show version
--autocomplete LINE Get list of possible endings
-h, --help print help
kartit> ping
katello -u admin -p admin ping
-----------------------------------------------------------------------------------------------------------
Katello Status
Status Service Result Duration Message
-----------------------------------------------------------------------------------------------------------
FAIL
candlepin ok 141ms
candlepin_auth ok 225ms
elasticsearch ok 795ms
katello_jobs FAIL katello-jobs service not running
pulp ok 1706ms
pulp_auth ok 618ms
[cli-gems]: http://www.awesomecommandlineapps.com/gems.html "CLI related
gems"
[thor]: https://github.com/wycats/thor "Thor homepage"
[boson]: https://github.com/cldwalker/boson "Boson homepage"
[clamp]: https://github.com/mdub/clamp "Clamp homepage"
[table-p]: https://github.com/arches/table_print "table-print homepage"
More information about the katello-devel
mailing list