sscarduzio
sscarduzio

Reputation: 6188

Why I cannot change env.hosts from within a function?

I really need this to work somehow:

from fabric.api import *
from fabric.contrib import *

def test():
  global env
  env.user = 'vagrant'
  env.hosts = ['127.0.0.1', ]
  env.port = 2222
  env.key_filename = "/Users/sscarduzio/.vagrant.d/insecure_private_key"
  run('ls /')

test case:

$ fab test
No hosts found. Please specify (single) host string for connection:

I can't figure out why it's ok to change the value of env.* outside a function and as soon as structure my code in functions (or classes) fabric ignores it.

Thanks!

Upvotes: 1

Views: 490

Answers (6)

sscarduzio
sscarduzio

Reputation: 6188

So, the answer was right in the docs. I didn't see it because Google always finds the old version of the docs, I don't know why.

The main issue is indeed with the propagation of the env.hosts (other env.* values seem to propagate normally.The solution to call a method with an arbitrary list of hosts was of invoking it using execute(<someFunction>, hosts=<someHostList>).

For example:

from fabric.api import env, run, execute
def f1():
  someList = ['remoteHost1','remoteHost2']
  execute(f2, hosts=someList)

def f2():
  run('ls /')

To be run with the command: $ fab f1.

EDIT: updated version

Upvotes: 1

Andrew Walker
Andrew Walker

Reputation: 42450

This isn't really a fabric problem at all and although you can solve the problem this way you're better not to. SSH really does have much better tools for managing this issue, and for scaling up to more complex setups.

Firstly setup an alternate SSH config file, or add this to your ~/.ssh/config

Host myvagrant
  HostName 127.0.0.1
  Port 2222
  User vagrant
  IdentityFile /Users/sscarduzio/.vagrant.d/insecure_private_key

At that point you should be able to ssh into myvagrant

$ ssh myvagrant

Or:

$ ssh -F .ssh_config myvagrant

Now your fabric code should read:

from fabric.api import *
env.use_ssh_config = True
#env.ssh_config_path = '.ssh_config'
@task
def f2():
    run('ls /')

Upvotes: 0

Alberto Meg&#237;a
Alberto Meg&#237;a

Reputation: 2255

With my Amazon machines I use:

from fabric.api import env, sudo

def set_env():
  env.host_string = "myuser@myhost"
  env.key_filename = "myfile.pem"

  # run commands
  sudo("ls /")

Upvotes: 1

glglgl
glglgl

Reputation: 91017

According to what I found, env needs item access instead of attributes.

Thus, do

from fabric.api import env, run

def test():
    env['user'] = 'vagrant'
    env['hosts'] = ['127.0.0.1', ]
    env['port'] = 2222
    env['key_filename'] = "/Users/sscarduzio/.vagrant.d/insecure_private_key"
    run('ls /')

I am not sure, however, if this information is right, and I haven't the ability to test it.

Upvotes: 0

lev
lev

Reputation: 4127

you should try something like this:

def test():
  with settings(user='vagrant', host_string='localhost',...):
      run('ls /')

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599490

Don't use import *, and don't use globals. There's no need for either.

from fabric.api import env, run

def test():
  env.user = 'vagrant'
  env.hosts = ['127.0.0.1', ]
  env.port = 2222
  env.key_filename = "/Users/sscarduzio/.vagrant.d/insecure_private_key"
  run('ls /')

Upvotes: 1

Related Questions