summaryrefslogtreecommitdiff
path: root/docsite
diff options
context:
space:
mode:
Diffstat (limited to 'docsite')
-rw-r--r--docsite/Makefile4
-rw-r--r--docsite/_themes/srtd/footer.html11
-rw-r--r--docsite/_themes/srtd/layout.html38
-rw-r--r--docsite/_themes/srtd/layout_old.html205
-rw-r--r--docsite/_themes/srtd/searchbox.html61
-rw-r--r--docsite/_themes/srtd/static/css/theme.css21
-rw-r--r--docsite/_themes/srtd/static/images/banner_ad_1.pngbin4510 -> 0 bytes
-rw-r--r--docsite/_themes/srtd/static/images/banner_ad_2.pngbin4951 -> 0 bytes
-rwxr-xr-xdocsite/build-site.py23
-rw-r--r--docsite/rst/YAMLSyntax.rst55
-rw-r--r--docsite/rst/become.rst14
-rw-r--r--docsite/rst/developing.rst1
-rw-r--r--docsite/rst/developing_api.rst76
-rw-r--r--docsite/rst/developing_modules.rst31
-rw-r--r--docsite/rst/developing_releases.rst48
-rw-r--r--docsite/rst/developing_test_pr.rst29
-rw-r--r--docsite/rst/faq.rst2
-rw-r--r--docsite/rst/galaxy.rst340
-rw-r--r--docsite/rst/guide_cloudstack.rst4
-rw-r--r--docsite/rst/guide_vagrant.rst149
-rw-r--r--docsite/rst/index.rst1
-rw-r--r--docsite/rst/intro_adhoc.rst8
-rw-r--r--docsite/rst/intro_bsd.rst2
-rw-r--r--docsite/rst/intro_configuration.rst25
-rw-r--r--docsite/rst/intro_dynamic_inventory.rst76
-rw-r--r--docsite/rst/intro_getting_started.rst2
-rw-r--r--docsite/rst/intro_installation.rst13
-rw-r--r--docsite/rst/intro_patterns.rst2
-rw-r--r--docsite/rst/intro_windows.rst32
-rw-r--r--docsite/rst/modules_core.rst2
-rw-r--r--docsite/rst/playbooks_best_practices.rst4
-rw-r--r--docsite/rst/playbooks_conditionals.rst2
-rw-r--r--docsite/rst/playbooks_delegation.rst32
-rw-r--r--docsite/rst/playbooks_environment.rst2
-rw-r--r--docsite/rst/playbooks_filters.rst47
-rw-r--r--docsite/rst/playbooks_intro.rst3
-rw-r--r--docsite/rst/playbooks_lookups.rst106
-rw-r--r--docsite/rst/playbooks_loops.rst31
-rw-r--r--docsite/rst/playbooks_roles.rst15
-rw-r--r--docsite/rst/playbooks_variables.rst6
-rw-r--r--docsite/rst/porting_guide_2.0.rst183
41 files changed, 1170 insertions, 536 deletions
diff --git a/docsite/Makefile b/docsite/Makefile
index 92129f7851..2b87827c59 100644
--- a/docsite/Makefile
+++ b/docsite/Makefile
@@ -20,6 +20,8 @@ viewdocs: clean staticmin
htmldocs: staticmin
./build-site.py rst
+webdocs: htmldocs
+
clean:
-rm -rf htmlout
-rm -f .buildinfo
@@ -43,4 +45,4 @@ modules: $(FORMATTER) ../hacking/templates/rst.j2
PYTHONPATH=../lib $(FORMATTER) -t rst --template-dir=../hacking/templates --module-dir=../lib/ansible/modules -o rst/
staticmin:
- cat _themes/srtd/static/css/theme.css | sed -e 's/^[ \t]*//g; s/[ \t]*$$//g; s/\([:{;,]\) /\1/g; s/ {/{/g; s/\/\*.*\*\///g; /^$$/d' | sed -e :a -e '$$!N; s/\n\(.\)/\1/; ta' > _themes/srtd/static/css/theme.min.css
+ cat _themes/srtd/static/css/theme.css | sed -e 's/^[ ]*//g; s/[ ]*$$//g; s/\([:{;,]\) /\1/g; s/ {/{/g; s/\/\*.*\*\///g; /^$$/d' | sed -e :a -e '$$!N; s/\n\(.\)/\1/; ta' > _themes/srtd/static/css/theme.min.css
diff --git a/docsite/_themes/srtd/footer.html b/docsite/_themes/srtd/footer.html
index b70cfde7ad..dc1d70a4d1 100644
--- a/docsite/_themes/srtd/footer.html
+++ b/docsite/_themes/srtd/footer.html
@@ -12,8 +12,17 @@
<hr/>
+<script type="text/javascript">
+ (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
+ (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
+ e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
+ })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
+
+ _st('install','yABGvz2N8PwcwBxyfzUc','2.0.0');
+</script>
+
<p>
- &copy; Copyright 2015 <a href="http://ansible.com">Ansible, Inc.</a>.
+ &copy; Copyright 2016 <a href="http://ansible.com">Ansible, Inc.</a>.
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
diff --git a/docsite/_themes/srtd/layout.html b/docsite/_themes/srtd/layout.html
index f4d7a8a536..cb532191e6 100644
--- a/docsite/_themes/srtd/layout.html
+++ b/docsite/_themes/srtd/layout.html
@@ -150,11 +150,6 @@
</a>
</div>
- <div class="wy-side-nav-search" style="background-color:#5bbdbf;height=80px;margin:'auto auto auto auto'">
- <!-- <a href="{{ pathto(master_doc) }}" class="icon icon-home"> {{ project }}</a> -->
- {% include "searchbox.html" %}
- </div>
-
<div id="menu-id" class="wy-menu wy-menu-vertical" data-spy="affix">
{% set toctree = toctree(maxdepth=2, collapse=False) %}
{% if toctree %}
@@ -166,16 +161,9 @@
<!-- changeable widget -->
<center>
<br/>
-<span class="hs-cta-wrapper" id="hs-cta-wrapper-71d47584-8ef5-4b06-87ae-8d25bc2a837e">
- <span class="hs-cta-node hs-cta-71d47584-8ef5-4b06-87ae-8d25bc2a837e" id="hs-cta-71d47584-8ef5-4b06-87ae-8d25bc2a837e">
- <!--[if lte IE 8]><div id="hs-cta-ie-element"></div><![endif]-->
- <a href="http://cta-redirect.hubspot.com/cta/redirect/330046/71d47584-8ef5-4b06-87ae-8d25bc2a837e"><img class="hs-cta-img" id="hs-cta-img-71d47584-8ef5-4b06-87ae-8d25bc2a837e" style="border-width:0px;" src="https://no-cache.hubspot.com/cta/default/330046/71d47584-8ef5-4b06-87ae-8d25bc2a837e.png" /></a>
- </span>
- <script charset="utf-8" src="https://js.hscta.net/cta/current.js"></script>
- <script type="text/javascript">
- hbspt.cta.load(330046, '71d47584-8ef5-4b06-87ae-8d25bc2a837e');
- </script>
-</span>
+<a href="http://www.ansible.com/docs-left?utm_source=docs">
+ <img style="border-width:0px;" src="https://cdn2.hubspot.net/hubfs/330046/docs-graphics/ASB-docs-left-rail.png" />
+</a>
</center>
@@ -196,15 +184,17 @@
<div class="wy-nav-content">
<div class="rst-content">
- <!-- Tower ads -->
- <a class="DocSiteBanner" href="http://www.ansible.com/tower?utm_source=docs">
- <div class="DocSiteBanner-imgWrapper">
- <img src="{{ pathto('_static/', 1) }}images/banner_ad_1.png">
- </div>
- <div class="DocSiteBanner-imgWrapper">
- <img src="{{ pathto('_static/', 1) }}images/banner_ad_2.png">
- </div>
- </a>
+ <!-- Banner ads -->
+ <div class="DocSiteBanner">
+ <a class="DocSiteBanner-imgWrapper"
+ href="http://www.ansible.com/docs-top?utm_source=docs">
+ <img src="https://cdn2.hubspot.net/hubfs/330046/docs-graphics/ASB-docs-top-left.png">
+ </a>
+ <a class="DocSiteBanner-imgWrapper"
+ href="http://www.ansible.com/docs-top?utm_source=docs">
+ <img src="https://cdn2.hubspot.net/hubfs/330046/docs-graphics/ASB-docs-top-right.png">
+ </a>
+ </div>
{% include "breadcrumbs.html" %}
<div id="page-content">
diff --git a/docsite/_themes/srtd/layout_old.html b/docsite/_themes/srtd/layout_old.html
deleted file mode 100644
index deb8df2a1a..0000000000
--- a/docsite/_themes/srtd/layout_old.html
+++ /dev/null
@@ -1,205 +0,0 @@
-{#
- basic/layout.html
- ~~~~~~~~~~~~~~~~~
-
- Master layout template for Sphinx themes.
-
- :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-#}
-{%- block doctype -%}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-{%- endblock %}
-{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
-{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
-{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
- (sidebars != []) %}
-{%- set url_root = pathto('', 1) %}
-{# XXX necessary? #}
-{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
-{%- if not embedded and docstitle %}
- {%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
-{%- else %}
- {%- set titlesuffix = "" %}
-{%- endif %}
-
-{%- macro relbar() %}
- <div class="related">
- <h3>{{ _('Navigation') }}</h3>
- <ul>
- {%- for rellink in rellinks %}
- <li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
- <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
- {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
- {%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
- {%- endfor %}
- {%- block rootrellink %}
- <li><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
- {%- endblock %}
- {%- for parent in parents %}
- <li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
- {%- endfor %}
- {%- block relbaritems %} {% endblock %}
- </ul>
- </div>
-{%- endmacro %}
-
-{%- macro sidebar() %}
- {%- if render_sidebar %}
- <div class="sphinxsidebar">
- <div class="sphinxsidebarwrapper">
- {%- block sidebarlogo %}
- {%- if logo %}
- <p class="logo"><a href="{{ pathto(master_doc) }}">
- <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
- </a></p>
- {%- endif %}
- {%- endblock %}
- {%- if sidebars != None %}
- {#- new style sidebar: explicitly include/exclude templates #}
- {%- for sidebartemplate in sidebars %}
- {%- include sidebartemplate %}
- {%- endfor %}
- {%- else %}
- {#- old style sidebars: using blocks -- should be deprecated #}
- {%- block sidebartoc %}
- {%- include "localtoc.html" %}
- {%- endblock %}
- {%- block sidebarrel %}
- {%- include "relations.html" %}
- {%- endblock %}
- {%- block sidebarsourcelink %}
- {%- include "sourcelink.html" %}
- {%- endblock %}
- {%- if customsidebar %}
- {%- include customsidebar %}
- {%- endif %}
- {%- block sidebarsearch %}
- {%- include "searchbox.html" %}
- {%- endblock %}
- {%- endif %}
- </div>
- </div>
- {%- endif %}
-{%- endmacro %}
-
-{%- macro script() %}
- <script type="text/javascript">
- var DOCUMENTATION_OPTIONS = {
- URL_ROOT: '{{ url_root }}',
- VERSION: '{{ release|e }}',
- COLLAPSE_INDEX: false,
- FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
- HAS_SOURCE: {{ has_source|lower }}
- };
- </script>
- {%- for scriptfile in script_files %}
- <script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
- {%- endfor %}
-{%- endmacro %}
-
-{%- macro css() %}
- <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
- <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
- {%- for cssfile in css_files %}
- <link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
- {%- endfor %}
-{%- endmacro %}
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
- {{ metatags }}
- {%- block htmltitle %}
- <title>{{ title|striptags|e }}{{ titlesuffix }}</title>
- {%- endblock %}
- {{ css() }}
- {%- if not embedded %}
- {{ script() }}
- {%- if use_opensearch %}
- <link rel="search" type="application/opensearchdescription+xml"
- title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
- href="{{ pathto('_static/opensearch.xml', 1) }}"/>
- {%- endif %}
- {%- if favicon %}
- <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
- {%- endif %}
- {%- endif %}
-{%- block linktags %}
- {%- if hasdoc('about') %}
- <link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
- {%- endif %}
- {%- if hasdoc('genindex') %}
- <link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
- {%- endif %}
- {%- if hasdoc('search') %}
- <link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
- {%- endif %}
- {%- if hasdoc('copyright') %}
- <link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
- {%- endif %}
- <link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
- {%- if parents %}
- <link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
- {%- endif %}
- {%- if next %}
- <link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
- {%- endif %}
- {%- if prev %}
- <link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
- {%- endif %}
-{%- endblock %}
-{%- block extrahead %} {% endblock %}
- </head>
- <body>
-{%- block header %}{% endblock %}
-
-{%- block relbar1 %}{{ relbar() }}{% endblock %}
-
-{%- block content %}
- {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
-
- <div class="document">
- {%- block document %}
- <div class="documentwrapper">
- {%- if render_sidebar %}
- <div class="bodywrapper">
- {%- endif %}
- <div class="body">
- {% block body %} {% endblock %}
- </div>
- {%- if render_sidebar %}
- </div>
- {%- endif %}
- </div>
- {%- endblock %}
-
- {%- block sidebar2 %}{{ sidebar() }}{% endblock %}
- <div class="clearer"></div>
- </div>
-{%- endblock %}
-
-{%- block relbar2 %}{{ relbar() }}{% endblock %}
-
-{%- block footer %}
- <div class="footer">
- {%- if show_copyright %}
- {%- if hasdoc('copyright') %}
- {% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
- {%- else %}
- {% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
- {%- endif %}
- {%- endif %}
- {%- if last_updated %}
- {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
- {%- endif %}
- {%- if show_sphinx %}
- {% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
- {%- endif %}
- </div>
- <p>asdf asdf asdf asdf 22</p>
-{%- endblock %}
- </body>
-</html>
-
diff --git a/docsite/_themes/srtd/searchbox.html b/docsite/_themes/srtd/searchbox.html
deleted file mode 100644
index b0310cff98..0000000000
--- a/docsite/_themes/srtd/searchbox.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!-- <form class="wy-form" action="{{ pathto('search') }}" method="get">
- <input type="text" name="q" placeholder="Search docs" />
- <input type="hidden" name="check_keywords" value="yes" />
- <input type="hidden" name="area" value="default" />
-</form> -->
-
-<script>
- (function() {
- var cx = '006019874985968165468:eu5pbnxp4po';
- var gcse = document.createElement('script');
- gcse.type = 'text/javascript';
- gcse.async = true;
- gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
- '//www.google.com/cse/cse.js?cx=' + cx;
- var s = document.getElementsByTagName('script')[0];
- s.parentNode.insertBefore(gcse, s);
- })();
-</script>
-
-<form id="search-form-id" action="">
- <input type="text" name="query" id="search-box-id" />
- <a class="search-reset-start" id="search-reset"><i class="fa fa-times"></i></a>
- <a class="search-reset-start" id="search-start"><i class="fa fa-search"></i></a>
-</form>
-
-<script type="text/javascript" src="http://www.google.com/cse/brand?form=search-form-id&inputbox=search-box-id"></script>
-
-<script>
- function executeQuery() {
- var input = document.getElementById('search-box-id');
- var element = google.search.cse.element.getElement('searchresults-only0');
- element.resultsUrl = '/htmlout/search.html'
- if (input.value == '') {
- element.clearAllResults();
- $('#page-content, .rst-footer-buttons, #search-start').show();
- $('#search-results, #search-reset').hide();
- } else {
- $('#page-content, .rst-footer-buttons, #search-start').hide();
- $('#search-results, #search-reset').show();
- element.execute(input.value);
- }
- return false;
- }
-
- $('#search-reset').hide();
-
- $('#search-box-id').css('background-position', '1em center');
-
- $('#search-box-id').on('blur', function() {
- $('#search-box-id').css('background-position', '1em center');
- });
-
- $('#search-start').click(function(e) { executeQuery(); });
- $('#search-reset').click(function(e) { $('#search-box-id').val(''); executeQuery(); });
-
- $('#search-form-id').submit(function(e) {
- console.log('submitting!');
- executeQuery();
- e.preventDefault();
- });
-</script>
diff --git a/docsite/_themes/srtd/static/css/theme.css b/docsite/_themes/srtd/static/css/theme.css
index 4f7cbc8caa..246e513b79 100644
--- a/docsite/_themes/srtd/static/css/theme.css
+++ b/docsite/_themes/srtd/static/css/theme.css
@@ -4723,33 +4723,16 @@ span[id*='MathJax-Span'] {
padding: 0.4045em 1.618em;
}
-
.DocSiteBanner {
- width: 100%;
display: flex;
display: -webkit-flex;
+ justify-content: center;
+ -webkit-justify-content: center;
flex-wrap: wrap;
-webkit-flex-wrap: wrap;
- justify-content: space-between;
- -webkit-justify-content: space-between;
- background-color: #ff5850;
margin-bottom: 25px;
}
.DocSiteBanner-imgWrapper {
max-width: 100%;
}
-
-@media screen and (max-width: 1403px) {
- .DocSiteBanner {
- width: 100%;
- display: flex;
- display: -webkit-flex;
- flex-wrap: wrap;
- -webkit-flex-wrap: wrap;
- justify-content: center;
- -webkit-justify-content: center;
- background-color: #fff;
- margin-bottom: 25px;
- }
-}
diff --git a/docsite/_themes/srtd/static/images/banner_ad_1.png b/docsite/_themes/srtd/static/images/banner_ad_1.png
deleted file mode 100644
index a6555f2567..0000000000
--- a/docsite/_themes/srtd/static/images/banner_ad_1.png
+++ /dev/null
Binary files differ
diff --git a/docsite/_themes/srtd/static/images/banner_ad_2.png b/docsite/_themes/srtd/static/images/banner_ad_2.png
deleted file mode 100644
index f9d6c6d42c..0000000000
--- a/docsite/_themes/srtd/static/images/banner_ad_2.png
+++ /dev/null
Binary files differ
diff --git a/docsite/build-site.py b/docsite/build-site.py
index 587a189f07..24f9fc9a64 100755
--- a/docsite/build-site.py
+++ b/docsite/build-site.py
@@ -15,6 +15,7 @@
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+from __future__ import print_function
__docformat__ = 'restructuredtext'
@@ -24,9 +25,9 @@ import traceback
try:
from sphinx.application import Sphinx
except ImportError:
- print "#################################"
- print "Dependency missing: Python Sphinx"
- print "#################################"
+ print("#################################")
+ print("Dependency missing: Python Sphinx")
+ print("#################################")
sys.exit(1)
import os
@@ -40,7 +41,7 @@ class SphinxBuilder(object):
"""
Run the DocCommand.
"""
- print "Creating html documentation ..."
+ print("Creating html documentation ...")
try:
buildername = 'html'
@@ -69,10 +70,10 @@ class SphinxBuilder(object):
app.builder.build_all()
- except ImportError, ie:
+ except ImportError:
traceback.print_exc()
- except Exception, ex:
- print >> sys.stderr, "FAIL! exiting ... (%s)" % ex
+ except Exception as ex:
+ print("FAIL! exiting ... (%s)" % ex, file=sys.stderr)
def build_docs(self):
self.app.builder.build_all()
@@ -83,9 +84,9 @@ def build_rst_docs():
if __name__ == '__main__':
if '-h' in sys.argv or '--help' in sys.argv:
- print "This script builds the html documentation from rst/asciidoc sources.\n"
- print " Run 'make docs' to build everything."
- print " Run 'make viewdocs' to build and then preview in a web browser."
+ print("This script builds the html documentation from rst/asciidoc sources.\n")
+ print(" Run 'make docs' to build everything.")
+ print(" Run 'make viewdocs' to build and then preview in a web browser.")
sys.exit(0)
build_rst_docs()
@@ -93,4 +94,4 @@ if __name__ == '__main__':
if "view" in sys.argv:
import webbrowser
if not webbrowser.open('htmlout/index.html'):
- print >> sys.stderr, "Could not open on your webbrowser."
+ print("Could not open on your webbrowser.", file=sys.stderr)
diff --git a/docsite/rst/YAMLSyntax.rst b/docsite/rst/YAMLSyntax.rst
index 76683f6ba3..8189a6caf6 100644
--- a/docsite/rst/YAMLSyntax.rst
+++ b/docsite/rst/YAMLSyntax.rst
@@ -20,52 +20,52 @@ Each item in the list is a list of key/value pairs, commonly
called a "hash" or a "dictionary". So, we need to know how
to write lists and dictionaries in YAML.
-There's another small quirk to YAML. All YAML files (regardless of their association with
-Ansible or not) should begin with ``---``. This is part of the YAML
-format and indicates the start of a document.
+There's another small quirk to YAML. All YAML files (regardless of their association with Ansible or not) can optionally
+begin with ``---`` and end with ``...``. This is part of the YAML format and indicates the start and end of a document.
-All members of a list are lines beginning at the same indentation level starting
-with a ``"- "`` (a dash and a space)::
+All members of a list are lines beginning at the same indentation level starting with a ``"- "`` (a dash and a space)::
---
# A list of tasty fruits
- - Apple
- - Orange
- - Strawberry
- - Mango
+ fruits:
+ - Apple
+ - Orange
+ - Strawberry
+ - Mango
+ ...
A dictionary is represented in a simple ``key: value`` form (the colon must be followed by a space)::
- ---
# An employee record
- name: Example Developer
- job: Developer
- skill: Elite
+ - martin:
+ name: Martin D'vloper
+ job: Developer
+ skill: Elite
-Dictionaries can also be represented in an abbreviated form if you really want to::
+Dictionaries and lists can also be represented in an abbreviated form if you really want to::
---
- # An employee record
- {name: Example Developer, job: Developer, skill: Elite}
+ employees:
+ - martin: {name: Martin D'vloper, job: Developer, skill: Elite}
+ fruits: ['Apple', 'Orange', 'Strawberry', 'Mango']
.. _truthiness:
-Ansible doesn't really use these too much, but you can also specify a
-boolean value (true/false) in several forms::
+Ansible doesn't really use these too much, but you can also specify a boolean value (true/false) in several forms::
- ---
create_key: yes
needs_agent: no
knows_oop: True
likes_emacs: TRUE
uses_cvs: false
-Let's combine what we learned so far in an arbitrary YAML example. This really
-has nothing to do with Ansible, but will give you a feel for the format::
+
+Let's combine what we learned so far in an arbitrary YAML example.
+This really has nothing to do with Ansible, but will give you a feel for the format::
---
# An employee record
- name: Example Developer
+ name: Martin D'vloper
job: Developer
skill: Elite
employed: True
@@ -79,8 +79,7 @@ has nothing to do with Ansible, but will give you a feel for the format::
python: Elite
dotnet: Lame
-That's all you really need to know about YAML to start writing
-`Ansible` playbooks.
+That's all you really need to know about YAML to start writing `Ansible` playbooks.
Gotchas
-------
@@ -100,6 +99,14 @@ with a "{", YAML will think it is a dictionary, so you must quote it, like so::
foo: "{{ variable }}"
+The same applies for strings that start or contain any YAML special characters `` [] {} : > | `` .
+
+Boolean conversion is helpful, but this can be a problem when you want a literal `yes` or other boolean values as a string.
+In these cases just use quotes::
+
+ non_boolean: "yes"
+ other_string: "False"
+
.. seealso::
diff --git a/docsite/rst/become.rst b/docsite/rst/become.rst
index 64628515c6..7597643f88 100644
--- a/docsite/rst/become.rst
+++ b/docsite/rst/become.rst
@@ -1,5 +1,5 @@
-Ansible Privilege Escalation
-++++++++++++++++++++++++++++
+Become (Privilege Escalation)
++++++++++++++++++++++++++++++
Ansible can use existing privilege escalation systems to allow a user to execute tasks as another.
@@ -7,17 +7,17 @@ Ansible can use existing privilege escalation systems to allow a user to execute
Become
``````
-Before 1.9 Ansible mostly allowed the use of sudo and a limited use of su to allow a login/remote user to become a different user
-and execute tasks, create resources with the 2nd user's permissions. As of 1.9 'become' supersedes the old sudo/su, while still
-being backwards compatible. This new system also makes it easier to add other privilege escalation tools like pbrun (Powerbroker),
-pfexec and others.
+Before 1.9 Ansible mostly allowed the use of `sudo` and a limited use of `su` to allow a login/remote user to become a different user
+and execute tasks, create resources with the 2nd user's permissions. As of 1.9 `become` supersedes the old sudo/su, while still
+being backwards compatible. This new system also makes it easier to add other privilege escalation tools like `pbrun` (Powerbroker),
+`pfexec` and others.
New directives
--------------
become
- equivalent to adding 'sudo:' or 'su:' to a play or task, set to 'true'/'yes' to activate privilege escalation
+ equivalent to adding `sudo:` or `su:` to a play or task, set to 'true'/'yes' to activate privilege escalation
become_user
equivalent to adding 'sudo_user:' or 'su_user:' to a play or task, set to user with desired privileges
diff --git a/docsite/rst/developing.rst b/docsite/rst/developing.rst
index 2a25899301..c5a1dca061 100644
--- a/docsite/rst/developing.rst
+++ b/docsite/rst/developing.rst
@@ -11,6 +11,7 @@ Learn how to build modules of your own in any language, and also how to extend A
developing_modules
developing_plugins
developing_test_pr
+ developing_releases
Developers will also likely be interested in the fully-discoverable in :doc:`tower`. It's great for embedding Ansible in all manner of applications.
diff --git a/docsite/rst/developing_api.rst b/docsite/rst/developing_api.rst
index 76cebb64f1..96a447c05c 100644
--- a/docsite/rst/developing_api.rst
+++ b/docsite/rst/developing_api.rst
@@ -6,7 +6,7 @@ Python API
There are several interesting ways to use Ansible from an API perspective. You can use
the Ansible python API to control nodes, you can extend Ansible to respond to various python events, you can
write various plugins, and you can plug in inventory data from external data sources. This document
-covers the Runner and Playbook API at a basic level.
+covers the execution and Playbook API at a basic level.
If you are looking to use Ansible programmatically from something other than Python, trigger events asynchronously,
or have access control and logging demands, take a look at :doc:`tower`
@@ -17,11 +17,69 @@ This chapter discusses the Python API.
.. _python_api:
-Python API
-----------
+The Python API is very powerful, and is how the all the ansible CLI tools are implemented.
+In version 2.0 the core ansible got rewritten and the API was mostly rewritten.
+
+:.. note:: Ansible relies on forking processes, as such the API is not thread safe.
+
+.. _python_api_20:
+
+Python API 2.0
+--------------
+
+In 2.0 things get a bit more complicated to start, but you end up with much more discrete and readable classes::
+
+
+ #!/usr/bin/python2
+
+ from collections import namedtuple
+ from ansible.parsing.dataloader import DataLoader
+ from ansible.vars import VariableManager
+ from ansible.inventory import Inventory
+ from ansible.playbook.play import Play
+ from ansible.executor.task_queue_manager import TaskQueueManager
+
+ Options = namedtuple('Options', ['connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])
+ # initialize needed objects
+ variable_manager = VariableManager()
+ loader = DataLoader()
+ options = Options(connection='local', module_path='/path/to/mymodules', forks=100, remote_user=None, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user=None, verbosity=None, check=False)
+ passwords = dict(vault_pass='secret')
+
+ # create inventory and pass to var manager
+ inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost')
+ variable_manager.set_inventory(inventory)
+
+ # create play with tasks
+ play_source = dict(
+ name = "Ansible Play",
+ hosts = 'localhost',
+ gather_facts = 'no',
+ tasks = [ dict(action=dict(module='debug', args=dict(msg='Hello Galaxy!'))) ]
+ )
+ play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
+
+ # actually run it
+ tqm = None
+ try:
+ tqm = TaskQueueManager(
+ inventory=inventory,
+ variable_manager=variable_manager,
+ loader=loader,
+ options=options,
+ passwords=passwords,
+ stdout_callback='default',
+ )
+ result = tqm.run(play)
+ finally:
+ if tqm is not None:
+ tqm.cleanup()
+
+
+.. _python_api_old:
-The Python API is very powerful, and is how the ansible CLI and ansible-playbook
-are implemented.
+Python API pre 2.0
+------------------
It's pretty simple::
@@ -51,7 +109,7 @@ expressed in the :doc:`modules` documentation.::
A module can return any type of JSON data it wants, so Ansible can
be used as a framework to rapidly build powerful applications and scripts.
-.. _detailed_api_example:
+.. _detailed_api_old_example:
Detailed API Example
````````````````````
@@ -87,9 +145,9 @@ The following script prints out the uptime information for all hosts::
for (hostname, result) in results['dark'].items():
print "%s >>> %s" % (hostname, result)
-Advanced programmers may also wish to read the source to ansible itself, for
-it uses the Runner() API (with all available options) to implement the
-command line tools ``ansible`` and ``ansible-playbook``.
+Advanced programmers may also wish to read the source to ansible itself,
+for it uses the API (with all available options) to implement the ``ansible``
+command line tools (``lib/ansible/cli/``).
.. seealso::
diff --git a/docsite/rst/developing_modules.rst b/docsite/rst/developing_modules.rst
index dd62275828..dc5b7e8f5f 100644
--- a/docsite/rst/developing_modules.rst
+++ b/docsite/rst/developing_modules.rst
@@ -191,7 +191,7 @@ a lot shorter than this::
Let's test that module::
- ansible/hacking/test-module -m ./time -a "time=\"March 14 12:23\""
+ ansible/hacking/test-module -m ./timetest.py -a "time=\"March 14 12:23\""
This should return something like::
@@ -219,7 +219,7 @@ this, just have the module return a `ansible_facts` key, like so, along with oth
}
These 'facts' will be available to all statements called after that module (but not before) in the playbook.
-A good idea might be make a module called 'site_facts' and always call it at the top of each playbook, though
+A good idea might be to make a module called 'site_facts' and always call it at the top of each playbook, though
we're always open to improving the selection of core facts in Ansible as well.
.. _common_module_boilerplate:
@@ -247,7 +247,7 @@ And instantiating the module class like::
argument_spec = dict(
state = dict(default='present', choices=['present', 'absent']),
name = dict(required=True),
- enabled = dict(required=True, choices=BOOLEANS),
+ enabled = dict(required=True, type='bool'),
something = dict(aliases=['whatever'])
)
)
@@ -335,7 +335,7 @@ and guidelines:
* If you have a company module that returns facts specific to your installations, a good name for this module is `site_facts`.
-* Modules accepting boolean status should generally accept 'yes', 'no', 'true', 'false', or anything else a user may likely throw at them. The AnsibleModule common code supports this with "choices=BOOLEANS" and a module.boolean(value) casting function.
+* Modules accepting boolean status should generally accept 'yes', 'no', 'true', 'false', or anything else a user may likely throw at them. The AnsibleModule common code supports this with "type='bool'".
* 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.
@@ -347,7 +347,7 @@ and guidelines:
* In the event of failure, a key of 'failed' should be included, along with a string explanation in 'msg'. Modules that raise tracebacks (stacktraces) are generally considered 'poor' modules, though Ansible can deal with these returns and will automatically convert anything unparseable into a failed result. If you are using the AnsibleModule common Python code, the 'failed' element will be included for you automatically when you call 'fail_json'.
-* Return codes from modules are not actually not significant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
+* Return codes from modules are actually not significant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
* As results from many hosts will be aggregated at once, modules should return only relevant output. Returning the entire contents of a log file is generally bad form.
@@ -479,9 +479,10 @@ Module checklist
````````````````
* The shebang should always be #!/usr/bin/python, this allows ansible_python_interpreter to work
+* Modules must be written to support Python 2.4. If this is not possible, required minimum python version and rationale should be explained in the requirements section in DOCUMENTATION.
* Documentation: Make sure it exists
* `required` should always be present, be it true or false
- * If `required` is false you need to document `default`, even if the default is 'None' (which is the default if no parameter is supplied). Make sure default parameter in docs matches default parameter in code.
+ * If `required` is false you need to document `default`, even if the default is 'null' (which is the default if no parameter is supplied). Make sure default parameter in docs matches default parameter in code.
* `default` is not needed for `required: true`
* Remove unnecessary doc like `aliases: []` or `choices: []`
* The version is not a float number and value the current development version
@@ -538,24 +539,34 @@ Windows modules checklist
#!powershell
-then::
+ then::
+
<GPL header>
-then::
+
+ then::
+
# WANT_JSON
# POWERSHELL_COMMON
-then, to parse all arguments into a variable modules generally use::
+ then, to parse all arguments into a variable modules generally use::
+
$params = Parse-Args $args
* Arguments:
* Try and use state present and state absent like other modules
* You need to check that all your mandatory args are present. You can do this using the builtin Get-AnsibleParam function.
* Required arguments::
+
$package = Get-AnsibleParam -obj $params -name name -failifempty $true
+
* Required arguments with name validation::
+
$state = Get-AnsibleParam -obj $params -name "State" -ValidateSet "Present","Absent" -resultobj $resultobj -failifempty $true
+
* Optional arguments with name validation::
+
$state = Get-AnsibleParam -obj $params -name "State" -default "Present" -ValidateSet "Present","Absent"
+
* the If "FailIfEmpty" is true, the resultobj parameter is used to specify the object returned to fail-json. You can also override the default message
using $emptyattributefailmessage (for missing required attributes) and $ValidateSetErrorMessage (for attribute validation errors)
* Look at existing modules for more examples of argument checking.
@@ -586,7 +597,7 @@ Starting in 1.8 you can deprecate modules by renaming them with a preceding _, i
_old_cloud.py, This will keep the module available but hide it from the primary docs and listing.
You can also rename modules and keep an alias to the old name by using a symlink that starts with _.
-This example allows the stat module to be called with fileinfo, making the following examples equivalent
+This example allows the stat module to be called with fileinfo, making the following examples equivalent::
EXAMPLES = '''
ln -s stat.py _fileinfo.py
diff --git a/docsite/rst/developing_releases.rst b/docsite/rst/developing_releases.rst
new file mode 100644
index 0000000000..2332459c30
--- /dev/null
+++ b/docsite/rst/developing_releases.rst
@@ -0,0 +1,48 @@
+Releases
+========
+
+.. contents:: Topics
+ :local:
+
+.. _schedule:
+
+Release Schedule
+````````````````
+Ansible is on a 'flexible' 4 month release schedule, sometimes this can be extended if there is a major change that requires a longer cycle (i.e. 2.0 core rewrite).
+Currently modules get released at the same time as the main Ansible repo, even though they are separated into ansible-modules-core and ansible-modules-extras.
+
+The major features and bugs fixed in a release should be reflected in the CHANGELOG.md, minor ones will be in the commit history (FIXME: add git exmaple to list).
+When a fix/feature gets added to the `devel` branch it will be part of the next release, some bugfixes can be backported to previous releases and might be part of a minor point release if it is deemed necessary.
+
+Sometimes an RC can be extended by a few days if a bugfix makes a change that can have far reaching consequences, so users have enough time to find any new issues that may stem from this.
+
+.. _methods:
+
+Release methods
+````````````````
+
+Ansible normally goes through a 'release candidate', issuing an RC1 for a release, if no major bugs are discovered in it after 5 business days we'll get a final release.
+Otherwise fixes will be applied and an RC2 will be provided for testing and if no bugs after 2 days, the final release will be made, iterating this last step and incrementing the candidate number as we find major bugs.
+
+
+.. _freezing:
+
+Release feature freeze
+``````````````````````
+
+During the release candidate process, the focus will be on bugfixes that affect the RC, new features will be delayed while we try to produce a final version. Some bugfixes that are minor or don't affect the RC will also be postponed until after the release is finalized.
+
+.. seealso::
+
+ :doc:`developing_api`
+ Python API to Playbooks and Ad Hoc Task Execution
+ :doc:`developing_modules`
+ How to develop modules
+ :doc:`developing_plugins`
+ How to develop plugins
+ `Ansible Tower <http://ansible.com/ansible-tower>`_
+ REST API endpoint and GUI for Ansible, syncs with dynamic inventory
+ `Development Mailing List <http://groups.google.com/group/ansible-devel>`_
+ Mailing list for development topics
+ `irc.freenode.net <http://irc.freenode.net>`_
+ #ansible IRC chat channel
diff --git a/docsite/rst/developing_test_pr.rst b/docsite/rst/developing_test_pr.rst
index b6ec4e10ba..cf3d0d7536 100644
--- a/docsite/rst/developing_test_pr.rst
+++ b/docsite/rst/developing_test_pr.rst
@@ -81,27 +81,34 @@ and destination repositories. It will look something like this::
Someuser wants to merge 1 commit into ansible:devel from someuser:feature_branch_name
.. note::
- It is important that the PR request target be ansible:devel, as we do not accept pull requests into any other branch.
- Dot releases are cherry-picked manually by ansible staff.
+ It is important that the PR request target be ansible:devel, as we do not accept pull requests into any other branch. Dot releases are cherry-picked manually by ansible staff.
The username and branch at the end are the important parts, which will be turned into git commands as follows::
git checkout -b testing_PRXXXX devel
git pull https://github.com/someuser/ansible.git feature_branch_name
-The first command creates and switches to a new branch named testing_PRXXXX, where the XXXX is the actual issue number associated
-with the pull request (for example, 1234). This branch is based on the devel branch. The second command pulls the new code from the
-users feature branch into the newly created branch.
+The first command creates and switches to a new branch named testing_PRXXXX, where the XXXX is the actual issue number associated with the pull request (for example, 1234). This branch is based on the devel branch. The second command pulls the new code from the users feature branch into the newly created branch.
.. note::
- If the GitHub user interface shows that the pull request will not merge cleanly, we do not recommend proceeding if you
- are not somewhat familiar with git and coding, as you will have to resolve a merge conflict. This is the responsibility of
- the original pull request contributor.
+ If the GitHub user interface shows that the pull request will not merge cleanly, we do not recommend proceeding if you are not somewhat familiar with git and coding, as you will have to resolve a merge conflict. This is the responsibility of the original pull request contributor.
.. note::
- Some users do not create feature branches, which can cause problems when they have multiple, un-related commits in
- their version of `devel`. If the source looks like `someuser:devel`, make sure there is only one commit listed on
- the pull request.
+ Some users do not create feature branches, which can cause problems when they have multiple, un-related commits in their version of `devel`. If the source looks like `someuser:devel`, make sure there is only one commit listed on the pull request.
+
+Finding a Pull Request for Ansible Modules
+++++++++++++++++++++++++++++++++++++++++++
+Ansible modules are in separate repositories, which are managed as Git submodules. Here's a step by step process for checking out a PR for an Ansible extras module, for instance:
+
+1. git clone https://github.com/ansible/ansible.git
+2. cd ansible
+3. git submodule init
+4. git submodule update --recursive [ fetches the submodules ]
+5. cd lib/ansible/modules/extras
+6. git fetch origin pull/1234/head:pr/1234 [ fetches the specific PR ]
+7. git checkout pr/1234 [ do your testing here ]
+8. cd /path/to/ansible/clone
+9. git submodule update --recursive
For Those About To Test, We Salute You
++++++++++++++++++++++++++++++++++++++
diff --git a/docsite/rst/faq.rst b/docsite/rst/faq.rst
index 90b9a1cb09..e51a1751fe 100644
--- a/docsite/rst/faq.rst
+++ b/docsite/rst/faq.rst
@@ -38,7 +38,7 @@ You can also dictate the connection type to be used, if you want::
foo.example.com
bar.example.com
-You may also wish to keep these in group variables instead, or file in them in a group_vars/<groupname> file.
+You may also wish to keep these in group variables instead, or file them in a group_vars/<groupname> file.
See the rest of the documentation for more information about how to organize variables.
.. _use_ssh:
diff --git a/docsite/rst/galaxy.rst b/docsite/rst/galaxy.rst
index 8df268175a..ba841eed09 100644
--- a/docsite/rst/galaxy.rst
+++ b/docsite/rst/galaxy.rst
@@ -1,55 +1,60 @@
Ansible Galaxy
++++++++++++++
-"Ansible Galaxy" can either refer to a website for sharing and downloading Ansible roles, or a command line tool that helps work with roles.
+"Ansible Galaxy" can either refer to a website for sharing and downloading Ansible roles, or a command line tool for managing and creating roles.
.. contents:: Topics
The Website
```````````
-The website `Ansible Galaxy <https://galaxy.ansible.com>`_, is a free site for finding, downloading, rating, and reviewing all kinds of community developed Ansible roles and can be a great way to get a jumpstart on your automation projects.
+The website `Ansible Galaxy <https://galaxy.ansible.com>`_, is a free site for finding, downloading, and sharing community developed Ansible roles. Downloading roles from Galaxy is a great way to jumpstart your automation projects.
-You can sign up with social auth and use the download client 'ansible-galaxy' which is included in Ansible 1.4.2 and later.
+Access the Galaxy web site using GitHub OAuth, and to install roles use the 'ansible-galaxy' command line tool included in Ansible 1.4.2 and later.
Read the "About" page on the Galaxy site for more information.
The ansible-galaxy command line tool
````````````````````````````````````
-The command line ansible-galaxy has many different subcommands.
+The ansible-galaxy command has many different sub-commands for managing roles both locally and at `galaxy.ansible.com <https://galaxy.ansible.com>`_.
+
+.. note::
+
+ The search, login, import, delete, and setup commands in the Ansible 2.0 version of ansible-galaxy require access to the
+ 2.0 Beta release of the Galaxy web site available at `https://galaxy-qa.ansible.com <https://galaxy-qa.ansible.com>`_.
+
+ Use the ``--server`` option to access the beta site. For example::
+
+ $ ansible-galaxy search --server https://galaxy-qa.ansible.com mysql --author geerlingguy
+
+ Additionally, you can define a server in ansible.cfg::
+
+ [galaxy]
+ server=https://galaxy-qa.ansible.com
Installing Roles
----------------
-The most obvious is downloading roles from the Ansible Galaxy website::
+The most obvious use of the ansible-galaxy command is downloading roles from `the Ansible Galaxy website <https://galaxy.ansible.com>`_::
- ansible-galaxy install username.rolename
-
-.. _galaxy_cli_roles_path:
+ $ ansible-galaxy install username.rolename
roles_path
-===============
+==========
You can specify a particular directory where you want the downloaded roles to be placed::
- ansible-galaxy install username.role -p ~/Code/ansible_roles/
+ $ ansible-galaxy install username.role -p ~/Code/ansible_roles/
This can be useful if you have a master folder that contains ansible galaxy roles shared across several projects. The default is the roles_path configured in your ansible.cfg file (/etc/ansible/roles if not configured).
-Building out Role Scaffolding
------------------------------
-
-It can also be used to initialize the base structure of a new role, saving time on creating the various directories and main.yml files a role requires::
-
- ansible-galaxy init rolename
-
Installing Multiple Roles From A File
--------------------------------------
+=====================================
To install multiple roles, the ansible-galaxy CLI can be fed a requirements file. All versions of ansible allow the following syntax for installing roles from the Ansible Galaxy website::
- ansible-galaxy install -r requirements.txt
+ $ ansible-galaxy install -r requirements.txt
Where the requirements.txt looks like::
@@ -64,7 +69,7 @@ To request specific versions (tags) of a role, use this syntax in the roles file
Available versions will be listed on the Ansible Galaxy webpage for that role.
Advanced Control over Role Requirements Files
----------------------------------------------
+=============================================
For more advanced control over where to download roles from, including support for remote repositories, Ansible 1.8 and later support a new YAML format for the role requirements file, which must end in a 'yml' extension. It works like this::
@@ -77,14 +82,10 @@ And here's an example showing some specific version downloads from multiple sour
# from galaxy
- src: yatesr.timezone
- # from github
- - src: https://github.com/bennojoy/nginx
-
- # from github installing to a relative path
+ # from GitHub
- src: https://github.com/bennojoy/nginx
- path: vagrant/roles/
- # from github, overriding the name and specifying a specific tag
+ # from GitHub, overriding the name and specifying a specific tag
- src: https://github.com/bennojoy/nginx
version: master
name: nginx_role
@@ -93,19 +94,18 @@ And here's an example showing some specific version downloads from multiple sour
- src: https://some.webserver.example.com/files/master.tar.gz
name: http-role
- # from bitbucket, if bitbucket happens to be operational right now :)
+ # from Bitbucket
- src: git+http://bitbucket.org/willthames/git-ansible-galaxy
version: v1.4
- # from bitbucket, alternative syntax and caveats
+ # from Bitbucket, alternative syntax and caveats
- src: http://bitbucket.org/willthames/hg-ansible-galaxy
scm: hg
- # from gitlab or other git-based scm
+ # from GitLab or other git-based scm
- src: git@gitlab.company.com:mygroup/ansible-base.git
scm: git
version: 0.1.0
- path: roles/
As you can see in the above, there are a large amount of controls available
to customize where roles can be pulled from, and what to save roles as.
@@ -121,3 +121,283 @@ Roles pulled from galaxy work as with other SCM sourced roles above. To download
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel
+Building Role Scaffolding
+-------------------------
+
+Use the init command to initialize the base structure of a new role, saving time on creating the various directories and main.yml files a role requires::
+
+ $ ansible-galaxy init rolename
+
+The above will create the following directory structure in the current working directory:
+
+::
+
+ README.md
+ .travis.yml
+ defaults/
+ main.yml
+ files/
+ handlers/
+ main.yml
+ meta/
+ main.yml
+ templates/
+ tests/
+ inventory
+ test.yml
+ vars/
+ main.yml
+
+.. note::
+
+ .travis.yml and tests/ are new in Ansible 2.0
+
+If a directory matching the name of the role already exists in the current working directory, the init command will result in an error. To ignore the error use the --force option. Force will create the above subdirectories and files, replacing anything that matches.
+
+Search for Roles
+----------------
+
+The search command provides for querying the Galaxy database, allowing for searching by tags, platforms, author and multiple keywords. For example:
+
+::
+
+ $ ansible-galaxy search elasticsearch --author geerlingguy
+
+The search command will return a list of the first 1000 results matching your search:
+
+::
+
+ Found 2 roles matching your search:
+
+ Name Description
+ ---- -----------
+ geerlingguy.elasticsearch Elasticsearch for Linux.
+ geerlingguy.elasticsearch-curator Elasticsearch curator for Linux.
+
+.. note::
+
+ The format of results pictured here is new in Ansible 2.0.
+
+Get More Information About a Role
+---------------------------------
+
+Use the info command To view more detail about a specific role:
+
+::
+
+ $ ansible-galaxy info username.role_name
+
+This returns everything found in Galaxy for the role:
+
+::
+
+ Role: username.rolename
+ description: Installs and configures a thing, a distributed, highly available NoSQL thing.
+ active: True
+ commit: c01947b7bc89ebc0b8a2e298b87ab416aed9dd57
+ commit_message: Adding travis
+ commit_url: https://github.com/username/repo_name/commit/c01947b7bc89ebc0b8a2e298b87ab
+ company: My Company, Inc.
+ created: 2015-12-08T14:17:52.773Z
+ download_count: 1
+ forks_count: 0
+ github_branch:
+ github_repo: repo_name
+ github_user: username
+ id: 6381
+ is_valid: True
+ issue_tracker_url:
+ license: Apache
+ min_ansible_version: 1.4
+ modified: 2015-12-08T18:43:49.085Z
+ namespace: username
+ open_issues_count: 0
+ path: /Users/username/projects/roles
+ scm: None
+ src: username.repo_name
+ stargazers_count: 0
+ travis_status_url: https://travis-ci.org/username/repo_name.svg?branch=master
+ version:
+ watchers_count: 1
+
+
+List Installed Roles
+--------------------
+
+The list command shows the name and version of each role installed in roles_path.
+
+::
+
+ $ ansible-galaxy list
+
+ - chouseknecht.role-install_mongod, master
+ - chouseknecht.test-role-1, v1.0.2
+ - chrismeyersfsu.role-iptables, master
+ - chrismeyersfsu.role-required_vars, master
+
+Remove an Installed Role
+------------------------
+
+The remove command will delete a role from roles_path:
+
+::
+
+ $ ansible-galaxy remove username.rolename
+
+Authenticate with Galaxy
+------------------------
+
+To use the import, delete and setup commands authentication with Galaxy is required. The login command will authenticate the user,retrieve a token from Galaxy, and store it in the user's home directory.
+
+::
+
+ $ ansible-galaxy login
+
+ We need your Github login to identify you.
+ This information will not be sent to Galaxy, only to api.github.com.
+ The password will not be displayed.
+
+ Use --github-token if you do not want to enter your password.
+
+ Github Username: dsmith
+ Password for dsmith:
+ Succesfully logged into Galaxy as dsmith
+
+As depicted above, the login command prompts for a GitHub username and password. It does NOT send your password to Galaxy. It actually authenticates with GitHub and creates a personal access token. It then sends the personal access token to Galaxy, which in turn verifies that you are you and returns a Galaxy access token. After authentication completes the GitHub personal access token is destroyed.
+
+If you do not wish to use your GitHub password, or if you have two-factor authentication enabled with GitHub, use the --github-token option to pass a personal access token that you create. Log into GitHub, go to Settings and click on Personal Access Token to create a token.
+
+.. note::
+
+ The login command in Ansible 2.0 requires using the Galaxy 2.0 Beta site. Use the ``--server`` option to access
+ `https://galaxy-qa.ansible.com <https://galaxy-qa.ansible.com>`_. You can also add a *server* definition in the [galaxy]
+ section of your ansible.cfg file.
+
+Import a Role
+-------------
+
+Roles can be imported using ansible-galaxy. The import command expects that the user previously authenticated with Galaxy using the login command.
+
+Import any GitHub repo you have access to:
+
+::
+
+ $ ansible-galaxy import github_user github_repo
+
+By default the command will wait for the role to be imported by Galaxy, displaying the results as the import progresses:
+
+::
+
+ Successfully submitted import request 41
+ Starting import 41: role_name=myrole repo=githubuser/ansible-role-repo ref=
+ Retrieving Github repo githubuser/ansible-role-repo
+ Accessing branch: master
+ Parsing and validating meta/main.yml
+ Parsing galaxy_tags
+ Parsing platforms
+ Adding dependencies
+ Parsing and validating README.md
+ Adding repo tags as role versions
+ Import completed
+ Status SUCCESS : warnings=0 errors=0
+
+Use the --branch option to import a specific branch. If not specified, the default branch for the repo will be used.
+
+If the --no-wait option is present, the command will not wait for results. Results of the most recent import for any of your roles is available on the Galaxy web site under My Imports.
+
+.. note::
+
+ The import command in Ansible 2.0 requires using the Galaxy 2.0 Beta site. Use the ``--server`` option to access
+ `https://galaxy-qa.ansible.com <https://galaxy-qa.ansible.com>`_. You can also add a *server* definition in the [galaxy]
+ section of your ansible.cfg file.
+
+Delete a Role
+-------------
+
+Remove a role from the Galaxy web site using the delete command. You can delete any role that you have access to in GitHub. The delete command expects that the user previously authenticated with Galaxy using the login command.
+
+::
+
+ $ ansible-galaxy delete github_user github_repo
+
+This only removes the role from Galaxy. It does not impact the actual GitHub repo.
+
+.. note::
+
+ The delete command in Ansible 2.0 requires using the Galaxy 2.0 Beta site. Use the ``--server`` option to access
+ `https://galaxy-qa.ansible.com <https://galaxy-qa.ansible.com>`_. You can also add a *server* definition in the [galaxy]
+ section of your ansible.cfg file.
+
+Setup Travis Integrations
+--------------------------
+
+Using the setup command you can enable notifications from `travis <http://travis-ci.org>`_. The setup command expects that the user previously authenticated with Galaxy using the login command.
+
+::
+
+ $ ansible-galaxy setup travis github_user github_repo xxxtravistokenxxx
+
+ Added integration for travis github_user/github_repo
+
+The setup command requires your Travis token. The Travis token is not stored in Galaxy. It is used along with the GitHub username and repo to create a hash as described in `the Travis documentation <https://docs.travis-ci.com/user/notifications/>`_. The calculated hash is stored in Galaxy and used to verify notifications received from Travis.
+
+The setup command enables Galaxy to respond to notifications. Follow the `Travis getting started guide <https://docs.travis-ci.com/user/getting-started/>`_ to enable the Travis build process for the role repository.
+
+When you create your .travis.yml file add the following to cause Travis to notify Galaxy when a build completes:
+
+::
+
+ notifications:
+ webhooks: https://galaxy.ansible.com/api/v1/notifications/
+
+.. note::
+
+ The setup command in Ansible 2.0 requires using the Galaxy 2.0 Beta site. Use the ``--server`` option to access
+ `https://galaxy-qa.ansible.com <https://galaxy-qa.ansible.com>`_. You can also add a *server* definition in the [galaxy]
+ section of your ansible.cfg file.
+
+
+List Travis Integrations
+========================
+
+Use the --list option to display your Travis integrations:
+
+::
+
+ $ ansible-galaxy setup --list
+
+
+ ID Source Repo
+ ---------- ---------- ----------
+ 2 travis github_user/github_repo
+ 1 travis github_user/github_repo
+
+
+Remove Travis Integrations
+==========================
+
+Use the --remove option to disable and remove a Travis integration:
+
+::
+
+ $ ansible-galaxy setup --remove ID
+
+Provide the ID of the integration you want disabled. Use the --list option to get the ID.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docsite/rst/guide_cloudstack.rst b/docsite/rst/guide_cloudstack.rst
index 93b4540b09..c798b26ea1 100644
--- a/docsite/rst/guide_cloudstack.rst
+++ b/docsite/rst/guide_cloudstack.rst
@@ -178,8 +178,8 @@ Now to the fun part. We create a playbook to create our infrastructure we call i
- name: ensure firewall ports opened
cs_firewall:
- ip_address: {{ public_ip }}
- port: {{ item.port }}
+ ip_address: "{{ public_ip }}"
+ port: "{{ item.port }}"
cidr: "{{ item.cidr | default('0.0.0.0/0') }}"
with_items: cs_firewall
when: public_ip is defined
diff --git a/docsite/rst/guide_vagrant.rst b/docsite/rst/guide_vagrant.rst
index 2aad2f1a03..e5870bdd85 100644
--- a/docsite/rst/guide_vagrant.rst
+++ b/docsite/rst/guide_vagrant.rst
@@ -6,12 +6,13 @@ Using Vagrant and Ansible
Introduction
````````````
-Vagrant is a tool to manage virtual machine environments, and allows you to
-configure and use reproducible work environments on top of various
-virtualization and cloud platforms. It also has integration with Ansible as a
-provisioner for these virtual machines, and the two tools work together well.
+`Vagrant <http://vagrantup.com/>`_ is a tool to manage virtual machine
+environments, and allows you to configure and use reproducible work
+environments on top of various virtualization and cloud platforms.
+It also has integration with Ansible as a provisioner for these virtual
+machines, and the two tools work together well.
-This guide will describe how to use Vagrant and Ansible together.
+This guide will describe how to use Vagrant 1.7+ and Ansible together.
If you're not familiar with Vagrant, you should visit `the documentation
<http://docs.vagrantup.com/v2/>`_.
@@ -27,54 +28,48 @@ Vagrant Setup
The first step once you've installed Vagrant is to create a ``Vagrantfile``
and customize it to suit your needs. This is covered in detail in the Vagrant
-documentation, but here is a quick example:
+documentation, but here is a quick example that includes a section to use the
+Ansible provisioner to manage a single machine:
-.. code-block:: bash
+.. code-block:: ruby
- $ mkdir vagrant-test
- $ cd vagrant-test
- $ vagrant init precise32 http://files.vagrantup.com/precise32.box
+ # This guide is optimized for Vagrant 1.7 and above.
+ # Although versions 1.6.x should behave very similarly, it is recommended
+ # to upgrade instead of disabling the requirement below.
+ Vagrant.require_version ">= 1.7.0"
-This will create a file called Vagrantfile that you can edit to suit your
-needs. The default Vagrantfile has a lot of comments. Here is a simplified
-example that includes a section to use the Ansible provisioner:
+ Vagrant.configure(2) do |config|
-.. code-block:: ruby
+ config.vm.box = "ubuntu/trusty64"
+
+ # Disable the new default behavior introduced in Vagrant 1.7, to
+ # ensure that all Vagrant machines will use the same SSH key pair.
+ # See https://github.com/mitchellh/vagrant/issues/5005
+ config.ssh.insert_key = false
- # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
- VAGRANTFILE_API_VERSION = "2"
-
- Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
- config.vm.box = "precise32"
- config.vm.box_url = "http://files.vagrantup.com/precise32.box"
-
- config.vm.network :public_network
-
- config.vm.provision "ansible" do |ansible|
- ansible.playbook = "playbook.yml"
- end
+ config.vm.provision "ansible" do |ansible|
+ ansible.verbose = "v"
+ ansible.playbook = "playbook.yml"
end
+ end
-The Vagrantfile has a lot of options, but these are the most important ones.
Notice the ``config.vm.provision`` section that refers to an Ansible playbook
-called ``playbook.yml`` in the same directory as the Vagrantfile. Vagrant runs
-the provisioner once the virtual machine has booted and is ready for SSH
+called ``playbook.yml`` in the same directory as the ``Vagrantfile``. Vagrant
+runs the provisioner once the virtual machine has booted and is ready for SSH
access.
+There are a lot of Ansible options you can configure in your ``Vagrantfile``.
+Visit the `Ansible Provisioner documentation
+<http://docs.vagrantup.com/v2/provisioning/ansible.html>`_ for more
+information.
+
.. code-block:: bash
$ vagrant up
-This will start the VM and run the provisioning playbook.
-
-There are a lot of Ansible options you can configure in your Vagrantfile. Some
-particularly useful options are ``ansible.extra_vars``, ``ansible.sudo`` and
-``ansible.sudo_user``, and ``ansible.host_key_checking`` which you can disable
-to avoid SSH connection problems to new virtual machines.
+This will start the VM, and run the provisioning playbook (on the first VM
+startup).
-Visit the `Ansible Provisioner documentation
-<http://docs.vagrantup.com/v2/provisioning/ansible.html>`_ for more
-information.
To re-run a playbook on an existing VM, just run:
@@ -82,7 +77,19 @@ To re-run a playbook on an existing VM, just run:
$ vagrant provision
-This will re-run the playbook.
+This will re-run the playbook against the existing VM.
+
+Note that having the ``ansible.verbose`` option enabled will instruct Vagrant
+to show the full ``ansible-playbook`` command used behind the scene, as
+illustrated by this example:
+
+.. code-block:: bash
+
+ $ PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/home/someone/.vagrant.d/insecure_private_key --user=vagrant --connection=ssh --limit='machine1' --inventory-file=/home/someone/coding-in-a-project/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml
+
+This information can be quite useful to debug integration issues and can also
+be used to manually execute Ansible from a shell, as explained in the next
+section.
.. _running_ansible:
@@ -90,44 +97,58 @@ Running Ansible Manually
````````````````````````
Sometimes you may want to run Ansible manually against the machines. This is
-pretty easy to do.
+faster than kicking ``vagrant provision`` and pretty easy to do.
-Vagrant automatically creates an inventory file for each Vagrant machine in
-the same directory located under ``.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory``.
-It configures the inventory file according to the SSH tunnel that Vagrant
-automatically creates, and executes ``ansible-playbook`` with the correct
-username and SSH key options to allow access. A typical automatically-created
-inventory file may look something like this:
+With our ``Vagrantfile`` example, Vagrant automatically creates an Ansible
+inventory file in ``.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory``.
+This inventory is configured according to the SSH tunnel that Vagrant
+automatically creates. A typical automatically-created inventory file for a
+single machine environment may look something like this:
.. code-block:: none
# Generated by Vagrant
- machine ansible_host=127.0.0.1 ansible_port=2222
-
-.. include:: ansible_ssh_changes_note.rst
+ default ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
If you want to run Ansible manually, you will want to make sure to pass
-``ansible`` or ``ansible-playbook`` commands the correct arguments for the
-username (usually ``vagrant``) and the SSH key (since Vagrant 1.7.0, this will be something like
-``.vagrant/machines/[machine name]/[provider]/private_key``), and the autogenerated inventory file.
+``ansible`` or ``ansible-playbook`` commands the correct arguments, at least
+for the *username*, the *SSH private key* and the *inventory*.
+
+Here is an example using the Vagrant global insecure key (``config.ssh.insert_key``
+must be set to ``false`` in your ``Vagrantfile``):
-Here is an example:
+.. code-block:: bash
+
+ $ ansible-playbook --private-key=~/.vagrant.d/insecure_private_key -u vagrant -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml
+
+Here is a second example using the random private key that Vagrant 1.7+
+automatically configures for each new VM (each key is stored in a path like
+``.vagrant/machines/[machine name]/[provider]/private_key``):
.. code-block:: bash
-
- $ ansible-playbook -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory --private-key=.vagrant/machines/default/virtualbox/private_key -u vagrant playbook.yml
-Note: Vagrant versions prior to 1.7.0 will use the private key located at ``~/.vagrant.d/insecure_private_key.``
+ $ ansible-playbook --private-key=.vagrant/machines/default/virtualbox/private_key -u vagrant -i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory playbook.yml
+
+Advanced Usages
+```````````````
+
+The "Tips and Tricks" chapter of the `Ansible Provisioner documentation
+<http://docs.vagrantup.com/v2/provisioning/ansible.html>`_ provides detailed information about more advanced Ansible features like:
+
+ - how to parallely execute a playbook in a multi-machine environment
+ - how to integrate a local ``ansible.cfg`` configuration file
.. seealso::
- `Vagrant Home <http://www.vagrantup.com/>`_
- The Vagrant homepage with downloads
- `Vagrant Documentation <http://docs.vagrantup.com/v2/>`_
- Vagrant Documentation
- `Ansible Provisioner <http://docs.vagrantup.com/v2/provisioning/ansible.html>`_
- The Vagrant documentation for the Ansible provisioner
- :doc:`playbooks`
- An introduction to playbooks
+ `Vagrant Home <http://www.vagrantup.com/>`_
+ The Vagrant homepage with downloads
+ `Vagrant Documentation <http://docs.vagrantup.com/v2/>`_
+ Vagrant Documentation
+ `Ansible Provisioner <http://docs.vagrantup.com/v2/provisioning/ansible.html>`_
+ The Vagrant documentation for the Ansible provisioner
+ `Vagrant Issue Tracker <https://github.com/mitchellh/vagrant/issues?q=is%3Aopen+is%3Aissue+label%3Aprovisioners%2Fansible>`_
+ The open issues for the Ansible provisioner in the Vagrant project
+ :doc:`playbooks`
+ An introduction to playbooks
diff --git a/docsite/rst/index.rst b/docsite/rst/index.rst
index 936a485c9e..4f77125bb9 100644
--- a/docsite/rst/index.rst
+++ b/docsite/rst/index.rst
@@ -40,4 +40,5 @@ Ansible, Inc. releases a new major release of Ansible approximately every two mo
faq
glossary
YAMLSyntax
+ porting_guide_2.0
diff --git a/docsite/rst/intro_adhoc.rst b/docsite/rst/intro_adhoc.rst
index 9e104d5836..e9abdccc95 100644
--- a/docsite/rst/intro_adhoc.rst
+++ b/docsite/rst/intro_adhoc.rst
@@ -88,7 +88,7 @@ The ``-f 10`` in the above specifies the usage of 10 simultaneous
processes to use. You can also set this in :doc:`intro_configuration` to avoid setting it again. The default is actually 5, which
is really small and conservative. You are probably going to want to talk to a lot more simultaneous hosts so feel free
to crank this up. If you have more hosts than the value set for the fork count, Ansible will talk to them, but it will
-take a little longer. Feel free to push this value as high as your system can handle it!
+take a little longer. Feel free to push this value as high as your system can handle!
You can also select what Ansible "module" you want to run. Normally commands also take a ``-m`` for module name, but
the default module name is 'command', so we didn't need to
@@ -112,7 +112,7 @@ For example, using double rather than single quotes in the above example would
evaluate the variable on the box you were on.
So far we've been demoing simple command execution, but most Ansible modules usually do not work like
-simple scripts. They make the remote system look like you state, and run the commands necessary to
+simple scripts. They make the remote system look like a state, and run the commands necessary to
get it there. This is commonly referred to as 'idempotence', and is a core design goal of Ansible.
However, we also recognize that running arbitrary commands is equally important, so Ansible easily supports both.
@@ -170,7 +170,7 @@ Ensure a package is not installed::
Ansible has modules for managing packages under many platforms. If your package manager
does not have a module available for it, you can install
-for other packages using the command module or (better!) contribute a module
+packages using the command module or (better!) contribute a module
for other package managers. Stop by the mailing list for info/details.
.. _users_and_groups:
@@ -249,7 +249,7 @@ very quickly. After the time limit (in seconds) runs out (``-B``), the process o
the remote nodes will be terminated.
Typically you'll only be backgrounding long-running
-shell commands or software upgrades only. Backgrounding the copy module does not do a background file transfer. :doc:`Playbooks <playbooks>` also support polling, and have a simplified syntax for this.
+shell commands or software upgrades. Backgrounding the copy module does not do a background file transfer. :doc:`Playbooks <playbooks>` also support polling, and have a simplified syntax for this.
.. _checking_facts:
diff --git a/docsite/rst/intro_bsd.rst b/docsite/rst/intro_bsd.rst
index 17c1b8d151..ba0e07f2c8 100644
--- a/docsite/rst/intro_bsd.rst
+++ b/docsite/rst/intro_bsd.rst
@@ -30,7 +30,7 @@ Bootstrapping BSD
For Ansible to effectively manage your machine, we need to install Python along with a json library, in this case we are using Python 2.7 which already has json included.
On your control machine you can simply execute the following for most versions of FreeBSD::
- ansible -m raw -a “pkg_add -r python27” mybsdhost1
+ ansible -m raw -a “pkg install -y python27” mybsdhost1
Once this is done you can now use other Ansible modules aside from the ``raw`` module.
diff --git a/docsite/rst/intro_configuration.rst b/docsite/rst/intro_configuration.rst
index dda07fc450..51a1ad1e58 100644
--- a/docsite/rst/intro_configuration.rst
+++ b/docsite/rst/intro_configuration.rst
@@ -587,11 +587,12 @@ the sudo implementation is matching CLI flags with the standard sudo::
sudo_flags
==========
-Additional flags to pass to sudo when engaging sudo support. The default is '-H' which preserves the $HOME environment variable
-of the original user. In some situations you may wish to add or remove flags, but in general most users
-will not need to change this setting::
+Additional flags to pass to sudo when engaging sudo support. The default is '-H -S -n' which sets the HOME environment
+variable, prompts for passwords via STDIN, and avoids prompting the user for input of any kind. Note that '-n' will conflict
+with using password-less sudo auth, such as pam_ssh_agent_auth. In some situations you may wish to add or remove flags, but
+in general most users will not need to change this setting:::
- sudo_flags=-H
+ sudo_flags=-H -S -n
.. _sudo_user:
@@ -897,3 +898,19 @@ The normal behaviour is for operations to copy the existing context or use the u
The default list is: nfs,vboxsf,fuse,ramfs::
special_context_filesystems = nfs,vboxsf,fuse,ramfs,myspecialfs
+
+Galaxy Settings
+---------------
+
+The following options can be set in the [galaxy] section of ansible.cfg:
+
+server
+======
+
+Override the default Galaxy server value of https://galaxy.ansible.com. Useful if you have a hosted version of the Galaxy web app or want to point to the testing site https://galaxy-qa.ansible.com. It does not work against private, hosted repos, which Galaxy can use for fetching and installing roles.
+
+ignore_certs
+============
+
+If set to *yes*, ansible-galaxy will not validate TLS certificates. Handy for testing against a server with a self-signed certificate
+.
diff --git a/docsite/rst/intro_dynamic_inventory.rst b/docsite/rst/intro_dynamic_inventory.rst
index 1a2bd6f72c..71f6408176 100644
--- a/docsite/rst/intro_dynamic_inventory.rst
+++ b/docsite/rst/intro_dynamic_inventory.rst
@@ -111,9 +111,8 @@ If you use boto profiles to manage multiple AWS accounts, you can pass ``--profi
aws_access_key_id = <prod access key>
aws_secret_access_key = <prod secret key>
-You can then run ``ec2.py --profile prod`` to get the inventory for the prod account, or run playbooks with: ``ansible-playbook -i 'ec2.py --profile prod' myplaybook.yml``.
-
-Alternatively, use the ``AWS_PROFILE`` variable - e.g. ``AWS_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml``
+You can then run ``ec2.py --profile prod`` to get the inventory for the prod account, this option is not supported by ``anisble-playbook`` though.
+But you can use the ``AWS_PROFILE`` variable - e.g. ``AWS_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml``
Since each region requires its own API call, if you are only using a small set of regions, feel free to edit ``ec2.ini`` and list only the regions you are interested in. There are other config options in ``ec2.ini`` including cache control, and destination variables.
@@ -207,6 +206,77 @@ explicitly clear the cache, you can run the ec2.py script with the ``--refresh-c
# ./ec2.py --refresh-cache
+.. _openstack_example:
+
+Example: OpenStack External Inventory Script
+````````````````````````````````````````````
+
+If you use an OpenStack based cloud, instead of manually maintaining your own inventory file, you can use the openstack.py dynamic inventory to pull information about your compute instances directly from OpenStack.
+
+You can download the latest version of the OpenStack inventory script at: https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.py
+
+You can use the inventory script explicitly (by passing the `-i openstack.py` argument to Ansible) or implicitly (by placing the script at `/etc/ansible/hosts`).
+
+Explicit use of inventory script
+++++++++++++++++++++++++++++++++
+
+Download the latest version of the OpenStack dynamic inventory script and make it executable::
+
+ wget https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.py
+ chmod +x openstack.py
+
+Source an OpenStack RC file::
+
+ source openstack.rc
+
+.. note::
+
+ An OpenStack RC file contains the environment variables required by the client tools to establish a connection with the cloud provider, such as the authentication URL, user name, password and region name. For more information on how to download, create or source an OpenStack RC file, please refer to http://docs.openstack.org/cli-reference/content/cli_openrc.html.
+
+You can confirm the file has been successfully sourced by running a simple command, such as `nova list` and ensuring it return no errors.
+
+.. note::
+
+ The OpenStack command line clients are required to run the `nova list` command. For more information on how to install them, please refer to http://docs.openstack.org/cli-reference/content/install_clients.html.
+
+You can test the OpenStack dynamic inventory script manually to confirm it is working as expected::
+
+ ./openstack.py --list
+
+After a few moments you should see some JSON output with information about your compute instances.
+
+Once you confirm the dynamic inventory script is working as expected, you can tell Ansible to use the `openstack.py` script as an inventory file, as illustrated below::
+
+ ansible -i openstack.py all -m ping
+
+Implicit use of inventory script
+++++++++++++++++++++++++++++++++
+
+Download the latest version of the OpenStack dynamic inventory script, make it executable and copy it to `/etc/ansible/hosts`::
+
+ wget https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.py
+ chmod +x openstack.py
+ sudo cp openstack.py /etc/ansible/hosts
+
+Download the sample configuration file, modify it to suit your needs and copy it to `/etc/ansible/openstack.yml`::
+
+ wget https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.yml
+ vi openstack.yml
+ sudo cp openstack.yml /etc/ansible/
+
+You can test the OpenStack dynamic inventory script manually to confirm it is working as expected::
+
+ /etc/ansible/hosts --list
+
+After a few moments you should see some JSON output with information about your compute instances.
+
+Refresh the cache
++++++++++++++++++
+
+Note that the OpenStack dynamic inventory script will cache results to avoid repeated API calls. To explicitly clear the cache, you can run the openstack.py (or hosts) script with the --refresh parameter:
+
+ ./openstack.py --refresh
+
.. _other_inventory_scripts:
Other inventory scripts
diff --git a/docsite/rst/intro_getting_started.rst b/docsite/rst/intro_getting_started.rst
index d6a22a8bb4..7b783209de 100644
--- a/docsite/rst/intro_getting_started.rst
+++ b/docsite/rst/intro_getting_started.rst
@@ -33,7 +33,7 @@ In releases up to and including Ansible 1.2, the default was strictly paramiko.
Occasionally you'll encounter a device that doesn't support SFTP. This is rare, but should it occur, you can switch to SCP mode in :doc:`intro_configuration`.
-When speaking with remote machines, Ansible by default assumes you are using SSH keys. SSH keys are encouraged but password authentication can also be used where needed by supplying the option ``--ask-pass``. If using sudo features and when sudo requires a password, also supply ``--ask-sudo-pass``.
+When speaking with remote machines, Ansible by default assumes you are using SSH keys. SSH keys are encouraged but password authentication can also be used where needed by supplying the option ``--ask-pass``. If using sudo features and when sudo requires a password, also supply ``--ask-become-pass`` (previously ``--ask-sudo-pass`` which has been depricated).
While it may be common sense, it is worth sharing: Any management system benefits from being run near the machines being managed. If you are running Ansible in a cloud, consider running it from a machine inside that cloud. In most cases this will work better than on the open Internet.
diff --git a/docsite/rst/intro_installation.rst b/docsite/rst/intro_installation.rst
index 28bbd69151..99e2661226 100644
--- a/docsite/rst/intro_installation.rst
+++ b/docsite/rst/intro_installation.rst
@@ -27,12 +27,11 @@ What Version To Pick?
`````````````````````
Because it runs so easily from source and does not require any installation of software on remote
-machines, many users will actually track the development version.
+machines, many users will actually track the development version.
-Ansible's release cycles are usually about two months long. Due to this
-short release cycle, minor bugs will generally be fixed in the next release versus maintaining
-backports on the stable branch. Major bugs will still have maintenance releases when needed, though
-these are infrequent.
+Ansible's release cycles are usually about four months long. Due to this short release cycle,
+minor bugs will generally be fixed in the next release versus maintaining backports on the stable branch.
+Major bugs will still have maintenance releases when needed, though these are infrequent.
If you are wishing to run the latest released version of Ansible and you are running Red Hat Enterprise Linux (TM), CentOS, Fedora, Debian, or Ubuntu, we recommend using the OS package manager.
@@ -52,8 +51,8 @@ This includes Red Hat, Debian, CentOS, OS X, any of the BSDs, and so on.
.. note::
- As of 2.0 ansible uses a few more file handles to manage it's forks, OS X has a very low setting so if you want to use 15 or more forks
- you'll need to raise the ulimit, like so ``sudo launchctl limit maxfiles 1024 2048``. Or just any time you see a "Too many open files" error.
+ As of 2.0 ansible uses a few more file handles to manage its forks, OS X has a very low setting so if you want to use 15 or more forks
+ you'll need to raise the ulimit, like so ``sudo launchctl limit maxfiles 1024 unlimited``. Or just any time you see a "Too many open files" error.
.. _managed_node_requirements:
diff --git a/docsite/rst/intro_patterns.rst b/docsite/rst/intro_patterns.rst
index a97aed42d4..f7f7994887 100644
--- a/docsite/rst/intro_patterns.rst
+++ b/docsite/rst/intro_patterns.rst
@@ -31,7 +31,7 @@ It is also possible to address a specific host or set of hosts by name::
192.168.1.50
192.168.1.*
-The following patterns address one or more groups. Groups separated by a comma indicate an "OR" configuration.
+The following patterns address one or more groups. Groups separated by a colon indicate an "OR" configuration.
This means the host may be in either one group or the other::
webservers
diff --git a/docsite/rst/intro_windows.rst b/docsite/rst/intro_windows.rst
index 64cd64b885..b9b195643b 100644
--- a/docsite/rst/intro_windows.rst
+++ b/docsite/rst/intro_windows.rst
@@ -26,12 +26,12 @@ Installing on the Control Machine
On a Linux control machine::
- pip install https://github.com/diyan/pywinrm/archive/master.zip#egg=pywinrm
+ pip install "pywinrm>=0.1.1"
Active Directory Support
++++++++++++++++++++++++
-If you wish to connect to domain accounts published through Active Directory (as opposed to local accounts created on the remote host), you will need to install the "python-kerberos" module and the MIT krb5 libraries it depends on.
+If you wish to connect to domain accounts published through Active Directory (as opposed to local accounts created on the remote host), you will need to install the "python-kerberos" module on the Ansible control host (and the MIT krb5 libraries it depends on). The Ansible control host also requires a properly configured computer account in Active Directory.
Installing python-kerberos dependencies
---------------------------------------
@@ -131,7 +131,9 @@ To test this, ping the windows host you want to control by name then use the ip
If you get different hostnames back than the name you originally pinged, speak to your active directory administrator and get them to check that DNS Scavenging is enabled and that DNS and DHCP are updating each other.
-Check your ansible controller's clock is synchronised with your domain controller. Kerberos is time sensitive and a little clock drift can cause tickets not be granted.
+Ensure that the Ansible controller has a properly configured computer account in the domain.
+
+Check your Ansible controller's clock is synchronised with your domain controller. Kerberos is time sensitive and a little clock drift can cause tickets not be granted.
Check you are using the real fully qualified domain name for the domain. Sometimes domains are commonly known to users by aliases. To check this run:
@@ -165,6 +167,8 @@ In group_vars/windows.yml, define the following inventory variables::
ansible_password: SecretPasswordGoesHere
ansible_port: 5986
ansible_connection: winrm
+ # The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates:
+ ansible_winrm_server_cert_validation: ignore
Although Ansible is mostly an SSH-oriented system, Windows management will not happen over SSH (`yet <http://blogs.msdn.com/b/powershell/archive/2015/06/03/looking-forward-microsoft-support-for-secure-shell-ssh.aspx>`).
@@ -189,6 +193,7 @@ Since 2.0, the following custom inventory variables are also supported for addit
* ``ansible_winrm_path``: Specify an alternate path to the WinRM endpoint. Ansible uses ``/wsman`` by default.
* ``ansible_winrm_realm``: Specify the realm to use for Kerberos authentication. If the username contains ``@``, Ansible will use the part of the username after ``@`` by default.
* ``ansible_winrm_transport``: Specify one or more transports as a comma-separated list. By default, Ansible will use ``kerberos,plaintext`` if the ``kerberos`` module is installed and a realm is defined, otherwise ``plaintext``.
+* ``ansible_winrm_server_cert_validation``: Specify the server certificate validation mode (``ignore`` or ``validate``). Ansible defaults to ``validate`` on Python 2.7.9 and higher, which will result in certificate validation errors against the Windows self-signed certificates. Unless verifiable certificates have been configured on the WinRM listeners, this should be set to ``ignore``
* ``ansible_winrm_*``: Any additional keyword arguments supported by ``winrm.Protocol`` may be provided.
.. _windows_system_prep:
@@ -221,7 +226,7 @@ Getting to PowerShell 3.0 or higher
PowerShell 3.0 or higher is needed for most provided Ansible modules for Windows, and is also required to run the above setup script. Note that PowerShell 3.0 is only supported on Windows 7 SP1, Windows Server 2008 SP1, and later releases of Windows.
-Looking at an ansible checkout, copy the `examples/scripts/upgrade_to_ps3.ps1 <https://github.com/cchurch/ansible/blob/devel/examples/scripts/upgrade_to_ps3.ps1>`_ script onto the remote host and run a PowerShell console as an administrator. You will now be running PowerShell 3 and can try connectivity again using the win_ping technique referenced above.
+Looking at an Ansible checkout, copy the `examples/scripts/upgrade_to_ps3.ps1 <https://github.com/cchurch/ansible/blob/devel/examples/scripts/upgrade_to_ps3.ps1>`_ script onto the remote host and run a PowerShell console as an administrator. You will now be running PowerShell 3 and can try connectivity again using the win_ping technique referenced above.
.. _what_windows_modules_are_available:
@@ -248,13 +253,10 @@ Note there are a few other Ansible modules that don't start with "win" that also
Developers: Supported modules and how it works
``````````````````````````````````````````````
-Developing ansible modules are covered in a `later section of the documentation <http://docs.ansible.com/developing_modules.html>`_, with a focus on Linux/Unix.
-What if you want to write Windows modules for ansible though?
-
-For Windows, ansible modules are implemented in PowerShell. Skim those Linux/Unix module development chapters before proceeding.
+Developing Ansible modules are covered in a `later section of the documentation <http://docs.ansible.com/developing_modules.html>`_, with a focus on Linux/Unix.
+What if you want to write Windows modules for Ansible though?
-Windows modules live in a "windows/" subfolder in the Ansible "library/" subtree. For example, if a module is named
-"library/windows/win_ping", there will be embedded documentation in the "win_ping" file, and the actual PowerShell code will live in a "win_ping.ps1" file. Take a look at the sources and this will make more sense.
+For Windows, Ansible modules are implemented in PowerShell. Skim those Linux/Unix module development chapters before proceeding. Windows modules in the core and extras repo live in a "windows/" subdir. Custom modules can go directly into the Ansible "library/" directories or those added in ansible.cfg. Documentation lives in a a `.py` file with the same name. For example, if a module is named "win_ping", there will be embedded documentation in the "win_ping.py" file, and the actual PowerShell code will live in a "win_ping.ps1" file. Take a look at the sources and this will make more sense.
Modules (ps1 files) should start as follows::
@@ -317,6 +319,14 @@ Running individual commands uses the 'raw' module, as opposed to the shell or co
register: ipconfig
- debug: var=ipconfig
+Running common DOS commands like 'del", 'move', or 'copy" is unlikely to work on a remote Windows Server using Powershell, but they can work by prefacing the commands with "CMD /C" and enclosing the command in double quotes as in this example::
+
+ - name: another raw module example
+ hosts: windows
+ tasks:
+ - name: Move file on remote Windows Server from one location to another
+ raw: CMD /C "MOVE /Y C:\teststuff\myfile.conf C:\builds\smtp.conf"
+
And for a final example, here's how to use the win_stat module to test for file existence. Note that the data returned by the win_stat module is slightly different than what is provided by the Linux equivalent::
- name: test stat module
@@ -351,7 +361,7 @@ form of new modules, tweaks to existing modules, documentation, or something els
:doc:`developing_modules`
How to write modules
:doc:`playbooks`
- Learning ansible's configuration management language
+ Learning Ansible's configuration management language
`List of Windows Modules <http://docs.ansible.com/list_of_windows_modules.html>`_
Windows specific module list, all implemented in PowerShell
`Mailing List <http://groups.google.com/group/ansible-project>`_
diff --git a/docsite/rst/modules_core.rst b/docsite/rst/modules_core.rst
index 6364a1556f..4d692dad15 100644
--- a/docsite/rst/modules_core.rst
+++ b/docsite/rst/modules_core.rst
@@ -8,6 +8,6 @@ The source of these modules is hosted on GitHub in the `ansible-modules-core <ht
If you believe you have found a bug in a core module and are already running the latest stable or development version of Ansible, first look in the `issue tracker at github.com/ansible/ansible-modules-core <http://github.com/ansible/ansible-modules-core>`_ to see if a bug has already been filed. If not, we would be grateful if you would file one.
-Should you have a question rather than a bug report, inquries are welcome on the `ansible-project google group <https://groups.google.com/forum/#!forum/ansible-project>`_ or on Ansible's "#ansible" channel, located on irc.freenode.net. Development oriented topics should instead use the similar `ansible-devel google group <https://groups.google.com/forum/#!forum/ansible-devel>`_.
+Should you have a question rather than a bug report, inquiries are welcome on the `ansible-project google group <https://groups.google.com/forum/#!forum/ansible-project>`_ or on Ansible's "#ansible" channel, located on irc.freenode.net. Development oriented topics should instead use the similar `ansible-devel google group <https://groups.google.com/forum/#!forum/ansible-devel>`_.
Documentation updates for these modules can also be edited directly in the module itself and by submitting a pull request to the module source code, just look for the "DOCUMENTATION" block in the source tree.
diff --git a/docsite/rst/playbooks_best_practices.rst b/docsite/rst/playbooks_best_practices.rst
index ecca4d75cb..653d7f8a19 100644
--- a/docsite/rst/playbooks_best_practices.rst
+++ b/docsite/rst/playbooks_best_practices.rst
@@ -254,8 +254,8 @@ What about just my webservers in Boston?::
What about just the first 10, and then the next 10?::
- ansible-playbook -i production webservers.yml --limit boston[0-10]
- ansible-playbook -i production webservers.yml --limit boston[10-20]
+ ansible-playbook -i production webservers.yml --limit boston[1-10]
+ ansible-playbook -i production webservers.yml --limit boston[11-20]
And of course just basic ad-hoc stuff is also possible.::
diff --git a/docsite/rst/playbooks_conditionals.rst b/docsite/rst/playbooks_conditionals.rst
index 15d397c7ac..47cc844f45 100644
--- a/docsite/rst/playbooks_conditionals.rst
+++ b/docsite/rst/playbooks_conditionals.rst
@@ -47,7 +47,7 @@ decide to do something conditionally based on success or failure::
- command: /bin/something
when: result|failed
- command: /bin/something_else
- when: result|success
+ when: result|succeeded
- command: /bin/still/something_else
when: result|skipped
diff --git a/docsite/rst/playbooks_delegation.rst b/docsite/rst/playbooks_delegation.rst
index 4411e4aa29..fa808abb65 100644
--- a/docsite/rst/playbooks_delegation.rst
+++ b/docsite/rst/playbooks_delegation.rst
@@ -130,6 +130,29 @@ Here is an example::
Note that you must have passphrase-less SSH keys or an ssh-agent configured for this to work, otherwise rsync
will need to ask for a passphrase.
+.. _delegate_facts:
+
+Delegated facts
+```````````````
+
+.. versionadded:: 2.0
+
+By default, any fact gathered by a delegated task are assigned to the `inventory_hostname` (the current host) instead of the host which actually produced the facts (the delegated to host).
+In 2.0, the directive `delegate_facts` may be set to `True` to assign the task's gathered facts to the delegated host instead of the current one.::
+
+
+ - hosts: app_servers
+ tasks:
+ - name: gather facts from db servers
+ setup:
+ delegate_to: "{{item}}"
+ delegate_facts: True
+ with_items: "{{groups['dbservers'}}"
+
+The above will gather facts for the machines in the dbservers group and assign the facts to those machines and not to app_servers.
+This way you can lookup `hostvars['dbhost1']['default_ipv4_addresses'][0]` even though dbservers were not part of the play, or left out by using `--limit`.
+
+
.. _run_once:
Run Once
@@ -159,13 +182,18 @@ This can be optionally paired with "delegate_to" to specify an individual host t
delegate_to: web01.example.org
When "run_once" is not used with "delegate_to" it will execute on the first host, as defined by inventory,
-in the group(s) of hosts targeted by the play. e.g. webservers[0] if the play targeted "hosts: webservers".
+in the group(s) of hosts targeted by the play - e.g. webservers[0] if the play targeted "hosts: webservers".
-This approach is similar, although more concise and cleaner than applying a conditional to a task such as::
+This approach is similar to applying a conditional to a task such as::
- command: /opt/application/upgrade_db.py
when: inventory_hostname == webservers[0]
+.. note::
+ When used together with "serial", tasks marked as "run_once" will be ran on one host in *each* serial batch.
+ If it's crucial that the task is run only once regardless of "serial" mode, use
+ :code:`inventory_hostname == my_group_name[0]` construct.
+
.. _local_playbooks:
Local Playbooks
diff --git a/docsite/rst/playbooks_environment.rst b/docsite/rst/playbooks_environment.rst
index da050f007d..f909bfcd6e 100644
--- a/docsite/rst/playbooks_environment.rst
+++ b/docsite/rst/playbooks_environment.rst
@@ -31,7 +31,7 @@ The environment can also be stored in a variable, and accessed like so::
tasks:
- apt: name=cobbler state=installed
- environment: proxy_env
+ environment: "{{proxy_env}}"
You can also use it at a playbook level::
diff --git a/docsite/rst/playbooks_filters.rst b/docsite/rst/playbooks_filters.rst
index 7d4ace9c4b..05ff830e3b 100644
--- a/docsite/rst/playbooks_filters.rst
+++ b/docsite/rst/playbooks_filters.rst
@@ -58,12 +58,17 @@ The following tasks are illustrative of how filters can be used with conditional
- debug: msg="it changed"
when: result|changed
+ - debug: msg="it succeeded in Ansible >= 2.1"
+ when: result|succeeded
+
- debug: msg="it succeeded"
when: result|success
- debug: msg="it was skipped"
when: result|skipped
+.. note:: From 2.1 You can also use success, failure, change, skip so the grammer matches, for those that want to be strict about it.
+
.. _forcing_variables_to_be_defined:
Forcing Variables To Be Defined
@@ -352,6 +357,39 @@ override those in `b`, and so on.
This behaviour does not depend on the value of the `hash_behaviour`
setting in `ansible.cfg`.
+.. _extract_filter:
+
+Extracting values from containers
+---------------------------------
+
+.. versionadded:: 2.1
+
+The `extract` filter is used to map from a list of indices to a list of
+values from a container (hash or array)::
+
+ {{ [0,2]|map('extract', ['x','y','z'])|list }}
+ {{ ['x','y']|map('extract', {'x': 42, 'y': 31})|list }}
+
+The results of the above expressions would be::
+
+ ['x', 'z']
+ [42, 31]
+
+The filter can take another argument::
+
+ {{ groups['x']|map('extract', hostvars, 'ec2_ip_address')|list }}
+
+This takes the list of hosts in group 'x', looks them up in `hostvars`,
+and then looks up the `ec2_ip_address` of the result. The final result
+is a list of IP addresses for the hosts in group 'x'.
+
+The third argument to the filter can also be a list, for a recursive
+lookup inside the container::
+
+ {{ ['a']|map('extract', b, ['x','y'])|list }}
+
+This would return a list containing the value of `b['a']['x']['y']`.
+
.. _comment_filter:
Comment Filter
@@ -514,20 +552,25 @@ To match strings against a regex, use the "match" or "search" filter::
To replace text in a string with regex, use the "regex_replace" filter::
- # convert "ansible" to "able"
+ # convert "ansible" to "able"
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}
# convert "foobar" to "bar"
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}
+ # convert "localhost:80" to "localhost, 80" using named groups
+ {{ 'localhost:80' | regex_replace('^(?P<host>.+):(?P<port>\\d+)$', '\\g<host>, \\g<port>') }}
+
.. note:: Prior to ansible 2.0, if "regex_replace" filter was used with variables inside YAML arguments (as opposed to simpler 'key=value' arguments),
then you needed to escape backreferences (e.g. ``\\1``) with 4 backslashes (``\\\\``) instead of 2 (``\\``).
+.. versionadded:: 2.0
+
To escape special characters within a regex, use the "regex_escape" filter::
# convert '^f.*o(.*)$' to '\^f\.\*o\(\.\*\)\$'
{{ '^f.*o(.*)$' | regex_escape() }}
-
+
To make use of one attribute from each item in a list of complex variables, use the "map" filter (see the `Jinja2 map() docs`_ for more)::
# get a comma-separated list of the mount points (e.g. "/,/mnt/stuff") on a host
diff --git a/docsite/rst/playbooks_intro.rst b/docsite/rst/playbooks_intro.rst
index e0f1aec5c1..55cd3359be 100644
--- a/docsite/rst/playbooks_intro.rst
+++ b/docsite/rst/playbooks_intro.rst
@@ -41,7 +41,7 @@ Each playbook is composed of one or more 'plays' in a list.
The goal of a play is to map a group of hosts to some well defined roles, represented by
things ansible calls tasks. At a basic level, a task is nothing more than a call
-to an ansible module, which you should have learned about in earlier chapters.
+to an ansible module (see :doc:`Modules`).
By composing a playbook of multiple 'plays', it is possible to
orchestrate multi-machine deployments, running certain steps on all
@@ -386,6 +386,7 @@ won't need them for much else.
* Handler names live in a global namespace.
* If two handler tasks have the same name, only one will run.
`* <https://github.com/ansible/ansible/issues/4943>`_
+ * You cannot notify a handler that is defined inside of an include
Roles are described later on, but it's worthwhile to point out that:
diff --git a/docsite/rst/playbooks_lookups.rst b/docsite/rst/playbooks_lookups.rst
index 25560e284d..3c2222c337 100644
--- a/docsite/rst/playbooks_lookups.rst
+++ b/docsite/rst/playbooks_lookups.rst
@@ -240,6 +240,112 @@ If you're not using 2.0 yet, you can do something similar with the credstash too
debug: msg="Poor man's credstash lookup! {{ lookup('pipe', 'credstash -r us-west-1 get my-other-password') }}"
+.. _dns_lookup:
+
+The DNS Lookup (dig)
+````````````````````
+.. versionadded:: 1.9.0
+
+.. warning:: This lookup depends on the `dnspython <http://www.dnspython.org/>`_
+ library.
+
+The ``dig`` lookup runs queries against DNS servers to retrieve DNS records for
+a specific name (*FQDN* - fully qualified domain name). It is possible to lookup any DNS record in this manner.
+
+There is a couple of different syntaxes that can be used to specify what record
+should be retrieved, and for which name. It is also possible to explicitly
+specify the DNS server(s) to use for lookups.
+
+In its simplest form, the ``dig`` lookup plugin can be used to retrieve an IPv4
+address (DNS ``A`` record) associated with *FQDN*:
+
+.. note:: If you need to obtain the ``AAAA`` record (IPv6 address), you must
+ specify the record type explicitly. Syntax for specifying the record
+ type is described below.
+
+.. note:: The trailing dot in most of the examples listed is purely optional,
+ but is specified for completeness/correctness sake.
+
+::
+
+ - debug: msg="The IPv4 address for example.com. is {{ lookup('dig', 'example.com.')}}"
+
+In addition to (default) ``A`` record, it is also possible to specify a different
+record type that should be queried. This can be done by either passing-in
+additional parameter of format ``qtype=TYPE`` to the ``dig`` lookup, or by
+appending ``/TYPE`` to the *FQDN* being queried. For example::
+
+ - debug: msg="The TXT record for gmail.com. is {{ lookup('dig', 'gmail.com.', 'qtype=TXT') }}"
+ - debug: msg="The TXT record for gmail.com. is {{ lookup('dig', 'gmail.com./TXT') }}"
+
+If multiple values are associated with the requested record, the results will be
+returned as a comma-separated list. In such cases you may want to pass option
+``wantlist=True`` to the plugin, which will result in the record values being
+returned as a list over which you can iterate later on::
+
+ - debug: msg="One of the MX records for gmail.com. is {{ item }}"
+ with_items: "{{ lookup('dig', 'gmail.com./MX', wantlist=True) }}"
+
+In case of reverse DNS lookups (``PTR`` records), you can also use a convenience
+syntax of format ``IP_ADDRESS/PTR``. The following three lines would produce the
+same output::
+
+ - debug: msg="Reverse DNS for 8.8.8.8 is {{ lookup('dig', '8.8.8.8/PTR') }}"
+ - debug: msg="Reverse DNS for 8.8.8.8 is {{ lookup('dig', '8.8.8.8.in-addr.arpa./PTR') }}"
+ - debug: msg="Reverse DNS for 8.8.8.8 is {{ lookup('dig', '8.8.8.8.in-addr.arpa.', 'qtype=PTR') }}"
+
+By default, the lookup will rely on system-wide configured DNS servers for
+performing the query. It is also possible to explicitly specify DNS servers to
+query using the ``@DNS_SERVER_1,DNS_SERVER_2,...,DNS_SERVER_N`` notation. This
+needs to be passed-in as an additional parameter to the lookup. For example::
+
+ - debug: msg="Querying 8.8.8.8 for IPv4 address for example.com. produces {{ lookup('dig', 'example.com', '@8.8.8.8') }}"
+
+In some cases the DNS records may hold a more complex data structure, or it may
+be useful to obtain the results in a form of a dictionary for future
+processing. The ``dig`` lookup supports parsing of a number of such records,
+with the result being returned as a dictionary. This way it is possible to
+easily access such nested data. This return format can be requested by
+passing-in the ``flat=0`` option to the lookup. For example::
+
+ - debug: msg="XMPP service for gmail.com. is available at {{ item.target }} on port {{ item.port }}"
+ with_items: "{{ lookup('dig', '_xmpp-server._tcp.gmail.com./SRV', 'flat=0', wantlist=True) }}"
+
+Take note that due to the way Ansible lookups work, you must pass the
+``wantlist=True`` argument to the lookup, otherwise Ansible will report errors.
+
+Currently the dictionary results are supported for the following records:
+
+.. note:: *ALL* is not a record per-se, merely the listed fields are available
+ for any record results you retrieve in the form of a dictionary.
+
+========== =============================================================================
+Record Fields
+---------- -----------------------------------------------------------------------------
+*ALL* owner, ttl, type
+A address
+AAAA address
+CNAME target
+DNAME target
+DLV algorithm, digest_type, key_tag, digest
+DNSKEY flags, algorithm, protocol, key
+DS algorithm, digest_type, key_tag, digest
+HINFO cpu, os
+LOC latitude, longitude, altitude, size, horizontal_precision, vertical_precision
+MX preference, exchange
+NAPTR order, preference, flags, service, regexp, replacement
+NS target
+NSEC3PARAM algorithm, flags, iterations, salt
+PTR target
+RP mbox, txt
+SOA mname, rname, serial, refresh, retry, expire, minimum
+SPF strings
+SRV priority, weight, port, target
+SSHFP algorithm, fp_type, fingerprint
+TLSA usage, selector, mtype, cert
+TXT strings
+========== =============================================================================
+
.. _more_lookups:
More Lookups
diff --git a/docsite/rst/playbooks_loops.rst b/docsite/rst/playbooks_loops.rst
index 9cb8083b9b..6f14922dea 100644
--- a/docsite/rst/playbooks_loops.rst
+++ b/docsite/rst/playbooks_loops.rst
@@ -96,7 +96,7 @@ And you want to print every user's name and phone number. You can loop through
Looping over Files
``````````````````
-``with_file`` iterates over a list of files, setting `item` to the content of each file in sequence. It can be used like this::
+``with_file`` iterates over the content of a list of files, `item` will be set to the content of each file in sequence. It can be used like this::
---
- hosts: all
@@ -516,10 +516,37 @@ Subsequent loops over the registered variable to inspect the results may look li
+.. _looping_over_the_inventory:
+
+Looping over the inventory
+``````````````````````````
+
+If you wish to loop over the inventory, or just a subset of it, there is multiple ways.
+One can use a regular ``with_items`` with the ``play_hosts`` or ``groups`` variables, like this::
+
+ # show all the hosts in the inventory
+ - debug: msg={{ item }}
+ with_items: "{{groups['all']}}"
+
+ # show all the hosts in the current play
+ - debug: msg={{ item }}
+ with_items: play_hosts
+
+There is also a specific lookup plugin ``inventory_hostname`` that can be used like this::
+
+ # show all the hosts in the inventory
+ - debug: msg={{ item }}
+ with_inventory_hostname: all
+
+ # show all the hosts matching the pattern, ie all but the group www
+ - debug: msg={{ item }}
+ with_inventory_hostname: all:!www
+
+More information on the patterns can be found on :doc:`intro_patterns`
+
.. _loops_and_includes:
Loops and Includes
-
``````````````````
In 2.0 you are able to use `with_` loops and task includes (but not playbook includes), this adds the ability to loop over the set of tasks in one shot.
diff --git a/docsite/rst/playbooks_roles.rst b/docsite/rst/playbooks_roles.rst
index 516403ac80..73c9710f51 100644
--- a/docsite/rst/playbooks_roles.rst
+++ b/docsite/rst/playbooks_roles.rst
@@ -132,7 +132,7 @@ Note that you cannot do variable substitution when including one playbook
inside another.
.. note::
- You can not conditionally path the location to an include file,
+ You can not conditionally pass the location to an include file,
like you can with 'vars_files'. If you find yourself needing to do
this, consider how you can restructure your playbook to be more
class/role oriented. This is to say you cannot use a 'fact' to
@@ -191,11 +191,8 @@ This designates the following behaviors, for each role 'x':
- If roles/x/handlers/main.yml exists, handlers listed therein will be added to the play
- If roles/x/vars/main.yml exists, variables listed therein will be added to the play
- If roles/x/meta/main.yml exists, any role dependencies listed therein will be added to the list of roles (1.3 and later)
-- Any copy tasks can reference files in roles/x/files/ without having to path them relatively or absolutely
-- Any script tasks can reference scripts in roles/x/files/ without having to path them relatively or absolutely
-- Any template tasks can reference files in roles/x/templates/ without having to path them relatively or absolutely
-- Any include tasks can reference files in roles/x/tasks/ without having to path them relatively or absolutely
-
+- Any copy, script, template or include tasks (in the role) can reference files in roles/x/{files,templates,tasks}/ (dir depends on task) without having to path them relatively or absolutely
+
In Ansible 1.4 and later you can configure a roles_path to search for roles. Use this to check all of your common roles out to one location, and share
them easily between multiple playbook projects. See :doc:`intro_configuration` for details about how to set this up in ansible.cfg.
@@ -216,8 +213,8 @@ Also, should you wish to parameterize roles, by adding variables, you can do so,
- hosts: webservers
roles:
- common
- - { role: foo_app_instance, dir: '/opt/a', port: 5000 }
- - { role: foo_app_instance, dir: '/opt/b', port: 5001 }
+ - { role: foo_app_instance, dir: '/opt/a', app_port: 5000 }
+ - { role: foo_app_instance, dir: '/opt/b', app_port: 5001 }
While it's probably not something you should do often, you can also conditionally apply roles like so::
@@ -287,7 +284,7 @@ a list of roles and parameters to insert before the specified role, such as the
---
dependencies:
- { role: common, some_parameter: 3 }
- - { role: apache, port: 80 }
+ - { role: apache, appache_port: 80 }
- { role: postgres, dbname: blarg, other_parameter: 12 }
Role dependencies can also be specified as a full path, just like top level roles::
diff --git a/docsite/rst/playbooks_variables.rst b/docsite/rst/playbooks_variables.rst
index 18f1e57f72..122c0ef923 100644
--- a/docsite/rst/playbooks_variables.rst
+++ b/docsite/rst/playbooks_variables.rst
@@ -793,10 +793,10 @@ Basically, anything that goes into "role defaults" (the defaults folder inside t
.. rubric:: Footnotes
-.. [1] Tasks in each role will see their own role's defaults tasks outside of roles will the last role's defaults
-.. [2] Variables defined in inventory file or provided by dynamic inventory
+.. [1] Tasks in each role will see their own role's defaults. Tasks defined outside of a role will see the last role's defaults.
+.. [2] Variables defined in inventory file or provided by dynamic inventory.
-.. note:: Within a any section, redefining a var will overwrite the previous instance.
+.. note:: Within any section, redefining a var will overwrite the previous instance.
If multiple groups have the same variable, the last one loaded wins.
If you define a variable twice in a play's vars: section, the 2nd one wins.
.. note:: the previous describes the default config `hash_behavior=replace`, switch to 'merge' to only partially overwrite.
diff --git a/docsite/rst/porting_guide_2.0.rst b/docsite/rst/porting_guide_2.0.rst
new file mode 100644
index 0000000000..a26763fc14
--- /dev/null
+++ b/docsite/rst/porting_guide_2.0.rst
@@ -0,0 +1,183 @@
+Porting Guide
+=============
+
+
+Playbook
+--------
+
+* backslash escapes When specifying parameters in jinja2 expressions in YAML
+ dicts, backslashes sometimes needed to be escaped twice. This has been fixed
+ in 2.0.x so that escaping once works. The following example shows how
+ playbooks must be modified::
+
+ # Syntax in 1.9.x
+ - debug:
+ msg: "{{ 'test1_junk 1\\\\3' | regex_replace('(.*)_junk (.*)', '\\\\1 \\\\2') }}"
+ # Syntax in 2.0.x
+ - debug:
+ msg: "{{ 'test1_junk 1\\3' | regex_replace('(.*)_junk (.*)', '\\1 \\2') }}"
+
+ # Output:
+ "msg": "test1 1\\3"
+
+To make an escaped string that will work on all versions you have two options::
+
+- debug: msg="{{ 'test1_junk 1\\3' | regex_replace('(.*)_junk (.*)', '\\1 \\2') }}"
+
+uses key=value escaping which has not changed. The other option is to check for the ansible version::
+
+"{{ (ansible_version|version_compare('ge', '2.0'))|ternary( 'test1_junk 1\\3' | regex_replace('(.*)_junk (.*)', '\\1 \\2') , 'test1_junk 1\\\\3' | regex_replace('(.*)_junk (.*)', '\\\\1 \\\\2') ) }}"
+
+* trailing newline When a string with a trailing newline was specified in the
+ playbook via yaml dict format, the trailing newline was stripped. When
+ specified in key=value format, the trailing newlines were kept. In v2, both
+ methods of specifying the string will keep the trailing newlines. If you
+ relied on the trailing newline being stripped, you can change your playbook
+ using the following as an example::
+
+ # Syntax in 1.9.x
+ vars:
+ message: >
+ Testing
+ some things
+ tasks:
+ - debug:
+ msg: "{{ message }}"
+
+ # Syntax in 2.0.x
+ vars:
+ old_message: >
+ Testing
+ some things
+ message: "{{ old_messsage[:-1] }}"
+ - debug:
+ msg: "{{ message }}"
+ # Output
+ "msg": "Testing some things"
+
+* When specifying complex args as a variable, the variable must use the full jinja2
+ variable syntax (```{{var_name}}```) - bare variable names there are no longer accepted.
+ In fact, even specifying args with variables has been deprecated, and will not be
+ allowed in future versions::
+
+ ---
+ - hosts: localhost
+ connection: local
+ gather_facts: false
+ vars:
+ my_dirs:
+ - { path: /tmp/3a, state: directory, mode: 0755 }
+ - { path: /tmp/3b, state: directory, mode: 0700 }
+ tasks:
+ - file:
+ args: "{{item}}" # <- args here uses the full variable syntax
+ with_items: my_dirs
+
+* porting task includes
+* More dynamic. Corner-case formats that were not supposed to work now do not, as expected.
+* variables defined in the yaml dict format https://github.com/ansible/ansible/issues/13324
+* templating (variables in playbooks and template lookups) has improved with regard to keeping the original instead of turning everything into a string.
+ If you need the old behavior, quote the value to pass it around as a string.
+* Empty variables and variables set to null in yaml are no longer converted to empty strings. They will retain the value of `None`.
+ You can override the `null_representation` setting to an empty string in your config file by setting the `ANSIBLE_NULL_REPRESENTATION` environment variable.
+* Extras callbacks must be whitelisted in ansible.cfg. Copying is no longer necessary but whitelisting in ansible.cfg must be completed.
+* dnf module has been rewritten. Some minor changes in behavior may be observed.
+* win_updates has been rewritten and works as expected now.
+
+Deprecated
+----------
+
+While all items listed here will show a deprecation warning message, they still work as they did in 1.9.x. Please note that they will be removed in 2.2 (Ansible always waits two major releases to remove a deprecated feature).
+
+* Bare variables in `with_` loops should instead use the “{{var}}” syntax, which helps eliminate ambiguity.
+* The ansible-galaxy text format requirements file. Users should use the YAML format for requirements instead.
+* Undefined variables within a `with_` loop’s list currently do not interrupt the loop, but they do issue a warning; in the future, they will issue an error.
+* Using dictionary variables to set all task parameters is unsafe and will be removed in a future version. For example::
+
+ - hosts: localhost
+ gather_facts: no
+ vars:
+ debug_params:
+ msg: "hello there"
+ tasks:
+ # These are both deprecated:
+ - debug: "{{debug_params}}"
+ - debug:
+ args: "{{debug_params}}"
+
+ # Use this instead:
+ - debug:
+ msg: "{{debug_params['msg']}}"
+
+* Host patterns should use a comma (,) or colon (:) instead of a semicolon (;) to separate hosts/groups in the pattern.
+* Ranges specified in host patterns should use the [x:y] syntax, instead of [x-y].
+* Playbooks using privilege escalation should always use “become*” options rather than the old su*/sudo* options.
+* The “short form” for vars_prompt is no longer supported.
+ For example::
+
+ vars_prompt:
+ variable_name: "Prompt string"
+
+* Specifying variables at the top level of a task include statement is no longer supported. For example::
+
+ - include: foo.yml
+ a: 1
+
+Should now be::
+
+ - include: foo.yml
+ args:
+ a: 1
+
+* Setting any_errors_fatal on a task is no longer supported. This should be set at the play level only.
+* Bare variables in the `environment` dictionary (for plays/tasks/etc.) are no longer supported. Variables specified there should use the full variable syntax: ‘{{foo}}’.
+* Tags should no longer be specified with other parameters in a task include. Instead, they should be specified as an option on the task.
+ For example::
+
+ - include: foo.yml tags=a,b,c
+
+ Should be::
+
+ - include: foo.yml
+ tags: [a, b, c]
+
+* The first_available_file option on tasks has been deprecated. Users should use the with_first_found option or lookup (‘first_found’, …) plugin.
+
+
+Porting plugins
+===============
+
+In ansible-1.9.x, you would generally copy an existing plugin to create a new one. Simply implementing the methods and attributes that the caller of the plugin expected made it a plugin of that type. In ansible-2.0, most plugins are implemented by subclassing a base class for each plugin type. This way the custom plugin does not need to contain methods which are not customized.
+
+
+Lookup plugins
+--------------
+* lookup plugins ; import version
+
+
+Connection plugins
+------------------
+
+* connection plugins
+
+Action plugins
+--------------
+
+* action plugins
+
+Callback plugins
+----------------
+
+* callback plugins
+
+Connection plugins
+------------------
+
+* connection plugins
+
+
+Porting custom scripts
+======================
+
+Custom scripts that used the ``ansible.runner.Runner`` API in 1.x have to be ported in 2.x. Please refer to:
+https://github.com/ansible/ansible/blob/devel/docsite/rst/developing_api.rst