Streamline Deployments With Fabric

by Osama Abulail
published on Dec. 20, 2017

Fabric can execute system commands on your local computer where fabric is installed, and also can execute commands on remote computers via normal SSH connection.

for a typical use case, normally when I am working with a project and it’s time to deploy an update, I do the following:

  1. I commit and push the changes to github
  2. connect to the production server via SSH
  3. navigate to the project folder
  4. pull changes from the github repository
  5. backing up databases to some folder (when critical changes)
  6. do the migrations
  7. updating static files
  8. … (other tasks depending on the project)

this process becomes very boring and slows you down from doing the creative work

imagine if you can automate all that with something like a wizard on your local computer. fabric let’s you build that wizard.

let’s install and use this awsome tool to demonstrate all this.

Installation

I’ll be using a linux machine for this demonstration (specificly Ubuntu 16.04), but you can use Windows also.

you can install using the ubuntu apt-get command:

sudo apt-get install fabric

or using the python package manager, pip (you’ll need pip installed):

pip install fabric

that’s all, fabric is now setup and installed.

Usage

Now, in your projects directory, (whatever type of project). you create a file and name it fabfile.py. inside this python scripy you define a group of Tasks however you like.

take a look at the follwing code block as it represents the simplist fabfile:

from fabric.api import * def reboot_server(): pass def another_task(argument=''): pass

and then to run a specific task (rebooting a remote server for example), from the linux console run:

fab reboot_server

you can also give it some custom arguments and read them inside the script:

fab another_task argument:"some_value"

and this will execute that specific task.

Note: the fabfile.py file is best placed at the root directory of your project.

and how exactly to write the fabfile.py?, keep reading.

Fabric Operations

to implement the fabric tasks you’ll need a set of operations provided by the fabric.operations module. some of the most used ones include:

run

result = run("ls ~/project")

this will execute the provided command string to a remote server (will use an SSH connection), and will return a string as the console output from the command. this string will also expose the following attributes:

result.failed (True if failed)

result.succeeded (True if executed without errors)

result.command (the actual run command)

sudo

result = sudo("apt-get install cowsay")

very similar to run, but executes the command with sudo privileges, and also returns the console output.

local

local(ls ~/project")

similar to run, but the execution happens at the local computer (running fabric). and doesn’t return the console output

local is built on top of a python module called “subprocess”, to do more advanced execution on the local computer consider using subprocess.

these are the most used commands, however you can find many more usefull commands like … and others form the official fabric documentation

Fabric Context Managers

Context managers are helpers you can use when writing the fabric script, the most used ones are, cd, lcd and settings. context managers live in the fabric.context_managers module. to demonstrate thier usage, take a look at the following examples:

fabric.context_managers.cd: this will change the state of the current directory of the remote server, and each operation inside it's block code will be prefixed by "cd <path>".

so instead of saying:

run('cd /var/www') run('ls') run('mkdir dir')

you can do it like this:

with cd('/var/www'): run('ls') # Turns into "cd /var/www && ls" run('mkdir dir') # Turns into "cd /var/www && mkdir dir"

fabric.context_managers.lcd: this will operate just like cd, but on the local computer, so within the wrapped block you will use local for example and not run

Env Variables

The environment dictionary env is single dictionary object shared between all of your fabric tasks, it lives under fabric.state.env, and is included in fabric.api for convenience. you will mostly use this to set some variables for the working environment. variables like the username of the remote server, the password and list of remote hosts that fabric will execute upon.

these settings live under env.hosts[], env.user and env.password attributes.

to domonstrate all what you’ve learned so far, take a look at the following complete example fabfile:

from fabric.api import * env.hosts = [ 'www.example.com', # you can add other hosts as well ] # Set the username env.user = "username" # Set the password # it's not recommended to set passwords like this # you can configure an SSH connection, see fabric docs # env.password = "password" def first_task(): """ update the system packages """ run("sudo apt-get update") run("sudo apt-get -y upgrade") def second_task(): """ create 2 directories inside /var """ with cd('/var'): run('mkdir dir1') run('mkdir dir2')

The cool thing is that this script is written in python, on of the most diverse languages.

you can call both tasks from the command line like this:

fab first_task second_task

Conclusion

This article servers as a simple introduction to what fabric is and what is does. basically, you will benifit from using fabric if you have some repititive task that you can automate to cut time and not having to do work that a computer can do. however, there’s a lot more for fabric, and I advise you to take a look at thier own documentation. I will also be covering another related post that shows how to use fabric in a more professional and secure way. and by usign two files; the fabfile.py and a JSON file fabric.config.json, the later one I use to store some project configurations for fabric.