2

i am working on Fabric for my deploying tools and also distribute the command on multiple hosts. but i don't know how can define a complex hosts in my fabfile.py

for example: i have 4 servers. serverA, serverB, serverC, serverD

def prod():
    env.hosts = ["serverA', "serverB" ]

def dev():
    env.hosts = ["serverC' "serverD"]

def all():
    prod()
    dev()

is it possible for me to run a command on all hosts without define again?

EX: fab all {command}
Calvin Pham
  • 55
  • 1
  • 5

2 Answers2

1

You could take a look at defining roles for your environment.

from fabric.api import env, run
from fabric.decorators import task

env.roledefs = {
    'prod': ['ServerA', 'ServerB'],
    'dev': ['ServerC', 'ServerD'],
    'envC': ['ServerE', 'ServerF']
}

env.roledefs['all'] = [h for r in env.roledefs.values() for h in r]


@task
def hostname():
    run('hostname -f')

This would mean that your will now have to issue your fabric calls like this:

fab -R prod hostname
fab -R dev hostname
fab -R all hostname
fab -R dev,envC hostname
user76776
  • 436
  • 2
  • 4
  • It does not work on my side. here is my fabric version: > $ fab -V > Fabric 1.8.0 > Paramiko 1.12.0 > $ fabb -R all cmd:"ls" > Fatal error: The following specified roles do not exist: all > Aborting. – Calvin Pham Jan 15 '14 at 06:22
  • I edited the answer and added the full contents of the fabfile. I tested it with Fabric 1.8.1 and Paramiko 1.12.1. – user76776 Jan 15 '14 at 16:17
  • Thank you so much because of your kind. i wish can vote you more :) – Calvin Pham Jan 20 '14 at 16:56
0

An alternate solution for something more dynamic... no static config in the fabfile, using bash.

mfab() {
    hosts=()
    while [ "$#" != 0 ]; do
        if [ "$1" = -- ]; then
            shift
            break
        fi
        hosts+=("$1")
        shift
    done

    list=$(echo "${hosts[@]}" | tr ' ' ',')
    fab -H "$list" "$@"
}

Here's a way to make it do a dry run... run this before your tests:

fab() { echo fab "$@"; }

example 1: arbitrary size list using shell expansions/globbinb/whatever you want to use

mfab node{A..D}{01..05} -- example_command

will run a command like:

fab -H nodeA01,nodeA02,nodeA03,nodeA04,nodeA05,nodeB01,nodeB02,nodeB03,nodeB04,nodeB05,nodeC01,nodeC02,nodeC03,nodeC04,nodeC05,nodeD01,nodeD02,nodeD03,nodeD04,nodeD05 example_command

example 2: I just deployed 7 new machines and every 2nd one is broken and I want to run a command to check/fix it.

mfab node{100..106..2} -- example_command

will run a command like:

fab -H node100,node102,node104,node106 example_command

example 3: more options including -- used by fabric itself:

mfab node{01..10} -- -P -- uname -a
Peter
  • 2,756
  • 1
  • 20
  • 26