After a few rounds of preliminary discussions on the mailing list, I felt it is better to begin building the CLI as per current design decisions. I feel that discussions over a piece of code would be more effective than just talk. Now that I have clearly expressed how I would approach the task and what's in my mind, it would be easy for the mentors to correct me or give me a proceed.

I have made a fair progress on implementing the CLI in the last week.I am  being a bit cautious and slow, as I have not yet received a review on the initial commits, which I expect at any moment.

Currently, I have implemented the following functionalities of the CLI project
  • The directory structure
    cli/
       |--mmclient             --- The mmclient command
       |--core/
            |--lists.py           --- The file that holds the Lists class
            |--domains.py     --- The file that holds the Domains class
       |--client/
            |--cmdparser.py  --- The command line parser parses aguments and triggers
            |                            an action
            |--shell.py          --- The Command shell
    The core directory contains the classes and scripts that perform the requested actions and the client directory holds the user interface managers like the shell and the command line parser.

  • The mmclient command, which if used without arguments, launches the Mailman shell else performs the specified action on the specified instance
  • The set of mailman commands follow the following format
    mmclient [instance name] [action] [options/flags]
    where the instance name can belong to {domain, list, user}, action can belong to {create, list, delete}. The options and flags are used to provide arguments to the action, like list name, domain name and boolean flags like ll.
  • The command line parser script, instantiates the Mailman instance mentioned in the command, and uses the getattr function to get the method of the instance which corresponds to the action mentioned in the command. This imposes a strict yet reasonable restriction upon the classes, that the methods corresponding to the action must have the same name as the action. The arguments dictionary returned by argparse parser are passed to the class method.
    This approach makes the implementation more scalable, although a bit restrictive with method names. My first implementation contained a if else ladder for each action, which requires to add an elif condition when a new action is added.
  • If the Mailman installation uses a non default login credentials to login to the REST API, the credentials may be specified using the options host, port, restuser, and restpass
  • The domain create command is used to create new domains, and takes domain name as argument
  • The list create command is used to create a new mailing list, and takes domain name and list name as arguments
  • The list action is implemented for both domains and lists. Using the –ll flag gives a detailed listing of domain or list. Listing mailing lists takes an optional argument domain name that can be used to filter out the lists
  • The long list feature produces a pretty printed table, describing the lists or domains. For lists, List ID, list name, mail host, display name, FQDN listen name are printed, while for domains base URL,contact address, mail host, URL host are printed. The long list feature is implemented using the python tabulate package, which has been added to Mailman client install requires.
  • All of the exceptions that have occurred during the development, like MailmanConnectionError, urllib2.HTTPError, have been handled appropriately and corresponding error messages are displayed when they occour.
  • The usage of developed commands are updated in the cli/docs/using.txt file