Reputation: 71
Python 3.8.2, Fabric 2.5.0, Paramiko 2.7.2, Invoke 1.4.1
Hello,
I have a fabfile which needs to handle hosts passed at the command-line (using -H
) and hosts defined in the fabfile if -H
was not passed. Here's an example of the issue I'm facing:
target_group = None
@task
def prod(c):
_env_handler(c, "prod")
def _env_handler(c, env_name):
global target_group
if not hasattr(c, 'host'):
target_group = Group("somehost1.tld", "somehost2.tld")
@task(hosts=target_group)
def test(c):
print(c)
If I run fab prod test
:
<Context: <Config: {'run': {'asynch ...
If I run fab -H 1,2 test
:
<Connection host=1>
<Connection host=2>
So, passing hosts using the @task(hosts=[...]
decorator produces a c Context
object, and using -H
produces a c Connection
object.
I know using a task (prod(c)
) to wrap environment logic may be questionable...but is there a way to ensure the task (test(c)
) always receives a Connection
object...or am I fundamentally misunderstanding something?
Thanks.
Edit: I've also tried directly passing a hosts list (e.g. @task(hosts=["somehost1.tld", "somehost2.tld"]))
with the same result.
Edit: Here's the current workaround, but it's obviously not ideal if you have a lot of tasks:
@task
def test(c):
if not hasattr(c, 'host'):
for c in target_group:
test(c)
else:
logging.info(f"Targeting {c.host}")
Upvotes: 2
Views: 211
Reputation: 71
Workaround using a custom task decorator:
def _task_handler(func):
@task
@functools.wraps(func)
def wrapper(c):
if not hasattr(c, 'host'):
for c in target_group:
func(c)
else:
func(c)
return wrapper
Upvotes: 1