Commit 1fb830fb by Augustus Kling

Merge remote-tracking branch 'upstream/devel' into locale

parents 6b75e751 2060ae55
...@@ -24,7 +24,9 @@ docs/man/man3/* ...@@ -24,7 +24,9 @@ docs/man/man3/*
*.sublime-project *.sublime-project
*.sublime-workspace *.sublime-workspace
# docsite stuff... # docsite stuff...
docsite/rst/modules docsite/rst/modules_by_category.rst
docsite/rst/list_of_*.rst
docsite/rst/*_module.rst
docsite/*.html docsite/*.html
docsite/_static/*.gif docsite/_static/*.gif
docsite/_static/*.png docsite/_static/*.png
......
...@@ -3,7 +3,40 @@ Ansible Changes By Release ...@@ -3,7 +3,40 @@ Ansible Changes By Release
## 1.5 "Love Walks In" - Release pending! ## 1.5 "Love Walks In" - Release pending!
Major features/changes:
* when_foo which was previously deprecated is now removed, use "when:" instead. Code generates appropriate error suggestion.
* include + with_items which was previously deprecated is now removed, ditto. Use with_nested / with_together, etc.
* only_if, which is much older than when_foo and was deprecated, is similarly removed.
* ssh connection plugin is now more efficient if you add 'pipelining=True' in ansible.cfg under [ssh_connection], see example.cfg
New modules:
* Details pending
Misc:
* no_reboot is now defaulted to "no" in the ec2_ami module to ensure filesystem consistency in the resulting AMI. * no_reboot is now defaulted to "no" in the ec2_ami module to ensure filesystem consistency in the resulting AMI.
* sysctl module overhauled
* authorized_key module overhauled
* synchronized module now handles local transport better
* apt_key module now ignores case on keys
* zypper_repository now skips on check mode
* file module now responds to force behavior when dealing with hardlinks
* new lookup plugin 'csvfile'
* fixes to allow hash_merge behavior to work with dynamic inventory
* mysql module will use port argument on dump/import
* subversion module now ignores locale to better intercept status messages
* rax api_key argument is no longer logged
* backwards/forwards compatibility for OpenStack modules, 'quantum' modules grok neutron renaming
* hosts properly uniqueified if appearing in redundant groups
* hostname module support added for ScientificLinux
* various other bug fixes
## 1.4.4 "Could This Be Magic" - January 6, 2014
- fixed a minor issue with newer versions of pip dropping the "use-mirrors" parameter.
## 1.4.3 "Could This Be Magic" - December 20, 2013 ## 1.4.3 "Could This Be Magic" - December 20, 2013
......
...@@ -32,8 +32,10 @@ Sharing A Feature Idea ...@@ -32,8 +32,10 @@ Sharing A Feature Idea
If you have an idea for a new feature, you can open a new ticket at If you have an idea for a new feature, you can open a new ticket at
[github.com/ansible/ansible](https://github.com/ansible/ansible), though in general we like to [github.com/ansible/ansible](https://github.com/ansible/ansible), though in general we like to
talk about feature ideas first and bring in lots of people into the discussion. Consider stopping talk about feature ideas first and bring in lots of people into the discussion. Consider stopping
by the [Ansible project mailing list](https://groups.google.com/forum/#!forum/ansible-project) or #ansible by the
on irc.freenode.net. [Ansible project mailing list](https://groups.google.com/forum/#!forum/ansible-project) ([Subscribe](https://groups.google.com/forum/#!forum/ansible-project/join))
or #ansible on irc.freenode.net. There is an overview about more mailing lists
later in this document.
Helping with Documentation Helping with Documentation
-------------------------- --------------------------
......
...@@ -64,9 +64,6 @@ all: clean python ...@@ -64,9 +64,6 @@ all: clean python
tests: tests:
PYTHONPATH=./lib ANSIBLE_LIBRARY=./library $(NOSETESTS) -d -v PYTHONPATH=./lib ANSIBLE_LIBRARY=./library $(NOSETESTS) -d -v
# To force a rebuild of the docs run 'touch VERSION && make docs'
docs: $(MANPAGES) modulepages
authors: authors:
sh hacking/authors.sh sh hacking/authors.sh
...@@ -127,7 +124,7 @@ install: ...@@ -127,7 +124,7 @@ install:
sdist: clean docs sdist: clean docs
$(PYTHON) setup.py sdist -t MANIFEST.in $(PYTHON) setup.py sdist -t MANIFEST.in
rpmcommon: sdist rpmcommon: $(MANPAGES) sdist
@mkdir -p rpm-build @mkdir -p rpm-build
@cp dist/*.gz rpm-build/ @cp dist/*.gz rpm-build/
@sed -e 's#^Version:.*#Version: $(VERSION)#' -e 's#^Release:.*#Release: $(RPMRELEASE)%{?dist}#' $(RPMSPEC) >rpm-build/$(NAME).spec @sed -e 's#^Version:.*#Version: $(VERSION)#' -e 's#^Release:.*#Release: $(RPMRELEASE)%{?dist}#' $(RPMSPEC) >rpm-build/$(NAME).spec
...@@ -172,11 +169,6 @@ deb: debian ...@@ -172,11 +169,6 @@ deb: debian
# for arch or gentoo, read instructions in the appropriate 'packaging' subdirectory directory # for arch or gentoo, read instructions in the appropriate 'packaging' subdirectory directory
modulepages: webdocs: $(MANPAGES)
PYTHONPATH=./lib $(PYTHON) hacking/module_formatter.py -A $(VERSION) -t man -o docs/man/man3/ --module-dir=library --template-dir=hacking/templates # --verbose
# because this requires Sphinx it is not run as part of every build, those building the RPM and so on can ignore this
webdocs:
(cd docsite/; make docs) (cd docsite/; make docs)
...@@ -88,7 +88,7 @@ A brief description of the role goes here. ...@@ -88,7 +88,7 @@ A brief description of the role goes here.
Requirements Requirements
------------ ------------
Any pre-requisites that may not be covered by the ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables Role Variables
-------------- --------------
...@@ -135,8 +135,10 @@ def build_option_parser(action): ...@@ -135,8 +135,10 @@ def build_option_parser(action):
the user wants to execute. the user wants to execute.
""" """
parser = OptionParser() usage = "usage: %%prog [%s] [--help] [options] ..." % "|".join(VALID_ACTIONS)
parser.set_usage("usage: %%prog [%s] [options] ..." % "|".join(VALID_ACTIONS)) epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
OptionParser.format_epilog = lambda self, formatter: self.epilog
parser = OptionParser(usage=usage, epilog=epilog)
if not action: if not action:
parser.print_help() parser.print_help()
...@@ -241,8 +243,12 @@ def api_lookup_role_by_name(api_server, role_name): ...@@ -241,8 +243,12 @@ def api_lookup_role_by_name(api_server, role_name):
role_name = urllib.quote(role_name) role_name = urllib.quote(role_name)
try: try:
user_name,role_name = role_name.split(".", 1) parts = role_name.split(".")
user_name = ".".join(parts[0:-1])
role_name = parts[-1]
print " downloading role '%s', owned by %s" % (role_name, user_name)
except: except:
parser.print_help()
print "Invalid role name (%s). You must specify username.rolename" % role_name print "Invalid role name (%s). You must specify username.rolename" % role_name
sys.exit(1) sys.exit(1)
...@@ -481,7 +487,7 @@ def install_role(role_name, role_version, role_filename, options): ...@@ -481,7 +487,7 @@ def install_role(role_name, role_version, role_filename, options):
# Action functions # Action functions
#------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------
def execute_init(args, options): def execute_init(args, options, parser):
""" """
Executes the init action, which creates the skeleton framework Executes the init action, which creates the skeleton framework
of a role that complies with the galaxy metadata format. of a role that complies with the galaxy metadata format.
...@@ -513,6 +519,7 @@ def execute_init(args, options): ...@@ -513,6 +519,7 @@ def execute_init(args, options):
"been modified there already." "been modified there already."
sys.exit(1) sys.exit(1)
except Exception, e: except Exception, e:
parser.print_help()
print "No role name specified for init" print "No role name specified for init"
sys.exit(1) sys.exit(1)
...@@ -574,7 +581,7 @@ def execute_init(args, options): ...@@ -574,7 +581,7 @@ def execute_init(args, options):
f.close() f.close()
print "%s was created successfully" % role_name print "%s was created successfully" % role_name
def execute_info(args, options): def execute_info(args, options, parser):
""" """
Executes the info action. This action prints out detailed Executes the info action. This action prints out detailed
information about an installed role as well as info available information about an installed role as well as info available
...@@ -583,7 +590,7 @@ def execute_info(args, options): ...@@ -583,7 +590,7 @@ def execute_info(args, options):
pass pass
def execute_install(args, options): def execute_install(args, options, parser):
""" """
Executes the installation action. The args list contains the Executes the installation action. The args list contains the
roles to be installed, unless -f was specified. The list of roles roles to be installed, unless -f was specified. The list of roles
...@@ -598,11 +605,13 @@ def execute_install(args, options): ...@@ -598,11 +605,13 @@ def execute_install(args, options):
if len(args) == 0 and not role_file: if len(args) == 0 and not role_file:
# the user needs to specify one of either --role-file # the user needs to specify one of either --role-file
# or specify a single user/role name # or specify a single user/role name
parser.print_help()
print "You must specify a user/role name or a roles file" print "You must specify a user/role name or a roles file"
sys.exit() sys.exit()
elif len(args) == 1 and role_file: elif len(args) == 1 and role_file:
# using a role file is mutually exclusive of specifying # using a role file is mutually exclusive of specifying
# the role name on the command line # the role name on the command line
parser.print_help()
print "Please specify a user/role name, or a roles file, but not both" print "Please specify a user/role name, or a roles file, but not both"
sys.exit(1) sys.exit(1)
...@@ -695,13 +704,14 @@ def execute_install(args, options): ...@@ -695,13 +704,14 @@ def execute_install(args, options):
exit_without_ignore(options) exit_without_ignore(options)
sys.exit(0) sys.exit(0)
def execute_remove(args, options): def execute_remove(args, options, parser):
""" """
Executes the remove action. The args list contains the list Executes the remove action. The args list contains the list
of roles to be removed. This list can contain more than one role. of roles to be removed. This list can contain more than one role.
""" """
if len(args) == 0: if len(args) == 0:
parser.print_help()
print 'You must specify at least one role to remove.' print 'You must specify at least one role to remove.'
sys.exit() sys.exit()
...@@ -715,7 +725,7 @@ def execute_remove(args, options): ...@@ -715,7 +725,7 @@ def execute_remove(args, options):
print '%s is not installed, skipping.' % role print '%s is not installed, skipping.' % role
sys.exit(0) sys.exit(0)
def execute_list(args, options): def execute_list(args, options, parser):
""" """
Executes the list action. The args list can contain zero Executes the list action. The args list can contain zero
or one role. If one is specified, only that role will be or one role. If one is specified, only that role will be
...@@ -747,10 +757,12 @@ def execute_list(args, options): ...@@ -747,10 +757,12 @@ def execute_list(args, options):
roles_path = get_opt(options, 'roles_path') roles_path = get_opt(options, 'roles_path')
roles_path = os.path.expanduser(roles_path) roles_path = os.path.expanduser(roles_path)
if not os.path.exists(roles_path): if not os.path.exists(roles_path):
parser.print_help()
print "The path %s does not exist. Please specify a valid path with --roles-path" % roles_path print "The path %s does not exist. Please specify a valid path with --roles-path" % roles_path
sys.exit(1) sys.exit(1)
elif not os.path.isdir(roles_path): elif not os.path.isdir(roles_path):
print "%s exists, but it is not a directory. Please specify a valid path with --roles-path" % roles_path print "%s exists, but it is not a directory. Please specify a valid path with --roles-path" % roles_path
parser.print_help()
sys.exit(1) sys.exit(1)
path_files = os.listdir(roles_path) path_files = os.listdir(roles_path)
for path_file in path_files: for path_file in path_files:
...@@ -777,7 +789,7 @@ def main(): ...@@ -777,7 +789,7 @@ def main():
# execute the desired action # execute the desired action
if 1: #try: if 1: #try:
fn = globals()["execute_%s" % action] fn = globals()["execute_%s" % action]
fn(args, options) fn(args, options, parser)
#except KeyError, e: #except KeyError, e:
# print "Error: %s is not a valid action. Valid actions are: %s" % (action, ", ".join(VALID_ACTIONS)) # print "Error: %s is not a valid action. Valid actions are: %s" % (action, ", ".join(VALID_ACTIONS))
# sys.exit(1) # sys.exit(1)
......
...@@ -270,4 +270,7 @@ if __name__ == "__main__": ...@@ -270,4 +270,7 @@ if __name__ == "__main__":
except errors.AnsibleError, e: except errors.AnsibleError, e:
display("ERROR: %s" % e, color='red', stderr=True) display("ERROR: %s" % e, color='red', stderr=True)
sys.exit(1) sys.exit(1)
except KeyboardInterrupt, ke:
display("ERROR: interrupted", color='red', stderr=True)
sys.exit(1)
...@@ -45,23 +45,18 @@ import sys ...@@ -45,23 +45,18 @@ import sys
import datetime import datetime
import socket import socket
from ansible import utils from ansible import utils
from ansible.utils import cmd_functions
DEFAULT_REPO_TYPE = 'git' DEFAULT_REPO_TYPE = 'git'
DEFAULT_PLAYBOOK = 'local.yml' DEFAULT_PLAYBOOK = 'local.yml'
PLAYBOOK_ERRORS = {1: 'File does not exist', PLAYBOOK_ERRORS = {1: 'File does not exist',
2: 'File is not readable'} 2: 'File is not readable'}
VERBOSITY=0
def _run(cmd): def increment_debug(option, opt, value, parser):
print >>sys.stderr, "Running: '%s'" % cmd global VERBOSITY
cmd = subprocess.Popen(cmd, shell=True, VERBOSITY += 1
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, err) = cmd.communicate()
print out
if cmd.returncode != 0:
print >>sys.stderr, err
return cmd.returncode, out
def try_playbook(path): def try_playbook(path):
if not os.path.exists(path): if not os.path.exists(path):
...@@ -112,6 +107,8 @@ def main(args): ...@@ -112,6 +107,8 @@ def main(args):
'not be updated') 'not be updated')
parser.add_option('-d', '--directory', dest='dest', default=None, parser.add_option('-d', '--directory', dest='dest', default=None,
help='directory to checkout repository to') help='directory to checkout repository to')
#parser.add_option('-l', '--live', default=True, action='store_live',
# help='Print the ansible-playbook output while running')
parser.add_option('-U', '--url', dest='url', default=None, parser.add_option('-U', '--url', dest='url', default=None,
help='URL of the playbook repository') help='URL of the playbook repository')
parser.add_option('-C', '--checkout', dest='checkout', parser.add_option('-C', '--checkout', dest='checkout',
...@@ -119,6 +116,9 @@ def main(args): ...@@ -119,6 +116,9 @@ def main(args):
'Defaults to behavior of repository module.') 'Defaults to behavior of repository module.')
parser.add_option('-i', '--inventory-file', dest='inventory', parser.add_option('-i', '--inventory-file', dest='inventory',
help="location of the inventory host file") help="location of the inventory host file")
parser.add_option('-v', '--verbose', default=False, action="callback",
callback=increment_debug,
help='Pass -vvvv to ansible-playbook')
parser.add_option('-m', '--module-name', dest='module_name', parser.add_option('-m', '--module-name', dest='module_name',
default=DEFAULT_REPO_TYPE, default=DEFAULT_REPO_TYPE,
help='Module name used to check out repository. ' help='Module name used to check out repository. '
...@@ -141,8 +141,14 @@ def main(args): ...@@ -141,8 +141,14 @@ def main(args):
inv_opts = 'localhost,' inv_opts = 'localhost,'
limit_opts = 'localhost:%s:127.0.0.1' % hostname limit_opts = 'localhost:%s:127.0.0.1' % hostname
base_opts = '-c local --limit "%s"' % limit_opts
repo_opts = "name=%s dest=%s" % (options.url, options.dest) repo_opts = "name=%s dest=%s" % (options.url, options.dest)
if VERBOSITY == 0:
base_opts = '-c local --limit "%s"' % limit_opts
elif VERBOSITY > 0:
debug_level = ''.join([ "v" for x in range(0, VERBOSITY) ])
base_opts = '-%s -c local --limit "%s"' % (debug_level, limit_opts)
if options.checkout: if options.checkout:
repo_opts += ' version=%s' % options.checkout repo_opts += ' version=%s' % options.checkout
path = utils.plugins.module_finder.find_plugin(options.module_name) path = utils.plugins.module_finder.find_plugin(options.module_name)
...@@ -152,7 +158,10 @@ def main(args): ...@@ -152,7 +158,10 @@ def main(args):
cmd = 'ansible all -i "%s" %s -m %s -a "%s"' % ( cmd = 'ansible all -i "%s" %s -m %s -a "%s"' % (
inv_opts, base_opts, options.module_name, repo_opts inv_opts, base_opts, options.module_name, repo_opts
) )
rc, out = _run(cmd)
# RUN THE CHECKOUT COMMAND
rc, out, err = cmd_functions.run_cmd(cmd, live=True)
if rc != 0: if rc != 0:
if options.force: if options.force:
print "Unable to update repository. Continuing with (forced) run of playbook." print "Unable to update repository. Continuing with (forced) run of playbook."
...@@ -172,7 +181,9 @@ def main(args): ...@@ -172,7 +181,9 @@ def main(args):
if options.inventory: if options.inventory:
cmd += ' -i "%s"' % options.inventory cmd += ' -i "%s"' % options.inventory
os.chdir(options.dest) os.chdir(options.dest)
rc, out = _run(cmd)
# RUN THE PLAYBOOK COMMAND
rc, out, err = cmd_functions.run_cmd(cmd, live=True)
if options.purge: if options.purge:
os.chdir('/') os.chdir('/')
......
'\" t '\" t
.\" Title: ansible .\" Title: ansible
.\" Author: [see the "AUTHOR" section] .\" Author: :doctype:manpage
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/> .\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
.\" Date: 11/27/2013 .\" Date: 01/02/2014
.\" Manual: System administration commands .\" Manual: System administration commands
.\" Source: Ansible 1.4.1 .\" Source: Ansible 1.5
.\" Language: English .\" Language: English
.\" .\"
.TH "ANSIBLE" "1" "11/27/2013" "Ansible 1\&.4\&.1" "System administration commands" .TH "ANSIBLE" "1" "01/03/2014" "Ansible 1\&.5" "System administration commands"
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
.\" * set default formatting .\" * set default formatting
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
...@@ -25,7 +25,7 @@ ansible-pull \- set up a remote copy of ansible on each managed node ...@@ -25,7 +25,7 @@ ansible-pull \- set up a remote copy of ansible on each managed node
ansible \-d DEST \-U URL [options] [ <filename\&.yml> ] ansible \-d DEST \-U URL [options] [ <filename\&.yml> ]
.SH "DESCRIPTION" .SH "DESCRIPTION"
.sp .sp
\fBAnsible\fR is an extra\-simple tool/framework/API for doing \'remote things\' over SSH\&. \fBAnsible\fR is an extra\-simple tool/framework/API for doing \*(Aqremote things\*(Aq over SSH\&.
.sp .sp
Use ansible\-pull to set up a remote copy of ansible on each managed node, each set to run via cron and update playbook source via a source repository\&. This inverts the default \fBpush\fR architecture of ansible into a \fBpull\fR architecture, which has near\-limitless scaling potential\&. Use ansible\-pull to set up a remote copy of ansible on each managed node, each set to run via cron and update playbook source via a source repository\&. This inverts the default \fBpush\fR architecture of ansible into a \fBpull\fR architecture, which has near\-limitless scaling potential\&.
.sp .sp
...@@ -77,6 +77,11 @@ Purge the checkout after the playbook is run\&. ...@@ -77,6 +77,11 @@ Purge the checkout after the playbook is run\&.
.RS 4 .RS 4
Module used to checkout playbook repository\&. Defaults to git\&. Module used to checkout playbook repository\&. Defaults to git\&.
.RE .RE
.PP
\fB\-o\fR, \fB\-\-only\-if\-changed\fR
.RS 4
Run the playbook only if the repository has changed
.RE
.SH "AUTHOR" .SH "AUTHOR"
.sp .sp
Ansible was originally written by Michael DeHaan\&. See the AUTHORS file for a complete list of contributors\&. Ansible was originally written by Michael DeHaan\&. See the AUTHORS file for a complete list of contributors\&.
...@@ -90,3 +95,9 @@ Ansible is released under the terms of the GPLv3 License\&. ...@@ -90,3 +95,9 @@ Ansible is released under the terms of the GPLv3 License\&.
\fBansible\fR(1), \fBansible\-playbook\fR(1), \fBansible\-doc\fR(1) \fBansible\fR(1), \fBansible\-playbook\fR(1), \fBansible\-doc\fR(1)
.sp .sp
Extensive documentation as well as IRC and mailing list info is available on the ansible home page: https://ansible\&.github\&.com/ Extensive documentation as well as IRC and mailing list info is available on the ansible home page: https://ansible\&.github\&.com/
.SH "AUTHOR"
.PP
\fB:doctype:manpage\fR
.RS 4
Author.
.RE
...@@ -83,6 +83,9 @@ Purge the checkout after the playbook is run. ...@@ -83,6 +83,9 @@ Purge the checkout after the playbook is run.
Module used to checkout playbook repository. Defaults to git. Module used to checkout playbook repository. Defaults to git.
*-o*, *--only-if-changed*::
Run the playbook only if the repository has changed
AUTHOR AUTHOR
------ ------
......
...@@ -12,3 +12,4 @@ ansible*.xml ...@@ -12,3 +12,4 @@ ansible*.xml
objects.inv objects.inv
.doctrees .doctrees
rst/modules/*.rst rst/modules/*.rst
*.min.css
...@@ -4,13 +4,13 @@ FORMATTER=../hacking/module_formatter.py ...@@ -4,13 +4,13 @@ FORMATTER=../hacking/module_formatter.py
all: clean docs all: clean docs
docs: clean modules docs: clean modules staticmin
./build-site.py ./build-site.py
viewdocs: clean viewdocs: clean staticmin
./build-site.py view ./build-site.py view
htmldocs: htmldocs: staticmin
./build-site.py rst ./build-site.py rst
clean: clean:
...@@ -18,6 +18,8 @@ clean: ...@@ -18,6 +18,8 @@ clean:
-rm -f .buildinfo -rm -f .buildinfo
-rm -f *.inv -rm -f *.inv
-rm -rf *.doctrees -rm -rf *.doctrees
@echo "Cleaning up minified css files"
find . -type f -name "*.min.css" -delete
@echo "Cleaning up byte compiled python stuff" @echo "Cleaning up byte compiled python stuff"
find . -regex ".*\.py[co]$$" -delete find . -regex ".*\.py[co]$$" -delete
@echo "Cleaning up editor backup files" @echo "Cleaning up editor backup files"
...@@ -27,6 +29,7 @@ clean: ...@@ -27,6 +29,7 @@ clean:
.PHONEY: docs clean .PHONEY: docs clean
modules: $(FORMATTER) ../hacking/templates/rst.j2 modules: $(FORMATTER) ../hacking/templates/rst.j2
PYTHONPATH=../lib $(FORMATTER) -t rst --template-dir=../hacking/templates --module-dir=../library -o rst/modules/ --includes-file=rst/modules/_list.rst PYTHONPATH=../lib $(FORMATTER) -t rst --template-dir=../hacking/templates --module-dir=../library -o rst/
staticmin:
cat _themes/srtd/static/css/theme.css | sed -e 's/^[ \t]*//g; s/[ \t]*$$//g; s/\([:{;,]\) /\1/g; s/ {/{/g; s/\/\*.*\*\///g; /^$$/d' | sed -e :a -e '$$!N; s/\n\(.\)/\1/; ta' > _themes/srtd/static/css/theme.min.css
...@@ -5,12 +5,14 @@ This project hosts the source behind [ansibleworks.com/docs](http://www.ansiblew ...@@ -5,12 +5,14 @@ This project hosts the source behind [ansibleworks.com/docs](http://www.ansiblew
Contributions to the documentation are welcome. To make changes, submit a pull request Contributions to the documentation are welcome. To make changes, submit a pull request
that changes the reStructuredText files in the "rst/" directory only, and Michael can that changes the reStructuredText files in the "rst/" directory only, and Michael can
do a docs build and push the static files. If you wish to verify output from the markup do a docs build and push the static files.
such as link references, you may [install Sphinx] and build the documentation by running
`make viewdocs` from the `ansible/docsite` directory. To include module documentation If you wish to verify output from the markup
you'll need to run `make webdocs` at the top level of the repository. The generated such as link references, you may install sphinx and build the documentation by running
html files are in docsite/htmlout/ and really won't be formatted right until up `make viewdocs` from the `ansible/docsite` directory.
on ansibleworks.com.
To include module documentation you'll need to run `make webdocs` at the top level of the repository. The generated
html files are in docsite/htmlout/.
If you do not want to learn the reStructuredText format, you can also [file issues] about If you do not want to learn the reStructuredText format, you can also [file issues] about
documentation problems on the Ansible GitHub project. documentation problems on the Ansible GitHub project.
...@@ -19,7 +21,8 @@ Note that module documentation can actually be [generated from a DOCUMENTATION d ...@@ -19,7 +21,8 @@ Note that module documentation can actually be [generated from a DOCUMENTATION d
in the modules directory, so corrections to modules written as such need to be made in the modules directory, so corrections to modules written as such need to be made
in the module source, rather than in docsite source. in the module source, rather than in docsite source.
[install Sphinx]: http://sphinx-doc.org/install.html To install sphinx and the required theme, install pip and then "pip install sphinx sphinx_rtd_theme"
[file issues]: https://github.com/ansible/ansible/issues [file issues]: https://github.com/ansible/ansible/issues
[module-docs]: http://www.ansibleworks.com/docs/developing_modules.html#documenting-your-module [module-docs]: http://www.ansibleworks.com/docs/developing_modules.html#documenting-your-module
/* solar.css
* Modified from sphinxdoc.css of the sphinxdoc theme.
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: 'Open Sans', sans-serif;
font-size: 14px;
line-height: 150%;
text-align: center;
color: #002b36;
padding: 0;
margin: 0px 80px 0px 80px;
min-width: 740px;
-moz-box-shadow: 0px 0px 10px #93a1a1;
-webkit-box-shadow: 0px 0px 10px #93a1a1;
box-shadow: 0px 0px 10px #93a1a1;
background: url("subtle_dots.png") repeat;
}
div.document {
background-color: #fcfcfc;
text-align: left;
background-repeat: repeat-x;
}
div.bodywrapper {
margin: 0 240px 0 0;
border-right: 1px dotted #eee8d5;
}
div.body {
background-color: white;
margin: 0;
padding: 0.5em 20px 20px 20px;
}
div.related {
font-size: 1em;
background: #002b36;
color: #839496;
padding: 5px 0px;
}
div.related ul {
height: 2em;
margin: 2px;
}
div.related ul li {
margin: 0;
padding: 0;
height: 2em;
float: left;
}
div.related ul li.right {
float: right;
margin-right: 5px;
}
div.related ul li a {
margin: 0;
padding: 2px 5px;
line-height: 2em;
text-decoration: none;
color: #839496;
}
div.related ul li a:hover {
background-color: #073642;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
div.sphinxsidebarwrapper {
padding: 0;
}
div.sphinxsidebar {
margin: 0;
padding: 0.5em 15px 15px 0;
width: 210px;
float: right;
font-size: 0.9em;
text-align: left;
}
div.sphinxsidebar h3, div.sphinxsidebar h4 {
margin: 1em 0 0.5em 0;
font-size: 1em;
padding: 0.7em;
background-color: #eeeff1;
}
div.sphinxsidebar h3 a {
color: #2E3436;
}
div.sphinxsidebar ul {
padding-left: 1.5em;
margin-top: 7px;
padding: 0;
line-height: 150%;
color: #586e75;
}
div.sphinxsidebar ul ul {
margin-left: 20px;
}
div.sphinxsidebar input {
border: 1px solid #eee8d5;
}
div.footer {
background-color: #93a1a1;
color: #eee;
padding: 3px 8px 3px 0;
clear: both;
font-size: 0.8em;
text-align: right;
}
div.footer a {
color: #eee;
text-decoration: none;
}
/* -- body styles ----------------------------------------------------------- */
p {
margin: 0.8em 0 0.5em 0;
}
div.body a, div.sphinxsidebarwrapper a {
color: #268bd2;
text-decoration: none;
}
div.body a:hover, div.sphinxsidebarwrapper a:hover {
border-bottom: 1px solid #268bd2;
}
h1, h2, h3, h4, h5, h6 {
font-family: "Open Sans", sans-serif;
font-weight: 300;
}
h1 {
margin: 0;
padding: 0.7em 0 0.3em 0;
line-height: 1.2em;
color: #002b36;
text-shadow: #eee 0.1em 0.1em 0.1em;
}
h2 {
margin: 1.3em 0 0.2em 0;
padding: 0 0 10px 0;
color: #073642;
border-bottom: 1px solid #eee;
}
h3 {
margin: 1em 0 -0.3em 0;
padding-bottom: 5px;
}
h3, h4, h5, h6 {
color: #073642;
border-bottom: 1px dotted #eee;
}
div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
color: #657B83!important;
}
h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
display: none;
margin: 0 0 0 0.3em;
padding: 0 0.2em 0 0.2em;
color: #aaa!important;
}
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
h5:hover a.anchor, h6:hover a.anchor {
display: inline;
}
h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
h5 a.anchor:hover, h6 a.anchor:hover {
color: #777;
background-color: #eee;
}
a.headerlink {
color: #c60f0f!important;
font-size: 1em;
margin-left: 6px;
padding: 0 4px 0 4px;
text-decoration: none!important;
}
a.headerlink:hover {
background-color: #ccc;
color: white!important;
}
cite, code, tt {
font-family: 'Source Code Pro', monospace;
font-size: 0.9em;
letter-spacing: 0.01em;
background-color: #eeeff2;
font-style: normal;
}
hr {
border: 1px solid #eee;
margin: 2em;
}
.highlight {
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
pre {
font-family: 'Source Code Pro', monospace;
font-style: normal;
font-size: 0.9em;
letter-spacing: 0.015em;
line-height: 120%;
padding: 0.7em;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
pre a {
color: inherit;
text-decoration: underline;
}
td.linenos pre {
padding: 0.5em 0;
}
div.quotebar {
background-color: #f8f8f8;
max-width: 250px;
float: right;
padding: 2px 7px;
border: 1px solid #ccc;
}
div.topic {
background-color: #f8f8f8;
}
table {
border-collapse: collapse;
margin: 0 -0.5em 0 -0.5em;
}
table td, table th {
padding: 0.2em 0.5em 0.2em 0.5em;
}
div.admonition {
font-size: 0.9em;
margin: 1em 0 1em 0;
border: 1px solid #eee;
background-color: #f7f7f7;
padding: 0;
-moz-box-shadow: 0px 8px 6px -8px #93a1a1;
-webkit-box-shadow: 0px 8px 6px -8px #93a1a1;
box-shadow: 0px 8px 6px -8px #93a1a1;
}
div.admonition p {
margin: 0.5em 1em 0.5em 1em;
padding: 0.2em;
}
div.admonition pre {
margin: 0.4em 1em 0.4em 1em;
}
div.admonition p.admonition-title
{
margin: 0;
padding: 0.2em 0 0.2em 0.6em;
color: white;
border-bottom: 1px solid #eee8d5;
font-weight: bold;
background-color: #268bd2;
}
div.warning p.admonition-title,
div.important p.admonition-title {
background-color: #cb4b16;
}
div.hint p.admonition-title,
div.tip p.admonition-title {
background-color: #859900;
}
div.caution p.admonition-title,
div.attention p.admonition-title,
div.danger p.admonition-title,
div.error p.admonition-title {
background-color: #dc322f;
}
div.admonition ul, div.admonition ol {
margin: 0.1em 0.5em 0.5em 3em;
padding: 0;
}
div.versioninfo {
margin: 1em 0 0 0;
border: 1px solid #eee;
background-color: #DDEAF0;
padding: 8px;
line-height: 1.3em;
font-size: 0.9em;
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
}
/* solarized dark style for solar theme */
/*style pre scrollbar*/
pre::-webkit-scrollbar, .highlight::-webkit-scrollbar {
height: 0.5em;
background: #073642;
}
pre::-webkit-scrollbar-thumb {
border-radius: 1em;
background: #93a1a1;
}
/* pygments style */
.highlight .hll { background-color: #ffffcc }
.highlight { background: #002B36!important; color: #93A1A1 }
.highlight .c { color: #586E75 } /* Comment */
.highlight .err { color: #93A1A1 } /* Error */
.highlight .g { color: #93A1A1 } /* Generic */
.highlight .k { color: #859900 } /* Keyword */
.highlight .l { color: #93A1A1 } /* Literal */
.highlight .n { color: #93A1A1 } /* Name */
.highlight .o { color: #859900 } /* Operator */
.highlight .x { color: #CB4B16 } /* Other */
.highlight .p { color: #93A1A1 } /* Punctuation */
.highlight .cm { color: #586E75 } /* Comment.Multiline */
.highlight .cp { color: #859900 } /* Comment.Preproc */
.highlight .c1 { color: #586E75 } /* Comment.Single */
.highlight .cs { color: #859900 } /* Comment.Special */
.highlight .gd { color: #2AA198 } /* Generic.Deleted */
.highlight .ge { color: #93A1A1; font-style: italic } /* Generic.Emph */
.highlight .gr { color: #DC322F } /* Generic.Error */
.highlight .gh { color: #CB4B16 } /* Generic.Heading */
.highlight .gi { color: #859900 } /* Generic.Inserted */
.highlight .go { color: #93A1A1 } /* Generic.Output */
.highlight .gp { color: #93A1A1 } /* Generic.Prompt */
.highlight .gs { color: #93A1A1; font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #CB4B16 } /* Generic.Subheading */
.highlight .gt { color: #93A1A1 } /* Generic.Traceback */
.highlight .kc { color: #CB4B16 } /* Keyword.Constant */
.highlight .kd { color: #268BD2 } /* Keyword.Declaration */
.highlight .kn { color: #859900 } /* Keyword.Namespace */
.highlight .kp { color: #859900 } /* Keyword.Pseudo */
.highlight .kr { color: #268BD2 } /* Keyword.Reserved */
.highlight .kt { color: #DC322F } /* Keyword.Type */
.highlight .ld { color: #93A1A1 } /* Literal.Date */
.highlight .m { color: #2AA198 } /* Literal.Number */
.highlight .s { color: #2AA198 } /* Literal.String */
.highlight .na { color: #93A1A1 } /* Name.Attribute */
.highlight .nb { color: #B58900 } /* Name.Builtin */
.highlight .nc { color: #268BD2 } /* Name.Class */
.highlight .no { color: #CB4B16 } /* Name.Constant */
.highlight .nd { color: #268BD2 } /* Name.Decorator */
.highlight .ni { color: #CB4B16 } /* Name.Entity */
.highlight .ne { color: #CB4B16 } /* Name.Exception */
.highlight .nf { color: #268BD2 } /* Name.Function */
.highlight .nl { color: #93A1A1 } /* Name.Label */
.highlight .nn { color: #93A1A1 } /* Name.Namespace */
.highlight .nx { color: #93A1A1 } /* Name.Other */
.highlight .py { color: #93A1A1 } /* Name.Property */
.highlight .nt { color: #268BD2 } /* Name.Tag */
.highlight .nv { color: #268BD2 } /* Name.Variable */
.highlight .ow { color: #859900 } /* Operator.Word */
.highlight .w { color: #93A1A1 } /* Text.Whitespace */
.highlight .mf { color: #2AA198 } /* Literal.Number.Float */
.highlight .mh { color: #2AA198 } /* Literal.Number.Hex */
.highlight .mi { color: #2AA198 } /* Literal.Number.Integer */
.highlight .mo { color: #2AA198 } /* Literal.Number.Oct */
.highlight .sb { color: #586E75 } /* Literal.String.Backtick */
.highlight .sc { color: #2AA198 } /* Literal.String.Char */
.highlight .sd { color: #93A1A1 } /* Literal.String.Doc */
.highlight .s2 { color: #2AA198 } /* Literal.String.Double */
.highlight .se { color: #CB4B16 } /* Literal.String.Escape */
.highlight .sh { color: #93A1A1 } /* Literal.String.Heredoc */
.highlight .si { color: #2AA198 } /* Literal.String.Interpol */
.highlight .sx { color: #2AA198 } /* Literal.String.Other */
.highlight .sr { color: #DC322F } /* Literal.String.Regex */
.highlight .s1 { color: #2AA198 } /* Literal.String.Single */
.highlight .ss { color: #2AA198 } /* Literal.String.Symbol */
.highlight .bp { color: #268BD2 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #268BD2 } /* Name.Variable.Class */
.highlight .vg { color: #268BD2 } /* Name.Variable.Global */
.highlight .vi { color: #268BD2 } /* Name.Variable.Instance */
.highlight .il { color: #2AA198 } /* Literal.Number.Integer.Long */
<?php
require('../wp-blog-header.php');
get_header();
?>
<div class="row">
<div class="container">
<?php if (function_exists('bootstrapwp_breadcrumbs')) bootstrapwp_breadcrumbs(); ?>
</div><!--/.container -->
</div><!--/.row -->
{% macro navBar() %}
<div id="left-sidebar" class="span3 sidebar">
<div class="side-nav sidebar-block left-side-nav">
<ul><li><a href="/docs/"><strong>Documentation Home</strong></a></li></ul>
{% if title == "Ansible Documentation Index" %}
{{ toctree(maxdepth=1) }}
{% else %}
{{ toc }}
{% endif %}
<hr />
<div class="qsButton pagination-centered" />
<a href="/quickstart"><button class="btn btn-primary" type="button">Quick Start Video</button></a>
</div>
</div>
</div>
{% endmacro %}
{# Silence the sidebar's, relbar's #}
{% block sidebar1 %}{% endblock %}
{% block sidebar2 %}{% endblock %}
{% block relbar1 %}{% endblock %}
{% block relbar2 %}{% endblock %}
{%- block content %}
<div class="container doc-content">
<div class="row clear-both">
<!-- BEGIN LEFT-SIDEBAR -->
{% block header %}{{ navBar() }}{% endblock %}
<!-- END LEFT-SIDEBAR -->
<!-- BEGIN ARTICLE CONTENT AREA -->
<div class="span8 main-column two-columns-left">
{% block body %} {% endblock %}
</div><!-- END ARTICLE CONTENT AREA -->
</div> <!-- class=row -->
</div> <!-- class=container -->
{%- endblock %}
<?php get_footer('home'); ?>
{%- if prev %}
<li><a href="{{ prev.link|e }}"
title="{{ _('previous chapter') }}">{{ "&laquo;"|safe }} {{ prev.title }}</a></li>
{%- endif %}
{%- if next %}
<li><a href="{{ next.link|e }}"
title="{{ _('next chapter') }}">{{ next.title }} {{ "&raquo;"|safe }}</a></li>
{%- endif %}
{%- if pagename != "search" %}
<form class="pull-left" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
{%- endif %}
{%- if show_source and has_source and sourcename %}
<li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
rel="nofollow">{{ _('Source') }}</a></li>
{%- endif %}
# Twitter Bootstrap Theme
[theme]
inherit = basic
stylesheet = basic.css
pygments_style = tango
<li class="dropdown" data-dropdown="dropdown">
<a href="{{ pathto(master_doc) }}"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc">{{ toctree(maxdepth=1) }}</span>
</li>
{% extends "basic/layout.html" %}
{% set script_files = script_files + ['_static/bootstrap-dropdown.js', '_static/bootstrap-scrollspy.js'] %}
{% set css_files = ['_static/bootstrap.css', '_static/bootstrap-sphinx.css', '_static/ansible-local.css'] + css_files %}
{# Sidebar: Rework into our Boostrap nav section. #}
{% macro navBar() %}
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<!-- <a class="brand" href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a> -->
<ul class="nav">
{% block sidebartoc %}
<li><a href="/">Home</A>
{% include "globaltoc.html" %}
{% include "localtoc.html" %}
{% endblock %}
</ul>
<ul class="nav secondary-nav">
{% block sidebarsearch %}
{% include "searchbox.html" %}
{% endblock %}
</ul>
</div>
</div>
</div>
{% endmacro %}
<p></p>
{%- block extrahead %}
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<script type="text/javascript">
// Set the maximum height of drop down menus to just less than the height
// of the viewport.
var set_max_menu_height = function () {
// set menu max height to 75 less than viewport height
$('.dropdown-menu').css('max-height', $(window).height() - 75);
}
// Set this when we set the page up and on each resize.
$(window).resize(set_max_menu_height);
$(window).ready(set_max_menu_height);
</script>
{% endblock %}
{% block header %}{{ navBar() }}{% endblock %}
{# Silence the sidebar's, relbar's #}
{% block sidebar1 %}{% endblock %}
{% block sidebar2 %}{% endblock %}
{% block relbar1 %}{% endblock %}
{% block relbar2 %}{% endblock %}
{%- block content %}
<div class="container">
{% block body %} {% endblock %}
<br/>
</div>
{%- endblock %}
{%- block footer %}
<footer class="footer">
<center>
<a href="http://ansibleworks.com"><img src="http://ansible.cc/img/AnsibleWorks.png" alt="AnsibleWorks"></a>
<p>
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}<br/>
{%- else %}
{% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}<br/>
{%- endif %}
{%- endif %}
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}<br/>
{%- endif %}
</p>
</div>
</center>
</footer>
{%- endblock %}
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">{{ _('Section') }}</a>
<span class="localtoc">{{ toc }}</span>
</li>
{%- if prev %}
<li><a href="{{ prev.link|e }}"
title="{{ _('previous chapter') }}">{{ "&laquo;"|safe }} {{ prev.title }}</a></li>
{%- endif %}
{%- if next %}
<li><a href="{{ next.link|e }}"
title="{{ _('next chapter') }}">{{ next.title }} {{ "&raquo;"|safe }}</a></li>
{%- endif %}
{%- if pagename != "search" %}
<form class="pull-left" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
{%- endif %}
{%- if show_source and has_source and sourcename %}
<li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
rel="nofollow">{{ _('Source') }}</a></li>
{%- endif %}
/* ============================================================
* bootstrap-dropdown.js v1.4.0
* http://twitter.github.com/bootstrap/javascript.html#dropdown
* ============================================================
* Copyright 2011 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function( $ ){
"use strict"
/* DROPDOWN PLUGIN DEFINITION
* ========================== */
$.fn.dropdown = function ( selector ) {
return this.each(function () {
$(this).delegate(selector || d, 'click', function (e) {
var li = $(this).parent('li')
, isActive = li.hasClass('open')
clearMenus()
!isActive && li.toggleClass('open')
return false
})
})
}
/* APPLY TO STANDARD DROPDOWN ELEMENTS
* =================================== */
var d = 'a.menu, .dropdown-toggle'
function clearMenus() {
$(d).parent('li').removeClass('open')
}
$(function () {
$('html').bind("click", clearMenus)
$('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' )
})
}( window.jQuery || window.ender );
/* =============================================================
* bootstrap-scrollspy.js v1.4.0
* http://twitter.github.com/bootstrap/javascript.html#scrollspy
* =============================================================
* Copyright 2011 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================== */
!function ( $ ) {
"use strict"
var $window = $(window)
function ScrollSpy( topbar, selector ) {
var processScroll = $.proxy(this.processScroll, this)
this.$topbar = $(topbar)
this.selector = selector || 'li > a'
this.refresh()
this.$topbar.delegate(this.selector, 'click', processScroll)
$window.scroll(processScroll)
this.processScroll()
}
ScrollSpy.prototype = {
refresh: function () {
this.targets = this.$topbar.find(this.selector).map(function () {
var href = $(this).attr('href')
return /^#\w/.test(href) && $(href).length ? href : null
})
this.offsets = $.map(this.targets, function (id) {
return $(id).offset().top
})
}
, processScroll: function () {
var scrollTop = $window.scrollTop() + 10
, offsets = this.offsets
, targets = this.targets
, activeTarget = this.activeTarget
, i
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
&& (!offsets[i + 1] || scrollTop <= offsets[i + 1])
&& this.activateButton( targets[i] )
}
}
, activateButton: function (target) {
this.activeTarget = target
this.$topbar
.find(this.selector).parent('.active')
.removeClass('active')
this.$topbar
.find(this.selector + '[href="' + target + '"]')
.parent('li')
.addClass('active')
}
}
/* SCROLLSPY PLUGIN DEFINITION
* =========================== */
$.fn.scrollSpy = function( options ) {
var scrollspy = this.data('scrollspy')
if (!scrollspy) {
return this.each(function () {
$(this).data('scrollspy', new ScrollSpy( this, options ))
})
}
if ( options === true ) {
return scrollspy
}
if ( typeof options == 'string' ) {
scrollspy[options]()
}
return this
}
$(document).ready(function () {
$('body').scrollSpy('[data-scrollspy] li > a')
})
}( window.jQuery || window.ender );
\ No newline at end of file
/*
* bootstrap-sphinx.css
* ~~~~~~~~~~~~~~~~~~~~
*
* Sphinx stylesheet -- Twitter Bootstrap theme.
*/
body {
padding-top: 42px;
}
div.documentwrapper {
float: left;
width: 100%;
}
{%- block sidebarlogo %}
{%- if logo %}
.topbar h3 a, .topbar .brand {
background: transparent url("{{ logo }}") no-repeat 22px 3px;
padding-left: 62px;
}
{%- endif %}
{%- endblock %}
# Twitter Bootstrap Theme
[theme]
inherit = basic
stylesheet = basic.css
pygments_style = tango
"""Sphinx ReadTheDocs theme.
From https://github.com/ryan-roemer/sphinx-bootstrap-theme.
"""
import os
VERSION = (0, 1, 5)
__version__ = ".".join(str(v) for v in VERSION)
__version_full__ = __version__
def get_html_theme_path():
"""Return list of HTML theme paths."""
cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
return cur_dir
<ul class="wy-breadcrumbs">
<li><a href="{{ pathto(master_doc) }}">Docs</a> &raquo;</li>
<li><a href="">{{ title }}</a></li>
{% if not pagename.endswith('_module') and (not 'list_of' in pagename) and (not 'category' in pagename) %}
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/ansible/ansible/blob/devel/docsite/rst/{{ pagename }}.rst" class="icon icon-github"> Edit on GitHub</a>
</li>
{% endif %}
</ul>
<hr/>
<footer>
{% if next or prev %}
<div class="rst-footer-buttons">
{% if next %}
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}"/>Next <span class="icon icon-circle-arrow-right"></span></a>
{% endif %}
{% if prev %}
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}"><span class="icon icon-circle-arrow-left"></span> Previous</a>
{% endif %}
</div>
{% endif %}
<hr/>
<p>
&copy; Copyright 2013 <a href="http://ansibleworks.com">AnsibleWorks</a>.
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %}
</p>
Ansible docs are generated from <a href="http://github.com/ansible/ansible">GitHub sources</A> using <A HREF="http://sphinx-doc.org/">Sphinx</A> using a theme provided by <a href="http://readthedocs.org">Read the Docs</a>. {% if pagename.endswith("_module") %}. Module documentation is not edited directly, but is generated from the source code for the modules. To submit an update to module docs, edit the 'DOCUMENTATION' metadata in the <A HREF="https://github.com/ansible/ansible/tree/devel/library">module source tree</A>. {% endif %}
</footer>
{# TEMPLATE VAR SETTINGS #}
{%- set url_root = pathto('', 1) %}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- begin analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-29861888-3', 'ansible.com');
ga('send', 'pageview');
</script>
<!-- end analytics -->
{% block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{% endblock %}
{# FAVICON #}
{% if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{% endif %}
{# CSS #}
<link href='https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700' rel='stylesheet' type='text/css'>
<link href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.0.3/css/font-awesome.min.css' rel='stylesheet' type='text/css'>
{# JS #}
{% if not embedded %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'{{ url_root }}',
VERSION:'{{ release|e }}',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{% if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{% endif %}
{% endif %}
{# RTD hosts these file themselves, so just load on non RTD builds #}
{% if not READTHEDOCS %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<script type="text/javascript" src="_static/js/theme.js"></script>
{% endif %}
{% for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}"
href="{{ pathto('about') }}"/>
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}"
href="{{ pathto('genindex') }}"/>
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}"/>
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}"/>
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}"/>
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"/>
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"/>
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"/>
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
<style>
.search-reset-start {
color: #463E3F;
float: right;
position: relative;
top: -25px;
left: -10px;
z-index: 10;
}
.search-reset-start:hover {
cursor: pointer;
color: #2980B9;
}
#search-box-id {
padding-right: 25px;
}
</style>
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
{# SIDE NAV, TOGGLES ON MOBILE #}
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search">
<a href="{{ pathto(master_doc) }}" class="icon icon-home"> {{ project }}</a>
{% include "searchbox.html" %}
</div>
<div id="menu-id" class="wy-menu wy-menu-vertical" data-spy="affix">
{% set toctree = toctree(maxdepth=2, collapse=False) %}
{% if toctree %}
{{ toctree }}
{% else %}
{{ toc }}
{% endif %}
</div>
&nbsp;
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
{# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
<nav class="wy-nav-top">
<i data-toggle="wy-nav-top" class="icon icon-reorder"></i>
<a href="/">{{ project }}</a>
</nav>
{# PAGE CONTENT #}
<div class="wy-nav-content">
<div class="rst-content">
{% include "breadcrumbs.html" %}
<div id="page-content">
{% block body %}{% endblock %}
</div>
<div id="search-results"><gcse:searchresults-only></div>
{% include "footer.html" %}
</div>
</div>
</section>
</div>
{% include "versions.html" %}
<!-- begin analytics -->
<script type="text/javascript">
var _hsq = _hsq || [];
_hsq.push(["setContentType", "standard-page"]);
(function(d,s,i,r) {
if (d.getElementById(i)){return;}
var n = d.createElement(s),e = document.getElementsByTagName(s)[0];
n.id=i;n.src = '//js.hs-analytics.net/analytics/'+(Math.ceil(new Date()/r)*r)+'/330046.js';
e.parentNode.insertBefore(n, e);
})(document, "script", "hs-analytics",300000);
</script>
<!-- end analytics -->
</body>
</html>
{#
basic/layout.html
~~~~~~~~~~~~~~~~~
Master layout template for Sphinx themes.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block doctype -%}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
{%- endblock %}
{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
(sidebars != []) %}
{%- set url_root = pathto('', 1) %}
{# XXX necessary? #}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}
{%- macro relbar() %}
<div class="related">
<h3>{{ _('Navigation') }}</h3>
<ul>
{%- for rellink in rellinks %}
<li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
{%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
{%- endfor %}
{%- block rootrellink %}
<li><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
{%- endblock %}
{%- for parent in parents %}
<li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
{%- endfor %}
{%- block relbaritems %} {% endblock %}
</ul>
</div>
{%- endmacro %}
{%- macro sidebar() %}
{%- if render_sidebar %}
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
</a></p>
{%- endif %}
{%- endblock %}
{%- if sidebars != None %}
{#- new style sidebar: explicitly include/exclude templates #}
{%- for sidebartemplate in sidebars %}
{%- include sidebartemplate %}
{%- endfor %}
{%- else %}
{#- old style sidebars: using blocks -- should be deprecated #}
{%- block sidebartoc %}
{%- include "localtoc.html" %}
{%- endblock %}
{%- block sidebarrel %}
{%- include "relations.html" %}
{%- endblock %}
{%- block sidebarsourcelink %}
{%- include "sourcelink.html" %}
{%- endblock %}
{%- if customsidebar %}
{%- include customsidebar %}
{%- endif %}
{%- block sidebarsearch %}
{%- include "searchbox.html" %}
{%- endblock %}
{%- endif %}
</div>
</div>
{%- endif %}
{%- endmacro %}
{%- macro script() %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ url_root }}',
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{%- endmacro %}
{%- macro css() %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
{%- for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{%- endfor %}
{%- endmacro %}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
{{ metatags }}
{%- block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{%- endblock %}
{{ css() }}
{%- if not embedded %}
{{ script() }}
{%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{%- endif %}
{%- if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{%- endif %}
{%- endif %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
<body>
{%- block header %}{% endblock %}
{%- block relbar1 %}{{ relbar() }}{% endblock %}
{%- block content %}
{%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
<div class="document">
{%- block document %}
<div class="documentwrapper">
{%- if render_sidebar %}
<div class="bodywrapper">
{%- endif %}
<div class="body">
{% block body %} {% endblock %}
</div>
{%- if render_sidebar %}
</div>
{%- endif %}
</div>
{%- endblock %}
{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
<div class="clearer"></div>
</div>
{%- endblock %}
{%- block relbar2 %}{{ relbar() }}{% endblock %}
{%- block footer %}
<div class="footer">
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
{%- else %}
{% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
{%- endif %}
{%- endif %}
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %}
{%- if show_sphinx %}
{% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
{%- endif %}
</div>
<p>asdf asdf asdf asdf 22</p>
{%- endblock %}
</body>
</html>
{#
basic/search.html
~~~~~~~~~~~~~~~~~
Template for the search page.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- extends "layout.html" %}
{% set title = _('Search') %}
{% set script_files = script_files + ['_static/searchtools.js'] %}
{% block extrahead %}
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
</script>
{# this is used when loading the search index using $.ajax fails,
such as on Chrome for documents on localhost #}
<script type="text/javascript" id="searchindexloader"></script>
{{ super() }}
{% endblock %}
{% block body %}
<noscript>
<div id="fallback" class="admonition warning">
<p class="last">
{% trans %}Please activate JavaScript to enable the search
functionality.{% endtrans %}
</p>
</div>
</noscript>
{% if search_performed %}
<h2>{{ _('Search Results') }}</h2>
{% if not search_results %}
<p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
{% endif %}
{% endif %}
<div id="search-results">
{% if search_results %}
<ul>
{% for href, caption, context in search_results %}
<li>
<a href="{{ pathto(item.href) }}">{{ caption }}</a>
<p class="context">{{ context|e }}</p>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endblock %}
<!-- <form class="wy-form" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form> -->
<script>
(function() {
var cx = '015514069825911246756:eu5pbnxp4po';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
<form id="search-form-id" action="">
<input type="text" name="query" id="search-box-id" />
<a class="search-reset-start" id="search-reset"><i class="fa fa-times"></i></a>
<a class="search-reset-start" id="search-start"><i class="fa fa-search"></i></a>
</form>
<script type="text/javascript" src="http://www.google.com/cse/brand?form=search-form-id&inputbox=search-box-id"></script>
<script>
function executeQuery() {
var input = document.getElementById('search-box-id');
var element = google.search.cse.element.getElement('searchresults-only0');
element.resultsUrl = '/htmlout/search.html'
if (input.value == '') {
element.clearAllResults();
$('#page-content, .rst-footer-buttons, #search-start').show();
$('#search-results, #search-reset').hide();
} else {
$('#page-content, .rst-footer-buttons, #search-start').hide();
$('#search-results, #search-reset').show();
element.execute(input.value);
}
return false;
}
$('#search-reset').hide();
$('#search-box-id').css('background-position', '1em center');
$('#search-box-id').on('blur', function() {
$('#search-box-id').css('background-position', '1em center');
});
$('#search-start').click(function(e) { executeQuery(); });
$('#search-reset').click(function(e) { $('#search-box-id').val(''); executeQuery(); });
$('#search-form-id').submit(function(e) {
console.log('submitting!');
executeQuery();
e.preventDefault();
});
</script>
.font-smooth,.icon:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:fontawesome-webfont;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#fontawesome-webfont") format("svg")}.icon:before{display:inline-block;font-family:fontawesome-webfont;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .icon{display:inline-block;text-decoration:inherit}li .icon{display:inline-block}li .icon-large:before,li .icon-large:before{width:1.875em}ul.icons{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.icons li .icon{width:0.8em}ul.icons li .icon-large:before,ul.icons li .icon-large:before{vertical-align:baseline}.icon-book:before{content:"\f02d"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}
This source diff could not be displayed because it is too large. You can view the blob instead.
$( document ).ready(function() {
// Shift nav in mobile when clicking the menu.
$("[data-toggle='wy-nav-top']").click(function() {
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
});
// Close menu when you click a link.
$(".wy-menu-vertical .current ul li a").click(function() {
$("[data-toggle='wy-nav-shift']").removeClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
});
$("[data-toggle='rst-current-version']").click(function() {
$("[data-toggle='rst-versions']").toggleClass("shift-up");
});
$("table.docutils:not(.field-list").wrap("<div class='wy-table-responsive'></div>");
});
[theme]
inherit = basic
stylesheet = css/theme.min.css
[options]
typekit_id = hiw1hhg
analytics_id =
{% if READTHEDOCS %}
{# Add rst-badge after rst-versions for small badge style. #}
<div class="rst-versions" data-toggle="rst-versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span class="icon icon-book"> Read the Docs</span>
v: {{ current_version }}
<span class="icon icon-caret-down"></span>
</span>
<div class="rst-other-versions">
<dl>
<dt>Versions</dt>
{% for slug, url in versions %}
<dd><a href="{{ url }}">{{ slug }}</a></dd>
{% endfor %}
</dl>
<dl>
<dt>Downloads</dt>
{% for type, url in downloads %}
<dd><a href="{{ url }}">{{ type }}</a></dd>
{% endfor %}
</dl>
<dl>
<dt>On Read the Docs</dt>
<dd>
<a href="//{{ PRODUCTION_DOMAIN }}/projects/{{ slug }}/?fromdocs={{ slug }}">Project Home</a>
</dd>
<dd>
<a href="//{{ PRODUCTION_DOMAIN }}/builds/{{ slug }}/?fromdocs={{ slug }}">Builds</a>
</dd>
</dl>
<hr/>
Free document hosting provided by <a href="http://www.readthedocs.org">Read the Docs</a>.
</div>
</div>
{% endif %}
...@@ -16,11 +16,15 @@ ...@@ -16,11 +16,15 @@
import sys import sys
import os import os
# pip install sphinx_rtd_theme
#import sphinx_rtd_theme
#html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# If your extensions are in another directory, add it here. If the directory # If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it # is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here. # absolute, like shown here.
#sys.path.append(os.path.abspath('some/directory')) #sys.path.append(os.path.abspath('some/directory'))
#
sys.path.insert(0, os.path.join('ansible', 'lib')) sys.path.insert(0, os.path.join('ansible', 'lib'))
sys.path.append(os.path.abspath('_themes')) sys.path.append(os.path.abspath('_themes'))
...@@ -50,7 +54,7 @@ source_suffix = '.rst' ...@@ -50,7 +54,7 @@ source_suffix = '.rst'
master_doc = 'index' master_doc = 'index'
# General substitutions. # General substitutions.
project = 'Ansible 1.2 Documentation' project = 'Ansible Documentation'
copyright = "2013 AnsibleWorks" copyright = "2013 AnsibleWorks"
# The default replacements for |version| and |release|, also used in various # The default replacements for |version| and |release|, also used in various
...@@ -101,17 +105,17 @@ pygments_style = 'sphinx' ...@@ -101,17 +105,17 @@ pygments_style = 'sphinx'
# ----------------------- # -----------------------
html_theme_path = ['_themes'] html_theme_path = ['_themes']
html_theme = 'aworks' html_theme = 'srtd'
html_short_title = 'Ansible Documentation' html_short_title = 'Ansible Documentation'
# The style sheet to use for HTML and HTML Help pages. A file of that name # The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths # must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path. # given in html_static_path.
html_style = 'default.css' #html_style = 'solar.css'
# The name for this set of Sphinx documents. If None, it defaults to # The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation". # "<project> v<release> documentation".
html_title = 'Ansible 1.2 Documentation' html_title = 'Ansible Documentation'
# A shorter title for the navigation bar. Default is the same as html_title. # A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None #html_short_title = None
......
YAML Syntax YAML Syntax
=========== ===========
.. contents::
:depth: 2
This page provides a basic overview of correct YAML syntax, which is how Ansible This page provides a basic overview of correct YAML syntax, which is how Ansible
playbooks (our configuration management language) are expressed. playbooks (our configuration management language) are expressed.
......
AnsibleWorks AWX
````````````````
`AnsibleWorks <http://ansibleworks.com>`_, who also sponsors the Ansible community, also produces 'AWX', which is a web-based solution that makes Ansible even more easy to use for IT teams of all kinds. It's designed to be the hub for all of your automation tasks.
AWX allows you to control access to who can access what, even allowing sharing of SSH credentials without someone being able to transfer those credentials. Inventory can be graphically managed or synced with a wide variety of cloud sources. It logs all of your jobs, integrates well with LDAP, and has an amazing browsable REST API. Command line tools are available for easy integration
with Jenkins as well.
Find out more about AWX features and how to download it on the `AWX webpage <http://ansibleworks.com/ansibleworks-awx>`_. AWX
is free for usage for up to 10 nodes, and comes bundled with amazing support from AnsibleWorks. As you would expect, AWX is
installed using Ansible playbooks!
Community Information
`````````````````````
Ansible is an open source project designed to bring together developers and administrators of all kinds to collaborate on building
IT automation solutions that work well for them. Should you wish to get more involved -- whether in terms of just asking a question, helping other users, introducing new people to Ansible, or helping with the software or documentation, we welcome your contributions to the project.
`Ways to interact <https://github.com/ansible/ansible/blob/devel/CONTRIBUTING.md>`_
Developer Information
`````````````````````
Learn how to build modules of your own in any language, and also how to extend Ansible through several kinds of plugins. Explore Ansible's Python API and write Python plugins to integrate with other solutions in your environment.
.. toctree::
:maxdepth: 1
developing_api
developing_inventory
developing_modules
developing_plugins
Developers will also likely be interested in the fully-discoverable `REST API <http://ansibleworks.com/ansibleworks-awx>`_ that is part of AnsibleWorks AWX. It's great for embedding Ansible in all manner of applications.
Python API Python API
========== ==========
.. contents:: Topics
There are several interesting ways to use Ansible from an API perspective. You can use There are several interesting ways to use Ansible from an API perspective. You can use
the Ansible python API to control nodes, you can extend Ansible to respond to various python events, you can the Ansible python API to control nodes, you can extend Ansible to respond to various python events, you can
write various plugins, and you can plug in inventory data from external data sources. This document write various plugins, and you can plug in inventory data from external data sources. This document
...@@ -13,9 +15,6 @@ as it has a very nice REST API that provides all of these things at a higher lev ...@@ -13,9 +15,6 @@ as it has a very nice REST API that provides all of these things at a higher lev
Ansible is written in its own API so you have a considerable amount of power across the board. Ansible is written in its own API so you have a considerable amount of power across the board.
This chapter discusses the Python API. This chapter discusses the Python API.
.. contents:: `Table of contents`
:depth: 2
.. _python_api: .. _python_api:
Python API Python API
...@@ -38,7 +37,7 @@ It's pretty simple:: ...@@ -38,7 +37,7 @@ It's pretty simple::
The run method returns results per host, grouped by whether they The run method returns results per host, grouped by whether they
could be contacted or not. Return types are module specific, as could be contacted or not. Return types are module specific, as
expressed in the 'ansible-modules' documentation.:: expressed in the :doc:`modules` documentation.::
{ {
"dark" : { "dark" : {
......
Developing Dynamic Inventory Sources Developing Dynamic Inventory Sources
==================================== ====================================
.. contents:: `Table of contents` .. contents:: Topics
:depth: 2 :local:
As described in `intro_inventory_dynamic`, ansible can pull inventory information from dynamic sources, including cloud sources. As described in :doc:`intro_dynamic_inventory`, ansible can pull inventory information from dynamic sources, including cloud sources.
How do we write a new one? How do we write a new one?
......
Developing Modules Developing Modules
================== ==================
.. contents:: Topics
Ansible modules are reusable units of magic that can be used by the Ansible API, Ansible modules are reusable units of magic that can be used by the Ansible API,
or by the `ansible` or `ansible-playbook` programs. or by the `ansible` or `ansible-playbook` programs.
...@@ -13,9 +15,6 @@ Should you develop an interesting Ansible module, consider sending a pull reques ...@@ -13,9 +15,6 @@ Should you develop an interesting Ansible module, consider sending a pull reques
`github project <http://github.com/ansible/ansible>`_ to see about getting your module `github project <http://github.com/ansible/ansible>`_ to see about getting your module
included in the core project. included in the core project.
.. contents::
:depth: 2
.. _module_dev_tutorial: .. _module_dev_tutorial:
Tutorial Tutorial
...@@ -92,7 +91,7 @@ The example usage we are trying to achieve to set the time is:: ...@@ -92,7 +91,7 @@ The example usage we are trying to achieve to set the time is::
If no time parameter is set, we'll just leave the time as is and return the current time. If no time parameter is set, we'll just leave the time as is and return the current time.
.. note: .. note::
This is obviously an unrealistic idea for a module. You'd most likely just This is obviously an unrealistic idea for a module. You'd most likely just
use the shell module. However, it probably makes a decent tutorial. use the shell module. However, it probably makes a decent tutorial.
...@@ -229,8 +228,7 @@ The 'group' and 'user' modules are reasonably non-trivial and showcase what this ...@@ -229,8 +228,7 @@ The 'group' and 'user' modules are reasonably non-trivial and showcase what this
Key parts include always ending the module file with:: Key parts include always ending the module file with::
# include magic from lib/ansible/module_common.py from ansible.module_utils.basic import *
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main() main()
And instantiating the module class like:: And instantiating the module class like::
...@@ -375,10 +373,7 @@ syntax highlighting before you include it in your Python file. ...@@ -375,10 +373,7 @@ syntax highlighting before you include it in your Python file.
Example Example
+++++++ +++++++
To print a basic documentation string, run ``./hacking/module_formatter.py -G``. See an example documentation string in the checkout under `examples/DOCUMENTATION.yml <https://github.com/ansible/ansible/blob/devel/examples/DOCUMENTATION.yml>`_.
You can copy it into your module and use it as a starting point
when writing your own docs.
Include it in your module file like this:: Include it in your module file like this::
...@@ -392,8 +387,9 @@ Include it in your module file like this:: ...@@ -392,8 +387,9 @@ Include it in your module file like this::
# ... snip ... # ... snip ...
''' '''
The ``description``, and ``notes`` The ``description``, and ``notes`` fields
support formatting in some of the output formats (e.g. ``rst``, ``man``). support formatting with some special macros.
These formatting functions are ``U()``, ``M()``, ``I()``, and ``C()`` These formatting functions are ``U()``, ``M()``, ``I()``, and ``C()``
for URL, module, italic, and constant-width respectively. It is suggested for URL, module, italic, and constant-width respectively. It is suggested
to use ``C()`` for file and option names, and ``I()`` when referencing to use ``C()`` for file and option names, and ``I()`` when referencing
...@@ -408,9 +404,8 @@ like this:: ...@@ -408,9 +404,8 @@ like this::
- action: modulename opt1=arg1 opt2=arg2 - action: modulename opt1=arg1 opt2=arg2
''' '''
The ``module_formatter.py`` script and ``ansible-doc(1)`` append the The EXAMPLES section, just like the documentation section, is required in
``EXAMPLES`` blob after any existing (deprecated) ``examples`` you may have in the all module pull requests for new modules.
YAML ``DOCUMENTATION`` string.
.. _module_dev_testing: .. _module_dev_testing:
......
Developing Plugins Developing Plugins
================== ==================
.. contents:: .. contents:: Topics
:depth: 2
Ansible is pluggable in a lot of other ways separate from inventory scripts and callbacks. Many of these features are there to cover fringe use cases and are infrequently needed, and others are pluggable simply because they are there to implement core features Ansible is pluggable in a lot of other ways separate from inventory scripts and callbacks. Many of these features are there to cover fringe use cases and are infrequently needed, and others are pluggable simply because they are there to implement core features
in ansible and were most convenient to be made pluggable. in ansible and were most convenient to be made pluggable.
...@@ -15,14 +14,14 @@ as often. ...@@ -15,14 +14,14 @@ as often.
Connection Type Plugins Connection Type Plugins
----------------------- -----------------------
By default, ansible ships with a 'paramiko' SSH, native ssh (just called 'ssh'), and 'local' connection type, and an accelerated connection type named 'fireball' -- there are also some minor players like 'chroot' and 'jail'. All of these can be used By default, ansible ships with a 'paramiko' SSH, native ssh (just called 'ssh'), 'local' connection type, and an accelerated connection type named 'fireball' (superseded in 1.3 by :doc:`playbooks_acceleration`) -- there are also some minor players like 'chroot' and 'jail'. All of these can be used
in playbooks and with /usr/bin/ansible to decide how you want to talk to remote machines. The basics of these connection types in playbooks and with /usr/bin/ansible to decide how you want to talk to remote machines. The basics of these connection types
are covered in the 'getting started' section. Should you want to extend Ansible to support other transports (SNMP? Message bus? are covered in the :doc:`intro_getting_started` section. Should you want to extend Ansible to support other transports (SNMP? Message bus?
Carrier Pigeon?) it's as simple as copying the format of one of the existing modules and dropping it into the connection plugins Carrier Pigeon?) it's as simple as copying the format of one of the existing modules and dropping it into the connection plugins
directory. The value of 'smart' for a connection allows selection of paramiko or openssh based on system capabilities, and chooses directory. The value of 'smart' for a connection allows selection of paramiko or openssh based on system capabilities, and chooses
'ssh' if OpenSSH supports ControlPersist, in Ansible 1.2.1 an later. Previous versions did not support 'smart'. 'ssh' if OpenSSH supports ControlPersist, in Ansible 1.2.1 an later. Previous versions did not support 'smart'.
More documentation on writing connection plugins is pending, though you can jump into lib/ansible/runner/connection_plugins and figure things out pretty easily. More documentation on writing connection plugins is pending, though you can jump into `lib/ansible/runner/connection_plugins <https://github.com/ansible/ansible/tree/devel/lib/ansible/runner/connection_plugins>`_ and figure things out pretty easily.
.. _developing_lookup_plugins: .. _developing_lookup_plugins:
...@@ -31,7 +30,7 @@ Lookup Plugins ...@@ -31,7 +30,7 @@ Lookup Plugins
Language constructs like "with_fileglob" and "with_items" are implemented via lookup plugins. Just like other plugin types, you can write your own. Language constructs like "with_fileglob" and "with_items" are implemented via lookup plugins. Just like other plugin types, you can write your own.
More documentation on writing connection plugins is pending, though you can jump into lib/ansible/runner/lookup_plugins and figure More documentation on writing connection plugins is pending, though you can jump into `lib/ansible/runner/lookup_plugins <https://github.com/ansible/ansible/tree/devel/lib/ansible/runner/lookup_plugins>`_ and figure
things out pretty easily. things out pretty easily.
.. _developing_vars_plugins: .. _developing_vars_plugins:
...@@ -43,7 +42,7 @@ Playbook constructs like 'host_vars' and 'group_vars' work via 'vars' plugins. ...@@ -43,7 +42,7 @@ Playbook constructs like 'host_vars' and 'group_vars' work via 'vars' plugins.
data into ansible runs that did not come from an inventory, playbook, or command line. Note that variables data into ansible runs that did not come from an inventory, playbook, or command line. Note that variables
can also be returned from inventory, so in most cases, you won't need to write or understand vars_plugins. can also be returned from inventory, so in most cases, you won't need to write or understand vars_plugins.
More documentation on writing connection plugins is pending, though you can jump into lib/ansible/inventory/vars_plugins and figure More documentation on writing connection plugins is pending, though you can jump into `lib/ansible/inventory/vars_plugins <https://github.com/ansible/ansible/tree/devel/lib/ansible/inventory/vars_plugins>`_ and figure
things out pretty easily. things out pretty easily.
If you find yourself wanting to write a vars_plugin, it's more likely you should write an inventory script instead. If you find yourself wanting to write a vars_plugin, it's more likely you should write an inventory script instead.
...@@ -53,9 +52,9 @@ If you find yourself wanting to write a vars_plugin, it's more likely you should ...@@ -53,9 +52,9 @@ If you find yourself wanting to write a vars_plugin, it's more likely you should
Filter Plugins Filter Plugins
-------------- --------------
If you want more Jinja2 filters available in a Jinja2 template (filters like to_yaml and to_json are provided by default), they can be extended by writing a filter plugin. Most of the time, when someone comes up with an idea for a new filter they would like to make available in a playbook, we'll just include them in 'core.py' instead. If you want more Jinja2 filters available in a Jinja2 template (filters like to_yaml and to_json are provided by default), they can be extended by writing a filter plugin. Most of the time, when someone comes up with an idea for a new filter they would like to make available in a playbook, we'll just include them in 'core.py' instead.
Jump into lib/ansible/runner/filter_plugins/ for details. Jump into `lib/ansible/runner/filter_plugins/ <https://github.com/ansible/ansible/tree/devel/lib/ansible/runner/filter_plugins>`_ for details.
.. _developing_callbacks: .. _developing_callbacks:
...@@ -69,27 +68,34 @@ Callbacks are one of the more interesting plugin types. Adding additional callb ...@@ -69,27 +68,34 @@ Callbacks are one of the more interesting plugin types. Adding additional callb
Examples Examples
++++++++ ++++++++
Example callbacks are shown `in github in the callbacks directory <https://github.com/ansible/ansible/tree/devel/plugins/callbacks>_`. Example callbacks are shown in `plugins/callbacks <https://github.com/ansible/ansible/tree/devel/plugins/callbacks>`_.
The 'log_plays' callback is an example of how to intercept playbook events to a log file, and the 'mail' callback sends email The `log_plays
when playbooks complete. <https://github.com/ansible/ansible/blob/devel/plugins/callbacks/log_plays.py>`_
callback is an example of how to intercept playbook events to a log
file, and the `mail
<https://github.com/ansible/ansible/blob/devel/plugins/callbacks/mail.py>`_
callback sends email when playbooks complete.
The 'osx_say' callback provided is particularly entertaining -- it will respond with computer synthesized speech on OS X in relation The `osx_say
to playbook events, and is guaranteed to entertain and/or annoy coworkers. <https://github.com/ansible/ansible/blob/devel/plugins/callbacks/osx_say.py>`_
callback provided is particularly entertaining -- it will respond with
computer synthesized speech on OS X in relation to playbook events,
and is guaranteed to entertain and/or annoy coworkers.
.. _configuring_callbacks: .. _configuring_callbacks:
Configuring Configuring
+++++++++++ +++++++++++
To active a callback drop it in a callback directory as configured in ansible.cfg. To active a callback drop it in a callback directory as configured in :ref:`ansible.cfg <callback_plugins>`.
.. _callback_development: .. _callback_development:
Development Development
+++++++++++ +++++++++++
More information will come later, though see the source of any of the existing callbacks and you should be able to get started quickly. More information will come later, though see the source of any of the existing callbacks and you should be able to get started quickly.
They should be reasonably self explanatory. They should be reasonably self explanatory.
.. _distributing_plugins: .. _distributing_plugins:
...@@ -125,4 +131,3 @@ In addition, plugins can be shipped in a subdirectory relative to a top-level pl ...@@ -125,4 +131,3 @@ In addition, plugins can be shipped in a subdirectory relative to a top-level pl
The development mailing list The development mailing list
`irc.freenode.net <http://irc.freenode.net>`_ `irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel #ansible IRC chat channel
...@@ -3,9 +3,6 @@ Frequently Asked Questions ...@@ -3,9 +3,6 @@ Frequently Asked Questions
Here are some commonly-asked questions and their answers. Here are some commonly-asked questions and their answers.
.. contents::
:depth: 2
.. _users_and_ports: .. _users_and_ports:
How do I handle different machines needing different user accounts or ports to log in with? How do I handle different machines needing different user accounts or ports to log in with?
...@@ -94,7 +91,7 @@ Where does the configuration file live and what can I configure in it? ...@@ -94,7 +91,7 @@ Where does the configuration file live and what can I configure in it?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
See `intro_configuration`. See :doc:`intro_configuration`.
.. _who_would_ever_want_to_disable_cowsay_but_ok_here_is_how: .. _who_would_ever_want_to_disable_cowsay_but_ok_here_is_how:
...@@ -141,6 +138,42 @@ Then you can use the facts inside your template, like this:: ...@@ -141,6 +138,42 @@ Then you can use the facts inside your template, like this::
{{ hostvars[host]['ansible_eth0']['ipv4']['address'] }} {{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}
{% endfor %} {% endfor %}
.. _programatic_access_to_a_variable:
How do I access a variable name programatically?
++++++++++++++++++++++++++++++++++++++++++++++++
An example may come up where we need to get the ipv4 address of an arbitrary interface, where the interface to be used may be supplied
via a role parameter or other input. Variable names can be built by adding strings together, like so::
{{ hostvars[inventory_hostname]['ansible_' + which_interface]['ipv4']['address'] }}
The trick about going through hostvars is neccessary because it's a dictionary of the entire namespace of variables. 'inventory_hostname'
is a magic variable that indiciates the current host you are looping over in the host loop.
.. _first_host_in_a_group:
How do I access a variable of the first host in a group?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
What happens if we want the ip address of the first webserver in the webservers group? Well, we can do that too. Note that if we
are using dynamic inventory, which host is the 'first' may not be consistent, so you wouldn't want to do this unless your inventory
was static and predictable. (If you are using AWX, it will use database order, so this isn't a problem even if you are using cloud
based inventory scripts).
Anyway, here's the trick::
{{ hostvars[groups['webservers'][0]]['ansible_eth0']['ipv4']['address'] }}
Notice how we're pulling out the hostname of the first machine of the webservers group. If you are doing this in a template, you
could use the Jinja2 '#set' directive to simplify this, or in a playbook, you could also use set_fact:
- set_fact: headnode={{ groups[['webservers'][0]] }}
- debug: msg={{ hostvars[headnode].ansible_eth0.ipv4.address }}
Notice how we interchanged the bracket syntax for dots -- that can be done anywhere.
.. _file_recursion: .. _file_recursion:
How do I copy files recursively onto a target host? How do I copy files recursively onto a target host?
...@@ -182,9 +215,19 @@ Ansible 1.4 will also make remote environment variables available via facts in t ...@@ -182,9 +215,19 @@ Ansible 1.4 will also make remote environment variables available via facts in t
How do I generate crypted passwords for the user module? How do I generate crypted passwords for the user module?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Crypted password values can be generated as follows:: The mkpasswd utility that is available on most Linux systems is a great option::
mkpasswd --method=SHA-512
If this utility is not installed on your system (e.g. you are using OS X) then you can still easily
generate these passwords using Python. First, ensure that the `Passlib <https://code.google.com/p/passlib/>`_
password hashing library is installed.
pip install passlib
Once the library is ready, SHA512 password values can then be generated as follows::
openssl passwd -salt <salt> -1 <plaintext> python -c "from passlib.hash import sha512_crypt; print sha512_crypt.encrypt('<password>')"
.. _commercial_support: .. _commercial_support:
...@@ -199,7 +242,7 @@ Is there a web interface / REST API / etc? ...@@ -199,7 +242,7 @@ Is there a web interface / REST API / etc?
++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++
Yes! AnsibleWorks makes a great product that makes Ansible even more powerful Yes! AnsibleWorks makes a great product that makes Ansible even more powerful
and easy to use: `AnsibleWorks AWX <http://ansibleworks.com/ansible-awx/>` and easy to use: `AnsibleWorks AWX <http://ansibleworks.com/ansible-awx/>`_.
.. _docs_contributions: .. _docs_contributions:
...@@ -215,7 +258,7 @@ I don't see my question here ...@@ -215,7 +258,7 @@ I don't see my question here
We're happy to help. We're happy to help.
See the "Resources" section of the documentation home page for a link to the IRC and Google Group. See the `Resources <http://www.ansibleworks.com/community/>`_ section of the documentation home page for a link to the IRC and Google Group.
.. seealso:: .. seealso::
......
AnsibleWorks Galaxy
```````````````````
.. image:: https://galaxy.ansibleworks.com/static/img/galaxy_logo_small.png
:alt: AnsibleWorks Galaxy Logo
:width: 619px
:height: 109px
`AnsibleWorks Galaxy <http://galaxy.ansibleworks.com>`_, is a free site for finding, downloading, rating, and reviewing all kinds of community developed Ansible roles and can be a great way to get a jumpstart on your automation projects.
You can sign up with social auth, and the download client 'ansible-galaxy' is included in Ansible 1.4.2 and later.
Read the "About" page on the Galaxy site for more information.
Glossary Glossary
======== ========
.. contents::
:depth: 2
The following is a list (and re-explanation) of term definitions used elsewhere in the Ansible documentation. The following is a list (and re-explanation) of term definitions used elsewhere in the Ansible documentation.
Consult the documentation home page for the full documentation and to see the terms in context, but this should be a good resource Consult the documentation home page for the full documentation and to see the terms in context, but this should be a good resource
...@@ -59,8 +56,8 @@ Conditionals ...@@ -59,8 +56,8 @@ Conditionals
++++++++++++ ++++++++++++
A conditional is an expression that evaluates to true or false that decides whether a given task will be executed on a given A conditional is an expression that evaluates to true or false that decides whether a given task will be executed on a given
machine or not. Ansible's conditionals include 'when_boolean', machine or not. Ansible's conditionals are powered by the 'when' statement, and are
'when_string', and 'when_integer'. These are discussed in the playbook documentation. discussed in the playbook documentation.
Diff Mode Diff Mode
+++++++++ +++++++++
...@@ -223,11 +220,6 @@ JSON ...@@ -223,11 +220,6 @@ JSON
Ansible uses JSON for return data from remote modules. This allows modules to be written in any language, not just Python. Ansible uses JSON for return data from remote modules. This allows modules to be written in any language, not just Python.
only_if
+++++++
A deprecated form of the "when:" statement. It should no longer be used.
Library Library
+++++++ +++++++
......
Amazon Web Services Guide Amazon Web Services Guide
========================= =========================
.. contents::
:depth: 2
.. _aws_intro: .. _aws_intro:
Introduction Introduction
...@@ -55,7 +52,7 @@ The ec2 module provides the ability to provision instances within EC2. Typicall ...@@ -55,7 +52,7 @@ The ec2 module provides the ability to provision instances within EC2. Typicall
exporting the variable as EC2_URL=https://myhost:8773/services/Eucalyptus. exporting the variable as EC2_URL=https://myhost:8773/services/Eucalyptus.
This can be set using the 'environment' keyword in Ansible if you like. This can be set using the 'environment' keyword in Ansible if you like.
Here is an example of provisioning a number of instances in ad-hoc mode mode: Here is an example of provisioning a number of instances in ad-hoc mode:
.. code-block:: bash .. code-block:: bash
...@@ -118,6 +115,22 @@ You may wish to schedule a regular refresh of the inventory cache to accommodate ...@@ -118,6 +115,22 @@ You may wish to schedule a regular refresh of the inventory cache to accommodate
Put this into a crontab as appropriate to make calls from your Ansible master server to the EC2 API endpoints and gather host information. The aim is to keep the view of hosts as up-to-date as possible, so schedule accordingly. Playbook calls could then also be scheduled to act on the refreshed hosts inventory after each refresh. This approach means that machine images can remain "raw", containing no payload and OS-only. Configuration of the workload is handled entirely by Ansible. Put this into a crontab as appropriate to make calls from your Ansible master server to the EC2 API endpoints and gather host information. The aim is to keep the view of hosts as up-to-date as possible, so schedule accordingly. Playbook calls could then also be scheduled to act on the refreshed hosts inventory after each refresh. This approach means that machine images can remain "raw", containing no payload and OS-only. Configuration of the workload is handled entirely by Ansible.
Tags
++++
There's a feature in the ec2 inventory script where hosts tagged with
certain keys and values automatically appear in certain groups.
For instance, if a host is given the "class" tag with the value of "webserver",
it will be automatically discoverable via a dynamic group like so::
- hosts: tag_class_webserver
tasks:
- ping
Using this philosophy can be a great way to manage groups dynamically, without
having to maintain seperate inventory.
.. _aws_pull: .. _aws_pull:
Pull Configuration Pull Configuration
...@@ -125,7 +138,7 @@ Pull Configuration ...@@ -125,7 +138,7 @@ Pull Configuration
For some the delay between refreshing host information and acting on that host information (i.e. running Ansible tasks against the hosts) may be too long. This may be the case in such scenarios where EC2 AutoScaling is being used to scale the number of instances as a result of a particular event. Such an event may require that hosts come online and are configured as soon as possible (even a 1 minute delay may be undesirable). Its possible to pre-bake machine images which contain the necessary ansible-pull script and components to pull and run a playbook via git. The machine images could be configured to run ansible-pull upon boot as part of the bootstrapping procedure. For some the delay between refreshing host information and acting on that host information (i.e. running Ansible tasks against the hosts) may be too long. This may be the case in such scenarios where EC2 AutoScaling is being used to scale the number of instances as a result of a particular event. Such an event may require that hosts come online and are configured as soon as possible (even a 1 minute delay may be undesirable). Its possible to pre-bake machine images which contain the necessary ansible-pull script and components to pull and run a playbook via git. The machine images could be configured to run ansible-pull upon boot as part of the bootstrapping procedure.
More information on pull-mode playbooks can be found `here <http://www.ansibleworks.com/docs/playbooks2.html#pull-mode-playbooks>`_. Read :ref:`ansible-pull` for more information on pull-mode playbooks.
(Various developments around Ansible are also going to make this easier in the near future. Stay tuned!) (Various developments around Ansible are also going to make this easier in the near future. Stay tuned!)
......
Rackspace Cloud Guide Rackspace Cloud Guide
===================== =====================
.. contents::
:depth: 3
.. _introduction: .. _introduction:
Introduction Introduction
...@@ -100,7 +97,7 @@ provisioning task will be performed from your Ansible control server against the ...@@ -100,7 +97,7 @@ provisioning task will be performed from your Ansible control server against the
specifying your username and API key as environment variables or passing specifying your username and API key as environment variables or passing
them as module arguments. them as module arguments.
Here is a basic example of provisioning a instance in ad-hoc mode mode: Here is a basic example of provisioning a instance in ad-hoc mode:
.. code-block:: bash .. code-block:: bash
...@@ -542,7 +539,7 @@ Build a complete webserver environment with servers, custom networks and load ba ...@@ -542,7 +539,7 @@ Build a complete webserver environment with servers, custom networks and load ba
module: rax_clb_nodes module: rax_clb_nodes
credentials: ~/.raxpub credentials: ~/.raxpub
load_balancer_id: "{{ clb.balancer.id }}" load_balancer_id: "{{ clb.balancer.id }}"
address: "{{ item.networks.private|first }}" address: "{{ item.rax_networks.private|first }}"
port: 80 port: 80
condition: enabled condition: enabled
type: primary type: primary
......
Continuous Delivery and Rolling Upgrades Continuous Delivery and Rolling Upgrades
======================================== ========================================
.. contents::
:depth: 2
.. _lamp_introduction: .. _lamp_introduction:
Introduction Introduction
...@@ -78,7 +75,7 @@ as push updates to all of the servers:: ...@@ -78,7 +75,7 @@ as push updates to all of the servers::
- base-apache - base-apache
- nagios - nagios
.. note: .. note::
If you're not familiar with terms like playbooks and plays, you should review :doc:`playbooks`. If you're not familiar with terms like playbooks and plays, you should review :doc:`playbooks`.
...@@ -121,7 +118,7 @@ Here is lamp_haproxy's ``group_vars/all`` file. As you might expect, these varia ...@@ -121,7 +118,7 @@ Here is lamp_haproxy's ``group_vars/all`` file. As you might expect, these varia
This is a YAML file, and you can create lists and dictionaries for more complex variable structures. This is a YAML file, and you can create lists and dictionaries for more complex variable structures.
In this case, we are just setting two variables, one for the port for the web server, and one for the In this case, we are just setting two variables, one for the port for the web server, and one for the
NTP server that our machiens should use for time synchronization. NTP server that our machines should use for time synchronization.
Here's another group variables file. This is ``group_vars/dbservers`` which applies to the hosts in the ``dbservers`` group:: Here's another group variables file. This is ``group_vars/dbservers`` which applies to the hosts in the ``dbservers`` group::
......
Using Vagrant and Ansible Using Vagrant and Ansible
========================= =========================
.. contents::
:depth: 2
.. _vagrant_intro: .. _vagrant_intro:
Introduction Introduction
......
Detailed Guides
```````````````
This section is new and evolving. The idea here is explore particular use cases in greater depth and provide a more "top down" explanation of some basic features.
.. toctree::
:maxdepth: 1
guide_aws
guide_rax
guide_vagrant
guide_rolling_upgrade
Pending topics may include: Docker, Jenkins, Google Compute Engine, Linode/Digital Ocean, Continous Deployment, and more.
...@@ -18,187 +18,25 @@ upgrade remote daemons or the problem of not being able to manage systems becaus ...@@ -18,187 +18,25 @@ upgrade remote daemons or the problem of not being able to manage systems becaus
You may be interested in reading about `some notable Ansible users <http://www.ansibleworks.com/users/>`_. You may be interested in reading about `some notable Ansible users <http://www.ansibleworks.com/users/>`_.
This documentation covers the current released version of Ansible (1.4.3) and also some development version features (1.5). For recent features, in each section, the version of Ansible where the feature is added is indicated. AnsibleWorks releases a new major release of Ansible approximately every 2 months. The core application evolves somewhat conservatively, valuing simplicity in language design and setup, while the community around new modules and plugins being developed and contributed moves very very quickly, typically adding 20 or so new modules in each release. This documentation covers the current released version of Ansible (1.4.4) and also some development version features (1.5). For recent features, in each section, the version of Ansible where the feature is added is indicated. AnsibleWorks releases a new major release of Ansible approximately every 2 months. The core application evolves somewhat conservatively, valuing simplicity in language design and setup, while the community around new modules and plugins being developed and contributed moves very very quickly, typically adding 20 or so new modules in each release.
.. _an_introduction: .. _an_introduction:
The Basics
``````````
Before we dive into the really fun parts -- playbooks, configuration management, deployment, and orchestration, we'll learn how to get Ansible installed and some basic concepts. We'll go over how to execute ad-hoc commands in parallel across your nodes using /usr/bin/ansible. We'll also see what sort of modules are available in Ansible's core (though you can also write your own, which we'll also show later).
.. toctree::
:maxdepth: 1
intro_installation
intro_getting_started
intro_inventory
intro_dynamic_inventory
intro_patterns
intro_adhoc
intro_configuration
Modules
```````
Ansible modules are resources that are distributed to remote nodes to make them perform particular tasks or match a particular
state. Ansible follows a "batteries included" philosophy, so you have a lot of great modules for all manner of
IT tasks in the core distribution. This means modules are well up-to-date and you don't have to hunt for an implementation
that will work on your platform. You may think of the module library as a toolbox full of useful system management tools,
and playbooks as the instructions for building something using those tools.
.. toctree::
:maxdepth: 1
modules
.. _overview:
Architecture Diagram
````````````````````
.. image:: http://www.ansibleworks.com/wp-content/uploads/2013/06/ANSIBLE_DIAGRAM.jpg
:alt: ansible architecture diagram
:width: 788px
:height: 436px
.. _introduction_to_playbooks:
Playbooks
`````````
Playbooks are Ansible's configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.
If Ansible modules are the tools in your workshop, playbooks are your design plans.
At a basic level, playbooks can be used to manage configurations of and deployments to remote machines. At a more advanced level, they can sequence multi-tier rollouts involving rolling updates, and can delegate actions to other hosts, interacting with monitoring servers and load balancers along the way.
While there's a lot of information here, there's no need to learn everything at once. You can start small and pick up more features
over time as you need them.
Playbooks are designed to be human-readable and are developed in a basic text language. There are multiple
ways to organize playbooks and the files they include, and we'll offer up some suggestions on that and making the most out of Ansible.
It is recommended to look at `Example Playbooks <https://github.com/ansible/ansible-examples>`_ while reading along with the playbook documentation. These illustrate best practices as well as how to put many of the various concepts together.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
intro
quickstart
playbooks playbooks
playbooks_roles playbooks_special_topics
playbooks_variables modules
playbooks_conditionals modules_by_category
playbooks_loops guides
playbooks_best_practices developing
awx
.. _advanced_topics_in_playbooks: community
galaxy
Special Topics In Playbooks
```````````````````````````
Here are some playbook features that not everyone may need to learn, but can be quite useful for particular applications.
Browsing these topics is recommended as you may find some useful tips here, but feel free to learn the basics of Ansible first
and adopt these only if they seem relevant or useful to your environment.
.. toctree::
:maxdepth: 1
playbooks_acceleration
playbooks_async
playbooks_checkmode
playbooks_delegation
playbooks_environment
playbooks_error_handling
playbooks_lookups
playbooks_prompts
playbooks_tags
.. _ansibleworks_awx:
AnsibleWorks AWX
````````````````
`AnsibleWorks <http://ansibleworks.com>`_, who also sponsors the Ansible community, also produces 'AWX', which is a web-based solution that makes Ansible even more easy to use for IT teams of all kinds. It's designed to be the hub for all of your automation tasks.
AWX allows you to control access to who can access what, even allowing sharing of SSH credentials without someone being able to transfer those credentials. Inventory can be graphically managed or synced with a wide variety of cloud sources. It logs all of your jobs, integrates well with LDAP, and has an amazing browsable REST API. Command line tools are available for easy integration
with Jenkins as well.
Find out more about AWX features and how to download it on the `AWX webpage <http://ansibleworks.com/ansibleworks-awx>`_. AWX
is free for usage for up to 10 nodes, and comes bundled with amazing support from AnsibleWorks. As you would expect, AWX is
installed using Ansible playbooks!
.. _ansibleworks_galaxy:
AnsibleWorks Galaxy
```````````````````
.. image:: https://galaxy.ansibleworks.com/static/img/galaxy_logo_small.png
:alt: AnsibleWorks Galaxy Logo
:width: 619px
:height: 109px
`AnsibleWorks Galaxy <http://galaxy.ansibleworks.com>`_, is a free site for finding, downloading, rating, and reviewing all kinds of community developed Ansible roles and can be a great way to get a jumpstart on your automation projects.
You can sign up with social auth, and the download client 'ansible-galaxy' is included in Ansible 1.4.2 and later.
Read the "About" page on the Galaxy site for more information.
.. _detailed_guides:
Detailed Guides
```````````````
This section is new and evolving. The idea here is explore particular use cases in greater depth and provide a more "top down" explanation of some basic features.
.. toctree::
:maxdepth: 1
guide_aws
guide_rax
guide_vagrant
guide_rolling_upgrade
Pending topics may include: Docker, Jenkins, Google Compute Engine, Linode/Digital Ocean, Continous Deployment, and more.
.. _community_information:
Community Information
`````````````````````
Ansible is an open source project designed to bring together developers and administrators of all kinds to collaborate on building
IT automation solutions that work well for them. Should you wish to get more involved -- whether in terms of just asking a question, helping other users, introducing new people to Ansible, or helping with the software or documentation, we welcome your contributions to the project.
`Ways to interact <https://github.com/ansible/ansible/blob/devel/CONTRIBUTING.md>`_
.. _developer_information:
Developer Information
`````````````````````
Learn how to build modules of your own in any language, and also how to extend Ansible through several kinds of plugins. Explore Ansible's Python API and write Python plugins to integrate with other solutions in your environment.
.. toctree::
:maxdepth: 1
developing_api
developing_inventory
developing_modules
developing_plugins
Developers will also likely be interested in the fully-discoverable `REST API <http://ansibleworks.com/ansibleworks-awx>`_ that is part of AnsibleWorks AWX. It's great for embedding Ansible in all manner of applications.
.. _misc:
Miscellaneous
`````````````
Some additional topics you may be interested in:
.. toctree::
:maxdepth: 1
faq faq
glossary glossary
YAMLSyntax YAMLSyntax
Introduction
============
Before we dive into the really fun parts -- playbooks, configuration management, deployment, and orchestration, we'll learn how to get Ansible installed and some basic concepts. We'll go over how to execute ad-hoc commands in parallel across your nodes using /usr/bin/ansible. We'll also see what sort of modules are available in Ansible's core (though you can also write your own, which we'll also show later).
.. toctree::
:maxdepth: 1
intro_installation
intro_getting_started
intro_inventory
intro_dynamic_inventory
intro_patterns
intro_adhoc
intro_configuration
Introduction To Ad-Hoc Commands Introduction To Ad-Hoc Commands
=============================== ===============================
.. contents:: Topics
.. highlight:: bash .. highlight:: bash
The following examples show how to use `/usr/bin/ansible` for running The following examples show how to use `/usr/bin/ansible` for running
...@@ -31,9 +33,6 @@ port over directly to the playbook language. ...@@ -31,9 +33,6 @@ port over directly to the playbook language.
If you haven't read :doc:`intro_inventory` already, please look that over a bit first If you haven't read :doc:`intro_inventory` already, please look that over a bit first
and then we'll get going. and then we'll get going.
.. contents::
:depth: 2
.. _parallelism_and_shell_commands: .. _parallelism_and_shell_commands:
Parallelism and Shell Commands Parallelism and Shell Commands
......
The Ansible Configuration File The Ansible Configuration File
++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
.. contents:: Topics
.. highlight:: bash .. highlight:: bash
Certain things in Ansible are adjustable in a configuration file. In general, the stock configuration is probably Certain things in Ansible are adjustable in a configuration file. In general, the stock configuration is probably
...@@ -15,9 +17,6 @@ The mechanism for doing this is the "ansible.cfg" file, which is looked for in t ...@@ -15,9 +17,6 @@ The mechanism for doing this is the "ansible.cfg" file, which is looked for in t
If multiple file locations matching the above exist, the last location on the above list is used. Settings in files If multiple file locations matching the above exist, the last location on the above list is used. Settings in files
are not merged together. are not merged together.
.. contents::
:depth: 2
.. _getting_the_latest_configuration: .. _getting_the_latest_configuration:
Getting the latest configuration Getting the latest configuration
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
Dynamic Inventory Dynamic Inventory
================= =================
.. contents:: Topics
Often a user of a configuration management system will want to keep inventory Often a user of a configuration management system will want to keep inventory
in a different software system. Ansible provides a basic text-based system as described in in a different software system. Ansible provides a basic text-based system as described in
:doc:`intro_inventory` but what if you want to use something else? :doc:`intro_inventory` but what if you want to use something else?
...@@ -16,9 +18,6 @@ Ansible easily supports all of these options via an external inventory system. ...@@ -16,9 +18,6 @@ Ansible easily supports all of these options via an external inventory system.
For information about writing your own dynamic inventory source, see :doc:`developing_inventory`. For information about writing your own dynamic inventory source, see :doc:`developing_inventory`.
.. contents::
:depth: 2
.. _cobbler_example: .. _cobbler_example:
......
Getting Started Getting Started
=============== ===============
.. contents:: .. contents:: Topics
:depth: 2
.. _gs_about: .. _gs_about:
About Foreword
````` ````````
Now that you've read :doc:`intro_installation` and installed Ansible, it's time to dig in and get Now that you've read :doc:`intro_installation` and installed Ansible, it's time to dig in and get
started with some commands. started with some commands.
......
Installation Installation
============ ============
.. contents:: .. contents:: Topics
:depth: 2
.. _getting_ansible: .. _getting_ansible:
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
Inventory Inventory
========= =========
.. contents:: Topics
Ansible works against multiple systems in your infrastructure at the Ansible works against multiple systems in your infrastructure at the
same time. It does this by selecting portions of systems listed in same time. It does this by selecting portions of systems listed in
Ansible's inventory file, which defaults to being saved in Ansible's inventory file, which defaults to being saved in
...@@ -12,9 +14,6 @@ Not only is this inventory configurable, but you can also use ...@@ -12,9 +14,6 @@ Not only is this inventory configurable, but you can also use
multiple inventory files at the same time (explained below) and also multiple inventory files at the same time (explained below) and also
pull inventory from dynamic or cloud sources, as described in :doc:`intro_dynamic_inventory`. pull inventory from dynamic or cloud sources, as described in :doc:`intro_dynamic_inventory`.
.. contents::
:depth: 2
.. _inventoryformat: .. _inventoryformat:
Hosts and Groups Hosts and Groups
...@@ -36,6 +35,9 @@ The format for /etc/ansible/hosts is an INI format and looks like this:: ...@@ -36,6 +35,9 @@ The format for /etc/ansible/hosts is an INI format and looks like this::
The things in brackets are group names, which are used in classifying systems The things in brackets are group names, which are used in classifying systems
and deciding what systems you are controlling at what times and for what purpose. and deciding what systems you are controlling at what times and for what purpose.
It is ok to put systems in more than one group, for instance a server could be both a webserver and a dbserver.
If you do, note that variables will come from all of the groups they are a member of, and variable precedence is detailed in a later chapter.
If you have hosts that run on non-standard SSH ports you can put the port number If you have hosts that run on non-standard SSH ports you can put the port number
after the hostname with a colon. Ports listed in your SSH config file won't be used, after the hostname with a colon. Ports listed in your SSH config file won't be used,
so it is important that you set them if things are not running on the default port:: so it is important that you set them if things are not running on the default port::
...@@ -191,7 +193,7 @@ mentioned:: ...@@ -191,7 +193,7 @@ mentioned::
ansible_ssh_pass ansible_ssh_pass
The ssh password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys) The ssh password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys)
ansible_sudo_pass ansible_sudo_pass
The sudo password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys) The sudo password to use (this is insecure, we strongly recommend using --ask-sudo-pass)
ansible_connection ansible_connection
Connection type of the host. Candidates are local, ssh or paramiko. The default is paramiko before Ansible 1.2, and 'smart' afterwards which detects whether usage of 'ssh' would be feasible based on whether ControlPersist is supported. Connection type of the host. Candidates are local, ssh or paramiko. The default is paramiko before Ansible 1.2, and 'smart' afterwards which detects whether usage of 'ssh' would be feasible based on whether ControlPersist is supported.
ansible_ssh_private_key_file ansible_ssh_private_key_file
......
Patterns Patterns
++++++++ ++++++++
.. contents:: .. contents:: Topics
:depth: 2
Patterns in Ansible are how we decide which hosts to manage. This can mean what hosts to communicate with, but in terms Patterns in Ansible are how we decide which hosts to manage. This can mean what hosts to communicate with, but in terms
of :doc:`playbooks` it actually means what hosts to apply a particular configuration or IT process to. of :doc:`playbooks` it actually means what hosts to apply a particular configuration or IT process to.
......
Ansible Modules About Modules
=============== =============
.. contents:: .. toctree::
:depth: 3 :maxdepth: 4
.. _modules_intro: .. _modules_intro:
Introduction Introduction
```````````` ````````````
Ansible ships with a number of modules (called the 'module library') Ansible ships with a number of modules (called the 'module library')
that can be executed directly on remote hosts or through :doc:`Playbooks <playbooks>`. that can be executed directly on remote hosts or through :doc:`Playbooks <playbooks>`.
Users can also write their own modules. These modules can control system
resources, like services, packages, or files (anything really), or Users can also write their own modules. These modules can control system resources, like services, packages, or files (anything really), or
handle executing system commands. handle executing system commands.
Let's review how we execute three different modules from the command line:: Let's review how we execute three different modules from the command line::
...@@ -23,65 +22,28 @@ Let's review how we execute three different modules from the command line:: ...@@ -23,65 +22,28 @@ Let's review how we execute three different modules from the command line::
ansible webservers -m command -a "/sbin/reboot -t now" ansible webservers -m command -a "/sbin/reboot -t now"
Each module supports taking arguments. Nearly all modules take ``key=value`` Each module supports taking arguments. Nearly all modules take ``key=value``
arguments, space delimited. Some modules take no arguments, and the arguments, space delimited. Some modules take no arguments, and the command/shell modules simply
command/shell modules simply take the string of the command you want to run. take the string of the command you want to run.
From playbooks, Ansible modules are executed in a very similar way:: From playbooks, Ansible modules are executed in a very similar way::
- name: reboot the servers - name: reboot the servers
action: command /sbin/reboot -t now action: command /sbin/reboot -t now
Version 0.8 and higher support the following shorter syntax:: Which can be abbreviated to::
- name: reboot the servers - name: reboot the servers
command: /sbin/reboot -t now command: /sbin/reboot -t now
All modules technically return JSON format data, though if you are using the All modules technically return JSON format data, though if you are using the command line or playbooks, you don't really need to know much about
command line or playbooks, you don't really need to know much about that. If you're writing your own module, you care, and this means you do not have to write modules in any particular language -- you get to choose.
that. If you're writing your own module, you care, and this means you do
not have to write modules in any particular language -- you get to choose.
Modules are `idempotent`, meaning they will seek to avoid changes to the system unless a change needs to be made. When using Ansible Modules are `idempotent`, meaning they will seek to avoid changes to the system unless a change needs to be made. When using Ansible
playbooks, these modules can trigger 'change events' in the form of notifying 'handlers' playbooks, these modules can trigger 'change events' in the form of notifying 'handlers' to run additional tasks.
to run additional tasks.
Documentation for each module can be accessed from the command line with the
ansible-doc as well as the man command::
ansible-doc command
man ansible.template
Let's see what's available in the Ansible module library, out of the box:
.. include:: modules/_list.rst
.. _ansible_doc:
Reading Module Documentation Locally
````````````````````````````````````
ansible-doc is a friendly command line tool that allows you to access module documentation locally.
It comes with Ansible.
To list documentation for a particular module::
ansible-doc yum | less
To list all modules available::
ansible-doc --list | less
To access modules outside of the stock module path (such as custom modules that live in your playbook directory),
use the '--module-path' option to specify the directory where the module lives.
.. _writing_modules:
Writing your own modules Documentation for each module can be accessed from the command line with the ansible-doc tool::
````````````````````````
See :doc:`developing_modules`. ansible-doc yum
.. seealso:: .. seealso::
......
Accelerated Mode Accelerated Mode
================ ================
.. contents::
:depth: 2
.. versionadded:: 1.3 .. versionadded:: 1.3
While OpenSSH using the ControlPersist feature is quite fast and scalable, there is a certain small amount of overhead involved in While OpenSSH using the ControlPersist feature is quite fast and scalable, there is a certain small amount of overhead involved in
......
Asynchronous Actions and Polling Asynchronous Actions and Polling
================================ ================================
.. contents::
:depth: 2
By default tasks in playbooks block, meaning the connections stay open By default tasks in playbooks block, meaning the connections stay open
until the task is done on each node. This may not always be desirable, or you may until the task is done on each node. This may not always be desirable, or you may
be running operations that take longer than the SSH timeout. be running operations that take longer than the SSH timeout.
......
...@@ -5,8 +5,7 @@ Here are some tips for making the most of Ansible playbooks. ...@@ -5,8 +5,7 @@ Here are some tips for making the most of Ansible playbooks.
You can find some example playbooks illustrating these best practices in our `ansible-examples repository <https://github.com/ansible/ansible-examples>`_. (NOTE: These may not use all of the features in the latest release, but are still an excellent reference!). You can find some example playbooks illustrating these best practices in our `ansible-examples repository <https://github.com/ansible/ansible-examples>`_. (NOTE: These may not use all of the features in the latest release, but are still an excellent reference!).
.. contents:: .. contents:: Topics
:depth: 2
.. _content_organization: .. _content_organization:
......
Check Mode ("Dry Run") Check Mode ("Dry Run")
====================== ======================
.. contents::
:depth: 2
.. versionadded:: 1.1 .. versionadded:: 1.1
.. contents:: Topics
When ansible-playbook is executed with --check it will not make any changes on remote systems. Instead, any module When ansible-playbook is executed with --check it will not make any changes on remote systems. Instead, any module
instrumented to support 'check mode' (which contains most of the primary core modules, but it is not required that all modules do instrumented to support 'check mode' (which contains most of the primary core modules, but it is not required that all modules do
this) will report what changes they would have made rather than making them. Other modules that do not support check mode will also take no action, but just will not report what changes they might have made. this) will report what changes they would have made rather than making them. Other modules that do not support check mode will also take no action, but just will not report what changes they might have made.
......
Conditionals Conditionals
============ ============
.. contents:: .. contents:: Topics
:depth: 2
Often the result of a play may depend on the value of a variable, fact (something learned about the remote system), Often the result of a play may depend on the value of a variable, fact (something learned about the remote system),
or previous task result. In some cases, the values of variables may depend on other variables. or previous task result. In some cases, the values of variables may depend on other variables.
...@@ -21,7 +21,7 @@ Sometimes you will want to skip a particular step on a particular host. This co ...@@ -21,7 +21,7 @@ Sometimes you will want to skip a particular step on a particular host. This co
as simple as not installing a certain package if the operating system is a particular version, as simple as not installing a certain package if the operating system is a particular version,
or it could be something like performing some cleanup steps if a filesystem is getting full. or it could be something like performing some cleanup steps if a filesystem is getting full.
This is easy to do in Ansible, with the `when` clause, which contains a Jinja2 expression (see `playbooks_variables`). This is easy to do in Ansible, with the `when` clause, which contains a Jinja2 expression (see :doc:`playbooks_variables`).
It's actually pretty simple:: It's actually pretty simple::
tasks: tasks:
...@@ -82,7 +82,7 @@ If a required variable has not been set, you can skip or fail using Jinja2's ...@@ -82,7 +82,7 @@ If a required variable has not been set, you can skip or fail using Jinja2's
- shell: echo "I've got '{{ foo }}' and am not afraid to use it!" - shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
when: foo is defined when: foo is defined
- fail: msg="Bailing out: this play requires 'bar'" - fail: msg="Bailing out. this play requires 'bar'"
when: bar is not defined when: bar is not defined
This is especially useful in combination with the conditional import of vars This is especially useful in combination with the conditional import of vars
...@@ -125,7 +125,7 @@ Or with a role:: ...@@ -125,7 +125,7 @@ Or with a role::
- { role: debian_stock_config, when: ansible_os_family == 'Debian' } - { role: debian_stock_config, when: ansible_os_family == 'Debian' }
You will note a lot of 'skipped' output by default in Ansible when using this approach on systems that don't match the criteria. You will note a lot of 'skipped' output by default in Ansible when using this approach on systems that don't match the criteria.
Read up on the 'group_by' module in the `modules` docs for a more streamlined way to accomplish the same thing. Read up on the 'group_by' module in the :doc:`modules` docs for a more streamlined way to accomplish the same thing.
Conditional Imports Conditional Imports
``````````````````` ```````````````````
...@@ -193,10 +193,10 @@ The following example shows how to template out a configuration file that was ve ...@@ -193,10 +193,10 @@ The following example shows how to template out a configuration file that was ve
- name: template a file - name: template a file
template: src={{ item }} dest=/etc/myapp/foo.conf template: src={{ item }} dest=/etc/myapp/foo.conf
with_first_found: with_first_found:
files: - files:
- {{ ansible_distribution }}.conf - {{ ansible_distribution }}.conf
- default.conf - default.conf
paths: paths:
- search_location_one/somedir/ - search_location_one/somedir/
- /opt/other_location/somedir/ - /opt/other_location/somedir/
......
Delegation, Rolling Updates, and Local Actions Delegation, Rolling Updates, and Local Actions
============================================== ==============================================
.. contents:: .. contents:: Topics
:depth: 2
Being designed for multi-tier deployments since the beginning, Ansible is great at doing things on one host on behalf of another, or doing local steps with reference to some remote hosts. Being designed for multi-tier deployments since the beginning, Ansible is great at doing things on one host on behalf of another, or doing local steps with reference to some remote hosts.
......
Setting the Environment (and Working With Proxies) Setting the Environment (and Working With Proxies)
================================================== ==================================================
.. contents::
:depth: 2
.. versionadded:: 1.1 .. versionadded:: 1.1
It is quite possible that you may need to get package updates through a proxy, or even get some package It is quite possible that you may need to get package updates through a proxy, or even get some package
......
Error Handling In Playbooks Error Handling In Playbooks
=========================== ===========================
.. contents:: .. contents:: Topics
:depth: 2
Ansible normally has defaults that make sure to check the return codes of commands and modules and Ansible normally has defaults that make sure to check the return codes of commands and modules and
it fails fast -- forcing an error to be dealt with unless you decide otherwise. it fails fast -- forcing an error to be dealt with unless you decide otherwise.
......
Using Lookups Using Lookups
============= =============
.. contents::
:depth: 2
Lookup plugins allow access of data in Ansible from outside sources. This can include the filesystem Lookup plugins allow access of data in Ansible from outside sources. This can include the filesystem
but also external datastores. These values are then made available using the standard templating system but also external datastores. These values are then made available using the standard templating system
in Ansible, and are typically used to load variables or templates with information from those systems. in Ansible, and are typically used to load variables or templates with information from those systems.
.. note:: This is considered an advanced feature, and many users will probably not rely on these features. .. note:: This is considered an advanced feature, and many users will probably not rely on these features.
.. contents:: Topics
.. _getting_file_contents: .. _getting_file_contents:
Intro to Lookups: Getting File Contents Intro to Lookups: Getting File Contents
......
Loops Loops
===== =====
.. contents::
:depth: 2
Often you'll want to do many things in one task, such as create a lot of users, install a lot of packages, or Often you'll want to do many things in one task, such as create a lot of users, install a lot of packages, or
repeat a polling step until a certain result is reached. repeat a polling step until a certain result is reached.
This chapter is all about how to use loops in playbooks. This chapter is all about how to use loops in playbooks.
.. contents:: Topics
.. _standard_loops: .. _standard_loops:
Standard Loops Standard Loops
...@@ -321,7 +320,7 @@ That's how! ...@@ -321,7 +320,7 @@ That's how!
Using register with a loop Using register with a loop
`````````````````````````` ``````````````````````````
When using ``register`` with a loop the data strucutre placed in the variable during a loop, will contain a ``results`` attribute, that is a list of all responses from the module. When using ``register`` with a loop the data structure placed in the variable during a loop, will contain a ``results`` attribute, that is a list of all responses from the module.
Here is an example of using ``register`` with ``with_items``:: Here is an example of using ``register`` with ``with_items``::
...@@ -331,7 +330,7 @@ Here is an example of using ``register`` with ``with_items``:: ...@@ -331,7 +330,7 @@ Here is an example of using ``register`` with ``with_items``::
- two - two
register: echo register: echo
This differs from the data strucutre returned when using ``register`` without a loop:: This differs from the data structure returned when using ``register`` without a loop::
{ {
"changed": true, "changed": true,
...@@ -383,7 +382,7 @@ Subsequent loops over the registered variable to inspect the results may look li ...@@ -383,7 +382,7 @@ Subsequent loops over the registered variable to inspect the results may look li
Writing Your Own Iterators Writing Your Own Iterators
`````````````````````````` ``````````````````````````
While you ordinarily shouldn't have to, should you wish to write your own ways to loop over arbitrary datastructures, you can read `developing_plugins` for some starter While you ordinarily shouldn't have to, should you wish to write your own ways to loop over arbitrary datastructures, you can read :doc:`developing_plugins` for some starter
information. Each of the above features are implemented as plugins in ansible, so there are many implementations to reference. information. Each of the above features are implemented as plugins in ansible, so there are many implementations to reference.
.. seealso:: .. seealso::
......
Prompts Prompts
======= =======
.. contents::
:depth: 2
When running a playbook, you may wish to prompt the user for certain input, and can When running a playbook, you may wish to prompt the user for certain input, and can
do so with the 'vars_prompt' section. do so with the 'vars_prompt' section.
......
Playbook Roles and Include Statements Playbook Roles and Include Statements
===================================== =====================================
.. contents:: .. contents:: Topics
:depth: 2
Introduction Introduction
```````````` ````````````
......
Playbooks: Special Topics
`````````````````````````
Here are some playbook features that not everyone may need to learn, but can be quite useful for particular applications.
Browsing these topics is recommended as you may find some useful tips here, but feel free to learn the basics of Ansible first
and adopt these only if they seem relevant or useful to your environment.
.. toctree::
:maxdepth: 1
playbooks_acceleration
playbooks_async
playbooks_checkmode
playbooks_delegation
playbooks_environment
playbooks_error_handling
playbooks_lookups
playbooks_prompts
playbooks_tags
Tags Tags
==== ====
.. contents::
:depth: 2
If you have a large playbook it may become useful to be able to run a If you have a large playbook it may become useful to be able to run a
specific part of the configuration without running the whole playbook. specific part of the configuration without running the whole playbook.
......
Variables Variables
========= =========
.. contents:: Topics
While automation exists to make it easier to make things repeatable, all of your systems are likely not exactly alike. While automation exists to make it easier to make things repeatable, all of your systems are likely not exactly alike.
All of your systems are likely not the same. On some systems you may want to set some behavior All of your systems are likely not the same. On some systems you may want to set some behavior
...@@ -15,15 +17,12 @@ based on those variables. ...@@ -15,15 +17,12 @@ based on those variables.
Variables in Ansible are how we deal with differences between systems. Variables in Ansible are how we deal with differences between systems.
Once understanding variables you'll also want to dig into `playbooks_conditionals` and `playbooks_loops`. Once understanding variables you'll also want to dig into :doc:`playbooks_conditionals` and :doc:`playbooks_loops`.
Useful things like the "group_by" module Useful things like the "group_by" module
and the "when" conditional can also be used with variables, and to help manage differences between systems. and the "when" conditional can also be used with variables, and to help manage differences between systems.
It's highly recommended that you consult the ansible-examples github repository to see a lot of examples of variables put to use. It's highly recommended that you consult the ansible-examples github repository to see a lot of examples of variables put to use.
.. contents::
:depth: 2
.. _valid_variable_names: .. _valid_variable_names:
What Makes A Valid Variable Name What Makes A Valid Variable Name
...@@ -50,7 +49,7 @@ a bit of a refresher. ...@@ -50,7 +49,7 @@ a bit of a refresher.
Often you'll want to set variables based on what groups a machine is in. For instance, maybe machines in Boston Often you'll want to set variables based on what groups a machine is in. For instance, maybe machines in Boston
want to use 'boston.ntp.example.com' as an NTP server. want to use 'boston.ntp.example.com' as an NTP server.
See the `intro_inventory` document for multiple ways on how to define variables in inventory. See the :doc:`intro_inventory` document for multiple ways on how to define variables in inventory.
.. _playbook_variables: .. _playbook_variables:
...@@ -68,11 +67,11 @@ This can be nice as it's right there when you are reading the playbook. ...@@ -68,11 +67,11 @@ This can be nice as it's right there when you are reading the playbook.
.. _included_variables: .. _included_variables:
Variables defined from included files and roles Variables defined from included files and roles
----------------------------------------------- ```````````````````````````````````````````````
It turns out we've already talked about variables in another place too. It turns out we've already talked about variables in another place too.
As described in `intro_roles`, variables can also be included in the playbook via include files, which may or may As described in :doc:`playbooks_roles`, variables can also be included in the playbook via include files, which may or may
not be part of an "Ansible Role". Usage of roles is preferred as it provides a nice organizational system. not be part of an "Ansible Role". Usage of roles is preferred as it provides a nice organizational system.
.. _about_jinja2: .. _about_jinja2:
...@@ -86,13 +85,13 @@ Ansible allows you to ...@@ -86,13 +85,13 @@ Ansible allows you to
reference variables in your playbooks using the Jinja2 templating system. While you can do a lot of complex reference variables in your playbooks using the Jinja2 templating system. While you can do a lot of complex
things in Jinja, only the basics are things you really need to learn at first. things in Jinja, only the basics are things you really need to learn at first.
For instance, in a simple template, you can do something like For instance, in a simple template, you can do something like::
My amp goes to {{ max_amp_value }} My amp goes to {{ max_amp_value }}
And that will provide the most basic form of variable substitution. And that will provide the most basic form of variable substitution.
This is also valid directly in playbooks, and you'll occasionally want to do things like: This is also valid directly in playbooks, and you'll occasionally want to do things like::
template: src=foo.cfg.j2 dest={{ remote_install_path}}/foo.cfg template: src=foo.cfg.j2 dest={{ remote_install_path}}/foo.cfg
...@@ -111,7 +110,7 @@ it's more than that -- you can also read variables about other hosts. We'll sho ...@@ -111,7 +110,7 @@ it's more than that -- you can also read variables about other hosts. We'll sho
Jinja2 Filters Jinja2 Filters
`````````````` ``````````````
.. note: These are infrequently utilized features. Use them if they fit a use case you have, but this is optional knowledge. .. note:: These are infrequently utilized features. Use them if they fit a use case you have, but this is optional knowledge.
Filters in Jinja2 are a way of transforming template expressions from one kind of data into another. Jinja2 Filters in Jinja2 are a way of transforming template expressions from one kind of data into another. Jinja2
ships with many of these as documented on the official Jinja2 template documentation. ships with many of these as documented on the official Jinja2 template documentation.
...@@ -191,9 +190,9 @@ To get the difference of 2 lists (items in 1 that don't exist in 2):: ...@@ -191,9 +190,9 @@ To get the difference of 2 lists (items in 1 that don't exist in 2)::
{{ list1 |difference(list2)}} {{ list1 |difference(list2)}}
To get the symetric difference of 2 lists (items exclusive to each list):: To get the symmetric difference of 2 lists (items exclusive to each list)::
{{ list1 |symetric_difference(list2)}} {{ list1 |symmetric_difference(list2)}}
.. _other_useful_filters: .. _other_useful_filters:
...@@ -233,7 +232,7 @@ Hey Wait, A YAML Gotcha ...@@ -233,7 +232,7 @@ Hey Wait, A YAML Gotcha
``````````````````````` ```````````````````````
YAML syntax requires that if you start a value with {{ foo }} you quote the whole line, since it wants to be YAML syntax requires that if you start a value with {{ foo }} you quote the whole line, since it wants to be
sure you aren't trying to start a YAML dictionary. This is covered on the `YAMLSyntax` page. sure you aren't trying to start a YAML dictionary. This is covered on the :doc:`YAMLSyntax` page.
This won't work:: This won't work::
...@@ -573,7 +572,7 @@ Registered Variables ...@@ -573,7 +572,7 @@ Registered Variables
Another major use of variables is running a command and using the result of that command to save the result into a variable. Another major use of variables is running a command and using the result of that command to save the result into a variable.
The value of a task being executed in ansible can be saved in a variable and used later. See some examples of this in the The value of a task being executed in ansible can be saved in a variable and used later. See some examples of this in the
`playbooks_conditionals` chapter. :doc:`playbooks_conditionals` chapter.
While it's mentioned elsewhere in that document too, here's a quick syntax example:: While it's mentioned elsewhere in that document too, here's a quick syntax example::
...@@ -650,8 +649,6 @@ A frequently used idiom is walking a group to find all IP addresses in that grou ...@@ -650,8 +649,6 @@ A frequently used idiom is walking a group to find all IP addresses in that grou
An example of this could include pointing a frontend proxy server to all of the app servers, setting up the correct firewall rules between servers, etc. An example of this could include pointing a frontend proxy server to all of the app servers, setting up the correct firewall rules between servers, etc.
Just a few other 'magic' variables are available... There aren't many.
Additionally, *inventory_hostname* is the name of the hostname as configured in Ansible's inventory host file. This can Additionally, *inventory_hostname* is the name of the hostname as configured in Ansible's inventory host file. This can
be useful for when you don't want to rely on the discovered hostname `ansible_hostname` or for other mysterious be useful for when you don't want to rely on the discovered hostname `ansible_hostname` or for other mysterious
reasons. If you have a long FQDN, *inventory_hostname_short* also contains the part up to the first reasons. If you have a long FQDN, *inventory_hostname_short* also contains the part up to the first
...@@ -740,7 +737,7 @@ or in a file as above. ...@@ -740,7 +737,7 @@ or in a file as above.
Conditional Imports Conditional Imports
``````````````````` ```````````````````
.. note: this behavior is infrequently used in Ansible. You may wish to skip this section. The 'group_by' module as described in the module documentation is a better way to achieve this behavior in most cases. .. note:: This behavior is infrequently used in Ansible. You may wish to skip this section. The 'group_by' module as described in the module documentation is a better way to achieve this behavior in most cases.
Sometimes you will want to do certain things differently in a playbook based on certain criteria. Sometimes you will want to do certain things differently in a playbook based on certain criteria.
Having one playbook that works on multiple platforms and OS versions is a good example. Having one playbook that works on multiple platforms and OS versions is a good example.
...@@ -820,7 +817,7 @@ control you might want over values. ...@@ -820,7 +817,7 @@ control you might want over values.
First off, group variables are super powerful. First off, group variables are super powerful.
Site wide defaults should be defined as a 'group_vars/all' setting. Group variables are generally placed alongside Site wide defaults should be defined as a 'group_vars/all' setting. Group variables are generally placed alongside
your inventory file. They can also be returned by a dynamic inventory script (see `intro_dynamic_inventory`) or defined your inventory file. They can also be returned by a dynamic inventory script (see :doc:`intro_dynamic_inventory`) or defined
in things like AnsibleWorks AWX from the UI or API:: in things like AnsibleWorks AWX from the UI or API::
--- ---
...@@ -838,7 +835,7 @@ If for some crazy reason we wanted to tell just a specific host to use a specifi ...@@ -838,7 +835,7 @@ If for some crazy reason we wanted to tell just a specific host to use a specifi
--- ---
# file: /etc/ansible/host_vars/xyz.boston.example.com # file: /etc/ansible/host_vars/xyz.boston.example.com
ntp-server: override.example.com ntp_server: override.example.com
So that covers inventory and what you would normally set there. It's a great place for things that deal with geography or behavior. Since groups are frequently the entity that maps roles onto hosts, it is sometimes a shortcut to set variables on the group instead of defining them on a role. You could go either way. So that covers inventory and what you would normally set there. It's a great place for things that deal with geography or behavior. Since groups are frequently the entity that maps roles onto hosts, it is sometimes a shortcut to set variables on the group instead of defining them on a role. You could go either way.
......
Quickstart Video
````````````````
We've recorded a short video that shows how to get started with Ansible that you may like to use alongside the documentation.
The `quickstart video <http://ansibleworks.com/quickstart/>`_ is about 20 minutes long and will show you some of the basics about your
first steps with Ansible.
Enjoy, and be sure to visit the rest of the documentation to learn more.
...@@ -131,6 +131,16 @@ filter_plugins = /usr/share/ansible_plugins/filter_plugins ...@@ -131,6 +131,16 @@ filter_plugins = /usr/share/ansible_plugins/filter_plugins
# control_path = %(directory)s/%%h-%%r # control_path = %(directory)s/%%h-%%r
#control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r #control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r
# Enabling pipelining reduces the number of SSH operations required to
# execute a module on the remote server. This can result in a significant
# performance improvement when enabled, however when using "sudo:" you must
# first disable 'requiretty' in /etc/sudoers
#
# By default, this option is disabled to preserve compatibility with
# sudoers configurations that have requiretty (the default on many distros).
#
#pipelining = False
# if True, make ansible use scp if the connection type is ssh # if True, make ansible use scp if the connection type is ssh
# (default is sftp) # (default is sftp)
#scp_if_ssh = True #scp_if_ssh = True
......
<!-- @{ module | upper }@ -->
<h2>@{module}@</h2>
{% for desc in description -%}
@{ desc | jpfunc }@
{% endfor %}
function AnsibleModules($scope) {
$scope.modules = @{ json }@;
$scope.orderProp = "module";
}
{# -------------------------------------------------------------------
template for module_formatter.py for LaTeX output (Ansible Booklet)
by Jan-Piet Mens.
Note: nodes & code examples are omitted on purpose.
-------------------------------------------------------------------- #}
%--- @{ module | upper }@ ---- from @{ filename }@ ---
%: -- module header
\mods{@{module}@}{@{docuri}@}{
{% for desc in description -%}
@{ desc | jpfunc }@
{% endfor -%}
{% if version_added is defined -%}
(\I{* new in version @{ version_added }@})
{% endif -%}
}
%: -- module options
{% if options %}
\begin{xlist}{abcdefghijklmno}
{% for (opt,v) in options.iteritems() %}
{% if v['required'] %}
\item[\man\,\C{@{ opt }@}]
{% else %}
\item[\opt\,\C{@{ opt }@}]
{% endif %}
{# -------- option description ----------#}
{% for desc in v.description %}
@{ desc | jpfunc }@
{% endfor %}
{% if v['choices'] %}
\B{Choices}:\,
{% for choice in v['choices'] %}\C{@{ choice }@}{% if not loop.last %},{% else %}.{% endif %}
{% endfor %}
{% endif %}
{% if v['default'] %}
(default \C{@{ v['default'] }@})
{% endif %}
{% if v['version_added'] is defined %}
(\I{* version @{ v['version_added'] }@})
{% endif %}
{% endfor %}
\end{xlist}
{% endif %}
{# ---------------------------------------
{% if notes %}
{% for note in notes %}
\I{@{ note | jpfunc }@}
{% endfor %}
{% endif %}
----------------------------- #}
{#-------------------------------------------
{% if examples is defined -%}
{% for e in examples %}
\begin{extymeta}
@{ e['code'] }@
\end{extymeta}
{% endfor %}
{% endif %}
----------------------------------- #}
{% if extradata is defined %}
%--- BEGIN-EXTRADATA
\begin{extymeta}
@{ extradata }@
\end{extymeta}
%----- END-EXTRADATA
{% endif %}
.TH ANSIBLE.@{ module | upper }@ 3 "@{ now_date }@" "@{ ansible_version }@" "ANSIBLE MODULES"
.\" generated from @{ filename }@
.SH NAME
@{ module }@ \- @{ short_description }@
.\" ------ DESCRIPTION
.SH DESCRIPTION
{% for desc in description %}
.PP
@{ desc | jpfunc }@
{% endfor %}
.\" ------ OPTIONS
.\"
.\"
{% if options %}
.SH OPTIONS
{% for k in option_keys %}
{% set v = options[k] %}
.IP @{ k }@
{% for desc in v.description %}@{ desc | jpfunc }@{% endfor %}
{% if v.get('choices') %}
.IR Choices :
{% for choice in v.get('choices',[]) %}{% if choice == True %}yes{%elif choice == False %}no{% else %}@{ choice }@{% endif %}{% if not loop.last %},{%else%}.{%endif%}{% endfor %}{% endif %}
{% if v.get('required') %}(required){% endif %}
{% if v.get('default') %} (default: {% if v.get('default') == True %}yes{%elif v.get('default') == False %}no{% else %}@{ v.get('default') }@){% endif %}{% endif %}
{#---------------------------------------------- #}
{% if v.get('version_added') %}
(Added in Ansible version @{ v.get('version_added') }@.)
{% endif %}
{% endfor %}
{% endif %}
.\"
.\"
.\" ------ NOTES
{% if notes %}
.SH NOTES
{% for note in notes %}
.PP
@{ note | jpfunc }@
{% endfor %}
{% endif %}
.\"
.\"
.\" ------ EXAMPLES
{% if examples is defined %}
.SH EXAMPLES
{% for e in examples %}
.PP
{% if e['description'] %}
@{ e['description'] | jpfunc }@
{% endif %}
.nf
@{ e['code'] }@
.fi
{% endfor %}
{% endif %}
.\" ------ PLAINEXAMPLES
{% if plainexamples is defined %}
.SH EXAMPLES
.nf
@{ plainexamples }@
.fi
{% endif %}
.\" ------- AUTHOR
{% if author is defined %}
.SH AUTHOR
@{ author }@
{% endif %}
.SH SEE ALSO
.IR ansible (1),
.I http://ansible.github.com/modules.html#@{docuri}@
## @{ module | jpfunc }@
{# ------------------------------------------
#
# This is Github-flavored Markdown
#
--------------------------------------------#}
{% if version_added is defined -%}
New in version @{ version_added }@.
{% endif %}
{% for desc in description -%}
@{ desc | jpfunc }@
{% endfor %}
{% if options -%}
<table>
<tr>
<th class="head">parameter</th>
<th class="head">required</th>
<th class="head">default</th>
<th class="head">choices</th>
<th class="head">comments</th>
</tr>
{% for (k,v) in options.iteritems() %}
<tr>
<td>@{ k }@</td>
<td>{% if v.get('required', False) %}yes{% else %}no{% endif %}</td>
<td>{% if v['default'] %}@{ v['default'] }@{% endif %}</td>
<td><ul>{% for choice in v.get('choices',[]) -%}<li>@{ choice }@</li>{% endfor -%}</ul></td>
<td>{% for desc in v.description -%}@{ desc | html_ify }@{% endfor -%}{% if v['version_added'] %} (added in Ansible @{v['version_added']}@){% endif %}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if examples or plainexamples %}
#### Examples
{% endif %}
{% for example in examples %}
{% if example['description'] %}
* @{ example['description'] | jpfunc }@
{% endif %}
```
@{ example['code'] }@
```
{% endfor %}
{% if plainexamples -%}
```
@{ plainexamples }@
```
{% endif %}
{% if notes %}
#### Notes
{% for note in notes %}
@{ note | jpfunc }@
{% endfor %}
{% endif %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment