Don't check in docsite static HTML, so folks will know to just edit the RST.

This commit is contained in:
Michael DeHaan 2012-10-10 18:41:02 -04:00
parent dbeb26ad6d
commit 8ae9831439
16 changed files with 0 additions and 8027 deletions

View file

@ -1,259 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>YAML Syntax &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="Playbooks" href="playbooks.html" />
<link rel="prev" title="Ansible Modules" href="modules.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">YAML Syntax</a><ul>
<li><a class="reference internal" href="#yaml-basics">YAML Basics</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="yaml-syntax">
<h1>YAML Syntax<a class="headerlink" href="#yaml-syntax" title="Permalink to this headline"></a></h1>
<p>This page provides a basic overview of correct YAML syntax, which is how Ansible
playbooks (our configuration management language) are expressed.</p>
<p>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.</p>
<p>You may also wish to read <a class="reference internal" href="playbooks.html"><em>Playbooks</em></a> at the same time to see how this
is used in practice.</p>
<div class="section" id="yaml-basics">
<h2>YAML Basics<a class="headerlink" href="#yaml-basics" title="Permalink to this headline"></a></h2>
<p>For <cite>ansible</cite>, nearly every YAML file starts with a list.
Each item in the list is a list of key/value pairs, commonly
called a &#8220;hash&#8221; or a &#8220;dictionary&#8221;. So, we need to know how
to write lists and dictionaries in YAML.</p>
<p>There&#8217;s another small quirk to YAML. All YAML files (regardless of their association with
<cite>ansible</cite> or not) should start with <tt class="docutils literal"><span class="pre">---</span></tt>. This is just a YAML
format thing that means &#8220;this is the start of a document&#8221;.</p>
<p>All members of a list are lines beginning at the same indentation level starting
with a <tt class="docutils literal"><span class="pre">-</span></tt> (dash) character:</p>
<div class="highlight-python"><pre>---
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango</pre>
</div>
<p>A dictionary is represented in a simple <tt class="docutils literal"><span class="pre">key:</span></tt> and <tt class="docutils literal"><span class="pre">value</span></tt> form:</p>
<div class="highlight-python"><pre>---
# An employee record
name: John Eckersberg
job: Developer
skill: Elite</pre>
</div>
<p>Dictionaries can also be represented in an abbreviated form if you really want to:</p>
<div class="highlight-python"><pre>---
# An employee record
{name: John Eckersberg, job: Developer, skill: Elite}</pre>
</div>
<p id="truthiness">Ansible doesn&#8217;t really use these too much, but you can also specify a
boolean value (true/false) in several forms:</p>
<div class="highlight-python"><pre>---
knows_oop: True
likes_emacs: TRUE
uses_cvs: false</pre>
</div>
<p>Let&#8217;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:</p>
<div class="highlight-python"><pre>---
# An employee record
name: John Eckersberg
job: Developer
skill: Elite
employed: True
foods:
- Apple
- Orange
- Strawberry
- Mango
languages:
ruby: Elite
python: Elite
dotnet: Lame</pre>
</div>
<p>That&#8217;s all you really need to know about YAML to get started writing
<cite>Ansible</cite> playbooks.</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="playbooks.html"><em>Playbooks</em></a></dt>
<dd>Learn what playbooks can do and how to write/run them.</dd>
<dt><a class="reference external" href="http://yamllint.com/">YAMLLint</a></dt>
<dd>YAML Lint (online) helps you debug YAML syntax if you are having problems</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/tree/devel/examples/playbooks">Github examples directory</a></dt>
<dd>Complete playbook files from the github project source</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,474 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>API &amp; Integrations &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="Module Development" href="moduledev.html" />
<link rel="prev" title="Best Practices" href="bestpractices.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">API &amp; Integrations</a><ul>
<li><a class="reference internal" href="#python-api">Python API</a><ul>
<li><a class="reference internal" href="#detailed-api-example">Detailed API Example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#plugins-repository">Plugins Repository</a></li>
<li><a class="reference internal" href="#external-inventory-scripts">External Inventory Scripts</a><ul>
<li><a class="reference internal" href="#script-conventions">Script Conventions</a></li>
<li><a class="reference internal" href="#example-the-cobbler-external-inventory-script">Example: The Cobbler External Inventory Script</a></li>
<li><a class="reference internal" href="#example-aws-ec2-external-inventory-script">Example: AWS EC2 External Inventory Script</a></li>
<li><a class="reference internal" href="#example-openstack">Example: OpenStack</a></li>
</ul>
</li>
<li><a class="reference internal" href="#callback-plugins">Callback Plugins</a></li>
<li><a class="reference internal" href="#connection-type-plugins">Connection Type Plugins</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="api-integrations">
<h1><a class="toc-backref" href="#table-of-contents">API &amp; Integrations</a><a class="headerlink" href="#api-integrations" title="Permalink to this headline"></a></h1>
<p>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.</p>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first"><cite>Table of contents</cite></p>
<ul class="simple">
<li><a class="reference internal" href="#api-integrations" id="id2">API &amp; Integrations</a><ul>
<li><a class="reference internal" href="#python-api" id="id3">Python API</a></li>
<li><a class="reference internal" href="#plugins-repository" id="id4">Plugins Repository</a></li>
<li><a class="reference internal" href="#external-inventory-scripts" id="id5">External Inventory Scripts</a></li>
<li><a class="reference internal" href="#callback-plugins" id="id6">Callback Plugins</a></li>
<li><a class="reference internal" href="#connection-type-plugins" id="id7">Connection Type Plugins</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="python-api">
<h2><a class="toc-backref" href="#table-of-contents">Python API</a><a class="headerlink" href="#python-api" title="Permalink to this headline"></a></h2>
<p>The Python API is very powerful, and is how the ansible CLI and ansible-playbook
are implemented.</p>
<p>It&#8217;s pretty simple:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">ansible.runner</span>
<span class="n">runner</span> <span class="o">=</span> <span class="n">ansible</span><span class="o">.</span><span class="n">runner</span><span class="o">.</span><span class="n">Runner</span><span class="p">(</span>
<span class="n">module_name</span><span class="o">=</span><span class="s">&#39;ping&#39;</span><span class="p">,</span>
<span class="n">module_args</span><span class="o">=</span><span class="s">&#39;&#39;</span><span class="p">,</span>
<span class="n">pattern</span><span class="o">=</span><span class="s">&#39;web*&#39;</span><span class="p">,</span>
<span class="n">forks</span><span class="o">=</span><span class="mi">10</span>
<span class="p">)</span>
<span class="n">datastructure</span> <span class="o">=</span> <span class="n">runner</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>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 &#8216;ansible-modules&#8217; documentation.:</p>
<div class="highlight-python"><pre>{
"dark" : {
"web1.example.com" : "failure message"
}
"contacted" : {
"web2.example.com" : 1
}
}</pre>
</div>
<p>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.</p>
<div class="section" id="detailed-api-example">
<h3>Detailed API Example<a class="headerlink" href="#detailed-api-example" title="Permalink to this headline"></a></h3>
<p>The following script prints out the uptime information for all hosts:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/python</span>
<span class="kn">import</span> <span class="nn">ansible.runner</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="c"># construct the ansible runner and execute on all hosts</span>
<span class="n">results</span> <span class="o">=</span> <span class="n">ansible</span><span class="o">.</span><span class="n">runner</span><span class="o">.</span><span class="n">Runner</span><span class="p">(</span>
<span class="n">pattern</span><span class="o">=</span><span class="s">&#39;*&#39;</span><span class="p">,</span> <span class="n">forks</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span>
<span class="n">module_name</span><span class="o">=</span><span class="s">&#39;command&#39;</span><span class="p">,</span> <span class="n">module_args</span><span class="o">=</span><span class="s">&#39;/usr/bin/uptime&#39;</span><span class="p">,</span>
<span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="k">if</span> <span class="n">results</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">print</span> <span class="s">&quot;No hosts found&quot;</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="s">&quot;UP ***********&quot;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">hostname</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span> <span class="ow">in</span> <span class="n">results</span><span class="p">[</span><span class="s">&#39;contacted&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="s">&#39;failed&#39;</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
<span class="k">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s"> &gt;&gt;&gt; </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">hostname</span><span class="p">,</span> <span class="n">result</span><span class="p">[</span><span class="s">&#39;stdout&#39;</span><span class="p">])</span>
<span class="k">print</span> <span class="s">&quot;FAILED *******&quot;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">hostname</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span> <span class="ow">in</span> <span class="n">results</span><span class="p">[</span><span class="s">&#39;contacted&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="s">&#39;failed&#39;</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
<span class="k">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s"> &gt;&gt;&gt; </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">hostname</span><span class="p">,</span> <span class="n">result</span><span class="p">[</span><span class="s">&#39;msg&#39;</span><span class="p">])</span>
<span class="k">print</span> <span class="s">&quot;DOWN *********&quot;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">hostname</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span> <span class="ow">in</span> <span class="n">results</span><span class="p">[</span><span class="s">&#39;dark&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s"> &gt;&gt;&gt; </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">hostname</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
</pre></div>
</div>
<p>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 <tt class="docutils literal"><span class="pre">ansible</span></tt> and <tt class="docutils literal"><span class="pre">ansible-playbook</span></tt>.</p>
</div>
</div>
<div class="section" id="plugins-repository">
<h2><a class="toc-backref" href="#table-of-contents">Plugins Repository</a><a class="headerlink" href="#plugins-repository" title="Permalink to this headline"></a></h2>
<p>The remainder of features in the API docs have components available in <a class="reference external" href="https://github.com/ansible/ansible/blob/devel/plugins">ansible-plugins</a>. Send us a github pull request if you develop any interesting features.</p>
</div>
<div class="section" id="external-inventory-scripts">
<h2><a class="toc-backref" href="#table-of-contents">External Inventory Scripts</a><a class="headerlink" href="#external-inventory-scripts" title="Permalink to this headline"></a></h2>
<p>Often a user of a configuration management system will want to keep inventory
in a different system. Frequent examples include LDAP, <a class="reference external" href="http://cobbler.github.com">Cobbler</a>,
or a piece of expensive enterprisey CMDB software. Ansible easily supports all
of these options via an external inventory system. The plugins directory contains some of these already &#8211; including options for EC2/Eucalyptus and OpenStack, which will be detailed below.</p>
<p>It&#8217;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 &#8216;external nodes&#8217;, with the slight difference that it also defines which hosts are managed.</p>
<div class="section" id="script-conventions">
<h3>Script Conventions<a class="headerlink" href="#script-conventions" title="Permalink to this headline"></a></h3>
<p>When the external node script is called with the single argument &#8216;&#8211;list&#8217;, 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:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">&#39;databases&#39;</span> <span class="p">:</span> <span class="p">[</span> <span class="s">&#39;host1.example.com&#39;</span><span class="p">,</span> <span class="s">&#39;host2.example.com&#39;</span> <span class="p">],</span>
<span class="s">&#39;webservers&#39;</span> <span class="p">:</span> <span class="p">[</span> <span class="s">&#39;host2.example.com&#39;</span><span class="p">,</span> <span class="s">&#39;host3.example.com&#39;</span> <span class="p">],</span>
<span class="s">&#39;atlanta&#39;</span> <span class="p">:</span> <span class="p">[</span> <span class="s">&#39;host1.example.com&#39;</span><span class="p">,</span> <span class="s">&#39;host4.example.com&#39;</span><span class="p">,</span> <span class="s">&#39;host5.example.com&#39;</span> <span class="p">]</span>
<span class="p">}</span>
</pre></div>
</div>
<p>When called with the arguments &#8216;&#8211;host &lt;hostname&gt;&#8217; (where &lt;hostname&gt; 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:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span>
<span class="s">&#39;favcolor&#39;</span> <span class="p">:</span> <span class="s">&#39;red&#39;</span><span class="p">,</span>
<span class="s">&#39;ntpserver&#39;</span> <span class="p">:</span> <span class="s">&#39;wolf.example.com&#39;</span><span class="p">,</span>
<span class="s">&#39;monitoring&#39;</span> <span class="p">:</span> <span class="s">&#39;pack.example.com&#39;</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="example-the-cobbler-external-inventory-script">
<h3>Example: The Cobbler External Inventory Script<a class="headerlink" href="#example-the-cobbler-external-inventory-script" title="Permalink to this headline"></a></h3>
<p>It is expected that many Ansible users will also be <a class="reference external" href="http://cobbler.github.com">Cobbler</a> 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 &#8216;lightweight CMDB&#8217; by some admins. This particular script will communicate with Cobbler
using Cobbler&#8217;s XMLRPC API.</p>
<p>To tie Ansible&#8217;s inventory to Cobbler (optional), copy <a class="reference external" href="https://raw.github.com/ansible/ansible/devel/plugins/inventory/cobbler.py">this script</a> to /etc/ansible/hosts and <cite>chmod +x</cite> the file. cobblerd will now need
to be running when you are using Ansible.</p>
<p>Test the file by running <cite>./etc/ansible/hosts</cite> directly. You should see some JSON data output, but it may not have
anything in it just yet.</p>
<p>Let&#8217;s explore what this does. In cobbler, assume a scenario somewhat like the following:</p>
<div class="highlight-python"><pre>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"</pre>
</div>
<p>In the example above, the system &#8216;foo.example.com&#8217; will be addressable by ansible directly, but will also be addressable when using the group names &#8216;webserver&#8217; or &#8216;atlanta&#8217;. Since Ansible uses SSH, we&#8217;ll try to contract system foo over &#8216;foo.example.com&#8217;, only, never just &#8216;foo&#8217;. Similarly, if you try &#8220;ansible foo&#8221; it wouldn&#8217;t find the system... but &#8220;ansible &#8216;foo*&#8217;&#8221; would, because the system DNS name starts with &#8216;foo&#8217;.</p>
<p>The script doesn&#8217;t just provide host and group info. In addition, as a bonus, when the &#8216;setup&#8217; module is run (which happens automatically when using playbooks), the variables &#8216;a&#8217;, &#8216;b&#8217;, and &#8216;c&#8217; will all be auto-populated in the templates:</p>
<div class="highlight-python"><pre># file: /srv/motd.j2
Welcome, I am templated with a value of a={{ a }}, b={{ b }}, and c={{ c }}</pre>
</div>
<p>Which could be executed just like this:</p>
<div class="highlight-python"><pre>ansible webserver -m setup
ansible webserver -m template -a "src=/tmp/motd.j2 dest=/etc/motd"</pre>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">The name &#8216;webserver&#8217; 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.</p>
</div>
<p>So, with the template above (motd.j2), this would result in the following data being written to /etc/motd for system &#8216;foo&#8217;:</p>
<div class="highlight-python"><pre>Welcome, I am templated with a value of a=2, b=3, and c=4</pre>
</div>
<p>And on system &#8216;bar&#8217; (bar.example.com):</p>
<div class="highlight-python"><pre>Welcome, I am templated with a value of a=2, b=3, and c=5</pre>
</div>
<p>And technically, though there is no major good reason to do it, this also works too:</p>
<div class="highlight-python"><pre>ansible webserver -m shell -a "echo {{ a }}"</pre>
</div>
<p>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?</p>
<p>So that&#8217;s the Cobbler integration support &#8211; 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.</p>
</div>
<div class="section" id="example-aws-ec2-external-inventory-script">
<h3>Example: AWS EC2 External Inventory Script<a class="headerlink" href="#example-aws-ec2-external-inventory-script" title="Permalink to this headline"></a></h3>
<p>If you use Amazon Web Services EC2, maintaining an inventory file might not be the best approach. For this reason, you can use the <a class="reference external" href="https://raw.github.com/ansible/ansible/devel/plugins/inventory/ec2.py">EC2 external inventory</a> script.</p>
<p>You can use this script in one of two ways. The easiest is to use Ansible&#8217;s <tt class="docutils literal"><span class="pre">-i</span></tt> command line option and specify the path to the script.</p>
<blockquote>
<div>ansible -i ec2.py -u ubuntu us-east-1d -m ping</div></blockquote>
<p>The second option is to copy the script to <cite>/etc/ansible/hosts</cite> and <cite>chmod +x</cite> it. You will also need to copy the <tt class="docutils literal"><span class="pre">ec2.ini</span></tt> file to <cite>/etc/ansible/ec2.ini</cite>. Then you can run ansible as you would normally.</p>
<p>To successfully make an API call to AWS, you will need to configure Boto (the Python interface to AWS). There are a <a class="reference external" href="http://docs.pythonboto.org/en/latest/boto_config_tut.html">variety of methods</a> available, but the simplest is just to export two environment variables:</p>
<blockquote>
<div>export AWS_ACCESS_KEY_ID=&#8217;AK123&#8217;
export AWS_SECRET_ACCESS_KEY=&#8217;abc123&#8217;</div></blockquote>
<p>You can test the script by itself to make sure your config is correct</p>
<blockquote>
<div>cd examples/scripts
./ec2_external_inventory.py &#8211;list</div></blockquote>
<p>After a few moments, you should see your entire EC2 inventory across all regions in JSON.</p>
<p>Since each region requires its own API call, if you are only using a small set of regions, feel free to edit <tt class="docutils literal"><span class="pre">ec2.ini</span></tt> and list only the regions you are interested in. There are other config options in <tt class="docutils literal"><span class="pre">ec2.ini</span></tt> including cache control, and destination variables.</p>
<p>At their heart, inventory files are simply a mapping from some name to a destination address. The default <tt class="docutils literal"><span class="pre">ec2.ini</span></tt> 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 <tt class="docutils literal"><span class="pre">destination_variable</span></tt> in <tt class="docutils literal"><span class="pre">ec2.ini</span></tt> 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, <cite>vpc_destination_variable</cite> in <tt class="docutils literal"><span class="pre">ec2.ini</span></tt> provides a means of using which ever <a class="reference external" href="http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance">boto.ec2.instance variable</a> makes the most sense for your use case.</p>
<p>The EC2 external inventory provides mappings to instances from several groups:</p>
<dl class="docutils">
<dt>Instance ID</dt>
<dd>These are groups of one since instance IDs are unique.
e.g.
<tt class="docutils literal"><span class="pre">i-00112233</span></tt>
<tt class="docutils literal"><span class="pre">i-a1b1c1d1</span></tt></dd>
<dt>Region</dt>
<dd>A group of all instances in an AWS region.
e.g.
<tt class="docutils literal"><span class="pre">us-east-1</span></tt>
<tt class="docutils literal"><span class="pre">us-west-2</span></tt></dd>
<dt>Availability Zone</dt>
<dd>A group of all instances in an availability zone.
e.g.
<tt class="docutils literal"><span class="pre">us-east-1a</span></tt>
<tt class="docutils literal"><span class="pre">us-east-1b</span></tt></dd>
<dt>Security Group</dt>
<dd>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 <tt class="docutils literal"><span class="pre">security_group_</span></tt>
e.g.
<tt class="docutils literal"><span class="pre">security_group_default</span></tt>
<tt class="docutils literal"><span class="pre">security_group_webservers</span></tt>
<tt class="docutils literal"><span class="pre">security_group_Pete_s_Fancy_Group</span></tt></dd>
<dt>Tags</dt>
<dd>Each instance can have a variety of key/value pairs associated with it called Tags. The most common tag key is &#8216;Name&#8217;, though anything is possible. Each key/value pair is its own group of instances, again with special characters converted to underscores, in the format <tt class="docutils literal"><span class="pre">tag_KEY_VALUE</span></tt>
e.g.
<tt class="docutils literal"><span class="pre">tag_Name_Web</span></tt>
<tt class="docutils literal"><span class="pre">tag_Name_redis-master-001</span></tt>
<tt class="docutils literal"><span class="pre">tag_aws_cloudformation_logical-id_WebServerGroup</span></tt></dd>
</dl>
<p>When the Ansible is interacting with a specific server, the EC2 inventory script is called again with the <tt class="docutils literal"><span class="pre">--host</span> <span class="pre">HOST</span></tt> 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 <tt class="docutils literal"><span class="pre">ec2_</span></tt>. Here are some of the variables available:</p>
<ul class="simple">
<li>ec2_architecture</li>
<li>ec2_description</li>
<li>ec2_dns_name</li>
<li>ec2_id</li>
<li>ec2_image_id</li>
<li>ec2_instance_type</li>
<li>ec2_ip_address</li>
<li>ec2_kernel</li>
<li>ec2_key_name</li>
<li>ec2_launch_time</li>
<li>ec2_monitored</li>
<li>ec2_ownerId</li>
<li>ec2_placement</li>
<li>ec2_platform</li>
<li>ec2_previous_state</li>
<li>ec2_private_dns_name</li>
<li>ec2_private_ip_address</li>
<li>ec2_public_dns_name</li>
<li>ec2_ramdisk</li>
<li>ec2_region</li>
<li>ec2_root_device_name</li>
<li>ec2_root_device_type</li>
<li>ec2_security_group_ids</li>
<li>ec2_security_group_names</li>
<li>ec2_spot_instance_request_id</li>
<li>ec2_state</li>
<li>ec2_state_code</li>
<li>ec2_state_reason</li>
<li>ec2_status</li>
<li>ec2_subnet_id</li>
<li>ec2_tag_Name</li>
<li>ec2_tenancy</li>
<li>ec2_virtualization_type</li>
<li>ec2_vpc_id</li>
</ul>
<p>Both <tt class="docutils literal"><span class="pre">ec2_security_group_ids</span></tt> and <tt class="docutils literal"><span class="pre">ec2_security_group_names</span></tt> are comma-separated lists of all security groups. Each EC2 tag is a variable in the format <tt class="docutils literal"><span class="pre">ec2_tag_KEY</span></tt>.</p>
<p>To see the complete list of variables available for an instance, run the script by itself:</p>
<div class="highlight-python"><pre>cd examples/scripts
./ec2_external_inventory.py --host ec2-12-12-12-12.compute-1.amazonaws.com</pre>
</div>
</div>
<div class="section" id="example-openstack">
<h3>Example: OpenStack<a class="headerlink" href="#example-openstack" title="Permalink to this headline"></a></h3>
<p>Though not detailed here in as much depth as the EC2 module, there&#8217;s also a OpenStack Nova external inventory source in the plugins directory. See the inline comments in the module source.</p>
</div>
</div>
<div class="section" id="callback-plugins">
<h2><a class="toc-backref" href="#table-of-contents">Callback Plugins</a><a class="headerlink" href="#callback-plugins" title="Permalink to this headline"></a></h2>
<p>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 plugins directory.</p>
</div>
<div class="section" id="connection-type-plugins">
<h2><a class="toc-backref" href="#table-of-contents">Connection Type Plugins</a><a class="headerlink" href="#connection-type-plugins" title="Permalink to this headline"></a></h2>
<p>By default, ansible ships with a &#8216;paramiko&#8217; SSH, native ssh (just called &#8216;ssh&#8217;), and &#8216;local&#8217; 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 &#8216;getting started&#8217; section. Should you want to extend Ansible to support other transports (SNMP? Message bus?
Carrier Pigeon?) it&#8217;s as simple as copying the format of one of the existing modules and dropping it into the connection plugins
directory.</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="modules.html"><em>Ansible Modules</em></a></dt>
<dd>List of built-in modules</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,318 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Best Practices &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="API &amp; Integrations" href="api.html" />
<link rel="prev" title="Advanced Playbooks" href="playbooks2.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Best Practices</a><ul>
<li><a class="reference internal" href="#always-mention-state">Always Mention State</a></li>
<li><a class="reference internal" href="#group-by-roles">Group By Roles</a></li>
<li><a class="reference internal" href="#directory-organization">Directory Organization</a></li>
<li><a class="reference internal" href="#bundling-ansible-modules-with-playbooks">Bundling Ansible Modules With Playbooks</a></li>
<li><a class="reference internal" href="#miscellaneous-tips">Miscellaneous Tips</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="best-practices">
<h1><a class="toc-backref" href="#contents">Best Practices</a><a class="headerlink" href="#best-practices" title="Permalink to this headline"></a></h1>
<p>Here are some tips for making the most of Ansible.</p>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#best-practices" id="id1">Best Practices</a><ul>
<li><a class="reference internal" href="#always-mention-state" id="id2">Always Mention State</a></li>
<li><a class="reference internal" href="#group-by-roles" id="id3">Group By Roles</a></li>
<li><a class="reference internal" href="#directory-organization" id="id4">Directory Organization</a></li>
<li><a class="reference internal" href="#bundling-ansible-modules-with-playbooks" id="id5">Bundling Ansible Modules With Playbooks</a></li>
<li><a class="reference internal" href="#miscellaneous-tips" id="id6">Miscellaneous Tips</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="always-mention-state">
<h2><a class="toc-backref" href="#contents">Always Mention State</a><a class="headerlink" href="#always-mention-state" title="Permalink to this headline"></a></h2>
<p>The &#8216;state&#8217; parameter is optional to a lot of modules. Whether
&#8216;state=present&#8217; or &#8216;state=absent&#8217;, it&#8217;s always best to leave that
parameter in your playbooks to make it clear, especially as some
modules support additional states.</p>
</div>
<div class="section" id="group-by-roles">
<h2><a class="toc-backref" href="#contents">Group By Roles</a><a class="headerlink" href="#group-by-roles" title="Permalink to this headline"></a></h2>
<p>A system can be in multiple groups. See <a class="reference internal" href="patterns.html"><em>Inventory &amp; Patterns</em></a>. Having groups named after things like
<em>webservers</em> and <em>dbservers</em> is repeated in the examples because it&#8217;s a very powerful concept.</p>
<p>This allows playbooks to target machines based on role, as well as to assign role specific variables
using the group variable system.</p>
</div>
<div class="section" id="directory-organization">
<h2><a class="toc-backref" href="#contents">Directory Organization</a><a class="headerlink" href="#directory-organization" title="Permalink to this headline"></a></h2>
<p>Playbooks should be organized like this:</p>
<div class="highlight-python"><pre># 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</pre>
</div>
<p>Any directories or files not needed can be omitted. Not all modules
may require &#8216;vars&#8217; or &#8216;files&#8217; sections, though most will require
&#8216;handlers&#8217;, &#8216;tasks&#8217;, and &#8216;templates&#8217;. To review what each of
these sections do, see <a class="reference internal" href="playbooks.html"><em>Playbooks</em></a> and <a class="reference internal" href="playbooks2.html"><em>Advanced Playbooks</em></a>.</p>
<p>The acme/setup.yml playbook would be as simple as:</p>
<div class="highlight-python"><pre>---
- hosts: webservers
user: root
vars_files:
- ../global_vars.yml
- vars/main.yml
tasks:
- include: tasks/setup.yml
handlers:
- include: handlers/main.yml</pre>
</div>
<p>The tasks are individually broken out in &#8216;acme/tasks/setup.yml&#8217;, and handlers, which are common to all task files,
are contained in &#8216;acme/handlers/main.yml&#8217;. As a reminder, handlers are mostly just used to notify services to restart
when things change, and these are described in <a class="reference internal" href="playbooks.html"><em>Playbooks</em></a>.</p>
<p>Including more than one setup file or more than one handlers file is of course legal.</p>
</div>
<div class="section" id="bundling-ansible-modules-with-playbooks">
<h2><a class="toc-backref" href="#contents">Bundling Ansible Modules With Playbooks</a><a class="headerlink" href="#bundling-ansible-modules-with-playbooks" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.5.</span></p>
<p>If a playbook has a &#8221;./library&#8221; directory relative to it&#8217;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.</p>
</div>
<div class="section" id="miscellaneous-tips">
<h2><a class="toc-backref" href="#contents">Miscellaneous Tips</a><a class="headerlink" href="#miscellaneous-tips" title="Permalink to this headline"></a></h2>
<p>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 &#8216;vars&#8217;,
&#8216;vars_files&#8217;, &#8216;vars_prompt&#8217; and &#8216;&#8211;extra-vars&#8217; all at once,
while also using an external inventory file.</p>
<p>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 &#8216;#&#8217;. It is also useful to comment
at the top of each file the purpose of the individual file and the
author, including email address.</p>
<p>It is possible to leave off the &#8216;name&#8217; for a given task, though it
is recommended to provide a descriptive comment about why something is
being done instead.</p>
<p>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.</p>
<p>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 &#8216;yum&#8217; and &#8216;apt&#8217; module. Yum and apt have different
capabilities, and we don&#8217;t want to code for the least common
denominator.</p>
<p>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.</p>
<p>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.</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="YAMLSyntax.html"><em>YAML Syntax</em></a></dt>
<dd>Learn about YAML syntax</dd>
<dt><a class="reference internal" href="playbooks.html"><em>Playbooks</em></a></dt>
<dd>Review the basic playbook features</dd>
<dt><a class="reference internal" href="modules.html"><em>Ansible Modules</em></a></dt>
<dd>Learn about available modules</dd>
<dt><a class="reference internal" href="moduledev.html"><em>Module Development</em></a></dt>
<dd>Learn how to extend Ansible by writing your own modules</dd>
<dt><a class="reference internal" href="patterns.html"><em>Inventory &amp; Patterns</em></a></dt>
<dd>Learn about how to select hosts</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/tree/devel/examples/playbooks">Github examples directory</a></dt>
<dd>Complete playbook files from the github project source</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,437 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Command Line Examples And Next Steps &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="Ansible Modules" href="modules.html" />
<link rel="prev" title="Inventory &amp; Patterns" href="patterns.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Command Line Examples And Next Steps</a><ul>
<li><a class="reference internal" href="#parallelism-and-shell-commands">Parallelism and Shell Commands</a></li>
<li><a class="reference internal" href="#file-transfer">File Transfer</a></li>
<li><a class="reference internal" href="#managing-packages">Managing Packages</a></li>
<li><a class="reference internal" href="#users-and-groups">Users and Groups</a></li>
<li><a class="reference internal" href="#deploying-from-source-control">Deploying From Source Control</a></li>
<li><a class="reference internal" href="#managing-services">Managing Services</a></li>
<li><a class="reference internal" href="#time-limited-background-operations">Time Limited Background Operations</a></li>
<li><a class="reference internal" href="#limiting-selected-hosts">Limiting Selected Hosts</a></li>
<li><a class="reference internal" href="#configuration-defaults">Configuration &amp; Defaults</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="command-line-examples-and-next-steps">
<h1><a class="toc-backref" href="#contents">Command Line Examples And Next Steps</a><a class="headerlink" href="#command-line-examples-and-next-steps" title="Permalink to this headline"></a></h1>
<p>The following examples show how to use <cite>/usr/bin/ansible</cite> for running
ad hoc tasks. Start here.</p>
<p>For configuration management and deployments, you&#8217;ll want to pick up on
using <cite>/usr/bin/ansible-playbook</cite> &#8211; the concepts port over directly.
(See <a class="reference internal" href="playbooks.html"><em>Playbooks</em></a> for more information about those)</p>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#command-line-examples-and-next-steps" id="id1">Command Line Examples And Next Steps</a><ul>
<li><a class="reference internal" href="#parallelism-and-shell-commands" id="id2">Parallelism and Shell Commands</a></li>
<li><a class="reference internal" href="#file-transfer" id="id3">File Transfer</a></li>
<li><a class="reference internal" href="#managing-packages" id="id4">Managing Packages</a></li>
<li><a class="reference internal" href="#users-and-groups" id="id5">Users and Groups</a></li>
<li><a class="reference internal" href="#deploying-from-source-control" id="id6">Deploying From Source Control</a></li>
<li><a class="reference internal" href="#managing-services" id="id7">Managing Services</a></li>
<li><a class="reference internal" href="#time-limited-background-operations" id="id8">Time Limited Background Operations</a></li>
<li><a class="reference internal" href="#limiting-selected-hosts" id="id9">Limiting Selected Hosts</a></li>
<li><a class="reference internal" href="#configuration-defaults" id="id10">Configuration &amp; Defaults</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="parallelism-and-shell-commands">
<h2><a class="toc-backref" href="#contents">Parallelism and Shell Commands</a><a class="headerlink" href="#parallelism-and-shell-commands" title="Permalink to this headline"></a></h2>
<p>Let&#8217;s use ansible&#8217;s command line tool to reboot all web servers in Atlanta, 10 at a time. First, let&#8217;s
set up SSH-agent so it can remember our credentials:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ssh-agent bash
<span class="nv">$ </span>ssh-add ~/.ssh/id_rsa.pub
</pre></div>
</div>
<p>If you don&#8217;t want to use ssh-agent and want to instead SSH with a
password instead of keys, you can with <tt class="docutils literal"><span class="pre">--ask-pass</span></tt> (<tt class="docutils literal"><span class="pre">-k</span></tt>), but
it&#8217;s much better to just use ssh-agent.</p>
<p>Now to run the command on all servers in a group, in this case,
<em>atlanta</em>, in 10 parallel forks:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible atlanta -a <span class="s2">&quot;/sbin/reboot&quot;</span> -f 10
</pre></div>
</div>
<p>In 0.7 and later, this will default to running from your user account. If you do not like this
behavior, pass in &#8220;-u username&#8221;. (In 0.6 and before, it defaulted to root. Most folks prefered
defaulting to the current user, so we changed it).</p>
<p>If you want to run commands as a different user, it looks like this:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible atlanta -a <span class="s2">&quot;/usr/bin/foo&quot;</span> -u username
</pre></div>
</div>
<p>If you want to run commands through sudo:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible atlanta -a <span class="s2">&quot;/usr/bin/foo&quot;</span> -u username --sudo <span class="o">[</span>--ask-sudo-pass<span class="o">]</span>
</pre></div>
</div>
<p>Use <tt class="docutils literal"><span class="pre">--ask-sudo-pass</span></tt> (<tt class="docutils literal"><span class="pre">-K</span></tt>) 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&#8217;s not
required.</p>
<p>It is also possible to sudo to a user other than root using
<tt class="docutils literal"><span class="pre">--sudo-user</span></tt> (<tt class="docutils literal"><span class="pre">-U</span></tt>):</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible atlanta -a <span class="s2">&quot;/usr/bin/foo&quot;</span> -u username -U otheruser <span class="o">[</span>--ask-sudo-pass<span class="o">]</span>
</pre></div>
</div>
<p>Ok, so those are basics. If you didn&#8217;t read about patterns and groups yet, go back and read <a class="reference internal" href="patterns.html"><em>Inventory &amp; Patterns</em></a>.</p>
<p>The <tt class="docutils literal"><span class="pre">-f</span> <span class="pre">10</span></tt> in the above specifies the usage of 10 simultaneous
processes. Normally commands also take a <tt class="docutils literal"><span class="pre">-m</span></tt> for module name, but
the default module name is &#8216;command&#8217;, so we didn&#8217;t need to
specify that all of the time. We&#8217;ll use <tt class="docutils literal"><span class="pre">-m</span></tt> in later examples to
run some other <a class="reference internal" href="modules.html"><em>Ansible Modules</em></a>.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">The <a class="reference internal" href="modules.html#command"><em>command</em></a> 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 <a class="reference internal" href="modules.html"><em>Ansible Modules</em></a>
page.</p>
</div>
<p>Using the <a class="reference internal" href="modules.html#shell"><em>shell</em></a> module looks like this:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible raleigh -m shell -a <span class="s1">&#39;echo $TERM&#39;</span>
</pre></div>
</div>
<p>When running any command with the ansible <em>ad hoc</em> CLI (as opposed to
<a class="reference internal" href="playbooks.html"><em>Playbooks</em></a>), pay particular attention to shell quoting rules, so
the shell doesn&#8217;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.</p>
<p>So far we&#8217;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 &#8216;idempotence&#8217;, and is a core design goal of ansible.
However, we also recognize that running <em>ad hoc</em> commands is equally important, so Ansible easily supports both.</p>
</div>
<div class="section" id="file-transfer">
<h2><a class="toc-backref" href="#contents">File Transfer</a><a class="headerlink" href="#file-transfer" title="Permalink to this headline"></a></h2>
<p>Here&#8217;s another use case for the <cite>/usr/bin/ansible</cite> command line. Ansible can SCP lots of files to multiple machines in parallel.</p>
<p>To transfer a file directly to many different servers:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible atlanta -m copy -a <span class="s2">&quot;src=/etc/hosts dest=/tmp/hosts&quot;</span>
</pre></div>
</div>
<p>If you use playbooks, you can also take advantage of the <tt class="docutils literal"><span class="pre">template</span></tt> module,
which takes this another step further. (See module and playbook documentation).</p>
<p>The <tt class="docutils literal"><span class="pre">file</span></tt> module allows changing ownership and permissions on files. These
same options can be passed directly to the <tt class="docutils literal"><span class="pre">copy</span></tt> module as well:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m file -a <span class="s2">&quot;dest=/srv/foo/a.txt mode=600&quot;</span>
<span class="nv">$ </span>ansible webservers -m file -a <span class="s2">&quot;dest=/srv/foo/b.txt mode=600 owner=mdehaan group=mdehaan&quot;</span>
</pre></div>
</div>
<p>The <tt class="docutils literal"><span class="pre">file</span></tt> module can also create directories, similar to <tt class="docutils literal"><span class="pre">mkdir</span> <span class="pre">-p</span></tt>:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m file -a <span class="s2">&quot;dest=/path/to/c mode=644 owner=mdehaan group=mdehaan state=directory&quot;</span>
</pre></div>
</div>
<p>As well as delete directories (recursively) and delete files:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m file -a <span class="s2">&quot;dest=/path/to/c state=absent&quot;</span>
</pre></div>
</div>
</div>
<div class="section" id="managing-packages">
<h2><a class="toc-backref" href="#contents">Managing Packages</a><a class="headerlink" href="#managing-packages" title="Permalink to this headline"></a></h2>
<p>There are modules available for yum and apt. Here are some examples
with yum.</p>
<p>Ensure a package is installed, but don&#8217;t update it:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m yum -a <span class="s2">&quot;pkg=acme state=installed&quot;</span>
</pre></div>
</div>
<p>Ensure a package is installed to a specific version:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m yum -a <span class="s2">&quot;pkg=acme-1.5 state=installed&quot;</span>
</pre></div>
</div>
<p>Ensure a package is at the latest version:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m yum -a <span class="s2">&quot;pkg=acme state=latest&quot;</span>
</pre></div>
</div>
<p>Ensure a package is not installed:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m yum -a <span class="s2">&quot;pkg=acme state=removed&quot;</span>
</pre></div>
</div>
<p>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.</p>
</div>
<div class="section" id="users-and-groups">
<h2><a class="toc-backref" href="#contents">Users and Groups</a><a class="headerlink" href="#users-and-groups" title="Permalink to this headline"></a></h2>
<p>The &#8216;user&#8217; module allows easy creation and manipulation of
existing user accounts, as well as removal of user accounts that may
exist:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible all -m user -a <span class="s2">&quot;name=foo password=&lt;crypted password here&gt;&quot;</span>
<span class="nv">$ </span>ansible all -m user -a <span class="s2">&quot;name=foo state=absent&quot;</span>
</pre></div>
</div>
<p>See the <a class="reference internal" href="modules.html"><em>Ansible Modules</em></a> section for details on all of the available options, including
how to manipulate groups and group membership.</p>
</div>
<div class="section" id="deploying-from-source-control">
<h2><a class="toc-backref" href="#contents">Deploying From Source Control</a><a class="headerlink" href="#deploying-from-source-control" title="Permalink to this headline"></a></h2>
<p>Deploy your webapp straight from git:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m git -a <span class="s2">&quot;repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD&quot;</span>
</pre></div>
</div>
<p>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.</p>
</div>
<div class="section" id="managing-services">
<h2><a class="toc-backref" href="#contents">Managing Services</a><a class="headerlink" href="#managing-services" title="Permalink to this headline"></a></h2>
<p>Ensure a service is started on all webservers:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m service -a <span class="s2">&quot;name=httpd state=started&quot;</span>
</pre></div>
</div>
<p>Alternatively, restart a service on all webservers:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m service -a <span class="s2">&quot;name=httpd state=restarted&quot;</span>
</pre></div>
</div>
<p>Ensure a service is stopped:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers -m service -a <span class="s2">&quot;name=httpd state=stopped&quot;</span>
</pre></div>
</div>
</div>
<div class="section" id="time-limited-background-operations">
<h2><a class="toc-backref" href="#contents">Time Limited Background Operations</a><a class="headerlink" href="#time-limited-background-operations" title="Permalink to this headline"></a></h2>
<p>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&#8217;t lose track. If you kick hosts and don&#8217;t want
to poll, it looks like this:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible all -B 3600 -a <span class="s2">&quot;/usr/bin/long_running_operation --do-stuff&quot;</span>
</pre></div>
</div>
<p>If you do decide you want to check on the job status later, you can:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible all -m async_status -a <span class="s2">&quot;jid=123456789&quot;</span>
</pre></div>
</div>
<p>Polling is built-in and looks like this:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible all -B 1800 -P 60 -a <span class="s2">&quot;/usr/bin/long_running_operation --do-stuff&quot;</span>
</pre></div>
</div>
<p>The above example says &#8220;run for 30 minutes max (<tt class="docutils literal"><span class="pre">-B</span></tt>: 30*60=1800),
poll for status (<tt class="docutils literal"><span class="pre">-P</span></tt>) every 60 seconds&#8221;.</p>
<p>Poll mode is smart so all jobs will be started before polling will begin on any machine.
Be sure to use a high enough <tt class="docutils literal"><span class="pre">--forks</span></tt> value if you want to get all of your jobs started
very quickly. After the time limit (in seconds) runs out (<tt class="docutils literal"><span class="pre">-B</span></tt>), the process on
the remote nodes will be terminated.</p>
<p>Typically you&#8217;ll be only be backgrounding long-running
shell commands or software upgrades only. Backgrounding the copy module does not do a background file transfer. <a class="reference internal" href="playbooks.html"><em>Playbooks</em></a> also support polling, and have a simplified syntax for this.</p>
</div>
<div class="section" id="limiting-selected-hosts">
<h2><a class="toc-backref" href="#contents">Limiting Selected Hosts</a><a class="headerlink" href="#limiting-selected-hosts" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.7.</span></p>
<p>What hosts you select to manage can be additionally constrained by using the &#8216;&#8211;limit&#8217; parameter or
by using &#8216;batch&#8217; (or &#8216;range&#8217;) selectors.</p>
<p>As mentioned above, patterns can be strung together to select hosts in more than one group:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers:dbservers -m <span class="nb">command</span> -a <span class="s2">&quot;/bin/foo xyz&quot;</span>
</pre></div>
</div>
<p>This is an &#8220;or&#8221; condition. If you want to further constrain the selection, use &#8211;limit, which
also works with <tt class="docutils literal"><span class="pre">ansible-playbook</span></tt>:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers:dbservers -m <span class="nb">command</span> -a <span class="s2">&quot;/bin/foo xyz&quot;</span> region
</pre></div>
</div>
<p>Now let&#8217;s talk about range selection. Suppose you have 1000 servers in group &#8216;datacenter&#8217;, but only want to target one at a time. This is also easy:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible webservers<span class="o">[</span>0-99<span class="o">]</span> -m <span class="nb">command</span> -a <span class="s2">&quot;/bin/foo xyz&quot;</span>
<span class="nv">$ </span>ansible webservers<span class="o">[</span>100-199<span class="o">]</span> -m <span class="nb">command</span> -a <span class="s2">&quot;/bin/foo xyz&quot;</span>
</pre></div>
</div>
<p>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).</p>
<p>Both of these methods can be used at the same time, and ranges can also be passed to the &#8211;limit parameter.</p>
</div>
<div class="section" id="configuration-defaults">
<h2><a class="toc-backref" href="#contents">Configuration &amp; Defaults</a><a class="headerlink" href="#configuration-defaults" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.7.</span></p>
<p>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:</p>
<ol class="arabic simple">
<li>File specified by the <tt class="docutils literal"><span class="pre">ANSIBLE_CONFIG</span></tt> environment variable</li>
<li><tt class="docutils literal"><span class="pre">ansible.cfg</span></tt> in the current working directory. (version 0.8 and up)</li>
<li><tt class="docutils literal"><span class="pre">~/.ansible.cfg</span></tt></li>
<li><tt class="docutils literal"><span class="pre">/etc/ansible/ansible.cfg</span></tt></li>
</ol>
<p>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.</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="modules.html"><em>Ansible Modules</em></a></dt>
<dd>A list of available modules</dd>
<dt><a class="reference internal" href="playbooks.html"><em>Playbooks</em></a></dt>
<dd>Using ansible for configuration management &amp; deployment</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,176 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Index &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul>
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"></span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<h1 id="index">Index</h1>
<div class="genindex-jumpbox">
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,394 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Getting Started &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="Inventory &amp; Patterns" href="patterns.html" />
<link rel="prev" title="Contents" href="index.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1 current"><a class="current reference internal" href="">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Getting Started</a><ul>
<li><a class="reference internal" href="#requirements">Requirements</a></li>
<li><a class="reference internal" href="#python-2-6-epel-instructions-for-rhel-and-centos-5">Python 2.6 EPEL instructions for RHEL and CentOS 5</a></li>
<li><a class="reference internal" href="#getting-ansible">Getting Ansible</a><ul>
<li><a class="reference internal" href="#running-from-checkout">Running From Checkout</a></li>
<li><a class="reference internal" href="#make-install">Make Install</a></li>
<li><a class="reference internal" href="#via-rpm">Via RPM</a></li>
<li><a class="reference internal" href="#debian-gentoo-arch-others">Debian, Gentoo, Arch, Others</a></li>
<li><a class="reference internal" href="#tagged-releases">Tagged Releases</a></li>
</ul>
</li>
<li><a class="reference internal" href="#choosing-between-paramiko-and-native-ssh">Choosing Between Paramiko and Native SSH</a></li>
<li><a class="reference internal" href="#your-first-commands">Your first commands</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="getting-started">
<h1><a class="toc-backref" href="#contents">Getting Started</a><a class="headerlink" href="#getting-started" title="Permalink to this headline"></a></h1>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#getting-started" id="id1">Getting Started</a><ul>
<li><a class="reference internal" href="#requirements" id="id2">Requirements</a></li>
<li><a class="reference internal" href="#python-2-6-epel-instructions-for-rhel-and-centos-5" id="id3">Python 2.6 EPEL instructions for RHEL and CentOS 5</a></li>
<li><a class="reference internal" href="#getting-ansible" id="id4">Getting Ansible</a></li>
<li><a class="reference internal" href="#choosing-between-paramiko-and-native-ssh" id="id5">Choosing Between Paramiko and Native SSH</a></li>
<li><a class="reference internal" href="#your-first-commands" id="id6">Your first commands</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="requirements">
<h2><a class="toc-backref" href="#contents">Requirements</a><a class="headerlink" href="#requirements" title="Permalink to this headline"></a></h2>
<p>Requirements for Ansible are extremely minimal.</p>
<p>Ansible is written for Python 2.6. If you are running Python 2.5 on an &#8220;Enterprise Linux&#8221; 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.</p>
<p>In additon to Python 2.6, you will want the following packages:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">paramiko</span></tt></li>
<li><tt class="docutils literal"><span class="pre">PyYAML</span></tt></li>
<li><tt class="docutils literal"><span class="pre">python-jinja2</span></tt></li>
</ul>
<p>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:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">python-simplejson</span></tt></li>
</ul>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Ansible&#8217;s &#8220;raw&#8221; module (for executing commands in a quick and dirty
way) and the copy module &#8211; some of the most basic features in
ansible &#8211; don&#8217;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&#8217;s jumping ahead
though.)</p>
</div>
</div>
<div class="section" id="python-2-6-epel-instructions-for-rhel-and-centos-5">
<h2><a class="toc-backref" href="#contents">Python 2.6 EPEL instructions for RHEL and CentOS 5</a><a class="headerlink" href="#python-2-6-epel-instructions-for-rhel-and-centos-5" title="Permalink to this headline"></a></h2>
<p>These distributions don&#8217;t have Python 2.6 by default, but it is easily
installable. If you have not already done so, <a class="reference external" href="http://fedoraproject.org/wiki/EPEL">configure EPEL</a></p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>yum install python26 python26-PyYAML python26-paramiko python26-jinja2
</pre></div>
</div>
</div>
<div class="section" id="getting-ansible">
<h2><a class="toc-backref" href="#contents">Getting Ansible</a><a class="headerlink" href="#getting-ansible" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p>Instructions for installing from source are below.</p>
<p>Ansible&#8217;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.</p>
<p>You may also wish to follow the <a class="reference external" href="https://github.com/ansible/ansible">Github project</a> if
you have a github account. This is also where we keep the issue tracker for sharing
bugs and feature ideas.</p>
<div class="section" id="running-from-checkout">
<h3>Running From Checkout<a class="headerlink" href="#running-from-checkout" title="Permalink to this headline"></a></h3>
<p>Ansible is trivially easy to run from a checkout, root permissions are not required
to use it:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>git clone git://github.com/ansible/ansible.git
<span class="nv">$ </span><span class="nb">cd</span> ./ansible
<span class="nv">$ </span><span class="nb">source</span> ./hacking/env-setup
</pre></div>
</div>
<p>You can optionally specify an inventory file (see <a class="reference internal" href="patterns.html"><em>Inventory &amp; Patterns</em></a>) other than /etc/ansible/hosts:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span><span class="nb">echo</span> <span class="s2">&quot;127.0.0.1&quot;</span> &gt; ~/ansible_hosts
<span class="nv">$ </span><span class="nb">export </span><span class="nv">ANSIBLE_HOSTS</span><span class="o">=</span>~/ansible_hosts
</pre></div>
</div>
<p>Now let&#8217;s test things:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible all -m ping --ask-pass
</pre></div>
</div>
</div>
<div class="section" id="make-install">
<h3>Make Install<a class="headerlink" href="#make-install" title="Permalink to this headline"></a></h3>
<p>If you are not working from a distribution where Ansible is packaged yet, you can install Ansible
using &#8220;make install&#8221;. This is done through <cite>python-distutils</cite>:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>git clone git://github.com/ansible/ansible.git
<span class="nv">$ </span><span class="nb">cd</span> ./ansible
<span class="nv">$ </span>sudo make install
</pre></div>
</div>
</div>
<div class="section" id="via-rpm">
<h3>Via RPM<a class="headerlink" href="#via-rpm" title="Permalink to this headline"></a></h3>
<p>RPMs for the last Ansible release are available for <a class="reference external" href="http://fedoraproject.org/wiki/EPEL">EPEL</a> 6 and currently supported
Fedora distributions. Ansible itself can manage earlier operating
systems that contain python 2.4 or higher.</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="c"># install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux</span>
<span class="nv">$ </span>sudo yum install ansible
</pre></div>
</div>
<p>You can also use the <tt class="docutils literal"><span class="pre">make</span> <span class="pre">rpm</span></tt> command to build an RPM you can
distribute and install:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>git clone git://github.com/ansible/ansible.git
<span class="nv">$ </span><span class="nb">cd</span> ./ansible
<span class="nv">$ </span>make rpm
<span class="nv">$ </span>sudo rpm -Uvh ~/rpmbuild/ansible-*.noarch.rpm
</pre></div>
</div>
</div>
<div class="section" id="debian-gentoo-arch-others">
<h3>Debian, Gentoo, Arch, Others<a class="headerlink" href="#debian-gentoo-arch-others" title="Permalink to this headline"></a></h3>
<p>Ubuntu builds are available <a class="reference external" href="https://launchpad.net/~rquillo/+archive/ansible">in a PPA here</a></p>
<p>Debian/Ubuntu package recipes can also be built from the source checkout, run:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>make debian
</pre></div>
</div>
<p>Gentoo eBuilds are available <a class="reference external" href="https://github.com/uu/ubuilds">on github here</a></p>
<p>An Arch PKGBUILD is available on <a class="reference external" href="https://aur.archlinux.org/packages.php?ID=58621">AUR</a>
If you have python3 installed on Arch, you probably want to symlink python to python2:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>sudo ln -sf /usr/bin/python2 /usr/bin/python
</pre></div>
</div>
<p>If you would like to package Ansible for Homebrew, BSD, or others,
please stop by the mailing list and say hi!</p>
</div>
<div class="section" id="tagged-releases">
<h3>Tagged Releases<a class="headerlink" href="#tagged-releases" title="Permalink to this headline"></a></h3>
<p>Tagged releases are available as tar.gz files from the Ansible github
project page:</p>
<ul class="simple">
<li><a class="reference external" href="https://github.com/ansible/ansible/downloads">Ansible/downloads</a></li>
</ul>
</div>
</div>
<div class="section" id="choosing-between-paramiko-and-native-ssh">
<h2><a class="toc-backref" href="#contents">Choosing Between Paramiko and Native SSH</a><a class="headerlink" href="#choosing-between-paramiko-and-native-ssh" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p class="versionadded">
<span class="versionmodified">New in version 0.5.</span></p>
<p>If you want to leverage more advanced SSH features (such as Kerberized
SSH or jump hosts), pass the flag &#8220;&#8211;connection=ssh&#8221; to any ansible
command, or set the ANSIBLE_TRANSPORT environment variable to
&#8216;ssh&#8217;. This will cause Ansible to use openssh tools instead.</p>
<p>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.</p>
<p>If none of this makes sense to you, the default paramiko option is probably fine.</p>
</div>
<div class="section" id="your-first-commands">
<h2><a class="toc-backref" href="#contents">Your first commands</a><a class="headerlink" href="#your-first-commands" title="Permalink to this headline"></a></h2>
<p>Now that you&#8217;ve installed Ansible, it&#8217;s time to test it.</p>
<p>Edit (or create) /etc/ansible/hosts and put one or more remote systems in it, for
which you have your SSH key in <tt class="docutils literal"><span class="pre">authorized_keys</span></tt>:</p>
<div class="highlight-python"><pre>192.168.1.50
aserver.example.org
bserver.example.org</pre>
</div>
<p>Set up SSH agent to avoid retyping passwords:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ssh-agent bash
<span class="nv">$ </span>ssh-add ~/.ssh/id_rsa
</pre></div>
</div>
<p>(Depending on your setup, you may wish to ansible&#8217;s &#8211;private-key-file option to specify a pem file instead)</p>
<p>Now ping all your nodes:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible all -m ping
</pre></div>
</div>
<p>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 &#8216;root&#8217; (we liked the current
user behavior better). To override the remote user name, just use the &#8216;-u&#8217; parameter.</p>
<p>If you would like to access sudo mode, there are also flags to do that:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="c"># as bruce</span>
<span class="nv">$ </span>ansible all -m ping -u bruce
<span class="c"># as bruce, sudoing to root</span>
<span class="nv">$ </span>ansible all -m ping -u bruce --sudo
<span class="c"># as bruce, sudoing to batman</span>
<span class="nv">$ </span>ansible all -m ping -u bruce --sudo --sudo-user batman
</pre></div>
</div>
<p>Now run a live command on all of your nodes:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>ansible all -a <span class="s2">&quot;/bin/echo hello&quot;</span>
</pre></div>
</div>
<p>Congratulations. You&#8217;ve just contacted your nodes with Ansible. It&#8217;s
now time to read some of the more real-world <a class="reference internal" href="examples.html"><em>Command Line Examples And Next Steps</em></a>, and explore
what you can do with different modules, as well as the Ansible
<a class="reference internal" href="playbooks.html"><em>Playbooks</em></a> language. Ansible is not just about running commands, it
also has powerful configuration management and deployment features. There&#8217;s more to
explore, but you already have a fully working infrastructure!</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="examples.html"><em>Command Line Examples And Next Steps</em></a></dt>
<dd>Examples of basic commands</dd>
<dt><a class="reference internal" href="playbooks.html"><em>Playbooks</em></a></dt>
<dd>Learning ansible&#8217;s configuration management language</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,269 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Glossary &mdash; Ansible - SSH-Based Configuration Management &amp; Deployment</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible - SSH-Based Configuration Management &amp; Deployment" href="index.html" />
<link rel="next" title="Who Uses Ansible" href="who_uses_ansible.html" />
<link rel="prev" title="FAQ" href="faq.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<!-- <a class="brand" href="index.html">Ansible</a> -->
<ul class="nav">
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
<li class="toctree-l1"><a class="reference internal" href="faq.html">FAQ</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="who_uses_ansible.html">Who Uses Ansible</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Glossary</a></li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<a href="http://github.com/ansible/ansible"><img style="position: absolute; right: 0; border: 0;" src="http://ansible.github.com/github.png" alt="Fork me on GitHub"></a>
<div class="container">
<a href="http://ansible.github.com"><img src="http://ansible.github.com/ansible-logo.png" alt="Ansible"/></a><br/>
<br/>
<div class="section" id="glossary">
<h1>Glossary<a class="headerlink" href="#glossary" title="Permalink to this headline"></a></h1>
<p>After reading through the rest of the documentation, it may be helpful to review some terms.</p>
<p>ansible &#8211; from science fiction, a device for communicating instanteously over large distances.</p>
<p>ansible &#8211; When speaking of /usr/bin/ansible, a tool for ad-hoc task execution on a group of hosts. This constrasts with /usr/bin/ansible-playbook, which is a full on configuration management and orchestration tool built on top of these fundamentals. Both come with &#8216;ansible&#8217;, the application.</p>
<p>action &#8211; the part of a task that specifies what module to run and what arguments to send it</p>
<p>async &#8211; the act of running a ansible task in the background, potentially polling it for completion. This is useful for kicking off tasks where the result is not important, or in executing tasks that would exceed the SSH timeout.</p>
<p>cobbler &#8211; a kickstart, mirroring, power management, and miscellaneous datacenter management tool that Michael wrote before Ansible, and is frequently used with it. See <a class="reference external" href="http://cobbler.github.com">Cobbler</a></p>
<p>common module code &#8211; a facility in which Ansible modules written in Python can minimize boilerplate code for argument validation and returning values. This is not available to non-Python modules but modules can still be written in languages other than Python.</p>
<p>connection &#8211; how Ansible connects to and manages remote hosts. Paramiko and native ssh are the main options, though
there is also a local connection mode.</p>
<p>cowsay &#8211; a special utility program that, if installed, greatly enhances the clarity of ansible-playbook output.</p>
<p>daisy chaining &#8211; comes up in development discussions. It&#8217;s how in Ansible one module (like copy or template) can
use parameters supported by the file module by requesting the file module be run after the copy module. For example, if specifying a file be templated, we can also specify the mode and owner because the file module is automatically daisy-chained
after the file module.</p>
<p>DSL &#8211; domain specific language. The idea of making a special &#8220;programming&#8221; language or a subset of a language to build a tool out of. Ansible doesn&#8217;t believe in these, and instead treats it&#8217;s playbook language as a data format.</p>
<p>env-setup &#8211; a very useful script in the &#8220;hacking&#8221; directory of an ansible checkout. Sourcing this script makes it very easy to run ansible from source without doing any installation.</p>
<p>external inventory script &#8211; the act of using an executable script in place of an ansible inventory file, so that ansible will invoke the script when needed to ask about what hosts it is managing and variables related to those hosts.</p>
<p>fact &#8211; a variable discovered about a remote host, rather than configured in a config file. Facts can include
the system architecture, the hostname, the operating system version, and so on. facts can be used in configuration
files.</p>
<p>forks &#8211; the level of parallelism used with a /usr/bin/ansible or /usr/bin/ansible-playbook command. Ansible executes multiple remote management commands in parallel to get things done faster.</p>
<p>func &#8211; an earlier ad-hoc execution tool that is the basis of some of the ideas in Ansible. Michael wrote Func with some colleagues from Red Hat, and a later tool called taboot built on Func helped inspire the playbooks language. Func didn&#8217;t have a configuration management language on top of it, nor did it use SSH, but it helped pave the way for several other tools.</p>
<p>handler &#8211; a special class of a task that is not run unless a given task registers a change event. Handlers are most
frequently used for restarting services when the contents of configuration files change.</p>
<p>idempotent &#8211; when applied to configuration management, this means that running a given task twice does not produce
an unexpected effect on the system. Mathematically, F(x) = F(F(x)). Ansible&#8217;s core modules all support this concept
but Ansible does not force this upon you.</p>
<p>include &#8211; a playbook, handler, or variable data loaded from another file</p>
<p>infrastructure as code &#8211; the practice of treating configuration, management, and deployment of systems as a software project. Ansible doesn&#8217;t really believe in this and tries to simplify things by making a simpler language that is easier to write and audit, and is therefore easier to understand by all parties involved. More advanced takes on I.A.C. use actual programming languages to describe configurations.</p>
<p>inventory &#8211; ansible keeps track of what hosts you are managing, and allows them to be put in groups for easier selection. This file is by default in a simple INI format, but can be replaced with an &#8216;external inventory script&#8217;</p>
<p>Jinja2 &#8211; Ansible uses this as a templating language for the &#8216;template&#8217; module.</p>
<p>JSON &#8211; the format Ansible modules use to return data over the wire. &#8220;Java Script Object Notation&#8221;</p>
<p>module &#8211; a reusable unit of logic that tells Ansible how to do things on remote machines. Ansible ships with many modules written in Python, but modules can be written in any language. Modules return structured data in JSON.</p>
<p>notify &#8211; what a task does when it detects that something has changed on the remote system. A task notifying a handler
means it is sending a message to the handler that it needs to run at the end of a playbook execution.</p>
<p>paramiko &#8211; the default connection type for ansible uses a pure-Python SSH library called paramiko. It is generally
easier to set up than native SSH but does not offer as many configuration options and does not support Kerberized SSH.</p>
<p>pattern &#8211; a selector that can match host or group names using wildcards. Patterns are used in plays or in ad-hoc executions of /usr/bin/ansible to target groups of hosts to manage.</p>
<p>play &#8211; a group of ansible tasks that are to be executed on the same set of hosts. A play is always run by the same user account and may optionally sudo to a particular user after connecting. In addition to a list of tasks, a play may also choose to define variables or include them from other files, all of which are shared with each task in the play.</p>
<p>playbook &#8211; a list of ansible plays grouped together in a single file, which are run top to bottom. Each play may select different hosts and have different tasks. A playbook is analogous to a Chef recipe, a Puppet manifest, a CFEngine &#8220;promise&#8221;. Playbooks can be broken up into more than one file using includes, in which case it&#8217;s still ok to call it a playbook.</p>
<p>pull &#8211; the act of a managed system phoning home to ask how it is configured. This is useful in large scale out scenarios or for periodic automatic system remediation.</p>
<p>push &#8211; the act of reaching out to systems you want to manage rather than them phoning home. This is Ansible&#8217;s default
mode, but pull is also supported via the &#8216;ansible-pull&#8217; script.</p>
<p>runner &#8211; comes up in development discussions. a core component of the ansible code that runs a single module/task against a given set of hosts. /usr/bin/ansible makes use of runner directly. Playbooks instantiate multiple instances of runner,
one for each task in a playbook.</p>
<p>setup cache &#8211; comes up in development discussions. The setup cache is a mechanism of storing fact results from various
systems and makes them available as variables in action lines and templates</p>
<p>SSH &#8211; secure shell. Ansible by default uses SSH to talk to remote hosts because it is already there and very secure. It does not require any additional daemons.</p>
<p>task &#8211; one of many ansible modules to execute on a given set of hosts, and the parameters to use when calling it.
A task has a name, an &#8216;action&#8217;, and other optional variables. Making sure a package is installed, or a file
is templated and transferred, is the example of a task.</p>
<p>template &#8211; the act of taking a file with variable placeholders in it and substituting variables to make a final file. Templating is frequently used to place configuration files.</p>
<p>test-module &#8211; a useful script in the &#8220;hacking&#8221; directory of an ansible checkout for running a module locally, without ansible&#8217;s core code in the way. Used when developing or debugging modules.</p>
<p>Van Halen &#8211; the great American Rock Band, known for great instrumental guitar work and also songs about Alien Abductions. All Ansible releases are code named after Van Halen songs. C&#8217;mon Dave, gimme a break.</p>
<p>YAML &#8211; the core language format for ansible playbooks and include files. Stands for &#8220;YAML Ain&#8217;t Markup Language&#8221;. YAML can be taken to extremes where it is difficult to write and read, but Ansible uses a relatively simple dialect and minimal levels of nesting.</p>
</div>
<br/>
</div>
<footer class="footer">
<div class="container">
<div id="fb-root"></div>
<p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_donations">
<input type="hidden" name="business" value="michael.dehaan@gmail.com">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="item_name" value="Ansible">
<input type="hidden" name="no_note" value="0">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="bn" value="PP-DonationsBF:btn_donate_LG.gif:NonHostedGuest">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
</p>
<p>
<a href="https://twitter.com/share" class="twitter-share-button" data-text="ansible.github.com">Share On Twitter</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
<g:plusone annotation="inline"></g:plusone>
<div class="fb-like" data-href="http://ansible.github.com" data-send="true" data-width="450" data-show-faces="false"></div>
</p>
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Aug 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,191 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Contents &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="#" />
<link rel="next" title="Getting Started" href="gettingstarted.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="#">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul>
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Contents</a><ul>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="contents">
<h1>Contents<a class="headerlink" href="#contents" title="Permalink to this headline"></a></h1>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,202 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Man Pages &mdash; Ansible - SSH-Based Configuration Management &amp; Deployment</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible - SSH-Based Configuration Management &amp; Deployment" href="index.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible</a>
<ul class="nav">
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul>
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Downloads &amp; Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">The Inventory File, Patterns, and Groups</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="faq.html">Frequently Asked Questions</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Man Pages</a><ul>
<li><a class="reference internal" href="#ansible-1">ansible(1)</a></li>
<li><a class="reference internal" href="#ansible-playbook-1">ansible-playbook(1)</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="man-pages">
<span id="man"></span><h1>Man Pages<a class="headerlink" href="#man-pages" title="Permalink to this headline"></a></h1>
<p>Ansible&#8217;s man pages list available command line options. See the rest of the web site for
examples of these tools in use.</p>
<div class="section" id="ansible-1">
<h2>ansible(1)<a class="headerlink" href="#ansible-1" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><a class="reference external" href="man/ansible.1.html">View ansible.1</a></li>
</ul>
</div>
<div class="section" id="ansible-playbook-1">
<h2>ansible-playbook(1)<a class="headerlink" href="#ansible-playbook-1" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><a class="reference external" href="man/ansible-playbook.1.html">View ansible-playbook.1</a></li>
</ul>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="examples.html"><em>Command Line Examples</em></a></dt>
<dd>Examples of basic commands</dd>
<dt><a class="reference internal" href="modules.html"><em>Ansible Modules</em></a></dt>
<dd>List of built-in modules</dd>
<dt><a class="reference internal" href="playbooks.html"><em>Playbooks</em></a></dt>
<dd>Learning ansible&#8217;s configuration management language</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
</dl>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-right"><a href="#">Back to top</a></p>
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Apr 12, 2012.<br/>
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.8.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,498 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Module Development &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="prev" title="API &amp; Integrations" href="api.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Module Development</a><ul>
<li><a class="reference internal" href="#tutorial">Tutorial</a></li>
<li><a class="reference internal" href="#testing-modules">Testing Modules</a></li>
<li><a class="reference internal" href="#reading-input">Reading Input</a></li>
<li><a class="reference internal" href="#module-provided-facts">Module Provided &#8216;Facts&#8217;</a></li>
<li><a class="reference internal" href="#common-module-boilerplate">Common Module Boilerplate</a></li>
<li><a class="reference internal" href="#common-pitfalls">Common Pitfalls</a></li>
<li><a class="reference internal" href="#conventions-recomendations">Conventions/Recomendations</a></li>
<li><a class="reference internal" href="#shorthand-vs-json">Shorthand Vs JSON</a></li>
<li><a class="reference internal" href="#sharing-your-module">Sharing Your Module</a></li>
<li><a class="reference internal" href="#getting-your-module-into-core">Getting Your Module Into Core</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="module-development">
<h1><a class="toc-backref" href="#contents">Module Development</a><a class="headerlink" href="#module-development" title="Permalink to this headline"></a></h1>
<p>Ansible modules are reusable units of magic that can be used by the Ansible API,
or by the <cite>ansible</cite> or <cite>ansible-playbook</cite> programs.</p>
<p>Modules can be written in any language and are found in the path specified
by <cite>ANSIBLE_LIBRARY_PATH</cite> or the <tt class="docutils literal"><span class="pre">--module-path</span></tt> command line option.</p>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#module-development" id="id2">Module Development</a><ul>
<li><a class="reference internal" href="#tutorial" id="id3">Tutorial</a></li>
<li><a class="reference internal" href="#testing-modules" id="id4">Testing Modules</a></li>
<li><a class="reference internal" href="#reading-input" id="id5">Reading Input</a></li>
<li><a class="reference internal" href="#module-provided-facts" id="id6">Module Provided &#8216;Facts&#8217;</a></li>
<li><a class="reference internal" href="#common-module-boilerplate" id="id7">Common Module Boilerplate</a></li>
<li><a class="reference internal" href="#common-pitfalls" id="id8">Common Pitfalls</a></li>
<li><a class="reference internal" href="#conventions-recomendations" id="id9">Conventions/Recomendations</a></li>
<li><a class="reference internal" href="#shorthand-vs-json" id="id10">Shorthand Vs JSON</a></li>
<li><a class="reference internal" href="#sharing-your-module" id="id11">Sharing Your Module</a></li>
<li><a class="reference internal" href="#getting-your-module-into-core" id="id12">Getting Your Module Into Core</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="tutorial">
<h2><a class="toc-backref" href="#contents">Tutorial</a><a class="headerlink" href="#tutorial" title="Permalink to this headline"></a></h2>
<p>Let&#8217;s build a module to get and set the system time. For starters, let&#8217;s build
a module that just outputs the current time.</p>
<p>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.</p>
<p>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&#8217;ll show the easy
way later.</p>
<p>So, here&#8217;s an example. You would never really need to build a module to set the system time,
the &#8216;command&#8217; module could already be used to do this. Though we&#8217;re going to make one.</p>
<p>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&#8217;s source tree are internalisms,
so look at <cite>service</cite> or <cite>yum</cite>, and don&#8217;t stare too close into things like <cite>async_wrapper</cite> or
you&#8217;ll turn to stone. Nobody ever executes async_wrapper directly.</p>
<p>Ok, let&#8217;s get going with an example. We&#8217;ll use Python. For starters, save this as a file named <cite>time</cite>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/python</span>
<span class="kn">import</span> <span class="nn">datetime</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="n">date</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">())</span>
<span class="k">print</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span>
<span class="s">&quot;time&quot;</span> <span class="p">:</span> <span class="n">date</span>
<span class="p">})</span>
</pre></div>
</div>
</div>
<div class="section" id="testing-modules">
<h2><a class="toc-backref" href="#contents">Testing Modules</a><a class="headerlink" href="#testing-modules" title="Permalink to this headline"></a></h2>
<p>There&#8217;s a useful test script in the source checkout for ansible:</p>
<div class="highlight-python"><pre>git clone git@github.com:ansible/ansible.git
chmod +x ansible/hacking/test-module</pre>
</div>
<p>Let&#8217;s run the script you just wrote with that:</p>
<div class="highlight-python"><pre>ansible/hacking/test-module -m ./time</pre>
</div>
<p>You should see output that looks something like this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span><span class="s">u&#39;time&#39;</span><span class="p">:</span> <span class="s">u&#39;2012-03-14 22:13:48.539183&#39;</span><span class="p">}</span>
</pre></div>
</div>
<p>If you did not, you might have a typo in your module, so recheck it and try again.</p>
</div>
<div class="section" id="reading-input">
<h2><a class="toc-backref" href="#contents">Reading Input</a><a class="headerlink" href="#reading-input" title="Permalink to this headline"></a></h2>
<p>Let&#8217;s modify the module to allow setting the current time. We&#8217;ll do this by seeing
if a key value pair in the form <cite>time=&lt;string&gt;</cite> is passed in to the module.</p>
<p>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&#8217;ll do some basic parsing to treat the input as key=value.</p>
<p>The example usage we are trying to achieve to set the time is:</p>
<div class="highlight-python"><pre>time time="March 14 22:10"</pre>
</div>
<p>If no time parameter is set, we&#8217;ll just leave the time as is and return the current time.</p>
<p>Let&#8217;s look at the code. Read the comments as we&#8217;ll explain as we go. Note that this
is highly verbose because it&#8217;s intended as an educational example. You can write modules
a lot shorter than this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c">#!/usr/bin/python</span>
<span class="c"># import some python modules that we&#39;ll use. These are all</span>
<span class="c"># available in Python&#39;s core</span>
<span class="kn">import</span> <span class="nn">datetime</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">shlex</span>
<span class="c"># read the argument string from the arguments file</span>
<span class="n">args_file</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">args_data</span> <span class="o">=</span> <span class="nb">file</span><span class="p">(</span><span class="n">args_file</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="c"># for this module, we&#39;re going to do key=value style arguments</span>
<span class="c"># this is up to each module to decide what it wants, but all</span>
<span class="c"># core modules besides &#39;command&#39; and &#39;shell&#39; take key=value</span>
<span class="c"># so this is highly recommended</span>
<span class="n">arguments</span> <span class="o">=</span> <span class="n">shlex</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">args_data</span><span class="p">)</span>
<span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">arguments</span><span class="p">:</span>
<span class="c"># ignore any arguments without an equals in it</span>
<span class="k">if</span> <span class="n">arg</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">&quot;=&quot;</span><span class="p">)</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
<span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="o">=</span> <span class="n">arg</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot;=&quot;</span><span class="p">)</span>
<span class="c"># if setting the time, the key &#39;time&#39;</span>
<span class="c"># will contain the value we want to set the time to</span>
<span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&quot;time&quot;</span><span class="p">:</span>
<span class="c"># now we&#39;ll affect the change. Many modules</span>
<span class="c"># will strive to be &#39;idempotent&#39;, meaning they</span>
<span class="c"># will only make changes when the desired state</span>
<span class="c"># expressed to the module does not match</span>
<span class="c"># the current state. Look at &#39;service&#39;</span>
<span class="c"># or &#39;yum&#39; in the main git tree for an example</span>
<span class="c"># of how that might look.</span>
<span class="n">rc</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s">&quot;date -s </span><span class="se">\&quot;</span><span class="si">%s</span><span class="se">\&quot;</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">value</span><span class="p">)</span>
<span class="c"># always handle all possible errors</span>
<span class="c">#</span>
<span class="c"># when returning a failure, include &#39;failed&#39;</span>
<span class="c"># in the return data, and explain the failure</span>
<span class="c"># in &#39;msg&#39;. Both of these conventions are</span>
<span class="c"># required however additional keys and values</span>
<span class="c"># can be added.</span>
<span class="k">if</span> <span class="n">rc</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">print</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span>
<span class="s">&quot;failed&quot;</span> <span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
<span class="s">&quot;msg&quot;</span> <span class="p">:</span> <span class="s">&quot;failed setting the time&quot;</span>
<span class="p">})</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="c"># when things do not fail, we do not</span>
<span class="c"># have any restrictions on what kinds of</span>
<span class="c"># data are returned, but it&#39;s always a</span>
<span class="c"># good idea to include whether or not</span>
<span class="c"># a change was made, as that will allow</span>
<span class="c"># notifiers to be used in playbooks.</span>
<span class="n">date</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">())</span>
<span class="k">print</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span>
<span class="s">&quot;time&quot;</span> <span class="p">:</span> <span class="n">date</span><span class="p">,</span>
<span class="s">&quot;changed&quot;</span> <span class="p">:</span> <span class="bp">True</span>
<span class="p">})</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c"># if no parameters are sent, the module may or</span>
<span class="c"># may not error out, this one will just</span>
<span class="c"># return the time</span>
<span class="n">date</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">())</span>
<span class="k">print</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span>
<span class="s">&quot;time&quot;</span> <span class="p">:</span> <span class="n">date</span>
<span class="p">})</span>
</pre></div>
</div>
<p>Let&#8217;s test that module:</p>
<div class="highlight-python"><pre>ansible/hacking/test-module -m ./time -a time=\"March 14 12:23\"</pre>
</div>
<p>This should return something like:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">{</span><span class="s">&quot;changed&quot;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="s">&quot;time&quot;</span><span class="p">:</span> <span class="s">&quot;2012-03-14 12:23:00.000307&quot;</span><span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="module-provided-facts">
<h2><a class="toc-backref" href="#contents">Module Provided &#8216;Facts&#8217;</a><a class="headerlink" href="#module-provided-facts" title="Permalink to this headline"></a></h2>
<p>The &#8216;setup&#8217; module that ships with Ansible provides many variables about a system that can be used in playbooks
and templates. However, it&#8217;s possible to also add your own facts without modifying the system module. To do
this, just have the module return a <cite>ansible_facts</cite> key, like so, along with other return data:</p>
<div class="highlight-python"><pre>{
"changed" : True,
"rc" : 5,
"ansible_facts" : {
"leptons" : 5000
"colors" : {
"red" : "FF0000",
"white" : "FFFFFF"
}
}
}</pre>
</div>
<p>These &#8216;facts&#8217; 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 &#8216;site_facts&#8217; and always call it at the top of each playbook, though
we&#8217;re always open to improving the selection of core facts in Ansible as well.</p>
</div>
<div class="section" id="common-module-boilerplate">
<h2><a class="toc-backref" href="#contents">Common Module Boilerplate</a><a class="headerlink" href="#common-module-boilerplate" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p>Rather than mention these here, the best way to learn is to read some of the <a class="reference external" href="https://github.com/ansible/ansible/tree/devel/library">source of the modules</a> that come with Ansible.</p>
<p>The &#8216;group&#8217; and &#8216;user&#8217; modules are reasonably non-trival and showcase what this looks like.</p>
<p>Key parts include always ending the module file with:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="c"># include magic from lib/ansible/module_common.py</span>
<span class="c">#&lt;&lt;INCLUDE_ANSIBLE_MODULE_COMMON&gt;&gt;</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<p>And instantiating the module class like:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">module</span> <span class="o">=</span> <span class="n">AnsibleModule</span><span class="p">(</span>
<span class="n">argument_spec</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
<span class="n">state</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">default</span><span class="o">=</span><span class="s">&#39;present&#39;</span><span class="p">,</span> <span class="n">choices</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;present&#39;</span><span class="p">,</span> <span class="s">&#39;absent&#39;</span><span class="p">]),</span>
<span class="n">name</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
<span class="n">enabled</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">choices</span><span class="o">=</span><span class="n">BOOLEANS</span><span class="p">),</span>
<span class="n">something</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">aliases</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;whatever&#39;</span><span class="p">])</span>
<span class="p">)</span>
<span class="p">)</span>
</pre></div>
</div>
<p>The AnsibleModule provides lots of common code for handling returns, parses your arguments
for you, and allows you to check inputs.</p>
<p>Successful returns are made like this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">module</span><span class="o">.</span><span class="n">exit_json</span><span class="p">(</span><span class="n">changed</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">something_else</span><span class="o">=</span><span class="mi">12345</span><span class="p">)</span>
</pre></div>
</div>
<p>And failures are just as simple (where &#8216;msg&#8217; is a required parameter to explain the error):</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">module</span><span class="o">.</span><span class="n">fail_json</span><span class="p">(</span><span class="n">msg</span><span class="o">=</span><span class="s">&quot;Something fatal happened&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>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.</p>
<p>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.</p>
<p>If submitting a module to ansible&#8217;s core code, which we encourage, use of the AnsibleModule
class is required.</p>
</div>
<div class="section" id="common-pitfalls">
<h2><a class="toc-backref" href="#contents">Common Pitfalls</a><a class="headerlink" href="#common-pitfalls" title="Permalink to this headline"></a></h2>
<p>You should also never do this in a module:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">print</span> <span class="s">&quot;some status message&quot;</span>
</pre></div>
</div>
<p>Because the output is supposed to be valid JSON. Except that&#8217;s not quite true,
but we&#8217;ll get to that later.</p>
<p>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.</p>
<p>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.</p>
<p>Always use the hacking/test-module script when developing modules and it will warn
you about these kind of things.</p>
</div>
<div class="section" id="conventions-recomendations">
<h2><a class="toc-backref" href="#contents">Conventions/Recomendations</a><a class="headerlink" href="#conventions-recomendations" title="Permalink to this headline"></a></h2>
<p>As a reminder from the example code above, here are some basic conventions
and guidelines:</p>
<ul class="simple">
<li>If the module is addressing an object, the parameter for that object should be called &#8216;name&#8217; whenever possible, or accept &#8216;name&#8217; as an alias.</li>
<li>If you have a company module that returns facts specific to your installations, a good name for this module is <cite>site_facts</cite>.</li>
<li>Modules accepting boolean status should generally accept &#8216;yes&#8217;, &#8216;no&#8217;, &#8216;true&#8217;, &#8216;false&#8217;, or anything else a user may likely throw at them. The AnsibleModule common code supports this with &#8220;choices=BOOLEANS&#8221; and a module.boolean(value) casting function.</li>
<li>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.</li>
<li>Modules must be self contained in one file to be auto-transferred by ansible.</li>
<li>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.</li>
<li>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.</li>
<li>In the event of failure, a key of &#8216;failed&#8217; should be included, along with a string explanation in &#8216;msg&#8217;. Modules that raise tracebacks (stacktraces) are generally considered &#8216;poor&#8217; 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 &#8216;failed&#8217; element will be included for you automatically when you call &#8216;fail_json&#8217;.</li>
<li>Return codes from modules are not actually not signficant, but continue on with 0=success and non-zero=failure for reasons of future proofing.</li>
<li>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.</li>
</ul>
</div>
<div class="section" id="shorthand-vs-json">
<h2><a class="toc-backref" href="#contents">Shorthand Vs JSON</a><a class="headerlink" href="#shorthand-vs-json" title="Permalink to this headline"></a></h2>
<p>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:</p>
<div class="highlight-python"><pre>somekey=1 somevalue=2 rc=3 favcolor=red</pre>
</div>
<p>If you&#8217;re writing a module in Python or Ruby or whatever, though, returning
JSON is probably the simplest way to go.</p>
</div>
<div class="section" id="sharing-your-module">
<h2><a class="toc-backref" href="#contents">Sharing Your Module</a><a class="headerlink" href="#sharing-your-module" title="Permalink to this headline"></a></h2>
<p>If you think your module is generally useful to others, a good place to share it
is in <a class="reference external" href="https://github.com/ansible/ansible/tree/devel/contrib">Ansible Resources</a>. This is maintained
as a simple repo with pointers to other github projects.</p>
<p>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.</p>
<p><a class="reference external" href="http://groups.google.com/group/ansible-project">Ansible Mailing List</a></p>
</div>
<div class="section" id="getting-your-module-into-core">
<h2><a class="toc-backref" href="#contents">Getting Your Module Into Core</a><a class="headerlink" href="#getting-your-module-into-core" title="Permalink to this headline"></a></h2>
<p>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.</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="modules.html"><em>Ansible Modules</em></a></dt>
<dd>Learn about available modules</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/tree/devel/contrib">Ansible Resources</a></dt>
<dd>User contributed playbooks, modules, and articles</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/tree/devel/library">Github modules directory</a></dt>
<dd>Browse source of core modules</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,377 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Inventory &amp; Patterns &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="Command Line Examples And Next Steps" href="examples.html" />
<link rel="prev" title="Getting Started" href="gettingstarted.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Inventory &amp; Patterns</a><ul>
<li><a class="reference internal" href="#hosts-and-groups">Hosts and Groups</a></li>
<li><a class="reference internal" href="#selecting-targets">Selecting Targets</a></li>
<li><a class="reference internal" href="#host-variables">Host Variables</a></li>
<li><a class="reference internal" href="#group-variables">Group Variables</a></li>
<li><a class="reference internal" href="#groups-of-groups-and-group-variables">Groups of Groups, and Group Variables</a></li>
<li><a class="reference internal" href="#splitting-out-host-and-group-specific-data">Splitting Out Host and Group Specific Data</a></li>
<li><a class="reference internal" href="#yaml-inventory">YAML Inventory</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="inventory-patterns">
<span id="patterns"></span><h1><a class="toc-backref" href="#table-of-contents">Inventory &amp; Patterns</a><a class="headerlink" href="#inventory-patterns" title="Permalink to this headline"></a></h1>
<p>Ansible works against multiple systems in your infrastructure at the
same time. It does this by selecting portions of systems listed in
Ansible&#8217;s inventory file, which defaults to /etc/ansible/hosts.</p>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first"><cite>Table of contents</cite></p>
<ul class="simple">
<li><a class="reference internal" href="#inventory-patterns" id="id1">Inventory &amp; Patterns</a><ul>
<li><a class="reference internal" href="#hosts-and-groups" id="id2">Hosts and Groups</a></li>
<li><a class="reference internal" href="#selecting-targets" id="id3">Selecting Targets</a></li>
<li><a class="reference internal" href="#host-variables" id="id4">Host Variables</a></li>
<li><a class="reference internal" href="#group-variables" id="id5">Group Variables</a></li>
<li><a class="reference internal" href="#groups-of-groups-and-group-variables" id="id6">Groups of Groups, and Group Variables</a></li>
<li><a class="reference internal" href="#splitting-out-host-and-group-specific-data" id="id7">Splitting Out Host and Group Specific Data</a></li>
<li><a class="reference internal" href="#yaml-inventory" id="id8">YAML Inventory</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="hosts-and-groups">
<span id="inventoryformat"></span><h2><a class="toc-backref" href="#table-of-contents">Hosts and Groups</a><a class="headerlink" href="#hosts-and-groups" title="Permalink to this headline"></a></h2>
<p>The format for /etc/ansible/hosts is an INI format and looks like this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">mail</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="p">[</span><span class="n">webservers</span><span class="p">]</span>
<span class="n">foo</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">bar</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="p">[</span><span class="n">dbservers</span><span class="p">]</span>
<span class="n">one</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">two</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
<span class="n">three</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
</pre></div>
</div>
<p>The things in brackets are group names. You don&#8217;t have to have them,
but they are useful.</p>
<p>If you have hosts that run on non-standard SSH ports you can put the port number
after the hostname with a colon.</p>
<blockquote>
<div>four.example.com:5309</div></blockquote>
<p>In 0.6 and later, if you have a lot of hosts following similar patterns you can do this rather than listing each hostname:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">[</span><span class="n">webservers</span><span class="p">]</span>
<span class="n">www</span><span class="p">[</span><span class="mo">01</span><span class="p">:</span><span class="mi">50</span><span class="p">]</span><span class="o">.</span><span class="n">example</span><span class="o">.</span><span class="n">com</span>
</pre></div>
</div>
<p>Leading zeros can be included or removed, as desired, and the ranges are inclusive.</p>
</div>
<div class="section" id="selecting-targets">
<h2><a class="toc-backref" href="#table-of-contents">Selecting Targets</a><a class="headerlink" href="#selecting-targets" title="Permalink to this headline"></a></h2>
<p>We&#8217;ll go over how to use the command line in <a class="reference internal" href="examples.html"><em>Command Line Examples And Next Steps</em></a> section, however, basically it looks like this:</p>
<div class="highlight-python"><pre>ansible &lt;pattern_goes_here&gt; -m &lt;module_name&gt; -a &lt;arguments&gt;</pre>
</div>
<p>Such as:</p>
<div class="highlight-python"><pre>ansible webservers -m service -a "name=httpd state=restarted"</pre>
</div>
<p>Within <a class="reference internal" href="playbooks.html"><em>Playbooks</em></a>, these patterns can be used for even greater purposes.</p>
<p>Anyway, to use Ansible, you&#8217;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.</p>
<p>The following patterns target all hosts in the inventory file:</p>
<div class="highlight-python"><pre>all
*</pre>
</div>
<p>Basically &#8216;all&#8217; is an alias for &#8216;*&#8217;. It is also possible to address a specific host or hosts:</p>
<div class="highlight-python"><pre>one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*</pre>
</div>
<p>The following patterns address one or more groups, which are denoted
with the aforementioned bracket headers in the inventory file:</p>
<div class="highlight-python"><pre>webservers
webservers:dbservers</pre>
</div>
<p>You can exclude groups as well, for instance, all webservers not in Phoenix:</p>
<div class="highlight-python"><pre>webservers:!phoenix</pre>
</div>
<p>Individual host names (or IPs), but not groups, can also be referenced using
wildcards:</p>
<div class="highlight-python"><pre>*.example.com
*.com</pre>
</div>
<p>It&#8217;s also ok to mix wildcard patterns and groups at the same time:</p>
<div class="highlight-python"><pre>one*.com:dbservers</pre>
</div>
<p>Easy enough. See <a class="reference internal" href="examples.html"><em>Command Line Examples And Next Steps</em></a> and then <a class="reference internal" href="playbooks.html"><em>Playbooks</em></a> for how to do things to selected hosts.</p>
</div>
<div class="section" id="host-variables">
<h2><a class="toc-backref" href="#table-of-contents">Host Variables</a><a class="headerlink" href="#host-variables" title="Permalink to this headline"></a></h2>
<p>It is easy to assign variables to hosts that will be used later in playbooks:</p>
<div class="highlight-python"><pre>[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909</pre>
</div>
</div>
<div class="section" id="group-variables">
<h2><a class="toc-backref" href="#table-of-contents">Group Variables</a><a class="headerlink" href="#group-variables" title="Permalink to this headline"></a></h2>
<p>Variables can also be applied to an entire group at once:</p>
<div class="highlight-python"><pre>[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com</pre>
</div>
</div>
<div class="section" id="groups-of-groups-and-group-variables">
<h2><a class="toc-backref" href="#table-of-contents">Groups of Groups, and Group Variables</a><a class="headerlink" href="#groups-of-groups-and-group-variables" title="Permalink to this headline"></a></h2>
<p>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:</p>
<div class="highlight-python"><pre>[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</pre>
</div>
<p>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.</p>
</div>
<div class="section" id="splitting-out-host-and-group-specific-data">
<h2><a class="toc-backref" href="#table-of-contents">Splitting Out Host and Group Specific Data</a><a class="headerlink" href="#splitting-out-host-and-group-specific-data" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.6.</span></p>
<p>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.</p>
<p>Assuming the inventory file path is:</p>
<div class="highlight-python"><pre>/etc/ansible/hosts</pre>
</div>
<p>If the host is named &#8216;foosball&#8217;, and in groups &#8216;raleigh&#8217; and &#8216;webservers&#8217;, variables
in YAML files at the following locations will be made available to the host:</p>
<div class="highlight-python"><pre>/etc/ansible/group_vars/raleigh
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball</pre>
</div>
<p>For instance, suppose you have hosts grouped by datacenter, and each datacenter
uses some different servers. The data in the groupfile &#8216;/etc/ansible/group_vars/raleigh&#8217; for
the &#8216;raleigh&#8217; group might look like:</p>
<div class="highlight-python"><pre>---
ntp_server: acme.example.org
database_server: storage.example.org</pre>
</div>
<p>It is ok if these files do not exist, this is an optional feature.</p>
<p>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.</p>
<p class="versionadded">
<span class="versionmodified">New in version 0.5: </span>If you ever have two python interpreters on a system, set a
variable called &#8216;ansible_python_interpreter&#8217; to the Python
interpreter path you would like to use.</p>
</div>
<div class="section" id="yaml-inventory">
<h2><a class="toc-backref" href="#table-of-contents">YAML Inventory</a><a class="headerlink" href="#yaml-inventory" title="Permalink to this headline"></a></h2>
<p class="deprecated">
<span class="versionmodified">Deprecated since version 0.7.</span></p>
<p>Ansible&#8217;s YAML inventory format is deprecated and will be removed in
Ansible 0.7. Ansible 0.6 includes a <a class="reference external" href="https://github.com/ansible/ansible/blob/devel/examples/scripts/yaml_to_ini.py">conversion script</a>.</p>
<p>Usage:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">yaml_to_ini</span><span class="o">.</span><span class="n">py</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ansible</span><span class="o">/</span><span class="n">hosts</span>
</pre></div>
</div>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="examples.html"><em>Command Line Examples And Next Steps</em></a></dt>
<dd>Examples of basic commands</dd>
<dt><a class="reference internal" href="playbooks.html"><em>Playbooks</em></a></dt>
<dd>Learning ansible&#8217;s configuration management language</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,550 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Playbooks &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="Advanced Playbooks" href="playbooks2.html" />
<link rel="prev" title="YAML Syntax" href="YAMLSyntax.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Playbooks</a><ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#playbook-language-example">Playbook Language Example</a></li>
<li><a class="reference internal" href="#basics">Basics</a><ul>
<li><a class="reference internal" href="#hosts-and-users">Hosts and Users</a></li>
<li><a class="reference internal" href="#vars-section">Vars section</a></li>
<li><a class="reference internal" href="#tasks-list">Tasks list</a></li>
</ul>
</li>
<li><a class="reference internal" href="#running-operations-on-change">Running Operations On Change</a></li>
<li><a class="reference internal" href="#include-files-and-encouraging-reuse">Include Files And Encouraging Reuse</a></li>
<li><a class="reference internal" href="#executing-a-playbook">Executing A Playbook</a></li>
<li><a class="reference internal" href="#tips-and-tricks">Tips and Tricks</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="playbooks">
<h1><a class="toc-backref" href="#contents">Playbooks</a><a class="headerlink" href="#playbooks" title="Permalink to this headline"></a></h1>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#playbooks" id="id2">Playbooks</a><ul>
<li><a class="reference internal" href="#introduction" id="id3">Introduction</a></li>
<li><a class="reference internal" href="#playbook-language-example" id="id4">Playbook Language Example</a></li>
<li><a class="reference internal" href="#basics" id="id5">Basics</a></li>
<li><a class="reference internal" href="#running-operations-on-change" id="id6">Running Operations On Change</a></li>
<li><a class="reference internal" href="#include-files-and-encouraging-reuse" id="id7">Include Files And Encouraging Reuse</a></li>
<li><a class="reference internal" href="#executing-a-playbook" id="id8">Executing A Playbook</a></li>
<li><a class="reference internal" href="#tips-and-tricks" id="id9">Tips and Tricks</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="introduction">
<h2><a class="toc-backref" href="#contents">Introduction</a><a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>Let&#8217;s dive in and see how they work. As you go, you may wish to open
the <a class="reference external" href="https://github.com/ansible/ansible/tree/devel/examples/playbooks">github examples directory</a> in
another tab, so you can apply the theory to what things look like in practice.</p>
</div>
<div class="section" id="playbook-language-example">
<h2><a class="toc-backref" href="#contents">Playbook Language Example</a><a class="headerlink" href="#playbook-language-example" title="Permalink to this headline"></a></h2>
<p>Playbooks are expressed in YAML format and have a minimum of syntax.
Each playbook is composed of one or more &#8216;plays&#8217; in a list.</p>
<p>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.</p>
<p>By composing a playbook of multiple &#8216;plays&#8217;, 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.</p>
<p>For starters, here&#8217;s a playbook that contains just one play:</p>
<div class="highlight-python"><pre>---
- 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</pre>
</div>
<p>Below, we&#8217;ll break down what the various features of the playbook language are.</p>
</div>
<div class="section" id="basics">
<h2><a class="toc-backref" href="#contents">Basics</a><a class="headerlink" href="#basics" title="Permalink to this headline"></a></h2>
<div class="section" id="hosts-and-users">
<h3>Hosts and Users<a class="headerlink" href="#hosts-and-users" title="Permalink to this headline"></a></h3>
<p>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.</p>
<p>The <cite>hosts</cite> line is a list of one or more groups or host patterns,
separated by colons, as described in the <a class="reference internal" href="patterns.html#patterns"><em>Inventory &amp; Patterns</em></a>
documentation. The <cite>user</cite> is just the name of the user account:</p>
<div class="highlight-python"><pre>---
- hosts: webservers
user: root</pre>
</div>
<p>Support for running things from sudo is also available:</p>
<div class="highlight-python"><pre>---
- hosts: webservers
user: yourname
sudo: True</pre>
</div>
<p>You can also login as you, and then sudo to different users than root:</p>
<div class="highlight-python"><pre>---
- hosts: webservers
user: yourname
sudo: True
sudo_user: postgres</pre>
</div>
<p>If you need to specify a password to sudo, run <cite>ansible-playbook</cite> with <tt class="docutils literal"><span class="pre">--ask-sudo-pass</span></tt> (<cite>-K</cite>).
If you run a sudo playbook and the playbook seems to hang, it&#8217;s probably stuck at the sudo prompt.
Just <cite>Control-C</cite> to kill it and run it again with <cite>-K</cite>.</p>
<div class="admonition important">
<p class="first admonition-title">Important</p>
<p class="last">When using <cite>sudo_user</cite> 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 &#8216;bob&#8217; to &#8216;timmy&#8217;, not
when going from &#8216;bob&#8217; to &#8216;root&#8217;, or logging in directly as &#8216;bob&#8217; or
&#8216;root&#8217;. If this concerns you that this data is briefly readable
(not writeable), avoid transferring uncrypted passwords with
<cite>sudo_user</cite> set. In other cases, &#8216;/tmp&#8217; is not used and this does
not come into play. Ansible also takes care to not log password
parameters.</p>
</div>
</div>
<div class="section" id="vars-section">
<h3>Vars section<a class="headerlink" href="#vars-section" title="Permalink to this headline"></a></h3>
<p>The <cite>vars</cite> section contains a list of variables and values that can be used in the plays, like this:</p>
<div class="highlight-python"><pre>---
- hosts: webservers
user: root
vars:
http_port: 80
van_halen_port: 5150
other: 'magic'</pre>
</div>
<p>These variables can be used later in the playbook like this:</p>
<div class="highlight-python"><pre>$varname or ${varname}</pre>
</div>
<p>The later is useful in the event you need to do something like ${other}_some_string.</p>
<p>Inside templates, the full power of the <a class="reference external" href="http://jinja.pocoo.org/docs/">Jinja2</a> templating language is also available, which looks like this:</p>
<div class="highlight-python"><pre>{{ varname }}</pre>
</div>
<p>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.</p>
<p>If there are discovered variables about the system, called &#8216;facts&#8217;, 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 &#8216;ansible&#8217;, and are documented under &#8216;setup&#8217; in the module documentation. Additionally,
facts can be gathered by ohai and facter if they are installed. Facter variables are prefixed with <tt class="docutils literal"><span class="pre">facter_</span></tt> and Ohai
variables are prefixed with <tt class="docutils literal"><span class="pre">ohai_</span></tt>.</p>
<p>So for instance, if I wanted
to write the hostname into the /etc/motd file, I could say:</p>
<div class="highlight-python"><pre>- name: write the motd
action: template src=/srv/templates/motd.j2 dest=/etc/motd</pre>
</div>
<p>And in /srv/templates/motd.j2:</p>
<div class="highlight-python"><pre>You are logged into {{ facter_hostname }}</pre>
</div>
<p>But we&#8217;re getting ahead of ourselves. Let&#8217;s talk about tasks.</p>
</div>
<div class="section" id="tasks-list">
<h3>Tasks list<a class="headerlink" href="#tasks-list" title="Permalink to this headline"></a></h3>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>Modules are &#8216;idempotent&#8217;, 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&#8217;t change things
unless they have to change things.</p>
<p>The <cite>command</cite> and <cite>shell</cite> modules will typically rerun the same command again,
which is totally ok if the command is something like
&#8216;chmod&#8217; or &#8216;setsebool&#8217;, etc. Though there is a &#8216;creates&#8217; flag available which can
be used to make these modules also idempotent.</p>
<p>Every task should have a <cite>name</cite>, 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 &#8216;action&#8217; will be used for
output.</p>
<p>Here is what a basic task looks like, as with most modules,
the service module takes key=value arguments:</p>
<div class="highlight-python"><pre>tasks:
- name: make sure apache is running
action: service name=httpd state=running</pre>
</div>
<p>The <cite>command</cite> and <cite>shell</cite> modules are the one modules that just takes a list
of arguments, and don&#8217;t use the key=value form. This makes
them work just like you would expect. Simple:</p>
<div class="highlight-python"><pre>tasks:
- name: disable selinux
action: command /sbin/setenforce 0</pre>
</div>
<p>The command and shell module care about return codes, so if you have a command
who&#8217;s successful exit code is not zero, you may wish to do this:</p>
<div class="highlight-python"><pre>tasks:
- name: run this command and ignore the result
action: shell /usr/bin/somecommand &amp; /bin/true</pre>
</div>
<p>Variables can be used in action lines. Suppose you defined
a variable called &#8216;vhost&#8217; in the &#8216;vars&#8217; section, you could do this:</p>
<div class="highlight-python"><pre>tasks:
- name: create a virtual host file for $vhost
action: template src=somefile.j2 dest=/etc/httpd/conf.d/$vhost</pre>
</div>
<p>Those same variables are usable in templates, which we&#8217;ll get to later.</p>
<p>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 &#8216;include:&#8217; directive. We&#8217;ll show that a bit later.</p>
</div>
</div>
<div class="section" id="running-operations-on-change">
<h2><a class="toc-backref" href="#contents">Running Operations On Change</a><a class="headerlink" href="#running-operations-on-change" title="Permalink to this headline"></a></h2>
<p>As we&#8217;ve mentioned, modules are written to be &#8216;idempotent&#8217; 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.</p>
<p>These &#8216;notify&#8217; actions are triggered at the end of each &#8216;play&#8217; 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.</p>
<p>Here&#8217;s an example of restarting two services when the contents of a file
change, but only if the file changes:</p>
<div class="highlight-python"><pre>- name: template configuration file
action: template src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache</pre>
</div>
<p>The things listed in the &#8216;notify&#8217; section of a task are called
handlers.</p>
<p>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.</p>
<p>Here&#8217;s an example handlers section:</p>
<div class="highlight-python"><pre>handlers:
- name: restart memcached
action: service name=memcached state=restarted
- name: restart apache
action: service name=apache state=restarted</pre>
</div>
<p>Handlers are best used to restart services and trigger reboots. You probably
won&#8217;t need them for much else.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Notify handlers are always run in the order written.</p>
</div>
</div>
<div class="section" id="include-files-and-encouraging-reuse">
<h2><a class="toc-backref" href="#contents">Include Files And Encouraging Reuse</a><a class="headerlink" href="#include-files-and-encouraging-reuse" title="Permalink to this headline"></a></h2>
<p>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&#8217;s see what this looks like...</p>
<p>A task include file simply contains a flat list of tasks, like so:</p>
<div class="highlight-python"><pre>---
# possibly saved as tasks/foo.yml
- name: placeholder foo
action: command /bin/foo
- name: placeholder bar
action: command /bin/bar</pre>
</div>
<p>Include directives look like this, and can be mixed in with regular tasks in a playbook:</p>
<div class="highlight-python"><pre>tasks:
- include: tasks/foo.yml</pre>
</div>
<p>You can also pass variables into includes. We call this a &#8216;parameterized include&#8217;.</p>
<p>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:</p>
<div class="highlight-python"><pre>tasks:
- include: wordpress.yml user=timmy
- include: wordpress.yml user=alice
- include: wordpress.yml user=bob</pre>
</div>
<p>Variables passed in can then be used in the included files. You can reference them like this:</p>
<div class="highlight-python"><pre>$user</pre>
</div>
<p>(In addition to the explicitly passed in parameters, all variables from
the vars section are also available for use here as well.)</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">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.</p>
</div>
<p>Includes can also be used in the &#8216;handlers&#8217; 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:</p>
<div class="highlight-python"><pre>----
# this might be in a file like handlers/handlers.yml
- name: restart apache
action: service name=apache state=restarted</pre>
</div>
<p>And in your main playbook file, just include it like so, at the bottom
of a play:</p>
<div class="highlight-python"><pre>handlers:
- include: handlers/handlers.yml</pre>
</div>
<p>You can mix in includes along with your regular non-included tasks and handlers.</p>
<p>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.</p>
<p>For example:</p>
<div class="highlight-python"><pre>- 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</pre>
</div>
<p>Note that you cannot do variable substitution when including one playbook
inside another.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">You can not conditionally path the location to an include file,
like you can with &#8216;vars_files&#8217;. 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 &#8216;fact&#8217; to
decide what include file to use. All hosts contained within the
play are going to get the same tasks. (&#8216;only_if&#8217; provides some
ability for hosts to conditionally skip tasks).</p>
</div>
</div>
<div class="section" id="executing-a-playbook">
<h2><a class="toc-backref" href="#contents">Executing A Playbook</a><a class="headerlink" href="#executing-a-playbook" title="Permalink to this headline"></a></h2>
<p>Now that you&#8217;ve learned playbook syntax, how do you run a playbook? It&#8217;s simple.
Let&#8217;s run a playbook using a parallelism level of 10:</p>
<div class="highlight-python"><pre>ansible-playbook playbook.yml -f 10</pre>
</div>
</div>
<div class="section" id="tips-and-tricks">
<h2><a class="toc-backref" href="#contents">Tips and Tricks</a><a class="headerlink" href="#tips-and-tricks" title="Permalink to this headline"></a></h2>
<p>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 &#8220;unreachable&#8221; communication attempts are
kept seperate in the counts.</p>
<p>If you ever want to see detailed output from successful modules as well as unsuccessful ones,
use the &#8216;&#8211;verbose&#8217; flag. This is available in Ansible 0.5 and later.</p>
<p>Also, in version 0.5 and later, Ansible playbook output is vastly upgraded if the cowsay
package is installed. Try it!</p>
<p>In version 0.7 and later, to see what hosts would be affected by a playbook before you run it, you
can do this:</p>
<div class="highlight-python"><pre>ansible-playbook playbook.yml --list-hosts.</pre>
</div>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="YAMLSyntax.html"><em>YAML Syntax</em></a></dt>
<dd>Learn about YAML syntax</dd>
<dt><a class="reference internal" href=""><em>Playbooks</em></a></dt>
<dd>Review the basic Playbook language features</dd>
<dt><a class="reference internal" href="playbooks2.html"><em>Advanced Playbooks</em></a></dt>
<dd>Learn about Advanced Playbook Features</dd>
<dt><a class="reference internal" href="bestpractices.html"><em>Best Practices</em></a></dt>
<dd>Various tips about managing playbooks in the real world</dd>
<dt><a class="reference internal" href="modules.html"><em>Ansible Modules</em></a></dt>
<dd>Learn about available modules</dd>
<dt><a class="reference internal" href="moduledev.html"><em>Module Development</em></a></dt>
<dd>Learn how to extend Ansible by writing your own modules</dd>
<dt><a class="reference internal" href="patterns.html"><em>Inventory &amp; Patterns</em></a></dt>
<dd>Learn about how to select hosts</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/tree/devel/examples/playbooks">Github examples directory</a></dt>
<dd>Complete playbook files from the github project source</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,723 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Advanced Playbooks &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<link rel="next" title="Best Practices" href="bestpractices.html" />
<link rel="prev" title="Playbooks" href="playbooks.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Advanced Playbooks</a><ul>
<li><a class="reference internal" href="#tags">Tags</a></li>
<li><a class="reference internal" href="#playbooks-including-playbooks">Playbooks Including Playbooks</a></li>
<li><a class="reference internal" href="#ignoring-failed-commands">Ignoring Failed Commands</a></li>
<li><a class="reference internal" href="#accessing-complex-variable-data">Accessing Complex Variable Data</a></li>
<li><a class="reference internal" href="#accessing-information-about-other-hosts">Accessing Information About Other Hosts</a></li>
<li><a class="reference internal" href="#variable-file-seperation">Variable File Seperation</a></li>
<li><a class="reference internal" href="#prompting-for-sensitive-data">Prompting For Sensitive Data</a></li>
<li><a class="reference internal" href="#passing-variables-on-the-command-line">Passing Variables On The Command Line</a></li>
<li><a class="reference internal" href="#conditional-execution">Conditional Execution</a></li>
<li><a class="reference internal" href="#conditional-imports">Conditional Imports</a></li>
<li><a class="reference internal" href="#loops">Loops</a></li>
<li><a class="reference internal" href="#selecting-files-and-templates-based-on-variables">Selecting Files And Templates Based On Variables</a></li>
<li><a class="reference internal" href="#asynchronous-actions-and-polling">Asynchronous Actions and Polling</a></li>
<li><a class="reference internal" href="#local-playbooks">Local Playbooks</a></li>
<li><a class="reference internal" href="#turning-off-facts">Turning Off Facts</a></li>
<li><a class="reference internal" href="#pull-mode-playbooks">Pull-Mode Playbooks</a></li>
<li><a class="reference internal" href="#register-variables">Register Variables</a></li>
<li><a class="reference internal" href="#rolling-updates">Rolling Updates</a></li>
<li><a class="reference internal" href="#delegation">Delegation</a></li>
<li><a class="reference internal" href="#understanding-variable-precedence">Understanding Variable Precedence</a></li>
<li><a class="reference internal" href="#style-points">Style Points</a></li>
</ul>
</li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="section" id="advanced-playbooks">
<h1><a class="toc-backref" href="#contents">Advanced Playbooks</a><a class="headerlink" href="#advanced-playbooks" title="Permalink to this headline"></a></h1>
<p>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&#8217;t seem immediately
relevant, feel free to skip it. For many people, the features documented in <cite>playbooks</cite> will
be 90% or more of what they use in Ansible.</p>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#advanced-playbooks" id="id1">Advanced Playbooks</a><ul>
<li><a class="reference internal" href="#tags" id="id2">Tags</a></li>
<li><a class="reference internal" href="#playbooks-including-playbooks" id="id3">Playbooks Including Playbooks</a></li>
<li><a class="reference internal" href="#ignoring-failed-commands" id="id4">Ignoring Failed Commands</a></li>
<li><a class="reference internal" href="#accessing-complex-variable-data" id="id5">Accessing Complex Variable Data</a></li>
<li><a class="reference internal" href="#accessing-information-about-other-hosts" id="id6">Accessing Information About Other Hosts</a></li>
<li><a class="reference internal" href="#variable-file-seperation" id="id7">Variable File Seperation</a></li>
<li><a class="reference internal" href="#prompting-for-sensitive-data" id="id8">Prompting For Sensitive Data</a></li>
<li><a class="reference internal" href="#passing-variables-on-the-command-line" id="id9">Passing Variables On The Command Line</a></li>
<li><a class="reference internal" href="#conditional-execution" id="id10">Conditional Execution</a></li>
<li><a class="reference internal" href="#conditional-imports" id="id11">Conditional Imports</a></li>
<li><a class="reference internal" href="#loops" id="id12">Loops</a></li>
<li><a class="reference internal" href="#selecting-files-and-templates-based-on-variables" id="id13">Selecting Files And Templates Based On Variables</a></li>
<li><a class="reference internal" href="#asynchronous-actions-and-polling" id="id14">Asynchronous Actions and Polling</a></li>
<li><a class="reference internal" href="#local-playbooks" id="id15">Local Playbooks</a></li>
<li><a class="reference internal" href="#turning-off-facts" id="id16">Turning Off Facts</a></li>
<li><a class="reference internal" href="#pull-mode-playbooks" id="id17">Pull-Mode Playbooks</a></li>
<li><a class="reference internal" href="#register-variables" id="id18">Register Variables</a></li>
<li><a class="reference internal" href="#rolling-updates" id="id19">Rolling Updates</a></li>
<li><a class="reference internal" href="#delegation" id="id20">Delegation</a></li>
<li><a class="reference internal" href="#understanding-variable-precedence" id="id21">Understanding Variable Precedence</a></li>
<li><a class="reference internal" href="#style-points" id="id22">Style Points</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="tags">
<h2><a class="toc-backref" href="#contents">Tags</a><a class="headerlink" href="#tags" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.6.</span></p>
<p>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
&#8220;tags:&#8221; attribute for this reason.</p>
<p>Example:</p>
<div class="highlight-python"><pre>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</pre>
</div>
<p>If you wanted to just run the &#8220;configuration&#8221; and &#8220;packages&#8221; part of a very long playbook, you could do this:</p>
<div class="highlight-python"><pre>ansible-playbook example.yml --tags "configuration,packages"</pre>
</div>
</div>
<div class="section" id="playbooks-including-playbooks">
<h2><a class="toc-backref" href="#contents">Playbooks Including Playbooks</a><a class="headerlink" href="#playbooks-including-playbooks" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.6.</span></p>
<p>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 &#8220;webservers.yml&#8221; and all your database servers in
&#8220;dbservers.yml&#8221;. You can create a &#8220;site.yml&#8221; that would reconfigure
all of your systems like this:</p>
<div class="highlight-python"><pre>----
- include: playbooks/webservers.yml
- include: playbooks/dbservers.yml</pre>
</div>
<p>This concept works great with tags to rapidly select exactly what plays you want to run, and exactly
what parts of those plays.</p>
</div>
<div class="section" id="ignoring-failed-commands">
<h2><a class="toc-backref" href="#contents">Ignoring Failed Commands</a><a class="headerlink" href="#ignoring-failed-commands" title="Permalink to this headline"></a></h2>
<p class="deprecated">
<span class="versionmodified">Deprecated since version 0.6.</span></p>
<p>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:</p>
<div class="highlight-python"><pre>- name: this will not be counted as a failure
action: command /bin/false
ignore_errors: True</pre>
</div>
</div>
<div class="section" id="accessing-complex-variable-data">
<h2><a class="toc-backref" href="#contents">Accessing Complex Variable Data</a><a class="headerlink" href="#accessing-complex-variable-data" title="Permalink to this headline"></a></h2>
<p>Some provided facts, like networking information, are made available as nested data structures. To access
them a simple &#8216;$foo&#8217; is not sufficient, but it is still easy to do. Here&#8217;s how we get an IP address:</p>
<div class="highlight-python"><pre>${ansible_eth0.ipv4.address}</pre>
</div>
<p>It is also possible to access variables whose elements are arrays:</p>
<div class="highlight-python"><pre>${somelist[0]}</pre>
</div>
<p>And the array and hash reference syntaxes can be mixed.</p>
<p>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:</p>
<div class="highlight-python"><pre>{{ ansible_eth0["ipv4"]["address"] }}</pre>
</div>
</div>
<div class="section" id="accessing-information-about-other-hosts">
<h2><a class="toc-backref" href="#contents">Accessing Information About Other Hosts</a><a class="headerlink" href="#accessing-information-about-other-hosts" title="Permalink to this headline"></a></h2>
<p>If your database server wants to check the value of a &#8216;fact&#8217; from another node, or an inventory variable
assigned to another node, it&#8217;s easy to do so within a template or even an action line:</p>
<div class="highlight-python"><pre>${hostvars.hostname.factname}</pre>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">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.</p>
</div>
<p>Additionally, <em>group_names</em> 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:</p>
<div class="highlight-python"><pre>{% if 'webserver' in group_names %}
# some part of a configuration file that only applies to webservers
{% endif %}</pre>
</div>
<p><em>groups</em> 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:</p>
<div class="highlight-python"><pre>{% for host in groups['app_servers'] %}
# something that applies to all app servers.
{% endfor %}</pre>
</div>
<p>Use cases include pointing a frontend proxy server to all of the app servers, setting up the correct firewall rules between servers, etc.</p>
<p><em>inventory_hostname</em> is the name of the hostname as configured in Ansible&#8217;s inventory host file. This can
be useful for when you don&#8217;t want to rely on the discovered hostname <cite>ansible_hostname</cite> or for other mysterious
reasons. If you have a long FQDN, <em>inventory_hostname_short</em> (in Ansible 0.6) also contains the part up to the first
period.</p>
<p>Don&#8217;t worry about any of this unless you think you need it. You&#8217;ll know when you do.</p>
</div>
<div class="section" id="variable-file-seperation">
<h2><a class="toc-backref" href="#contents">Variable File Seperation</a><a class="headerlink" href="#variable-file-seperation" title="Permalink to this headline"></a></h2>
<p>It&#8217;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.</p>
<p>You can do this by using an external variables file, or files, just like this:</p>
<div class="highlight-python"><pre>---
- 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</pre>
</div>
<p>This removes the risk of sharing sensitive data with others when
sharing your playbook source with them.</p>
<p>The contents of each variables file is a simple YAML dictionary, like this:</p>
<div class="highlight-python"><pre>---
# in the above example, this would be vars/external_vars.yml
somevar: somevalue
password: magic</pre>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">It&#8217;s also possible to keep per-host and per-group variables in very
similar files, this is covered in <a class="reference internal" href="patterns.html#patterns"><em>Inventory &amp; Patterns</em></a>.</p>
</div>
</div>
<div class="section" id="prompting-for-sensitive-data">
<h2><a class="toc-backref" href="#contents">Prompting For Sensitive Data</a><a class="headerlink" href="#prompting-for-sensitive-data" title="Permalink to this headline"></a></h2>
<p>You may wish to prompt the user for certain input, and can
do so with the similarly named &#8216;vars_prompt&#8217; 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:</p>
<div class="highlight-python"><pre>---
- 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?"</pre>
</div>
<p>There are full examples of both of these items in the github examples/playbooks directory.</p>
<p>An alternative form of vars_prompt allows for hiding input from the user, and may later support
some other options, but otherwise works equivalently:</p>
<div class="highlight-python"><pre>vars_prompt:
- name: "some_password"
prompt: "Enter password"
private: True
- name: "release_version"
prompt: "Product release version"
private: False</pre>
</div>
</div>
<div class="section" id="passing-variables-on-the-command-line">
<h2><a class="toc-backref" href="#contents">Passing Variables On The Command Line</a><a class="headerlink" href="#passing-variables-on-the-command-line" title="Permalink to this headline"></a></h2>
<p>In addition to <cite>vars_prompt</cite> and <cite>vars_files</cite>, 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:</p>
<div class="highlight-python"><pre>ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"</pre>
</div>
<p>This is useful, for, among other things, setting the hosts group or the user for the playbook.</p>
<p>Example:</p>
<div class="highlight-python"><pre>-----
- user: $user
hosts: $hosts
tasks:
- ...
ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"</pre>
</div>
</div>
<div class="section" id="conditional-execution">
<h2><a class="toc-backref" href="#contents">Conditional Execution</a><a class="headerlink" href="#conditional-execution" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p>This is easy to do in Ansible, with the <cite>only_if</cite> clause, which actually is a Python expression.
Don&#8217;t panic &#8211; it&#8217;s actually pretty simple:</p>
<div class="highlight-python"><pre>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'</pre>
</div>
<p>Variables from tools like <cite>facter</cite> and <cite>ohai</cite> can be used here, if installed, or you can
use variables that bubble up from ansible, which many are provided by the <a class="reference internal" href="modules.html#setup"><em>setup</em></a> module. As a reminder,
these variables are prefixed, so it&#8217;s <cite>$facter_operatingsystem</cite>, not <cite>$operatingsystem</cite>. Ansible&#8217;s
built in variables are prefixed with <cite>ansible_</cite>.</p>
<p>The only_if expression is actually a tiny small bit of Python, so be sure to quote variables and make something
that evaluates to <cite>True</cite> or <cite>False</cite>. It is a good idea to use &#8216;vars_files&#8217; instead of &#8216;vars&#8217; to define
all of your conditional expressions in a way that makes them very easy to reuse between plays
and playbooks.</p>
<p>You cannot use live checks here, like &#8216;os.path.exists&#8217;, so don&#8217;t try.</p>
<p>It&#8217;s also easy to provide your own facts if you want, which is covered in <a class="reference internal" href="moduledev.html"><em>Module Development</em></a>. 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:</p>
<div class="highlight-python"><pre>tasks:
- name: gather site specific fact data
action: site_facts
- action: command echo ${my_custom_fact_can_be_used_now}</pre>
</div>
</div>
<div class="section" id="conditional-imports">
<h2><a class="toc-backref" href="#contents">Conditional Imports</a><a class="headerlink" href="#conditional-imports" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p>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:</p>
<div class="highlight-python"><pre>---
- 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</pre>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">The variable (<cite>$facter_operatingsystem</cite>) is being interpolated into
the list of filenames being defined for vars_files.</p>
</div>
<p>As a reminder, the various YAML files contain just keys and values:</p>
<div class="highlight-python"><pre>---
# for vars/CentOS.yml
apache: httpd
somethingelse: 42</pre>
</div>
<p>How does this work? If the operating system was &#8216;CentOS&#8217;, the first file Ansible would try to import
would be &#8216;vars/CentOS.yml&#8217;, followed up by &#8216;/vars/os_defaults.yml&#8217; 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 &#8216;vars/Debian.yml&#8217; instead of &#8216;vars/CentOS.yml&#8217;, before
falling back on &#8216;vars/os_defaults.yml&#8217;. Pretty simple.</p>
<p>To use this conditional import feature, you&#8217;ll need facter or ohai installed prior to running the playbook, but
you can of course push this out with Ansible if you like:</p>
<div class="highlight-python"><pre># 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"</pre>
</div>
<p>Ansible&#8217;s approach to configuration &#8211; 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 &amp; auditable configuration rules &#8211; especially because there are a
minimum of decision points to track.</p>
</div>
<div class="section" id="loops">
<h2><a class="toc-backref" href="#contents">Loops</a><a class="headerlink" href="#loops" title="Permalink to this headline"></a></h2>
<p>To save some typing, repeated tasks can be written in short-hand like so:</p>
<div class="highlight-python"><pre>- name: add user $item
action: user name=$item state=present groups=wheel
with_items:
- testuser1
- testuser2</pre>
</div>
<p>If you have defined a YAML list in a variables file, or the &#8216;vars&#8217; section, you can also do:</p>
<div class="highlight-python"><pre>with_items: $somelist</pre>
</div>
<p>The above would be the equivalent of:</p>
<div class="highlight-python"><pre>- name: add user testuser1
action: user name=testuser1 state=present groups=wheel
- name: add user testuser2
action: user name=testuser2 state=present groups=wheel</pre>
</div>
<p>The yum and apt modules use with_items to execute fewer package manager transactions.</p>
</div>
<div class="section" id="selecting-files-and-templates-based-on-variables">
<h2><a class="toc-backref" href="#contents">Selecting Files And Templates Based On Variables</a><a class="headerlink" href="#selecting-files-and-templates-based-on-variables" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p>The following example shows how to template out a configuration file that was very different between, say,
CentOS and Debian:</p>
<div class="highlight-python"><pre>- 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</pre>
</div>
</div>
<div class="section" id="asynchronous-actions-and-polling">
<h2><a class="toc-backref" href="#contents">Asynchronous Actions and Polling</a><a class="headerlink" href="#asynchronous-actions-and-polling" title="Permalink to this headline"></a></h2>
<p>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 <tt class="docutils literal"><span class="pre">--forks</span></tt>), 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.</p>
<p>You will also want to use asynchronous mode on very long running
operations that might be subject to timeout.</p>
<p>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 <cite>poll</cite>:</p>
<div class="highlight-python"><pre>---
- 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</pre>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">There is no default for the async time limit. If you leave off the
&#8216;async&#8217; keyword, the task runs synchronously, which is Ansible&#8217;s
default.</p>
</div>
<p>Alternatively, if you do not need to wait on the task to complete, you may
&#8220;fire and forget&#8221; by specifying a poll value of 0:</p>
<div class="highlight-python"><pre>---
- 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</pre>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">You shouldn&#8217;t &#8220;fire and forget&#8221; 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.</p>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Using a higher value for <tt class="docutils literal"><span class="pre">--forks</span></tt> will result in kicking off asynchronous
tasks even faster. This also increases the efficiency of polling.</p>
</div>
</div>
<div class="section" id="local-playbooks">
<h2><a class="toc-backref" href="#contents">Local Playbooks</a><a class="headerlink" href="#local-playbooks" title="Permalink to this headline"></a></h2>
<p>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.</p>
<p>To run an entire playbook locally, just set the &#8220;hosts:&#8221; line to &#8220;hosts:127.0.0.1&#8221; and then run the playbook like so:</p>
<div class="highlight-python"><pre>ansible-playbook playbook.yml --connection=local</pre>
</div>
<p>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:</p>
<div class="highlight-python"><pre>hosts: 127.0.0.1
connection: local</pre>
</div>
</div>
<div class="section" id="turning-off-facts">
<h2><a class="toc-backref" href="#contents">Turning Off Facts</a><a class="headerlink" href="#turning-off-facts" title="Permalink to this headline"></a></h2>
<p>If you know you don&#8217;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:</p>
<div class="highlight-python"><pre>- hosts: whatever
gather_facts: False</pre>
</div>
</div>
<div class="section" id="pull-mode-playbooks">
<h2><a class="toc-backref" href="#contents">Pull-Mode Playbooks</a><a class="headerlink" href="#pull-mode-playbooks" title="Permalink to this headline"></a></h2>
<p>The use of playbooks in local mode (above) is made extremely powerful with the addition of <cite>ansible-pull</cite>.
A script for setting up ansible-pull is provided in the examples/playbooks directory of the source
checkout.</p>
<p>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.</p>
<p>This is useful both for extreme scale-out as well as periodic remediation. Usage of the &#8216;fetch&#8217; module to retrieve
logs from ansible-pull runs would be an excellent way to gather and analyze remote logs from ansible-pull.</p>
</div>
<div class="section" id="register-variables">
<h2><a class="toc-backref" href="#contents">Register Variables</a><a class="headerlink" href="#register-variables" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.7.</span></p>
<p>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.</p>
<p>The &#8216;register&#8217; 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):</p>
<div class="highlight-python"><pre>- 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"</pre>
</div>
</div>
<div class="section" id="rolling-updates">
<h2><a class="toc-backref" href="#contents">Rolling Updates</a><a class="headerlink" href="#rolling-updates" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.7.</span></p>
<p>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 &#8216;&#8217;serial&#8217;&#8217; keyword:</p>
<div class="highlight-python"><pre>- name: test play
hosts: webservers
serial: 3</pre>
</div>
<p>In the above example, if we had 100 hosts, 3 hosts in the group &#8216;webservers&#8217;
would complete the play completely before moving on to the next 3 hosts.</p>
</div>
<div class="section" id="delegation">
<h2><a class="toc-backref" href="#contents">Delegation</a><a class="headerlink" href="#delegation" title="Permalink to this headline"></a></h2>
<p class="versionadded">
<span class="versionmodified">New in version 0.7.</span></p>
<p>If you want to perform a task on one host with reference to other hosts, use the &#8216;delegate_to&#8217; 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 &#8216;serial&#8217; keyword to control the number of hosts executing at one time is also
a good idea:</p>
<div class="highlight-python"><pre>---
- 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</pre>
</div>
<p>Here is the same playbook as above, but using the shorthand syntax,
&#8216;local_action&#8217;, for delegating to 127.0.0.1:</p>
<div class="highlight-python"><pre>---
# ...
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</pre>
</div>
</div>
<div class="section" id="understanding-variable-precedence">
<h2><a class="toc-backref" href="#contents">Understanding Variable Precedence</a><a class="headerlink" href="#understanding-variable-precedence" title="Permalink to this headline"></a></h2>
<p>You have already learned about inventory host and group variables, &#8216;vars&#8217;, and &#8216;vars_files&#8217;.</p>
<p>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.</p>
<ol class="arabic simple">
<li>Variables loaded from YAML files mentioned in &#8216;vars_files&#8217; in a playbook.</li>
<li>&#8216;vars&#8217; as defined in the playbook.</li>
<li>facts, whether built in or custom, or variables assigned from the &#8216;register&#8217; keyword.</li>
<li>variables passed to parameterized task include statements.</li>
<li>Host variables from inventory.</li>
<li>Group variables from inventory, in order of least specific group to most specific.</li>
</ol>
<p>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.</p>
</div>
<div class="section" id="style-points">
<h2><a class="toc-backref" href="#contents">Style Points</a><a class="headerlink" href="#style-points" title="Permalink to this headline"></a></h2>
<p>Ansible playbooks are colorized. If you do not like this, set the ANSIBLE_NOCOLOR=1 environment variable.</p>
<p>Ansible playbooks also look more impressive with cowsay installed, and we encourage installing this package.</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference internal" href="YAMLSyntax.html"><em>YAML Syntax</em></a></dt>
<dd>Learn about YAML syntax</dd>
<dt><a class="reference internal" href="playbooks.html"><em>Playbooks</em></a></dt>
<dd>Review the basic playbook features</dd>
<dt><a class="reference internal" href="bestpractices.html"><em>Best Practices</em></a></dt>
<dd>Various tips about playbooks in the real world</dd>
<dt><a class="reference internal" href="modules.html"><em>Ansible Modules</em></a></dt>
<dd>Learn about available modules</dd>
<dt><a class="reference internal" href="moduledev.html"><em>Module Development</em></a></dt>
<dd>Learn how to extend Ansible by writing your own modules</dd>
<dt><a class="reference internal" href="patterns.html"><em>Inventory &amp; Patterns</em></a></dt>
<dd>Learn about how to select hosts</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/tree/devel/examples/playbooks">Github examples directory</a></dt>
<dd>Complete playbook files from the github project source</dd>
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Questions? Help? Ideas? Stop by the list on Google Groups</dd>
</dl>
</div>
</div>
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,191 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Search &mdash; Ansible Documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/searchtools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible Documentation" href="index.html" />
<script type="text/javascript">
jQuery(function() { Search.loadIndex("searchindex.js"); });
</script>
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<a class="brand" href="index.html">Ansible Documentation</a>
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul>
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"></span>
</li>
</ul>
<ul class="nav secondary-nav">
</ul>
</div>
</div>
</div>
<div class="container">
<h1 id="search-documentation">Search</h1>
<div id="fallback" class="admonition warning">
<script type="text/javascript">$('#fallback').hide();</script>
<p>
Please activate JavaScript to enable the search
functionality.
</p>
</div>
<p>
From here you can search these documents. Enter your search
words into the box below and click "search". Note that the search
function will automatically search for all of the words. Pages
containing fewer words won't appear in the result list.
</p>
<form action="" method="get">
<input type="text" name="q" value="" />
<input type="submit" value="search" />
<span id="search-progress" style="padding-left: 10px"></span>
</form>
<div id="search-results">
</div>
<br/>
</div>
<footer class="footer">
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Oct 10, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>

View file

@ -1,267 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Who Uses Ansible &mdash; Ansible - SSH-Based Configuration Management &amp; Deployment</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.01',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: false
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/bootstrap-dropdown.js"></script>
<script type="text/javascript" src="_static/bootstrap-scrollspy.js"></script>
<link rel="shortcut icon" href="_static/favicon.ico"/>
<link rel="top" title="Ansible - SSH-Based Configuration Management &amp; Deployment" href="index.html" />
<script type="text/javascript">
(function () {
/**
* Patch TOC list.
*
* Will mutate the underlying span to have a correct ul for nav.
*
* @param $span: Span containing nested UL's to mutate.
* @param minLevel: Starting level for nested lists. (1: global, 2: local).
*/
var patchToc = function ($span, minLevel) {
var $tocList = $("<ul/>").attr('class', "dropdown-menu"),
findA;
// Find all a "internal" tags, traversing recursively.
findA = function ($elem, level) {
var level = level || 0,
$items = $elem.find("> li > a.internal, > ul, > li > ul");
// Iterate everything in order.
$items.each(function (index, item) {
var $item = $(item),
tag = item.tagName.toLowerCase(),
pad = 10 + ((level - minLevel) * 10);
if (tag === 'a' && level >= minLevel) {
// Add to existing padding.
$item.css('padding-left', pad + "px");
// Add list element.
$tocList.append($("<li/>").append($item));
} else if (tag === 'ul') {
// Recurse.
findA($item, level + 1);
}
});
};
// Start construction and return.
findA($span);
// Wipe out old list and patch in new one.
return $span.empty("ul").append($tocList);
};
$(document).ready(function () {
// Patch the global and local TOC's to be bootstrap-compliant.
patchToc($("span.globaltoc"), 1);
patchToc($("span.localtoc"), 2);
// Activate.
$('#topbar').dropdown();
});
}());
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-29861888-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' :
'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</head>
<body>
<div class="topbar" data-scrollspy="scrollspy" >
<div class="topbar-inner">
<div class="container">
<!-- <a class="brand" href="index.html">Ansible</a> -->
<ul class="nav">
<li><a href="/">Home</A>
<li class="dropdown" data-dropdown="dropdown">
<a href="index.html"
class="dropdown-toggle">Chapter</a>
<span class="globaltoc"><ul>
<li class="toctree-l1"><a class="reference internal" href="gettingstarted.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="patterns.html">Inventory &amp; Patterns</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples.html">Command Line Examples And Next Steps</a></li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">Ansible Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="YAMLSyntax.html">YAML Syntax</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks.html">Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="playbooks2.html">Advanced Playbooks</a></li>
<li class="toctree-l1"><a class="reference internal" href="bestpractices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API &amp; Integrations</a></li>
<li class="toctree-l1"><a class="reference internal" href="moduledev.html">Module Development</a></li>
</ul>
</span>
</li>
<li class="dropdown" data-dropdown="dropdown">
<a href="#"
class="dropdown-toggle">Page</a>
<span class="localtoc"><ul>
<li><a class="reference internal" href="#">Who Uses Ansible</a></li>
</ul>
</span>
</li>
</ul>
<ul class="nav secondary-nav">
<form class="pull-left" action="search.html" method="get">
<input type="text" name="q" placeholder="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</ul>
</div>
</div>
</div>
<h1>Ansible Documentation</h1>
<div class="container">
<a href="http://ansible.github.com"><img src="http://ansible.github.com/ansible-logo.png" alt="Ansible"/></a><br/>
<br/>
<div class="section" id="who-uses-ansible">
<h1>Who Uses Ansible<a class="headerlink" href="#who-uses-ansible" title="Permalink to this headline"></a></h1>
<p>Ansible is used by all sorts of organizations from hosted web applications, media companies, universities, consultancies, and ISVs &#8211; all over the world. Some of these users include:</p>
<table border="1" class="docutils">
<colgroup>
<col width="64%" />
<col width="36%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Who They Are</th>
<th class="head">What They Do</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><a class="reference external" href="http://www.altalang.com">Alta Language Services</a></td>
<td>Language testing, solutions, and translation services</td>
</tr>
<tr class="row-odd"><td><a class="reference external" href="http://basho.com">Basho</a></td>
<td>Makers of NoSQL key-value store Riak</td>
</tr>
<tr class="row-even"><td><a class="reference external" href="http://catn.com">CatN Hosting</a></td>
<td>Scalable Cloud Hosting</td>
</tr>
<tr class="row-odd"><td><a class="reference external" href="http://cygate.se">Cygate AB</a></td>
<td>IT solutions from Malmö, Sweden</td>
</tr>
<tr class="row-even"><td><a class="reference external" href="http://dagit.net">Dag IT Solutions</a></td>
<td>&#8220;Enterprise Linux and Beyond&#8221;</td>
</tr>
<tr class="row-odd"><td><a class="reference external" href="http://duke.edu">Duke University Economics</a></td>
<td>Research and Education</td>
</tr>
<tr class="row-even"><td><a class="reference external" href="http://fedoraproject.org">The Fedora Project</a></td>
<td>Produces the popular Linux distribution</td>
</tr>
<tr class="row-odd"><td><a class="reference external" href="http://fourkitchens.com">Four Kitchens</a></td>
<td>&#8220;The Drupal Experts&#8221;</td>
</tr>
<tr class="row-even"><td><a class="reference external" href="http://lizenzfrei.at/">Lizenzfrei</a></td>
<td>Open source consulting and development, Austria</td>
</tr>
<tr class="row-odd"><td><a class="reference external" href="http://www.schmoozecom.com/">Schmooze Com</a></td>
<td>Creators of Industry-Leading PBX Platforms</td>
</tr>
<tr class="row-even"><td><a class="reference external" href="http://www.grid.auth.gr/en/">Scientific Computing Center, Aristotle Univ. of Thessaloniki</a></td>
<td>Grid/Cloud-Based Scientific Computing</td>
</tr>
<tr class="row-odd"><td><a class="reference external" href="http://skylin.es">Skyline.es</a></td>
<td>Realtime Photo Search Engine</td>
</tr>
<tr class="row-even"><td><a class="reference external" href="http://steelhouse.com">Steelhouse</a></td>
<td>Behavioral Commerce</td>
</tr>
<tr class="row-odd"><td><a class="reference external" href="http://www.t-f-t.net/">Tomorrow Focus Technologies GmbH</a></td>
<td>Running some of the biggest web sites in Europe</td>
</tr>
<tr class="row-even"><td><a class="reference external" href="http://123i.com.br">123i.com.br</a></td>
<td>Find real estate in Brazil</td>
</tr>
</tbody>
</table>
<p>and lots of other people (you should see our Google Analytics data). Tweet at <a class="reference external" href="http://twitter.com/laserllama">Michael DeHaan</a> or <a class="reference external" href="mailto:michael&#46;dehaan&#37;&#52;&#48;gmail&#46;com">email him</a> to get your company or project listed here. (It&#8217;s free!)</p>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="last docutils">
<dt><a class="reference external" href="http://groups.google.com/group/ansible-project">Mailing List</a></dt>
<dd>Several hundred of our closest friends, great for Q&amp;A</dd>
<dt><a class="reference external" href="http://irc.freenode.net">irc.freenode.net</a></dt>
<dd>#ansible IRC chat channel</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/graphs/contributors">List of Github Contributors</a></dt>
<dd>all the awesome folks who have contributed improvements to Ansible</dd>
<dt><a class="reference external" href="https://github.com/ansible/ansible/graphs/impact">Github Impact Graphs</a></dt>
<dd>week-to-week source code activity, by contributor</dd>
</dl>
</div>
</div>
<br/>
</div>
<footer class="footer">
<div class="container">
<p>
<p>
&copy; Copyright 2012 Michael DeHaan.<br/>
Last updated on Sep 23, 2012.<br/>
</p>
</div>
</footer>
</body>
</html>