A client I have insists the command fab doit('my_ssh_key') refresh('dev')
works on windows (updates the remote dev server).
So I tried the command in linux (mint), and got "bash: syntax error near unexpected token
('"`.
So I added quotes, fab "doit('my_ssh_key')" "refresh('dev')"
and I got the error message in the title (same as when I escaped the parentheses with slashes).
How do I get this to work?
Here is the fabfile. fabfile.py:
###################################################################
#
# Usage:
# fab doit(path_to_ssh_key) refresh('dev|staging')
# fab doit(path_to_ssh_key) maintenanceon('dev|staging')
# fab doit(path_to_ssh_key) maintenanceoff('dev|staging')
#
# fab doit(path_to_ssh_key) productionrefresh
#
# Example: fab doit('c:\users\tom\.ssh\id_rsa.pem') maintenanceon('dev')
#
# If you use a passphrase then add --prompt-for-passphrase
####################################################################
from fabric import task, Connection
@task
def doit(ctx, keypath):
ctx.user = 'django'
ctx.host = '<servername>'
ctx.connect_kwargs.key_filename = ''.format(keypath)
@task
def maintenanceon(ctx, server):
conn = Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs)
# create ln to maintenance file
print('maintenance on')
with conn.cd('/usr/share/nginx/html/'):
conn.run('sudo ln -sf /home/django/sites/{0}.<servername>/src/project/templates/maintenance.html {0}-maintenance.html'.format(server))
@task
def maintenanceoff(ctx, server):
conn = Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs)
# create ln to maintenance file
print('maintenance off')
with conn.cd('/usr/share/nginx/html/'):
conn.run('sudo unlink {}-maintenance.html'.format(server))
@task
def refresh(ctx, server):
env_command = '. /home/django/sites/{0}.<servername>.com/{0}/bin/activate'.format(server)
conn = Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs)
# set to maintenance mode
with conn.cd('/usr/share/nginx/html/'):
print('maintenance on')
conn.run('sudo ln -sf /home/django/sites/{0}.<servername>.com/src/project/templates/maintenance.html {0}-maintenance.html'.format(server))
# refresh install
with conn.cd('/home/django/sites/{}.<servername>.com/src/'.format(server)):
print('git pull')
conn.run('git pull')
# check requirements
with conn.cd('/home/django/sites/{}.<servername>.com/src/requirements/'.format(server)):
print('pip-sync')
conn.run(env_command + '&&' + 'pip-sync {}.txt'.format(server))
# run migrations and collectstatic
with conn.cd('/home/django/sites/{}.<servername>.com/src/project/'.format(server)):
print('migrate')
conn.run(env_command + '&&' + 'python manage.py migrate')
print('collecstatic')
conn.run(env_command + '&&' + 'python manage.py collectstatic --no-input')
# restart server
print('restart server')
conn.sudo('systemctl restart {}.service'.format(server), pty=True)
# maintenance mode off
with conn.cd('/usr/share/nginx/html/'):
print('maintenance off)')
conn.run('sudo unlink {}-maintenance.html'.format(server))
@task
def productionrefresh(ctx):
env_command = '. /home/django/sites/www.<servername>.com/www/bin/activate'
conn = Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs)
# set to maintenance mode
with conn.cd('/usr/share/nginx/html/'):
print('Set to maintenance mode')
conn.run('sudo ln -sf /home/django/sites/www.<servername>.com/src/project/templates/maintenance.html prod-maintenance.html')
# refresh install
with conn.cd('/home/django/sites/www.<servername>.com/src/'):
print('Git pull')
conn.run('git pull')
# check requirements
with conn.cd('/home/django/sites/www.<servername>.com/src/requirements/'):
print('pip-sync production.txt')
conn.run(env_command + '&&' + 'pip-sync production.txt')
# run migrations and collectstatic
with conn.cd('/home/django/sites/www.<servername>.com/src/project/'):
print('python manage.py migrate')
conn.run(env_command + '&&' + 'python manage.py migrate')
print('python manage.py collectstatic')
conn.run(env_command + '&&' + 'python manage.py collectstatic --no-input')
# restart server
print('restart production service')
conn.sudo('systemctl restart production.service', pty=True)
# maintenance mode off
with conn.cd('/usr/share/nginx/html/'):
print('maintenance off')
conn.run('sudo unlink prod-maintenance.html')
@task
def productioncollect(ctx):
env_command = '. /home/django/sites/www.<servername>.com/www/bin/activate'
conn = Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs)
with conn.cd('/home/django/sites/www.<servername>.com/src/project/'):
conn.run(env_command + '&&' + 'python manage.py collectstatic --no-input')
Update:
I followed RedKrieg's answer and got the following error:
maintenance on
Traceback (most recent call last):
File "/home/michael/projects/campaignfinances/venv/bin/fab", line 8, in <module>
sys.exit(program.run())
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/invoke/program.py", line 384, in run
self.execute()
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/invoke/program.py", line 566, in execute
executor.execute(*self.tasks)
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/invoke/executor.py", line 129, in execute
result = call.task(*args, **call.kwargs)
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/invoke/tasks.py", line 127, in __call__
result = self.body(*args, **kwargs)
File "/home/michael/projects/campaignfinances/fabfile.py", line 51, in refresh
conn.run('sudo ln -sf /home/django/sites/{0}.<servername>.com/src/project/templates/maintenance.html {0}-maintenance.html'.format(server))
File "<decorator-gen-3>", line 2, in run
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/fabric/connection.py", line 29, in opens
self.open()
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/fabric/connection.py", line 634, in open
self.client.connect(**kwargs)
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/paramiko/client.py", line 340, in connect
to_try = list(self._families_and_addresses(hostname, port))
File "/home/michael/projects/campaignfinances/venv/lib/python3.6/site-packages/paramiko/client.py", line 204, in _families_and_addresses
hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
File "/usr/lib/python3.6/socket.py", line 745, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
I got this error doing both fab doit --keypath='cf_key' refresh --server='dev'
and fab doit 'cf_key' refresh 'dev'
Your problem has nothing to do with fabric. Your client is lying to you because that syntax is never (and can never be) used with the fab command line tool. To pass arguments to a fab task in fabric2 (which you are using in your python code here) you must use invoke style task arguments. For your examples, the following would be examples of the correct syntax:
#positional arguments
fab doit 'c:\users\tom\.ssh\id_rsa.pem' refresh 'dev|staging'
#named arguments, equals is optional
fab doit --keypath='c:\users\tom\.ssh\id_rsa.pem' maintenanceon --server='dev|staging'
http://docs.pyinvoke.org/en/latest/concepts/invoking-tasks.html#task-command-line-arguments