1

I have checked this question but it doesn't answer to my problem.

I would like to do something like:

@task
def setEnv(environment):
    if environment == 'prod':
        env.roledefs['nginx'] = [ 'www@tnginx01', 'www@tnginx02' ]
        env.roledefs['middle'] = [ 'www@tmiddle01', 'www@tmiddle02' ]
    elif environment == 'preprod':
        env.roledefs['nginx'] = [ 'www@pnginx01', 'www@pnginx02' ]
        env.roledefs['middle'] = [ 'www@pmiddle01', 'www@pmiddle02' ]
    else:
        puts(red("This environment doesn't exist. Possible values are 'preprod' and 'prod'", True))
        sys.exit()

    env.first_middle = env.roledefs['middle'][0]

@task
@roles(env.first_middle)
def deploy():
    run('pwd')

But it seems that it's not possible to change the value of env.roledefs after the Fabfile has been loaded into memory. When you try to run fab setEnv:prod deploy, it won't work:

No hosts found. Please specify (single) host string for connection

Does anyone know how to do that? Note that I cannot use roledefs to represent environments. I already use roledefs to store servers belonging to a same 'cluster', and each environment has several clusters with several servers.

Community
  • 1
  • 1
Fox
  • 707
  • 6
  • 13
  • So to be clear, you cannot set env.roledefs['first_middle'] = env.roledefs['middle'][:1], and set @roles('first_middle')? – justcompile Jul 04 '14 at 14:35
  • Yes, I can, but this wouldn't solve the problem of env.roledefs which cannot be edited from within a task. – Fox Jul 04 '14 at 15:00

1 Answers1

2

I just found the solution to my problem.

The key is that env.roledefs cannot be edited from within a Fabric task. So, the code editing it has to be at the beginning in the global scope.

if env.get('env') == 'prod':
    env.roledefs['nginx'] = [ 'www@tnginx01', 'www@tnginx02' ]
    env.roledefs['middle'] = [ 'www@tmiddle01', 'www@tmiddle02' ]
elif env.get('env') == 'preprod':
    env.roledefs['nginx'] = [ 'www@pnginx01', 'www@pnginx02' ]
    env.roledefs['middle'] = [ 'www@pmiddle01', 'www@pmiddle02' ]
else:
    puts(red("This environment doesn't exist. Possible values are 'preprod' and 'prod'", True))
    sys.exit()

    env.first_middle = env.roledefs['middle'][0]

@task
@roles(env.first_middle)
def deploy():
    run('pwd')

And then I just call the fabfile like this:

fab --set env=preprod deploy

My answer is inspired from this link which gave me the idea.

Fox
  • 707
  • 6
  • 13
  • Just in case someone finds this answer: You _can_ set/manipulate env.roledefs inside a task (if you call such a task from another task, don't forget to use execute()). The code in the question should throw an AttributeError, env has no "first_middle" at the time of the decorator definition (and in the answer above setting env.first_middle shouldn't be indented). Fox I think you drew the wrong conclusions. – Danny W. Adair Feb 18 '15 at 12:01