From 8e14aa0fcfd561350c8254f5b40fb05c4a4ee6ef Mon Sep 17 00:00:00 2001
From: Seblu <sebastien.luttringer@smartjog.com>
Date: Mon, 3 Jan 2011 19:37:54 +0100
Subject: [PATCH] Add profile support

---
 README                                 |  44 ++++++++++-
 bin/cc-cli                             | 105 +++++++++++++------------
 cccli/__init__.py                      |   1 +
 examples/alias                         |   6 ++
 examples/cli                           |   4 +
 examples/lab.profile                   |   5 ++
 examples/millet.profile                |   6 ++
 examples/{cc-cli.conf => prod.profile} |   8 +-
 8 files changed, 122 insertions(+), 57 deletions(-)
 create mode 100644 examples/alias
 create mode 100644 examples/cli
 create mode 100644 examples/lab.profile
 create mode 100644 examples/millet.profile
 rename examples/{cc-cli.conf => prod.profile} (51%)

diff --git a/README b/README
index 9888d12..5bb9391 100644
--- a/README
+++ b/README
@@ -1,6 +1,48 @@
+======
+Config
+======
+cc-cli support FreeDesktop BaseDirectory specifications (http://standards.freedesktop.org/basedir-spec/0.6/)
+Your main config is stored in ~/.config/cc-cli/cli (ini file format with section cli)
+You can configure all parameter in this file
+You will find an example in examples subdirectory in git.
+
+You can set default behaviour with environment variables. The following are recognised:
+CC_SERVER, CC_PORT, CC_LOGIN, CC_PASS, CC_DEBUG, CC_PROFILE
+
+To quickly connect to mulptiple servers, you can define profiles.
+A profile is an ini config file in ~/.config/cc-cli/ directory with suffix .profile and section profile.
+Profiles file are loaded exactly like the main config file.
+You can load toto profile by calling cc-cli -P toto
+You have to play with the following loading order to do worderful things.
+
+You configuration is loaded in this order:
+1 load default config file settings
+2 load default config file profile
+2 load environment profile
+3 load environment settings
+4 load argline profile
+5 load argline settings
+
+=====
+Alias
+=====
+CLI support aliasing. This is a very useful command substitution
+You can use the alias command to set alias.
+
+Setting an alias w, which list online client
+alias w "list a&con!=offline&role=client"
+
+Setting an alias vm, which list running vm (and show cpu)
+alias vm "list vm&status=running$cpu"
+
+===
+TQL
+===
+You can look in TQL file to see the power of tql.
+
 ===========
 New release
 ===========
 Update version in cccli/__init__.py
 Update version in debian/control
-Update version in debian/changelog
\ No newline at end of file
+Update version in debian/changelog
diff --git a/bin/cc-cli b/bin/cc-cli
index 95fb6d7..90abfb5 100755
--- a/bin/cc-cli
+++ b/bin/cc-cli
@@ -19,25 +19,41 @@ from cccli.cli import Cli
 from cccli.printer import Printer
 from cccli.exception import *
 
-canonical_name="cc-cli"
 settings = {
     "port": "1984",
-    "timeout": "5",
+    "timeout": "30",
     "hsize": "100",
-    "config": "%s/cli"%BaseDirectory.save_config_path(canonical_name),
-    "alias": "%s/alias"%BaseDirectory.save_config_path(canonical_name),
-    "history": "%s/history"%BaseDirectory.save_data_path(canonical_name),
+    "config": "%s/cli"%BaseDirectory.save_config_path(cccli.canonical_name),
+    "alias": "%s/alias"%BaseDirectory.save_config_path(cccli.canonical_name),
+    "history": "%s/history"%BaseDirectory.save_data_path(cccli.canonical_name),
     }
 
-printer = Printer(False)
+def load_config_file(config, filename, section):
+    '''Update a dict with param from an ini file '''
+    if os.access(filename, os.R_OK):
+        fparser = ConfigParser.SafeConfigParser()
+        fparser.read(filename)
+        if fparser.has_section(section):
+            config.update(fparser.items(section))
+    else:
+        printer.warn("Unable to load file %s"%filename)
+
+def get_profile_path(profile):
+    '''Force a profile path from a profile name'''
+    return "%s/%s/%s.profile"%(BaseDirectory.xdg_config_home, cccli.canonical_name, profile)
 
 try:
+    # load a printer
+    printer = Printer(False)
+
     # parse config file
     if os.access(settings["config"], os.R_OK):
-        fparser = ConfigParser.SafeConfigParser()
-        fparser.read(settings["config"])
-        if fparser.has_section("cli"):
-            settings.update(fparser.items("cli"))
+        load_config_file(settings, settings["config"], "cli")
+
+    # parse config file profile
+    if "profile" in settings:
+        load_config_file(settings, get_profile_path(settings["profile"]), "profile")
+        del settings["profile"]
 
     # parse env
     if "CC_SERVER" in os.environ:
@@ -51,65 +67,51 @@ try:
     if "CC_DEBUG" in os.environ:
         settings["debug"] = "True"
 
+    # parse env profile
+    if "CC_PROFILE" in os.environ:
+        load_config_file(settings, get_profile_path(os.environ["CC_PROFILE"]), "profile")
+
     # Parse line argument
     oparser = optparse.OptionParser(usage="usage: %prog [options] [commands]",
                                     version=cccli.version)
-    oparser.add_option("-d", "--debug",
-                       action="store_true",
-                       dest="debug",
-                       default="",
-                       help="debug mode")
-    oparser.add_option("-l", "--login",
-                       action="store",
-                       dest="login",
-                       default="",
-                       help="server login")
-    oparser.add_option("-s", "--server",
-                       action="store",
-                       dest="server",
-                       default="",
-                       help="server address")
-    oparser.add_option("-p", "--port",
-                       action="store",
-                       dest="port",
-                       default="1984",
-                       help="server port")
-    oparser.add_option("-t", "--timeout",
-                       action="store",
-                       dest="timeout",
-                       default="10",
-                       help="connection timeout")
-    oparser.add_option("--history-file",
-                       action="store",
-                       dest="history",
-                       default="",
+    oparser.add_option("-d", "--debug", action="store_true",dest="debug",
+                       help="Debug mode")
+    oparser.add_option("-l", "--login",action="store",dest="login",
+                       help="Server login")
+    oparser.add_option("-H", "--hostname",action="store",dest="server",
+                       help="Server hostname")
+    oparser.add_option("-P", "--port",action="store",dest="port",
+                       help="Server port")
+    oparser.add_option("-t", "--timeout",action="store",dest="timeout",
+                       help="Connection timeout")
+    oparser.add_option("-p", "--profile",action="store",dest="profile",
+                       help="Profile name")
+    oparser.add_option("--history-file",action="store",dest="history",
                        help="History file")
-    oparser.add_option("--history-size",
-                       action="store",
-                       dest="hsize",
-                       default="",
+    oparser.add_option("--history-size",action="store",dest="hsize",
                        help="History max entry count")
-    oparser.add_option("--force-yes",
-                       action="store_true",
-                       dest="forceyes",
-                       default="",
-                       help="Answer yes to yes/no question")
+    oparser.add_option("--force-yes",action="store_true",dest="forceyes",
+                       help="Answer Yes to all questions (Dangerous)")
     (options, args) = oparser.parse_args()
 
     # options handling
-    for i in ("debug", "login", "server", "port", "timeout", "history", "hsize", "forceyes"):
+    for i in [ x.dest for x in oparser.option_list if x.dest ]:
         if hasattr(options, i):
             o = getattr(options, i)
             if o:
                 settings[i] = o
 
+    # parse argline file profile
+    if "profile" in settings:
+        load_config_file(settings, get_profile_path(settings["profile"]), "profile")
+        del settings["profile"]
+
     # debug stuff
     if "debug" in settings:
         cccli.debug = bool(settings["debug"])
     else:
         warnings.filterwarnings("ignore")
     printer.debug("Debugging on")
-    printer.debug("Settings: %s"%settings)
 
     # checking server name
     if "server" not in settings:
@@ -131,6 +133,9 @@ try:
         printer.setinteractive()
         settings["pass"] = printer.getpass("Password: ")
 
+    # print settings
+    printer.debug("Settings: %s"%settings)
+
     # start cli
     cli = Cli(settings)
     cli.start(" ".join(args))
diff --git a/cccli/__init__.py b/cccli/__init__.py
index 243610e..1585ef8 100644
--- a/cccli/__init__.py
+++ b/cccli/__init__.py
@@ -5,5 +5,6 @@
 CloudControl CLI
 '''
 
+canonical_name="cc-cli"
 version = "1~dev"
 debug = False
diff --git a/examples/alias b/examples/alias
new file mode 100644
index 0000000..f9bded9
--- /dev/null
+++ b/examples/alias
@@ -0,0 +1,6 @@
+[alias]
+lt = list -t
+ls = list
+w = list a&con!=offline&role=client
+vm = list vm&status=running$cpu
+
diff --git a/examples/cli b/examples/cli
new file mode 100644
index 0000000..f1979bd
--- /dev/null
+++ b/examples/cli
@@ -0,0 +1,4 @@
+[cli]
+hsize = 1000
+profile = lab
+
diff --git a/examples/lab.profile b/examples/lab.profile
new file mode 100644
index 0000000..b625902
--- /dev/null
+++ b/examples/lab.profile
@@ -0,0 +1,5 @@
+[profile]
+login = sluttrin
+pass = toto42sh
+server = 192.168.0.162
+
diff --git a/examples/millet.profile b/examples/millet.profile
new file mode 100644
index 0000000..ccd42c5
--- /dev/null
+++ b/examples/millet.profile
@@ -0,0 +1,6 @@
+[profile]
+login = seblu
+pass = iloveseblu
+server = 192.168.0.41
+debug = true
+
diff --git a/examples/cc-cli.conf b/examples/prod.profile
similarity index 51%
rename from examples/cc-cli.conf
rename to examples/prod.profile
index 3252638..865359f 100644
--- a/examples/cc-cli.conf
+++ b/examples/prod.profile
@@ -1,7 +1,3 @@
-[cli]
-server = 10.15.255.42
-port = 1984
+[profile]
 login = sluttrin
-
-[alias]
-ls = list
+server = 10.15.255.42
-- 
GitLab