alexarsh
alexarsh

Reputation: 5391

running fabric script locally

I have a django app and I wrote a fabric script that installs my app on deployment server (Cent OS 5).

Now I want to run the same fabric script locally on the deployment server.

Is there a way to do it without supplying ssh user and password?

I mean just with "-H localhost"?

Thanks, Alex A.

Upvotes: 43

Views: 17218

Answers (6)

dbainbridge
dbainbridge

Reputation: 1202

A modified version of Varun's answer that takes into account local not capturing stdout/stderr. Without specifying capture=True you would not be able to get results from local.

from fabric.operations import local, run
from fabric.api import task
from fabric.state import env

def local_run(*args):
    return local(args[0], capture=True)

@task
def localhost():
    env.run = local_run
    env.hosts = ['localhost']

@task
def remote():
    env.run = run
    env.hosts = ['some.remote.host']

@task
def install():
    env.run('deploymentcmd')

Upvotes: 0

Aníbal Rivero
Aníbal Rivero

Reputation: 310

First, make sure you can ssh into your localhost without a password:

$ ssh-copy-id localhost

And then just run it as you said, with the -H localhost command line option

Upvotes: 3

Eugene Leonovich
Eugene Leonovich

Reputation: 924

You can run ssh server on your local machine to be able to ssh to localhost. And then just run scripts with "-H localhost". Works perfectly for me.

Upvotes: 2

Pieter Ennes
Pieter Ennes

Reputation: 2409

Slightly less elegant than Varun's answer, but maybe more practical by defaulting to run on the local machine unless another environment selector is given.

from fabric.api import *

# default to running on localhost
env.hosts = ["localhost"]

DEPLOYMENT_PATH = "/some/path/{}/"

def local_or_remote(*args, **kwargs):
    func = local if env.host == "localhost" else run
    return func(*args, **kwargs)


@task
def live():
    """
    Select live environment
    """
    env.hosts = ["host1", "host2"]
    env.path = DEPLOYMENT_PATH.format("live")


@task
def beta():
    """
    Select beta environment
    """
    env.hosts = ["host1", "host2"]
    env.path = DEPLOYMENT_PATH.format("beta")


@task
def host_info():
    local_or_remote("uname -a")

Then run locally as:

fab host_info

or remotely with:

fab live host_info

PS. Here is the Github issue on this topic.

Upvotes: 4

Varun Katta
Varun Katta

Reputation: 6836

Yes, you can run fab locally by using method local instead of run. What I do typically is have methods for setting up the environment, and call these methods first before calling the actual task. Let me illustrate this with an example for your specific question

fabfile.py

    from fabric.operations import local as lrun, run
    from fabric.api import task
    from fabric.state import env

    @task
    def localhost():
        env.run = lrun
        env.hosts = ['localhost']

    @task
    def remote():
        env.run = run
        env.hosts = ['some.remote.host']

    @task
    def install():
        env.run('deploymentcmd')

And based on the environment, you can do the following

Install on localhost:

    fab localhost install

Install on remote machine:

    fab remote install

Upvotes: 80

xuhcc
xuhcc

Reputation: 2460

I am using another trick for executing remote task locally:

from fabric.api import run, sudo, local
from contextlib import contextmanager

@contextmanager
def locally():
    global run
    global sudo
    global local
    _run, _sudo = run, sudo
    run = sudo = local
    yield
    run, sudo = _run, _sudo

def local_task():
    with locally():
        run("ls -la")

Upvotes: 7

Related Questions