Fabric and namespaces (modular fabfile)

n1
n1
Aug 27, 2017 · 2 min read

Have you ever wondered if there is a better approach to your fabfile.py then one file with tons of @tasks? Or have you ever wondered why you have to copy your fabric file from project to project, modify it and when you write cool task you have to copy it back to your original project? Yes? Well I have a comfy solution for you — namespaces.

Fabric has one handy tool and it’s called namespaces. With this in your head you are able to create more than one file full of tasks. Dive in and keep reading.

Namespaces basically allows us to separate fabric tasks into modules. What does that mean? It means you can create one main fabric file with very basic tasks (like dev or prod for switching environments) and then put the rest into separated files. Every module (file) will be prefixed and you will be able to acces it via . dot notation. Sounds great? Carry on.

I use Django framwork under virtualenv. Recently, I’ve ported my projects to Docker so I had no need of virtualenv anymore. But some of my projects still use that tool. Iwanted to keep fabfiles consistend so I’ve stepped into namespaces and I’ve split my fabfile into smaller chunks.

First of all create fabfile folder in your project. Now, you work with this folder, not with a single file. Luckily Fabric finds the folder automaticaly, so you don’t have to specify that like fab -f fabfile/.... Now create __init__.py in that folder. Thats gonna be your base “fabric” file.

Example of my __init__.pyfile:

from fabric.api import env, taskenv.use_ssh_config = True@task(alias="d")
def dev():
env.run = docker.run
env.PROJECT_DIR = "/usr/local/platformenv/app"
env.DOCKER_CONTAINER = "ht-dev"
env.DOCKER_COMPOSE_FILE = "docker-compose.dev.yml"
env.RUN_PARAMS = "--settings=pltfrm.settings.dev"
@task(alias="p")
def prod():
env.run = docker.run
env.PROJECT_DIR = "/usr/local/platformenv/app"
env.DOCKER_CONTAINER = "ht-prod"
env.DOCKER_COMPOSE_FILE = "docker-compose.prod.yml"
env.RUN_PARAMS = "--settings=pltfrm.settings.prod"

As you can see the only tasks I have there are dev and prod. These 2 tasks begins all my fab commands like fab dev ... or fab d ... (bacause of the alias). Ok, so where I hide all the actual tasks? Here comes all the magic…

So far we have:

fabfile/
__init__.py

Let’s create our first Fabric namespace. Let’s say you use Docker so we create docker.py inside our folder.

fabfile/
__init__.py
docker.py

Let’s put our first task in our new namespaced file.

from fabric.api import local@task
def ps():
local("docker ps -a")

Lastly import docker.py to __init__.py like import docker on top of your __init__.py. Tadaaaaa. Done.

Run fab -l in your terminal. You get something like this:

Available commands:    d
dev
p
prod
docker.ps
  • dev — switches environment to development (d is alias)
  • prod — switches environment to production (p is alias)
  • docker.ps — our first namespaced task taken from docker module.

Hope you enjoyed. For futher reading please follow to documentation.

)
n1

Written by

n1

Python and stuff

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade