Subtree merge of ansible-docs

This commit is contained in:
Michael DeHaan
2012-10-08 07:44:38 -04:00
113 changed files with 21134 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
YAML Syntax
===========
This page provides a basic overview of correct YAML syntax, which is how Ansible
playbooks (our configuration management language) are expressed.
We use YAML because it is easier to read and write for humans than other common
data formats like XML or JSON. Further, there are libraries available for reading
and writing YAML in most programming languages.
You may also wish to read :doc:`playbooks` at the same time to see how this
is used in practice.
YAML Basics
-----------
For `ansible`, nearly every YAML file starts with a list.
Each item in the list is a list of key/value pairs, commonly
called a "hash" or a "dictionary". So, we need to know how
to write lists and dictionaries in YAML.
There's another small quirk to YAML. All YAML files (regardless of their association with
`ansible` or not) should start with ``---``. This is just a YAML
format thing that means "this is the start of a document".
All members of a list are lines beginning at the same indentation level starting
with a ``-`` (dash) character::
---
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
A dictionary is represented in a simple ``key:`` and ``value`` form::
---
# An employee record
name: John Eckersberg
job: Developer
skill: Elite
Dictionaries can also be represented in an abbreviated form if you really want to::
---
# An employee record
{name: John Eckersberg, job: Developer, skill: Elite}
.. _truthiness:
Ansible doesn't really use these too much, but you can also specify a
boolean value (true/false) in several forms::
---
knows_oop: True
likes_emacs: TRUE
uses_cvs: false
Let's combine what we learned so far in an arbitary YAML example. This really
has nothing to do with Ansible, but will give you a feel for the format::
---
# An employee record
name: John Eckersberg
job: Developer
skill: Elite
employed: True
foods:
- Apple
- Orange
- Strawberry
- Mango
languages:
ruby: Elite
python: Elite
dotnet: Lame
That's all you really need to know about YAML to get started writing
`Ansible` playbooks.
.. seealso::
:doc:`playbooks`
Learn what playbooks can do and how to write/run them.
`YAMLLint <http://yamllint.com/>`_
YAML Lint (online) helps you debug YAML syntax if you are having problems
`Github examples directory <https://github.com/ansible/ansible/tree/devel/examples/playbooks>`_
Complete playbook files from the github project source
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

310
docsite/rst/api.rst Normal file
View File

@@ -0,0 +1,310 @@
API & Integrations
==================
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,
and you can plug in inventory data from external data sources. Ansible is written in its own
API so you have a considerable amount of power across the board.
.. contents:: `Table of contents`
:depth: 2
:backlinks: top
Python API
----------
The Python API is very powerful, and is how the ansible CLI and ansible-playbook
are implemented.
It's pretty simple::
import ansible.runner
runner = ansible.runner.Runner(
module_name='ping',
module_args='',
pattern='web*',
forks=10
)
datastructure = runner.run()
The run method returns results per host, grouped by whether they
could be contacted or not. Return types are module specific, as
expressed in the 'ansible-modules' documentation.::
{
"dark" : {
"web1.example.com" : "failure message"
}
"contacted" : {
"web2.example.com" : 1
}
}
A module can return any type of JSON data it wants, so Ansible can
be used as a framework to rapidly build powerful applications and scripts.
Detailed API Example
````````````````````
The following script prints out the uptime information for all hosts::
#!/usr/bin/python
import ansible.runner
import sys
# construct the ansible runner and execute on all hosts
results = ansible.runner.Runner(
pattern='*', forks=10,
module_name='command', module_args='/usr/bin/uptime',
).run()
if results is None:
print "No hosts found"
sys.exit(1)
print "UP ***********"
for (hostname, result) in results['contacted'].items():
if not 'failed' in result:
print "%s >>> %s" % (hostname, result['stdout'])
print "FAILED *******"
for (hostname, result) in results['contacted'].items():
if 'failed' in result:
print "%s >>> %s" % (hostname, result['msg'])
print "DOWN *********"
for (hostname, result) in results['dark'].items():
print "%s >>> %s" % (hostname, result)
Advanced programmers may also wish to read the source to ansible itself, for
it uses the Runner() API (with all available options) to implement the
command line tools ``ansible`` and ``ansible-playbook``.
Plugins Repository
------------------
The remainder of features in the API docs have components available in the `ansible-plugins <http://github.com/ansible/ansible-plugins>`_ repository. Please consult this repository for more information. Send us a github pull request if you develop any interesting features.
External Inventory Scripts
--------------------------
Often a user of a configuration management system will want to keep inventory
in a different system. Frequent examples include LDAP, `Cobbler <http://cobbler.github.com>`_,
or a piece of expensive enterprisey CMDB software. Ansible easily supports all
of these options via an external inventory system. The ansible-plugins repo contains some of these already -- including options for EC2/Eucalyptus and OpenStack, which will be detailed below.
It's possible to write an external inventory script in any language. If you are familiar with Puppet terminology, this concept is basically the same as 'external nodes', with the slight difference that it also defines which hosts are managed.
Script Conventions
``````````````````
When the external node script is called with the single argument '--list', the script must return a JSON hash/dictionary of all the groups to be managed, with a list of each host/IP as the value for each hash/dictionary element, like so::
{
'databases' : [ 'host1.example.com', 'host2.example.com' ],
'webservers' : [ 'host2.example.com', 'host3.example.com' ],
'atlanta' : [ 'host1.example.com', 'host4.example.com', 'host5.example.com' ]
}
When called with the arguments '--host <hostname>' (where <hostname> is a host from above), the script must return either an empty JSON
hash/dictionary, or a list of key/value variables to make available to templates or playbooks. Returning variables is optional,
if the script does not wish to do this, returning an empty hash/dictionary is the way to go::
{
'favcolor' : 'red',
'ntpserver' : 'wolf.example.com',
'monitoring' : 'pack.example.com'
}
Example: The Cobbler External Inventory Script
``````````````````````````````````````````````
It is expected that many Ansible users will also be `Cobbler <http://cobbler.github.com>`_ users. Cobbler has a generic
layer that allows it to represent data for multiple configuration management systems (even at the same time), and has
been referred to as a 'lightweight CMDB' by some admins. This particular script will communicate with Cobbler
using Cobbler's XMLRPC API.
To tie Ansible's inventory to Cobbler (optional), copy `this script <https://github.com/ansible/ansible-plugins/blob/master/inventory/cobbler.py>`_ to /etc/ansible/hosts and `chmod +x` the file. cobblerd will now need
to be running when you are using Ansible.
Test the file by running `./etc/ansible/hosts` directly. You should see some JSON data output, but it may not have
anything in it just yet.
Let's explore what this does. In cobbler, assume a scenario somewhat like the following::
cobbler profile add --name=webserver --distro=CentOS6-x86_64
cobbler profile edit --name=webserver --mgmt-classes="webserver" --ksmeta="a=2 b=3"
cobbler system edit --name=foo --dns-name="foo.example.com" --mgmt-classes="atlanta" --ksmeta="c=4"
cobbler system edit --name=bar --dns-name="bar.example.com" --mgmt-classes="atlanta" --ksmeta="c=5"
In the example above, the system 'foo.example.com' will be addressable by ansible directly, but will also be addressable when using the group names 'webserver' or 'atlanta'. Since Ansible uses SSH, we'll try to contract system foo over 'foo.example.com', only, never just 'foo'. Similarly, if you try "ansible foo" it wouldn't find the system... but "ansible 'foo*'" would, because the system DNS name starts with 'foo'.
The script doesn't just provide host and group info. In addition, as a bonus, when the 'setup' module is run (which happens automatically when using playbooks), the variables 'a', 'b', and 'c' will all be auto-populated in the templates::
# file: /srv/motd.j2
Welcome, I am templated with a value of a={{ a }}, b={{ b }}, and c={{ c }}
Which could be executed just like this::
ansible webserver -m setup
ansible webserver -m template -a "src=/tmp/motd.j2 dest=/etc/motd"
.. note::
The name 'webserver' came from cobbler, as did the variables for
the config file. You can still pass in your own variables like
normal in Ansible, but variables from the external inventory script
will override any that have the same name.
So, with the template above (motd.j2), this would result in the following data being written to /etc/motd for system 'foo'::
Welcome, I am templated with a value of a=2, b=3, and c=4
And on system 'bar' (bar.example.com)::
Welcome, I am templated with a value of a=2, b=3, and c=5
And technically, though there is no major good reason to do it, this also works too::
ansible webserver -m shell -a "echo {{ a }}"
So in other words, you can use those variables in arguments/actions as well. You might use this to name
a conf.d file appropriately or something similar. Who knows?
So that's the Cobbler integration support -- using the cobbler script as an example, it should be trivial to adapt Ansible to pull inventory, as well as variable information, from any data source. If you create anything interesting, please share with the mailing list, and we can keep it in the source code tree for others to use.
Example: AWS EC2 External Inventory Script
``````````````````````````````````````````
If you use Amazon Web Services EC2, maintaining an inventory file might not be the best approach. For this reason, you can use the `EC2 external inventory <https://github.com/ansible/ansible-plugins/blob/master/inventory/ec2.py>`_ script.
You can use this script in one of two ways. The easiest is to use Ansible's ``-i`` command line option and specify the path to the script.
ansible -i ec2.py -u ubuntu us-east-1d -m ping
The second option is to copy the script to `/etc/ansible/hosts` and `chmod +x` it. You will also need to copy the ``ec2.ini`` file to `/etc/ansible/ec2.ini`. Then you can run ansible as you would normally.
To successfully make an API call to AWS, you will need to configure Boto (the Python interface to AWS). There are a `variety of methods <http://docs.pythonboto.org/en/latest/boto_config_tut.html>`_ available, but the simplest is just to export two environment variables:
export AWS_ACCESS_KEY_ID='AK123'
export AWS_SECRET_ACCESS_KEY='abc123'
You can test the script by itself to make sure your config is correct
cd examples/scripts
./ec2_external_inventory.py --list
After a few moments, you should see your entire EC2 inventory across all regions in JSON.
Since each region requires its own API call, if you are only using a small set of regions, feel free to edit ``ec2.ini`` and list only the regions you are interested in. There are other config options in ``ec2.ini`` including cache control, and destination variables.
At their heart, inventory files are simply a mapping from some name to a destination address. The default ``ec2.ini`` settings are configured for running Ansible from outside EC2 (from your laptop for example). If you are running Ansible from within EC2, internal DNS names and IP addresses may make more sense than public DNS names. In this case, you can modify the ``destination_variable`` in ``ec2.ini`` to be the private DNS name of an instance. This is particularly important when running Ansible within a private subnet inside a VPC, where the only way to access an instance is via its private IP address. For VPC instances, `vpc_destination_variable` in ``ec2.ini`` provides a means of using which ever `boto.ec2.instance variable <http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance>`_ makes the most sense for your use case.
The EC2 external inventory provides mappings to instances from several groups:
Instance ID
These are groups of one since instance IDs are unique.
e.g.
``i-00112233``
``i-a1b1c1d1``
Region
A group of all instances in an AWS region.
e.g.
``us-east-1``
``us-west-2``
Availability Zone
A group of all instances in an availability zone.
e.g.
``us-east-1a``
``us-east-1b``
Security Group
Instances belong to one or more security groups. A group is created for each security group, with all characters except alphanumerics, dashes (-) converted to underscores (_). Each group is prefixed by ``security_group_``
e.g.
``security_group_default``
``security_group_webservers``
``security_group_Pete_s_Fancy_Group``
Tags
Each instance can have a variety of key/value pairs associated with it called Tags. The most common tag key is 'Name', though anything is possible. Each key/value pair is its own group of instances, again with special characters converted to underscores, in the format ``tag_KEY_VALUE``
e.g.
``tag_Name_Web``
``tag_Name_redis-master-001``
``tag_aws_cloudformation_logical-id_WebServerGroup``
When the Ansible is interacting with a specific server, the EC2 inventory script is called again with the ``--host HOST`` option. This looks up the HOST in the index cache to get the instance ID, and then makes an API call to AWS to get information about that specific instance. It then makes information about that instance available as variables to your playbooks. Each variable is prefixed by ``ec2_``. Here are some of the variables available:
- ec2_architecture
- ec2_description
- ec2_dns_name
- ec2_id
- ec2_image_id
- ec2_instance_type
- ec2_ip_address
- ec2_kernel
- ec2_key_name
- ec2_launch_time
- ec2_monitored
- ec2_ownerId
- ec2_placement
- ec2_platform
- ec2_previous_state
- ec2_private_dns_name
- ec2_private_ip_address
- ec2_public_dns_name
- ec2_ramdisk
- ec2_region
- ec2_root_device_name
- ec2_root_device_type
- ec2_security_group_ids
- ec2_security_group_names
- ec2_spot_instance_request_id
- ec2_state
- ec2_state_code
- ec2_state_reason
- ec2_status
- ec2_subnet_id
- ec2_tag_Name
- ec2_tenancy
- ec2_virtualization_type
- ec2_vpc_id
Both ``ec2_security_group_ids`` and ``ec2_security_group_names`` are comma-separated lists of all security groups. Each EC2 tag is a variable in the format ``ec2_tag_KEY``.
To see the complete list of variables available for an instance, run the script by itself::
cd examples/scripts
./ec2_external_inventory.py --host ec2-12-12-12-12.compute-1.amazonaws.com
Example: OpenStack
``````````````````
Though not detailed here in as much depth as the EC2 module, there's also a OpenStack Nova external inventory source in the ansible-plugins repository. See the inline comments in the module source.
Callback Plugins
----------------
Ansible can be configured via code to respond to external events. This can include enhancing logging, signalling an external software
system, or even (yes, really) making sound effects. Some examples are contained in the ansible-plugins repository.
Connection Type Plugins
-----------------------
By default, ansible ships with a 'paramiko' SSH, native ssh (just called 'ssh'), and 'local' connection type, which 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
are covered in the '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
directory.
.. seealso::
:doc:`modules`
List of built-in modules
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@@ -0,0 +1,143 @@
Best Practices
==============
Here are some tips for making the most of Ansible.
.. contents::
:depth: 2
:backlinks: top
Always Mention State
++++++++++++++++++++
The 'state' parameter is optional to a lot of modules. Whether
'state=present' or 'state=absent', it's always best to leave that
parameter in your playbooks to make it clear, especially as some
modules support additional states.
Group By Roles
++++++++++++++
A system can be in multiple groups. See :doc:`patterns`. Having groups named after things like
*webservers* and *dbservers* is repeated in the examples because it's a very powerful concept.
This allows playbooks to target machines based on role, as well as to assign role specific variables
using the group variable system.
Directory Organization
++++++++++++++++++++++
Playbooks should be organized like this::
# root of source control repository
├── acme/
│ ├── setup.yml
│ └── stop.yml
├── files/
│ └── some_file_path_foo.conf
├── handlers/
│ └── main.yml
├── tasks/
│ ├── setup.yml
│ └── stop.yml
├── templates/
│ ├── etc_acme_conf_acme.conf
│ └── etc_other_conf_other.conf
├── vars/
│ └── main.yml
└── global_vars.yml
Any directories or files not needed can be omitted. Not all modules
may require 'vars' or 'files' sections, though most will require
'handlers', 'tasks', and 'templates'. To review what each of
these sections do, see :doc:`playbooks` and :doc:`playbooks2`.
The acme/setup.yml playbook would be as simple as::
---
- hosts: webservers
user: root
vars_files:
- ../global_vars.yml
- vars/main.yml
tasks:
- include: tasks/setup.yml
handlers:
- include: handlers/main.yml
The tasks are individually broken out in 'acme/tasks/setup.yml', and handlers, which are common to all task files,
are contained in 'acme/handlers/main.yml'. As a reminder, handlers are mostly just used to notify services to restart
when things change, and these are described in :doc:`playbooks`.
Including more than one setup file or more than one handlers file is of course legal.
Bundling Ansible Modules With Playbooks
+++++++++++++++++++++++++++++++++++++++
.. versionadded:: 0.5
If a playbook has a "./library" directory relative to it's YAML file,
this directory can be used to add ansible modules that will
automatically be in the ansible module path. This is a great way to
keep modules that go with a playbook together.
Miscellaneous Tips
++++++++++++++++++
When you can do something simply, do something simply. Do not reach
to use every feature of Ansible together, all at once. Use what works
for you. For example, you should probably not need 'vars',
'vars_files', 'vars_prompt' and '--extra-vars' all at once,
while also using an external inventory file.
Optimize for readability. Whitespace between sections of YAML
documents and in between tasks is strongly encouraged, as is usage of
YAML comments, which start with '#'. It is also useful to comment
at the top of each file the purpose of the individual file and the
author, including email address.
It is possible to leave off the 'name' for a given task, though it
is recommended to provide a descriptive comment about why something is
being done instead.
Use version control. Keep your playbooks and inventory file in git
(or another version control system), and commit when you make changes
to them. This way you have an audit trail describing when and why you
changed the rules automating your infrastructure.
Resist the urge to write the same playbooks and configuration files
for heterogeneous distributions. While lots of software packages
claim to make this easy on you, the configuration files are often
quite different, to the point where it would be easier to treat them
as different playbooks. This is why, for example, Ansible has a
separate 'yum' and 'apt' module. Yum and apt have different
capabilities, and we don't want to code for the least common
denominator.
Use variables for user tunable settings versus having constants in the
tasks file or templates, so that it is easy to reconfigure a playbook.
Think about this as exposing the knobs to things you would like to
tweak.
Since a system can be in more than one group, if you have multiple
datacenters or sites, consider putting systems into groups by role,
but also different groups by geography. This allows you to assign
different variables to different geographies.
.. seealso::
:doc:`YAMLSyntax`
Learn about YAML syntax
:doc:`playbooks`
Review the basic playbook features
:doc:`modules`
Learn about available modules
:doc:`moduledev`
Learn how to extend Ansible by writing your own modules
:doc:`patterns`
Learn about how to select hosts
`Github examples directory <https://github.com/ansible/ansible/tree/devel/examples/playbooks>`_
Complete playbook files from the github project source
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups

263
docsite/rst/examples.rst Normal file
View File

@@ -0,0 +1,263 @@
Command Line Examples And Next Steps
====================================
.. highlight:: bash
The following examples show how to use `/usr/bin/ansible` for running
ad hoc tasks. Start here.
For configuration management and deployments, you'll want to pick up on
using `/usr/bin/ansible-playbook` -- the concepts port over directly.
(See :doc:`playbooks` for more information about those)
.. contents::
:depth: 2
:backlinks: top
Parallelism and Shell Commands
``````````````````````````````
Let's use ansible's command line tool to reboot all web servers in Atlanta, 10 at a time. First, let's
set up SSH-agent so it can remember our credentials::
$ ssh-agent bash
$ ssh-add ~/.ssh/id_rsa.pub
If you don't want to use ssh-agent and want to instead SSH with a
password instead of keys, you can with ``--ask-pass`` (``-k``), but
it's much better to just use ssh-agent.
Now to run the command on all servers in a group, in this case,
*atlanta*, in 10 parallel forks::
$ ansible atlanta -a "/sbin/reboot" -f 10
In 0.7 and later, this will default to running from your user account. If you do not like this
behavior, pass in "-u username". (In 0.6 and before, it defaulted to root. Most folks prefered
defaulting to the current user, so we changed it).
If you want to run commands as a different user, it looks like this::
$ ansible atlanta -a "/usr/bin/foo" -u username
If you want to run commands through sudo::
$ ansible atlanta -a "/usr/bin/foo" -u username --sudo [--ask-sudo-pass]
Use ``--ask-sudo-pass`` (``-K``) if you are not using passwordless
sudo. This will interactively prompt you for the password to use.
Use of passwordless sudo makes things easier to automate, but it's not
required.
It is also possible to sudo to a user other than root using
``--sudo-user`` (``-U``)::
$ ansible atlanta -a "/usr/bin/foo" -u username -U otheruser [--ask-sudo-pass]
Ok, so those are basics. If you didn't read about patterns and groups yet, go back and read :doc:`patterns`.
The ``-f 10`` in the above specifies the usage of 10 simultaneous
processes. Normally commands also take a ``-m`` for module name, but
the default module name is 'command', so we didn't need to
specify that all of the time. We'll use ``-m`` in later examples to
run some other :doc:`modules`.
.. note::
The :ref:`command` module requires absolute paths and does not
support shell variables. If we want to execute a module using a
shell, we can do those things, and also use pipe and redirection
operators. Read more about the differences on the :doc:`modules`
page.
Using the :ref:`shell` module looks like this::
$ ansible raleigh -m shell -a 'echo $TERM'
When running any command with the ansible *ad hoc* CLI (as opposed to
:doc:`playbooks`), pay particular attention to shell quoting rules, so
the shell doesn't eat a variable before it gets passed to Ansible.
For example, using double vs single quotes in the above example would
evaluate the variable on the box you were on.
So far we've been demoing simple command execution, but most Ansible modules usually do not work like
simple scripts. They make the remote system look like you state, and run the commands necessary to
get it there. This is commonly referred to as 'idempotence', and is a core design goal of ansible.
However, we also recognize that running *ad hoc* commands is equally important, so Ansible easily supports both.
File Transfer
`````````````
Here's another use case for the `/usr/bin/ansible` command line. Ansible can SCP lots of files to multiple machines in parallel.
To transfer a file directly to many different servers::
$ ansible atlanta -m copy -a "src=/etc/hosts dest=/tmp/hosts"
If you use playbooks, you can also take advantage of the ``template`` module,
which takes this another step further. (See module and playbook documentation).
The ``file`` module allows changing ownership and permissions on files. These
same options can be passed directly to the ``copy`` module as well::
$ ansible webservers -m file -a "dest=/srv/foo/a.txt mode=600"
$ ansible webservers -m file -a "dest=/srv/foo/b.txt mode=600 owner=mdehaan group=mdehaan"
The ``file`` module can also create directories, similar to ``mkdir -p``::
$ ansible webservers -m file -a "dest=/path/to/c mode=644 owner=mdehaan group=mdehaan state=directory"
As well as delete directories (recursively) and delete files::
$ ansible webservers -m file -a "dest=/path/to/c state=absent"
Managing Packages
`````````````````
There are modules available for yum and apt. Here are some examples
with yum.
Ensure a package is installed, but don't update it::
$ ansible webservers -m yum -a "pkg=acme state=installed"
Ensure a package is installed to a specific version::
$ ansible webservers -m yum -a "pkg=acme-1.5 state=installed"
Ensure a package is at the latest version::
$ ansible webservers -m yum -a "pkg=acme state=latest"
Ensure a package is not installed::
$ ansible webservers -m yum -a "pkg=acme state=removed"
Currently Ansible only has modules for managing packages with yum and apt. You can install
for other packages for now using the command module or (better!) contribute a module
for other package managers. Stop by the mailing list for info/details.
Users and Groups
````````````````
The 'user' module allows easy creation and manipulation of
existing user accounts, as well as removal of user accounts that may
exist::
$ ansible all -m user -a "name=foo password=<crypted password here>"
$ ansible all -m user -a "name=foo state=absent"
See the :doc:`modules` section for details on all of the available options, including
how to manipulate groups and group membership.
Deploying From Source Control
`````````````````````````````
Deploy your webapp straight from git::
$ ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"
Since ansible modules can notify change handlers it is possible to
tell ansible to run specific tasks when the code is updated, such as
deploying Perl/Python/PHP/Ruby directly from git and then restarting
apache.
Managing Services
`````````````````
Ensure a service is started on all webservers::
$ ansible webservers -m service -a "name=httpd state=started"
Alternatively, restart a service on all webservers::
$ ansible webservers -m service -a "name=httpd state=restarted"
Ensure a service is stopped::
$ ansible webservers -m service -a "name=httpd state=stopped"
Time Limited Background Operations
``````````````````````````````````
Long running operations can be backgrounded, and their status can be
checked on later. The same job ID is given to the same task on all
hosts, so you won't lose track. If you kick hosts and don't want
to poll, it looks like this::
$ ansible all -B 3600 -a "/usr/bin/long_running_operation --do-stuff"
If you do decide you want to check on the job status later, you can::
$ ansible all -m async_status -a "jid=123456789"
Polling is built-in and looks like this::
$ ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
The above example says "run for 30 minutes max (``-B``: 30*60=1800),
poll for status (``-P``) every 60 seconds".
Poll mode is smart so all jobs will be started before polling will begin on any machine.
Be sure to use a high enough ``--forks`` value if you want to get all of your jobs started
very quickly. After the time limit (in seconds) runs out (``-B``), the process on
the remote nodes will be terminated.
Typically you'll be only be backgrounding long-running
shell commands or software upgrades only. Backgrounding the copy module does not do a background file transfer. :doc:`playbooks` also support polling, and have a simplified syntax for this.
Limiting Selected Hosts
```````````````````````
.. versionadded:: 0.7
What hosts you select to manage can be additionally constrained by using the '--limit' parameter or
by using 'batch' (or 'range') selectors.
As mentioned above, patterns can be strung together to select hosts in more than one group::
$ ansible webservers:dbservers -m command -a "/bin/foo xyz"
This is an "or" condition. If you want to further constrain the selection, use --limit, which
also works with ``ansible-playbook``::
$ ansible webservers:dbservers -m command -a "/bin/foo xyz" region
Now let's talk about range selection. Suppose you have 1000 servers in group 'datacenter', but only want to target one at a time. This is also easy::
$ ansible webservers[0-99] -m command -a "/bin/foo xyz"
$ ansible webservers[100-199] -m command -a "/bin/foo xyz"
This will select the first 100, then the second 100, host entries in the webservers group. (It does not matter
what their names or IP addresses are).
Both of these methods can be used at the same time, and ranges can also be passed to the --limit parameter.
Configuration & Defaults
````````````````````````
.. versionadded:: 0.7
Ansible has an optional configuration file that can be used to tune settings and also eliminate the need to pass various command line flags. Ansible will look for the config file in the following order, using
the first config file it finds present:
1. File specified by the ``ANSIBLE_CONFIG`` environment variable
2. ``ansible.cfg`` in the current working directory. (version 0.8 and up)
3. ``~/.ansible.cfg``
4. ``/etc/ansible/ansible.cfg``
For those running from source, a sample configuration file lives in the examples/ directory. The RPM will install configuration into /etc/ansible/ansible.cfg automatically.
.. seealso::
:doc:`modules`
A list of available modules
:doc:`playbooks`
Using ansible for configuration management & deployment
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@@ -0,0 +1,247 @@
Getting Started
===============
.. contents::
:depth: 2
:backlinks: top
Requirements
````````````
Requirements for Ansible are extremely minimal.
Ansible is written for Python 2.6. If you are running Python 2.5 on an "Enterprise Linux" variant,
your distribution can easily install 2.6 (see instructions in the next section). Newer versions
of Linux and OS X should already have 2.6.
In additon to Python 2.6, you will want the following packages:
* ``paramiko``
* ``PyYAML``
* ``python-jinja2``
On the managed nodes, you only need Python 2.4 or later, but if you are are running less than Python 2.6 on them, you will
also need:
* ``python-simplejson``
.. note::
Ansible's "raw" module (for executing commands in a quick and dirty
way) and the copy module -- some of the most basic features in
ansible -- don't even need that. So technically, you can use
Ansible to install python-simplejson using the raw module, which
then allows you to use everything else. (That's jumping ahead
though.)
Python 2.6 EPEL instructions for RHEL and CentOS 5
``````````````````````````````````````````````````
These distributions don't have Python 2.6 by default, but it is easily
installable. If you have not already done so, `configure EPEL
<http://fedoraproject.org/wiki/EPEL>`_
.. code-block:: bash
$ yum install python26 python26-PyYAML python26-paramiko python26-jinja2
Getting Ansible
```````````````
If you are interested in using all the latest features, you may wish to keep up to date
with the development branch of the git checkout. This also makes it easiest to contribute
back to the project.
Instructions for installing from source are below.
Ansible's release cycles are about one month long. Due to this
short release cycle, any bugs will generally be fixed in the next release versus maintaining
backports on the stable branch.
You may also wish to follow the `Github project <https://github.com/ansible/ansible>`_ if
you have a github account. This is also where we keep the issue tracker for sharing
bugs and feature ideas.
Running From Checkout
+++++++++++++++++++++
Ansible is trivially easy to run from a checkout, root permissions are not required
to use it:
.. code-block:: bash
$ git clone git://github.com/ansible/ansible.git
$ cd ./ansible
$ source ./hacking/env-setup
You can optionally specify an inventory file (see :doc:`patterns`) other than /etc/ansible/hosts:
.. code-block:: bash
$ echo "127.0.0.1" > ~/ansible_hosts
$ export ANSIBLE_HOSTS=~/ansible_hosts
Now let's test things:
.. code-block:: bash
$ ansible all -m ping --ask-pass
Make Install
++++++++++++
If you are not working from a distribution where Ansible is packaged yet, you can install Ansible
using "make install". This is done through `python-distutils`:
.. code-block:: bash
$ git clone git://github.com/ansible/ansible.git
$ cd ./ansible
$ sudo make install
Via RPM
+++++++
RPMs for the last Ansible release are available for `EPEL
<http://fedoraproject.org/wiki/EPEL>`_ 6 and currently supported
Fedora distributions. Ansible itself can manage earlier operating
systems that contain python 2.4 or higher.
.. code-block:: bash
# install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux
$ sudo yum install ansible
You can also use the ``make rpm`` command to build an RPM you can
distribute and install:
.. code-block:: bash
$ git clone git://github.com/ansible/ansible.git
$ cd ./ansible
$ make rpm
$ sudo rpm -Uvh ~/rpmbuild/ansible-*.noarch.rpm
Debian, Gentoo, Arch, Others
++++++++++++++++++++++++++++
Ubuntu builds are available `in a PPA here <https://launchpad.net/~rquillo/+archive/ansible>`_
Debian/Ubuntu package recipes can also be built from the source checkout, run:
.. code-block:: bash
$ make debian
Gentoo eBuilds are available `on github here <https://github.com/uu/ubuilds>`_
An Arch PKGBUILD is available on `AUR <https://aur.archlinux.org/packages.php?ID=58621>`_
If you have python3 installed on Arch, you probably want to symlink python to python2:
.. code-block:: bash
$ sudo ln -sf /usr/bin/python2 /usr/bin/python
If you would like to package Ansible for Homebrew, BSD, or others,
please stop by the mailing list and say hi!
Tagged Releases
+++++++++++++++
Tagged releases are available as tar.gz files from the Ansible github
project page:
* `Ansible/downloads <https://github.com/ansible/ansible/downloads>`_
Choosing Between Paramiko and Native SSH
````````````````````````````````````````
By default, ansible uses paramiko to talk to managed nodes over SSH. Paramiko is fast, works
very transparently, requires no configuration, and is a good choice for most users.
However, it does not support some advanced SSH features that folks will want to use.
.. versionadded:: 0.5
If you want to leverage more advanced SSH features (such as Kerberized
SSH or jump hosts), pass the flag "--connection=ssh" to any ansible
command, or set the ANSIBLE_TRANSPORT environment variable to
'ssh'. This will cause Ansible to use openssh tools instead.
If ANSIBLE_SSH_ARGS are not set, ansible will try to use some sensible ControlMaster options
by default. You are free to override this environment variable, but should still pass ControlMaster
options to ensure performance of this transport. With ControlMaster in use, both transports
are roughly the same speed. Without CM, the binary ssh transport is signficantly slower.
If none of this makes sense to you, the default paramiko option is probably fine.
Your first commands
```````````````````
Now that you've installed Ansible, it's time to test it.
Edit (or create) /etc/ansible/hosts and put one or more remote systems in it, for
which you have your SSH key in ``authorized_keys``::
192.168.1.50
aserver.example.org
bserver.example.org
Set up SSH agent to avoid retyping passwords:
.. code-block:: bash
$ ssh-agent bash
$ ssh-add ~/.ssh/id_rsa
(Depending on your setup, you may wish to ansible's --private-key-file option to specify a pem file instead)
Now ping all your nodes:
.. code-block:: bash
$ ansible all -m ping
In Ansible 0.7 and later, ansible will attempt to remote connect to the machines using your current
user name, just like SSH would. In 0.6 and before, this actually defaults to 'root' (we liked the current
user behavior better). To override the remote user name, just use the '-u' parameter.
If you would like to access sudo mode, there are also flags to do that:
.. code-block:: bash
# as bruce
$ ansible all -m ping -u bruce
# as bruce, sudoing to root
$ ansible all -m ping -u bruce --sudo
# as bruce, sudoing to batman
$ ansible all -m ping -u bruce --sudo --sudo-user batman
Now run a live command on all of your nodes:
.. code-block:: bash
$ ansible all -a "/bin/echo hello"
Congratulations. You've just contacted your nodes with Ansible. It's
now time to read some of the more real-world :doc:`examples`, and explore
what you can do with different modules, as well as the Ansible
:doc:`playbooks` language. Ansible is not just about running commands, it
also has powerful configuration management and deployment features. There's more to
explore, but you already have a fully working infrastructure!
.. seealso::
:doc:`examples`
Examples of basic commands
:doc:`playbooks`
Learning ansible's configuration management language
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

18
docsite/rst/index.rst Normal file
View File

@@ -0,0 +1,18 @@
Contents
````````
.. toctree::
:maxdepth: 1
gettingstarted
patterns
examples
modules
YAMLSyntax
playbooks
playbooks2
bestpractices
api
moduledev

346
docsite/rst/moduledev.rst Normal file
View File

@@ -0,0 +1,346 @@
Module Development
==================
Ansible modules are reusable units of magic that can be used by the Ansible API,
or by the `ansible` or `ansible-playbook` programs.
Modules can be written in any language and are found in the path specified
by `ANSIBLE_LIBRARY_PATH` or the ``--module-path`` command line option.
.. contents::
:depth: 2
:backlinks: top
Tutorial
````````
Let's build a module to get and set the system time. For starters, let's build
a module that just outputs the current time.
We are going to use Python here but any language is possible. Only File I/O and outputing to standard
out are required. So, bash, C++, clojure, Python, Ruby, whatever you want
is fine.
Now Python Ansible modules contain some extremely powerful shortcuts (that all the core modules use)
but first we are going to build a module the very hard way. The reason we do this is because modules
written in any language OTHER than Python are going to have to do exactly this. We'll show the easy
way later.
So, here's an example. You would never really need to build a module to set the system time,
the 'command' module could already be used to do this. Though we're going to make one.
Reading the modules that come with ansible (linked above) is a great way to learn how to write
modules. Keep in mind, though, that some modules in ansible's source tree are internalisms,
so look at `service` or `yum`, and don't stare too close into things like `async_wrapper` or
you'll turn to stone. Nobody ever executes async_wrapper directly.
Ok, let's get going with an example. We'll use Python. For starters, save this as a file named `time`::
#!/usr/bin/python
import datetime
import json
date = str(datetime.datetime.now())
print json.dumps({
"time" : date
})
Testing Modules
```````````````
There's a useful test script in the source checkout for ansible::
git clone git@github.com:ansible/ansible.git
chmod +x ansible/hacking/test-module
Let's run the script you just wrote with that::
ansible/hacking/test-module -m ./time
You should see output that looks something like this::
{u'time': u'2012-03-14 22:13:48.539183'}
If you did not, you might have a typo in your module, so recheck it and try again.
Reading Input
`````````````
Let's modify the module to allow setting the current time. We'll do this by seeing
if a key value pair in the form `time=<string>` is passed in to the module.
Ansible internally saves arguments to an arguments file. So we must read the file
and parse it. The arguments file is just a string, so any form of arguments are legal.
Here we'll do some basic parsing to treat the input as key=value.
The example usage we are trying to achieve to set the time is::
time time="March 14 22:10"
If no time parameter is set, we'll just leave the time as is and return the current time.
.. note:
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.
Let's look at the code. Read the comments as we'll explain as we go. Note that this
is highly verbose because it's intended as an educational example. You can write modules
a lot shorter than this::
#!/usr/bin/python
# import some python modules that we'll use. These are all
# available in Python's core
import datetime
import sys
import json
import os
import shlex
# read the argument string from the arguments file
args_file = sys.argv[1]
args_data = file(args_file).read()
# for this module, we're going to do key=value style arguments
# this is up to each module to decide what it wants, but all
# core modules besides 'command' and 'shell' take key=value
# so this is highly recommended
arguments = shlex.split(args_data)
for arg in arguments:
# ignore any arguments without an equals in it
if arg.find("=") != -1:
(key, value) = arg.split("=")
# if setting the time, the key 'time'
# will contain the value we want to set the time to
if key == "time":
# now we'll affect the change. Many modules
# will strive to be 'idempotent', meaning they
# will only make changes when the desired state
# expressed to the module does not match
# the current state. Look at 'service'
# or 'yum' in the main git tree for an example
# of how that might look.
rc = os.system("date -s \"%s\"" % value)
# always handle all possible errors
#
# when returning a failure, include 'failed'
# in the return data, and explain the failure
# in 'msg'. Both of these conventions are
# required however additional keys and values
# can be added.
if rc != 0:
print json.dumps({
"failed" : True,
"msg" : "failed setting the time"
})
sys.exit(1)
# when things do not fail, we do not
# have any restrictions on what kinds of
# data are returned, but it's always a
# good idea to include whether or not
# a change was made, as that will allow
# notifiers to be used in playbooks.
date = str(datetime.datetime.now())
print json.dumps({
"time" : date,
"changed" : True
})
sys.exit(0)
# if no parameters are sent, the module may or
# may not error out, this one will just
# return the time
date = str(datetime.datetime.now())
print json.dumps({
"time" : date
})
Let's test that module::
ansible/hacking/test-module -m ./time -a time=\"March 14 12:23\"
This should return something like::
{"changed": True, "time": "2012-03-14 12:23:00.000307"}
Module Provided 'Facts'
```````````````````````
The 'setup' module that ships with Ansible provides many variables about a system that can be used in playbooks
and templates. However, it's possible to also add your own facts without modifying the system module. To do
this, just have the module return a `ansible_facts` key, like so, along with other return data::
{
"changed" : True,
"rc" : 5,
"ansible_facts" : {
"leptons" : 5000
"colors" : {
"red" : "FF0000",
"white" : "FFFFFF"
}
}
}
These 'facts' will be available to all statements called after that module (but not before) in the playbook.
A good idea might be make a module called 'site_facts' and always call it at the top of each playbook, though
we're always open to improving the selection of core facts in Ansible as well.
Common Module Boilerplate
`````````````````````````
As mentioned, if you are writing a module in Python, there are some very powerful shortcuts you can use.
Modules are still transferred as one file, but an arguments file is no longer needed, so these are not
only shorter in terms of code, they are actually FASTER in terms of execution time.
Rather than mention these here, the best way to learn is to read some of the `source of the modules <https://github.com/ansible/ansible/tree/devel/library>`_ that come with Ansible.
The 'group' and 'user' modules are reasonably non-trival and showcase what this looks like.
Key parts include always ending the module file with::
# include magic from lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()
And instantiating the module class like::
module = AnsibleModule(
argument_spec = dict(
state = dict(default='present', choices=['present', 'absent']),
name = dict(required=True),
enabled = dict(required=True, choices=BOOLEANS),
something = dict(aliases=['whatever'])
)
)
The AnsibleModule provides lots of common code for handling returns, parses your arguments
for you, and allows you to check inputs.
Successful returns are made like this::
module.exit_json(changed=True, something_else=12345)
And failures are just as simple (where 'msg' is a required parameter to explain the error)::
module.fail_json(msg="Something fatal happened")
There are also other useful functions in the module class, such as module.md5(path). See
lib/ansible/module_common.py in the source checkout for implementation details.
Again, modules developed this way are best tested with the hacking/test-module script in the git
source checkout. Because of the magic involved, this is really the only way the scripts
can function outside of Ansible.
If submitting a module to ansible's core code, which we encourage, use of the AnsibleModule
class is required.
Common Pitfalls
```````````````
You should also never do this in a module::
print "some status message"
Because the output is supposed to be valid JSON. Except that's not quite true,
but we'll get to that later.
Modules must not output anything on standard error, because the system will merge
standard out with standard error and prevent the JSON from parsing. Capturing standard
error and returning it as a variable in the JSON on standard out is fine, and is, in fact,
how the command module is implemented.
If a module returns stderr or otherwise fails to produce valid JSON, the actual output
will still be shown in Ansible, but the command will not succeed.
Always use the hacking/test-module script when developing modules and it will warn
you about these kind of things.
Conventions/Recomendations
``````````````````````````
As a reminder from the example code above, here are some basic conventions
and guidelines:
* If the module is addressing an object, the parameter for that object should be called 'name' whenever possible, or accept 'name' as an alias.
* If you have a company module that returns facts specific to your installations, a good name for this module is `site_facts`.
* Modules accepting boolean status should generally accept 'yes', 'no', 'true', 'false', or anything else a user may likely throw at them. The AnsibleModule common code supports this with "choices=BOOLEANS" and a module.boolean(value) casting function.
* Include a minimum of dependencies if possible. If there are dependencies, document them at the top of the module file, and have the module raise JSON error messages when the import fails.
* Modules must be self contained in one file to be auto-transferred by ansible.
* If packaging modules in an RPM, they only need to be installed on the control machine and should be dropped into /usr/share/ansible. This is entirely optional and up to you.
* Modules should return JSON or key=value results all on one line. JSON is best if you can do JSON. All return types must be hashes (dictionaries) although they can be nested. Lists or simple scalar values are not supported, though they can be trivially contained inside a dictionary.
* In the event of failure, a key of 'failed' should be included, along with a string explanation in 'msg'. Modules that raise tracebacks (stacktraces) are generally considered 'poor' modules, though Ansible can deal with these returns and will automatically convert anything unparseable into a failed result. If you are using the AnsibleModule common Python code, the 'failed' element will be included for you automatically when you call 'fail_json'.
* Return codes from modules are not actually not signficant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
* As results from many hosts will be aggregrated at once, modules should return only relevant output. Returning the entire contents of a log file is generally bad form.
Shorthand Vs JSON
`````````````````
To make it easier to write modules in bash and in cases where a JSON
module might not be available, it is acceptable for a module to return
key=value output all on one line, like this. The Ansible parser
will know what to do::
somekey=1 somevalue=2 rc=3 favcolor=red
If you're writing a module in Python or Ruby or whatever, though, returning
JSON is probably the simplest way to go.
Sharing Your Module
```````````````````
If you think your module is generally useful to others, a good place to share it
is in `Ansible Resources <https://github.com/ansible/ansible-resources>`_. This is maintained
as a simple repo with pointers to other github projects.
Contrib modules here can be implemented in a variety of languages.
We would like to build up as many of these as possible in as many languages as possible.
`Ansible Mailing List <http://groups.google.com/group/ansible-project>`_
Getting Your Module Into Core
`````````````````````````````
High-quality modules with minimal dependencies
can be included in the core, but core modules (just due to the programming
preferences of the developers) will need to be implemented in Python and use
the AnsibleModule common code, and should generally use consistent arguments with the rest of
the program. Stop by the mailing list to inquire about requirements.
.. seealso::
:doc:`modules`
Learn about available modules
`Ansible Resources <https://github.com/ansible/ansible-resources>`_
User contributed playbooks, modules, and articles
`Github modules directory <https://github.com/ansible/ansible/tree/devel/library>`_
Browse source of core modules
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

74
docsite/rst/modules.rst Normal file
View File

@@ -0,0 +1,74 @@
Ansible Modules
===============
.. contents::
:depth: 2
:backlinks: top
Introduction
````````````
Ansible ships with a number of modules (called the 'module library')
that can be executed directly on remote hosts or through :doc:`playbooks`.
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.
Let's review how we execute three different modules from the command line::
ansible webservers -m service -a "name=httpd state=running"
ansible webservers -m ping
ansible webservers -m command -a "/sbin/reboot -t now"
Each module supports taking arguments. Nearly all modules take ``key=value``
arguments, space delimited. Some modules take no arguments, and the
command/shell modules simply take the string of the command you want to run.
From playbooks, Ansible modules are executed in a very similar way::
- name: reboot the servers
action: command /sbin/reboot -t now
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
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
playbooks, these modules can trigger 'change events' in the form of notifying 'handlers'
to run additional tasks.
Let's see what's available in the Ansible module library, out of the box:
.. include:: modules/_list.rst
Additional Contrib Modules
``````````````````````````
In addition to the following built-in modules, community modules are available at `Ansible Resources <http://github.com/ansible/ansible-resources>`_.
Writing your own modules
````````````````````````
See :doc:`moduledev`.
.. seealso::
`Ansible Resources (Contrib) <https://github.com/ansible/ansible-resources>`_
User contributed playbooks, modules, and articles
:doc:`examples`
Examples of using modules in /usr/bin/ansible
:doc:`playbooks`
Examples of using modules with /usr/bin/ansible-playbook
:doc:`moduledev`
How to write your own modules
:doc:`api`
Examples of using modules with the Python API
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@@ -0,0 +1,43 @@
.. Generated by module_formatter
.. include:: modules/apt.rst
.. include:: modules/apt_repository.rst
.. include:: modules/assemble.rst
.. include:: modules/async_status.rst
.. include:: modules/authorized_key.rst
.. include:: modules/command.rst
.. include:: modules/copy.rst
.. include:: modules/easy_install.rst
.. include:: modules/facter.rst
.. include:: modules/fail.rst
.. include:: modules/fetch.rst
.. include:: modules/file.rst
.. include:: modules/fireball.rst
.. include:: modules/get_url.rst
.. include:: modules/git.rst
.. include:: modules/group.rst
.. include:: modules/ini_file.rst
.. include:: modules/lineinfile.rst
.. include:: modules/mount.rst
.. include:: modules/mysql_db.rst
.. include:: modules/mysql_user.rst
.. include:: modules/nagios.rst
.. include:: modules/ohai.rst
.. include:: modules/pause.rst
.. include:: modules/ping.rst
.. include:: modules/pip.rst
.. include:: modules/postgresql_db.rst
.. include:: modules/postgresql_user.rst
.. include:: modules/raw.rst
.. include:: modules/seboolean.rst
.. include:: modules/selinux.rst
.. include:: modules/service.rst
.. include:: modules/setup.rst
.. include:: modules/shell.rst
.. include:: modules/slurp.rst
.. include:: modules/subversion.rst
.. include:: modules/supervisorctl.rst
.. include:: modules/template.rst
.. include:: modules/user.rst
.. include:: modules/virt.rst
.. include:: modules/wait_for.rst
.. include:: modules/yum.rst

View File

@@ -0,0 +1,92 @@
.. _apt:
apt
``````````````````````````````
.. versionadded:: 0.0.2
Manages apt-packages (such as for Debian/Ubuntu).
.. raw:: html
<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>
<tr>
<td>purge</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Will force purging of configuration files if the module state is set to <code>absent</code>.</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>installed</li><li>latest</li><li>remove</li><li>absent</li><li>present</li></ul></td>
<td>Indicates the desired package state</td>
</tr>
<tr>
<td>force</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>If <code>yes</code>, force installs/removes.</td>
</tr>
<tr>
<td>pkg</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>A package name or package specifier with version, like <code>foo</code> or <code>foo=1.0</code></td>
</tr>
<tr>
<td>update_cache</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Run the equivalent of <code>apt-get update</code> before the operation. Can be run as part of the package installation or as a seperate step</td>
</tr>
<tr>
<td>default_release</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Corresponds to the <code>-t</code> option for <em>apt</em> and sets pin priorities</td>
</tr>
<tr>
<td>install_recommends</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Corresponds to the <code>--no-install-recommends</code> option for <em>apt</em>, default behavior works as apt's default behavior, <code>no</code> does not install recommended packages. Suggested packages are never installed.</td>
</tr>
</table>
.. raw:: html
<p>Update repositories cache and install <code>foo</code> package</p> <p><pre>
apt pkg=foo update-cache=yes
</pre></p>
<p>Remove <code>foo</code> package</p> <p><pre>
apt pkg=foo state=removed
</pre></p>
<p>Install the the package <code>foo</code></p> <p><pre>
apt pkg=foo state=installed
</pre></p>
<p>Install the version '1.00' of package <code>foo</code></p> <p><pre>
apt pkg=foo=1.00 state=installed
</pre></p>
<p>Update the repository cache and update package <code>ngnix</code> to latest version using default release <code>squeeze-backport</code></p> <p><pre>
apt pkg=nginx state=latest default-release=squeeze-backports update-cache=yes
</pre></p>
<p>Install latest version of <code>openjdk-6-jdk</code> ignoring <code>install-recomands</code></p> <p><pre>
apt pkg=openjdk-6-jdk state=latest install-recommends=no
</pre></p>
<br/>

View File

@@ -0,0 +1,51 @@
.. _apt_repository:
apt_repository
``````````````````````````````
.. versionadded:: 0.7
Manages apt repositores (such as for Debian/Ubuntu).
.. raw:: html
<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>
<tr>
<td>repo</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The repository name/value</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>The repository state</td>
</tr>
</table>
.. raw:: html
<p>Add nginx stable repository from PPA</p> <p><pre>
apt_repository repo=ppa://nginx/stable
</pre></p>
<p>Add specified repository into sources.</p> <p><pre>
apt_repository repo='deb http://archive.canonical.com/ubuntu hardy partner'
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>This module works on Debian and Ubuntu only and requires <code>apt-add-repository</code> be available on destination server. To ensure this package is available use the <code>apt</code> module and install the <code>python-software-properties</code> package before using this module.</p>
<p>A bug in <code>apt-add-repository</code> always adds <code>deb</code> and <code>deb-src</code> types for repositories (see the issue on Launchpad <a href='https://bugs.launchpad.net/ubuntu/+source/software-properties/+bug/987264'>https://bugs.launchpad.net/ubuntu/+source/software-properties/+bug/987264</a>), if a repo doesn't have source information (eg MongoDB repo from 10gen) the system will fail while updating repositories.</p>

View File

@@ -0,0 +1,56 @@
.. _assemble:
assemble
``````````````````````````````
.. versionadded:: 0.5
Assembles a configuration file from fragments. Often a particular program will take a single configuration file and does not support a ``conf.d`` style structure where it is easy to build up the configuration from multiple sources. Assemble will take a directory of files that have already been transferred to the system, and concatenate them together to produce a destination file. Files are assembled in string sorting order. Puppet calls this idea *fragments*.
.. raw:: html
<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>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>A file to create using the concatenation of all of the source files.</td>
</tr>
<tr>
<td>src</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>An already existing directory full of source files.</td>
</tr>
<tr>
<td>backup</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Create a backup file (if <code>yes</code>), including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.</td>
</tr>
<tr>
<td>others</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>all arguments accepted by the <span class='module'>file</span> module also work here</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
assemble src=/etc/someapp/fragments dest=/etc/someapp/someapp.conf
</pre></p>
<br/>

View File

@@ -0,0 +1,44 @@
.. _async_status:
async_status
``````````````````````````````
.. versionadded:: 0.5
This module gets the status of an asynchronous task. See: http://ansible.cc/docs/playbooks2.html#asynchronous-actions-and-polling
.. raw:: html
<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>
<tr>
<td>jid</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Job or task identifier</td>
</tr>
<tr>
<td>mode</td>
<td>no</td>
<td>status</td>
<td><ul><li>status</li><li>cleanup</li></ul></td>
<td>if <code>status</code>, obtain the status; if <code>cleanup</code>, clean up the async job cache located in <code>~/.ansible_async/</code> for the specified job <em>jid</em>.</td>
</tr>
</table>
.. raw:: html
<br/>
.. raw:: html
<h4>Notes</h4>
<p>See <a href='http://ansible.cc/docs/playbooks2.html#asynchronous-actions-and-polling'>http://ansible.cc/docs/playbooks2.html#asynchronous-actions-and-polling</a></p>

View File

@@ -0,0 +1,52 @@
.. _authorized_key:
authorized_key
``````````````````````````````
.. versionadded:: 0.5
Adds or removes an SSH authorized key for a user from a remote host.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>whether the given key should or should not be in the file</td>
</tr>
<tr>
<td>user</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Name of the user who should have access to the remote host</td>
</tr>
<tr>
<td>key</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>the SSH public key, as a string</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
authorized_key user=charlie key="ssh-dss ASDF1234L+8BTwaRYr/rycsBF1D8e5pTxEsXHQs4iq+mZdyWqlW++L6pMiam1A8yweP+rKtgjK2httVS6GigVsuWWfOd7/sdWippefq74nppVUELHPKkaIOjJNN1zUHFoL/YMwAAAEBALnAsQN10TNGsRDe5arBsW8cTOjqLyYBcIqgPYTZW8zENErFxt7ij3fW3Jh/sCpnmy8rkS7FyK8ULX0PEy/2yDx8/5rXgMIICbRH/XaBy9Ud5bRBFVkEDu/r+rXP33wFPHjWjwvHAtfci1NRBAudQI/98DbcGQw5HmE89CjgZRo5ktkC5yu/8agEPocVjdHyZr7PaHfxZGUDGKtGRL2QzRYukCmWo1cZbMBHcI5FzImvTHS9/8B3SATjXMPgbfBuEeBwuBK5EjL+CtHY5bWs9kmYjmeo0KfUMH8hY4MAXDoKhQ7DhBPIrcjS5jPtoGxIREZjba67r6/P2XKXaCZH6Fc= charlie@example.org 2011-01-17"
</pre></p>
<p>Shorthand available in Ansible 0.8 and later</p> <p><pre>
authorized_key user=charlie key=$FILE(/home/charlie/.ssh/id_rsa.pub)
</pre></p>
<br/>

View File

@@ -0,0 +1,64 @@
.. _command:
command
``````````````````````````````
The command module takes the command name followed by a list of space-delimited arguments.
The given command will be executed on all selected nodes. It will not be processed through the shell, so variables like ``$HOME`` and operations like ``"<"``, ``">"``, ``"|"``, and ``"&"`` will not work. As such, all paths to commands must be fully qualified
.. raw:: html
<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>
<tr>
<td>creates</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>a filename, when it already exists, this step will <b>not</b> be run.</td>
</tr>
<tr>
<td>free_form</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>the command module takes a free form command to run</td>
</tr>
<tr>
<td>chdir</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>cd into this directory before running the command (added in Ansible 0.6)</td>
</tr>
<tr>
<td>removes</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>a filename, when it does not exist, this step will <b>not</b> be run. (added in Ansible 0.8)</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
command /sbin/shutdown -t now
</pre></p>
<p><em>creates</em>, <em>removes</em>, and <em>chdir</em> can be specified after the command. For instance, if you only want to run a command if a certain file does not exist, use this.</p> <p><pre>
command /usr/bin/make_database.sh arg1 arg2 creates=/path/to/database
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>If you want to run a command through the shell (say you are using <code><</code>, <code>></code>, <code>|</code>, etc), you actually want the <span class='module'>shell</span> module instead. The <span class='module'>command</span> module is much more secure as it's not affected by the user's environment.</p>

View File

@@ -0,0 +1,58 @@
.. _copy:
copy
``````````````````````````````
The ``copy`` module copies a file on the local box to remote locations.
.. raw:: html
<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>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Remote absolute path where the file should be copied to.</td>
</tr>
<tr>
<td>src</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Local path to a file to copy to the remote server; can be absolute or relative.</td>
</tr>
<tr>
<td>backup</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly. (added in Ansible 0.7)</td>
</tr>
<tr>
<td>others</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>all arguments accepted by the <span class='module'>file</span> module also work here</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
copy src=/srv/myfiles/foo.conf dest=/etc/foo.conf owner=foo group=foo mode=0644
</pre></p>
<p>Copy a new <code>ntp.conf</code> file into place, backing up the original if it differs from the copied version</p> <p><pre>
copy src=/mine/ntp.conf dest=/etc/ntp.conf owner=root group=root mode=644 backup=yes
</pre></p>
<br/>

View File

@@ -0,0 +1,51 @@
.. _easy_install:
easy_install
``````````````````````````````
.. versionadded:: 0.7
Installs Python libraries, optionally in a *virtualenv*
.. raw:: html
<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>
<tr>
<td>virtualenv</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>an optional <em>virtualenv</em> directory path to install into. If the <em>virtualenv</em> does not exist, it is created automatically</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>A Python library name</td>
</tr>
</table>
.. raw:: html
<p>Examples from Ansible Playbooks</p> <p><pre>
easy_install name=pip
</pre></p>
<p>Install <em>Flask</em> (<a href='http://flask.pocoo.org/'>http://flask.pocoo.org/</a>) into the specified <em>virtualenv</em></p> <p><pre>
easy_install name=flask virtualenv=/webapps/myapp/venv
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Please note that the <span class='module'>easy_install</span> module can only install Python libraries. Thus this module is not able to remove libraries. It is generally recommended to use the <span class='module'>pip</span> module which you can first install using <span class='module'>easy_install</span>.</p>
<p>Also note that <em>virtualenv</em> must be installed on the remote host if the <code>virtualenv</code> parameter is specified.</p>

View File

@@ -0,0 +1,17 @@
.. _facter:
facter
``````````````````````````````
.. versionadded:: 0.2
Runs the *facter* discovery program (https://github.com/puppetlabs/facter) on the remote system, returning JSON data that can be useful for inventory purposes.
.. raw:: html
<p>Example command-line invocation</p> <p><pre>
ansible www.example.net -m facter
</pre></p>
<br/>

View File

@@ -0,0 +1,42 @@
.. _fail:
fail
``````````````````````````````
.. versionadded:: 0.8
This module fails the progress with a custom message. It can be useful for bailing out when a certain condition is met using only_if.
.. raw:: html
<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>
<tr>
<td>msg</td>
<td>no</td>
<td>Failed because only_if condition is true</td>
<td><ul></ul></td>
<td>The customized message used for failing execution. If ommited, fail will simple bail out with a generic message.</td>
</tr>
<tr>
<td>rc</td>
<td>no</td>
<td>1</td>
<td><ul></ul></td>
<td>The return code of the failure. This is currently not used by Ansible, but might be used in the future.</td>
</tr>
</table>
.. raw:: html
<p>Example of how a playbook may fail when a condition is not met</p> <p><pre>
[{'action': 'fail msg="The system may not be provisioned according to the CMDB status."', 'only_if': "'$cmdb_status' != 'to-be-staged'"}]
</pre></p>
<br/>

View File

@@ -0,0 +1,42 @@
.. _fetch:
fetch
``````````````````````````````
.. versionadded:: 0.2
This module works like ``copy``, but in reverse. It is used for fetching files from remote machines and storing them locally in a file tree, organized by hostname.
.. raw:: html
<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>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>A directory to save the file into. For example, if the <em>dest</em> directory is <code>/backup</code> a src file named <code>/etc/profile</code> on host <code>host.example.com</code>, would be saved into <code>/backup/host.example.com/etc/profile</code></td>
</tr>
<tr>
<td>src</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The file on the remote system to fetch. This must be a file, not a directory. Recursive fetching may be supported in a later release.</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
fetch src=/var/log/messages dest=/home/logtree
</pre></p>
<br/>

View File

@@ -0,0 +1,119 @@
.. _file:
file
``````````````````````````````
Sets attributes of files, symlinks, and directories, or removes files/symlinks/directories. Many other modules support the same options as the file module - including ``copy``, ``template``, and ``assmeble``.
.. raw:: html
<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>
<tr>
<td>src</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>path of the file to link to (applies only to <code>state=link</code>).</td>
</tr>
<tr>
<td>group</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>name of the group that should own the file/directory, as would be fed to <em>chown</em></td>
</tr>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>defines the file being managed, unless when used with <em>state=link</em>, and then sets the destination to create a symbolic link to using <em>src</em></td>
</tr>
<tr>
<td>selevel</td>
<td>no</td>
<td>s0</td>
<td><ul></ul></td>
<td>level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the <code>range</code>. <code>_default</code> feature works as for <em>seuser</em>.</td>
</tr>
<tr>
<td>seuser</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>user part of SELinux file context. Will default to system policy, if applicable. If set to <code>_default</code>, it will use the <code>user</code> portion of the the policy if available</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>file</td>
<td><ul><li>file</li><li>link</li><li>directory</li><li>absent</li></ul></td>
<td>If <code>directory</code>, all immediate subdirectories will be created if they do not exist. If <code>file</code>, the file will NOT be created if it does not exist, see the <span class='module'>copy</span> or <span class='module'>template</span> module if you want that behavior. If <code>link</code>, the symbolic link will be created or changed. If <code>absent</code>, directories will be recursively deleted, and files or symlinks will be unlinked.</td>
</tr>
<tr>
<td>serole</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>role part of SELinux file context, <code>_default</code> feature works as for <em>seuser</em>.</td>
</tr>
<tr>
<td>mode</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>mode the file or directory should be, such as 0644 as would be fed to</td>
</tr>
<tr>
<td>context</td>
<td>no</td>
<td></td>
<td><ul><li>default</li></ul></td>
<td>accepts only <code>default</code> as value. This will restore a file's SELinux context in the policy. Does nothing if no default value is available.</td>
</tr>
<tr>
<td>owner</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>name of the user that should own the file/directory, as would be fed to <em>chown</em></td>
</tr>
<tr>
<td>force</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>force is required when changing an existing file to a directory, or a link to a directory, and so on. Use this with caution.</td>
</tr>
<tr>
<td>setype</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>type part of SELinux file context, <code>_default</code> feature works as for <em>seuser</em>.</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
file path=/etc/foo.conf owner=foo group=foo mode=0644
</pre></p>
<p><pre>
file src=/file/to/link/to dest=/path/to/symlink owner=foo group=foo state=link
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>See also <span class='module'>copy</span>, <span class='module'>template</span>, <span class='module'>assemble</span></p>

View File

@@ -0,0 +1,61 @@
.. _fireball:
fireball
``````````````````````````````
.. versionadded:: 0.9
This modules launches an ephemeral *fireball* ZeroMQ message bus daemon on the remote node which Ansible can to communicate with nodes at high speed.
The daemon listens on a configurable port for a configurable amount of time.
Starting a new fireball as a given user terminates any existing user fireballs.
Fireball mode is AES encrypted
.. raw:: html
<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>
<tr>
<td>minutes</td>
<td>no</td>
<td>30</td>
<td><ul></ul></td>
<td>The <em>fireball</em> listener daemon is started on nodes and will stay around for this number of minutes before turning itself off.</td>
</tr>
<tr>
<td>port</td>
<td>no</td>
<td>5099</td>
<td><ul></ul></td>
<td>TCP port for ZeroMQ</td>
</tr>
</table>
.. raw:: html
<p>This example playbook has two plays: the first launches <em>fireball</em> mode on all hosts via SSH, and the second actually starts using <em>fireball</em> node for subsequent management over the fireball interface</p> <p><pre>
- hosts: devservers
gather_facts: false
connection: ssh
sudo: yes
tasks:
- action: fireball
- hosts: devservers
connection: fireball
tasks:
- action: command /usr/bin/anything
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>See the advanced playbooks chapter for more about using fireball mode.</p>

View File

@@ -0,0 +1,61 @@
.. _get_url:
get_url
``````````````````````````````
.. versionadded:: 0.6
Downloads files from HTTP, HTTPS, or FTP to the remote server. The remote server must have direct access to the remote resource.
.. raw:: html
<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>
<tr>
<td>url</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>HTTP, HTTPS, or FTP URL</td>
</tr>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>absolute path of where to download the file to.If <em>dest</em> is a directory, the basename of the file on the remote server will be used. If a directory, <em>thirsty=yes</em> must also be set.</td>
</tr>
<tr>
<td>thirsty</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>if <code>yes</code>, will download the file every time and replace the file if the contents change. if <code>no</code>, the file will only be downloaded if the destination does not exist. Generally should be <code>yes</code> only for small local files. prior to 0.6, acts if <code>yes</code> by default. (added in Ansible 0.7)</td>
</tr>
<tr>
<td>others</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>all arguments accepted by the <span class='module'>file</span> module also work here</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
get_url url=http://example.com/path/file.conf dest=/etc/foo.conf mode=0440
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>This module doesn't yet support configuration for proxies or passwords.</p>

View File

@@ -0,0 +1,63 @@
.. _git:
git
``````````````````````````````
.. versionadded:: 0.0.1
Manage git checkouts of repositories to deploy files or software.
.. raw:: html
<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>
<tr>
<td>repo</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>git, ssh, or http protocol address of the git repository.</td>
</tr>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Absolute path of where the repository should be checked out to.</td>
</tr>
<tr>
<td>version</td>
<td>no</td>
<td>HEAD</td>
<td><ul></ul></td>
<td>What version of the repository to check out. This can be the git <em>SHA</em>, the literal string <em>HEAD</em>, branch name, or a tag name.</td>
</tr>
<tr>
<td>force</td>
<td>no</td>
<td>yes</td>
<td><ul><li>True</li><li>False</li></ul></td>
<td>(New in 0.7) If yes, any modified files in the working repository will be discarded. Prior to 0.7, this was always 'yes' and could not be disabled.</td>
</tr>
<tr>
<td>remote</td>
<td>no</td>
<td>origin</td>
<td><ul></ul></td>
<td>Name of the remote branch.</td>
</tr>
</table>
.. raw:: html
<p>Example git checkout from Ansible Playbooks</p> <p><pre>
git repo=git://foosball.example.org/path/to/repo.git dest=/srv/checkout version=release-0.22
</pre></p>
<br/>

View File

@@ -0,0 +1,56 @@
.. _group:
group
``````````````````````````````
.. versionadded:: 0.0.2
Manage presence of groups on a host.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>Whether the group should be present or not on the remote host.</td>
</tr>
<tr>
<td>gid</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optional <em>GID</em> to set for the group.</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Name of the group to manage.</td>
</tr>
<tr>
<td>system</td>
<td>no</td>
<td>no</td>
<td><ul><li>True</li><li>False</li></ul></td>
<td>If <em>yes</em>, indicates that the group created is a system group.</td>
</tr>
</table>
.. raw:: html
<p>Example group command from Ansible Playbooks</p> <p><pre>
group name=somegroup state=present
</pre></p>
<br/>

View File

@@ -0,0 +1,83 @@
.. _ini_file:
ini_file
``````````````````````````````
.. versionadded:: 0.9
Manage (add, remove, change) individual settings in an INI-style file without having to manage the file as a whole with, say, ``template`` or ``assemble``. Adds missing sections if they don't exist.
.. raw:: html
<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>
<tr>
<td>option</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>if set (required for changing a <em>value</em>), this is the name of the option.May be omitted if adding/removing a whole <em>section</em>.</td>
</tr>
<tr>
<td>others</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>all arguments accepted by the <span class='module'>file</span> module also work here</td>
</tr>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Path to the INI-style file; this file is created if required</td>
</tr>
<tr>
<td>section</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Section name in INI file. This is added if <code>state=present</code> automatically when a single value is being set.</td>
</tr>
<tr>
<td>backup</td>
<td>no</td>
<td></td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.</td>
</tr>
<tr>
<td>value</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>the string value to be associated with an <em>option</em>. May be omitted when removing an <em>option</em>.</td>
</tr>
</table>
.. raw:: html
<p>Ensure <code>fav=lemonade</code> is in section <code>[drinks]</code> in said file</p> <p><pre>
ini_file dest=/etc/conf section=drinks option=fav value=lemonade mode=0600 backup=true
</pre></p>
<p><pre>
ini_file dest=/etc/anotherconf
section=drinks
option=temperature
value=cold
backup=true
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>While it is possible to add an <em>option</em> without specifying a <em>value</em>, this makes no sense.</p>

View File

@@ -0,0 +1,74 @@
.. _lineinfile:
lineinfile
``````````````````````````````
.. versionadded:: 0.7
This module will search a file for a line, and ensure that it is present or absent.
This is primarily useful when you want to change a single line in a file only. For other cases, see the ``copy`` or ``template`` modules.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>Whether the line should be there or not.</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The file to modify</td>
</tr>
<tr>
<td>insertafter</td>
<td>no</td>
<td>EOF</td>
<td><ul><li>BOF</li><li>EOF</li></ul></td>
<td>Used with <code>state=present</code>. If specified, the line will be inserted after the specified regular expression. Two special values are available; <code>BOF</code> for inserting the line at the beginning of the file, and <code>EOF</code> for inserting the line at the end of the file.</td>
</tr>
<tr>
<td>regexp</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The regular expression to look for in the file. For <code>state=present</code>, the pattern to replace. For <code>state=absent</code>, the pattern of the line to remove.</td>
</tr>
<tr>
<td>line</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Required for <code>state=present</code>. The line to insert/replace into the file. Must match the value given to <code>regexp</code>.</td>
</tr>
<tr>
<td>backup</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.</td>
</tr>
</table>
.. raw:: html
<p><pre>
lineinfile name=/etc/selinux/config regexp=^SELINUX= line=SELINUX=disabled
</pre></p>
<p><pre>
lineinfile name=/etc/sudoers state=absent regexp="^%wheel"
</pre></p>
<br/>

View File

@@ -0,0 +1,77 @@
.. _mount:
mount
``````````````````````````````
.. versionadded:: 0.6
This module controls active and configured mount points in ``/etc/fstab``.
.. raw:: html
<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>
<tr>
<td>src</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>device to be mounted on <em>name</em>.</td>
</tr>
<tr>
<td>state</td>
<td>yes</td>
<td></td>
<td><ul><li>present</li><li>absent</li><li>mounted</li><li>unmounted</li></ul></td>
<td>If <code>mounted</code> or <code>unmounted</code>, the device will be actively mounted or unmounted as well as just configured in <em>fstab</em>. <code>absent</code> and <code>present</code> only deal with <em>fstab</em>.</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>path to the mount point, eg: <code>/mnt/files</code></td>
</tr>
<tr>
<td>dump</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>dump (see fstab(8))</td>
</tr>
<tr>
<td>passno</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>passno (see fstab(8))</td>
</tr>
<tr>
<td>opts</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>mount options (see fstab(8))</td>
</tr>
<tr>
<td>fstype</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>file-system type</td>
</tr>
</table>
.. raw:: html
<p>Mount DVD read-only</p> <p><pre>
mount name=/mnt/dvd src=/dev/sr0 fstype=iso9660 opts=ro
</pre></p>
<br/>

View File

@@ -0,0 +1,83 @@
.. _mysql_db:
mysql_db
``````````````````````````````
.. versionadded:: 0.6
Add or remove MySQL databases from a remote host.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>The database state</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>name of the database to add or remove</td>
</tr>
<tr>
<td>encoding</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Encoding mode</td>
</tr>
<tr>
<td>collation</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Collation mode</td>
</tr>
<tr>
<td>login_user</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The username used to authenticate with</td>
</tr>
<tr>
<td>login_host</td>
<td>no</td>
<td>localhost</td>
<td><ul></ul></td>
<td>Host running the database</td>
</tr>
<tr>
<td>login_password</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The password used to authenticate with</td>
</tr>
</table>
.. raw:: html
<p>Create a new database with name 'bobdata'</p> <p><pre>
mysql_db db=bobdata state=present
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Requires the MySQLdb Python package on the remote host. For Ubuntu, this is as easy as apt-get install python-mysqldb.</p>
<p>Both <code>login_password</code> and <code>login_username</code> are required when you are passing credentials. If none are present, the module will attempt to read the credentials from <code>~/.my.cnf</code>, and finally fall back to using the MySQL default login of 'root' with no password.</p>

View File

@@ -0,0 +1,96 @@
.. _mysql_user:
mysql_user
``````````````````````````````
.. versionadded:: 0.6
Adds or removes a user from a MySQL database.
.. raw:: html
<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>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>name of the user (role) to add or remove</td>
</tr>
<tr>
<td>login_user</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The username used to authenticate with</td>
</tr>
<tr>
<td>login_host</td>
<td>no</td>
<td>localhost</td>
<td><ul></ul></td>
<td>Host running the database</td>
</tr>
<tr>
<td>host</td>
<td>no</td>
<td>localhost</td>
<td><ul></ul></td>
<td>the 'host' part of the MySQL username</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>The database state</td>
</tr>
<tr>
<td>login_password</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The password used to authenticate with</td>
</tr>
<tr>
<td>password</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>set the user's password</td>
</tr>
<tr>
<td>priv</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>MySQL privileges string in the format: <code>db.table:priv1,priv2</code></td>
</tr>
</table>
.. raw:: html
<p>Create database user with name 'bob' and password '12345' with all database privileges</p> <p><pre>
mysql_user name=bob password=12345 priv=*.*:ALL state=present
</pre></p>
<p>Ensure no user named 'sally' exists, also passing in the auth credentials.</p> <p><pre>
mysql_user login_user=root login_password=123456 name=sally state=absent
</pre></p>
<p>Example privileges string format</p> <p><pre>
mydb.*:INSERT,UPDATE/anotherdb.*:SELECT/yetanotherdb.*:ALL
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Requires the MySQLdb Python package on the remote host. For Ubuntu, this is as easy as apt-get install python-mysqldb.</p>
<p>Both <code>login_password</code> and <code>login_username</code> are required when you are passing credentials. If none are present, the module will attempt to read the credentials from <code>~/.my.cnf</code>, and finally fall back to using the MySQL default login of 'root' with no password.</p>

View File

@@ -0,0 +1,95 @@
.. _nagios:
nagios
``````````````````````````````
.. versionadded:: 0.7
The ``nagios`` module has two basic functions: scheduling downtime and toggling alerts for services or hosts.
All actions require the ``host`` parameter to be given explicitly. In playbooks you can use the ``$inventory_hostname`` variable to refer to the host the playbook is currently running on.
You can specify multiple services at once by separating them with commas, .e.g., ``services=httpd,nfs,puppet``.
When specifying what service to handle there is a special service value, *host*, which will handle alerts/downtime for the *host itself*, e.g., ``service=host``. This keyword may not be given with other services at the same time. *Setting alerts/downtime for a host does not affect alerts/downtime for any of the services running on it.*
When using the ``nagios`` module you will need to specify your nagios server using the ``delegate_to`` parameter.
.. raw:: html
<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>
<tr>
<td>action</td>
<td>yes</td>
<td></td>
<td><ul><li>downtime</li><li>enable_alerts</li><li>disable_alerts</li><li>silence</li><li>unsilence</li></ul></td>
<td>Action to take.</td>
</tr>
<tr>
<td>host</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Host to operate on in Nagios.</td>
</tr>
<tr>
<td>author</td>
<td>no</td>
<td>Ansible</td>
<td><ul></ul></td>
<td>Author to leave downtime comments as. - Only useable with the <code>downtime</code> action.</td>
</tr>
<tr>
<td>services</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>What to manage downtime/alerts for. Separate multiple services with commas.<code>service</code> is an alias for <code>services</code>.<b>Required</b> option when using the <code>downtime</code>, <code>enable_alerts</code>, and <code>disable_alerts</code> actions.</td>
</tr>
<tr>
<td>minutes</td>
<td>no</td>
<td>30</td>
<td><ul></ul></td>
<td>Minutes to schedule downtime for.Only useable with the <code>downtime</code> action.</td>
</tr>
<tr>
<td>cmdfile</td>
<td>no</td>
<td>auto-detected</td>
<td><ul></ul></td>
<td>Path to the nagios <em>command file</em> (FIFO pipe).Only required if auto-detection fails.</td>
</tr>
</table>
.. raw:: html
<p>set 30 minutes of apache downtime</p> <p><pre>
nagios action=downtime minutes=30 service=httpd host=$inventory_hostname
</pre></p>
<p>schedule an hour of HOST downtime</p> <p><pre>
nagios action=downtime minutes=60 service=host host=$inventory_hostname
</pre></p>
<p>schedule downtime for a few services</p> <p><pre>
nagios action=downtime services=frob,foobar,qeuz host=$inventory_hostname
</pre></p>
<p>enable SMART disk alerts</p> <p><pre>
nagios action=enable_alerts service=smart host=$inventory_hostname
</pre></p>
<p>two services at once: disable httpd and nfs alerts</p> <p><pre>
nagios action=disable_alerts service=httpd,nfs host=$inventory_hostname
</pre></p>
<p>disable HOST alerts</p> <p><pre>
nagios action=disable_alerts service=host host=$inventory_hostname
</pre></p>
<p>silence ALL alerts</p> <p><pre>
nagios action=silence host=$inventory_hostname
</pre></p>
<p>unsilence all alerts</p> <p><pre>
nagios action=unsilence host=$inventory_hostname
</pre></p>
<br/>

View File

@@ -0,0 +1,17 @@
.. _ohai:
ohai
``````````````````````````````
.. versionadded:: 0.6
Similar to the ``facter`` module, this runs the *ohai* discovery program (http://wiki.opscode.com/display/chef/Ohai) on the remote host and returns JSON inventory data. *Ohai* data is a bit more verbose and nested than *facter*.
.. raw:: html
<p>Retrieve <em>ohai</em> data from all Web servers and store in one-file per host</p> <p><pre>
ansible webservers -m ohai --tree=/tmp/ohaidata
</pre></p>
<br/>

View File

@@ -0,0 +1,57 @@
.. _pause:
pause
``````````````````````````````
.. versionadded:: 0.8
Pauses playbook execution for a set amount of time, or until a prompt is acknowledged. All parameters are optional. The default behavior is to pause with a prompt.
You can use ``ctrl+c`` if you wish to advance a pause earlier than it is set to expire or if you need to abort a playbook run entirely. To continue early: press ``ctrl+c`` and then ``c``. To abort a playbook: press ``ctrl+c`` and then ``a``.
The pause module integrates into async/parallelized playbooks without any special considerations (see also: Rolling Updates). When using pauses with the ``serial`` playbook parameter (as in rolling updates) you are only prompted once for the current group of hosts.
.. raw:: html
<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>
<tr>
<td>seconds</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Number of minutes to pause for.</td>
</tr>
<tr>
<td>minutes</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Number of minutes to pause for.</td>
</tr>
<tr>
<td>prompt</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optional text to use for the prompt message.</td>
</tr>
</table>
.. raw:: html
<p>Pause for 5 minutes to build app cache.</p> <p><pre>
pause minutes=5
</pre></p>
<p>Pause until you can verify updates to an application were successful.</p> <p><pre>
pause
</pre></p>
<p>A helpful reminder of what to look out for post-update.</p> <p><pre>
pause prompt=Make sure org.foo.FooOverload exception is not present
</pre></p>
<br/>

View File

@@ -0,0 +1,16 @@
.. _ping:
ping
``````````````````````````````
A trivial test module, this module always returns 'pong' on successful contact. It does not make sense in playbooks, but is useful from ``/usr/bin/ansible``
.. raw:: html
<p>Test 'webservers' status</p> <p><pre>
ansible webservers -m ping
</pre></p>
<br/>

View File

@@ -0,0 +1,80 @@
.. _pip:
pip
``````````````````````````````
.. versionadded:: 0.7
Manage Python library dependencies.
.. raw:: html
<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>
<tr>
<td>virtualenv</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>An optional path to a virtualenv directory to install into</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li><li>latest</li></ul></td>
<td>The state of module</td>
</tr>
<tr>
<td>version</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The version number to install of the Python library specified in the 'name' parameter</td>
</tr>
<tr>
<td>requirements</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The path to a pip requirements file</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The name of a Python library to install</td>
</tr>
</table>
.. raw:: html
<p>Install <em>flask</em> python package.</p> <p><pre>
pip name=flask
</pre></p>
<p>Install <em>flask</em> python package on version 0.8.</p> <p><pre>
pip name=flask version=0.8
</pre></p>
<p>Install <em>Flask</em> (<a href='http://flask.pocoo.org/'>http://flask.pocoo.org/</a>) into the specified <em>virtualenv</em></p> <p><pre>
pip name=flask virtualenv=/srv/webapps/my_app/venv
</pre></p>
<p>Install specified python requirements.</p> <p><pre>
pip requirements=/srv/webapps/my_app/src/requirements.txt
</pre></p>
<p>Install specified python requirements in indicated virtualenv.</p> <p><pre>
pip requirements=/srv/webapps/my_app/src/requirements.txt virtualenv=/srv/webapps/my_app/venv
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Please note that <a href='http://www.virtualenv.org/, virtualenv'>http://www.virtualenv.org/, virtualenv</a> must be installed on the remote host if the virtualenv parameter is specified.</p>

View File

@@ -0,0 +1,76 @@
.. _postgresql_db:
postgresql_db
``````````````````````````````
.. versionadded:: 0.6
Add or remove PostgreSQL databases from a remote host.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>The database state</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>name of the database to add or remove</td>
</tr>
<tr>
<td>login_password</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The password used to authenticate with</td>
</tr>
<tr>
<td>owner</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Name of the role to set as owner of the database</td>
</tr>
<tr>
<td>login_user</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The username used to authenticate with</td>
</tr>
<tr>
<td>login_host</td>
<td>no</td>
<td>localhost</td>
<td><ul></ul></td>
<td>Host running the database</td>
</tr>
</table>
.. raw:: html
<p>Create a new database with name 'acme'</p> <p><pre>
postgresql_db db=acme
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>The default authentication assumes that you are either logging in as or sudo'ing to the postgres account on the host.</p>
<p>This module uses psycopg2, a Python PostgreSQL database adapter. You must ensure that psycopg2 is installed on the host before using this module. If the remote host is the PostgreSQL server (which is the default case), then PostgreSQL must also be installed on the remote host. For Ubuntu-based systems, install the postgresql, libpq-dev, and python-psycopg2 packages on the remote host before using this module.</p>

View File

@@ -0,0 +1,108 @@
.. _postgresql_user:
postgresql_user
``````````````````````````````
.. versionadded:: 0.6
Add or remove PostgreSQL users (roles) from a remote host and, optionally, grant the users access to an existing database or tables.
The fundamental function of the module is to create, or delete, roles from a PostgreSQL cluster. Privilege assignment, or removal, is an optional step, which works on one database at a time. This allows for the module to be called several times in the same module to modify the permissions on different databases, or to grant permissions to already existing users.
A user cannot be removed untill all the privileges have been stripped from the user. In such situation, if the module tries to remove the user it will fail. To avoid this from happening the fail_on_user option signals the module to try to remove the user, but if not possible keep going; the module will report if changes happened and separately if the user was removed or not.
.. raw:: html
<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>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>name of the user (role) to add or remove</td>
</tr>
<tr>
<td>login_user</td>
<td>no</td>
<td>postgres</td>
<td><ul></ul></td>
<td>User (role) used to authenticate with PostgreSQL</td>
</tr>
<tr>
<td>login_host</td>
<td>no</td>
<td>localhost</td>
<td><ul></ul></td>
<td>Host running PostgreSQL.</td>
</tr>
<tr>
<td>db</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>name of database where permissions will be granted</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>The database state</td>
</tr>
<tr>
<td>login_password</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Password used to authenticate with PostgreSQL</td>
</tr>
<tr>
<td>password</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>set the user's password</td>
</tr>
<tr>
<td>fail_on_user</td>
<td>no</td>
<td>True</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>if yes, fail when user can't be removed. Otherwise just log and continue</td>
</tr>
<tr>
<td>priv</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>PostgreSQL privileges string in the format: <code>table:priv1,priv2</code></td>
</tr>
</table>
.. raw:: html
<p>Create django user and grant access to database and products table</p> <p><pre>
postgresql_user db=acme user=django password=ceec4eif7ya priv=CONNECT/products:ALL
</pre></p>
<p>Remove test user privileges from acme</p> <p><pre>
postgresql_user db=acme user=test priv=ALL/products:ALL state=absent fail_on_user=no
</pre></p>
<p>Remove test user from test database and the cluster</p> <p><pre>
postgresql_user db=test user=test priv=ALL state=absent
</pre></p>
<p>Example privileges string format</p> <p><pre>
INSERT,UPDATE/table:SELECT/anothertable:ALL
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>The default authentication assumes that you are either logging in as or sudo'ing to the postgres account on the host.</p>
<p>This module uses psycopg2, a Python PostgreSQL database adapter. You must ensure that psycopg2 is installed on the host before using this module. If the remote host is the PostgreSQL server (which is the default case), then PostgreSQL must also be installed on the remote host. For Ubuntu-based systems, install the postgresql, libpq-dev, and python-psycopg2 packages on the remote host before using this module.</p>

View File

@@ -0,0 +1,16 @@
.. _raw:
raw
``````````````````````````````
Executes a low-down and dirty SSH command, not going through the module subsystem. This is useful and should only be done in two cases. The first case is installing python-simplejson on older (Python 2.4 and before) hosts that need it as a dependency to run modules, since nearly all core modules require it. Another is speaking to any devices such as routers that do not have any Python installed. In any other case, using the ``shell`` or ``command`` module is much more appropriate. Arguments given to ``raw`` are run directly through the configured remote shell and only output is returned. There is no error detection or change handler support for this module
.. raw:: html
<p>Example from /usr/bin/ansible to bootstrap a legacy python 2.4 host</p> <p><pre>
ansible newhost.example.com -m raw -a "yum -y install python-simplejson"
</pre></p>
<br/>

View File

@@ -0,0 +1,54 @@
.. _seboolean:
seboolean
``````````````````````````````
.. versionadded:: 0.7
Toggles SELinux booleans.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>yes</td>
<td></td>
<td><ul><li>true</li><li>false</li></ul></td>
<td>Desired boolean value</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Name of the boolean to configure</td>
</tr>
<tr>
<td>persistent</td>
<td>no</td>
<td></td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Set to 'yes' if the boolean setting should survive a reboot</td>
</tr>
</table>
.. raw:: html
<p>Set <em>httpd_can_network_connect</em> SELinux flag to <em>true</em> and <em>persistent</em></p> <p><pre>
seboolean name=httpd_can_network_connect state=true persistent=yes
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Not tested on any debian based system</p>

View File

@@ -0,0 +1,57 @@
.. _selinux:
selinux
``````````````````````````````
.. versionadded:: 0.7
Configures the SELinux mode and policy. A reboot may be required after usage. Ansible will not issue this reboot but will let you know when it is required.
.. raw:: html
<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>
<tr>
<td>policy</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>name of the SELinux policy to use (example: 'targeted')</td>
</tr>
<tr>
<td>state</td>
<td>yes</td>
<td></td>
<td><ul><li>enforcing</li><li>permissive</li><li>disabled</li></ul></td>
<td>The SELinux mode</td>
</tr>
<tr>
<td>conf</td>
<td>no</td>
<td>/etc/selinux/config</td>
<td><ul></ul></td>
<td>path to the SELinux configuration file, if non-standard</td>
</tr>
</table>
.. raw:: html
<p><pre>
selinux policy=targeted state=enforcing
</pre></p>
<p><pre>
selinux policy=targeted state=disabled
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Not tested on any debian based system</p>

View File

@@ -0,0 +1,68 @@
.. _service:
service
``````````````````````````````
.. versionadded:: 0.1
Controls services on remote hosts.
.. raw:: html
<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>
<tr>
<td>pattern</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>If the service does not respond to the status command, name a substring to look for as would be found in the output of the <em>ps</em> command as a stand-in for a status result. If the string is found, the servie will be assumed to be running. (added in Ansible 0.7)</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td></td>
<td><ul><li>running</li><li>started</li><li>stopped</li><li>restarted</li><li>reloaded</li></ul></td>
<td><em>started</em>, <em>stopped</em>, <em>reloaded</em>, <em>restarted</em>. <em>Started</em>/<em>stopped</em> are idempotent actions that will not run commands unless necessary. <em>restarted</em> will always bounce the service. <em>reloaded</em> will always reload.</td>
</tr>
<tr>
<td>enabled</td>
<td>no</td>
<td></td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Whether the service should start on boot.</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Name of the service.</td>
</tr>
</table>
.. raw:: html
<p>Example action from Ansible Playbooks</p> <p><pre>
service name=httpd state=started
</pre></p>
<p>Example action from Ansible Playbooks</p> <p><pre>
service name=httpd state=stopped
</pre></p>
<p>Example action from Ansible Playbooks</p> <p><pre>
service name=httpd state=restarted
</pre></p>
<p>Example action from Ansible Playbooks</p> <p><pre>
service name=httpd state=reloaded
</pre></p>
<p>Example action from Ansible Playbooks</p> <p><pre>
service name=foo pattern=/usr/bin/foo state=started
</pre></p>
<br/>

View File

@@ -0,0 +1,21 @@
.. _setup:
setup
``````````````````````````````
This module is automatically called by playbooks to gather useful variables about remote hosts that can be used in playbooks. It can also be executed directly by ``/usr/bin/ansible`` to check what variables are available to a host. Ansible provides many *facts* about the system, automatically.
.. raw:: html
<p>Obtain facts from all hosts and store them indexed by hostname at /tmp/facts.</p> <p><pre>
ansible all -m setup -tree /tmp/facts
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>More ansible facts will be added with successive releases. If <em>facter</em> or <em>ohai</em> are installed, variables from these programs will also be snapshotted into the JSON file for usage in templating. These variables are prefixed with <code>facter_</code> and <code>ohai_</code> so it's easy to tell their source. All variables are bubbled up to the caller. Using the ansible facts and choosing to not install <em>facter</em> and <em>ohai</em> means you can avoid Ruby-dependencies on your remote systems.</p>

View File

@@ -0,0 +1,54 @@
.. _shell:
shell
``````````````````````````````
.. versionadded:: 0.2
The shell module takes the command name followed by a list of arguments, space delimited. It is almost exactly like the ``command`` module but runs the command through the user's configured shell on the remote node.
.. raw:: html
<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>
<tr>
<td>creates</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>a filename, when it already exists, this step will NOT be run</td>
</tr>
<tr>
<td>chdir</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>cd into this directory before running the command (0.6 and later)</td>
</tr>
<tr>
<td>(free form)</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>The command module takes a free form command to run</td>
</tr>
</table>
.. raw:: html
<p>Execute the command in remote shell</p> <p><pre>
shell somescript.sh >> somelog.txt
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>If you want to execute a command securely and predicably, it may be better to use the <span class='module'>command</span> module instead. Best practices when writing playbooks will follow the trend of using <span class='module'>command</span> unless <span class='module'>shell</span> is explicitly required. When running ad-hoc commands, use your best judgement.</p>

View File

@@ -0,0 +1,44 @@
.. _slurp:
slurp
``````````````````````````````
This module works like ``fetch``. It is used for fetching a base64- encoded blob containing the data in a remote file.
.. raw:: html
<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>
<tr>
<td>src</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The file on the remote system to fetch. This must be a file, not a directory.</td>
</tr>
</table>
.. raw:: html
<p>Example using <code>/usr/bin/ansible</code></p> <p><pre>
ansible host -m slurp -a 'src=/tmp/xx'
host | success >> {
"content": "aGVsbG8gQW5zaWJsZSB3b3JsZAo=",
"encoding": "base64"
}
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>See also: <span class='module'>fetch</span></p>

View File

@@ -0,0 +1,54 @@
.. _subversion:
subversion
``````````````````````````````
.. versionadded:: 0.7
This module is really simple, so for now this checks out from the given branch of a repo at a particular SHA or tag. Latest is not supported, you should not be doing that.
.. raw:: html
<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>
<tr>
<td>repo</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The subversion URL to the repository.</td>
</tr>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Absolute path where the repository should be deployed.</td>
</tr>
<tr>
<td>force</td>
<td>no</td>
<td>True</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>If yes, any modified files in the working repository will be discarded. If no, this module will fail if it encounters modified files.</td>
</tr>
</table>
.. raw:: html
<p>Export subversion repository in a specified folder</p> <p><pre>
subversion repo=svn+ssh://an.example.org/path/to/repo dest=/src/checkout
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Requires subversion and grep on the client.</p>

View File

@@ -0,0 +1,42 @@
.. _supervisorctl:
supervisorctl
``````````````````````````````
.. versionadded:: 0.7
Manage the state of a program or group of programs running via Supervisord
.. raw:: html
<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>
<tr>
<td>state</td>
<td>yes</td>
<td></td>
<td><ul><li>started</li><li>stopped</li><li>restarted</li></ul></td>
<td>The state of service</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>The name of the supervisord program/process to manage</td>
</tr>
</table>
.. raw:: html
<p>Manage the state of program <em>my_app</em> to be in <em>started</em> state.</p> <p><pre>
supervisorctl name=my_app state=started
</pre></p>
<br/>

View File

@@ -0,0 +1,60 @@
.. _template:
template
``````````````````````````````
Templates are processed by the Jinja2 templating language (http://jinja.pocoo.org/docs/) - documentation on the template formatting can be found in the Template Designer Documentation (http://jinja.pocoo.org/docs/templates/).
.. raw:: html
<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>
<tr>
<td>dest</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Location to render the template to on the remote machine.</td>
</tr>
<tr>
<td>src</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Path of a Jinja2 formatted template on the local server. This can be a relative or absolute path.</td>
</tr>
<tr>
<td>backup</td>
<td>no</td>
<td>no</td>
<td><ul><li>yes</li><li>no</li></ul></td>
<td>Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.</td>
</tr>
<tr>
<td>others</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>all arguments accepted by the <span class='module'>file</span> module also work here</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
template src=/mytemplates/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode=0644
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Since Ansible version 0.9, templates are loaded with <code>trim_blocks=True</code>.</p>

View File

@@ -0,0 +1,123 @@
.. _user:
user
``````````````````````````````
.. versionadded:: 0.2
Manage user accounts and user attributes.
.. raw:: html
<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>
<tr>
<td>comment</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optionally sets the description (aka <em>GECOS</em>) of user account.</td>
</tr>
<tr>
<td>shell</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optionally set the user's shell.</td>
</tr>
<tr>
<td>force</td>
<td>no</td>
<td>no</td>
<td><ul><li>True</li><li>False</li></ul></td>
<td>When used with <em>state=absent</em>, behavior is as with <em>userdel --force</em>.</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>Name of the user to create, remove or modify.</td>
</tr>
<tr>
<td>createhome</td>
<td>no</td>
<td>yes</td>
<td><ul><li>True</li><li>False</li></ul></td>
<td>Unless set to <em>no</em>, a home directory will be made for the user when the account is created.</td>
</tr>
<tr>
<td>system</td>
<td>no</td>
<td>no</td>
<td><ul><li>True</li><li>False</li></ul></td>
<td>When creating an account, setting this to <em>yes</em> makes the user a system account. This setting cannot be changed on existing users.</td>
</tr>
<tr>
<td>remove</td>
<td>no</td>
<td>no</td>
<td><ul><li>True</li><li>False</li></ul></td>
<td>When used with <em>state=absent</em>, behavior is as with <em>userdel --remove</em>.</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>absent</li></ul></td>
<td>Whether the account should exist. When <em>absent</em>, removes the user account.</td>
</tr>
<tr>
<td>groups</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Puts the user in this comma-delimited list of groups.</td>
</tr>
<tr>
<td>home</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optionally set the user's home directory.</td>
</tr>
<tr>
<td>group</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optionally sets the user's primary group (takes a group name).</td>
</tr>
<tr>
<td>password</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optionally set the user's password to this crypted value. See the user example in the github examples directory for what this looks like in a playbook.</td>
</tr>
<tr>
<td>append</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>If <em>yes</em>, will only add groups, not set them to just the list in <em>groups</em>.</td>
</tr>
<tr>
<td>uid</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>Optionally sets the <em>UID</em> of the user.</td>
</tr>
</table>
.. raw:: html
<br/>

View File

@@ -0,0 +1,57 @@
.. _virt:
virt
``````````````````````````````
.. versionadded:: 0.2
Manages virtual machines supported by *libvirt*.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>no</td>
<td>no</td>
<td><ul><li>running</li><li>shutdown</li><li>destroyed</li><li>undefined</li></ul></td>
<td>Note that there may be some lag for state requests like <code>shutdown</code> since these refer only to VM states. After starting a guest, it may not be immediately accessible.</td>
</tr>
<tr>
<td>command</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>in addition to state management, various non-idempotent commands are available. See examples</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>name of the guest VM being managed</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
virt guest=alpha state=running
</pre></p>
<p>Example guest management with <code>/usr/bin/ansible</code></p> <p><pre>
ansible host -m virt -a "guest=alpha command=status"
</pre></p>
<br/>
.. raw:: html
<h4>Notes</h4>
<p>Other non-idempotent commands are: <code>status</code>, <code>pause</code>, <code>unpause</code>, <code>get_xml</code>, <code>autostart</code>, <code>freemem</code>, <code>list_vms</code>, <code>info</code>, <code>nodeinfo</code>, <code>virttype</code></p>

View File

@@ -0,0 +1,63 @@
.. _wait_for:
wait_for
``````````````````````````````
.. versionadded:: 0.7
This is useful for when services are not immediately available after their init scripts return - which is true of certain Java application servers. It is also useful when starting guests with the ``virt`` module and needing to pause until they are ready.
.. raw:: html
<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>
<tr>
<td>delay</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>number of seconds to wait before starting to poll</td>
</tr>
<tr>
<td>host</td>
<td>no</td>
<td>127.0.0.1</td>
<td><ul></ul></td>
<td>hostname or IP address to wait for</td>
</tr>
<tr>
<td>port</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>port number to poll</td>
</tr>
<tr>
<td>timeout</td>
<td>no</td>
<td>300</td>
<td><ul></ul></td>
<td>maximum number of seconds to wait for</td>
</tr>
<tr>
<td>state</td>
<td>no</td>
<td>started</td>
<td><ul><li>started</li><li>stopped</li></ul></td>
<td>either <code>started</code>, or <code>stopped</code> depending on whether the module should poll for the port being open or closed.</td>
</tr>
</table>
.. raw:: html
<p>Example from Ansible Playbooks</p> <p><pre>
wait_for port=8000 delay=10
</pre></p>
<br/>

View File

@@ -0,0 +1,54 @@
.. _yum:
yum
``````````````````````````````
Will install, upgrade, remove, and list packages with the *yum* package manager.
.. raw:: html
<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>
<tr>
<td>state</td>
<td>no</td>
<td>present</td>
<td><ul><li>present</li><li>latest</li><li>absent</li></ul></td>
<td>whether to install (<code>present</code>, <code>latest</code>), or remove (<code>absent</code>) a package.</td>
</tr>
<tr>
<td>list</td>
<td>no</td>
<td></td>
<td><ul></ul></td>
<td>various non-idempotent commands for usage with <code>/usr/bin/ansible</code> and <em>not</em> playbooks. See examples.</td>
</tr>
<tr>
<td>name</td>
<td>yes</td>
<td></td>
<td><ul></ul></td>
<td>package name, or package specifier with version, like <code>name-1.0</code>.</td>
</tr>
</table>
.. raw:: html
<p><pre>
yum name=httpd state=latest
</pre></p>
<p><pre>
yum name=httpd state=removed
</pre></p>
<p><pre>
yum name=httpd state=installed
</pre></p>
<br/>

215
docsite/rst/patterns.rst Normal file
View File

@@ -0,0 +1,215 @@
.. _patterns:
Inventory & Patterns
====================
Ansible works against multiple systems in your infrastructure at the
same time. It does this by selecting portions of systems listed in
Ansible's inventory file, which defaults to /etc/ansible/hosts.
.. contents:: `Table of contents`
:depth: 2
:backlinks: top
.. _inventoryformat:
Hosts and Groups
++++++++++++++++
The format for /etc/ansible/hosts is an INI format and looks like this::
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
The things in brackets are group names. You don't have to have them,
but they are useful.
If you have hosts that run on non-standard SSH ports you can put the port number
after the hostname with a colon.
four.example.com:5309
In 0.6 and later, if you have a lot of hosts following similar patterns you can do this rather than listing each hostname::
[webservers]
www[01:50].example.com
Leading zeros can be included or removed, as desired, and the ranges are inclusive.
Selecting Targets
+++++++++++++++++
We'll go over how to use the command line in :doc:`examples` section, however, basically it looks like this::
ansible <pattern_goes_here> -m <module_name> -a <arguments>
Such as::
ansible webservers -m service -a "name=httpd state=restarted"
Within :doc:`playbooks`, these patterns can be used for even greater purposes.
Anyway, to use Ansible, you'll first need to know how to tell Ansible which hosts in your inventory file to talk to.
This is done by designating particular host names or groups of hosts.
The following patterns target all hosts in the inventory file::
all
*
Basically 'all' is an alias for '*'. It is also possible to address a specific host or hosts::
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
The following patterns address one or more groups, which are denoted
with the aforementioned bracket headers in the inventory file::
webservers
webservers:dbservers
You can exclude groups as well, for instance, all webservers not in Phoenix::
webservers:!phoenix
Individual host names (or IPs), but not groups, can also be referenced using
wildcards::
*.example.com
*.com
It's also ok to mix wildcard patterns and groups at the same time::
one*.com:dbservers
Easy enough. See :doc:`examples` and then :doc:`playbooks` for how to do things to selected hosts.
Host Variables
++++++++++++++
It is easy to assign variables to hosts that will be used later in playbooks::
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
Group Variables
+++++++++++++++
Variables can also be applied to an entire group at once::
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
Groups of Groups, and Group Variables
+++++++++++++++++++++++++++++++++++++
It is also possible to make groups of groups and assign
variables to groups. These variables can be used by /usr/bin/ansible-playbook, but not
/usr/bin/ansible::
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
[southeast:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
[usa:children]
southeast
northeast
southwest
southeast
If you need to store lists or hash data, or prefer to keep host and group specific variables
seperate from the inventory file, see the next section.
Splitting Out Host and Group Specific Data
++++++++++++++++++++++++++++++++++++++++++
.. versionadded:: 0.6
In addition to the storing variables directly in the INI file, host
and group variables can be stored in individual files relative to the
inventory file. These variable files are in YAML format.
Assuming the inventory file path is::
/etc/ansible/hosts
If the host is named 'foosball', and in groups 'raleigh' and 'webservers', variables
in YAML files at the following locations will be made available to the host::
/etc/ansible/group_vars/raleigh
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
For instance, suppose you have hosts grouped by datacenter, and each datacenter
uses some different servers. The data in the groupfile '/etc/ansible/group_vars/raleigh' for
the 'raleigh' group might look like::
---
ntp_server: acme.example.org
database_server: storage.example.org
It is ok if these files do not exist, this is an optional feature.
Tip: Keeping your inventory file and variables in a git repo (or other version control)
is an excellent way to track changes to your inventory and host variables.
.. versionadded:: 0.5
If you ever have two python interpreters on a system, set a
variable called 'ansible_python_interpreter' to the Python
interpreter path you would like to use.
YAML Inventory
++++++++++++++
.. deprecated:: 0.7
Ansible's YAML inventory format is deprecated and will be removed in
Ansible 0.7. Ansible 0.6 includes a `conversion script
<https://github.com/ansible/ansible/blob/devel/examples/scripts/yaml_to_ini.py>`_.
Usage::
yaml_to_ini.py /etc/ansible/hosts
.. seealso::
:doc:`examples`
Examples of basic commands
:doc:`playbooks`
Learning ansible's configuration management language
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

411
docsite/rst/playbooks.rst Normal file
View File

@@ -0,0 +1,411 @@
Playbooks
=========
.. contents::
:depth: 2
:backlinks: top
Introduction
````````````
Playbooks are a completely different way to use ansible than in task execution mode, and are
particularly powerful. Simply put, playbooks are the basis for a really simple
configuration management and multi-machine deployment system,
unlike any that already exist, and one that is very well suited to deploying complex applications.
Playbooks can declare configurations, but they can also orchestrate steps of
any manual ordered process, even as different steps must bounce back and forth
between sets of machines in particular orders. They can launch tasks
synchronously or asynchronously.
While you might run the main /usr/bin/ansible program for ad-hoc
tasks, playbooks are more likely to be kept in source control and used
to push out your configuration or assure the configurations of your
remote systems are in spec.
Let's dive in and see how they work. As you go, you may wish to open
the `github examples directory <https://github.com/ansible/ansible/tree/devel/examples/playbooks>`_ in
another tab, so you can apply the theory to what things look like in practice.
Playbook Language Example
`````````````````````````
Playbooks are expressed in YAML format and have a minimum of syntax.
Each playbook is composed of one or more 'plays' in a list.
The goal of a play is map a group of hosts to some well defined roles, represented by
things ansible called tasks. At the basic level, a task is nothing more than a call
to an ansible module, which you should have learned about in earlier chapters.
By composing a playbook of multiple 'plays', it is possible to
orchestrate multi-machine deployments, running certain steps on all
machines in the webservers group, then certain steps on the database
server group, then more commands back on the webservers group, etc.
For starters, here's a playbook that contains just one play::
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
user: root
tasks:
- name: ensure apache is at the latest version
action: yum pkg=httpd state=latest
- name: write the apache config file
action: template src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
action: service name=httpd state=started
handlers:
- name: restart apache
action: service name=httpd state=restarted
Below, we'll break down what the various features of the playbook language are.
Basics
``````
Hosts and Users
+++++++++++++++
For each play in a playbook, you get to choose which machines in your infrastructure
to target and what remote user to complete the steps (called tasks) as.
The `hosts` line is a list of one or more groups or host patterns,
separated by colons, as described in the :ref:`patterns`
documentation. The `user` is just the name of the user account::
---
- hosts: webservers
user: root
Support for running things from sudo is also available::
---
- hosts: webservers
user: yourname
sudo: True
You can also login as you, and then sudo to different users than root::
---
- hosts: webservers
user: yourname
sudo: True
sudo_user: postgres
If you need to specify a password to sudo, run `ansible-playbook` with ``--ask-sudo-pass`` (`-K`).
If you run a sudo playbook and the playbook seems to hang, it's probably stuck at the sudo prompt.
Just `Control-C` to kill it and run it again with `-K`.
.. important::
When using `sudo_user` to a user other than root, the module
arguments are briefly written into a random tempfile in /tmp.
These are deleted immediately after the command is executed. This
only occurs when sudoing from a user like 'bob' to 'timmy', not
when going from 'bob' to 'root', or logging in directly as 'bob' or
'root'. If this concerns you that this data is briefly readable
(not writeable), avoid transferring uncrypted passwords with
`sudo_user` set. In other cases, '/tmp' is not used and this does
not come into play. Ansible also takes care to not log password
parameters.
Vars section
++++++++++++
The `vars` section contains a list of variables and values that can be used in the plays, like this::
---
- hosts: webservers
user: root
vars:
http_port: 80
van_halen_port: 5150
other: 'magic'
These variables can be used later in the playbook like this::
$varname or ${varname}
The later is useful in the event you need to do something like ${other}_some_string.
Inside templates, the full power of the `Jinja2 <http://jinja.pocoo.org/docs/>`_ templating language is also available, which looks like this::
{{ varname }}
The Jinja2 documentation provides information about how to construct loops and conditionals for those
who which to use more advanced templating. This is optional and the $varname format still works in template
files.
If there are discovered variables about the system, called 'facts', these variables bubble up back into the
playbook, and can be used on each system just like explicitly set variables. Ansible provides several
of these, prefixed with 'ansible', and are documented under 'setup' in the module documentation. Additionally,
facts can be gathered by ohai and facter if they are installed. Facter variables are prefixed with ``facter_`` and Ohai
variables are prefixed with ``ohai_``.
So for instance, if I wanted
to write the hostname into the /etc/motd file, I could say::
- name: write the motd
action: template src=/srv/templates/motd.j2 dest=/etc/motd
And in /srv/templates/motd.j2::
You are logged into {{ facter_hostname }}
But we're getting ahead of ourselves. Let's talk about tasks.
Tasks list
++++++++++
Each play contains a list of tasks. Tasks are executed in order, one
at a time, against all machines matched by the host pattern,
before moving on to the next task. It is important to understand that, within a play,
all hosts are going to get the same task directives. It is the purpose of a play to map
a selection of hosts to tasks.
When running the playbook, which runs top to bottom, hosts with failed tasks are
taken out of the rotation for the entire playbook. If things fail, simply correct the playbook file and rerun.
The goal of each task is to execute a module, with very specific arguments.
Variables, as mentioned above, can be used in arguments to modules.
Modules are 'idempotent', meaning if you run them
again, they will make the changes they are told to make to bring the
system to the desired state. This makes it very safe to rerun
the same playbook multiple times. They won't change things
unless they have to change things.
The `command` and `shell` modules will typically rerun the same command again,
which is totally ok if the command is something like
'chmod' or 'setsebool', etc. Though there is a 'creates' flag available which can
be used to make these modules also idempotent.
Every task should have a `name`, which is included in the output from
running the playbook. This is output for humans, so it is
nice to have reasonably good descriptions of each task step. If the name
is not provided though, the string fed to 'action' will be used for
output.
Here is what a basic task looks like, as with most modules,
the service module takes key=value arguments::
tasks:
- name: make sure apache is running
action: service name=httpd state=running
The `command` and `shell` modules are the one modules that just takes a list
of arguments, and don't use the key=value form. This makes
them work just like you would expect. Simple::
tasks:
- name: disable selinux
action: command /sbin/setenforce 0
The command and shell module care about return codes, so if you have a command
who's successful exit code is not zero, you may wish to do this::
tasks:
- name: run this command and ignore the result
action: shell /usr/bin/somecommand & /bin/true
Variables can be used in action lines. Suppose you defined
a variable called 'vhost' in the 'vars' section, you could do this::
tasks:
- name: create a virtual host file for $vhost
action: template src=somefile.j2 dest=/etc/httpd/conf.d/$vhost
Those same variables are usable in templates, which we'll get to later.
Now in a very basic playbook all the tasks will be listed directly in that play, though it will usually
make more sense to break up tasks using the 'include:' directive. We'll show that a bit later.
Running Operations On Change
````````````````````````````
As we've mentioned, modules are written to be 'idempotent' and can relay when
they have made a change on the remote system. Playbooks recognize this and
have a basic event system that can be used to respond to change.
These 'notify' actions are triggered at the end of each 'play' in a playbook, and
trigger only once each. For instance, multiple resources may indicate
that apache needs to be restarted, but apache will only be bounced once.
Here's an example of restarting two services when the contents of a file
change, but only if the file changes::
- name: template configuration file
action: template src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
The things listed in the 'notify' section of a task are called
handlers.
Handlers are lists of tasks, not really any different from regular
tasks, that are referenced by name. Handlers are what notifiers
notify. If nothing notifies a handler, it will not run. Regardless
of how many things notify a handler, it will run only once, after all
of the tasks complete in a particular play.
Here's an example handlers section::
handlers:
- name: restart memcached
action: service name=memcached state=restarted
- name: restart apache
action: service name=apache state=restarted
Handlers are best used to restart services and trigger reboots. You probably
won't need them for much else.
.. note::
Notify handlers are always run in the order written.
Include Files And Encouraging Reuse
```````````````````````````````````
Suppose you want to reuse lists of tasks between plays or playbooks. You can use
include files to do this. Use of included task lists is a great way to define a role
that system is going to fulfill. Remember, the goal of a play in a playbook is to map
a group of systems into multiple roles. Let's see what this looks like...
A task include file simply contains a flat list of tasks, like so::
---
# possibly saved as tasks/foo.yml
- name: placeholder foo
action: command /bin/foo
- name: placeholder bar
action: command /bin/bar
Include directives look like this, and can be mixed in with regular tasks in a playbook::
tasks:
- include: tasks/foo.yml
You can also pass variables into includes. We call this a 'parameterized include'.
For instance, if deploying multiple wordpress instances, I could
contain all of my wordpress tasks in a single wordpress.yml file, and use it like so::
tasks:
- include: wordpress.yml user=timmy
- include: wordpress.yml user=alice
- include: wordpress.yml user=bob
Variables passed in can then be used in the included files. You can reference them like this::
$user
(In addition to the explicitly passed in parameters, all variables from
the vars section are also available for use here as well.)
.. note::
Task include statements are only usable one-level deep.
This means task includes can not include other
task includes. This may change in a later release.
Includes can also be used in the 'handlers' section, for instance, if you
want to define how to restart apache, you only have to do that once for all
of your playbooks. You might make a handlers.yml that looks like::
----
# this might be in a file like handlers/handlers.yml
- name: restart apache
action: service name=apache state=restarted
And in your main playbook file, just include it like so, at the bottom
of a play::
handlers:
- include: handlers/handlers.yml
You can mix in includes along with your regular non-included tasks and handlers.
Includes can also be used to import one playbook file into another. This allows
you to define a top-level playbook that is composed of other playbooks.
For example::
- name: this is a play at the top level of a file
hosts: all
user: root
tasks:
- name: say hi
tags: foo
action: shell echo "hi..."
- include: load_balancers.yml
- include: webservers.yml
- include: dbservers.yml
Note that you cannot do variable substitution when including one playbook
inside another.
.. note::
You can not conditionally path the location to an include file,
like you can with 'vars_files'. If you find yourself needing to do
this, consider how you can restructure your playbook to be more
class/role oriented. This is to say you cannot use a 'fact' to
decide what include file to use. All hosts contained within the
play are going to get the same tasks. ('only_if' provides some
ability for hosts to conditionally skip tasks).
Executing A Playbook
````````````````````
Now that you've learned playbook syntax, how do you run a playbook? It's simple.
Let's run a playbook using a parallelism level of 10::
ansible-playbook playbook.yml -f 10
Tips and Tricks
```````````````
Look at the bottom of the playbook execution for a summary of the nodes that were executed
and how they performed. General failures and fatal "unreachable" communication attempts are
kept seperate in the counts.
If you ever want to see detailed output from successful modules as well as unsuccessful ones,
use the '--verbose' flag. This is available in Ansible 0.5 and later.
Also, in version 0.5 and later, Ansible playbook output is vastly upgraded if the cowsay
package is installed. Try it!
In version 0.7 and later, to see what hosts would be affected by a playbook before you run it, you
can do this::
ansible-playbook playbook.yml --list-hosts.
.. seealso::
:doc:`YAMLSyntax`
Learn about YAML syntax
:doc:`playbooks`
Review the basic Playbook language features
:doc:`playbooks2`
Learn about Advanced Playbook Features
:doc:`bestpractices`
Various tips about managing playbooks in the real world
:doc:`modules`
Learn about available modules
:doc:`moduledev`
Learn how to extend Ansible by writing your own modules
:doc:`patterns`
Learn about how to select hosts
`Github examples directory <https://github.com/ansible/ansible/tree/devel/examples/playbooks>`_
Complete playbook files from the github project source
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups

572
docsite/rst/playbooks2.rst Normal file
View File

@@ -0,0 +1,572 @@
Advanced Playbooks
==================
Here are some advanced features of the playbooks language. Using all of these features
are not neccessary, but many of them will prove useful. If a feature doesn't seem immediately
relevant, feel free to skip it. For many people, the features documented in `playbooks` will
be 90% or more of what they use in Ansible.
.. contents::
:depth: 2
:backlinks: top
Tags
````
.. versionadded:: 0.6
If you have a large playbook it may become useful to be able to run a
specific part of the configuration. Both plays and tasks support a
"tags:" attribute for this reason.
Example::
tasks:
- action: yum name=$item state=installed
with_items:
- httpd
- memcached
tags:
- packages
- action: template src=templates/src.j2 dest=/etc/foo.conf
tags:
- configuration
If you wanted to just run the "configuration" and "packages" part of a very long playbook, you could do this::
ansible-playbook example.yml --tags "configuration,packages"
Playbooks Including Playbooks
`````````````````````````````
.. versionadded:: 0.6
To further advance the concept of include files, playbook files can
include other playbook files. Suppose you define the behavior of all
your webservers in "webservers.yml" and all your database servers in
"dbservers.yml". You can create a "site.yml" that would reconfigure
all of your systems like this::
----
- include: playbooks/webservers.yml
- include: playbooks/dbservers.yml
This concept works great with tags to rapidly select exactly what plays you want to run, and exactly
what parts of those plays.
Ignoring Failed Commands
````````````````````````
.. deprecated:: 0.6
Generally playbooks will stop executing any more steps on a host that
has a failure. Sometimes, though, you want to continue on. To do so,
write a task that looks like this::
- name: this will not be counted as a failure
action: command /bin/false
ignore_errors: True
Accessing Complex Variable Data
```````````````````````````````
Some provided facts, like networking information, are made available as nested data structures. To access
them a simple '$foo' is not sufficient, but it is still easy to do. Here's how we get an IP address::
${ansible_eth0.ipv4.address}
It is also possible to access variables whose elements are arrays::
${somelist[0]}
And the array and hash reference syntaxes can be mixed.
In templates, the simple access form still holds, but they can also be accessed from Jinja2 in more Python-native ways if
that is preferred::
{{ ansible_eth0["ipv4"]["address"] }}
Accessing Information About Other Hosts
```````````````````````````````````````
If your database server wants to check the value of a 'fact' from another node, or an inventory variable
assigned to another node, it's easy to do so within a template or even an action line::
${hostvars.hostname.factname}
.. note::
No database or other complex system is required to exchange data
between hosts. The hosts that you want to reference data from must
be included in either the current play or any previous play.
Additionally, *group_names* is a list (array) of all the groups the current host is in. This can be used in templates using Jinja2 syntax to make template source files that vary based on the group membership (or role) of the host::
{% if 'webserver' in group_names %}
# some part of a configuration file that only applies to webservers
{% endif %}
*groups* is a list of all the groups (and hosts) in the inventory. This can be used to enumerate all hosts within a group.
For example::
{% for host in groups['app_servers'] %}
# something that applies to all app servers.
{% endfor %}
Use cases include pointing a frontend proxy server to all of the app servers, setting up the correct firewall rules between servers, etc.
*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
reasons. If you have a long FQDN, *inventory_hostname_short* (in Ansible 0.6) also contains the part up to the first
period.
Don't worry about any of this unless you think you need it. You'll know when you do.
Variable File Seperation
````````````````````````
It's a great idea to keep your playbooks under source control, but
you may wish to make the playbook source public while keeping certain
important variables private. Similarly, sometimes you may just
want to keep certain information in different files, away from
the main playbook.
You can do this by using an external variables file, or files, just like this::
---
- hosts: all
user: root
vars:
favcolor: blue
vars_files:
- /vars/external_vars.yml
tasks:
- name: this is just a placeholder
action: command /bin/echo foo
This removes the risk of sharing sensitive data with others when
sharing your playbook source with them.
The contents of each variables file is a simple YAML dictionary, like this::
---
# in the above example, this would be vars/external_vars.yml
somevar: somevalue
password: magic
.. note::
It's also possible to keep per-host and per-group variables in very
similar files, this is covered in :ref:`patterns`.
Prompting For Sensitive Data
````````````````````````````
You may wish to prompt the user for certain input, and can
do so with the similarly named 'vars_prompt' section. This has uses
beyond security, for instance, you may use the same playbook for all
software releases and would prompt for a particular release version
in a push-script::
---
- hosts: all
user: root
vars:
from: "camelot"
vars_prompt:
name: "what is your name?"
quest: "what is your quest?"
favcolor: "what is your favorite color?"
There are full examples of both of these items in the github examples/playbooks directory.
An alternative form of vars_prompt allows for hiding input from the user, and may later support
some other options, but otherwise works equivalently::
vars_prompt:
- name: "some_password"
prompt: "Enter password"
private: True
- name: "release_version"
prompt: "Product release version"
private: False
Passing Variables On The Command Line
`````````````````````````````````````
In addition to `vars_prompt` and `vars_files`, it is possible to send variables over
the ansible command line. This is particularly useful when writing a generic release playbook
where you may want to pass in the version of the application to deploy::
ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
This is useful, for, among other things, setting the hosts group or the user for the playbook.
Example::
-----
- user: $user
hosts: $hosts
tasks:
- ...
ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"
Conditional Execution
`````````````````````
Sometimes you will want to skip a particular step on a particular host. This could be something
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.
This is easy to do in Ansible, with the `only_if` clause, which actually is a Python expression.
Don't panic -- it's actually pretty simple::
vars:
favcolor: blue
is_favcolor_blue: "'$favcolor' == 'blue'"
is_centos: "'$facter_operatingsystem' == 'CentOS'"
tasks:
- name: "shutdown if my favorite color is blue"
action: command /sbin/shutdown -t now
only_if: '$is_favcolor_blue'
Variables from tools like `facter` and `ohai` can be used here, if installed, or you can
use variables that bubble up from ansible, which many are provided by the :ref:`setup` module. As a reminder,
these variables are prefixed, so it's `$facter_operatingsystem`, not `$operatingsystem`. Ansible's
built in variables are prefixed with `ansible_`.
The only_if expression is actually a tiny small bit of Python, so be sure to quote variables and make something
that evaluates to `True` or `False`. It is a good idea to use 'vars_files' instead of 'vars' to define
all of your conditional expressions in a way that makes them very easy to reuse between plays
and playbooks.
You cannot use live checks here, like 'os.path.exists', so don't try.
It's also easy to provide your own facts if you want, which is covered in :doc:`moduledev`. To run them, just
make a call to your own custom fact gathering module at the top of your list of tasks, and variables returned
there will be accessible to future tasks::
tasks:
- name: gather site specific fact data
action: site_facts
- action: command echo ${my_custom_fact_can_be_used_now}
Conditional Imports
```````````````````
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.
As an example, the name of the Apache package may be different between CentOS and Debian,
but it is easily handled with a minimum of syntax in an Ansible Playbook::
---
- hosts: all
user: root
vars_files:
- "vars/common.yml"
- [ "vars/$facter_operatingsystem.yml", "vars/os_defaults.yml" ]
tasks:
- name: make sure apache is running
action: service name=$apache state=running
.. note::
The variable (`$facter_operatingsystem`) is being interpolated into
the list of filenames being defined for vars_files.
As a reminder, the various YAML files contain just keys and values::
---
# for vars/CentOS.yml
apache: httpd
somethingelse: 42
How does this work? If the operating system was 'CentOS', the first file Ansible would try to import
would be 'vars/CentOS.yml', followed up by '/vars/os_defaults.yml' if that file
did not exist. If no files in the list were found, an error would be raised.
On Debian, it would instead first look towards 'vars/Debian.yml' instead of 'vars/CentOS.yml', before
falling back on 'vars/os_defaults.yml'. Pretty simple.
To use this conditional import feature, you'll need facter or ohai installed prior to running the playbook, but
you can of course push this out with Ansible if you like::
# for facter
ansible -m yum -a "pkg=facter ensure=installed"
ansible -m yum -a "pkg=ruby-json ensure=installed"
# for ohai
ansible -m yum -a "pkg=ohai ensure=installed"
Ansible's approach to configuration -- seperating variables from tasks, keeps your playbooks
from turning into arbitrary code with ugly nested ifs, conditionals, and so on - and results
in more streamlined & auditable configuration rules -- especially because there are a
minimum of decision points to track.
Loops
`````
To save some typing, repeated tasks can be written in short-hand like so::
- name: add user $item
action: user name=$item state=present groups=wheel
with_items:
- testuser1
- testuser2
If you have defined a YAML list in a variables file, or the 'vars' section, you can also do::
with_items: $somelist
The above would be the equivalent of::
- name: add user testuser1
action: user name=testuser1 state=present groups=wheel
- name: add user testuser2
action: user name=testuser2 state=present groups=wheel
The yum and apt modules use with_items to execute fewer package manager transactions.
Selecting Files And Templates Based On Variables
````````````````````````````````````````````````
Sometimes a configuration file you want to copy, or a template you will use may depend on a variable.
The following construct selects the first available file appropriate for the variables of a given host,
which is often much cleaner than putting a lot of if conditionals in a template.
The following example shows how to template out a configuration file that was very different between, say,
CentOS and Debian::
- name: template a file
action: template src=$item dest=/etc/myapp/foo.conf
first_available_file:
- /srv/templates/myapp/${ansible_distribution}.conf
- /srv/templates/myapp/default.conf
Asynchronous Actions and Polling
````````````````````````````````
By default tasks in playbooks block, meaning the connections stay open
until the task is done on each node. If executing playbooks with
a small parallelism value (aka ``--forks``), you may wish that long
running operations can go faster. The easiest way to do this is
to kick them off all at once and then poll until they are done.
You will also want to use asynchronous mode on very long running
operations that might be subject to timeout.
To launch a task asynchronously, specify its maximum runtime
and how frequently you would like to poll for status. The default
poll value is 10 seconds if you do not specify a value for `poll`::
---
- hosts: all
user: root
tasks:
- name: simulate long running op (15 sec), wait for up to 45, poll every 5
action: command /bin/sleep 15
async: 45
poll: 5
.. note::
There is no default for the async time limit. If you leave off the
'async' keyword, the task runs synchronously, which is Ansible's
default.
Alternatively, if you do not need to wait on the task to complete, you may
"fire and forget" by specifying a poll value of 0::
---
- hosts: all
user: root
tasks:
- name: simulate long running op, allow to run for 45, fire and forget
action: command /bin/sleep 15
async: 45
poll: 0
.. note::
You shouldn't "fire and forget" with operations that require
exclusive locks, such as yum transactions, if you expect to run other
commands later in the playbook against those same resources.
.. note::
Using a higher value for ``--forks`` will result in kicking off asynchronous
tasks even faster. This also increases the efficiency of polling.
Local Playbooks
```````````````
It may be useful to use a playbook locally, rather than by connecting over SSH. This can be useful
for assuring the configuration of a system by putting a playbook on a crontab. This may also be used
to run a playbook inside a OS installer, such as an Anaconda kickstart.
To run an entire playbook locally, just set the "hosts:" line to "hosts:127.0.0.1" and then run the playbook like so::
ansible-playbook playbook.yml --connection=local
Alternatively, a local connection can be used in a single playbook play, even if other plays in the playbook
use the default remote connection type::
hosts: 127.0.0.1
connection: local
Turning Off Facts
`````````````````
If you know you don't need any fact data about your hosts, and know everything about your systems centrally, you
can turn off fact gathering. This has advantages in scaling ansible in push mode with very large numbers of
systems, mainly, or if you are using Ansible on experimental platforms. In any play, just do this::
- hosts: whatever
gather_facts: False
Pull-Mode Playbooks
```````````````````
The use of playbooks in local mode (above) is made extremely powerful with the addition of `ansible-pull`.
A script for setting up ansible-pull is provided in the examples/playbooks directory of the source
checkout.
The basic idea is to use Ansible to set up a remote copy of ansible on each managed node, each set to run via
cron and update playbook source via git. This interverts the default push architecture of ansible into a pull
architecture, which has near-limitless scaling potential. The setup playbook can be tuned to change
the cron frequency, logging locations, and parameters to ansible-pull.
This is useful both for extreme scale-out as well as periodic remediation. Usage of the 'fetch' module to retrieve
logs from ansible-pull runs would be an excellent way to gather and analyze remote logs from ansible-pull.
Register Variables
``````````````````
.. versionadded:: 0.7
Often in a playbook it may be useful to store the result of a given command in a variable and access
it later. Use of the command module in this way can in many ways eliminate the need to write site specific facts, for
instance, you could test for the existance of a particular program.
The 'register' keyword decides what variable to save a result in. The resulting variables can be used in templates, action lines, or only_if statements. It looks like this (in an obviously trivial example)::
- name: test play
hosts: all
tasks:
- action: shell cat /etc/motd
register: motd_contents
- action: shell echo "motd contains the word hi"
only_if: "'${motd_contents.stdout}'.find('hi') != -1"
Rolling Updates
```````````````
.. versionadded:: 0.7
By default ansible will try to manage all of the machines referenced in a play in parallel. For a rolling updates
use case, you can define how many hosts ansible should manage at a single time by using the ''serial'' keyword::
- name: test play
hosts: webservers
serial: 3
In the above example, if we had 100 hosts, 3 hosts in the group 'webservers'
would complete the play completely before moving on to the next 3 hosts.
Delegation
``````````
.. versionadded:: 0.7
If you want to perform a task on one host with reference to other hosts, use the 'delegate_to' keyword on a task.
This is ideal for placing nodes in a load balanced pool, or removing them. It is also very useful for controlling
outage windows. Using this with the 'serial' keyword to control the number of hosts executing at one time is also
a good idea::
---
- hosts: webservers
serial: 5
tasks:
- name: take out of load balancer pool
action: command /usr/bin/take_out_of_pool $inventory_hostname
delegate_to: 127.0.0.1
- name: actual steps would go here
action: yum name=acme-web-stack state=latest
- name: add back to load balancer pool
action: command /usr/bin/add_back_to_pool $inventory_hostname
delegate_to: 127.0.0.1
Here is the same playbook as above, but using the shorthand syntax,
'local_action', for delegating to 127.0.0.1::
---
# ...
tasks:
- name: take out of load balancer pool
local_action: command /usr/bin/take_out_of_pool $inventory_hostname
# ...
- name: add back to load balancer pool
local_action: command /usr/bin/add_back_to_pool $inventory_hostname
Understanding Variable Precedence
`````````````````````````````````
You have already learned about inventory host and group variables, 'vars', and 'vars_files'.
If a variable name is defined in more than one place with the same name, priority is as follows
to determine which place sets the value of the variable.
1. Variables loaded from YAML files mentioned in 'vars_files' in a playbook.
2. 'vars' as defined in the playbook.
3. facts, whether built in or custom, or variables assigned from the 'register' keyword.
4. variables passed to parameterized task include statements.
5. Host variables from inventory.
6. Group variables from inventory, in order of least specific group to most specific.
Therefore, if you want to set a default value for something you wish to override somewhere else, the best
place to set such a default is in a group variable.
Style Points
````````````
Ansible playbooks are colorized. If you do not like this, set the ANSIBLE_NOCOLOR=1 environment variable.
Ansible playbooks also look more impressive with cowsay installed, and we encourage installing this package.
.. seealso::
:doc:`YAMLSyntax`
Learn about YAML syntax
:doc:`playbooks`
Review the basic playbook features
:doc:`bestpractices`
Various tips about playbooks in the real world
:doc:`modules`
Learn about available modules
:doc:`moduledev`
Learn how to extend Ansible by writing your own modules
:doc:`patterns`
Learn about how to select hosts
`Github examples directory <https://github.com/ansible/ansible/tree/devel/examples/playbooks>`_
Complete playbook files from the github project source
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups