Pass parameter to fabric task
Asked Answered
A

5

132

How can I pass a parameter to a fabric task when calling "fab" from the command line? For example:

def task(something=''):
    print "You said %s" % something
$ fab task "hello"
You said hello

Done.

Is it possible to do this without prompting with fabric.operations.prompt?

Ambuscade answered 22/1, 2012 at 11:40 Comment(0)
K
218

Fabric 2 task arguments documentation:

http://docs.pyinvoke.org/en/latest/concepts/invoking-tasks.html#task-command-line-arguments


Fabric 1.X uses the following syntax for passing arguments to tasks:

 fab task:'hello world'
 fab task:something='hello'
 fab task:foo=99,bar=True
 fab task:foo,bar

You can read more about it in Fabric docs.

Kendakendal answered 22/1, 2012 at 12:0 Comment(5)
The quotes aren't necessary; all arguments are strings: "since this process involves string parsing, all values will end up as Python strings, so plan accordingly. (We hope to improve upon this in future versions of Fabric, provided an intuitive syntax can be found.)"Eskilstuna
The quotes around hello world seem necessary though?Stila
@Stila If that's true, quotes are probably necessary in that example because the terminal or fabric's command line parser would see the space and think that was the end of everything for that task and that world was a new task.Huntress
Additionally, after using this for less than a minute, I've found that, on Windows, using single quotes results in the single quotes being passed as part of the argument, but double quotes are stripped first. So, 'hello world' would result in a Python string of 'hello world', but "hello world" would result in hello world (which is probably what most people would want).Huntress
Since the process involves string parsing, bar=True in fabric command will passed as bar='True' which is not boolean valueMuskellunge
S
14

In Fabric 2, simply add the argument to your task function. For example, to pass the version argument to task deploy:

@task
def deploy(context, version):
    ...

Run it as follows:

fab -H host deploy --version v1.2.3

Fabric even documents the options automatically:

$ fab --help deploy
Usage: fab [--core-opts] deploy [--options] [other tasks here ...]

Docstring:
  none

Options:
  -v STRING, --version=STRING
Spencer answered 9/3, 2019 at 12:21 Comment(2)
is there a way to predefine the hosts in the function itself? Similar to @roles() tag where we can define list of hosts to run the task.Wisner
define them in a list.Troyes
S
7

Fabric 1.x arguments are understood with very basic string parsing, so you have to be a bit careful with how you send them.

Here are a few examples of different ways to pass arguments to the following test function:

@task
def test(*args, **kwargs):
    print("args:", args)
    print("named args:", kwargs)

$ fab "test:hello world"
('args:', ('hello world',))
('named args:', {})

$ fab "test:hello,world"
('args:', ('hello', 'world'))
('named args:', {})

$ fab "test:message=hello world"
('args:', ())
('named args:', {'message': 'hello world'})

$ fab "test:message=message \= hello\, world"
('args:', ())
('named args:', {'message': 'message = hello, world'})

I use double quote here to take the shell out of the equation, but single quotes may be better for some platforms. Also note the escapes for characters that fabric considers delimiters.

More details in the docs: http://docs.fabfile.org/en/1.14/usage/fab.html#per-task-arguments

Supposition answered 29/6, 2018 at 7:24 Comment(0)
C
2

You need to pass all Python variables as strings, especially if you are using sub-process to run the scripts, or you will get an error. You will need to convert the variables back to int/boolean types separately.

def print_this(var):
    print str(var)

fab print_this:'hello world'
fab print_this='hello'
fab print_this:'99'
fab print_this='True'
Cypress answered 17/4, 2016 at 23:2 Comment(0)
H
2

If someone is looking to pass parameters from one task to another in fabric2, just use the environment dictionary for that:

@task
def qa(ctx):
  ctx.config.run.env['counter'] = 22
  ctx.config.run.env['conn'] = Connection('qa_host')

@task
def sign(ctx):
  print(ctx.config.run.env['counter'])
  conn = ctx.config.run.env['conn']
  conn.run('touch mike_was_here.txt')

And run:

fab2 qa sign
Hominy answered 30/1, 2019 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.