aboutsummaryrefslogtreecommitdiffstats
path: root/docs/testing/developer/design/cli.rst
blob: 72d1fbafe99051a53769928668a3e127985718cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
***************************
QTIP Command Line Interface
***************************

Abstract
########

QTIP consists of different tools(metrics) to benchmark the NFVI. These metrics fall under different NFVI
subsystems(QPI's) such as compute, storage and network. A plan consists of one or more QPI's, depending upon how
the end user would want to measure performance. CLI is designed to help the user, execute benchmarks and
view respective scores.

Framework
=========

QTIP CLI has been created using the Python package `Click`_, Command Line Interface Creation Kit. It has been
chosen for number of reasons. It presents the user with a very simple yet powerful API to build complex
applications. One of the most striking features is command nesting.

As explained, QTIP consists of metrics, QPI's and plans. CLI is designed to provide interface to all
these components. It is responsible for execution, as well as provide listing and details of each individual
element making up these components.

Design
======

CLI's entry point extends Click's built in MultiCommand class object. It provides two methods, which are
overridden to provide custom configurations.

.. code-block:: python

    class QtipCli(click.MultiCommand):

        def list_commands(self, ctx):
            rv = []
            for filename in os.listdir(cmd_folder):
                if filename.endswith('.py') and \
                    filename.startswith('cmd_'):
                    rv.append(filename[4:-3])
            rv.sort()
            return rv

        def get_command(self, ctx, name):
            try:
                if sys.version_info[0] == 2:
                    name = name.encode('ascii', 'replace')
                mod = __import__('qtip.cli.commands.cmd_' + name,
                                 None, None, ['cli'])
            except ImportError:
                return
            return mod.cli

Commands and subcommands will then be loaded by the ``get_command`` method above.

Extending the Framework
=======================

Framework can be easily extended, as per the users requirements. One such example can be to override the builtin
configurations with user defined ones. These can be written in a file, loaded via a Click Context and passed
through to all the commands.

.. code-block:: python

   class Context:

       def __init__():

           self.config = ConfigParser.ConfigParser()
           self.config.read('path/to/configuration_file')

       def get_paths():

           paths = self.config.get('section', 'path')
           return paths

The above example loads configuration from user defined paths, which then need to be provided to the actual
command definitions.

.. code-block:: python

   from qtip.cli.entry import Context

   pass_context = click.make_pass_decorator(Context, ensure=False)

   @cli.command('list', help='List the Plans')
   @pass_context
   def list(ctx):
       plans = Plan.list_all(ctx.paths())
       table = utils.table('Plans', plans)
       click.echo(table)

.. _Click: http://click.pocoo.org/5/