def setup_ufw(rollback=False): """ Setup ufw and apply rules from settings UFW_RULES You can add rules and re-run setup_ufw but cannot delete rules or reset by script since deleting or reseting requires user interaction See Ubuntu Server documentation for more about UFW. """ if not rollback: #TODO - Optimize to store & compare existing rules to stop unecessary reloads #Should be able to do something with the ufw status command to store the rules #ufw_rules = sudo("ufw status | awk '/tcp|udp/ {print $1,$2,$3}'").split('\n') ufw = run("dpkg -l | grep '%s' | awk '{print $2}'").strip() #It would be nice to handle an existing installation but until ufw can easily #predefine rules in a conf we'll need to just mark it if woven installs it if not ufw: if env.verbosity: print env.host, "INSTALLING & ENABLING FIREWALL ufw" apt_get_install('ufw') set_server_state('ufw_installed') sudo('ufw allow %s/tcp'% env.port) #ssh port for rule in env.UFW_RULES: if rule: if env.verbosity: print ' *',rule sudo('ufw '+rule) backup_file('/etc/ufw/ufw.conf') sed('/etc/ufw/ufw.conf','ENABLED=no','ENABLED=yes',use_sudo=True) sudo('ufw reload') else: #if it was installed by woven remove it else leave it the hell alone if server_state('ufw_installed'): sudo('ufw disable') apt_get_purge('ufw') set_server_state('ufw_installed',delete=True)
def deploy(self, patch=False): if not exists(self.deploy_root): run("mkdir -p %s" % self.deploy_root) with cd(self.deploy_root): u_domain = self.domain.replace('.','_') filename = "%s.wsgi"% u_domain context = {"user": env.user, "project_name": env.project_name, "u_domain":u_domain, "root_domain":env.root_domain, } wsgi_exists = exists(filename) if wsgi_exists and not patch: print env.host,"%s already exists on the host %s. Skipping..."% (self.deploy_type,filename) return False elif not wsgi_exists and patch: print env.host,"Error: Cannot patch %s %s. This version does not exist"% (project_fullname(), self.deploy_type) return False current_version = active_version() if current_version == env.project_fullname and not patch: print env.host,"Warning: Cannot deploy %s, version %s already active. Increase the version and re-deploy. Skipping.."% (self.deploy_type,env.project_fullname) return False else: #not exists upload_template('woven/'+self.template, filename, context, ) #finally set the ownership/permissions #We'll use the group to allow www-data execute if self.deploy_type == 'wsgi': sudo("chown %s:www-data %s"% (env.user,filename)) run("chmod ug+xr %s"% filename) set_server_state(self.state+env.project_fullname)
def restrict_ssh(rollback=False): """ Set some sensible restrictions in Ubuntu /etc/ssh/sshd_config and restart sshd UseDNS no #prevents dns spoofing sshd defaults to yes X11Forwarding no # defaults to no AuthorizedKeysFile %h/.ssh/authorized_keys uncomments PasswordAuthentication no and restarts sshd """ if not rollback: if server_state('ssh_restricted'): print env.host, 'Warning: sshd_config has already been modified. Skipping..' return False sshd_config = '/etc/ssh/sshd_config' if env.verbosity: print env.host, "RESTRICTING SSH with "+sshd_config filename = 'sshd_config' if not exists('/home/%s/.ssh/authorized_keys'% env.user): #do not pass go do not collect $200 print env.host, 'You need to upload_ssh_key first.' return False backup_file(sshd_config) context = {"HOST_SSH_PORT": env.HOST_SSH_PORT} upload_template('woven/ssh/sshd_config','/etc/ssh/sshd_config',context=context,use_sudo=True) # Restart sshd sudo('/etc/init.d/ssh restart') # The user can modify the sshd_config file directly but we save if env.INTERACTIVE and contains('#PasswordAuthentication no','/etc/ssh/sshd_config',use_sudo=True): c_text = 'Woven will now remove password login from ssh, and use only your ssh key. \n' c_text = c_text + 'CAUTION: please confirm that you can ssh %s@%s -p%s from a terminal without requiring a password before continuing.\n'% (env.user, env.host, env.port) c_text += 'If you cannot login, press enter to rollback your sshd_config file' proceed = confirm(c_text,default=False) if not env.INTERACTIVE or proceed: #uncomments PasswordAuthentication no and restarts uncomment(sshd_config,'#(\s?)PasswordAuthentication(\s*)no',use_sudo=True) sudo('/etc/init.d/ssh restart') else: #rollback print env.host, 'Rolling back sshd_config to default and proceeding without passwordless login' restore_file('/etc/ssh/sshd_config', delete_backup=False) sed('/etc/ssh/sshd_config','Port '+ str(env.DEFAULT_SSH_PORT),'Port '+str(env.HOST_SSH_PORT),use_sudo=True) sudo('/etc/init.d/ssh restart') return False set_server_state('ssh_restricted') return True else: #Full rollback restore_file('/etc/ssh/sshd_config') if server_state('ssh_port_changed'): sed('/etc/ssh/sshd_config','Port '+ str(env.DEFAULT_SSH_PORT),'Port '+str(env.HOST_SSH_PORT),use_sudo=True) sudo('/etc/init.d/ssh restart') sudo('/etc/init.d/ssh restart') set_server_state('ssh_restricted', delete=True) return True
def delete(self): #walk backwards up the tree if active_version <> self.fullname: run('rm -rf '+self.deploy_root) #if nothing left in the specific env ls = run('ls '+ self.path).rstrip().split('\n') if not ls[0]: run('rm -rf '+ self.path) #if no envs left ls = run('ls '+ self.root).rstrip().split('\n') if not ls[0]: run('rm -rf '+ env.deployment_root) set_server_state(self.state+self.fullname,delete=True)
def test_activate(): sudo('rm -rf /home/woven/example.com') set_server_state('deployed_project_example_project-0.1',delete=True) set_server_state('created_virtualenv_example_project-0.1', delete=True) sudo('rm -rf /home/woven/workon-example_project') mkvirtualenv() deploy_project() activate()
def change_ssh_port(rollback=False): """ This would be the first function to be run to setup a server. By changing the ssh port first we can test it to see if it has been changed, and thus can reasonably assume that root has also been disabled in a previous setupserver execution Returns success or failure """ if not rollback: after = env.port before = str(env.DEFAULT_SSH_PORT) else: after = str(env.DEFAULT_SSH_PORT) before = env.port host = normalize(env.host_string)[1] host_string=join_host_strings('root',host,before) with settings(host_string=host_string, user='******', password=env.ROOT_PASSWORD): if env.verbosity: print env.host, "CHANGING SSH PORT TO: "+str(after) if not rollback: try: #Both test the port and also the ubuntu version. distribution, version = ubuntu_version() # print env.host, distribution, version if version < 9.10: print env.host, 'Woven is only compatible with Ubuntu versions 9.10 and greater' sys.exit(1) except KeyboardInterrupt: if env.verbosity: print >> sys.stderr, "\nStopped." sys.exit(1) except: #No way to catch the failing connection without catchall? print env.host, "Warning: Default port not responding. Setupnode may alredy have been run or the host is down. Skipping.." return False sed('/etc/ssh/sshd_config','Port '+ str(before),'Port '+str(after),use_sudo=True) if env.verbosity: print env.host, "RESTARTING SSH on",after sudo('/etc/init.d/ssh restart') set_server_state('ssh_port_changed',content=str(before)) return True else: port = server_state('ssh_port_changed') if port: sed('/etc/ssh/sshd_config','Port '+ str(before),'Port '+str(after),use_sudo=True) set_server_state('ssh_port_changed',delete=True) sudo('/etc/init.d/ssh restart') return True return False
def deploy(self,patch=False): with cd(self.deploy_root): log_dir = env.deployment_root+'log' if not exists(log_dir): run("mkdir -p %s"% log_dir) sudo("chown -R www-data:sudo %s" % log_dir) sudo("chmod -R ug+w %s"% log_dir) u_domain = self.domain.replace('.','_') filename = u_domain + '-'+self.version+'.conf' context = {"project_name": env.project_name, "u_domain":u_domain, "domain":self.domain, "root_domain":env.root_domain, "user":env.user, "host_ip":env.host, "media_url":self.media_url, "static_url":self.static_url, } conf_exists = exists(os.path.join(self.enabled_path,filename), use_sudo=True) state = server_state(self.state+env.project_fullname) if not conf_exists and patch: if env.verbosity: print env.host,"Cannot patch %s conf %s. This version does not exist on %s. Skipping"% (self.deploy_type, filename, env.host) return False elif state and not patch: #active version print "%s conf %s already exists on the host %s. Skipping"% (self.deploy_type, filename, env.host) return False else: enabled_sites = _ls_sites(self.enabled_path) if not patch: for site in enabled_sites: if env.verbosity: print env.host,'Disabling', site, filename sudo("rm %s%s"% (self.enabled_path,site)) upload_template('woven/'+self.template, filename, context, use_sudo=True) if not patch: #enable this site sudo("chmod 644 %s" % filename) if not exists(self.enabled_path+ filename): sudo("ln -s %s%s %s%s"% (self.deploy_root,filename,self.enabled_path,filename)) set_server_state(self.state + self.fullname) if env.verbosity: print env.host,'DEPLOYED',self.deploy_type
def test_deploy_static(): change_version('0.2','0.1') run('rm -rf /home/woven/example.com') set_server_state('deployed_static_example_project-0.1',delete=True) #Test simple with no app media deploy_static() #Test with just admin_media env.INSTALLED_APPS += ['django.contrib.admin'] deploy_static() assert exists('/home/woven/example.com/env/example_project-0.1/static/static/admin-media/css') #Teardown s = Static() s.delete() assert not server_state('deployed_static_example_project-0.1')
def test_webservices(): #Test start and stop webservices sudo('rm -rf /home/woven/example.com') sudo('rm -f /etc/nginx/sites-enabled/*') sudo('rm -f /etc/nginx/sites-available/*') sudo('rm -f /etc/apache2/sites-enabled/*') sudo('rm -f /etc/apache2/sites-available/*') set_server_state('deployed_apache_webserver_example_project-0.1',delete=True) set_server_state('deployed_nginx_webserver_example_project-0.1',delete=True) stop_webservices() deploy_webservers() start_webservices() stop_webservices() stop_webservices() start_webservices() start_webservices() stop_webservices()
def deploy_webservers(version='',patch=False): """ Deploy apache & nginx site configurations to the host """ if not env.DOMAINS: env.DOMAINS = [root_domain()] #TODO - incorrect - check for actual package if exists('/etc/apache2/sites-enabled/') and exists('/etc/nginx/sites-enabled'): for d in env.DOMAINS: a = ApacheWebserver(d,version) a.deploy(patch) n = NginxWebserver(d,version) n.deploy(patch) set_server_state('deployed_webservers_' + project_fullname()) return True else: print env.host,"""WARNING: Apache or Nginx not installed""" return False return False
def test_deploy_templates(): #teardown run('rm -rf /home/woven/example.com') set_server_state('deployed_templates_example_project-0.1',delete=True) #simple deploy with no templates defined deploy_templates() template_dir = os.path.join(os.getcwd(),'templates','example.com') template_dir1 = os.path.join(os.getcwd(),'templates') #Add in some templates env.TEMPLATE_DIRS = ( template_dir, template_dir1, ) deploy_templates() assert exists('/home/woven/example.com/env/example_project-0.1/templates/index.html') run('rm -rf /home/woven/example.com')
def test_deploy_public(): run('rm -rf /home/woven/example.com') run('rm -f dist/django-pony1.jpg') set_server_state('deployed_public_example_project-0.1',delete=True) env.MEDIA_ROOT ='' #Test simple with no media_root - fails deploy_public() #Test with a real media directory env.MEDIA_ROOT = os.path.join(setup_dir,'media_root','') print env.MEDIA_ROOT env.MEDIA_URL = '/media/' deploy_public() assert exists('/home/woven/example.com/public/media/django-pony.jpg') #Test with no files - skips deploy_public() #Teardown p = Public() p.delete() assert not server_state('deployed_public_example_project-0.1')
def test_server_state(): set_server_state('example',delete=True) set_server_state('example') print 'Server State:%s:'% str(server_state('example')) assert server_state('example') == True set_server_state('example',content='something') assert server_state('example') == 'something' assert server_state('example')
def test_pip_install_requirements(): #output.debug = True #Ensure nothing already there local('rm -f dist/requirements1-0.1.pybundle') local('rm -f requirements.txt') local('rm -f requirements1.txt') local('rm -f pip*') rmvirtualenv() set_server_state('pip_installed_example_project-0.1', delete=True) #Try installing without an virtual env which should fail p = pip_install_requirements() assert not p v = mkvirtualenv() #c = confirm('PROCEED Install Just woven & django') ##Install Just woven & django env.DJANGO_REQUIREMENT='file://'+os.path.join(os.getcwd(),'dist','Django-1.2.1.tar.gz') p = pip_install_requirements() assert exists('/home/woven/example.com/env/example_project-0.1/lib/python2.6/site-packages/django') set_server_state('pip_installed_example_project-0.1', delete=True) local("echo 'django-staticfiles' >> requirements1.txt") ##Install our example staticfiles #c = confirm('PROCEED Install staticfiles') p = pip_install_requirements() assert p assert exists('/home/woven/example.com/env/example_project-0.1/lib/python2.6/site-packages/staticfiles') #c = confirm('PROCEED fail test') #Try installing again - should fail p = pip_install_requirements() assert not p #c = confirm('PROCEED rollback') #Try rolling back installation pip_install_requirements(rollback=True) #assert not exists('/home/woven/example.com/env/example_project-0.1/lib/python2.6/site-packages/staticfiles') assert not exists('/home/woven/example.com/dist/') assert not exists('/home/woven/example.com/package-cache/') #c = confirm('PROCEED bundle') #Bundle something up into the dist directory bundle() p = pip_install_requirements() assert exists('/home/woven/example.com/dist/requirements1-0.1.pybundle') assert exists('/home/woven/example.com/env/example_project-0.1/lib/python2.6/site-packages/staticfiles') ##Finally clean up #Test to ensure it doesn't delete everything - BROKEN #put('dist/example_project-0.1.pybundle','/home/woven/example.com/dist/example_project-0.2.pybundle') #pip_install_requirements(rollback=True) #assert exists('/home/woven/example.com/dist/example_project-0.2.pybundle') rmvirtualenv() local('rm -f dist/example_project-0.1.pybundle') local('rm -f requirements.txt') local('rm -f requirements1.txt') set_server_state('pip_installed_example_project-0.1', delete=True)
def test_virtualenv(): #Ensure we're cleared out set_server_state('created_virtualenv_example_project-0.1', delete=True) set_server_state('created_virtualenv_example_project-0.2', delete=True) v = mkvirtualenv() #Returns True if it is created assert v assert exists('/home/woven/example.com/env/example_project-0.1/bin/python') v = mkvirtualenv() #Returns False if not created. assert not v #test updating the version no# v = mkvirtualenv('0.2') #teardown assert exists('/home/woven/example.com/env/example_project-0.2/bin/python') rmvirtualenv('0.2') assert not exists('/home/woven/example.com/env/example_project-0.2/bin/python') assert exists('/home/woven/example.com/env/example_project-0.1/bin/python') rmvirtualenv() assert not exists('/home/woven/example.com') assert not server_state('created_virtualenv_example_project-0.2')
def test_deploy_project(): #setup to ensure nothing left from a previous run change_version('0.2','0.1') run('rm -rf /home/woven/example.com') set_server_state('deployed_project_example_project-0.1',delete=True) set_server_state('deployed_project_example_project-0.2',delete=True) local('rm -rf example_project/sitesettings') #tests deploy_project() assert exists('/home/woven/example.com/env/example_project-0.1/project/setup.py') assert exists('/home/woven/example.com/env/example_project-0.1/project/example_project/sitesettings/example_com.py') assert contains('from example_project.settings import','/home/woven/example.com/env/example_project-0.1/project/example_project/sitesettings/example_com.py') #make sure we can't overwrite an existing project p = deploy_project() assert not p #Test patch #teardown p = Project() p.delete() #Next test to ensure .pyc orphans are not left deploy_project() run('touch /home/woven/example.com/env/example_project-0.1/project/example_project/someorphan.pyc') set_server_state('deployed_project_example_project-0.1',delete=True) deploy_project() assert not exists('/home/woven/example.com/env/example_project-0.1/project/example_project/someorphan.pyc') #Test a 2nd version deployment print "TEST 2ND DEPLOYMENT" run('ln -s /home/woven/example.com/env/example_project-0.1/ /home/woven/example.com/env/example_project') change_version('0.1','0.2') deploy_project(version='0.2') assert exists('/home/woven/example.com/env/example_project-0.2/project/setup.py') #Teardown one project at a time p = Project() p.delete() assert exists('/home/woven/example.com/env/example_project-0.1/project/setup.py') change_version('0.2','0.1') p = Project(version='0.1') p.delete() local('rm -rf example_project/sitesettings')
def install_packages(rollback = False,overwrite=False): """ Install a set of baseline packages on Ubuntu Server and configure where necessary overwrite will allow existing configurations to be overwritten """ u = env.HOST_BASE_PACKAGES + env.HOST_EXTRA_PACKAGES if not rollback: if env.verbosity: print env.host, "INSTALLING & CONFIGURING HOST PACKAGES:" #print ','.join(u) #Remove apparmor - TODO we may enable this later sudo('/etc/init.d/apparmor stop') sudo('update-rc.d -f apparmor remove') #Get a list of installed packages p = run("dpkg -l | awk '/ii/ {print $2}'").split('\n') #The principle we will use is to only install configurations and packages #if they do not already exist (ie manually installed or other method) for package in u: if not package in p: preinstalled = False apt_get_install(package) sudo("echo '%s' >> /var/local/woven/packages_installed.txt"% package) if package == 'apache2': sudo("a2dissite 000-default") elif package == 'nginx': sudo('rm -f /etc/nginx/sites-enabled/default') if env.verbosity: print ' * installed '+package else: preinstalled = True if package == 'apache2' and (overwrite or not preinstalled): if env.verbosity: print "Uploading Apache2 template /etc/apache2/ports.conf" context = {'host_ip':env.host} upload_template('woven/apache2/ports.conf','/etc/apache2/ports.conf',context=context, use_sudo=True) #Turn keep alive off on apache sed('/etc/apache2/apache2.conf',before='KeepAlive On',after='KeepAlive Off',use_sudo=True) with settings(warn_only=True): sudo("apache2ctl stop") elif package == 'nginx' and (overwrite or not preinstalled): if env.verbosity: print "Uploading Nginx templates /etc/nginx/nginx.conf /etc/nginx/proxy.conf" upload_template('woven/nginx/nginx.conf','/etc/nginx/nginx.conf',use_sudo=True) #Upload a default proxy upload_template('woven/nginx/proxy.conf','/etc/nginx/proxy.conf',use_sudo=True) with settings(warn_only=True): sudo("/etc/init.d/nginx stop") #Set unattended-updates configuration unattended_config = '/etc/apt/apt.conf.d/10periodic' if not exists(unattended_config, use_sudo=True): if env.verbosity: "Configuring unattended-updates /etc/apt/apt.conf.d/10periodic" sudo('touch '+unattended_config) #in theory append() should intelligently ignore lines if they already exist #in practice this doesn't work as expected for this particular list. #possibly some characters it is not matching correctly hence if the #file already exists we'll skip this append([ 'APT::Periodic::Update-Package-Lists "1";', 'APT::Periodic::Download-Upgradeable-Packages "1";', 'APT::Periodic::AutocleanInterval "7";', 'APT::Periodic::Unattended-Upgrade "1";', ], filename=' /etc/apt/apt.conf.d/10periodic',use_sudo=True) set_server_state('unattended_config_created') #Install base python packages #We'll use easy_install at this stage since it doesn't download if the package #is current whereas pip always downloads. #Once both these packages mature we'll move to using the standard Ubuntu packages sudo("easy_install -U virtualenv") sudo("easy_install -U pip") #cleanup after easy_install sudo("rm -rf build") else: #rollback p = sudo('cat /var/local/woven/packages_installed.txt').split('\n') for package in u: if package in p: apt_get_purge(package) p.remove(package) #Finally write back the list of packages sudo('rm -f /var/local/woven/packages_installed.txt') for package in p: sudo("echo '%s' >> /var/local/woven/packages_installed.txt"% package) #Rollback unattended updates if server_state('unattended_config_created'): sudo('rm -rf /etc/apt/apt.conf.d/10periodic') set_server_state('unattended_config_created',delete=True) #Finally remove any unneeded packages sudo('apt-get autoremove -qqy')
def disable_root(rollback=False): """ Disables root and creates a new sudo user as specified by HOST_USER in your settings or your host_string The normal pattern for hosting is to get a root account which is then disabled. If root is disabled as it is in the default ubuntu install then set ROOT_DISABLED:True in your settings returns True on success """ def enter_password(): password1 = prompt('Enter the password for %s:'% original_username) password2 = prompt('Re-enter the password:'******'The password was not the same' enter_password() return password1 if not rollback: #TODO write a test in paramiko to see whether root has already been disabled #Fabric doesn't have a way of detecting a login fail which would be the best way #that we could assume that root has been disabled #print env.host, 'settings:', env.host_string, env.user, env.port original_username = env.user original_password = env.get('HOST_PASSWORD','') (olduser,host,port) = normalize(env.host_string) host_string=join_host_strings('root',host,str(port)) with settings(host_string=host_string, password=env.ROOT_PASSWORD): if not contains('sudo','/etc/group',use_sudo=True): sudo('groupadd sudo') set_server_state('sudo-added') home_path = '/home/%s'% original_username if not exists(home_path, use_sudo=True): if env.verbosity: print env.host, 'CREATING A NEW ACCOUNT: %s'% original_username if not original_password: original_password = enter_password() add_user(username=original_username, password=original_password,group='sudo') #add user to /etc/sudoers if not exists('/etc/sudoers.wovenbak',use_sudo=True): sudo('cp -f /etc/sudoers /etc/sudoers.wovenbak') sudo('cp -f /etc/sudoers /tmp/sudoers.tmp') append("# Members of the sudo group may gain root privileges", '/tmp/sudoers.tmp', use_sudo=True) append("%sudo ALL=(ALL) ALL", '/tmp/sudoers.tmp', use_sudo=True) sudo('visudo -c -f /tmp/sudoers.tmp') sudo('cp -f /tmp/sudoers.tmp /etc/sudoers') sudo('rm -rf /tmp/sudoers.tmp') #Add existing user to sudo group else: sudo('adduser %s sudo'% original_username) env.password = original_password #finally disable root if env.verbosity: print env.host, 'DISABLING ROOT' sudo("usermod -L %s"% 'root') return True else: #rollback to root if not env.ROOT_PASSWORD: env.ROOT_PASSWORD = enter_password() run('echo %s:%s > /tmp/root_user.txt'% ('root',env.ROOT_PASSWORD)) sudo('chpasswd < /tmp/root_user.txt') sudo('rm -rf /tmp/root_user.txt') print "Closing connection %s"% env.host_string connections[env.host_string].close() original_username = env.user (olduser,host,port) = normalize(env.host_string) host_string=join_host_strings('root',host,str(env.port)) with settings(host_string=host_string, password=env.ROOT_PASSWORD): if env.INTERACTIVE: c_text = 'CAUTION: Woven will now delete the user %s and the home directory. \n'% original_username c_text = 'Please ensure you can login as root before continuing.\n' c_text += 'Do you wish to continue:' proceed = confirm(c_text,default=False) if not env.INTERACTIVE or proceed: sudo('deluser --remove-home '+original_username) if server_state('sudo-added'): #never true on default installation sudo('groupdel sudo') set_server_state('sudo-added',delete=True)
def test_deploy_webservers(): #setup for test change_version('0.2','0.1') sudo('rm -rf /home/woven/example.com') sudo('rm -f /etc/nginx/sites-enabled/*') sudo('rm -f /etc/nginx/sites-available/*') sudo('rm -f /etc/apache2/sites-enabled/*') sudo('rm -f /etc/apache2/sites-available/*') set_server_state('deployed_apache_webserver_example_project-0.1',delete=True) set_server_state('deployed_nginx_webserver_example_project-0.1',delete=True) set_server_state('deployed_apache_webserver_example_project-0.2',delete=True) set_server_state('deployed_nginx_webserver_example_project-0.2',delete=True) #Initial test print "SIMPLE TEST" deploy_webservers() assert exists('/etc/apache2/sites-enabled/example_com-0.1.conf') assert exists('/etc/nginx/sites-enabled/example_com-0.1.conf') #test bump to 0.2 and make sure foreign site doesn't get deleted change_version('0.1','0.2') sudo('cp /etc/nginx/sites-available/example_com-0.1.conf /etc/nginx/sites-enabled/someother_com-0.1.conf') sed(filename='/etc/nginx/sites-enabled/someother_com-0.1.conf',before='example.com',after='someexample.com', limit=2,use_sudo=True) sudo('rm -f /etc/nginx/sites-enabled/someother_com-0.1.conf.bak') print "BUMPED VERSION TO 0.2" deploy_webservers() assert not exists('/etc/apache2/sites-enabled/example_com-0.1.conf') assert not exists('/etc/nginx/sites-enabled/example_com-0.1.conf') change_version('0.2','0.1') assert exists('/etc/nginx/sites-enabled/someother_com-0.1.conf') #Teardown change_version('0.2','0.1') sudo('rm -rf /home/woven/example.com') sudo('rm -f /etc/nginx/sites-enabled/*') sudo('rm -f /etc/nginx/sites-available/*') sudo('rm -f /etc/apache2/sites-enabled/*') sudo('rm -f /etc/apache2/sites-available/*') set_server_state('deployed_apache_webserver_example_project-0.1',delete=True) set_server_state('deployed_nginx_webserver_example_project-0.1',delete=True) set_server_state('deployed_apache_webserver_example_project-0.2',delete=True) set_server_state('deployed_nginx_webserver_example_project-0.2',delete=True)
def test_deploy_wsgi(): run('rm -rf /home/woven/example.com') set_server_state('deployed_wsgi_example_project-0.1',delete=True) deploy_wsgi() assert exists('/home/woven/example.com/env/example_project-0.1/wsgi/example_com.wsgi')
def deploy(self,patch=False): """ Deploy your project """ if not self.local_path: if env.verbosity: print "Warning: No %s set in project settings. Skipping %s..."% (self.setting,self.deploy_type) return False if self.installed and not patch and self.versioned: if env.verbosity: print env.host,"Warning: %s version %s already deployed. Skipping..."% (self.deploy_type,self.fullname) return False elif not self.installed and not patch: run('mkdir -p '+self.deploy_root) #Webserver must be able to write into the public directory in the case of fileuploads #TODO - Make this optional?? if self.deploy_type == 'public': sudo("chown -R www-data:sudo %s" % self.deploy_root[:-1]) #strip trailing / sudo("chmod -R ug+w %s"% self.deploy_root[:-1]) elif not self.installed and patch and self.versioned: if env.verbosity: print env.host,"Warning: Cannot patch %s. This version %s does not exist. Skipping.."% (self.deploy_type,self.fullname) return False l = local('ls '+self.local_path).rstrip() if not l: if env.verbosity: print "Warning: Theres are no files to deploy for %s. Skipping.."% self.deploy_type return False #bug in fabric 0.9 on rsync on alternate port fixed in 1.0 fab_vers = int(get_version(form='short')[0]) if fab_vers < 1: extra_opts = '--rsh="ssh -p%s"'% env.port #to save a bit of network usage if there is an existing version we will copy that first if self.versioned: av = active_version() if av and not patch: delete=True av_root = self.deploy_root.replace(self.fullname,av) dest_root = self.deploy_root.replace(self.deploy_type+'/','') run('cp -R %s %s'% (av_root,dest_root)) elif patch: delete=False else: delete=True else: delete = False if self.dest_path_postfix: self.last_postfix = self.dest_path_postfix.split('/')[-2] #since -1 will be trailing slash and thus empty postfix = self.dest_path_postfix.replace(self.last_postfix+'/','') remote_dir = self.deploy_root[:-1]+postfix run('mkdir -p '+remote_dir) else: self.last_postfix = self.deploy_type remote_dir = env.deployment_root+'/'.join(['env',self.fullname]) staging_dir = self.stage_local_files() rsync_project(local_dir=os.path.join(staging_dir,self.last_postfix),remote_dir=remote_dir, extra_opts=extra_opts,exclude=self.rsync_exclude,delete=delete) #delete orphaned .pyc - specific to projects & remove 'woven' from installed apps if self.deploy_type == 'project': run("find %s -name '*.pyc' -delete"% self.deploy_root) set_server_state(self.state+self.fullname) if env.verbosity: if patch: print env.host,"PATCHED %s "% (self.deploy_type) else: print env.host,"DEPLOYED %s "% (self.deploy_type)
def delete(self): #if no envs if not exists(self.root): run('rm -rf '+ env.deployment_root) set_server_state(self.state+self.fullname,delete=True)