I need to sort env.hosts to run tasks in a specific order

97 views Asked by At

I need to sort the hosts from a roledef so they can run those tasks in a certain order.

I'm implementing a PostgreSQL BDR (http://2ndquadrant.com/en-us/resources/bdr/) deployer. In order to succeed, you need to create a BDR group in a host and only then join the BDR group in all other hosts.

The user need to choose which would be the first host from the list.

----EDITED----

I try to set env.hosts dynamically but it's not working.

env.roledefs = {
  'array1':    [],
}

env.hostsdefs = {
  'array1': [
    {'host': 'data-03', 'server': 'root@data-03'},
    {'host': 'data-01', 'server': 'root@data-01'},
  ],
}

@serial
def sort_and_echo(default_host):
    sort_host(default_host)
    echoing()

@serial
def sort_host(default_host):
    hostnames = env.hostsdefs[env.roles[0]]
    new_hosts = []
    for host in (hostnames):
        if (host['host'] != default_host):
            new_hosts.append(host['server'])
        else:
            new_hosts = [host['server']] + new_hosts
    env.hosts = new_hosts


@serial
def echoing():
    print env.hosts
    print('current host: %s' % (env.host_string))

This way, if I try:

fab -R array1 sort_and_echo:default_host=data-03
['root@data-03', 'root@data-01']
current host: None

Done.

It will not run echoing for each server in the list.

But if I try one sort and then echoing in the same command:

fab -R array1 sort_host:default_host=data-03 echoing

It will provide the expected output:

[root@data-03] Executing task 'echoing'
['root@data-03', 'root@data-01']
current host: root@data-03
[root@data-01] Executing task 'echoing'
['root@data-03', 'root@data-01']
current host: root@data-01

Done.

How can I change the hosts list in runtime?

2

There are 2 answers

0
otaviofcs On

After a while I solve my problem. It was easier than expected. No hacks needed.

Passing the hosts parameter would make the host to be added at the begging of the array. As the standard behaviour of fabric is to throw out deduplication (check Host list deduplication in http://docs.fabfile.org/en/1.10/usage/execution.html#combining-host-lists), it solves the problem.

If you don't pass the parameter, it will use the first one of the array

env.roledefs = {
'array1': {'hosts': ['root@data-01', 'root@data-03'], }
}

So when I try:

fab -R array1 -H data-03 echoing

It will run in the correct order:

[root@data-03] Executing task 'echoing'
['root@data-03']
current host: root@data-03
[root@data-01] Executing task 'echoing'
['root@data-03']
current host: root@data-01

Done.
4
Javier Buzzi On

If i understand you correctly, you can do something like this:

@task
def environment(*args):
    env.hosts = args

@task
def dev(*args):
    hosts = list(args)
    hosts.append('dev.host1')
    hosts.append('dev.host2')
    environment(*hosts)

@task
@serial # <--- PS. you dont really need this
def echoing():
    print env.hosts
    print('current host: %s' % (env.host_string))

you can now call it like this:

fab environment:node1.host.com,node2.host.com echoing

or:

# which is a "predetermined" list
fab dev echoing
# or add stuff to dev
fab dev:qa.node.host.com echoing
# ^^ this will just append the qa host to your existing list