I want to use Fabric to deploy my web app code to development, staging and production servers. My fabfile:
def deploy_2_dev():
deploy(\'dev\')
def deploy_
You need to set host_string
an example would be:
from fabric.context_managers import settings as _settings
def _get_hardware_node(virtualized):
return "localhost"
def mystuff(virtualized):
real_host = _get_hardware_node(virtualized)
with _settings(
host_string=real_host):
run("echo I run on the host %s :: `hostname -f`" % (real_host, ))
Use roledefs
from fabric.api import env, run
env.roledefs = {
'test': ['localhost'],
'dev': ['user@dev.example.com'],
'staging': ['user@staging.example.com'],
'production': ['user@production.example.com']
}
def deploy():
run('echo test')
Choose role with -R:
$ fab -R test deploy
[localhost] Executing task 'deploy'
...
It's very simple. Just initialize the env.host_string variable and all of the following commands will be executed on this host.
from fabric.api import env, run
env.host_string = 'user@exmaple.com'
def foo:
run("hostname -f")
Using roles is currently considered to be the "proper" and "correct" way of doing this and is what you "should" do it.
That said, if you are like most of what you "would like" or "desire" is the ability to perform a "twisted syster" or switching target systems on the fly.
So for entertainment purposes only (!) the following example illustrates what many might consider to a risky, and yet somehow thoroughly satisfying, manoeuvre that goes something like this:
env.remote_hosts = env.hosts = ['10.0.1.6']
env.remote_user = env.user = 'bob'
env.remote_password = env.password = 'password1'
env.remote_host_string = env.host_string
env.local_hosts = ['127.0.0.1']
env.local_user = 'mark'
env.local_password = 'password2'
def perform_sumersault():
env_local_host_string = env.host_string = env.local_user + '@' + env.local_hosts[0]
env.password = env.local_password
run("hostname -f")
env.host_string = env.remote_host_string
env.remote_password = env.password
run("hostname -f")
Then running:
fab perform_sumersault
You can assign to env.hoststring
before executing a subtask. Assign to this global variable in a loop if you want to iterate over multiple hosts.
Unfortunately for you and me, fabric is not designed for this use case. Check out the main
function at http://github.com/bitprophet/fabric/blob/master/fabric/main.py to see how it works.
Was stuck on this myself, but finally figured it out. You simply can't set the env.hosts configuration from within a task. Each task is executed N times, once for each Host specified, so the setting is fundamentally outside of task scope.
Looking at your code above, you could simply do this:
@hosts('dev')
def deploy_dev():
deploy()
@hosts('staging')
def deploy_staging():
deploy()
def deploy():
# do stuff...
Which seems like it would do what you're intending.
Or you can write some custom code in the global scope that parses the arguments manually, and sets env.hosts before your task function is defined. For a few reasons, that's actually how I've set mine up.