Vladimir Mihailenco avatar Vladimir Mihailenco committed e722384 Merge

Merge sudo_refactoring

Comments (0)

Files changed (10)

 .build/
 MANIFEST
 django_fab_deploy.egg-info/
+ve/

fab_deploy/apache.py

 def touch(wsgi_file=None):
     """ Reloads source code by touching the wsgi file. """
     if wsgi_file is None:
-        wsgi_file = env.conf['ENV_DIR']+'/var/wsgi/'+env.conf['INSTANCE_NAME']+'.py'
+        wsgi_file = env.conf['ENV_DIR'] + '/var/wsgi/' + env.conf['INSTANCE_NAME'] + '.py'
     run('touch ' + wsgi_file)
 
 def apache_make_wsgi():
     """ Uploads wsgi deployment script. """
-    wsgi_dir = env.conf['ENV_DIR']+'/var/wsgi/'
+    wsgi_dir = env.conf['ENV_DIR'] + '/var/wsgi/'
     run('mkdir -p ' + wsgi_dir)
-    file_name = env.conf['INSTANCE_NAME']+'.py'
-    utils.upload_config_template('django_wsgi.py', wsgi_dir+file_name)
+    file_name = env.conf['INSTANCE_NAME'] + '.py'
+    utils.upload_config_template('django_wsgi.py', wsgi_dir + file_name)
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def apache_restart():
     """ Restarts apache using init.d script. """
     # restart is not used because it can leak memory in some cases
-    run('invoke-rc.d apache2 stop')
-    run('invoke-rc.d apache2 start')
+    sudo('invoke-rc.d apache2 stop')
+    sudo('invoke-rc.d apache2 start')
 
 # ==== installation ===
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def apache_install():
     """ Installs apache. """
     system.aptitude_install('apache2 libapache2-mod-wsgi libapache2-mod-rpaf')
-    run('rm -f /etc/apache2/sites-enabled/default')
-    run('rm -f /etc/apache2/sites-enabled/000-default')
+    sudo('rm -f /etc/apache2/sites-enabled/default')
+    sudo('rm -f /etc/apache2/sites-enabled/000-default')
     apache_setup_locale()
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def apache_make_config():
     """ Updates apache config. """
     _apache_setup_port()
     name = env.conf['INSTANCE_NAME']
-    utils.upload_config_template('apache.config', '/etc/apache2/sites-available/%s' % name)
-    run('a2ensite %s' % name)
+    utils.upload_config_template('apache.config',
+                                 '/etc/apache2/sites-available/%s' % name,
+                                 use_sudo=True)
+    sudo('a2ensite %s' % name)
 
 def apache_setup():
     """ Updates apache config, wsgi script and restarts apache. """
     apache_make_wsgi()
     apache_restart()
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def apache_setup_locale():
     """ Setups apache locale. Apache is unable to handle file uploads with
     unicode file names without this. """
-    files.append('/etc/apache2/envvars', [
-            'export LANG="en_US.UTF-8"', 'export LC_ALL="en_US.UTF-8"'])
+    files.append('/etc/apache2/envvars',
+                 ['export LANG="en_US.UTF-8"', 'export LC_ALL="en_US.UTF-8"'],
+                 use_sudo=True)
 
 # === automatic apache ports management ===
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def _ports_lines():
-    with (settings(hide('stdout'))):
-        ports_data = run('cat ' + APACHE_PORTS_FILE)
+    with settings(hide('stdout')):
+        ports_data = sudo('cat ' + APACHE_PORTS_FILE)
     return ports_data.splitlines()
 
-@utils.run_as('root')
 def _used_ports(lines):
     ports_mapping = dict()
 
         if match:
             instance = None
             if index:
-                instance_match = re.match(instance_re, lines[index-1])
+                instance_match = re.match(instance_re, lines[index - 1])
                 if instance_match:
                     instance = instance_match.group('instance')
             ports_mapping[match.group('port')] = instance
     return ports_mapping
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def _apache_setup_port():
     """
     Makes sure some port is correctly listened in
             ])
             env.conf.APACHE_PORT = port
             puts('Instance is not binded to any port. Binding it to port ' + str(port))
-            run("echo '%s\n' > %s" % ('\n'.join(lines), APACHE_PORTS_FILE))
+            sudo("echo '%s\n' > %s" % ('\n'.join(lines), APACHE_PORTS_FILE))
             return
     warn('All apache ports are used!')

fab_deploy/deploy.py

 
 def make_clone():
     """ Creates repository clone on remote server. """
-    run('mkdir -p '+ env.conf.SRC_DIR)
+    run('mkdir -p ' + env.conf.SRC_DIR)
     with cd(env.conf.SRC_DIR):
         with settings(warn_only=True):
             vcs.init()
         if not console.confirm(message, default=False):
             abort("Aborting.")
 
-    @utils.run_as('root')
+    @utils.run_as_sudo
     def wipe_web():
-        run('rm -f /etc/nginx/sites-enabled/'+env.conf['INSTANCE_NAME'])
-        run('a2dissite ' + env.conf['INSTANCE_NAME'])
-        run('invoke-rc.d nginx reload')
-        run('invoke-rc.d apache2 reload')
+        sudo('rm -f /etc/nginx/sites-enabled/' + env.conf['INSTANCE_NAME'])
+        sudo('a2dissite ' + env.conf['INSTANCE_NAME'])
+        sudo('invoke-rc.d nginx reload')
+        sudo('invoke-rc.d apache2 reload')
 
     wipe_web()
     run('rm -rf %s' % env.conf.SRC_DIR)

fab_deploy/mysql.py

 __all__ = ['mysql_execute', 'mysql_install', 'mysql_create_db', 'mysqldump']
 
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def mysql_install():
     """ Installs mysql. """
     if _mysql_is_installed():
     # see http://serverfault.com/questions/19367/scripted-install-of-mysql-on-ubuntu
     os = utils.detect_os()
     system.aptitude_install('debconf-utils')
-    passwd=env.conf['DB_PASSWORD']
+    passwd = env.conf['DB_PASSWORD']
 
     mysql_versions = {'lenny': '5.0', 'squeeze': '5.1', 'maverick': '5.1'}
     version = mysql_versions[os]
         "mysql-server-%s mysql-server/root_password password %s" % (version, passwd),
     ]
 
-    run("echo '%s' | debconf-set-selections" % "\n".join(debconf_defaults))
+    sudo("echo '%s' | debconf-set-selections" % "\n".join(debconf_defaults))
 
     warn('\n=========\nThe password for mysql "root" user will be set to "%s"\n=========\n' % passwd)
     system.aptitude_install('mysql-server')

fab_deploy/nginx.py

 from __future__ import with_statement
-from fabric.api import run, env, settings
+from fabric.api import run, env, settings, sudo
 from fab_deploy import utils
 from fab_deploy import system
 from fab_deploy import apache
 __all__ = ['nginx_install', 'nginx_setup']
 
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def nginx_install():
     """ Installs nginx. """
     os = utils.detect_os()
     options = {'lenny': '-t lenny-backports'}
     system.aptitude_install('nginx', options.get(os, ''))
-    run('rm -f /etc/nginx/sites-enabled/default')
+    sudo('rm -f /etc/nginx/sites-enabled/default')
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def nginx_setup():
     """ Updates nginx config and restarts nginx. """
     apache._apache_setup_port()
     name = env.conf['INSTANCE_NAME']
-    utils.upload_config_template('nginx.config', '/etc/nginx/sites-available/%s' % name)
+    utils.upload_config_template('nginx.config',
+                                 '/etc/nginx/sites-available/%s' % name,
+                                 use_sudo=True)
     with settings(warn_only=True):
-        run('ln -s /etc/nginx/sites-available/%s /etc/nginx/sites-enabled/%s' % (name, name))
-    run('invoke-rc.d nginx restart')
+        sudo('ln -s /etc/nginx/sites-available/%s /etc/nginx/sites-enabled/%s' % (name, name))
+    sudo('invoke-rc.d nginx restart')

fab_deploy/system.py

 #coding: utf-8
 from __future__ import with_statement
 import os.path
-from fabric.api import run, settings, env, cd
+from fabric.api import run, settings, env, cd, sudo
 from fabric.contrib import files
 from fabric import utils as fabric_utils
 from fab_deploy import utils
 
 
-__all__ = ['create_linux_account', 'ssh_add_key']
+__all__ = ['create_linux_account', 'create_sudo_linux_account', 'ssh_add_key']
 
 
 def prepare_server():
     """ Prepares server: installs system packages. """
+    os = utils.detect_os()
+    if os in ['lenny', 'squeeze'] and env.conf.SUDO_USER == 'root':
+        install_sudo()
+
     setup_backports()
     install_common_software()
 
 @utils.run_as('root')
+def install_sudo():
+    run('aptitude install -y sudo')
+
+@utils.run_as_sudo
 def install_common_software():
     """ Installs common system packages. """
     common_packages = [
     extra_packages = {
         'lenny': ['libmysqlclient15-dev'],
         'squeeze': ['libmysqlclient-dev'],
-        'maverick': ['libmysqlclient-dev'],
+        'maverick': ['gcc', 'libmysqlclient-dev'],
     }
 
     os = utils.detect_os()
     aptitude_install('mercurial git', vcs_options.get(os, ""))
     aptitude_install('bzr', '--without-recommends')
 
-    run('easy_install -U pip')
-    run('pip install -U virtualenv')
+    sudo('easy_install -U pip')
+    sudo('pip install -U virtualenv')
 
 
-@utils.run_as('root')
 def setup_backports():
     """ Adds backports repo to apt sources. """
     os = utils.detect_os()
         fabric_utils.puts("Backports are not available for " + os)
         return
 
-    run("echo 'deb %s' > /etc/apt/sources.list.d/backports.sources.list" % backports[os])
+    sudo("echo 'deb %s' > /etc/apt/sources.list.d/backports.sources.list" % backports[os])
     with settings(warn_only=True):
-        run('aptitude update')
+        sudo('aptitude update')
 
-@utils.run_as('root')
+@utils.run_as_sudo
 def create_linux_account(pub_key_file):
     """ Creates linux account, setups ssh access and pip.conf file. """
     with open(os.path.normpath(pub_key_file), 'rt') as f:
         from fab_deploy import virtualenv
         virtualenv.pip_setup_conf()
 
+    #with (settings(warn_only=True)):
+    sudo('adduser %s --disabled-password --gecos ""' % username)
+    with cd(env.conf.HOME_DIR):
+        sudo('mkdir -p .ssh')
+        files.append('.ssh/authorized_keys', ssh_key, use_sudo=True)
+        sudo('chown -R %s:%s .ssh' % (username, username))
+    setup_pip_conf()
+
+@utils.run_as('root')
+def create_sudo_linux_account(pub_key_file, username=None):
+    if username is None:
+        username = env.conf.SUDO_USER
+    home_dir = '/home/%s' % username
+
+    with open(os.path.normpath(pub_key_file), 'rt') as f:
+        ssh_key = f.read()
+
+    @utils.run_as(username)
+    def setup_pip_conf():
+        from fab_deploy import virtualenv
+        virtualenv.pip_setup_conf()
+
     with (settings(warn_only=True)):
         run('adduser %s --disabled-password --gecos ""' % username)
-        with cd(env.conf.HOME_DIR):
+        with cd(home_dir):
             run('mkdir -p .ssh')
             files.append('.ssh/authorized_keys', ssh_key)
             run('chown -R %s:%s .ssh' % (username, username))
         setup_pip_conf()
 
+    line = '%s ALL=(ALL) NOPASSWD: ALL' % username
+    files.append('/etc/sudoers', line)
+
 def ssh_add_key(pub_key_file):
     """ Adds a ssh key from passed file to user's authorized_keys on server. """
     with open(os.path.normpath(pub_key_file), 'rt') as f:
     run('mkdir -p .ssh')
     files.append('.ssh/authorized_keys', ssh_key)
 
-
-@utils.run_as('root')
+@utils.run_as_sudo
 def aptitude_install(packages, options=''):
     """ Installs package via aptitude. """
-    run('aptitude install %s -y %s' % (options, packages,))
+    if not hasattr(env.conf, '_APTITUDE_UPDATED'):
+        sudo('aptitude update')
+        env.conf._APTITUDE_UPDATED = True
+    sudo('aptitude install %s -y %s' % (options, packages,))
 
-
-#@utils.run_as('root')
-#def install_backup_system():
-#    run('aptitude install -y s3cmd ruby rubygems libxml2-dev libxslt-dev libopenssl-ruby')
-#    run('gem install rubygems-update')
-#    run('/var/lib/gems/1.8/bin/update_rubygems')
-#    run('gem install astrails-safe --source http://gemcutter.org')
+@utils.run_as_sudo
+def install_backup_system():
+    sudo('aptitude install -y s3cmd ruby rubygems libxml2-dev libxslt-dev libopenssl-ruby')
+    sudo('gem install rubygems-update')
+    sudo('/var/lib/gems/1.8/bin/update_rubygems')
+    sudo('gem install astrails-safe --source http://gemcutter.org')

fab_deploy/utils.py

 from fabric import network
 
 
-__all__ = ['run_as', 'update_env',
-           'inside_project', 'inside_virtualenv', 'inside_src',
+__all__ = ['run_as', 'update_env', 'inside_project', 'inside_virtualenv',
            'delete_pyc', 'print_env', 'detect_os']
 
+
 def _codename(distname, version, id):
     patterns = [
         ('lenny', ('debian', '^5', '')),
         return inner
     return decorator
 
+def run_as_sudo(func):
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        return run_as(env.conf.SUDO_USER)(func)(*args, **kwargs)
+    return wrapper
+
 def upload_config_template(name, to=None, skip_unexistent=False, **kwargs):
     if to is None:
         base_dir = env.conf['ENV_DIR'] + "/etc/"
         run('mkdir -p ' + base_dir)
         to = base_dir + name
     config_template = _config_template_path(name)
+
     if config_template is None and skip_unexistent:
         return
     files.upload_template(config_template, to, env.conf, use_jinja=True,
             )
             update_env()
     """
-    assert len(env.hosts)==1, "Multiple hosts in env.hosts are not supported now. (%s)" % env.hosts
+    assert len(env.hosts) == 1, "Multiple hosts in env.hosts are not supported now. (%s)" % env.hosts
     user, host, port = network.normalize(env.hosts[0])
 
     env.conf = getattr(env, 'conf', {})
 
     defaults = state._AttributeDict(
         HG_BRANCH='default',
-        GIT_BRANCH = 'master',
+        GIT_BRANCH='master',
         DB_NAME=env.conf['INSTANCE_NAME'],
         DB_USER='root',
+        SUDO_USER='root',
         PROCESSES=1,
         THREADS=15,
         SERVER_NAME=host,
 
         PIP_REQUIREMENTS_PATH='reqs',
         PIP_REQUIREMENTS='all.txt',
-        PIP_REQUIREMENTS_ACTIVE = 'active.txt',
+        PIP_REQUIREMENTS_ACTIVE='active.txt',
 
         # these options shouldn't be set by user
         HOME_DIR=HOME_DIR,
         ENV_DIR=posixpath.join(HOME_DIR, 'envs', env.conf['INSTANCE_NAME']),
         SRC_DIR=SRC_DIR,
-        PROJECT_DIR = PROJECT_DIR,
+        PROJECT_DIR=PROJECT_DIR,
         USER=user,
     )
     defaults.update(env.conf)

fab_deploy/virtualenv.py

 
 def pip_setup_conf():
     """ Sets up pip.conf file """
+    run('mkdir -p .pip')
     utils.upload_config_template('pip.conf',
         env.conf.HOME_DIR + '/.pip/pip.conf', skip_unexistent=True)
 

fab_deploy_tests/tests/system_tests.py

 from __future__ import absolute_import
-from fabric.api import run,env,abort
+from fabric.api import run, env, abort
 from fabtest import fab, FabricAbortException
 
 from fab_deploy.utils import run_as
 
     def test_add_ssh_key(self):
         fab(setup_root_ssh)
-        env.password=None # should use ssh key
+        env.password = None # should use ssh key
         self.assertEqual(fab(whoami)[0], 'root')
 
 
 class PrepareServerTest(FabDeployTest):
     def test_prepare_server_ok(self):
+        setup_ssh()
+
         fab(prepare_server)
         self.assertPackageInstalled('memcached')
         self.assertPackageInstalled('python')

fab_deploy_tests/tests/utils_tests.py

 from fabric.api import *
 from fabtest import fab
 from fab_deploy.utils import run_as
+from fab_deploy.system import create_sudo_linux_account
 from .base import FabDeployTest
+from ..utils import public_key_path
 
 @run_as('root')
 def whoami():
         user = fab(whoami)[0]
         self.assertEqual(user, 'root')
 
+    def test_create_sudo_linux_account(self):
+        fab(create_sudo_linux_account, public_key_path(), 'test_sudo')
+
+        @run_as('test_sudo')
+        def whoami():
+            return run('whoami')
+
+        user = fab(whoami)[0]
+        self.assertEqual(user, 'test_sudo')
+
+        @run_as('test_sudo')
+        def test_sudo():
+            return run('sudo aptitude update')
+
+        fab(test_sudo)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.