Fabric fun.

home | blog | Teh Internet | guest blog |rants | political | projects | Gwen and Liam | Citadel patched | Tools | TMBG



Full talk here (not me) - thanks Wes Thomas for the info.
http://pyvideo.org/pytexas-2015/automate-your-web-deployments-with-fabric.html
And as always (in case the link goes away, here is boiled down points I got from that talk:
I will add my own stuff over time at the bottom of this page - see asdfjklm.

The basics.
fab comand
pip install fabric
...
fab

Expects that there is a file called fabfile.py that contains the what you want to do.
(don't worry, you can configure this as well - see namespacing below)
Once you have one with python functions in it, you can list via:
fab --list



Use ssh config to define hosts and keys:
In your fab file:

from fabric.api import *

#(this is false by default)
env.use_ssh_config = True

# define hosts for production with
define production():
 # ... or read from external file, db, or whatever - iterable is all it takes!
 env.hosts = ['host1', 'somehost']
 
# staging
define staging():
  env.hosts = ['stagehost']

- that allows you to pick production or test or whatever sub-sets you define to work on:
fab production runfunction
- or -
fab staging runfunction runanotherfunction

In:
~/.ssh/config

ServerAliveInterval 30

Host somehost
  HostName somehost.somedomain
  User youruser
  ItentityFile ~/.ssh/id_rsa

Host host1
  HostName host1.somedomain
  User youruser
  IdentityFile ~/.ssh/id_rsa

Host stagehost
  HostName stagehost.someotherdomain
  User youruseronathathost
  IdentityFile ~/.ssh/id_rsa


Alternatives to using ssh/config file:
fab -H hostname somecommand
fab -H somehost,host1 someothercommand


cd before run a command?:
def command():
  with cd('~/somedir/somesub/webproject'):
    run('somecommand ...')


Turbo mode! - Decorator @parallel
Does just what you think it does (run in parallel on hosts defined).
Set the pool_size arg if you have many hosts with complex ops. It limits your simultaneous connections - and thus load on your localhost.
# just add @parallel to functions
@parallel
def someop():
  run('do something')

#alternative
@parallel(pool_size = 5):
def someoplimited():
  run('do something')

# - things will happen out of order on hosts, so make sure your ops are atomic in your mind first!


Only do it once - @runs_once decorator
If you have a task that only needs to be done once (push files to cdn network, update a back end db, etc...
# note: won't work with @parallel decorator, so don't use both.
@runs_once
def dosomething():
  ...


Pile it on with execute()
def dothings():
  execute(deploy)
  execute(update)
  execute(define)

# where each arg is another function as before, but list allows you to combine steps in one function.


What roles can you apply to servers, and limit the functions to those that are in that role.
env.roledefs = {
    'db' : ['dbserver1', 'dbserver2'],
    'web': ['web1', 'web2', 'web3'],
    'ec2hosts' : ['someec2host', 'anotherec2host', 'blahec2host', 'yetanotherec2host']
}

@roles('db')
def migrate():
  # some db things
  pass

@roles('web'):
def restartapache();
  # web only things
  pass


Limit the noise. Your fabfile is full!
# the @task decorator will quiet down the fab --list method

@task
def userallowedfunction():
  #some code
  pass

def someinternalthing():
  # othercode
  pass

fab --list
- should now only display userallowedfunction
- it also caps the other commands to private (i.e. not runnable via the fab command).
- you need to decorate all allowed functions with @task that the user can get to.


That is too much typing to run that function!
# you can alter the @task decorator - see above
# just add alias = 'tla'
@task(alias = 'rtadse')
def run_this_and_do_something_else();
  # code...
  pass

fab --list

run_this_and_do_something_else
rtadse


namespaces - does the file need to be only fabfile.py?
- no, you can import from other files to get the modules and classes and other existing code to that fabfile.py.
(remember, it is just python, so the sky is the limit - i.e. batteries included.)


Don't re-invent the wheel. If you need to append to a config file, see append in the docs.
If you need to add an ssh key, that is easy...
If you need to do sed, search and replace, exists (config already has this thingie), comment out line with regex ... line fab contrib items can be fun - not core, but close to it.
If you don't find it in the current docs, search. There are many others sharing fab examples to solve the repetitive issues.
I will post some of mine here later - famous last words.


My stuff to share: asdfjklm

Why use fabric?
Your programmers need answers, not a gate-keeper. Empower them with this as a tool. Things change, why teach everyone to be a sysadmin?
You can tweak a process that is otherwise painfull and make it easy.
It is repeatable, it is automated, it is easy to tweak.
You can share the easy to read fab file, and anyone can tweak it and improve it.
There is no need to cover up the hand waving things that happend on one-off deployments.

Is it hard to use for non-programmers?
You can have them pip install fabric, get the fabfile.py, and then they can just run:
fab sometask

So, no.
No need to explain the black box stuff that happens with sometask.
Think about wrapper it in a simple gui to share tasks and the load.

More to come. - insert test pattern here.
This page intentionally left blank.
http://this-page-intentionally-left-blank.org/



[æ]