How can I properly set the `env.hosts` in a function in my Python Fabric `fabfile.py`?

前端 未结 5 942
挽巷
挽巷 2021-01-11 23:08

When I run this fabfile.py...

from fabric.api import env, run, local, cd

def setenv(foo):
  env.hosts = [\'myhost\']

def mycmd(foo):
  setenv(         


        
相关标签:
5条回答
  • 2021-01-11 23:38

    I have figured out how to make it work:

    from fabric.api import env, run, local, cd
    
    def setenv(foo):
      env.hosts = ['myhost']
      return env
    
    def mycmd(foo):
      env = setenv(foo)
      print(env.hosts)
      run('ls')
    
    0 讨论(0)
  • 2021-01-11 23:41

    @Chris, the reason you're seeing this behavior is because the host list is constructed before the task function is called. So, even though you're changing env.hosts inside the function, it is too late for it to have any effect.

    Whereas the command fab setenv:foo mycmd:bar, would have resulted in something you would have expected:

    $ fab setenv:foo mycmd:bar
    [myhost] Executing task 'mycmd'
    ['myhost']
    [myhost] run: ls
    

    This is the same as the accepted answer, but because of the way setenv is defined, an argument is needed.

    Another example:

    from fabric.api import env, run, local, cd
    
    env.hosts = ['other_host']
    
    def setenv(foo):
        env.hosts = ['myhost']
    
    def mycmd(foo):
        setenv(foo)
        print('env.hosts inside mycmd: %s' % env.hosts)
        run('ls')
    

    The output of this is:

    $ fab mycmd:bar
    [other_host] Executing task 'mycmd'
    env.hosts inside mycmd: ['myhost']
    [other_host] run: ls
    
    Fatal error: Name lookup failed for other_host
    
    Underlying exception:
        (8, 'nodename nor servname provided, or not known')
    Aborting.
    

    As you can see, the host-list is already set to ['other_host', ] when fabric starts to execute mycmd.

    0 讨论(0)
  • 2021-01-11 23:44

    Have you tried to used the hosts decorator?

    from fabric.api import env, run, hosts
    
    @hosts('myhost')
    def mycmd(foo):
        print(env.hosts)
        run('ls')
    
    0 讨论(0)
  • 2021-01-11 23:48

    I know this question is super old, but just in case someone stumbles across this, I have found that you don't need to call this as a fab file per se (your file doesn't need to be called "fabfile.py" and command doesn't need to be fab setenv(foo) mycmd(bar). Since you are importing the needed fab elements, you can call the file anything you want (let's call it "testfile.py") and simply use the execute function in the file. That would make your command python testfile.py.

    Inside the testfile, set everything up like you would normally, but start the function using the execute keyword. Your file would look something like this:

    from fabric.api import env, run
    
    def setenv(foo):
        env.hosts = ['myhost']
        execute(mycmd, bar)
    
    def mycmd(bar):
        run('ls')
    
    setenv(foo)
    

    ** It's important to note that the execute command does look like a regular function call. It will call the function and send the arguments in a single comma separated line. You can find more information here

    So you'd start your program which would first call setenv, then setenv would execute the mycmd function. With this, you can also set multiple hosts within the same array. Something like:

    env.hosts=['myhost1','myhost2','myhost3']
    
    0 讨论(0)
  • 2021-01-12 00:02

    The way you are doing it is not normally how I would use Fabric.

    from fabric.api import *
    
    def hostname():
    
        env.hosts = ['myhosts']
    
    def mycmd():
        print env.hosts
        run('ls -l')
    

    To run this I would then do

    fab hostname mycmd

    this allows you to seperate which host/hosts you want to perform the command on.

    hope it helps.

    0 讨论(0)
提交回复
热议问题