RickyA
RickyA

Reputation: 16029

Update hosts within fabric script

I am trying to loop over all my server configurations in fabric and get their hostname like such:

from fabric.api import env, run

def serv_foo():
    env.hosts = ['[email protected]']

def serv_bar():
    env.hosts = ['[email protected]']

def get_all_servers():
    return {(k,v) for k,v in globals().items() if k.startswith("serv_")}

def get_hostnames():
    for serv_name, serv_fptr in get_all_servers():
        print(env.hosts)
        serv_fptr()
        print(env.hosts)
        hostname = run("hostname")
        print(hostname)

This however fails:

>>> fab get_hostnames

>>> []
>>> ['[email protected]']
>>> No hosts found. Please specify (single) host string for connection: 

How can I dynamically update the hosts in fabric?

Upvotes: 1

Views: 149

Answers (1)

alecxe
alecxe

Reputation: 473813

You should set a host for the run command by using execute:

from fabric.api import env, run
from fabric.tasks import execute


def serv_foo():
    return ['[email protected]']


def serv_bar():
    return ['[email protected]']


def get_all_servers():
    return {(k, v) for k, v in globals().items() if k.startswith("serv_")}


def get_hostname():
    return run("hostname")


def get_hostnames():
    for serv_name, serv_fptr in get_all_servers():
        print(env.hosts)
        hostname = execute(get_hostname, hosts=serv_fptr())
        print(hostname)

or settings context manager:

from fabric.api import run
from fabric.context_managers import settings


def serv_foo():
    return '[email protected]'


def serv_bar():
    return '[email protected]'


def get_all_servers():
    return {(k, v) for k, v in globals().items() if k.startswith("serv_")}


def get_hostnames():
    for serv_name, serv_fptr in get_all_servers():
        with settings(host_string=serv_fptr()):
            hostname = run("hostname")
            print(hostname)

Hope that helps.

Upvotes: 1

Related Questions