Example of Python automated operations and deployment project tool Fabric

  • 2020-05-10 18:25:37
  • OfStack

Fabric is a good tool for an automated operation and deployment project developed with Python. You can automate interactions with remote servers through SSH, such as sending local files to the server and executing shell commands on the server.

Here is an example of an automated deployment of the Django project


# -*- coding: utf-8 -*-
#  The file name is to be saved as  fabfile.py

from __future__ import unicode_literals
from fabric.api import *

#  Login user and host name: 
env.user = 'root'
#  If not, when you need to log in, fabric  It will prompt you to type in 
env.password = 'youpassword'
#  If you have multiple hosts, fabric Will automatically deploy in sequence 
env.hosts = ['www.example.com']

TAR_FILE_NAME = 'deploy.tar.gz'

def pack():
  """
   define 1 a pack task ,  play 1 a tar package 
  :return:
  """
  tar_files = ['*.py', 'static/*', 'templates/*', 'vue_app/', '*/*.py', 'requirements.txt']
  exclude_files = ['fabfile.py', 'deploy/*', '*.tar.gz', '.DS_Store', '*/.DS_Store',
           '*/.*.py', '__pycache__/*']
  exclude_files = ['--exclude=\'%s\'' % t for t in exclude_files]
  local('rm -f %s' % TAR_FILE_NAME)
 
  local('tar -czvf %s %s %s' % (TAR_FILE_NAME, ' '.join(exclude_files), ' '.join(tar_files)))
  print(' Create in the current directory 1 Package file : %s' % TAR_FILE_NAME)


def deploy():
  """
   define 1 Three deployment tasks 
  :return:
  """
  #  Pack first 
  pack()

  #  Temporary file for the remote server 
  remote_tmp_tar = '/tmp/%s' % TAR_FILE_NAME
  run('rm -f %s' % remote_tmp_tar)
  #  upload tar File to remote server , local_path, remote_path
  put(TAR_FILE_NAME, remote_tmp_tar)
  #  Unpack the 
  remote_dist_base_dir = '/home/python/django_app'
  #  If it doesn't exist ,  Create a folder 
  run('mkdir -p %s' % remote_dist_dir)

 # cd  Command to switch the remote host's working directory to the specified directory  
  with cd(remote_dist_dir):
    print(' Unzip the file to the directory : %s' % remote_dist_dir)
    run('tar -xzvf %s' % remote_tmp_tar)
    print(' The installation  requirements.txt  Dependent package in ')
    #  I'm using  python3  To develop the 
    run('pip3 install -r requirements.txt')
    remote_settings_file = '%s/django_app/settings.py' % remote_dist_dir
    settings_file = 'deploy/settings.py' % name
    print(' upload  settings.py  file  %s' % settings_file)
    put(settings_file, remote_settings_file)

    nginx_file = 'deploy/django_app.conf'
    remote_nginx_file = '/etc/nginx/conf.d/django_app.conf'
    print(' upload  nginx  The configuration file  %s' % nginx_file)
    put(nginx_file, remote_nginx_file)
 
 #  Subdirectories in the current directory  deploy  In the  supervisor  The configuration file is uploaded to the server 
  supervisor_file = 'deploy/django_app.ini'
  remote_supervisor_file = '/etc/supervisord.d/django_app.ini'
  print(' upload  supervisor  The configuration file  %s' % supervisor_file)
  put(supervisor_file, remote_supervisor_file)
 
 #  Reload the  nginx  Configuration file 
  run('nginx -s reload')
  run('nginx -t')
  #  Delete the local package file 
  local('rm -f %s' % TAR_FILE_NAME)
  #  Load the latest configuration file, stop the old process and start all the processes in the new configuration 
  run('supervisorctl reload')
  #  perform  restart all . start  or  stop fabric  Both give an error and abort the run 
  #  But looking at the logs on the server, supervisor  Have to restart 
  # run('supervisorctl restart all')

Perform the pack task

fab pack

Perform the deploy task

fab deploy

Let me share with you an automated deployment of code using Fabric


#coding=utf-8
from fabric.api import local, abort, settings, env, cd, run
from fabric.colors import *
from fabric.contrib.console import confirm

env.hosts = ["root@115.28. X x x x x "]
env.password = " X x x x x "


def get_git_status():
  git_status_result = local("git status", capture=True)
  if " No files to submit, clean workspace " not in git_status_result:
    print red("**** The current branch has files not yet committed ")
    print git_status_result
    abort("**** Has been terminated ")


def local_unit_test():
  with settings(warn_only=True):
    test_result = local("python manage.py test")
    if test_result.failed:
      print test_result
      if not confirm(red("**** Unit test failed. Do you want to continue? ")):
        abort("**** Has been terminated ")


def server_unit_test():
  with settings(warn_only=True):
    test_result = run("python manage.py test")
    if test_result.failed:
      print test_result
      if not confirm(red("**** Unit test failed. Do you want to continue? ")):
        abort("**** Has been terminated ")


def upload_code():
  local("git push origin dev")
  print green("**** Code uploaded successfully ")


def deploy_at_server():
  print green("****ssh Go to the server and do the following ")
  with cd("/var/www/ X x x x x x "):
    #print run("pwd")
    print green("**** The code will be downloaded from the remote repository ")
    run("git checkout dev")
    get_git_status()
    run("git pull origin dev")
    print green("**** The unit tests will be run on the server ")
    server_unit_test()
    run("service apache2 restart", pty=False)
    print green("**** restart apache2 successful ")
    print green("******** Code deployment successful ********")


def deploy():
  get_git_status()
  local("git checkout dev", capture=False)
  print green("**** Switch to the dev branch ")
  get_git_status()
  print green("**** The unit tests will start running ")
  local_unit_test()
  print green("**** The unit tests are complete and the code is uploaded ")
  upload_code()
  deploy_at_server()

fabric can reduce manual operations by solidifying commands for automated deployment or multi-machine operations into a single script. It was written after I first touched this thing today, which is really useful. run fab deploy Will do.

The main logic is to run the local dev branch out of the unit test, submit it to the server, log in ssh to the server, then run pull down, run the unit test, and then restart apache2. The first time I write it, it might be easier, but I'm going to keep improving.


Related articles: