Commits

Vladimir Mihailenco committed f635cb3

Generalize config handling (try env.conf.current_time); detect_os is task now; cpu_count task added

  • Participants
  • Parent commits f0a5382
  • Tags v0.1.3

Comments (0)

Files changed (6)

File fabdeploy/base.py

 import sys
 import posixpath
 import logging
+import datetime
 try:
     from collections import OrderedDict
 except ImportError:
 from fabric.api import env
 from fabric import network
 
-from fabdeploy.containers import MultiSourceDict, AttributeDict
-from fabdeploy.utils import get_home_path, detect_os
+from fabdeploy.containers import MultiSourceDict, AttributeDict, conf
+from fabdeploy.utils import get_home_path
 
 
 logger = logging.getLogger('fabdeploy')
     return posixpath.join(env.conf.django_path, name)
 
 
-try:
-    import multiprocessing
-except ImportError:
-    CPU_COUNT = 4
-else:
-    CPU_COUNT = multiprocessing.cpu_count()
+@conf
+def os_codename(conf):
+    from fabdeploy import system
+    conf.os = system.os_codename.run()
+    return conf.os
+
+
+@conf
+def cpu_count(conf):
+    from fabdeploy import system
+    conf.cpu_count = system.cpu_count.run()
+    return conf.cpu_count
+
+
+@conf
+def current_time(conf):
+    return datetime.datetime.utcnow().strftime(conf.time_format)
 
 
 DEFAULTS = OrderedDict([
+    ('os', os_codename),
+    ('cpu_count', cpu_count),
+
     ('instance_name', '%(user)s'),
     ('django_path_getter', get_django_path),
     ('django_lpath_getter', get_django_lpath),
     ('project_dir', ''),
     # directory name that contains manage.py file (django project root)
     ('django_dir', ''),
-    ('home_path', lambda conf: get_home_path(conf.user)),
+    ('home_path', conf(lambda conf: get_home_path(conf.user))),
     ('src_path', ['%(home_path)s', 'src', '%(instance_name)s']),
     ('project_path', ['%(src_path)s', '%(project_dir)s']),
     ('django_path', ['%(project_path)s', '%(django_dir)s']),
     ('django_lpath', ['%(src_lpath)s', '%(django_ldir)s']),
 
     ('time_format', '%Y.%m.%d-%H.%M'),
+    ('current_time', current_time),
     # user that have sudo right
     # this is useful, because usually deploy user don't have sudo right
     ('sudo_user', 'root'),
     ('server_admin', 'admin@%(host)s'),
 
     ('apache_processes', 1),
-    ('apache_threads', CPU_COUNT * 2 + 1),
-    ('uwsgi_processes', CPU_COUNT * 2 + 1),
-    ('gunicorn_workers', CPU_COUNT * 2 + 1),
+    ('apache_threads', conf(lambda conf: conf.cpu_count * 2 + 1)),
+    ('uwsgi_processes', conf(lambda conf: conf.cpu_count * 2 + 1)),
 
     ('config_templates_lpath_getter', get_config_template_path),
     ('config_templates_pathes', ['config_templates']),
 
 def process_conf(user_conf, use_defaults=True):
     user_conf = AttributeDict(user_conf or {})
-    conf = AttributeDict()
+    conf = MultiSourceDict(name='process_conf')
 
     if 'address' in user_conf:
         conf.setdefault('address', user_conf.address)
         conf.setdefault('user', username)
         conf.setdefault('host', host)
 
-    if 'os' not in user_conf and 'address' in conf:
-        conf.setdefault('os', detect_os(conf.address))
-
     if use_defaults:
         merged_conf = DEFAULTS.copy()
         merged_conf.update(user_conf)
         merged_conf = user_conf
 
     for k, v in merged_conf.items():
-        if callable(v) and not k.endswith('_getter'):
-            v = v(conf)
-
         try:
             v = substitute(v, conf)
         except ValueError:
             logger.debug('Can not format %r=%r' % (k, v))
-            pass
 
         if k.endswith(('_dir', '_path')) and isinstance(v, (list, tuple)):
             v = posixpath.join(*v).rstrip(posixpath.sep)

File fabdeploy/containers.py

 
         self.kwargs = kwargs or {}
 
+    def process_conf(self, conf, name):
+        value = conf[name]
+        if callable(value) and hasattr(value, '_is_conf'):
+            value = value(self)
+            if name in self.kwargs:
+                env.conf[name] = self.kwargs[name]
+        return value
+
     def get_value(self, name, use_prompt=True):
         if name in self.kwargs:
-            return self.kwargs[name]
+            return self.process_conf(self.kwargs, name)
 
         if name in self.task_conf_keys:
             # delete to avoid recursion
             else:
                 raise MissingVarException(name)
 
-        return self.conf[name]
+        return self.process_conf(self.conf, name)
 
     def set_value(self, name, value):
         self.kwargs[name] = value

File fabdeploy/fabd.py

 
 class Debug(Task):
     """Echo config variable."""
+
     def do(self):
         puts(self.conf[self.conf.var])
 

File fabdeploy/system.py

-from fabric.api import env, sudo
+import re
+import ast
+
+from fabric.api import env, run, sudo, settings, hide
 from fabric.utils import puts, abort
 
 from fabdeploy.containers import conf
 from fabdeploy import pip
 
 
-__all__ = ['aptitude_install', 'setup_backports', 'install_common_software']
+__all__ = ['cpu_count', 'os_codename', 'aptitude_install', 'setup_backports',
+           'install_common_software']
+
+
+class CpuCount(Task):
+    def get_cpu_count(self):
+        with settings(hide('everything')):
+            output = run('python -c "import multiprocessing; '
+                         'print multiprocessing.cpu_count()"')
+        return ast.literal_eval(output)
+
+    def do(self):
+        cpu_count = self.get_cpu_count()
+        puts('Number of CPUs: %s' % cpu_count)
+        return cpu_count
+
+cpu_count = CpuCount()
+
+
+class OSCodename(Task):
+    def get_codename(self):
+        with settings(hide('everything')):
+            output = run('python -c "import platform; print platform.dist()"')
+        distname, version, id = ast.literal_eval(output)
+
+        patterns = [
+            ('squeeze', ('debian', '^6', '')),
+            ('lenny', ('debian', '^5', '')),
+            ('natty', ('Ubuntu', '^11.04', '')),
+            ('maverick', ('Ubuntu', '^10.10', '')),
+            ('lucid', ('Ubuntu', '^10.04', '')),
+        ]
+        for name, p in patterns:
+            if (re.match(p[0], distname) and
+                    re.match(p[1], version) and
+                    re.match(p[2], id)):
+                return name
+
+    def do(self):
+        codename = self.get_codename()
+        if codename is None:
+            abort('Your OS is unsupported')
+            return
+        puts('OS codename: %s' % codename)
+        return codename
+
+os_codename = OSCodename()
 
 
 class AptitudeUpdate(Task):

File fabdeploy/task.py

     def do(self):
         raise NotImplementedError()
 
-    @conf
-    def current_time(self):
-        return datetime.datetime.utcnow().strftime(self.conf.time_format)
-
     def generate_name(self):
         s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', self.__class__.__name__)
         return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
             if old_kwargs is not None:
                 # conf can be reused, but kwargs should not
                 self.conf.kwargs = old_kwargs
-            else:
+            elif self.conf:
                 self.conf.kwargs = {}
                 self.conf = None
 

File fabdeploy/utils.py

-import re
 import posixpath
 from functools import wraps
 from contextlib import contextmanager
 
-from fabric.api import env, cd, run, prefix, abort
+from fabric.api import env, cd, prefix
 from fabric import network
-from fabric.utils import puts
 from fabric.operations import _handle_failure
 from fabric.contrib.files import upload_template
 
 
-DETECTION_ERROR_MESSAGE = """
-OS detection failed. This probably means your OS is not
-supported by django-fab-deploy. If you really know what
-you are doing, set env.conf.OS variable to desired OS
-name in order to bypass this error message.
-If you believe the OS is supported but the detection
-fails or you want to get your OS supported, please fire an issue at
-https://bitbucket.org/kmike/django-fab-deploy/issues/new
-"""
-
-
-def codename(distname, version, id):
-    patterns = [
-        ('squeeze', ('debian', '^6', '')),
-        ('lenny', ('debian', '^5', '')),
-        ('natty', ('Ubuntu', '^11.04', '')),
-        ('maverick', ('Ubuntu', '^10.10', '')),
-        ('lucid', ('Ubuntu', '^10.04', '')),
-    ]
-    for name, p in patterns:
-        if (re.match(p[0], distname) and
-                re.match(p[1], version) and
-                re.match(p[2], id)):
-            return name
-
-
-def detect_os(address):
-    with host(address):
-        output = run('python -c "import platform; print platform.dist()"')
-
-    name = codename(*eval(output))
-    if name is None:
-        abort(DETECTION_ERROR_MESSAGE)
-        return
-
-    puts('OS %s is detected' % name)
-    return name
-
-
 @contextmanager
 def host(host_string):
     old_host_string = env.host_string