简体   繁体   中英

Passing a Fabric env.hosts sting as a variable is not work in function

Passing a Fabric env.hosts sting as a variable is not work in function.

demo.py

#!/usr/bin/env python

from fabric.api import env, run

def deploy(hosts, command):
    print hosts
    env.hosts = hosts
    run(command)

main.py

#!/usr/bin/env python

from demo import deploy

hosts = ['localhost']
command = 'hostname'
deploy(hosts, command)

python main.py

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

But env.host_string works!

demo.py

#!/usr/bin/env python

from fabric.api import env, run

def deploy(host, command):
  print host
  env.host_string = host
  run(command)

main.py

#!/usr/bin/env python

from demo import deploy

host = 'localhost'
command = 'hostname'
deploy(host, command)

python main.py

localhost
[localhost] run: hostname
[localhost] out: heydevops-workspace

But the env.host_string is not enough for us, it's a single host. Maybe we can use env.host_string within a loop, but that's not good. Because we also want to set the concurrent tasks number and run them parallelly.

Now in ddep(my deployment engine), I only use MySQLdb to get the parameters then execute the fab command like:

os.system("fab -f service/%s.py -H %s -P -z %s %s" % (project,host,number,task))

This is a simple way but not good. Because if I use the fab command, I can't catch the exceptions and failures of the results in Python, to make my ddep can "retry" the failed hosts. If I use the "from demo import deploy", I can control and get them by some codes in Python.

So now "env.host " is the trouble. Can somebody give me a solution? Thanks a lot.

Here's my insight.

According to docs , if you're calling fabric tasks from python scripts - you should use fabric.tasks.execute .

Should be smth like this:

  • demo.py

     from fabric.api import run from fabric.tasks import execute def deploy(hosts, command): execute(execute_deploy, command=command, hosts=hosts) def execute_deploy(command): run(command) 
  • main.py

     from demo import deploy hosts = ['localhost'] command = 'hostname' deploy(hosts, command) 

Then, just run python main.py . Hope that helps.

Finally, I fixed this problem by using execute() and exec.

main.py

#!/usr/bin/env python

from demo import FabricSupport

hosts = ['localhost']

myfab = FabricSupport()
myfab.execute("df",hosts)

demo.py

#!/usr/bin/env python

from fabric.api import env, run, execute

class FabricSupport:
    def __init__(self):
        pass

    def hostname(self):
        run("hostname")

    def df(self):
        run("df -h")

    def execute(self,task,hosts):
        get_task = "task = self.%s" % task
        exec get_task
        execute(task,hosts=hosts)

python main.py

[localhost] Executing task 'hostname'
[localhost] run: hostname
[localhost] out: heydevops-workspace

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM