Have you tried instantiating a context with the config from Fabric's connection? I haven't mixed invoke tasks and fabric tasks in the same module before, I'm surprised the same task decorator will work for both using `inv` on the command line and `fab` as well. If you have a task that only does local work inside your fabfile module, I'd recommend using conn.local instead of making it an invoke task. If you have an existing invoke task codebase, I would import that module from my fabfile module and run tasks with a locally created context, since you're not calling the task from the invoke cli.
``` tasks.py ==== from invoke.tasks import task @task def build(ctx): ctx.run('make artifact') fabfile.py ==== from fabric.tasks import task from invoke.context import Context from tasks import build @task(hosts=PROD) def deploy(conn): ctx = Context(config=conn.config) build(ctx) conn.put('artifact', '/app') ``` On Tue, Apr 2, 2019 at 2:04 AM Michel Albert <mic...@albert.lu> wrote: > > I understand the differences. The only traceback I got was the one I sent > earlier. This traceback is correct, only maybe a bit cryptic. > > So far, I managed to get some basic tasks ported to fabric2. > > However, this morning I ran into a new problem: > > I have a remote task (deploy) which depends on a local task (build) and I > want to be able to call the build step separately. But now I don't know how > to call "build" from the "deploy" task. The docs state to simply call the > function and forward the connection/context. But when calling from the > "deploy" task, I have a "Connection" instance, but I need a "Context" > instance to pass into the "build" task. Is there a way to get the Invoke > context from the Connection instance? Example: > > @task > def build(ctx): > ctx.run('make artifact') > > @task(hosts=PROD) > def deploy(conn): > build(?) # <- what do I need to pass onto build? "conn" won't work > conn.put('artifact', '/app') > > On Mon, Apr 1, 2019 at 9:33 PM Brandon Whaley <redkr...@gmail.com> wrote: >> >> There is no local attribute on invoke contexts, only on fabric >> connections (which inherits from invoke contexts). If this isn't what >> you're trying to do, could you provide some code examples that give >> you the traceback you're seeing? >> >> On Mon, Apr 1, 2019 at 1:07 PM Michel Albert <mic...@albert.lu> wrote: >> > >> > Ok. I think I will get it to work like that. >> > >> > But after fiddling around with it I found out that the type of the first >> > argument depends on whether a "hosts" argument was passed into the task >> > decorator or not. This was quite confusing. And the error is a bit >> > cryptic. When calling "local" on an invoke context, the following >> > AttributeError is thrown: >> > >> > Traceback (most recent call last): >> > File "/usr/lib/python3.7/site-packages/invoke/config.py", line 113, in >> > __getattr__ >> > return self._get(key) >> > File "/usr/lib/python3.7/site-packages/invoke/config.py", line 178, in >> > _get >> > value = self._config[key] >> > File "/usr/lib/python3.7/site-packages/invoke/config.py", line 169, in >> > __getitem__ >> > return self._get(key) >> > File "/usr/lib/python3.7/site-packages/invoke/config.py", line 178, in >> > _get >> > value = self._config[key] >> > KeyError: 'local' >> > >> > During handling of the above exception, another exception occurred: >> > >> > Traceback (most recent call last): >> > File "/home/exhuma/.local/bin/fab", line 10, in <module> >> > sys.exit(program.run()) >> > File "/usr/lib/python3.7/site-packages/invoke/program.py", line 363, in >> > run >> > self.execute() >> > File "/usr/lib/python3.7/site-packages/invoke/program.py", line 532, in >> > execute >> > executor.execute(*self.tasks) >> > File "/usr/lib/python3.7/site-packages/invoke/executor.py", line 129, in >> > execute >> > result = call.task(*args, **call.kwargs) >> > File "/usr/lib/python3.7/site-packages/invoke/tasks.py", line 128, in >> > __call__ >> > result = self.body(*args, **kwargs) >> > File "/home/exhuma/tmp/fabfile.py", line 8, in get_version >> > version = ctx.local('python setup.py --version').strip() >> > File "/usr/lib/python3.7/site-packages/invoke/config.py", line 125, in >> > __getattr__ >> > raise AttributeError(err) >> > AttributeError: No attribute or config key found for 'local' >> > >> > Valid keys: ['connect_kwargs', 'forward_agent', 'gateway', >> > 'inline_ssh_env', 'load_ssh_configs', 'port', 'run', 'runners', >> > 'ssh_config_path', 'sudo', 'tasks', 'timeouts', 'user'] >> > >> > Valid real attributes: ['cd', 'clear', 'config', 'cwd', 'from_data', >> > 'pop', 'popitem', 'prefix', 'run', 'setdefault', 'sudo', 'update'] >> > >> > >> > On Mon, Apr 1, 2019 at 5:37 PM Brandon Whaley <redkr...@gmail.com> wrote: >> >> >> >> Hi Mich, >> >> >> >> The connection object (you're using ctx in your examples) has a .local >> >> method that is just a pass-through to invoke.run. It's documented on >> >> the connection object's page: >> >> http://docs.fabfile.org/en/2.4/api/connection.html?highlight=local#fabric.connection.Connection.local >> >> >> >> On Mon, Apr 1, 2019 at 5:55 AM Michel Albert <mic...@albert.lu> wrote: >> >> > >> >> > Hi, >> >> > >> >> > >> >> > Consider the following fabric-1 task. For illustration I kept it really >> >> > short: >> >> > >> >> > @fab.task >> >> > def sample(): >> >> > version = fab.local('python setup.py --version') >> >> > fab.run('mkdir -p /snapshots/%s' % version.strip()) >> >> > >> >> > This task needs to run a local and remote command. I am now trying to >> >> > port this to fabric-2, and I can't figure out how I can implement this. >> >> > If I define the "hosts" variable in the task, then the first line will >> >> > be executed on the remote host as well, which I don't want. A naive >> >> > aproach which won't work: >> >> > >> >> > @task(hosts=PROD) >> >> > def sample(ctx): >> >> > version = ctx.run('python setup.py --version').strip() # <- this >> >> > won't work >> >> > ctx.run('mkdir -p /snapshots/%s' % version) >> >> > >> >> > At first I thought I would split the task into two, one for just local >> >> > commands and one for remote tasks, but then I am forced to pass in the >> >> > context, which will in turn cause it again to be run remotely: >> >> > >> >> > @task >> >> > def get_version(ctx): >> >> > version = ctx.run('python setup.py --version').strip() >> >> > return version >> >> > >> >> > @task(hosts=PROD) >> >> > def sample(ctx): >> >> > version = get_version(ctx) # <- this won't work >> >> > ctx.run('mkdir -p /snapshots/%s' % version) >> >> > >> >> > How can I accomplish something like this? And where is it noted in the >> >> > docs? In the current example on the "Upgrading from 1.x" page does not >> >> > have a single task mixing local with remote commands in any way. >> >> > >> >> > >> >> > Regards, >> >> > >> >> > >> >> > Mich >> >> > >> >> > _______________________________________________ >> >> > Fab-user mailing list >> >> > Fab-user@nongnu.org >> >> > https://lists.nongnu.org/mailman/listinfo/fab-user _______________________________________________ Fab-user mailing list Fab-user@nongnu.org https://lists.nongnu.org/mailman/listinfo/fab-user