def domain_sites(): """ Get a list of domains Each domain is an attribute dict with name, site_id and settings """ if not hasattr(env,'domains'): sites = _get_django_sites() site_ids = sites.keys() site_ids.sort() domains = [] for id in site_ids: for file in _sitesettings_files(): domain = _AttributeDict({}) if file == 'settings.py': domain.name = sites[id] else: #prefix indicates subdomain subdomain = file[:-12].replace('_','.') domain.name = ''.join([subdomain,sites[id]]) domain.settings = file domain.site_id = id domains.append(domain) env.domains = domains if env.domains: env.root_domain = env.domains[0].name else: domain.name = _root_domain(); domain.site_id = 1; domain.settings='settings.py' env.domains = [domain] return env.domains
def lsb_release(): """ Get the linux distribution information and return in an attribute dict The following attributes should be available: base, distributor_id, description, release, codename For example Ubuntu Lucid would return base = debian distributor_id = Ubuntu description = Ubuntu 10.04.x LTS release = 10.04 codename = lucid """ output = run('lsb_release -a').split('\n') release = _AttributeDict({}) for line in output: try: key, value = line.split(':') except ValueError: continue release[key.strip().replace(' ','_').lower()]=value.strip() if exists('/etc/debian_version'): release.base = 'debian' elif exists('/etc/redhat-release'): release.base = 'redhat' else: release.base = 'unknown' return release
def adict(**kwargs): """Returns a fabric _AttributeDict that you can query as an object, to avoid using the ['foo'] bore. It allows for creating all envs like: envs = adict( production = adict( name = 'production', user = '******', hosts = ['domain.com'], db = dbdict( name = 'db_name', user = '******', password = '******', info = '-u%s -p%s %s', path_backup = '/some/path', ), paths = adict( source = '/some/path', documentation = '/some/path', ), restart_web_server_command = 'supervisorctl restart domain.com' ), testing = adict( ... similar to "production". If you want a access a setting from a specific env, you can the do something like: envs.production.db.name """ return _AttributeDict(dict(**kwargs))
def dbdict(**kwargs): """Special adict that formats info with db name, user and password info for use with mysql and mysqldump commands.""" the_dict = _AttributeDict(dict(**kwargs)) the_dict.info = the_dict.info % (the_dict.user, the_dict.password, the_dict.name) return the_dict
def set_platform(self, **write): """ Sets fabric.api.env attributes from the selected platform The setup follows the sequence: fabfile.env.platforms > tests_integration.platforms.common > tests_integration.platforms.<selected_platform> :param write: dictionary to inject into fabric.api.env """ module = import_module('.platforms.' + self.platform.platform_name, ROOT) getattr(module, self.platform.platform_name)(**self.platform.get_hosts(True)) self.platform.user = getattr(self.env, 'default_ssh_user', 'root') for k, v in write.iteritems(): setattr(self.env, k, v) # wait sshd daemon running on host platform self.platform.wait_process('/usr/sbin/sshd') # save and replace all references to fabric.api.env self.org_api_env = pyjack.replace_all_refs(api.env, _AttributeDict(api.env)) self.org_instances = pyjack.replace_all_refs(api.env.instances, dict(api.env.instances)) return self
Use of @hosts only """ host_list = ['a', 'b'] @hosts(*host_list) def command(): pass eq_hosts(command, host_list) fake_roles = {'r1': ['a', 'b'], 'r2': ['b', 'c']} @with_patched_object('fabric.state', 'env', _AttributeDict({'roledefs': fake_roles})) def test_roles_decorator_by_itself(): """ Use of @roles only """ @roles('r1') def command(): pass eq_hosts(command, ['a', 'b']) @with_patched_object('fabric.state', 'env', _AttributeDict({'roledefs': fake_roles})) def test_hosts_and_roles_together(): """
from fabric.state import _AttributeDict from fabric.api import cd from utils import upload_config, config_dir, build_properties from cloudbio.package.deb import _apt_packages import os DEFAULTS = dict( path='/var/puppet', log_level='info', modules=config_dir(os.path.join('puppet', 'modules')) ) puppet = _AttributeDict(DEFAULTS) def _puppet_provision(env, classes): env.safe_sudo('mkdir -p %(path)s' % puppet) manifest_body = "node default {\n%s\n}\n" % _build_node_def_body(env, classes) config_files = {"manifest.pp": manifest_body} upload_config(puppet, config_folder_names=["modules"], config_files=config_files) # TODO: Allow yum based install _apt_packages(pkg_list=["puppet"]) with cd(puppet.path): env.safe_sudo("sudo puppet apply --modulepath=modules manifest.pp") def _build_node_def_body(env, classes): contents = "" properties = build_properties(env, "puppet") contents += "\n".join(["$%s = '%s'" % (key, value.replace("'", r"\'")) for key, value in properties.iteritems()])
def load_sites(self, config_file_content=None, env_dict=None): """ Called from self.sites and returns a dictionary with the different sites and their individual settings. """ if not config_file_content: if env.get("use_local_config_ini", False): output = open("config.ini") else: config_file = os.path.join(env.path, "config.ini") if exists(config_file): output = StringIO.StringIO() get(u"%s" % config_file, output) output.seek(0) else: raise Exception("Missing config.ini, tried path %s" % config_file) else: output = StringIO.StringIO(config_file_content) if not env_dict: env_dict = env config = EnvConfigParser() config.readfp(output) self._sites = {} variables = { 'static_collected': STATIC_COLLECTED, 'data_directory': DATA_DIRECTORY, } for site in config.section_namespaces("django") or ["main"]: attr_dict = self.defaults.copy() for key, value in attr_dict.items(): attr_dict[key] = None if value is None else _AttributeDict(value.copy()) for section in config.sections(): section = section.split(":")[0] is_custom_process = section in (env_dict.get('custom_processes') or []) if is_custom_process: attr_dict[section] = { 'enabled': config.getboolean(section, 'enabled', env=site), 'command': config.get(section, 'command', env=site) % variables, 'django': config.getboolean(section, 'django', env=site), } continue if self.defaults.get(section) is None: print "Caution: Section %s is not supported, skipped" % section continue for option, default_value in config.items(section, env=site): setting = self.defaults.get(section).get(option) if type(setting) == bool: value = config.getboolean(section, option, env=site) elif type(setting) == int: value = config.getint(section, option, env=site) elif type(setting) == float: value = config.getfloat(section, option, env=site) else: value = config.get(section, option, env=site) % variables attr_dict[section][option] = value self.sites[site] = _AttributeDict(attr_dict) attr_dict.update(self.deployment(site, env_dict)) if attr_dict.get("checkout").get("tool") == "buildout": # e.g. bin/django -> /home/username/app/bin/django attr_dict["django"]["cmd"] = posixpath.join( attr_dict.get("deployment").get("path"), attr_dict.get("django").get("cmd") ) else: # e.g. manage.py -> /home/username/app/bin/python /home/username/app/manage.py new_django_cmd = [ posixpath.join( attr_dict.get("deployment").get("path"), "bin/python", ), posixpath.join( attr_dict.get("deployment").get("path"), attr_dict.get("django").get("base"), attr_dict.get("django").get("cmd") ) ] attr_dict["django"]["cmd"] = " ".join(new_django_cmd) if attr_dict["django"]["append_settings"]: attr_dict["django"]["args"].append(" --settings=%s" % ('_gen.settings', )) if attr_dict["newrelic"]["enabled"]: attr_dict["django"]["cmd"] = posixpath.join( attr_dict.get("deployment").get("path"), "bin/newrelic-admin" ) + " run-program " + attr_dict["django"]["cmd"] attr_dict.update({'processes': self.processes(site, env_dict)}) attr_dict['environment'] = self.environment(site, env_dict) attr_dict['environment'].setdefault('DEPLOYMENT_SITE', site) if attr_dict['deployment']['django_settings_module']: attr_dict['environment']['DJANGO_SETTINGS_MODULE'] = attr_dict['deployment']['django_settings_module'] attr_dict['environment_export'] = self.build_environment_export(attr_dict['environment']) attr_dict['identifier'] = env_dict.identifier self._sites[site] = _AttributeDict(attr_dict) return self._sites
def new(self, *items, **kwargs): kwargs.setdefault('base', _AttributeDict()) return self._extend(items, kwargs)
def load_sites(self, config_file_content=None, env_dict=None): """ Called from self.sites and returns a dictionary with the different sites and their individual settings. """ if not config_file_content: config_file = os.path.join(env.path, "config.ini") if exists(config_file): output = StringIO.StringIO() get(u"%s" % config_file, output) output.seek(0) else: raise Exception("Missing config.ini, tried path %s" % config_file) else: output = StringIO.StringIO(config_file_content) if not env_dict: env_dict = env config = EnvConfigParser() config.readfp(output) self._sites = {} for site in config.section_namespaces("django") or ["main"]: attr_dict = self.defaults.copy() for key, value in attr_dict.items(): attr_dict[key] = _AttributeDict(value.copy()) for section in config.sections(): section = section.split(":")[0] if self.defaults.get(section) is None: print "Caution: Section %s is not supported, skipped" % section continue for option, default_value in config.items(section, env=site): setting = self.defaults.get(section).get(option) if type(setting) == bool: value = config.getboolean(section, option, env=site) elif type(setting) == int: value = config.getint(section, option, env=site) elif type(setting) == float: value = config.getfloat(section, option, env=site) else: variables = { 'static_collected': STATIC_COLLECTED, 'data_directory': DATA_DIRECTORY, } value = config.get(section, option, env=site) % variables attr_dict[section][option] = value self.sites[site] = _AttributeDict(attr_dict) attr_dict.update(self.deployment(site, env_dict)) if attr_dict.get("checkout").get("tool") == "buildout": # e.g. bin/django -> /home/username/app/bin/django attr_dict["django"]["cmd"] = posixpath.join( attr_dict.get("deployment").get("path"), attr_dict.get("django").get("cmd")) else: # e.g. manage.py -> /home/username/app/bin/python /home/username/app/manage.py new_django_cmd = [ posixpath.join( attr_dict.get("deployment").get("path"), "bin/python", ), posixpath.join( attr_dict.get("deployment").get("path"), attr_dict.get("django").get("base"), attr_dict.get("django").get("cmd")) ] attr_dict["django"]["cmd"] = " ".join(new_django_cmd) if attr_dict["django"]["append_settings"]: attr_dict["django"]["args"].append(" --settings=%s" % ('_gen.settings', )) attr_dict.update({'processes': self.processes(site, env_dict)}) self._sites[site] = _AttributeDict(attr_dict) return self._sites
def update_env(): """ Updates :attr:`env.conf` configuration with some defaults and converts it to state._AttributeDict (that's a dictionary subclass enabling attribute lookup/assignment of keys/values). Call :func:`update_env` at the end of each server-configuring function. :: from fab_deploy import * def my_site(): env.hosts = ['*****@*****.**'] env.conf = dict( DB_PASSWORD = '******', ) update_env() """ 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', {}) env.conf.setdefault('INSTANCE_NAME', user) env.conf.setdefault('PROJECT_PATH', '') HOME_DIR = '/home/%s' % user if user != 'root' else '/root' SRC_DIR = posixpath.join(HOME_DIR, 'src', env.conf['INSTANCE_NAME']) PROJECT_DIR = posixpath.join(SRC_DIR, env.conf['PROJECT_PATH']).rstrip('/') defaults = state._AttributeDict( HG_BRANCH='default', GIT_BRANCH='master', DB_NAME=env.conf['INSTANCE_NAME'], DB_USER='******', SUDO_USER='******', PROCESSES=1, THREADS=15, SERVER_NAME=host, SERVER_ADMIN='*****@*****.**', VCS='hg', PROJECT_PATH='', LOCAL_CONFIG='config.py', REMOTE_CONFIG_TEMPLATE='config.server.py', CONFIG_TEMPLATES_PATHS=['config_templates'], PIP_REQUIREMENTS_PATH='reqs', PIP_REQUIREMENTS='all.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, USER=user, ) defaults.update(env.conf) env.conf = defaults if env.conf.DB_USER == 'root': if 'DB_ROOT_PASSWORD' in env.conf and 'DB_PASSWORD' in env.conf: msg = "DB_ROOT_PASSWORD and DB_PASSWORD must be the same because DB_USER is root" assert env.conf.DB_ROOT_PASSWORD == env.conf.DB_PASSWORD, msg else: # auto-fill the missing option password = env.conf.get('DB_ROOT_PASSWORD', env.conf.get('DB_PASSWORD', None)) if password is not None: env.conf.DB_PASSWORD = env.conf.DB_ROOT_PASSWORD = password for vcs in ['git', 'hg', 'none']: # expand VCS name to full import path if env.conf.VCS == vcs: env.conf.VCS = 'fab_deploy.vcs.' + vcs
woven_env = _AttributeDict( { "HOSTS": [], # optional - a list of host strings to setup on as per Fabric "ROLEDEFS": {}, # optional as per fabric. eg {'staging':['*****@*****.**']} "HOST_SSH_PORT": 10022, # optional - the ssh port to be setup "HOST_USER": "", # optional - can be used in place of defining it elsewhere (ie host_string) "HOST_PASSWORD": "", # optional # The first setup task is usually disabling the default root account and changing the ssh port. # If root is already disabled and the port changed. we assume the host_string user is already created and has sudo permissions "ROOT_DISABLED": False, # optional - also means the port has been changed to a new port. "ROOT_PASSWORD": "", # optional - blank by default "DEFAULT_SSH_PORT": 22, # optional - The default ssh port, prior to woven changing it. Defaults to 22 "UFW_DISABLED": False, # optional - If some alternative firewall is already pre-installed "UFW_RULES": [ "allow 80/tcp", "allow 443/tcp", ], # optional - the default firewall rules (note ssh is always allowed) "ROLE_UFW_RULES": {}, # The default ubuntu packages that are setup. It is NOT recommended you change these: "HOST_BASE_PACKAGES": [ "subversion", "git-core", "mercurial", "bzr", # version control "gcc", "build-essential", "python-dev", "python-setuptools", # build "apache2", "libapache2-mod-wsgi", "nginx", # webservers "python-paramiko", "fabric", "python-imaging", # pil "python-psycopg2", "python-mysqldb", "python-pysqlite2", ], # default database drivers "HOST_EXTRA_PACKAGES": [], # optional - additional ubuntu packages as required "ROLE_PACKAGES": {}, # define ROLEDEFS packages instead of using HOST_BASE_PACKAGES + HOST_EXTRA_PACKAGES # Virtualenv/Pip "DEPLOYMENT_ROOT": "", "PIP_REQUIREMENTS": [], # a list of pip requirement and or pybundle files to use for installation "DJANGO_REQUIREMENT": "", # A pip requirements string for the version of Django to install # Application media "STATIC_URL": "", # optional "STATIC_ROOT": "", # optional # Database migrations "MANUAL_MIGRATION": False, # optional Manage database migrations manually } )
def load_sites(self, config_file_content=None, env_dict=None): """ Called from self.sites and returns a dictionary with the different sites and their individual settings. """ if not config_file_content: config_file = os.path.join(env.path, "config.ini") if exists(config_file): output = StringIO.StringIO() get(u"%s" % config_file, output) output.seek(0) else: raise Exception("Missing config.ini, tried path %s" % config_file) else: output = StringIO.StringIO(config_file_content) if not env_dict: env_dict = env config = EnvConfigParser() config.readfp(output) self._sites = {} for site in config.section_namespaces("django") or ["main"]: attr_dict = self.defaults.copy() for key, value in attr_dict.items(): attr_dict[key] = _AttributeDict(value.copy()) for section in config.sections(): section = section.split(":")[0] if self.defaults.get(section) is None: print "Caution: Section %s is not supported, skipped" % section continue for option, default_value in config.items(section, env=site): setting = self.defaults.get(section).get(option) if type(setting) == bool: value = config.getboolean(section, option, env=site) elif type(setting) == int: value = config.getint(section, option, env=site) elif type(setting) == float: value = config.getfloat(section, option, env=site) else: variables = { 'static_collected': STATIC_COLLECTED, 'data_directory': DATA_DIRECTORY, } value = config.get(section, option, env=site) % variables attr_dict[section][option] = value self.sites[site] = _AttributeDict(attr_dict) attr_dict.update(self.deployment(site, env_dict)) if attr_dict.get("checkout").get("tool") == "buildout": # e.g. bin/django -> /home/username/app/bin/django attr_dict["django"]["cmd"] = posixpath.join( attr_dict.get("deployment").get("path"), attr_dict.get("django").get("cmd") ) else: # e.g. manage.py -> /home/username/app/bin/python /home/username/app/manage.py new_django_cmd = [ posixpath.join( attr_dict.get("deployment").get("path"), "bin/python", ), posixpath.join( attr_dict.get("deployment").get("path"), attr_dict.get("django").get("base"), attr_dict.get("django").get("cmd") ) ] attr_dict["django"]["cmd"] = " ".join(new_django_cmd) if attr_dict["django"]["append_settings"]: attr_dict["django"]["args"].append(" --settings=%s" % ('_gen.settings', )) attr_dict.update({'processes': self.processes(site, env_dict)}) self._sites[site] = _AttributeDict(attr_dict) return self._sites
def setup_conf(self): env.conf = _AttributeDict()
def setUp(self): self.setup_env() disconnect_all() self.previous_env = state._AttributeDict(env) super(FabTest, self).setUp()
import os import sys import tempfile from fabric.api import env, abort, runs_once from fabric.state import _AttributeDict from models import Proj myenv = env.myenv = _AttributeDict({ #'ltmp': '/tmp', # local temp path 'tmp': '/tmp', # remote temp path }) @runs_once def install_webadmin_path(): cwd = os.path.dirname(os.path.abspath(__file__)) cata_path = os.path.join(cwd, '..') sys.path.insert(0, cata_path) os.environ['DJANGO_SETTINGS_MODULE'] = 'webadmin.settings' def update_host(uuid, ips, **info): install_webadmin_path() from webadmin.core.models import Host, IP try: host = Host.objects.get(uuid=uuid) except Host.DoesNotExist: host = Host(uuid=uuid)
woven_env = _AttributeDict({ # Optional - a list of host strings to setup on as per Fabric. 'HOSTS': [], # Optional as per fabric. eg {'staging': ['*****@*****.**']}. 'ROLEDEFS': {}, # Optional - the ssh port to be setup. 'HOST_SSH_PORT': 10022, # Optional - can be used in place of defining it elsewhere # (ie. host_string). 'HOST_USER': '', # Optional. 'HOST_PASSWORD': '', # Optional - as per fabric, a path to a key to use in place your # local .ssh key. 'SSH_KEY_FILENAME': '', # The first setup task is usually disabling the default root # account and changing the ssh port. # # Optional - mostly the default administrative account is root. 'ROOT_USER': '******', # Optional - disable the default administrative account. 'DISABLE_ROOT': False, # Optional - blank by default. 'ROOT_PASSWORD': '', # Optional - The default ssh port, prior to woven changing it. # Defaults to 22. 'DEFAULT_SSH_PORT': 22, # Optional - setting this to true will disable password login and # use ssh keys only. 'DISABLE_SSH_PASSWORD': False, # Optional - If some alternative firewall is already pre-installed. 'ENABLE_UFW': True, # Optional - the default firewall rules (note ssh is always allowed). 'UFW_RULES': ['allow 80,443/tcp'], 'ROLE_UFW_RULES': {}, # The default packages that are setup. It is NOT recommended you # change these: 'HOST_BASE_PACKAGES': [ # Firewall. 'ufw', # Version control. 'subversion', 'git-core', 'mercurial', 'bzr', # Build. 'gcc', 'build-essential', 'python-dev', 'python-setuptools', # Webservers. 'apache2', 'libapache2-mod-wsgi', 'nginx', # PIL. 'python-imaging', # Default database drivers. 'python-psycopg2', 'python-mysqldb', 'python-pysqlite2'], # Optional - additional packages as required 'HOST_EXTRA_PACKAGES': [], # Define ROLEDEFS packages instead of using # HOST_BASE_PACKAGES + HOST_EXTRA_PACKAGES. 'ROLE_PACKAGES': {}, # Apache list of modules to disable for performance and memory # efficiency. This list gets disabled: 'APACHE_DISABLE_MODULES': [ 'alias', 'auth_basic', 'authn_file', 'authz_default', 'authz_groupfile', 'authz_user', 'autoindex', 'cgid', 'dir', 'setenvif', 'status', ], # Specify a linux base backend to use. Not yet implemented #'LINUX_BASE': 'debian', # Define a list of repositories/sources to search for packages. # eg. ppa: bchesneau/gunicorn 'LINUX_PACKAGE_REPOSITORIES': [], # Virtualenv/Pip. 'DEPLOYMENT_ROOT': '', # A relative path from the project package directory for any local # apps. 'PROJECT_APPS_PATH': '', # A list of pip requirement and or pybundle files to use for # installation. 'PIP_REQUIREMENTS': [], # Application media. # Optional. 'STATIC_URL': '', # Optional. 'STATIC_ROOT': '', # Database migrations. # # Optional - Manage database migrations manually. 'MANUAL_MIGRATION': False, })
woven_env = _AttributeDict({ 'HOSTS':[], #optional - a list of host strings to setup on as per Fabric 'DOMAINS':[], #optional a list of domains that will be deployed on the host. The first is the primary domain 'ROLEDEFS':{'staging':['']}, #optional as per fabric. Staging will be used in deployment 'HOST_SSH_PORT':10022, #optional - the ssh port to be setup 'HOST_USER':'', #optional - can be used in place of defining it elsewhere (ie host_string) 'HOST_PASSWORD':'',#optional #The first setup task is usually disabling the default root account and changing the ssh port. #If root is already disabled and the port changed. we assume the host_string user is already created and has sudo permissions 'ROOT_DISABLED': False, #optional - also means the port has been changed to a new port. 'ROOT_PASSWORD':'', #optional - blank by default 'DEFAULT_SSH_PORT':22, #optional - The default ssh port, prior to woven changing it. Defaults to 22 'UFW_DISABLED':False, #optional - If some alternative firewall is already pre-installed 'UFW_RULES':['allow 80/tcp','allow 443/tcp'], #optional - the default firewall rules (note ssh is always allowed) #The default ubuntu packages that are setup. It is NOT recommended you change these: 'HOST_BASE_PACKAGES':[ 'unattended-upgrades', #base 'subversion','git-core','mercurial','bzr', #version control 'gcc','build-essential', 'python-dev', 'python-setuptools', #build 'apache2','libapache2-mod-wsgi','nginx', #webservers 'python-paramiko','fabric', 'python-imaging', #pil 'python-psycopg2','python-mysqldb','python-pysqlite2'], #default database drivers #Put any additional packages here 'HOST_EXTRA_PACKAGES':[], #optional - additional ubuntu packages as required #Virtualenv/Pip 'PIP_REQUIREMENTS':[], # a list of pip requirement and or pybundle files to use for installation 'DJANGO_REQUIREMENT':'Django',#A pip requirements string for the version of Django to install #Application media 'STATIC_URL':'', #optional 'STATIC_ROOT':'', #optional })
""" Use of @hosts only """ host_list = ['a', 'b'] @hosts(*host_list) def command(): pass eq_hosts(command, host_list) fake_roles = { 'r1': ['a', 'b'], 'r2': ['b', 'c'] } @with_patched_object('fabric.state', 'env', _AttributeDict({'roledefs': fake_roles})) def test_roles_decorator_by_itself(): """ Use of @roles only """ @roles('r1') def command(): pass eq_hosts(command, ['a', 'b']) @with_patched_object('fabric.state', 'env', _AttributeDict({'roledefs': fake_roles})) def test_hosts_and_roles_together(): """ Use of @roles and @hosts together results in union of both """
import os,sys from fabric.api import env, abort, runs_once from fabric.state import _AttributeDict myenv = env.myenv = _AttributeDict({ 'ltmp': '/tmp', # local temp path 'tmp': '/tmp', # remote temp path #FIXME: tmp path need to cleanup automaticly #FIXME: workcopy used by "svn export" should be remove automaticly }) @runs_once def install_webadmin_path(): cwd = os.path.dirname(os.path.abspath(__file__)) cata_path = os.path.join(cwd, '..') sys.path.insert(0, cata_path) os.environ['DJANGO_SETTINGS_MODULE'] = 'webadmin.settings' def update_host(uuid, ips, **info): install_webadmin_path() from webadmin.core.models import Host, IP try: host = Host.objects.get(uuid=uuid) except Host.DoesNotExist: host = Host(uuid=uuid)
def update_env(): """ Updates :attr:`env.conf` configuration with some defaults and converts it to state._AttributeDict (that's a dictionary subclass enabling attribute lookup/assignment of keys/values). Call :func:`update_env` at the end of each server-configuring function. :: from fab_deploy import * def my_site(): env.hosts = ['*****@*****.**'] env.conf = dict( DB_PASSWORD = '******', ) update_env() """ 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', {}) env.conf.setdefault('INSTANCE_NAME', user) env.conf.setdefault('PROJECT_PATH', '') HOME_DIR = '/home/%s' % user if user != 'root' else '/root' SRC_DIR = posixpath.join(HOME_DIR, 'src', env.conf['INSTANCE_NAME']) PROJECT_DIR = posixpath.join(SRC_DIR, env.conf['PROJECT_PATH']).rstrip('/') defaults = state._AttributeDict( HG_BRANCH='default', GIT_BRANCH='master', DB_NAME=env.conf['INSTANCE_NAME'], DB_USER='******', SUDO_USER='******', PROCESSES=1, THREADS=15, SERVER_NAME=host, SERVER_ADMIN='*****@*****.**', VCS='hg', PROJECT_PATH='', LOCAL_CONFIG='config.py', REMOTE_CONFIG_TEMPLATE='config.server.py', CONFIG_TEMPLATES_PATHS=['config_templates'], PIP_REQUIREMENTS_PATH='reqs', PIP_REQUIREMENTS='all.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, USER=user, ) defaults.update(env.conf) env.conf = defaults if env.conf.DB_USER == 'root': if 'DB_ROOT_PASSWORD' in env.conf and 'DB_PASSWORD' in env.conf: msg = "DB_ROOT_PASSWORD and DB_PASSWORD must be the same because DB_USER is root" assert env.conf.DB_ROOT_PASSWORD == env.conf.DB_PASSWORD, msg else: # auto-fill the missing option password = env.conf.get('DB_ROOT_PASSWORD', env.conf.get('DB_PASSWORD', None)) if password is not None: env.conf.DB_PASSWORD = env.conf.DB_ROOT_PASSWORD = password for vcs in ['git', 'hg', 'none']: # expand VCS name to full import path if env.conf.VCS == vcs: env.conf.VCS = 'fab_deploy.vcs.' + vcs
Use of @hosts only """ host_list = ['a', 'b'] @hosts(*host_list) def command(): pass eq_hosts(command, host_list) fake_roles = { 'r1': ['a', 'b'], 'r2': ['b', 'c'] } @with_patched_object( 'fabric.state', 'env', _AttributeDict({'roledefs': fake_roles}) ) def test_roles_decorator_by_itself(): """ Use of @roles only """ @roles('r1') def command(): pass eq_hosts(command, ['a', 'b']) @with_patched_object( 'fabric.state', 'env', _AttributeDict({'roledefs': fake_roles}) ) def test_hosts_and_roles_together():
""" Use of @hosts only """ host_list = ["a", "b"] @hosts(*host_list) def command(): pass eq_hosts(command, host_list) fake_roles = {"r1": ["a", "b"], "r2": ["b", "c"]} @with_patched_object(fabric.state, "env", _AttributeDict({"roledefs": fake_roles})) def test_roles_decorator_by_itself(): """ Use of @roles only """ @roles("r1") def command(): pass eq_hosts(command, ["a", "b"]) @with_patched_object("fabric.state", "env", _AttributeDict({"roledefs": fake_roles})) def test_hosts_and_roles_together(): """
woven_env = _AttributeDict( { "HOSTS": [], # optional - a list of host strings to setup on as per Fabric "ROLEDEFS": {}, # optional as per fabric. eg {'staging':['*****@*****.**']} "HOST_SSH_PORT": 10022, # optional - the ssh port to be setup "HOST_USER": "", # optional - can be used in place of defining it elsewhere (ie host_string) "HOST_PASSWORD": "", # optional "SSH_KEY_FILENAME": "", # optional - as per fabric, a path to a key to use in place your local .ssh key # The first setup task is usually disabling the default root account and changing the ssh port. "ROOT_USER": "******", # optional - mostly the default administrative account is root "DISABLE_ROOT": False, # optional - disable the default administrative account "ROOT_PASSWORD": "", # optional - blank by default "DEFAULT_SSH_PORT": 22, # optional - The default ssh port, prior to woven changing it. Defaults to 22 "DISABLE_SSH_PASSWORD": False, # optional - setting this to true will disable password login and use ssh keys only. "ENABLE_UFW": True, # optional - If some alternative firewall is already pre-installed # optional - the default firewall rules (note ssh is always allowed) "UFW_RULES": ["allow 80,443/tcp"], "ROLE_UFW_RULES": {}, # The default packages that are setup. It is NOT recommended you change these: "HOST_BASE_PACKAGES": [ "ufw", # firewall "subversion", "git-core", "mercurial", "bzr", # version control "gcc", "build-essential", "python-dev", "python-setuptools", # build "apache2", "libapache2-mod-wsgi", "nginx", # webservers "python-paramiko", "fabric", "python-imaging", # pil "python-psycopg2", "python-mysqldb", "python-pysqlite2", ], # default database drivers "HOST_EXTRA_PACKAGES": [], # optional - additional packages as required "ROLE_PACKAGES": {}, # define ROLEDEFS packages instead of using HOST_BASE_PACKAGES + HOST_EXTRA_PACKAGES # Apache list of modules to disable for performance and memory efficiency # This list gets disabled "APACHE_DISABLE_MODULES": [ "alias", "auth_basic", "authn_file", "authz_default", "authz_groupfile", "authz_user", "autoindex", "cgid", "dir", "setenvif", "status", ], # Specify a linux base backend to use. Not yet implemented #'LINUX_BASE':'debian', # define a list of repositories/sources to search for packages "LINUX_PACKAGE_REPOSITORIES": [], # eg ppa:bchesneau/gunicorn # Virtualenv/Pip "DEPLOYMENT_ROOT": "", "PROJECT_APPS_PATH": "", # a relative path from the project package directory for any local apps "PIP_REQUIREMENTS": [], # a list of pip requirement and or pybundle files to use for installation "DJANGO_REQUIREMENT": "", # A pip requirements string for the version of Django to install # Application media "STATIC_URL": "", # optional "STATIC_ROOT": "", # optional # Database migrations "MANUAL_MIGRATION": False, # optional Manage database migrations manually } )
woven_env = _AttributeDict({ 'HOSTS': [], #optional - a list of host strings to setup on as per Fabric 'ROLEDEFS': {}, #optional as per fabric. eg {'staging':['*****@*****.**']} 'HOST_SSH_PORT': 10022, #optional - the ssh port to be setup 'HOST_USER': '', #optional - can be used in place of defining it elsewhere (ie host_string) 'HOST_PASSWORD': '', #optional 'SSH_KEY_FILENAME': '', #optional - as per fabric, a path to a key to use in place your local .ssh key #The first setup task is usually disabling the default root account and changing the ssh port. 'ROOT_USER': '******', #optional - mostly the default administrative account is root 'DISABLE_ROOT': False, #optional - disable the default administrative account 'ROOT_PASSWORD': '', #optional - blank by default 'DEFAULT_SSH_PORT': 22, #optional - The default ssh port, prior to woven changing it. Defaults to 22 'DISABLE_SSH_PASSWORD': False, #optional - setting this to true will disable password login and use ssh keys only. 'ENABLE_UFW': True, #optional - If some alternative firewall is already pre-installed #optional - the default firewall rules (note ssh is always allowed) 'UFW_RULES': ['allow 80,443/tcp'], 'ROLE_UFW_RULES': {}, #The default packages that are setup. It is NOT recommended you change these: 'HOST_BASE_PACKAGES': [ 'ufw', #firewall 'subversion', 'git-core', 'mercurial', 'bzr', #version control 'gcc', 'build-essential', 'python-dev', 'python-setuptools', #build 'apache2', 'libapache2-mod-wsgi', 'nginx', #webservers 'python-imaging', #pil 'python-psycopg2', 'python-mysqldb', 'python-pysqlite2' ], #default database drivers 'HOST_EXTRA_PACKAGES': [], #optional - additional packages as required 'ROLE_PACKAGES': {}, #define ROLEDEFS packages instead of using HOST_BASE_PACKAGES + HOST_EXTRA_PACKAGES #Apache list of modules to disable for performance and memory efficiency #This list gets disabled 'APACHE_DISABLE_MODULES': [ 'alias', 'auth_basic', 'authn_file', 'authz_default', 'authz_groupfile', 'authz_user', 'autoindex', 'cgid', 'dir', 'setenvif', 'status' ], #Specify a linux base backend to use. Not yet implemented #'LINUX_BASE':'debian', #define a list of repositories/sources to search for packages 'LINUX_PACKAGE_REPOSITORIES': [], # eg ppa:bchesneau/gunicorn #Virtualenv/Pip 'DEPLOYMENT_ROOT': '', 'PROJECT_APPS_PATH': '', #a relative path from the project package directory for any local apps 'PIP_REQUIREMENTS': [], #a list of pip requirement and or pybundle files to use for installation #Application media 'STATIC_URL': '', #optional 'STATIC_ROOT': '', #optional #Database migrations 'MANUAL_MIGRATION': False, #optional Manage database migrations manually })