1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

-p has been replaced by a required option. Various docs changes.

This commit is contained in:
Michael DeHaan 2012-03-01 22:10:47 -05:00
parent 4ce1f1dd5e
commit 847846af0e
7 changed files with 89 additions and 77 deletions

View file

@ -66,22 +66,22 @@ Example:
192.168.10.52 192.168.10.52
When running ansible commands, specific hosts are addressed by wildcard or group name. When running ansible commands, specific hosts are addressed by wildcard or group name.
The default pattern is '*', meaning all ansible hosts. This is required for all ansible commands.
-p '*.example.com' '*.example.com'
-p 'atlanta;raleigh' 'atlanta;raleigh'
-p 'database*;appserver*' 'database*;appserver*'
-p '192.168.10.50;192.168.10.52' '192.168.10.50;192.168.10.52'
Example: Massive Parallelism and Running Shell Commands Example: Massive Parallelism and Running Shell Commands
======================================================= =======================================================
Reboot all web servers in Atlanta, 10 at a time: Reboot all web servers in Atlanta, 10 at a time:
ssh-agent bash > ssh-agent bash
ssh-add ~/.ssh/id_rsa.pub > ssh-add ~/.ssh/id_rsa.pub
ansible -p "atlanta-web*" -f 10 -n command -a "/sbin/reboot" > ansible atlanta -a "/sbin/reboot" -f 10
The -f 10 specifies the usage of 10 simultaneous processes. The -f 10 specifies the usage of 10 simultaneous processes.
@ -98,15 +98,15 @@ them as template sources.
To just transfer a file directly to many different servers: To just transfer a file directly to many different servers:
ansible -n copy -a "/etc/hosts /tmp/hosts" > ansible atlanta copy -a "/etc/hosts /tmp/hosts"
To use templating, first run the setup module to put the template variables you would To use templating, first run the setup module to put the template variables you would
like to use on the remote host. Then use the template module to write the like to use on the remote host. Then use the template module to write the
files using the templates. Templates are written in Jinja2 format. files using the templates. Templates are written in Jinja2 format.
ansible -p webservers -n setup -a "favcolor=red ntp_server=192.168.1.1" > ansible webservers -m setup -a "favcolor=red ntp_server=192.168.1.1"
ansible -p webservers -n template -a "src=/srv/motd.j2 dest=/etc/motd" > ansible webservers -m template -a "src=/srv/motd.j2 dest=/etc/motd"
ansible -p webservers -n template -a "src=/srv/ntp.j2 dest=/etc/ntp.conf" > ansible webservers -m template -a "src=/srv/ntp.j2 dest=/etc/ntp.conf"
Need something like the fqdn in a template? If facter or ohai are installed, data from these projects Need something like the fqdn in a template? If facter or ohai are installed, data from these projects
will also be made available to the template engine, using 'facter_' and 'ohai_' prefixes for each. will also be made available to the template engine, using 'facter_' and 'ohai_' prefixes for each.
@ -116,7 +116,7 @@ Example: Software Deployment From Source Control
Deploy your webapp straight from git Deploy your webapp straight from git
ansible -p webservers -n git -a "repo=git://foo dest=/srv/myapp version=HEAD" > ansible webservers -m git -a "repo=git://foo dest=/srv/myapp version=HEAD"
Other Modules Other Modules
============= =============

View file

@ -38,37 +38,33 @@ class Cli(object):
pass pass
def runner(self): def runner(self):
parser = OptionParser() parser = OptionParser(usage = 'ansible <host-pattern> [options]')
parser.add_option("-a", "--args", dest="module_args", parser.add_option("-a", "--args", dest="module_args",
help="module arguments", default=C.DEFAULT_MODULE_ARGS) help="module arguments", default=C.DEFAULT_MODULE_ARGS)
parser.add_option('-f','--forks', dest='forks', default=C.DEFAULT_FORKS, type='int', parser.add_option('-f','--forks', dest='forks', default=C.DEFAULT_FORKS, type='int',
help='set the number of forks to start up') help='number of parallel processes to use')
parser.add_option("-p", "--host-pattern", dest="hosts", parser.add_option("-i", "--inventory-file", dest="inventory",
help="hostname glob or group name", default=C.DEFAULT_PATTERN) help="inventory host file", default=C.DEFAULT_HOST_LIST)
parser.add_option("-i", "--inventory", dest="inventory",
help="inventory host list", default=C.DEFAULT_HOST_LIST)
parser.add_option("-k", "--ask-pass", default=False, action="store_true", parser.add_option("-k", "--ask-pass", default=False, action="store_true",
help="ask the user to input the ssh password for connecting") help="ask for SSH password")
parser.add_option("-m", "--module-path", dest="module_path", parser.add_option("-M", "--module-path", dest="module_path",
help="path to module library", default=C.DEFAULT_MODULE_PATH) help="path to module library", default=C.DEFAULT_MODULE_PATH)
parser.add_option("-n", "--name", dest="module_name", parser.add_option("-m", "--module-name", dest="module_name",
help="module name to execute", default=None) help="module name to execute", default=C.DEFAULT_MODULE_NAME)
parser.add_option('-o', '--one-line', dest='one_line', action='store_true', parser.add_option('-o', '--one-line', dest='one_line', action='store_true',
help="try to print output on one line") help="condense output")
parser.add_option('-t', '--tree', dest='tree', default=None, parser.add_option('-t', '--tree', dest='tree', default=None,
help="if specified, a directory name to save output to, one file per host") help="log output to this directory")
parser.add_option('-T', '--timeout', default=C.DEFAULT_TIMEOUT, type='int', parser.add_option('-T', '--timeout', default=C.DEFAULT_TIMEOUT, type='int',
dest='timeout', help="set the timeout in seconds for ssh") dest='timeout', help="set the SSH timeout in seconds")
parser.add_option('-u', '--user', default=C.DEFAULT_REMOTE_USER, parser.add_option('-u', '--user', default=C.DEFAULT_REMOTE_USER,
dest='remote_user', help='set the default username') dest='remote_user', help='connect as this user')
options, args = parser.parse_args() options, args = parser.parse_args()
if options.module_name is None: if len(args) == 0 or len(args) > 1:
print >> sys.stderr, "-n is required" parser.print_help()
sys.exit(1) sys.exit(1)
pattern = args[0]
# TODO: more shell like splitting on module_args would
# be a good idea
sshpass = None sshpass = None
if options.ask_pass: if options.ask_pass:
@ -85,7 +81,7 @@ class Cli(object):
host_list=options.inventory, host_list=options.inventory,
timeout=options.timeout, timeout=options.timeout,
forks=options.forks, forks=options.forks,
pattern=options.hosts, pattern=pattern,
verbose=True, verbose=True,
) )
return runner return runner
@ -95,6 +91,10 @@ class Cli(object):
# if specifying output destination (aka tree output saves), create the # if specifying output destination (aka tree output saves), create the
# directory to output to # directory to output to
if results is None:
print >> sys.stderr, "No hosts matched"
sys.exit(1)
options = self.options options = self.options
# TODO: split into function # TODO: split into function
@ -117,64 +117,64 @@ class Cli(object):
for hostname in sorted(results['contacted']): for hostname in sorted(results['contacted']):
result = results['contacted'][hostname] result = results['contacted'][hostname]
# TODO: refactor
rc = 0 rc = 0
msg = ''
failed = False failed = False
stdout = None stdout = None
stderr = None stderr = None
traceback = None traceback = None
error = None
if type(result) == dict: if type(result) == dict:
failed = result.get('failed', 0) failed = result.get('failed', 0)
msg = result.get('msg', '')
if module_name == 'command': if module_name == 'command':
# TODO: refactor
rc = result.get('rc',0) rc = result.get('rc',0)
stdout = result.get('stdout', '') stdout = result.get('stdout', '')
stderr = result.get('stderr', '') stderr = result.get('stderr', '')
traceback = result.get('traceback', '') traceback = result.get('traceback', '')
error = result.get('error', '')
# detect and show failures, if any
if rc != 0 or failed:
msg = "Error: %s: \n" % hostname
if stdout:
msg += stdout
if stderr:
msg += stderr
if traceback:
msg += traceback
if error:
msg += error
print >> sys.stderr, msg
continue
if options.one_line: if options.one_line:
# try to print everything on one line, but don't strip newlines # try to print everything on one line, but don't strip newlines
# if the command output happend to be too long # if the command output happend to be too long
if module_name == 'command': if module_name == 'command':
msg = "(stdout) %s" % stdout if not failed:
if stderr.rstrip() != '': buf = "(stdout) %s" % stdout
msg = "(stdout) %s (stderr) %s" % (stdout,stderr) if stderr.rstrip() != '':
print "%s | rc=%s | %s" % ( buf = "(stdout) %s (stderr) %s" % (stdout,stderr)
hostname, rc, msg print "%s | rc=%s | %s" % (
) hostname, rc, buf
)
else:
print "%s | (error) %s" % (hostname, msg)
else: else:
print "%s | %s" % (hostname, result) print "%s | %s" % (hostname, result)
else: else:
# summarize response from command in multiple lines # summarize response from command in multiple lines
buf = ''
if module_name == 'command': if module_name == 'command':
buf = '' if not failed:
buf += "%s | rc=%s >>\n" % (hostname, rc) buf += "%s | rc=%s >>\n" % (hostname, rc)
else:
buf += "%s | rc=%s | FAILED >>\n" % (hostname, rc)
buf += stdout buf += stdout
if stderr: if stderr:
buf += stderr buf += stderr
if msg:
buf += msg
print buf print buf
if options.tree:
path = os.path.join(options.tree, hostname)
fd = open(path, "w+")
fd.write(buf)
fd.close()
else: else:
print "%s >>" % hostname if not failed:
print json.dumps(result, indent=4, sort_keys=True) buf += "%s >>" % hostname
else:
buf += "%s | FAILED >>" % hostname
buf += json.dumps(result, indent=4, sort_keys=True)
if options.tree:
path = os.path.join(options.tree, hostname)
fd = open(path, "w+")
fd.write(buf)
fd.close()
if len(results['dark'].keys()) > 0: if len(results['dark'].keys()) > 0:
print >> sys.stderr, "*** Hosts which could not be contacted or did not respond: ***" print >> sys.stderr, "*** Hosts which could not be contacted or did not respond: ***"

View file

@ -12,7 +12,7 @@ ansible - run a command somewhere else
SYNOPSIS SYNOPSIS
-------- --------
ansible [-f forks] [-p pattern ] [-n module_name] [-a args] ansible <host-pattern> [-f forks] [-m module_name] [-a args]
DESCRIPTION DESCRIPTION
@ -22,6 +22,15 @@ DESCRIPTION
SSH. SSH.
ARGUMENTS
---------
*hostspec*
A name of a group in the inventory file, a shell-like glob selecting hosts in inventory
file, or any combination of the two seperated by semicolons.
OPTIONS OPTIONS
------- -------
@ -36,16 +45,11 @@ Path to the inventory hosts file, which defaults to /etc/ansible/hosts.
Level of parallelism. Specify as an integer, the default is 5. Level of parallelism. Specify as an integer, the default is 5.
*-n*, *--name*:: *-m*, *--module-name*::
Module name to execute. Module name to execute.
*-a*, *--args*::
Arguments to module, as a single string.
*-p*, *--pattern*:: *-p*, *--pattern*::
Hostname pattern. Accepts shell-like globs which can be seperated with ";" Hostname pattern. Accepts shell-like globs which can be seperated with ";"
@ -89,8 +93,9 @@ Ansible is released under the terms of the GPLv3 License.
SEE ALSO SEE ALSO
-------- --------
Ansible home page: <https://github.com/mpdehaan/ansible/>
*ansible-modules*(5), *ansible-modules*(5),
*ansible-playbook*(5), *ansible-playbook*(5),
Ansible home page: <https://github.com/mpdehaan/ansible/>

View file

@ -19,8 +19,8 @@
# control side (aka 'overlord') # control side (aka 'overlord')
DEFAULT_HOST_LIST = '/etc/ansible/hosts' DEFAULT_HOST_LIST = '/etc/ansible/hosts'
DEFAULT_MODULE_PATH = '/usr/share/ansible' DEFAULT_MODULE_PATH = '/usr/share/ansible'
DEFAULT_MODULE_NAME = 'ping' DEFAULT_MODULE_NAME = 'command'
DEFAULT_PATTERN = '*' DEFAULT_PATTERN = None
DEFAULT_FORKS = 3 DEFAULT_FORKS = 3
DEFAULT_MODULE_ARGS = '' DEFAULT_MODULE_ARGS = ''
DEFAULT_TIMEOUT = 10 DEFAULT_TIMEOUT = 10

View file

@ -152,6 +152,11 @@ class PlayBook(object):
) )
results = runner.run() results = runner.run()
# if no hosts are matched, carry on, unlike /bin/ansible
# which would warn you about this
if results is None:
results = {}
# walk through the results and build up # walk through the results and build up
# summary information about successes and # summary information about successes and
# failures. TODO: split into subfunction # failures. TODO: split into subfunction

View file

@ -326,6 +326,8 @@ class Runner(object):
# find hosts that match the pattern # find hosts that match the pattern
hosts = self.match_hosts(self.pattern) hosts = self.match_hosts(self.pattern)
if len(hosts) == 0:
return None
# attack pool of hosts in N forks # attack pool of hosts in N forks
# _executor_hook does all of the work # _executor_hook does all of the work

View file

@ -45,13 +45,13 @@ try:
except (OSError, IOError), e: except (OSError, IOError), e:
print json.dumps({ print json.dumps({
"failed": 1, "failed": 1,
"error": str(e), "msg": str(e),
}) })
sys.exit(1) sys.exit(1)
except: except:
print json.dumps({ print json.dumps({
"failed" : 1, "failed" : 1,
"traceback" : traceback.format_exc() "msg" : traceback.format_exc()
}) })
sys.exit(1) sys.exit(1)