def ec2_fab(service, args): """ Run Fabric commands against EC2 instances """ instance_ids = args.instances instances = service.list(elb=args.elb, instance_ids=instance_ids) hosts = service.resolve_hosts(instances) fab.env.hosts = hosts fab.env.key_filename = settings.get('SSH', 'KEY_FILE') fab.env.user = settings.get('SSH', 'USER', getpass.getuser()) fab.env.parallel = True fabfile = find_fabfile(args.file) if not fabfile: print 'Couldn\'t find any fabfiles!' return fab.env.real_fabile = fabfile docstring, callables, default = load_fabfile(fabfile) fab_state.commands.update(callables) commands_to_run = parse_arguments(args.methods) for name, args, kwargs, arg_hosts, arg_roles, arg_exclude_hosts in commands_to_run: fab.execute(name, hosts=arg_hosts, roles=arg_roles, exclude_hosts=arg_exclude_hosts, *args, **kwargs)
def visit_fabfile(path=None): """Load and process a fabfile from the current working directory.""" path = path or find_fabfile() if not path: raise ValueError('No fabfile detected') callables = load_fabfile(path)[1] return visit(callables)
def test_find_fabfile_can_discovery_package_with_pyc_only(self): """ Fabric should be capable of loading a package with __init__.pyc only. """ path = self.mkfile("__init__.pyc", "") name = os.path.dirname(path) assert find_fabfile([name,]) is not None
def test_find_fabfile_can_discovery_package(self): """Fabric should be capable of loading a normal package.""" path = self.mkfile("__init__.py", "") name = os.path.dirname(path) assert find_fabfile([ name, ]) is not None
def test_find_fabfile_should_refuse_fake_package(self): """Fabric should refuse to load a non-package directory.""" path = self.mkfile("foo.py", "") name = os.path.dirname(path) assert find_fabfile([ name, ]) is None
def display_fabric_tasks(): paths = find_fabfile() docstring, callables, default = load_fabfile(paths) callables.pop('setup', None) state.commands.update(callables) commands = list_commands(docstring, 'normal') print("\n".join(commands))
def import_fabfile(fabfile='fabfile.py'): """ you have to call this first to enable fabric tasks""" from fabric.main import find_fabfile, load_fabfile from fabric.network import normalize from fabric import state state.env.fabfile = fabfile _, fabfile = load_fabfile(find_fabfile()) return fabfile
def test_find_fabfile_can_discovery_package_with_pyc_only(self): """ Fabric should be capable of loading a package with __init__.pyc only. """ path = self.mkfile("__init__.pyc", "") name = os.path.dirname(path) assert find_fabfile([ name, ]) is not None
def get_fabric_tasks(request): """ Generate a list of fabric tasks that are available """ try: docstring, callables, default = load_fabfile(find_fabfile(None)) all_tasks = _task_names(callables) dict_with_docs = {task: callables[task].__doc__ for task in all_tasks} except Exception as e: messages.error(request, 'Error loading fabfile: ' + e.message) dict_with_docs = {} return dict_with_docs
def deploy(): """ Deploy local copy of repository to target environment. """ require('branch', provided_by=[master, stable, branch, ]) with context_managers.lcd(os.path.dirname(find_fabfile())): # Allows you to run deploy from any child directory of the project ret = wp.deploy() if ret.return_code and ret.return_code > 0: if ret.return_code in [4, ]: print(colors.red("Try running ") + colors.white("fab wp.verify_prerequisites")) else: notify_hipchat()
def main(): """Load our default fabfile, then attempt to load any local fabfiles.""" our_fab = os.path.join(os.path.dirname(__file__), 'default_tasks.py') docstring, callables, default = fab.load_fabfile(our_fab) fab.state.commands.update(callables) fabfiles = [] other_fab = fab.find_fabfile() if other_fab: fabfiles.append(other_fab) fabfiles.append(our_fab) fab.main(fabfiles)
def deploy(): """ Deploy local copy of repository to target environment. """ require('branch', provided_by=[ master, stable, branch, ]) with context_managers.lcd(os.path.dirname(find_fabfile( ))): # Allows you to run deploy from any child directory of the project ret = wp.deploy() if ret.return_code and ret.return_code > 0: if ret.return_code in [ 4, ]: print( colors.red("Try running ") + colors.white("fab wp.verify_prerequisites")) else: notify_hipchat()
def main(fabfile_locations=None, file_paths=None): # type: (list, list) -> None fabfile_local = find_fabfile() if fabfile_locations is None and fabfile_local is None: fabfile_locations = ['~/fabfile.py'] print_info('Added $HOME to fabfile locations') docstring, new_style, classic, default = load_tasks_from_module(api) tasks = new_style if state.env.new_style_tasks else classic state.commands.update(tasks) print_info('Forwarding execution to Fabric') _load_settings_original = fabric_main.load_settings def hemp_load_settings(path): print_info('Loading hempfiles') load_hempfiles(file_paths) return _load_settings_original(path) fabric_main.load_settings = hemp_load_settings fabric_main.main(fabfile_locations)
def set_env(settings=None, setup_dir=''): """ Used in management commands or at the module level of a fabfile to integrate woven project django.conf settings into fabric, and set the local current working directory to the distribution root (where setup.py lives). ``settings`` is your django settings module to pass in if you want to call this from a fabric script. ``setup_dir`` is an optional path to the directory containing setup.py This would be used in instances where setup.py was not above the cwd This function is used to set the environment for all hosts """ #switch the working directory to the distribution root where setup.py is if hasattr(env, 'setup_path') and env.setup_path: setup_path = env.setup_path else: with fab_settings(fabfile='setup.py'): if setup_dir: setup_path = os.path.join(setup_dir, 'setup.py') else: setup_path = find_fabfile() if not setup_path: print 'Error: You must have a setup.py file in the current or a parent folder' sys.exit(1) local_working_dir = os.path.split(setup_path)[0] os.chdir(local_working_dir) setup = run_setup('setup.py', stop_after="init") if setup.get_name() == 'UNKNOWN' or setup.get_version( ) == '0.0.0' or not setup.packages: print "ERROR: You must define a minimum of name, version and packages in your setup.py" sys.exit(1) #project env variables for deployment env.project_name = setup.get_name() #project_name() env.project_full_version = setup.get_version( ) #local('python setup.py --version').rstrip() env.project_version = _parse_project_version(env.project_full_version) env.project_fullname = '-'.join([env.project_name, env.project_version]) env.project_package_name = setup.packages[0] env.patch = False #django settings are passed in by the command #We'll assume that if the settings aren't passed in we're running from a fabfile if not settings: sys.path.insert(0, local_working_dir) #import global settings project_settings = import_module(env.project_name + '.settings') else: project_settings = settings #If sqlite is used we can manage the database on first deployment env.DEFAULT_DATABASE_ENGINE = project_settings.DATABASES['default'][ 'ENGINE'] env.DEFAULT_DATABASE_NAME = project_settings.DATABASES['default']['NAME'] #overwrite with main sitesettings module #just for MEDIA_URL, ADMIN_MEDIA_PREFIX, and STATIC_URL #if this settings file exists try: site_settings = import_module('.'.join( [env.project_name, 'sitesettings.settings'])) project_settings.MEDIA_URL = site_settings.MEDIA_URL project_settings.ADMIN_MEDIA_PREFIX = site_settings.ADMIN_MEDIA_PREFIX project_settings.DATABASES = site_settings.DATABASES if hasattr(site_settings, 'STATIC_URL'): project_settings.STATIC_URL = site_settings.STATIC_URL else: project_settings.STATIC_URL = project_settings.ADMIN_MEDIA_PREFIX except ImportError: pass #update woven_env from project_settings local_settings = dir(project_settings) #only get settings that woven uses for setting in local_settings: if setting.isupper() and hasattr(woven_env, setting): s = getattr(project_settings, setting, '') woven_env[setting] = s #upate the fabric env with all the woven settings env.update(woven_env) #set any user/password defaults if they are not supplied #Fabric would get the user from the options by default as the system user #We will overwrite that if woven_env.HOST_USER: env.user = woven_env.HOST_USER env.password = woven_env.HOST_PASSWORD #set the hosts if they aren't already if not env.hosts: env.hosts = woven_env.HOSTS if not env.roledefs: env.roledefs = woven_env.ROLEDEFS #reverse_lookup hosts to roles role_lookup = {} for role in env.roles: r_hosts = env.roledefs[role] for host in r_hosts: #since port is not handled by fabric.main.normalize we'll do it ourselves role_lookup['%s:%s' % (host, str(woven_env.HOST_SSH_PORT))] = role #now add any hosts that aren't already defined in roles for host in env.hosts: host_string = '%s:%s' % (host, str(woven_env.HOST_SSH_PORT)) if host_string not in role_lookup.keys(): role_lookup[host_string] = '' env.role_lookup = role_lookup env.hosts = role_lookup.keys() #remove any unneeded db adaptors - except sqlite remove_backends = ['postgresql_psycopg2', 'mysql'] for db in project_settings.DATABASES: engine = project_settings.DATABASES[db]['ENGINE'].split('.')[-1] if engine in remove_backends: remove_backends.remove(engine) for backend in remove_backends: if backend == 'postgresql_psycopg2': rm = 'python-psycopg2' elif backend == 'mysql': rm = 'python-mysqldb' env.HOST_BASE_PACKAGES.remove(rm) #packages can be just the base + extra packages #or role dependent we need to just map out the packages to hosts and roles here packages = {} all_packages = set([]) for role in env.roles: packages[role] = env.ROLE_PACKAGES.get(role, []) if not packages[role]: packages[role] = env.HOST_BASE_PACKAGES + env.HOST_EXTRA_PACKAGES all_packages = set(packages[role]) | all_packages #no role packages[''] = env.HOST_BASE_PACKAGES + env.HOST_EXTRA_PACKAGES all_packages = set(packages['']) | all_packages #conveniently add gunicorn ppa if 'gunicorn' in all_packages: if 'ppa:bchesneau/gunicorn' not in env.LINUX_PACKAGE_REPOSITORIES: env.LINUX_PACKAGE_REPOSITORIES.append('ppa:bchesneau/gunicorn') env.packages = packages #sanity check for unwanted combinations in the empty role u = set(packages['']) wsgi = u & set(['gunicorn', 'uwsgi']) if wsgi and 'apache2' in u: u = u - set(['apache2', 'libapache2-mod-wsgi']) #Used to detect certain apps eg South, static_builder env.INSTALLED_APPS = project_settings.INSTALLED_APPS env.packages[''] = list(u) #per host env.installed_packages = {} env.uninstalled_packages = {} #UFW firewall rules firewall_rules = {} for role in env.roles: firewall_rules[role] = env.ROLE_UFW_RULES.get(role, []) firewall_rules[''] = env.UFW_RULES env.firewall_rules = firewall_rules #Now update the env with any settings that are not defined by woven but may #be used by woven or fabric env.MEDIA_ROOT = project_settings.MEDIA_ROOT env.MEDIA_URL = project_settings.MEDIA_URL env.ADMIN_MEDIA_PREFIX = project_settings.ADMIN_MEDIA_PREFIX if not env.STATIC_URL: env.STATIC_URL = project_settings.ADMIN_MEDIA_PREFIX env.TEMPLATE_DIRS = project_settings.TEMPLATE_DIRS #Set the server /etc/timezone env.TIME_ZONE = project_settings.TIME_ZONE #Used to detect certain apps eg South, static_builder env.INSTALLED_APPS = project_settings.INSTALLED_APPS #SSH key if env.SSH_KEY_FILENAME: env.KEY_FILENAME = env.SSH_KEY_FILENAME else: env.KEY_FILENAME = '' #noinput if not hasattr(env, 'INTERACTIVE'): env.INTERACTIVE = True if not hasattr(env, 'verbosity'): env.verbosity = 1 #overwrite existing settings if not hasattr(env, 'overwrite'): env.overwrite = False #South integration defaults env.nomigration = False env.manualmigration = False env.migration = '' env.root_disabled = False #Sites env.sites = {} env.shell = '/bin/bash --noprofile -l -c'
def test_find_fabfile_should_refuse_fake_package(self): """Fabric should refuse to load a non-package directory.""" path = self.mkfile("foo.py", "") name = os.path.dirname(path) assert find_fabfile([name,]) is None
def import_fabfile(fabfile='fabfile.py'): "you have to call this first to enable fabric tasks" state.env.fabfile = fabfile _, fabfile = load_fabfile(find_fabfile()) return fabfile
def test_find_fabfile_can_discovery_package(self): """Fabric should be capable of loading a normal package.""" path = self.mkfile("__init__.py", "") name = os.path.dirname(path) assert find_fabfile([name,]) is not None
def set_env(settings=None, setup_dir=''): """ Used in management commands or at the module level of a fabfile to integrate woven project django.conf settings into fabric, and set the local current working directory to the distribution root (where setup.py lives). ``settings`` is your django settings module to pass in if you want to call this from a fabric script. ``setup_dir`` is an optional path to the directory containing setup.py This would be used in instances where setup.py was not above the CWD. This function is used to set the environment for all hosts. """ # Switch the working directory to the distribution root where # setup.py is. if hasattr(env, 'setup_path') and env.setup_path: setup_path = env.setup_path else: with fab_settings(fabfile='setup.py'): if setup_dir: setup_path = os.path.join(setup_dir, 'setup.py') else: setup_path = find_fabfile() if not setup_path: print 'Error: You must have a setup.py file in ' \ 'the current or a parent folder' sys.exit(1) local_working_dir = os.path.split(setup_path)[0] os.chdir(local_working_dir) setup = run_setup('setup.py', stop_after="init") if (setup.get_name() == 'UNKNOWN' or setup.get_version() == '0.0.0' or not setup.packages): print "ERROR: You must define a minimum of name, version " \ "and packages in your setup.py" sys.exit(1) # Project env variables for deployment. # Project_name(). env.project_name = setup.get_name() #local('python setup.py --version').rstrip() env.project_full_version = setup.get_version() env.project_version = _parse_project_version(env.project_full_version) env.project_fullname = '-'.join([env.project_name, env.project_version]) env.project_package_name = setup.packages[0] env.patch = False # Django settings are passed in by the command. We'll assume that # if the settings aren't passed in we're running from a fabfile. if not settings: sys.path.insert(0, local_working_dir) # Import global settings. project_settings = import_module(env.project_name + '.settings') else: project_settings = settings # If SQLite is used we can manage the database on first # deployment. env.DEFAULT_DATABASE_ENGINE = \ project_settings.DATABASES['default']['ENGINE'] env.DEFAULT_DATABASE_NAME = \ project_settings.DATABASES['default']['NAME'] # Overwrite with main sitesettings module just for MEDIA_URL, # ADMIN_MEDIA_PREFIX, and STATIC_URL if this settings file exists. try: site_settings = import_module( '.'.join([env.project_name, 'sitesettings.settings'])) project_settings.MEDIA_URL = site_settings.MEDIA_URL project_settings.ADMIN_MEDIA_PREFIX = site_settings.ADMIN_MEDIA_PREFIX project_settings.DATABASES = site_settings.DATABASES if hasattr(site_settings, 'STATIC_URL'): project_settings.STATIC_URL = site_settings.STATIC_URL else: project_settings.STATIC_URL = project_settings.ADMIN_MEDIA_PREFIX except ImportError: pass # Update woven_env from project_settings. local_settings = dir(project_settings) # Only get settings that woven uses. for setting in local_settings: if setting.isupper() and hasattr(woven_env, setting): s = getattr(project_settings, setting, '') woven_env[setting] = s # Upate the fabric env with all the woven settings. env.update(woven_env) # Set any user/password defaults if they are not supplied. # Fabric would get the user from the options by default as the # system user. We will overwrite that. if woven_env.HOST_USER: env.user = woven_env.HOST_USER env.password = woven_env.HOST_PASSWORD # Set the hosts if they aren't already. if not env.hosts: env.hosts = woven_env.HOSTS if not env.roledefs: env.roledefs = woven_env.ROLEDEFS # Reverse_lookup hosts to roles. role_lookup = {} for role in env.roles: r_hosts = env.roledefs[role] for host in r_hosts: # Since port is not handled by fabric.main.normalize we'll # do it ourselves. role_lookup['%s:%s' % (host, str(woven_env.HOST_SSH_PORT))] = role # Now add any hosts that aren't already defined in roles. for host in env.hosts: host_string = '%s:%s' % (host, str(woven_env.HOST_SSH_PORT)) if host_string not in role_lookup.keys(): role_lookup[host_string] = '' env.role_lookup = role_lookup env.hosts = role_lookup.keys() # Remove any unneeded db adaptors - except sqlite. remove_backends = ['postgresql_psycopg2', 'mysql'] for db in project_settings.DATABASES: engine = project_settings.DATABASES[db]['ENGINE'].split('.')[-1] if engine in remove_backends: remove_backends.remove(engine) for backend in remove_backends: if backend == 'postgresql_psycopg2': rm = 'python-psycopg2' elif backend == 'mysql': rm = 'python-mysqldb' env.HOST_BASE_PACKAGES.remove(rm) # Packages can be just the base + extra packages or role- # dependent. We need to just map out the packages to hosts and # roles here. packages = {} all_packages = set([]) for role in env.roles: packages[role] = env.ROLE_PACKAGES.get(role, []) if not packages[role]: packages[role] = env.HOST_BASE_PACKAGES + env.HOST_EXTRA_PACKAGES all_packages = set(packages[role]) | all_packages # No role. packages[''] = env.HOST_BASE_PACKAGES + env.HOST_EXTRA_PACKAGES all_packages = set(packages['']) | all_packages # Conveniently add gunicorn ppa. if 'gunicorn' in all_packages: if 'ppa:bchesneau/gunicorn' not in env.LINUX_PACKAGE_REPOSITORIES: env.LINUX_PACKAGE_REPOSITORIES.append('ppa:bchesneau/gunicorn') env.packages = packages # Sanity-check for unwanted combinations in the empty role. u = set(packages['']) wsgi = u & set(['gunicorn', 'uwsgi']) if wsgi and 'apache2' in u: u = u - set(['apache2', 'libapache2-mod-wsgi']) # Used to detect certain apps eg. South, static_builder. env.INSTALLED_APPS = project_settings.INSTALLED_APPS env.packages[''] = list(u) # Per host. env.installed_packages = {} env.uninstalled_packages = {} # UFW firewall rules. firewall_rules = {} for role in env.roles: firewall_rules[role] = env.ROLE_UFW_RULES.get(role, []) firewall_rules[''] = env.UFW_RULES env.firewall_rules = firewall_rules # Now update the env with any settings that are not defined by # woven but may be used by woven or fabric. env.MEDIA_ROOT = project_settings.MEDIA_ROOT env.MEDIA_URL = project_settings.MEDIA_URL try: env.ADMIN_MEDIA_PREFIX = project_settings.ADMIN_MEDIA_PREFIX except AttributeError: env.ADMIN_MEDIA_PREFIX = '' if not env.STATIC_URL: env.STATIC_URL = project_settings.ADMIN_MEDIA_PREFIX env.TEMPLATE_DIRS = project_settings.TEMPLATE_DIRS # Set the server /etc/timezone. env.TIME_ZONE = project_settings.TIME_ZONE # Used to detect certain apps eg. South, static_builder. env.INSTALLED_APPS = project_settings.INSTALLED_APPS # SSH key. if (not hasattr(env, 'key_filename') and not env.key_filename and env.SSH_KEY_FILENAME): env.key_filename = env.SSH_KEY_FILENAME elif not hasattr(env, 'key_filename'): env.key_filename = None # Noinput. if not hasattr(env, 'INTERACTIVE'): env.INTERACTIVE = True if not hasattr(env, 'verbosity'): env.verbosity = 1 # Overwrite existing settings. if not hasattr(env, 'overwrite'): env.overwrite = False # South integration defaults. env.nomigration = False env.manualmigration = False env.migration = '' env.root_disabled = False # Sites. env.sites = {} env.shell = '/bin/bash --noprofile -l -c'
def run(): try: # Parse command line options parser, options, arguments = parse_options() # Handle regular args vs -- args arguments = parser.largs if len(arguments) > 1: abort("You can call only one command!") if arguments: tmp_parts = arguments[0].split(':') parts = tmp_parts[0].split('.') if not command_exists(parts): print print 'Warning: command not found!' print return fabfile_locations = ['%s.py' % os.path.join(satellite.commands.__path__[0], *parts[:-1])] arguments[0] = parts[-1] + ''.join(":%s" % i for i in tmp_parts[1:]) else: print "Command tree:" print_tree_commands() return # Update env with any overridden option values # NOTE: This needs to remain the first thing that occurs # post-parsing, since so many things hinge on the values in env. for option in env_options: state.env[option.dest] = option.default # Handle --hosts, --roles, --exclude-hosts (comma separated string => # list) for key in ['hosts', 'roles', 'exclude_hosts']: if key in state.env and isinstance(state.env[key], basestring): state.env[key] = state.env[key].split(',') # Load settings from user settings file, into shared env dict. settings.update(load_settings(options.configfile)) state.env.update(settings.fabric) # Find local fabfile path or abort fabfile = find_fabfile(fabfile_locations) if not fabfile: abort("""Couldn't find any fabfiles! Use -h for help.""") # Store absolute path to fabfile in case anyone needs it state.env.real_fabfile = fabfile # Load fabfile (which calls its module-level code, including # tweaks to env values) and put its commands in the shared commands # dict default = None if fabfile: docstring, callables, default = load_fabfile(fabfile) state.commands.update(callables) # Abort if no commands found if not state.commands: abort("Fabfile didn't contain any commands!") # Now that we're settled on a fabfile, inform user. if state.output.debug: if fabfile: print("Using fabfile '%s'" % fabfile) else: print("No fabfile loaded -- remainder command only") # Parse arguments into commands to run (plus args/kwargs/hosts) commands_to_run = parse_arguments(arguments) if state.output.debug: names = ", ".join(x[0] for x in commands_to_run) print("Commands to run: %s" % names) # At this point all commands must exist, so execute them in order. for name, args, kwargs, arg_hosts, arg_roles, arg_exclude_hosts in commands_to_run: execute( name, hosts=arg_hosts, roles=arg_roles, exclude_hosts=arg_exclude_hosts, *args, **kwargs ) # If we got here, no errors occurred, so print a final note. if state.output.status: print("\nDone.") except SystemExit: # a number of internal functions might raise this one. raise except KeyboardInterrupt: if state.output.status: sys.stderr.write("\nStopped.\n") sys.exit(1) except: sys.excepthook(*sys.exc_info()) # we might leave stale threads if we don't explicitly exit() sys.exit(1) finally: disconnect_all() sys.exit(0)
project_name = args[1] try: email = args[2] except IndexError: email = '' start_distribution(project_name,options.src_dir, dist, noadmin = options.noadmin) #get the name of the settings from setup.py if DJANGO_SETTINGS_MODULE is not set if not os.environ.get('DJANGO_SETTINGS_MODULE') and not settings_mod: if startproject: os.chdir(os.path.join(orig_cwd,dist)) elif not 'setup.py' in os.listdir(os.getcwd()): #switch the working directory to the distribution root where setup.py is with settings(fabfile='setup.py'): env.setup_path = find_fabfile() if not env.setup_path: print 'Error: You must have a setup.py file in the current or a parent folder' sys.exit(1) local_working_dir = os.path.split(env.setup_path)[0] os.chdir(local_working_dir) woven_admin = sys.argv[0] setup = run_setup('setup.py',stop_after="init") settings_mod = '.'.join([setup.packages[0],'settings']) os.environ['DJANGO_SETTINGS_MODULE'] = settings_mod sys.argv.remove('setup.py') sys.argv.insert(0, woven_admin) #be path friendly like manage.py sys.path.append(os.getcwd())
from os.path import abspath, join from fabric.main import find_fabfile ROOT = abspath(join(find_fabfile(), '..')) import test
def set_env(settings=None, setup_dir=""): """ Used in management commands or at the module level of a fabfile to integrate woven project django.conf settings into fabric, and set the local current working directory to the distribution root (where setup.py lives). ``settings`` is your django settings module to pass in if you want to call this from a fabric script. ``setup_dir`` is an optional path to the directory containing setup.py This would be used in instances where setup.py was not above the cwd This function is used to set the environment for all hosts """ # switch the working directory to the distribution root where setup.py is original_fabfile = env.fabfile env.fabfile = "setup.py" if setup_dir: fabfile_path = os.path.join(setup_dir, "setup.py") else: fabfile_path = find_fabfile() if not fabfile_path: print "Error: You must create a setup.py file in your distribution" sys.exit(1) local_working_dir = os.path.split(fabfile_path)[0] env.fabfile = original_fabfile os.chdir(local_working_dir) setup = run_setup("setup.py", stop_after="init") if setup.get_name() == "UNKNOWN" or setup.get_version() == "0.0.0" or not setup.packages: print "ERROR: You must define a minimum of name, version and packages in your setup.py" sys.exit(1) # project env variables for deployment env.project_name = setup.get_name() # project_name() env.project_full_version = setup.get_version() # local('python setup.py --version').rstrip() env.project_version = _parse_project_version(env.project_full_version) env.project_fullname = "-".join([env.project_name, env.project_version]) env.project_package_name = setup.packages[0] env.patch = False # django settings are passed in by the command # We'll assume that if the settings aren't passed in we're running from a fabfile if not settings: sys.path.insert(0, local_working_dir) # import global settings project_settings = import_module(env.project_name + ".settings") else: project_settings = settings # If sqlite is used we can manage the database on first deployment env.DEFAULT_DATABASE_ENGINE = project_settings.DATABASES["default"]["ENGINE"] env.DEFAULT_DATABASE_NAME = project_settings.DATABASES["default"]["NAME"] # overwrite with main sitesettings module # just for MEDIA_URL, ADMIN_MEDIA_PREFIX, and STATIC_URL # if this settings file exists try: site_settings = import_module(".".join([env.project_name, "sitesettings.settings"])) project_settings.MEDIA_URL = site_settings.MEDIA_URL project_settings.ADMIN_MEDIA_PREFIX = site_settings.ADMIN_MEDIA_PREFIX project_settings.DATABASES = site_settings.DATABASES if hasattr(site_settings, "STATIC_URL"): project_settings.STATIC_URL = site_settings.STATIC_URL else: project_settings.STATIC_URL = project_settings.ADMIN_MEDIA_PREFIX except ImportError: pass # update woven_env from project_settings local_settings = dir(project_settings) # only get settings that woven uses for setting in local_settings: if setting.isupper() and hasattr(woven_env, setting): s = getattr(project_settings, setting, "") woven_env[setting] = s # upate the fabric env with all the woven settings env.update(woven_env) # set any user/password defaults if they are not supplied # Fabric would get the user from the options by default as the system user # We will overwrite that if woven_env.HOST_USER: env.user = woven_env.HOST_USER env.password = woven_env.HOST_PASSWORD # set the hosts if they aren't already if not env.hosts: env.hosts = woven_env.HOSTS if not env.roledefs: env.roledefs = woven_env.ROLEDEFS # reverse_lookup hosts to roles role_lookup = {} for role in env.roles: r_hosts = env.roledefs[role] for host in r_hosts: # since port is not handled by fabric.main.normalize we'll do it ourselves role_lookup["%s:%s" % (host, str(woven_env.HOST_SSH_PORT))] = role # now add any hosts that aren't already defined in roles for host in env.hosts: host_string = "%s:%s" % (host, str(woven_env.HOST_SSH_PORT)) if host_string not in role_lookup.keys(): role_lookup[host_string] = "" env.role_lookup = role_lookup env.hosts = role_lookup.keys() # remove any unneeded db adaptors - except sqlite remove_backends = ["postgresql_psycopg2", "mysql"] for db in project_settings.DATABASES: engine = project_settings.DATABASES[db]["ENGINE"].split(".")[-1] if engine in remove_backends: remove_backends.remove(engine) for backend in remove_backends: if backend == "postgresql_psycopg2": rm = "python-psycopg2" elif backend == "mysql": rm = "python-mysqldb" env.HOST_BASE_PACKAGES.remove(rm) # packages can be just the base + extra packages # or role dependent we need to just map out the packages to hosts and roles here packages = {} all_packages = set([]) for role in env.roles: packages[role] = env.ROLE_PACKAGES.get(role, []) if not packages[role]: packages[role] = env.HOST_BASE_PACKAGES + env.HOST_EXTRA_PACKAGES all_packages = set(packages[role]) | all_packages # no role packages[""] = env.HOST_BASE_PACKAGES + env.HOST_EXTRA_PACKAGES all_packages = set(packages[""]) | all_packages # conveniently add gunicorn ppa if "gunicorn" in all_packages: if "ppa:bchesneau/gunicorn" not in env.LINUX_PACKAGE_REPOSITORIES: env.LINUX_PACKAGE_REPOSITORIES.append("ppa:bchesneau/gunicorn") env.packages = packages # sanity check for unwanted combinations in the empty role u = set(packages[""]) wsgi = u & set(["gunicorn", "uwsgi"]) if wsgi and "apache2" in u: u = u - set(["apache2", "libapache2-mod-wsgi"]) env.packages[""] = list(u) # per host env.installed_packages = {} env.uninstalled_packages = {} # UFW firewall rules firewall_rules = {} for role in env.roles: firewall_rules[role] = env.ROLE_UFW_RULES.get(role, []) firewall_rules[""] = env.UFW_RULES env.firewall_rules = firewall_rules # Now update the env with any settings that are not defined by woven but may # be used by woven or fabric env.MEDIA_ROOT = project_settings.MEDIA_ROOT env.MEDIA_URL = project_settings.MEDIA_URL env.ADMIN_MEDIA_PREFIX = project_settings.ADMIN_MEDIA_PREFIX if not env.STATIC_URL: env.STATIC_URL = project_settings.ADMIN_MEDIA_PREFIX env.TEMPLATE_DIRS = project_settings.TEMPLATE_DIRS # Set the server /etc/timezone env.TIME_ZONE = project_settings.TIME_ZONE # Used to detect certain apps eg South, static_builder env.INSTALLED_APPS = project_settings.INSTALLED_APPS # SSH key if env.SSH_KEY_FILENAME: env.KEY_FILENAME = env.SSH_KEY_FILENAME else: env.KEY_FILENAME = "" # noinput if not hasattr(env, "INTERACTIVE"): env.INTERACTIVE = True if not hasattr(env, "verbosity"): env.verbosity = 1 # overwrite existing settings if not hasattr(env, "overwrite"): env.overwrite = False # South integration defaults env.nomigration = False env.manualmigration = False env.migration = "" env.root_disabled = False # Sites env.sites = {} env.shell = "/bin/bash --noprofile -l -c"
def set_env(settings=None, setup_dir=""): """ Used in management commands or at the module level of a fabfile to integrate woven project django.conf settings into fabric, and set the local current working directory to the distribution root (where setup.py lives). ``settings`` is your optional django.conf imported settings. ``setup_dir`` is an optional path to the directory containing setup.py This would be used in instances where setup.py was not above the cwd This function is used to set the environment for all hosts """ # switch the working directory to the distribution root where setup.py is original_fabfile = env.fabfile env.fabfile = "setup.py" if setup_dir: fabfile_path = os.path.join(setup_dir, "setup.py") else: fabfile_path = find_fabfile() if not fabfile_path: print "Error: You must have a setup.py file above your project directory" sys.exit(1) local_working_dir = os.path.split(fabfile_path)[0] env.fabfile = original_fabfile os.chdir(local_working_dir) # project env variables for deployment env.project_name = project_name() env.project_full_version = local("python setup.py --version").rstrip() env.project_version = _parse_project_version(env.project_full_version) env.project_fullname = "-".join([env.project_name, env.project_version]) env.patch = False # We'll assume that if the settings aren't passed in we're running from a fabfile if not settings: sys.path.insert(0, local_working_dir) # import global settings project_settings = import_module(env.project_name + ".settings") else: project_settings = settings # overwrite with main sitesettings module # just for MEDIA_URL, ADMIN_MEDIA_PREFIX, and STATIC_URL # if this settings file exists try: site_settings = import_module(".".join([env.project_name, "sitesettings.settings"])) project_settings.MEDIA_URL = site_settings.MEDIA_URL project_settings.ADMIN_MEDIA_PREFIX = site_settings.ADMIN_MEDIA_PREFIX if hasattr(site_settings, "STATIC_URL"): project_settings.STATIC_URL = site_settings.STATIC_URL except ImportError: pass # update woven_env from project_settings local_settings = dir(project_settings) # only get settings that woven uses for setting in local_settings: if setting.isupper() and hasattr(woven_env, setting): s = getattr(project_settings, setting, "") woven_env[setting] = s # upate the fabric env with all the woven settings env.update(woven_env) # set any user/password defaults if they are not supplied # Fabric would get the user from the options by default as the system user # We will overwrite that if woven_env.HOST_USER: env.user = woven_env.HOST_USER env.password = woven_env.HOST_PASSWORD # set the hosts if not env.hosts: env.hosts = woven_env.HOSTS if not env.roledefs: env.roledefs = woven_env.ROLEDEFS # since port is not handled by fabric.main.normalize we'll do it ourselves host_list = [] if "hosts" in env and isinstance(env["hosts"], list): for host_string in env.hosts: if not ":" in host_string: host_string += ":%s" % str(woven_env.HOST_SSH_PORT) # not sure that this is necessary but it seems clearer to make full # hoststrings with the correct user if not "@" in host_string: host_string = env.user + "@" + host_string host_list.append(host_string) env.hosts = host_list # Now update the env with any settings that are not defined by woven but may # be used by woven or fabric env.MEDIA_ROOT = project_settings.MEDIA_ROOT env.MEDIA_URL = project_settings.MEDIA_URL env.ADMIN_MEDIA_PREFIX = project_settings.ADMIN_MEDIA_PREFIX env.TEMPLATE_DIRS = project_settings.TEMPLATE_DIRS # If sqlite is used we can manage the database on deployment env.DEFAULT_DATABASE_ENGINE = project_settings.DATABASES["default"]["ENGINE"] env.DEFAULT_DATABASE_NAME = project_settings.DATABASES["default"]["NAME"] # Set the server /etc/timezone env.TIME_ZONE = project_settings.TIME_ZONE # Used to detect certain apps eg South, static_builder env.INSTALLED_APPS = project_settings.INSTALLED_APPS # noinput if not hasattr(env, "INTERACTIVE"): env.INTERACTIVE = True # South integration defaults env.nomigration = False env.manualmigration = False env.migration = "" # Sites env.sites = {} env.shell = "/bin/bash --noprofile -l -c"