Use aptitude safe-upgrade instead of apt-get upgrade to implement
apt: upgrade=yes. Using aptitude ensures that missing dependencies
will also be installed.
Fixes#2540
In the example, you want /bin/true to be executed if the first command has an error return code. Combining command with && will run the second only if the first is successful. Combining them with ||, the second will be run only of the first fails, what is wanted here.
Remove leading/trailing single or double quotes when parsing the my.cnf
file in mysql_user and mysql_db.
Do this so that these modules parse the my.cnf file the same way that
the mysql client does.
From: http://dev.mysql.com/doc/refman/5.0/en/option-files.html
You can optionally enclose the value within single quotation marks
or double quotation marks, which is useful if the value contains a
“#” comment character.
Fixes#2405
See issue #2471
This fixes get_remote_head() to be smarter about how to check remote
head. It checks if it is a remote branch or tag and then checks for the
remote object id associated with it. If it is sha1, get_remote_head()
returns it as-is since there doesn't appear to be a way to check a
remote repository for a specific object/sha1. is_remote_tag() is added
to help out the new functionalit in get_remote_head().
In main(), if check_mode is true and version is a sha1, the module now
checks to see if the object is present.
This fixes handling of arguments (module argument) in service_control().
It is now locally scoped such that modifications to it, in the case of a
systemd host, do not later impact subsequent calls to service_control().
See issue #2449.
Without patch:
ansible-service[6177]: Command /usr/bin/systemctl stop cups cups , daemonize True
With patch:
ansible-service[6475]: Command /usr/bin/systemctl start cups , daemonize True
I also updated the comments to reflect the case where systemd is really
being called.
This makes the log message the same, whether it is sent to systemd's
journal or to syslog. It retains the extra fields that are passed to
journal, such as MOUDLE=<name> and additional arguments. Since journal
will reflect messages to syslog, this keeps what goes to syslog
informative instead of the terse 'Ansible module invoked'.
See issue #2461.
The text parameter can contain non-ASCII characters, so we'll encode it
using UTF-8. For example the DOCUMENTATION of the bzr module has such
characters in the name of the author.
When using a .my.cnf file, when there is no user variable defined,
default to the login user.
This change has the mysql_user module behavior match the behavior
of the mysql command-line client.
Also adds an example .my.cnf to the docs.
Related to issue #2114. This hooks in check_mode to git module. This
will exit with changed=True at the following places:
* If the repo has not been cloned
* If the destination has local modifications, this will exit with
changed=True. This is because reset() will exit anyways if there are
local mods and force is False.
* If the remote HEAD commit id is not the same as that of the local HEAD.
This is determined by get_remote_head() that runs 'git ls-remote' to
determine remote HEAD.
Lastly, if this is run with check_mode enabled, this will exit with
changed=False before fetch() is invoked so that no local mods are made.
* As the FIXMEs note: only exit if enable state is going to change.
* This is already handled in service_enable_rcconf() being called by both subclasses.
Both modules seboolean and zfs have not been adapted since they defer from the default (either by having a 'null' or special state, or prefering "on"/"off" for state indication.
Arch python binary patch was broken since improvement in 785068d. This
change fixes patch, removing most of the lines thanks to the new PYTHON
variable.
New source file already uploaded on AUR.
Adds note on python 3 incompatibility
Added note about ansible_python_interpreter for people having python3 as default interpreter (mainly Arch users ?)
Should fix#2344
Adds needs_update() method which will inspect the checkout for the
current revision and then the HEAD. If the local check out is behind
HEAD, this will report changed=True and supply the revision numbers.
Fixed typo in passlib URL link
Fixed style in cryp scheme list
Fixed bullet 7 in variable precedence section
Adds statement regarding passlib requirement
As it used to be before, 'make rpm' from a cloned repository should work without the need to run hacking/env-setup. It's an easy fix, in line with what we already did for the man-pages.
The uri module can be configured to abort after a specified timeout if
it cannot connect to the configured uri. This prevents a uri action from
hanging indefinitely when the remote endpoint cannot be reached because
it is unavailable, there is a firewall in place etc. The default behavior
is left unchanged: timeout=None
This change also introduces a new type for module_parameters: int
Code was added to perform conversion from string -> int type in
module_common.py.
The new type was required in order to play nice with httplib2 which
refuses to accept (and convert) anything other than a numeric type for
the timeout value.
* Code influenced by the service module but without classes.
* Thanks to @dhozac for input and review.
* Thanks to @johanwiren for getting me to push this out the door.
This commit makes the Makefile nicer for packagers so they can select versions
of python. E.g. on a RHEL5 system with Python2.6 (installed from EPEL)
make PYTHON=python2.6 install
Added a Darwin family, commit acc1c004 had added some network facts
but weren't being shown as the Darwin family wasn't in use. This commit
reveals these facts.
A Darwin(Hardware) class has also been created ready to be populated with
hardware facts.
commit 076501459322cf6c14de742e504339d80ffdeed5
Author: Ton Kersten <tonk@tonkersten.com>
Date: Thu Feb 28 21:32:57 2013 +0100
Added date and time facts to setup
commit e057ea671395ec8847f920a63cf9524f5c8fde5f
Author: Ton Kersten <tonk@tonkersten.com>
Date: Thu Feb 28 13:02:25 2013 +0100
Fixed the service command not working
On Ubuntu 1[02].04 the service name was not recognized because
there is a SysV style init script, but not an upstart config file.
Example: The `ntp` client.
Also removed extra spaces at the end of the lines, while at it.
When running ansible -C, I get a traceback that ends with
AttributeError: Values instance has no attribute 'diff'
This fixes on_file_diff to behave similar to
PlaybookRunnerCallbacks.on_file_diff().
This updates the following modules to support check_mode:
* apt_key
* apt_repository
* easy_install
* pip - will always report changed due to the way it handles state
* seboolean
* selinux
* slurp - since nothing changes, it just adds that it supports
check_mode
* subversion - reports changed when checking out new repo and
when updating.
* supervisorctl
* svr4pkg
See issue #2114.
really due for some refactoring, but telling how a service is managed is
a little fuzzy anyway. on a systemd system typoing the service will now
give you a rather systemd specific error which is somewhat suboptimal.
management tools, which meant upstart services on CentOS6 were not startable. This tweak allows things like vmware-tools to be controlled
via the service module. More testing on other distributions (particularly with systemd) is presumably needed.
Added path expanding for dest in lineinfile
Added common file arguments to lineinfile so the module gets owner,
group, mode and SE options.
Decorated existing example to demonstate usage of file options and added
a couple more examples
Message is not set accordingly when file attributes were changed
'absent' handling code now handles the case where the file doesn't
exists (was issuing a Traceback before)
File attribute handling code has been added to the 'absent' handling
function too.
File attributes handling has been grouped in 'def check_file' since it's
required in both places.
'absent' mode now returns a message like it's counterpart 'present',
telling if file attributes were altered and if lines have matched.
Adds 'chroot' connection for executing modules chrooted to
a local dir. Requires running ansible as root.
chroot dirs should be specified in the inventory like any
other host.
You can do things like:
$ sudo -E ansible -vvv -f 1 "./chroot1,./chroot2" -c chroot \
all -m setup
$ sudo -E ansible-playbook -vvv -f 1 -i "./chroot1,./chroot2" \
-c chroot some-playbook.yml
some-playbook.yml:
---
- hosts: all
tasks:
- name: echo something
shell: echo "Yaaay!" >/tmp/foobar.txt
- name: install less
apt: pkg=less state=latest
* get_file_contents returns None when file is not available.
When /etc/mtab is pointing to /proc/mounts and /proc is not
mounted, mtab.split will traceback.
When destination sysctl file is missing, it is created.
But, for idempotency purposes, the creation process now takes place just before it is used, in the
main code path so an empty file is not left over if the code
module.fail_jsons before the file is really used.
When syscl file was missing, sysctl module was complaining about it and
bailing out.
This behaviour prevents usage of /etc/sysctl.d directory, present in
some distributions.
This patch accepts a missing sysctl.conf file so sysctl.d directory can
be used.
However, it will bail out if the destination directory doesn't exist.
be a BSD licensed snippet so that it's ok to write proprietary modules. The actual license of Ansible (GPLv3) or any modules
written for ansible (any) do not change.
Jinja extensions adds features to the jinja2 templating engine. This
patch allows module loading for the templating engine vian an
ansible.cfg configuration key (jinja_extensions).
The default behaviour doesn't change (no module loading).
Requested modules can be added coma separated in ansible.cfg
Adds whitespace handling in jinja_extension config
Added whitespace handling in jinja_extension configuration directive, so
things stay safe if user adds spaces around comas in the directives
list.
Adds config example for jinja_extensions
Added config example with multiple extentions for jinja_extensions
Now handle positive integer value in virtual files if they are separated
by group of space characters where the count is unpredictable.
Thanks to romeotheriault for filing this bug.
If we need to acquire a PTY for sudo's use, then it should really
inherit the capabilities of the calling environment. This is what
OpenSSH does, and so it makes sense to copy this behaviour for the
paramiko connection type.
Closes: #2065
Signed-off-by: martin f. krafft <madduck@madduck.net>
Postpone the paramiko.Channel.get_pty until we know sudo is used. If
sudo is not used, then we do not need a PTY. In fact, the paramiko docs
explicitly state that it's not desirable to allocate a PTY for a simple
exec_command.
Signed-off-by: martin f. krafft <madduck@madduck.net>
A collegue of mine has added basix AIX support to the setup, user and group modules.
We have tested this on AIX 5.3 and 6.1 and it works "as advertised"
Uses a generic BSD Network class, which uses ifconfig and
parses crap out of it. Modifies the Network __new__
implementation to search further down the subclass
tree
If it is a directory, change the destination path by appending the
basename of the source file, like is done if the destination ends with a
/, and try to get the MD5 of the new path.
Remove lots of re use that really shouldn't have been re in the first
place. Initialize pcidata even if lspci is unavailable, and check for
its usability before trying to use it.
Fixes#2060.
So In my Centos 5.9 machine, if there is RAID mount ansible will crash, as it cannot find scheduler file. The reason being, this should be a virtual device as there is no "device" folder under e.g. /sys/block/md0/
Here is the crash:
[kk@u1 ansible]$ ansible q3 -m setup -k -u root --tree=/tmp/facts
SSH password:
q3 | FAILED => failed to parse: /sys/block/md0
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-1360629441.14-171498703486275/setup", line 1797, in ?
main()
File "/root/.ansible/tmp/ansible-1360629441.14-171498703486275/setup", line 1050, in main
data = run_setup(module)
File "/root/.ansible/tmp/ansible-1360629441.14-171498703486275/setup", line 1000, in run_setup
facts = ansible_facts()
File "/root/.ansible/tmp/ansible-1360629441.14-171498703486275/setup", line 990, in ansible_facts
facts.update(Hardware().populate())
File "/root/.ansible/tmp/ansible-1360629441.14-171498703486275/setup", line 312, in populate
self.get_device_facts()
File "/root/.ansible/tmp/ansible-1360629441.14-171498703486275/setup", line 439, in get_device_facts
m = re.match(".*?(\[(.*)\])", scheduler)
File "/usr/lib64/python2.4/sre.py", line 129, in match
return _compile(pattern, flags).match(string)
TypeError: expected string or buffer
- added cron_file attribute: if specified, the file with appropriate
job is created in /etc/cron.d directory. Also, you can store multiple
jobs in one file. state='absent' attribute is handled in the following
way in this case: if after the deletion of the job from the file specified
by cron_file variable the file is empty, the file is deleted, otherwise
not.
- fixed the behaviour, when the backupfile is saved forever in /tmp
folder, even if the backup= atribute is not set (os.unlink() is called if
backup is not True).
- added some comments to the unobvious places
Makes it possible to remove a user from all but the primary group.
Setting 'groups=' is the equivalent to passing '-G ""' to
useradd/usermod, which is interpreted as "no group" on Linux.
Instead of having to remember when to use which one, rename template_ds
to template and move the last bit of code from template to varReplace
(which gets used for all string replacements, in the end).
This means that you can template any data type without worrying about
whether it's a string or not, and the right thing will happen.
Change ec2 fact names with colons (:) or dashes (:) to undescore (_)
so that they can be used in templates.
Note that this makes copies instead of replacing the exisitng fact
names to avoid breaking existing playbooks.
* improves error handling and reporting
* uses run_command to reduce code
* fails quicker on errors as opposed to return codes and tracebacks
* can now also specify the key as data versus needing to wget it from a file
To be consistent with the table showing available options, use
underscores in the example tasks, not hyphens, as the table doesn't
list hyphenated versions of option names, so it looks like the
examples could have typos in them.
If a relative path is passed as an argument, this change first
converts it to an absolute path.
This fixes a bug where the git module would attempt to chdir into an
invalid directory because of multiple chdir calls against a relative
path.
pkgin always returns 0 so can't be used to tell if the install or remove
worked. Instead this just queries the installed packages after
performing an operation.
This adds two dependencies to the apt_repository module: apt and
apt_pkg. These come from the package python-apt. This is used to parse
the host's sources.list and examine whether the repo is already
configured. This then eliminates the unnecessary
'add-apt-repository --remove' from running.
Hash variables are currently overriden if they are redefined. This
doesn't let the user refine hash entries or overriding selected keys,
which can, for some, be a desirable feature.
This patch let the user force hash merging by setting the
hash_behaviour value to "merge" (without the quotes) in ansible.cfg
However, by default, ansible behaves like it always did and if any value
besides "merge" is used ("replace" is suggested in the example ansible.cfg
file), it will also behave as always.
PluginLoader.add_directory() can receive None from, for example,
Inventory.add_directory(self.basedir()) if host_list is a custom list.
None has no reasonable interpretation other than ignore it.
- use boto instead of euca2ools
- improve error handling/propagation for run failures
- rename keypair to key_name (and preserve alias for old playbooks)
- should be 100% backward compatible with the euca2ools version
Adds -i to make_sudo_cmd so target user's environment gets loaded when configurationslike this are used :
- hosts: ubuntu
name: Install ruby for the configured ruby user
sudo: True
sudo_user: rubyuser
# should be ${ruby_user}, but can't for now because of #1665
tasks:
- name: Gets current ruby version
action: shell rbenv version
register: ruby_current_version
This adds "69" to the return codes from the status command that should be
considered as not running. At least "django-celery" uses this return code,
maybe others::
/venv/bin/python /code/project/manage.py celeryctl status
echo $? # 69 when not running.
A bit of googling let me to http://tldp.org/LDP/abs/html/exitcodes.html and
on a Ubuntu Server 12.10 I get::
~# cat /usr/include/sysexits.h | grep 69
#define EX_UNAVAILABLE 69 /* service unavailable */
I'm not sure if the content of sysexits.h is the same on other OS'es.
Pretty straightforward. Give it a URL with an exported GPG key for signing an
Apt repository. It downloads it and will install it using apt-key. It's even
smart enough to tell if it's already there (i.e. actually tells you if it
changed or not).
* Rename fail_on_rc_non_zero to check_rc, much more succinct.
* Simplify method defintion
* Fix command module and drop shell=shell option; whether to use
shell is determined by if args is a list.
This updates apt, apt_repository, command, cron, easy_install, facter,
fireball, git, group, mount, ohai, pip, service, setup, subversion,
supervisorctl, svr4pkg, user, and yum to take advantage of run_command
in module_common.py.
This adds a helper method that modules can call to execute a command via
subproces. It takes two arguments: the command to run and
keyword options that control how the process is executed. Supported
options are: fail_on_rc_non_zero, close_fds, and executable.
fail_on_rc_non_zero will call fail_json if the command fails. If
args is a list, the command will be run with shell=False; otherwise, if
a string, it will be run with shell=True. Otherwise, run_command() returns
the returncode, stdout, and stderr.
Without read permission to the current working directory, git-clone will
fail:
root@host:~$ sudo -u git -H git clone \
git://github.com/ansible/ansible.git /home/git/ansible
fatal: Could not change back to '/root': Permission denied
This commit ensures that the working directory is changed to the
parent-folder of the destination before doing the clone.
For compatibility with older releases as well as avoiding things like
action: raw executable= show status
to communicate with devices that don't have sh.
This commit extends the 'when_' conditions to failed and changed
json results
Additionally it makes when_{set,unset,failed,changed,int,str,flt}
behave more similiarily in that they all except and/or/not logic
Two problems here
* unchecked exception handling and erroneous assumption as to why
an exception might fire
* although the file module expands the path, when using file_args
the unexpanded path is passed.
Expected result: ~/path/to/file should work fine
Actual result: exception is because it doesn't find file with a message
about not being able to get the selinux context
Added two additional template variables
* template_fullpath - absolute path to the template
* template_run_date - date that the template was rendered
Documented these additional variables in the module documentation
Path might have to be expanded on some operations. It seems that path
containing '~' are not.
Using os.path.expanduser in appropriate places solves the problem, but
this might be required in many other places.
It seems that os.path.basename(__file__) can return a unicode
string. In this case syslog.openlog fails. Forcing the result
to a string causes the resulting error to go away.
Since we use 'raw' heavily on equipment where 'command' and 'shell' are not (yet) working (and python may need to be installed first using raw) these improvements are necessary in order to write more complex scripts (with return code handling and separated stdout/stderr).
This change includes the following changes:
- exec_command() now returns the return code of the command
- _low_level_exec_command() now returns a dict, including 'rc', 'stdout' and 'stderr'
- all users of the above interfaces have been improved to make use of the above changes
- all connection plugins have been modified to return rc and stderr
- fix the newline problem (stdout and stderr would have excess newlines)
In a future commit I intend to add assertions or error handling code to verify the return code in those places where it wasn't done. Since only the output was available, the return code was ignored, even though we expect them to be 0.
At the moment Ansible prefers yes/no for module booleans, however booleans in playbooks are still using True/False, rather than yes/no. This changes modifies boolean uses in playbooks (and man pages) to favor yes/no rather than True/False.
This change includes:
- Adaptation of documentation and examples to favor yes/no
- Modification to manpage output to favor yes/no (the docsite output already favors yes/no)
Three changes:
* Add set_default_selinux_context() to module_common that sets
a file's context according to the defaults in the policy
* In atomic_replace(), set the default context for the file if
selinux is enabled and the destination file does not exist.
* In authorized_key, set the default context when creating
$HOME/.ssh and $HOME/.ssh/authorized_keys. If these already
exist, this won't touch them.
I guess my previous pull request was confusing, by changing the message to something we already do for tasks, it makes it more clear.
Just like we say:
TASK: [foo bar]
skipping: [system01]
The message now is more clear:
PLAY [wagawaga] *******************************
skipping: no hosts matched
It makes it clear that we are skipping the play, just as is done for a task when a condition is not met.
- Do not silently ignore malformed pip requirements files.
- Properly reports changed when removing packages.
- "latest" i.e. --upgrade is *not* incompatible with requirements files.
- Less branchy, simpler logic.
- Removed pointless variable "initializations", Python doesn't need that.
Other code simplifications.
- Fun fact; pip install is (kind of) case insensitive, pip freeze is not.
So, 'sqlalchemy' will be reported as installed by install, but missing
by freeze.
The perhaps controversial change and the one that led to finding /
fixing above issues...
Instead of adding command parameters 'index', and 'find', and 'mirrors',
and etc. Added 'extra_args' which are passed onto pip.
The use case for --index-url is having a private pypi repo, like
http://pypi.python.org/pypi/localshop, to which you publish private
packages. I'm sure most every pip option has a use case for someone.
extra_args handles all those. Can reserve ansible command parameters for
the most common.
Tested with pip 1.1.
This allows patterns such as webservers:!debian:&datacenter1 to target
hosts in the webservers group, that are not in the debian group, but are
in the datacenter1 group. It also parses patterns left to right.
Add HTML-escaping to code examples in rST tempate of module-formatter
Add support for specifying port, addresses with phrases and attaching files
Add support for custom headers and document version_added for new options
X-Mailer header added :)
protect empty address lists & attachment list, and add bcc
- Added username, password arguments.
- Documented existing revision argument.
- Corrected documentation/docstrings; removed git references, use svn
nomenclature, etc.
- Refactored duplicate code, redundant shell calls, filter abuse,
inconsistent formating, etc.
- Shell quoting so it doesn't break for one guy who has spaces in
pathnames.
- svn called with '--non-interactive' and '--no-auth-cache'.
Move operations that are dependant on a remote branch under a if
is_remote_branch() conditional. While at it, remove assignment to cmd
string in same block that wasn't used when calling _run().
The git module would not pull in updates to a branch when
version=<branch>. This updates that block to checkout the branch
and then do a git reset --hard <remote>/<branch>. This
should now track updates to a branch.
I hit the following exception because errno is referenced but not imported.
```
fatal: [system01] => failed to parse: Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-1354644532.37-246102819320352/copy", line 782, in <module>
main()
File "/root/.ansible/tmp/ansible-1354644532.37-246102819320352/copy", line 117, in main
module.atomic_replace(dest_tmp, dest)
File "/root/.ansible/tmp/ansible-1354644532.37-246102819320352/copy", line 772, in atomic_replace
if e.errno != errno.EPERM:
NameError: global name 'errno' is not defined
```
In a virtualenv, pip is called just pip. This fixes the pip module to
search for the virtualenv pip first before trying the pip-python and
python-pip variants. Without this, pip module would not install to the
virtualenv when that parameter is provided.
This updates _is_package_installed() to accept a requirements file
as an argument. This is used later in main() to check if python libs
specified in a requirements file are already installed. I updated
main() to consolidate the handling of install/uninstall in a single
block. This should help if someone wants to remove packages specified
by a requirements file.
This ensures we don't litter remote systems with temporary directories
that don't get cleaned up, as well as speeds things up from not having
to touch every node.
commit 48069adf0f
Author: Gregory Duchatelet <skygreg@gmail.com>
Date: Tue Nov 27 10:13:08 2012 +0100
Removing this plugin from this branch.
commit 15400fffe6
Author: Gregory Duchatelet <skygreg@gmail.com>
Date: Tue Nov 27 09:53:16 2012 +0100
Enhance _match function in inventory with regex.
--limit ~regex could be used to filter hosts or group with a regex.
Tested on cli and ansible-playbook.
commit 63c1b2e17e
Author: Gregory Duchatelet <skygreg@gmail.com>
Date: Tue Nov 27 09:03:41 2012 +0100
Revert pull request #1684
commit 7c2c6fee3a
Merge: f023a2fdd5a847
Author: Gregory Duchatelet <skygreg@gmail.com>
Date: Tue Nov 27 08:52:53 2012 +0100
Merge remote branch 'upstream/devel' into devel
commit f023a2f3df
Author: Gregory Duchatelet <skygreg@gmail.com>
Date: Mon Nov 26 20:52:27 2012 +0100
Add an inventory plugin to fetch groups and host from our CMDB.
commit c64193b4c6
Author: Gregory Duchatelet <skygreg@gmail.com>
Date: Mon Nov 26 20:43:30 2012 +0100
Added possibility to filter hosts from a group, with a regex, separating
groupname and regex with a ~
Usage in group pattern: group~filterpattern
Samples:
ansible group~server-0[1236] -m ping
ansible web~proxy -m ping
ansible web~(proxy|frontend) -m ping
Add constant DEFAULT_MODULE_LANG that defaults to C. Can be set via
environment variable ANSIBLE_MODULE_LANG or configuration variable
module_lang. Updated test-module to have same behavior.
This makes the line parsing a lot more robust (and easier to read).
Code supplied by @dhozac, thanks!
Remove re import because this is not used anywhere.
When trying to perform enabled=yes followed by enabled=no
against FreeBSD the module would die with the following error:
TypeError: sub() takes at most 4 arguments (5 given)
The target FreeBSD client (8.2) is running python 2.6.6. It seems the
extra 'flags' argument was added to re.sub() in 2.7.
In fixing this issue I have attempted to create a general atomic method
for modifying a rc.conf file. Hopefully this will make it easier to add
other rc based platorms. The strip/split magic was inspired by the user
module.
This change avoids the "tcgetattr: Invalid argument" error by making sure the ssh we start does have a proper pseudo-tty.
We could also check whether our current terminal is a proper terminal (by doing a tcgetattr ourselves) but I don't think this adds anything.
This closes#1662 (if all use-cases have been tested: sudo, passwd)
* Basically the moving parts from the original service module arranged in
subclasses.
* General structure and helper methods comes from the user module.
* Less forgiving to unsupported platforms: it requires a subclass per platform.
(This makes it easier to work on one platform without having to think about.
what other platform might be affected in unexpected ways).
* Now has basic OpenBSD support.
* Solaris support needs to be added.
Thanks to @dhozac for general advice and Linux testing.
Thanks to @bcoca for clearing up some FreeBSD questions.
Otherwise, a host in two groups, A and B, using a variable defined
in group A and all will get the value of all, as B's variables will
include the all variable.
Partially fixes#1647.
global_vars has higher precedence than inventory. Putting the all
group's variables into it overrides all other groups and hosts.
Partially fixes#1647.
I added all known virtualization types from the virt-what project. However, the few virt types that rely on cpuid information have not been implemented lacking native python cpuid access. (hyperv)
As reported on the mailinglist, the user received a ValueError when the port number was not templated (fixed in #1649) and therefore it was not an integer. This change will catch the exception and provide a proper error so it is more clear.
Added a README.md to explain the purpose of the directory
Fixed dependencies in PKGBUILD
Added patch to change python binary name for arch users, so they
don't end up using python 3 (python links to python3 by default on arch
linux).
Currently when more than one playbook is provided on the commandline, ansible-playbook --list-hosts will only consider the first playbook and stop. This change will make it work for the various different playbooks.
When the inventory is empty, or the provided --limit subset returns an empty intersection, we don't want to loop over all plays but bail out at the very start.
Executive summary: skipping a host corrupts a variable (when it is registered)
We have a play existing out of multiple tasks that check a condition, if one of these tasks fails we want to skip all next tasks in the playbook. I noticed that if we skip a task because a certain condition is met, and this task has a register-attribute, I loose the value in the variable. Which means we cannot use that variable in subsequent tasks to evaluate because it was skipped:
```
- action: command test -d /some/directory
register: task
- action: command test -f /some/directory/file
register: task
only_if: '${task.rc} == 0'
- action: do something else
only_if: '${task.rc} == 0'
```
In the above example, if the second task is skipped (because the first failed), the third action will end with a "SyntaxError: invalid syntax" complaining about the unsubstituted ${task.rc} (even though it was set by the first task and used for skipping the second).
The following play demonstrates the problem:
```
- name: Test register on ignored tasks
hosts: all
gather_facts: no
vars:
skip: true
task: { 'rc': 666 }
tasks:
- action: debug msg='skip = ${skip}, task.rc = ${task.rc}'
- name: Skip this task, just to test if task has changed
action: command ls
register: task
only_if: '${skip} != True'
- action: debug msg='skip = ${skip}, task.rc = ${task.rc}'
- name: Now use task value
action: command echo 'Works !'
only_if: '${task.rc} == 0'
```
And the enclosed fix, fixes the above problem.
After spending 10 minutes to find which playbook had an action/local_action missing, I changed the error to include the task name (if set). The error eventually was caused because I added a name to a task, but the dash before the existing action was not removed.
Update constants.py so that one can specify environmental variable
ANSIBLE_SYSLOG_FACILITY or syslog_facility in ansible.cfg to define
the syslog facility to use. Alternatively, you can specify
ansible_syslog_facility in inventory. Runner now replaces
the syslog facility in the openlog() call with the default or
the injected variables ansible_syslog_facility.
This also updates hacking/test-module to behave similarly.
Without this fix, generating documentation results in:
```
Traceback (most recent call last):
File "hacking/module_formatter.py", line 376, in <module>
main()
File "hacking/module_formatter.py", line 365, in main
text = template.render(doc)
File "/usr/lib64/python2.6/site-packages/jinja2/environment.py", line 669, in render
return self.environment.handle_exception(exc_info, True)
File "hacking/templates/man.j2", line 20, in top-level template code
{% for desc in v.description %}@{ desc | jpfunc }@{% endfor %}
File "hacking/module_formatter.py", line 94, in man_ify
t = _ITALIC.sub(r'\\fI' + r"\1" + r"\\fR", text)
TypeError: expected string or buffer
```
Currently the message prepared for --oneline mode adds a newline to the msg-string, which is then printed (adding another newline). This change removes the added newline so that successes and failures do not differ in output (except if the output is multiline).
- Make sure exit_json() always returns a changed= value
- Modify the yum module to not return failed=False
- Modify install() and latest() similar to remove() in yum module
- Changed exit_json(failed=True, **res) into a fail_json(**res)
- Make sure yum rc= value reflects loop (similar to how we fixed remove())
Rewrote switch_version() to read .git/HEAD to find branch associated
with HEAD. If in a detached HEAD state, will read
.git/refs/remotes/<remote>/HEAD.
Rename pull() to fetch(). It does a git fetch and then a
git fetch --tags.
Add _run() method to handle all subprocess.Popen calls. Change
all previous calls to subprocess.Popen to use _run().
There is no need to require thirsty mode when the destination is a directory. We add the basename of the url to the destination directory and proceed with that. If that file exists in non-thirsty mode continue as expected.
I also cleaned up some of the logic that is no longer necessary if we simply rewrite the destination from the very start the way it is expected.
Since callbacks are called with different argument-types, we have to be careful. We support two different distinct cases:
- The error information can be in one ore more of the following items (msg, stderr or stdout)
- The res/msg value returned can be a string or a list
Splitting of the packaging so that fireball mode, with the
additional requirements of 0mq, is separately packaged.
Also a end node fireball support package (reqs only).
Several modules (e.g., pip) return stdout and stderr together in a "msg" variable (and the module development docs seem to suggest that the standard practice is to return status in this variable).
This change ensures that it is printed out with correct formatting (most importantly, with newlines appearing as newlines instead of \n).
I had made and pushed this change after you already pulled the request.
@dhozac indicated that it would probably be better to use return codes > 255 for anything related to Ansible itself. Which makes sens :)
We use the lineinfile module to modify configuration files of a proprietary application. This application reads configuration options from files, but does not require those files to exist (if the default options are fine). However this application may modify the configuration file at will, so we cannot copy or template those files. And after a silent install the configuration may not exist (depending on the response file).
Whatever the case, during deployment we need to make sure some configuration options are set after the installation.
So the cleanest way to handle this situation is to allow the lineinfile module to create the file if it is missing (and this is the expected behavior). When I proposed this behavior, @sergevanginderachter needed the same functionality and was now working around it as well.
I had made and pushed this change after you already pulled the request.
@dhozac indicated that it would probably be better to use return codes > 255 for anything related to Ansible itself. Which makes sens :)
Split module into a main calling function, and a generic
(Linux useradd/usermod/userdel) User class.
Added a __new__ function that selects most appropriate superclass
Added a FreeBSD User class
Tested against FreeBSD 9.0
If this is not a certainty, playbooks will fail without an 'rc' and checking both if there is an rc, and whether the 'rc' is (not) 0 is very complicated. (especially because ${something.rc} will not be substituted and all that)
If you sudo to a non-root user, you get a permission denied error.
Here's an example:
$ ansible myserver.example.com -m postgresql_db -a "db=mydatabase" -u ubuntu -s -U postgres
myserver.example.com | FAILED >> {
"failed": true,
"msg": "chmod: changing permissions of `/tmp/ansible-
1351092257.96-157699143369671/postgresql_db': Operation not
permitted\n/usr/bin/python: can't open file '/tmp/ansible-
1351092257.96-157699143369671/postgresql_db': [Errno 13]
Permission denied\n",
"parsed": false
}
The problem is that ansible is doing the chmod as the sudo user
when it should be doing it as the remote user.
Detect when on a 'no branch' branch. If so, checkout the HEAD branch
as reported by 'git remote show <remote>'. That should put the repo
back on a branch such that git can then merge changes as necessary.
In addition, removed hard-coded references to origin and replaced
with remote var.
- The old documentation stated not to quote the variable in the function, which is obviously wrong. When using lists or integers, we have to quote otherwise the startswith() method will trip over its non-existence.
- It was unclear that the only_if statement is processed for each item when doing with_items, so I added an example making it crystal clear how this can be used in your advantage (or why a non-existing list variable can break your logic if you expected the only_if to be processed once before running the task)
This allows one to create a SSH key for user. You may define:
ssh_key_type, ssh_key_bits, ssh_key_file, ssh_key_comment,
and ssh_key_passphrase. If no passphrase is provided, the
key will be passphrase-less. This will not overwrite an existing key.
In the JSON returned, it will provide the ssh_fingerprint and
ssh_key_file.
- fixed template (it was the template), adding indentation with Jinja2
- added description of code examples to man-page template (was missing)
- fixed fireball, cron, and debug module examples to confrom
Test for when environment variable and configuration file
variable both set now tests that the environment variable takes
precedence
Removed logic that would never be triggered from
lib/ansible/constants.py
I had trouble finding this information, so though it was worth
adding to docs... but am not sure its easy to find for someone
specifically to find. At least I think this inclusion matches the
tone of document, but maybe this info should go into a FAQ
instead/as-well?
On Red Hat, CentOS and Fedora systems, the pip binary will be called python-pip
instead of pip. This commit makes the pip module also check for python-pip.
The reason we check for python-pip *first*, is to have ansible fail on not
finding 'pip' and reporting *that*. This is consistent with current behaviour
and will not confuse users of Debian et al., where the 'python-pip' binary
never exists.
Tested on Fedora 18 and Ubuntu 12.04.
Try to autodetect MODULEDIR, instead of hardcoded path in jpmens
homedir.
Check if MODULEDIR exists; exit if it doesn't.
Rewrite boilerplate() to use DOCUMENTATION.yaml in examples/. This
makes use of tbielawa's recent change that added this example file.
This also fixes -G so that it works. boilerplate() was commented out
before.
This commit improves the following items:
- Remove the 'match' functionality, this can now be achieve by using the `fail` module together with `only_if` after running the `hpilo_facts` module. Since this gives more functionality, e.g. comparing server names, but also serial numbers or uuids with other inventory information, this is prefered. An example is added to show how this is achieved.
- Clean up all C() calls in documentation
- Added state=poweroff in order to power off a server. The use-case is here that in general we do not want to provision systems that are already running (this enforcement can be disabled using force=yes) but for test systems we should be able to power them off so we can start the normal provisioning process. (We could also force boot them, but that's less elegant)
- The module now correctly indicates when something has changed. So if a server is powered off that was not off already, this is indicated, or when media boot-settings have been changed, this is also correctly indicated. Previously every call to hpilo_boot was (incorrectly) considered a change.
This commit improves the following items:
- Remove the 'match' functionality, this can now be achieve by using the `fail` module together with `only_if` after running the `hpilo_facts` module. Since this gives more functionality, e.g. comparing server names, but also serial numbers or uuids with other inventory information **and** a proper message, this is prefered. An example is added to show how this is achieved.
- Clean up all C() calls in documentation
- Remove trailing spaces in HP iLO's Serial Number output so that they can be compared to CMDB or other inventory information
This is useful mostly for playbooks that run unattended and for a limited set of systems. In case of provisioninging this plugin (together with a final mail action) helps to get notified when something went wrong, or when the installation finished successfully.
Unfortunately, there is no way to enable/disable a plugin from a playbook. So installing the plugin means all other use-cases (provisioning, troubleshooting, reporting or management) all send mails on failure. Something we may want to fix in the future...
Sending mails could be part of the workflow to have teams/responsibles perform specific task. Or simply to notify that a process has finished successfully (e.g. provisioning).
This workaround is recommended from HP iLO's documentation, but may not be sufficient in all cases. Time will tell.
I also made a few cosmetic changes with no impact.
On RHEL5 and RHEL6 there is not argparse, and 'make rpm' fails because of this.
With this change it works, and I can test and fix my own documentation...
Much like we currently have *setup* register the variable `module_setup`, we would like other facts-modules register their own namespace. This means that:
- *network_facts* registers `module_network`
- *hpilo_facts* registers `module_hw`
- *vsphere_facts* registers `module_hw`
In retrospect, it would have made more sense to have `setup` register `module_ansible` instead as the setup module uses the `ansible_` namesepace.
Having the `module_` namespace allows us to check whether a certain namespace has already been loaded so we can avoid running the facts module a second time using only_if.
```yaml
- action: network_facts host=${ansible_hostname_short}
only_if: is_unset('$module_network')
```
This module gathers facts from a VMWare vSphere guest by querying vSphere. The facts include OS, network info (vlan, macaddress) and system info (cpu, memory, uuid) information. Useful information for provisioning and management.
This module gathers facts from the hardware interface by querying HP iLO. The facts include network info (vlan, macaddress) and system info (cpu, memory, uuid) information. Useful information for provisioning and management.
This module was previously named ilo_facts and mentioned in #1080, #1085, #1125 and #1217.
After helping someone on IRC he was interested to have this debug module in upstream. This module simply 'prints' a message, and can be ordered to fail if needed. It helps to troubleshoot or understand inventory/facts issues and/or experiment with statements and conditions using only_if.
Here is a small example playbook:
```yaml
- hosts: all
tasks:
- local_action: debug msg="System $inventory_hostname has uuid ${ansible_product_uuid}"
- local_action: debug msg="System $inventory_hostname lacks a gateway" fail=yes
only_if: "is_unset('$ansible_default_ipv4.gateway')"
- local_action: debug msg="System $inventory_hostname has gateway ${ansible_default_ipv4.gateway}"
only_if: "is_set('$ansible_default_ipv4.gateway')"
```
outputting:
```
[root@moria ansible]# ansible-playbook -v -l localhost:x220 test6.yml
PLAY [all] *********************
GATHERING FACTS *********************
ok: [localhost]
ok: [x220]
TASK: [debug msg="System $inventory_hostname has uuid $ansible_product_uuid"] *********************
ok: [localhost] => {"msg": "System localhost has uuid d125a48c-364f-4e65-b225-fed42ed61fac"}
ok: [x220] => {"msg": "System x220 has uuid d125a48c-364f-4e65-b225-fed42ed61fac"}
TASK: [debug msg="System $inventory_hostname lacks a gateway" fail=yes] *********************
failed: [localhost] => {"failed": true, "msg": "System localhost lacks a gateway", "rc": 1}
ok: [x220] => {"msg": "System x220 has gateway 192.168.1.1"}
PLAY RECAP *********************
localhost : ok=2 changed=0 unreachable=0 failed=1
x220 : ok=3 changed=0 unreachable=0 failed=0
```
I had some other plans for the module, like displaying host inventory and complete inventory to help understand inventory and facts modules, but that would require an action-plugin for transfering inventory information etc... And I am not sure this is wanted/best done in a module.
We now check explicitely for 'module_setup' in the SETUP_CACHE in order to avoid skipping setup because SETUP_CACHE was populated some other way. Other modules can implement the same mechanism to test if they've already run.
This closes#1206.
Since a skipped/ignored action is _very_ different from actual changes to a system, it always bothered me that it was not easily distinguishable when skimming the output. This change makes ignore/skip a different color, and I chose cyan. Contemplated using dark-gray/blue, but prefered something that is readable with most terminal colors.
In some cases you may want to deliberately fail the execution of a playbook. In our provisioning workflow we want to have safeguards in place to avoid provisioning systems that are already in production. Since we reboot physical and virtual systems, it is mandatory we take all the precautions to prevent accidental provisioning.
So in our use-case we have the following at the very start of the provisioning playbook:
### Safeguard to protect production systems
- local_action: fail msg="System is not ready to be staged according to CMDB"
only_if: "'$cmdb_status' != 'to-be-staged'"
and we repeat the same task in the (separate included) play that takes care of (re)booting the system using our own boot-media, so that it cannot be accidentally separately run by someone.
This change makes a distinction between no_hosts_matched and no_hosts_remaining.
In both cases we do not start facts-gathering, or run any tasks.
In the case that there are no more hosts remaining, we abort running tasks and abort the playbook.
I also cleaned up the leftovers from the previous patchsets, as these are no longer required.
This closes#1187.
Example playbook:
```yaml
---
- hosts: emptygroup
tasks:
- action: command date
- action: command false
- hosts: all
gather_facts: False
tasks:
- action: command ls
- action: command false
- action: command true
- hosts: all
tasks:
- action: command true
- action: command false
- hosts: all
tasks:
- action: command pwd
```
pipes.quote is a bit overzealous for what we want to do, quoting ;
and other characters that you most likely want to use in your shell
invocations. The regexp is the best I could come up with to be able
to only replace the parts of the arguments that shouldn't be
executed.
- This list should probably be generated by module_formatter ...
- modules.rst includes _list.rst for list of modules
- module-formatter will generate that list
- .rst now supresses default if none is set (looks better in HTML)
- .rst now handles empty options list
- Fixed postgresql_user and mysql_user because YAML contained colons
- docs for facter
This gathers LSB facts via lsb_release. This complements the
platform facts collected via the platform module. This reoprts
release, id, description, release, and codename. It also adds
'major_release', which is the major version number of a distribution.
Since BOOLEANS also contains integers, joining the list returns an error. Easy to test by giving a wrong value to a boolean argument:
service name=httpd enabled=True
Since True is not in the allowed BOOLEANS, it will cause the error, which in its turn bails out because it joins strings and integers.
We may want to remove the integers from the choices since '0' and '1' are already in the list as strings. Personally I would expect only strings as arguments, not sure where these could be integers ??
Automatic quoting of variables in only_if breaks existing playbooks
where entire statements are put in a variable, and other cases. See
issue #1120 for details.
This fixes a few issues,
- ${foo}${bar} would be parsed as a variable named foo}${bar,
which wouldn't be easily fixed without breaking ${foo.${bar}}
- allows escaping . in variable parts so e.g.
${hostvars.{test.example.com}.foo} works
This is slower than using re. 3 million templating calls take about
about twice as long to complete with this compared to the regexp,
from ~65 seconds to ~115 seconds on my laptop.
This fixes e.g. only_if: ${task.changed} which would always
evaluate to true due to it having been replaced by a string for its
boolean value. Also adds a test case to ensure it doesn't get
missed again.
In some cases (see issue #1067) with state=restarted, a failure to stop
the service (which wasn't running) would appear to the module to be a
failure to restart the service even though it successfully started the
service. This changes the behavior of the service module to focus
on the return code of the start command. If the rc of stop is not
0 and the rc of start does equal 0, it considers the service
successfully restarted. It then ignores the rc, stdout, and stderr
from the unsuccessful stop command.
Sometimes you may want to allow variables through host_vars or inventory, but prompt for a value if it is not set or if the value does not conform to something specific. This option allows you to specify when you want to offer a prompt.
This patch also moves check_conditional to utils, and adds an is_unset() function which is nicer to read:
only_if: "not is_set('${var}')"
vs
only_if: "is_unset('${var}')"
We have a password-prompt for a configurable login name. Since we require to ask the password for this specific login, it is important to indicate what password needs to be prov ided on the prompt. So the prompt needs to be templated. That's what this patch does.
This change includes:
- (on possibly older python versions ?) a string variable test using the 'is' operator fails (so it always return ok immediately after initial delay)
- add a missing socket.settimeout() for the state=started case (if the machine does not exist, timeout defaults to 60 seconds)
- add a connect_timeout option to customize the default connection timeout
- use socket.shutdown(2) to close immediately
- return the elapsed time
When the output of a command is stored in a register, this will create a
stdout_lines field in the result object that contains stdout split into a list
of lines. This list can then be iterated over using with_items.
The check for the destination being a directory is now done before
checking if the file exists, that way the user is informed that the
thirsty argument is required.
Ansible support configuration in:
```
~/.ansible.cfg
/etc/ansible/ansible.cfg
```
this patch add current user (usefull where user have some different projects) with the oreder:
```
./ansible.cfg
~/.ansible.cfg
/etc/ansible/ansible.cfg
```
Previously, importing a playbook in a different directory didn't
work because all of the relative paths were resolved relative to
the top-level playbook.
This patch resolves relative paths on a per-play level instead of
relative to the directory of the top-level playbook.
Also removes the dirname argument from the Play._get_vars method
since this argument wasn't used in the metho dbody.
If I create a database from scratch and assign permissions by doing:
- name: ensure database is created
action: postgresql_db db=$dbname
- name: ensure django user has access
action: postgresql_user db=$dbname user=$dbuser priv=ALL password=$dbpassword
Then it fails with the error:
File "/tmp/ansible-1347048449.32-29998829936529/postgresql_user", line 565, in <module>
main()
File "/tmp/ansible-1347048449.32-29998829936529/postgresql_user", line 273, in main
changed = grant_privileges(cursor, user, privs) or changed
File "/tmp/ansible-1347048449.32-29998829936529/postgresql_user", line 174, in grant_privileges
changed = grant_func(cursor, user, name, privilege)\
File "/tmp/ansible-1347048449.32-29998829936529/postgresql_user", line 132, in grant_database_privilege
prev_priv = get_database_privileges(cursor, user, db)
File "/tmp/ansible-1347048449.32-29998829936529/postgresql_user", line 118, in get_database_privileges
r = re.search('%s=(C?T?c?)/[a-z]+\,?' % user, datacl)
File "/usr/lib/python2.7/re.py", line 142, in search
return _compile(pattern, flags).search(string)
TypeError: expected string or buffer
This fix fixes the problem by not executing the regex if the
db query on pg_database returns None.
When using template module, if a restrictive umask is set, the
sudo_user won't be able to read the /tmp/ansible-dir/source file
after it is copied across following _transfer_str
I wonder if this behaviour shouldn't be abstracted somehow (as
this correction also happens after put_file in the copy module too)
The use-case here is that based on information in the /proc/cmdline certain actions can be taken.
A practical example in our case is that we have a play at the end of the provisioning phase that reboots the system. Since we don't want to accidentally reboot a system (or restart the network) on a production machine, having a way to separate an Anaconda post-install (sshd in chroot) with a normal system is a good way to make that distinction.
---
- name: reboot
hosts: all
tasks:
- action: command init 6
only_if: "not '${ansible_cmdline.BOOT_IMAGE}'.startswith('$')"
A practical problem here is the fact that we cannot simply check whether it is set or empty:
---
- name: reboot
hosts: all
tasks:
- action: command init 6
only_if: "'${ansible_cmdline.BOOT_IMAGE}'"
If ansible_cmdline was a string, a simple only_if: "'${ansible_cmdline}'.find(' BOOT_IMAGE=')" was an option, but still not very "beautiful" :-/
This implementation uses shlex.split() and uses split(sep, maxsplit=1).
Add a cross-reference link to the setup module documentation, so
users know where to look to find more detail about what ansible
variables are available.
The default branch is already devel (as of June 14, 2012), so there's
no need to check this one out explicitly. Also, it was being checked
out before we had even entered the source folder, which was obviously
a mistake.
Previously, there were two entries for 'dest'. I've combined them in a
way that makes sense to me.
This will be superfluous when 'path' is made. Ideally, I'd like to see
'path' have the bulk of the definition, and 'dest' to be an alias to
'path'.
Adds URL to AUR ansile page
Adds suggestion to symlink python to python2 since most Arch users have
python3 by default. This suggestion might not be wise, though it doesn't
seem to break anything.
It might be probably wiser to have a patch for the AUR build that takes
care of this.
Update manpages from ansible repo to show when options require args.
Update clean target Makefile so 'rm' doesn't print a useless error
when files aren't found while cleaning.
0.7 "Panama" -- release pending -- I can barely see the roadmap from the heat coming off of it.
1.1 "Mean Street" -- Release pending
Core Features
* added --check option for "dry run" mode
* added --diff option to show how templates or copied files change, or might change
* --list-tasks for the playbook will list the tasks without running them
* able to set the environment by setting "environment:" as a dictionary on any task (go proxy support!)
* added ansible_ssh_user and ansible_ssh_pass for per-host/group username and password
* jinja2 extensions can now be loaded from the config file
* support for complex arguments to modules (within reason)
* can specify ansible_connection=X to define the connection type in inventory variables
* a new chroot connection type
* module common code now has basic type checking (and casting) capability
* module common now supports a 'no_log' attribute to mark a field as not to be syslogged
* inventory can now point to a directory containing multiple scripts/hosts files, if using this, put group_vars/host_vars directories inside this directory
* added configurable crypt scheme for 'vars_prompt'
* (internals) template engine specifications to use template_ds everywhere
* better error message when your host file can not be found
* end of line comments now work in the inventory file
* directory destinations now work better with remote md5 code
* lookup plugin macros like $FILE and $ENV now work without returning arrays in variable definitions/playbooks
* uses yaml.safe_load everywhere
* able to add EXAMPLES to documentation via EXAMPLES docstring, rather than just in main documentation YAML
* can set ANSIBLE_COW_SELECTION to pick other cowsay types (including random)
* to_nice_yaml and to_nice_json available as Jinja2 filters that indent and sort
* cowsay able to run out of macports (very important!)
* improved logging for fireball mode
* nicer error message when talking to an older system that needs a JSON module installed
* 'magic' variable 'inventory_basedir' now gives path to inventory file
* 'magic' variable 'vars' works like 'hostvars' but gives global scope variables, useful for debugging in templates mostly
* conditionals can be used on plugins like add_host
* developers: all callbacks now have access to a ".runner" and ".playbook", ".play", and ".task" object (use getattr, they may not always be set!)
Facts:
* block device facts for the setup module
* facts for AIX
* fact detection for OS type on Amazon Linux
* device fact gathering stability improvements
* ansible_os_family fact added
* user_id (remote user name)
* a whole series of current time information under the 'datetime' hash
* more OS X facts
* support for detecting Alpine Linux
* added facts for OpenBSD
Module Changes/Fixes:
* ansible module common code (and ONLY that) which is mixed in with modules, is now BSD licensed. App remains GPLv3.
* service code works better on platforms that mix upstart, systemd, and system-v
* service enablement idempotence fixes for systemd and upstart
* service status 4 is also 'not running'
* supervisorctl restart fix
* increased error handling for ec2 module
* can recursively set permissions on directories
* ec2: change to the way AMI tags are handled
* cron module can now also manipulate cron.d files
* virtualenv module can now inherit system site packages (or not)
* lineinfile module now has an insertbefore option
* NetBSD service module support
* fixes to sysctl module where item has multiple values
* AIX support for the user and group modules
* able to specify a different hg repo to pull from than the original set
* add_host module can set ports and other inventory variables
* add_host module can add modules to multiple groups (groups=a,b,c), groups now alias for groupname
* subnet ID can be set on EC2 module
* MySQL module password handling improvements
* added new virtualenv flags to pip and easy_install modules
* various improvements to lineinfile module, now accepts common arguments from file
* force= now replaces thirsty where used before, thirsty remains an alias
* setup module can take a 'filter=<wildcard>' parameter to just return a few facts (not used by playbooks)
* cron module works even if no crontab is present (for cron.d)
* security group ID settable on EC2 module
* misc fixes to sysctl module
* fix to apt module so packages not in cache are still removable
* charset fix to mail module
* postresql db module now does not try to create the 'PUBLIC' user
* SVN module now works correctly with self signed certs
* apt module now has an upgrade parameter (values=yes, no, or 'dist')
* nagios module gets new silence/unsilence commands
* ability to disable proxy usage in get_url (use_proxy=no)
* more OS X facts
* added a 'fail_on_missing' (default no) option to fetch
* added timeout to the uri module (default 30 seconds, adjustable)
* ec2 now has a 'wait' parameter to wait for the instance to be active, eliminates need for seperate wait_for call.
* allow regex backreferences in lineinfile
* id attribute on ec2 module can be used to set idempotent-do-not-recreate launches
* icinga support for nagios module
* fix default logins when no my.conf for MySQL module
* option to create users with non-unique UIDs (user module)
* macports module can enable/disable packages
* quotes in my.cnf are stripped by the MySQL modules
* Solaris Service management added
* service module will attempt to auto-add unmanaged chkconfig services when needed
* service module supports systemd service unit files
Plugins:
* added 'with_random_choice' filter plugin
* fixed ~ expansion for fileglob
* with_nested allows for nested loops (see examples in examples/playbooks)
1.0 "Eruption" -- Feb 1 2013
New modules:
* new sysctl module
* new pacman module (Arch linux)
* new apt_key module
* hg module now in core
* new ec2_facts module
* added pkgin module for Joyent SmartOS
New config settings:
* sudo_exe parameter can be set in config to use sudo alternatives
* sudo_flags parameter can alter the flags used with sudo
New playbook/language features:
* added when_failed and when_changed
* task includes can now be of infinite depth
* when_set and when_unset can take more than one var (when_set: $a and $b and $c)
* added the with_sequence lookup plugin
* can override "connection:" on an indvidual task
* parameterized playbook includes can now define complex variables (not just all on one line)
* making inventory variables available for use in vars_files paths
* messages when skipping plays are now more clear
* --extra-vars now has maximum precedence (as intended)
Module fixes and new flags:
* ability to use raw module without python on remote system
* fix for service status checking on Ubuntu
* service module now responds to additional exit code for SERVICE_UNAVAILABLE
* fix for raw module with '-c local'
* various fixes to git module
* ec2 module now reports the public DNS name
* can pass executable= to the raw module to specify alternative shells
* fix for postgres module when user contains a "-"
* added additional template variables -- $template_fullpath and $template_run_date
* raise errors on invalid arguments used with a task include statement
* shell/command module takes a executable= parameter to specify a different shell than /bin/sh
* added return code and error output to the raw module
* added support for @reboot to the cron module
* misc fixes to the pip module
* nagios module can schedule downtime for all services on the host
* various subversion module improvements
* various mail module improvements
* SELinux fix for files created by authorized_key module
* "template override" ??
* get_url module can now send user/password authorization
* ec2 module can now deploy multiple simultaneous instances
* fix for apt_key modules stalling in some situations
* fix to enable Jinja2 {% include %} to work again in template
* ec2 module is now powered by Boto
* setup module can now detect if package manager is using pacman
* fix for yum module with enablerepo in use on EL 6
Core fixes and new behaviors:
* various fixes for variable resolution in playbooks
* fixes for handling of "~" in some paths
* various fixes to DWIM'ing of relative paths
* /bin/ansible now takes a --list-hosts just like ansible-playbook did
* various patterns can now take a regex vs a glob if they start with "~" (need docs on which!) - also /usr/bin/ansible
* allow intersecting host patterns by using "&" ("webservers:!debian:&datacenter1")
* handle tilde shell character for --private-key
* hash merging policy is now selectable in the config file, can choose to override or merge
* environment variables now available for setting all plugin paths (ANSIBLE_CALLBACK_PLUGINS, etc)
* added packaging file for macports (not upstreamed yet)
* hacking/test-module script now uses /usr/bin/env properly
* fixed error formatting for certain classes of playbook syntax errors
* fix for processing returns with large volumes of output
Inventory files/scripts:
* hostname patterns in the inventory file can now use alphabetic ranges
* whitespace is now allowed around group variables in the inventory file
* inventory scripts can now define groups of groups and group vars (need example for docs?)
0.9 "Dreams" -- Nov 30 2012
Highlighted core changes:
* various performance tweaks, ansible executes dramatically less SSH ops per unit of work
* close paramiko SFTP connections less often on copy/template operations (speed increase)
* change the way we use multiprocessing (speed/RAM usage improvements)
* able to set default for asking password & sudo password in config file
* ansible now installs nicely if running inside a virtualenv
* flag to allow SSH connection to move files by scp vs sftp (in config file)
* additional RPM subpackages for easily installing fireball mode deps (server and node)
* group_vars/host_vars now available to ansible, not just playbooks
* native ssh connection type (-c ssh) now supports passwords as well as keys
* ansible-doc program to show details
Other core changes:
* fix for template calls when last character is '$'
* if ansible_python_interpreter is set on a delegated host, it now works as intended
* --limit can now take "," as separator as well as ";" or ":"
* msg is now displaced with newlines when a task fails
* if any with_ plugin has no results in a list (empty list for with_items, etc), the task is now skipped
* various output formatting fixes/improvements
* fix for Xen dom0/domU detection in default facts
* 'ansible_domain' fact now available (ex value: example.com)
* configured remote temp file location is now always used even for root
* 'register'-ed variables are not recorded for skipped hosts (for example, using only_if/when)
* duplicate host records for the same host can no longer result when a host is listed in multiple groups
* ansible-pull now passes --limit to prevent running on multiple hosts when used with generic playbooks
* remote md5sum check fixes for Solaris 10
* ability to configure syslog facility used by remote module calls
* in templating, stray '$' characters are now handled more correctly
Playbook changes:
* relative paths now work for 'first_available_file'
* various templating engine fixes
* 'when' is an easier form of only if
* --list-hosts on the playbook command now supports multiple playbooks on the same command line
* playbook includes can now be parameterized
Module additions:
* (addhost) new module for adding a temporary host record (used for creating new guests)
* (group_by) module allows partitioning hosts based on group data
* (ec2) new module for creating ec2 hosts
* (script) added 'script' module for pushing and running self-deleting remote scripts
* (svr4pkg) solaris svr4pkg module
Module changes:
* (authorized key) module uses temp file now to prevent failure on full disk
* (fetch) now uses the 'slurp' internal code to work as you would expect under sudo'ed accounts
* (fetch) internal usage of md5 sums fixed for BSD
* (get_url) thirsty is no longer required for directory destinations
* (git) various git module improvements/tweaks
* (group) now subclassed for various platforms, includes SunOS support
* (lineinfile) create= option on lineinfile can create the file when it does not exist
* (mysql_db) module takes new grant options
* (postgresql_db) module now takes role_attr_flags
* (service) further upgrades to service module service status reporting
* (service) tweaks to get service module to play nice with BSD style service systems (rc.conf)
* (service) possible to pass additional arguments to services
* (shell) and command module now take an 'executable=' flag for specifying an alternate shell than /bin/sh
* (user) ability to create SSH keys for users when using user module to create users
* (user) atomic replacement of files preserves permissions of original file
* (user) module can create SSH keys
* (user) module now does Solaris and BSD
* (yum) module takes enablerepo= and disablerepo=
* (yum) misc yum module fixing for various corner cases
Plugin changes:
* EC2 inventory script now produces nicer failure message if AWS is down (or similar)
* plugin loading code now more streamlined
* lookup plugins for DNS text records, environment variables, and redis
* added a template lookup plugin $TEMPLATE('filename.j2')
* various tweaks to the EC2 inventory plugin
* jinja2 filters are now pluggable so it's easy to write your own (to_json/etc, are now impl. as such)
0.8 "Cathedral" -- Oct 19, 2012
Highlighted Core Changes:
* fireball mode -- ansible can bootstrap a ephemeral 0mq (zeromq) daemon that runs as a given user and expires after X period of time. It is very fast.
* playbooks with errors now return 2 on failure. 1 indicates a more fatal syntax error. Similar for /usr/bin/ansible
* server side action code (template, etc) are now fully pluggable
* ability to write lookup plugins, like the code powering "with_fileglob" (see below)
Other Core Changes:
* ansible config file can also go in '.ansible.cfg' in cwd in addition to ~/.ansible.cfg and /etc/ansible/ansible.cfg
* fix for inventory hosts at API level when hosts spec is a list and not a colon delimited string
* ansible-pull example now sets up logrotate for the ansible-pull cron job log
* a module for adding entries to the main crontab (though you may still wish to just drop template files into cron.d)
* debug module can be used for outputing messages without using 'shell echo'
* a fail module is now available for causing errors, you might want to use it with only_if to fail in certain conditions
Other module Changes, Upgrades, and Fixes:
* removes= exists on command just like creates=
* postgresql modules now take an optional port= parameter
* /proc/cmdline info is now available in Linux facts
* public host key detection for OS X
* lineinfile module now uses 'search' not exact 'match' in regexes, making it much more intuitive and not needing regex syntax most of the time
* added force=yes|no (default no) option for file module, which allows transition between files to directories and so on
* additional facts for SunOS virtualization
* copy module is now atomic when used across volumes
* url_get module now returns 'dest' with the location of the file saved
* fix for yum module when using local RPMs vs downloading
* cleaner error messages with copy if destination directory does not exist
* setup module now still works if PATH is not set
* service module status now correct for services with 'subsys locked' status
* misc fixes/upgrades to the wait_for module
* git module now expands any "~" in provided destination paths
* ignore stop error code failure for service module with state=restarted, always try to start
* inline documentation for modules allows documentation source to built without pull requests to the ansible-docs project, among other things
* variable '$ansible_managed' is now great to include at the top of your templates and includes useful information and a warning that it will be replaced
* "~" now expanded in command module when using creates/removes
* mysql module can do dumps and imports
* selinux policy is only required if setting to not disabled
* various fixes for yum module when working with packages not in any present repo
0.7 "Panama" -- Sept 6 2012
Module changes:
@ -75,13 +470,13 @@ playbooks:
* error reporting if with_items value is unbound
* with_items no longer creates lots of tasks, creates one task that makes multiple calls
* can use host_specific facts inside with_items (see above)
* at the top level of a playbook, set 'gather_facts: False' to skip fact gathering
* at the top level of a playbook, set 'gather_facts: no' to skip fact gathering
* first_available_file and with_items used together will now raise an error
* to catch typos, like 'var' for 'vars', playbooks and tasks now yell on invalid parameters
* automatically load (directory_of_inventory_file)/group_vars/groupname and /host_vars/hostname in vars_files
* playbook is now colorized, set ANSIBLE_NOCOLOR=1 if you do not like this, does not colorize if not a TTY
* hostvars now preserved between plays (regression in 0.5 from 0.4), useful for sharing vars in multinode configs
* ignore_errors: True on a task can be used to allow a task to fail and not stop the play
* ignore_errors: yes on a task can be used to allow a task to fail and not stop the play
* with_items with the apt/yum module will install/remove/update everything in a single command
inventory:
@ -140,7 +535,7 @@ internals:
* support for older versions of python-apt in the apt module
* a new "assemble" module, for constructing files from pieces of files (inspired by Puppet "fragments" idiom)
* ability to override most default values with ANSIBLE_FOO environment variables
* --module-path parameter can support multiple directories seperated with the OS path seperator
* --module-path parameter can support multiple directories separated with the OS path separator
* with_items can take a variable of type list
* ansible_python_interpreter variable available for systems with more than one Python
\fBansible\-doc\fR displays information on modules installed in Ansible libraries\&. It displays a terse listing of modules and their short descriptions, provides a printout of their DOCUMENTATION strings, and it can create a short "snippet" which can be pasted into a playbook\&.
@ -82,6 +82,26 @@ Prompt for the password to use for playbook plays that request sudo access, if a
Desired sudo user (default=root)\&.
.RE
.PP
\fB\-\-tags\fR
.RS4
Run only these tags from the playbook
.RE
.PP
\fB\-\-syntax\-check\fR
.RS4
Look for syntax errors in the playbook, but don\(cqt run anything
.RE
.PP
\fB\-\-check\fR
.RS4
Do not make any changes on the remote system, but test resources to see what might have changed\&. Note this can not scan all possible resource types and is only a simulation\&.
.RE
.PP
\fB\-\-diff\fR
.RS4
When changing any templated files, show the unified diffs of how they changed\&. When used with \-\-check, shows how the files would have changed if \-\-check were not used\&.
@ -34,7 +25,7 @@ ansible-pull \- set up a remote copy of ansible on each managed node
ansible \-d DEST \-U URL [ \-C CHECKOUT ]
.SH"DESCRIPTION"
.sp
\fBAnsible\fR is an extra\-simple tool/framework/API for doing \*(Aqremote things\*(Aq over SSH\&.
\fBAnsible\fR is an extra\-simple tool/framework/API for doing \'remote things\' over SSH\&.
.sp
Use ansible\-pull to set up a remote copy of ansible on each managed node, each set to run via cron and update playbook source via git\&. This inverts the default \fBpush\fR architecture of ansible into a \fBpull\fR architecture, which has near\-limitless scaling potential\&.
Ansible stores the hosts it can potentially operate on in an inventory file\&. The syntax is one host per line\&. Groups headers are allowed and are included on their own line, enclosed in square brackets that start the line\&.
@ -171,6 +171,10 @@ Ranges of hosts are also supported\&. For more information and additional option
/etc/ansible/hosts \(em Default inventory file
.sp
/usr/share/ansible/ \(em Default module library
.sp
/etc/ansible/ansible\&.cfg \(em Config file, used if present
.sp
~/\&.ansible\&.cfg \(em User config file, overrides the default config if present
.SH"ENVIRONMENT"
.sp
The following environment variables may specified\&.
@ -178,6 +182,8 @@ The following environment variables may specified\&.
ANSIBLE_HOSTS \(em Override the default ansible hosts file
.sp
ANSIBLE_LIBRARY \(em Override the default ansible module library path
.sp
ANSIBLE_CONFIG \(em Override the default ansible config file
.SH"AUTHOR"
.sp
Ansible was originally written by Michael DeHaan\&. See the AUTHORS file for a complete list of contributors\&.
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}elsethis.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)returnw;if(f&&binc.attrFn)returnc(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);vare=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){varj=$a.test(b);if(bina&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
// search finished, update title and status message
else{
Search.stopPulse();
Search.title.text(_('Search Results'));
if(!resultCount)
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
else
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s',resultCount));
Search.status.fadeIn(500);
}
}
displayNextItem();
},
performObjectSearch:function(object,otherterms){
varfilenames=this._index.filenames;
varobjects=this._index.objects;
varobjnames=this._index.objnames;
vartitles=this._index.titles;
varimportantResults=[];
varobjectResults=[];
varunimportantResults=[];
for(varprefixinobjects){
for(varnameinobjects[prefix]){
varfullname=(prefix?prefix+'.':'')+name;
if(fullname.toLowerCase().indexOf(object)>-1){
varmatch=objects[prefix][name];
varobjname=objnames[match[1]][2];
vartitle=titles[match[0]];
// If more than one term searched for, we require other words to be
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml"><head><metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"/><title>ansible-playbook</title><linkrel="stylesheet"href="./docbook-xsl.css"type="text/css"/><metaname="generator"content="DocBook XSL Stylesheets V1.75.2"/></head><body><divxml:lang="en"class="refentry"title="ansible-playbook"lang="en"><aid="id474207"></a><divclass="titlepage"></div><divclass="refnamediv"><h2>Name</h2><p>ansible-playbook — run an ansible playbook</p></div><divclass="refsynopsisdiv"title="Synopsis"><aid="_synopsis"></a><h2>Synopsis</h2><p>ansible-playbook <filename.yml> … [options]</p></div><divclass="refsect1"title="DESCRIPTION"><aid="_description"></a><h2>DESCRIPTION</h2><p><spanclass="strong"><strong>Ansible playbooks</strong></span> are a configuration and multinode deployment
system. Ansible-playbook is the tool used to run them. See the
project home page (link below) for more information.</p></div><divclass="refsect1"title="ARGUMENTS"><aid="_arguments"></a><h2>ARGUMENTS</h2><divclass="variablelist"><dl><dt><spanclass="term">
The <spanclass="emphasis"><em>PATH</em></span> to the inventory hosts file, which defaults to <spanclass="emphasis"><em>/etc/ansible/hosts</em></span>.
Connection timeout to use when trying to talk to hosts, in <spanclass="emphasis"><em>SECONDS</em></span>.
</dd></dl></div></div><divclass="refsect1"title="ENVIRONMENT"><aid="_environment"></a><h2>ENVIRONMENT</h2><p>The following environment variables may specified.</p><p>ANSIBLE_HOSTS —Override the default ansible hosts file</p><p>ANSIBLE_LIBRARY—Override the default ansible module library path</p></div><divclass="refsect1"title="AUTHOR"><aid="_author"></a><h2>AUTHOR</h2><p>Ansible was originally written by Michael DeHaan. See the AUTHORS file
is available on the ansible home page: <aclass="ulink"href="https://ansible.github.com/"target="_top">https://ansible.github.com/</a></p></div></div></body></html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml"><head><metahttp-equiv="Content-Type"content="text/html; charset=UTF-8"/><title>ansible</title><linkrel="stylesheet"href="./docbook-xsl.css"type="text/css"/><metaname="generator"content="DocBook XSL Stylesheets V1.75.2"/></head><body><divxml:lang="en"class="refentry"title="ansible"lang="en"><aid="id392901"></a><divclass="titlepage"></div><divclass="refnamediv"><h2>Name</h2><p>ansible — run a command somewhere else</p></div><divclass="refsynopsisdiv"title="Synopsis"><aid="_synopsis"></a><h2>Synopsis</h2><p>ansible <host-pattern> [-f forks] [-m module_name] [-a args]</p></div><divclass="refsect1"title="DESCRIPTION"><aid="_description"></a><h2>DESCRIPTION</h2><p><spanclass="strong"><strong>Ansible</strong></span> is an extra-simple tool/framework/API for doing 'remote things' over
The <spanclass="emphasis"><em>PATH</em></span> to the inventory hosts file, which defaults to <spanclass="emphasis"><em>/etc/ansible/hosts</em></span>.
Use this remote <spanclass="emphasis"><em>USERNAME</em></span> instead of root.
</dd></dl></div></div><divclass="refsect1"title="INVENTORY"><aid="_inventory"></a><h2>INVENTORY</h2><p>Ansible stores the hosts it can potentially operate on in an inventory
file. The syntax is one host per line. Groups headers are allowed and
are included on their own line, enclosed in square brackets.</p></div><divclass="refsect1"title="FILES"><aid="_files"></a><h2>FILES</h2><p>/etc/ansible/hosts—Default inventory file</p><p>/usr/share/ansible/—Default module library</p></div><divclass="refsect1"title="ENVIRONMENT"><aid="_environment"></a><h2>ENVIRONMENT</h2><p>The following environment variables may specified.</p><p>ANSIBLE_HOSTS —Override the default ansible hosts file</p><p>ANSIBLE_LIBRARY—Override the default ansible module library path</p></div><divclass="refsect1"title="AUTHOR"><aid="_author"></a><h2>AUTHOR</h2><p>Ansible was originally written by Michael DeHaan. See the AUTHORS file
is available on the ansible home page: <aclass="ulink"href="https://ansible.github.com/"target="_top">https://ansible.github.com/</a></p></div></div></body></html>
for (hostname, result) in results['contacted'].items():
if not 'failed' in result:
print "%s >>> %s" % (hostname, result['stdout'])
print "FAILED *******"
for (hostname, result) in results['contacted'].items():
if 'failed' in result:
print "%s >>> %s" % (hostname, result['msg'])
print "DOWN *********"
for (hostname, result) in results['dark'].items():
print "%s >>> %s" % (hostname, result)
Advanced programmers may also wish to read the source to ansible itself, for
it uses the Runner() API (with all available options) to implement the
command line tools ``ansible`` and ``ansible-playbook``.
Plugins Available Online
------------------------
The remainder of features in the API docs have components available in `ansible-plugins <https://github.com/ansible/ansible/blob/devel/plugins>`_. Send us a github pull request if you develop any interesting features.
External Inventory Scripts
--------------------------
Often a user of a configuration management system will want to keep inventory
in a different system. Frequent examples include LDAP, `Cobbler <http://cobbler.github.com>`_,
or a piece of expensive enterprisey CMDB software. Ansible easily supports all
of these options via an external inventory system. The plugins directory contains some of these already -- including options for EC2/Eucalyptus and OpenStack, which will be detailed below.
It's possible to write an external inventory script in any language. If you are familiar with Puppet terminology, this concept is basically the same as 'external nodes', with the slight difference that it also defines which hosts are managed.
Script Conventions
``````````````````
When the external node script is called with the single argument '--list', the script must return a JSON hash/dictionary of all the groups to be managed.
Each group's value should be either a hash/dictionary containing a list of each host/IP, potential child groups, and potential group variables, or
Before version 1.0, each group could only have a list of hostnames/IP addresses, like the webservers, marietta, and 5points groups above.
When called with the arguments '--host <hostname>' (where <hostname> is a host from above), the script must return either an empty JSON
hash/dictionary, or a hash/dictionary of variables to make available to templates and playbooks. Returning variables is optional,
if the script does not wish to do this, returning an empty hash/dictionary is the way to go::
{
'favcolor' : 'red',
'ntpserver' : 'wolf.example.com',
'monitoring' : 'pack.example.com'
}
Example: The Cobbler External Inventory Script
``````````````````````````````````````````````
It is expected that many Ansible users will also be `Cobbler <http://cobbler.github.com>`_ users. Cobbler has a generic
layer that allows it to represent data for multiple configuration management systems (even at the same time), and has
been referred to as a 'lightweight CMDB' by some admins. This particular script will communicate with Cobbler
using Cobbler's XMLRPC API.
To tie Ansible's inventory to Cobbler (optional), copy `this script <https://raw.github.com/ansible/ansible/devel/plugins/inventory/cobbler.py>`_ to /etc/ansible/hosts and `chmod +x` the file. cobblerd will now need
to be running when you are using Ansible.
Test the file by running `./etc/ansible/hosts` directly. You should see some JSON data output, but it may not have
anything in it just yet.
Let's explore what this does. In cobbler, assume a scenario somewhat like the following::
cobbler system edit --name=foo --dns-name="foo.example.com" --mgmt-classes="atlanta" --ksmeta="c=4"
cobbler system edit --name=bar --dns-name="bar.example.com" --mgmt-classes="atlanta" --ksmeta="c=5"
In the example above, the system 'foo.example.com' will be addressable by ansible directly, but will also be addressable when using the group names 'webserver' or 'atlanta'. Since Ansible uses SSH, we'll try to contract system foo over 'foo.example.com', only, never just 'foo'. Similarly, if you try "ansible foo" it wouldn't find the system... but "ansible 'foo*'" would, because the system DNS name starts with 'foo'.
The script doesn't just provide host and group info. In addition, as a bonus, when the 'setup' module is run (which happens automatically when using playbooks), the variables 'a', 'b', and 'c' will all be auto-populated in the templates::
# file: /srv/motd.j2
Welcome, I am templated with a value of a={{ a }}, b={{ b }}, and c={{ c }}
Which could be executed just like this::
ansible webserver -m setup
ansible webserver -m template -a "src=/tmp/motd.j2 dest=/etc/motd"
..note::
The name 'webserver' came from cobbler, as did the variables for
the config file. You can still pass in your own variables like
normal in Ansible, but variables from the external inventory script
will override any that have the same name.
So, with the template above (motd.j2), this would result in the following data being written to /etc/motd for system 'foo'::
Welcome, I am templated with a value of a=2, b=3, and c=4
And on system 'bar' (bar.example.com)::
Welcome, I am templated with a value of a=2, b=3, and c=5
And technically, though there is no major good reason to do it, this also works too::
ansible webserver -m shell -a "echo {{ a }}"
So in other words, you can use those variables in arguments/actions as well. You might use this to name
a conf.d file appropriately or something similar. Who knows?
So that's the Cobbler integration support -- using the cobbler script as an example, it should be trivial to adapt Ansible to pull inventory, as well as variable information, from any data source. If you create anything interesting, please share with the mailing list, and we can keep it in the source code tree for others to use.
Example: AWS EC2 External Inventory Script
``````````````````````````````````````````
If you use Amazon Web Services EC2, maintaining an inventory file might not be the best approach. For this reason, you can use the `EC2 external inventory <https://raw.github.com/ansible/ansible/devel/plugins/inventory/ec2.py>`_ script.
You can use this script in one of two ways. The easiest is to use Ansible's ``-i`` command line option and specify the path to the script.
ansible -i ec2.py -u ubuntu us-east-1d -m ping
The second option is to copy the script to `/etc/ansible/hosts` and `chmod +x` it. You will also need to copy the `ec2.ini <https://raw.github.com/ansible/ansible/devel/plugins/inventory/ec2.ini>`_ file to `/etc/ansible/ec2.ini`. Then you can run ansible as you would normally.
To successfully make an API call to AWS, you will need to configure Boto (the Python interface to AWS). There are a `variety of methods <http://docs.pythonboto.org/en/latest/boto_config_tut.html>`_ available, but the simplest is just to export two environment variables:
export AWS_ACCESS_KEY_ID='AK123'
export AWS_SECRET_ACCESS_KEY='abc123'
You can test the script by itself to make sure your config is correct
cd plugins/inventory
./ec2.py --list
After a few moments, you should see your entire EC2 inventory across all regions in JSON.
Since each region requires its own API call, if you are only using a small set of regions, feel free to edit ``ec2.ini`` and list only the regions you are interested in. There are other config options in ``ec2.ini`` including cache control, and destination variables.
At their heart, inventory files are simply a mapping from some name to a destination address. The default ``ec2.ini`` settings are configured for running Ansible from outside EC2 (from your laptop for example). If you are running Ansible from within EC2, internal DNS names and IP addresses may make more sense than public DNS names. In this case, you can modify the ``destination_variable`` in ``ec2.ini`` to be the private DNS name of an instance. This is particularly important when running Ansible within a private subnet inside a VPC, where the only way to access an instance is via its private IP address. For VPC instances, `vpc_destination_variable` in ``ec2.ini`` provides a means of using which ever `boto.ec2.instance variable <http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance>`_ makes the most sense for your use case.
The EC2 external inventory provides mappings to instances from several groups:
Instance ID
These are groups of one since instance IDs are unique.
e.g.
``i-00112233``
``i-a1b1c1d1``
Region
A group of all instances in an AWS region.
e.g.
``us-east-1``
``us-west-2``
Availability Zone
A group of all instances in an availability zone.
e.g.
``us-east-1a``
``us-east-1b``
Security Group
Instances belong to one or more security groups. A group is created for each security group, with all characters except alphanumerics, dashes (-) converted to underscores (_). Each group is prefixed by ``security_group_``
e.g.
``security_group_default``
``security_group_webservers``
``security_group_Pete_s_Fancy_Group``
Tags
Each instance can have a variety of key/value pairs associated with it called Tags. The most common tag key is 'Name', though anything is possible. Each key/value pair is its own group of instances, again with special characters converted to underscores, in the format ``tag_KEY_VALUE``
When the Ansible is interacting with a specific server, the EC2 inventory script is called again with the ``--host HOST`` option. This looks up the HOST in the index cache to get the instance ID, and then makes an API call to AWS to get information about that specific instance. It then makes information about that instance available as variables to your playbooks. Each variable is prefixed by ``ec2_``. Here are some of the variables available:
- ec2_architecture
- ec2_description
- ec2_dns_name
- ec2_id
- ec2_image_id
- ec2_instance_type
- ec2_ip_address
- ec2_kernel
- ec2_key_name
- ec2_launch_time
- ec2_monitored
- ec2_ownerId
- ec2_placement
- ec2_platform
- ec2_previous_state
- ec2_private_dns_name
- ec2_private_ip_address
- ec2_public_dns_name
- ec2_ramdisk
- ec2_region
- ec2_root_device_name
- ec2_root_device_type
- ec2_security_group_ids
- ec2_security_group_names
- ec2_spot_instance_request_id
- ec2_state
- ec2_state_code
- ec2_state_reason
- ec2_status
- ec2_subnet_id
- ec2_tag_Name
- ec2_tenancy
- ec2_virtualization_type
- ec2_vpc_id
Both ``ec2_security_group_ids`` and ``ec2_security_group_names`` are comma-separated lists of all security groups. Each EC2 tag is a variable in the format ``ec2_tag_KEY``.
To see the complete list of variables available for an instance, run the script by itself::
Though not detailed here in as much depth as the EC2 module, there's also a OpenStack Nova external inventory source in the plugins directory. See the inline comments in the module source for how to use it.
Callback Plugins
----------------
Ansible can be configured via code to respond to external events. This can include enhancing logging, signalling an external software
system, or even (yes, really) making sound effects. Some examples are contained in the plugins directory.
Connection Type Plugins
-----------------------
By default, ansible ships with a 'paramiko' SSH, native ssh (just called 'ssh'), and 'local' connection type. Release 0.8 also
added an accelerated connection type named 'fireball'. All of these can be used
in playbooks and with /usr/bin/ansible to decide how you want to talk to remote machines. The basics of these connection types
are covered in the 'getting started' section. Should you want to extend Ansible to support other transports (SNMP? Message bus?
Carrier Pigeon?) it's as simple as copying the format of one of the existing modules and dropping it into the connection plugins
directory.
Lookup Plugins
--------------
Language constructs like "with_fileglob" and "with_items" are implemented via lookup plugins. Just like other plugin types, you can write your own.
Vars Plugins
------------
Playbook constructs like 'host_vars' and 'group_vars' work via 'vars' plugins. They inject additional variable
data into ansible runs that did not come from an inventory, playbook, or command line. Note that variables
can also be returned from inventory, so in most cases, you won't need to write or understand vars_plugins.
Filter Plugins
--------------
If you want more Jinja2 filters available in a Jinja2 template (filters like to_yaml and to_json are provided by default), they can be extended by writing a filter plugin.
Distributing Plugins
--------------------
.. versionadded: 0.8
Plugins are loaded from both Python's site_packages (those that ship with ansible) and a configured plugins directory, which defaults
to /usr/share/ansible/plugins, in a subfolder for each plugin type::
* action_plugins
* lookup_plugins
* callback_plugins
* connection_plugins
* filter_plugins
* vars_plugins
To change this path, edit the ansible configuration file.
In addition, plugins can be shipped in a subdirectory relative to a top-level playbook, in folders named the same as indicated above.
..seealso::
:doc:`modules`
List of built-in modules
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
Here are some tips for making the most of Ansible.
You can find some example playbooks illustrating these best practices in our `ansible-examples repository <https://github.com/ansible/ansible-examples>`_.
..contents::
:depth:2
:backlinks:top
Content Organization
++++++++++++++++++++++
The following section shows one of many possible ways to organize content. Your usage of Ansible should fit your needs,
so feel free to modify this approach and organize as you see fit.
Directory Layout
````````````````
The top level of the directory would contain files and directories like so::
production # inventory file for production servers
stage # inventory file for stage environment
group_vars/
group1 # here we assign variables to particular groups
group2 # ""
host_vars/
hostname1 # if systems need specific variables, put them here
hostname2 # ""
site.yml # master playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
webtier/ # same kind of structure as "common" was above, done for the webtier role
monitoring/ # ""
fooapp/ # ""
How to Arrange Inventory, Stage vs Production
`````````````````````````````````````````````
In this example, the *production* file contains the inventory of all of your production hosts. Of course you can pull inventory from an external
data source as well, but this is just a basic example. Define groups based on purpose of the host (roles) and also geography or datacenter location::
# file: production
[atlanta-webservers]
www-atl-1.example.com
www-atl-2.example.com
[boston-webservers]
www-bos-1.example.com
www-bos-2.example.com
[atlanta-dbservers]
db-atl-1.example.com
db-atl-2.example.com
[boston-dbservers]
db-bos-1.example.com
# webservers in all geos
[webservers:children]
atlanta-webservers
boston-webservers
# dbservers in all geos
[dbservers:children]
atlanta-dbservers
boston-dbservers
# everything in the atlanta geo
[atlanta:children]
atlanta-webservers
atlanta-dbservers
# everything in the boston geo
[boston:children]
boston-webservers
boston-dbservers
Group And Host Variables
````````````````````````
Now, groups are nice for organization, but that's not all groups are good for. You can also assign variables to them! For instance, atlanta
has it's own NTP servers, so when settings up ntp.conf, we should use them. Let's set those now::
---
# file: group_vars/atlanta
ntp: ntp-atlanta.example.com
backup: backup-atlanta.example.com
Variables aren't just for geographic information either! Maybe the webservers have some configuration that doesn't make sense for the database
servers::
---
# file: group_vars/webservers
apacheMaxRequestsPerChild: 3000
apacheMaxClients: 900
If we had any default values, or values that were universally true, we would put them in a file called group_vars/all::
---
# file: group_vars/all
ntp: ntp-boston.example.com
backup: backup-boston.example.com
We can define specific hardware variance in systems in a host_vars file, but avoid doing this unless you need to::
---
# file: host_vars/db-bos-1.example.com
foo_agent_port: 86
bar_agent_port: 99
Top Level Playbooks Are Seperated By Role
`````````````````````````````````````````
In site.yml, we include a playbook that defines our entire infrastructure. Note this is SUPER short, because it's just including
some other playbooks. Remember playbooks are nothing more than lists of plays::
---
# file: site.yml
- include: webservers.yml
- include: dbservers.yml
In a file like webservers.yml (also at the top level), we simply map the configuration of the webservers group to the roles performed by the webservers group. Also notice this is incredibly short. For example::
---
# file: webservers.yml
- hosts: webservers
tasks:
- include: common/tasks/main.yml tags=common
- include: webtier/tasks/main.yml tags=webtier
handlers:
- include: common/handlers/main.yml
- include: webtier/handlers/main.yml
Task And Handler Organization For A Role
````````````````````````````````````````
This file is just mapping hosts to the roles they fulfill. Now, below is an example tasks file, that explains how a role works. Our common role here just sets up NTP, but it could do more if we wanted::
-`Exploring Configuration Management With Ansible <http://palominodb.com/blog/2012/08/01/exploring-configuration-management-ansible>`_ - Palamino DB
-`You Should Consider Using SSH Based Configuration Management <http://www.lshift.net/blog/2012/07/30/you-should-consider-using-ssh-based-configuration-management>`_ - LShift Ltd
-`Deploying Flask/uWSGI, Nginx, and Supervisorctl <http://mattupstate.github.com/python/devops/2012/08/07/flask-wsgi-application-deployment-with-ubuntu-ansible-nginx-supervisor-and-uwsgi.html>`_ - mattupstate
-`Infracoders Presentation <http://www.danielhall.me/2012/10/ansible-talk-infra-coders/>`_ - Daniel Hall
-`Ansible - an introduction <https://speakerdeck.com/jpmens/ansible-an-introduction>`_ - jp\_mens
-`Using Ansible to setup complex networking - <http://exarv.nl/2013/02/using-ansible-to-setup-complex-networking/>`_ - Robert Verspuy
-`Video presentation to Montreal Linux <http://www.youtube.com/embed/up3ofvQNm8c>`_ - Alexandre Bourget
-`Provisioning CentOS EC2 Instances with Ansible <http://jpmens.net/2012/11/21/provisioning-centos-ec2-instances-with-ansible/>`_ - jp\_mens
Disclaimer
``````````
Modules and playbooks here may not be using the latest in Ansible
features. When in doubt to the features of a particular version of
Ansbile, always consult `ansible.cc <http://ansible.cc>`_ and in
particular see `Best Practices <http://ansible.cc/docs/bestpractices.html>`_ for some tips
and tricks that may be useful.
Ansible is (C) 2012, `Michael DeHaan <http://twitter.com/laserllama>`_
and others and is available under the GPLv3 license. Content here is as
As well as delete directories (recursively) and delete files::
$ ansible webservers -m file -a "dest=/path/to/c state=absent"
Managing Packages
`````````````````
There are modules available for yum and apt. Here are some examples
with yum.
Ensure a package is installed, but don't update it::
$ ansible webservers -m yum -a "name=acme state=installed"
Ensure a package is installed to a specific version::
$ ansible webservers -m yum -a "name=acme-1.5 state=installed"
Ensure a package is at the latest version::
$ ansible webservers -m yum -a "name=acme state=latest"
Ensure a package is not installed::
$ ansible webservers -m yum -a "name=acme state=removed"
Currently Ansible only has modules for managing packages with yum and apt. You can install
for other packages for now using the command module or (better!) contribute a module
for other package managers. Stop by the mailing list for info/details.
Users and Groups
````````````````
The 'user' module allows easy creation and manipulation of
existing user accounts, as well as removal of user accounts that may
exist::
$ ansible all -m user -a "name=foo password=<crypted password here>"
$ ansible all -m user -a "name=foo state=absent"
See the :doc:`modules` section for details on all of the available options, including
how to manipulate groups and group membership.
Deploying From Source Control
`````````````````````````````
Deploy your webapp straight from git::
$ ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"
Since ansible modules can notify change handlers it is possible to
tell ansible to run specific tasks when the code is updated, such as
deploying Perl/Python/PHP/Ruby directly from git and then restarting
apache.
Managing Services
`````````````````
Ensure a service is started on all webservers::
$ ansible webservers -m service -a "name=httpd state=started"
Alternatively, restart a service on all webservers::
$ ansible webservers -m service -a "name=httpd state=restarted"
Ensure a service is stopped::
$ ansible webservers -m service -a "name=httpd state=stopped"
Time Limited Background Operations
``````````````````````````````````
Long running operations can be backgrounded, and their status can be
checked on later. The same job ID is given to the same task on all
hosts, so you won't lose track. If you kick hosts and don't want
to poll, it looks like this::
$ ansible all -B 3600 -a "/usr/bin/long_running_operation --do-stuff"
If you do decide you want to check on the job status later, you can::
$ ansible all -m async_status -a "jid=123456789"
Polling is built-in and looks like this::
$ ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
The above example says "run for 30 minutes max (``-B``: 30*60=1800),
poll for status (``-P``) every 60 seconds".
Poll mode is smart so all jobs will be started before polling will begin on any machine.
Be sure to use a high enough ``--forks`` value if you want to get all of your jobs started
very quickly. After the time limit (in seconds) runs out (``-B``), the process on
the remote nodes will be terminated.
Typically you'll be only be backgrounding long-running
shell commands or software upgrades only. Backgrounding the copy module does not do a background file transfer. :doc:`playbooks` also support polling, and have a simplified syntax for this.
Limiting Selected Hosts
```````````````````````
..versionadded:: 0.7
What hosts you select to manage can be additionally constrained by using the '--limit' parameter or
by using 'batch' (or 'range') selectors.
As mentioned above, patterns can be strung together to select hosts in more than one group::
$ ansible webservers:dbservers -m command -a "/bin/foo xyz"
This is an "or" condition. If you want to further constrain the selection, use --limit, which
also works with ``ansible-playbook``::
$ ansible webservers:dbservers -m command -a "/bin/foo xyz" --limit region
Assuming version 0.9 or later, as with other host patterns, values to limit can be separated with ";", ":", or ",".
Now let's talk about range selection. Suppose you have 1000 servers in group 'datacenter', but only want to target one at a time. This is also easy::
$ ansible webservers[0-99] -m command -a "/bin/foo xyz"
$ ansible webservers[100-199] -m command -a "/bin/foo xyz"
This will select the first 100, then the second 100, host entries in the webservers group. (It does not matter
what their names or IP addresses are).
Both of these methods can be used at the same time, and ranges can also be passed to the --limit parameter.
Configuration & Defaults
````````````````````````
..versionadded:: 0.7
Ansible has an optional configuration file that can be used to tune settings and also eliminate the need to pass various command line flags. Ansible will look for the config file in the following order, using
the first config file it finds present:
1. File specified by the ``ANSIBLE_CONFIG`` environment variable
2.``ansible.cfg`` in the current working directory. (version 0.8 and up)
3.``~/.ansible.cfg``
4.``/etc/ansible/ansible.cfg``
For those running from source, a sample configuration file lives in the examples/ directory. The RPM will install configuration into /etc/ansible/ansible.cfg automatically.
..seealso::
:doc:`modules`
A list of available modules
:doc:`playbooks`
Using ansible for configuration management & deployment
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
Ansible is written for Python 2.6+. If you are running Python 2.5 on an "Enterprise Linux" variant, we'll show you how to add
2.6. Newer versions of Linux and OS X should already have 2.6 or higher.
In additon to Python 2.6+, you will want the following Python modules (installed via pip or perhaps via your OS package manager via slightly different names):
*``paramiko``
*``PyYAML``
*``jinja2``
If you are using RHEL or CentOS 5 , python is version 2.4 by default, but you can get python 2.6 installed easily. `Use EPEL <http://fedoraproject.org/wiki/EPEL>`_ and install these dependencies as follows:
The following is a list (and re-explanation) of term definitions used elsewhere in the Ansible documentation.
Consult the documentation home page for the full documentation and to see this in context, but this should be a good resource
to check you know all of components of ansible and how they fit together. It's something you might wish to read for review or
when a term comes up on the mailing list.
See the main documentation if you are looking for examples to put all of this into context.
Action
++++++
An action is a part of ref:`task` that says what ref:`module` to run and what arguments to pass to that module. Each task can
have only one action, but it may also have other parameters.
Ad Hoc
++++++
Refers to running ansible to do some quick command, using /usr/bin/ansible, rather than the orchestration language, which is
/usr/bin/ansible-playbook. An example of an ad-hoc command might be rebooting 50 machines in your infrastructure. Anything
you can do ad-hoc you can do by writing a playbook, and playbooks can also glue lots of other operations together.
Async
+++++
Refers to a task that is configured to run in the background rather than waiting for completion. If you have a long process
that would run longer than the SSH timeout, it would make sense to launch that task in async mode. Async modes can poll
for completion every so many seconds, or can be configured to "fire and forget" in which case ansible will not even
check on the task again, it will just kick it off and proceed to future steps. Async modes work with both /usr/bin/ansible
and /usr/bin/ansible-playbook.
Callback Plugin
+++++++++++++++
Refers to some user-written code that can intercept the results from Ansbile and do something with it. Some supplied examples
in the github project perform custom logging, send email, or even play sound effects.
Check Mode
++++++++++
Refers to running ansible with --check, which does not make any changes on the remote systems, but only alerts what changes
might occur if run without --check. This is analogous to so-called "dry run" mode in other systems, though the user should
be warned that this does not take into account unexpected command failures or cascade effects (nor do those modes in other
systems). Use this to get an idea what might happen, but is not a substitute for a good staging environment.
Connection Type, Connection Plugin
++++++++++++++++++++++++++++++++++
Ansible by default talks to remote machines over SSH using a library called 'paramiko'. It also supports using native OpenSSH,
which if you have a new-enough open SSH, is equally fast, but also enables some features like Kereberos and jump hosts. This is
govered in the getting started section. There are also other connection types like 'fireball' mode, which must be bootstrapped
over SSH but is very fast, and local mode, which acts on the local system. Users can also write their own connection plugins.
Conditionals
++++++++++++
A conditional is an expression that evaluates to true or false that decides whether a given task will be executed on a given
machine or not. Ansible's conditionals include 'only_if', and the syntactically superior alternatives 'when_boolean',
'when_string', and 'when_integer'. These are discussed in the playbook documentation.
Diff Mode
+++++++++
A --diff flag can be passed to ansible to show how template files change when they are overwritten, or how they might change when used
with --check mode. These diffs come out in unified diff format.
Facts
+++++
Facts are simply things that are discovered about remote nodes. While they can be used in playbooks and templates just like variables, facts
are things that are inferred, rather than set. Facts are discovered automatically by ansible when running plays by running the internal 'setup'
module on the remote nodes. You never have to call the setup module explicitly, it just runs, but it can be disabled to save time if it is
not needed. For convience of users switching from other config systems, the fact module will also pull in facts from the 'ohai' and 'facter'
tools if they are installed, which are fact libraries from Chef and Puppet, respectfully.
Filter Plugin
+++++++++++++
A filter plugin is something that most users will never need to understand to use at all. These allow creation of new Jinja2 filters, which
are more of less only of use to people who know what Jinja2 filters are. If you need them, you can learn how to write them in the API
docs section.
Fireball Mode
+++++++++++++
By default Ansible uses SSH for connections -- either Paramiko (the actual default) or a common alternative, native Open SSH. Some users
may want to execute operations even faster though, and they can if they opt in on running an ephmeral message bus. What happens is Ansible
will start talking to a node over SSH, and then set up a temporary secured message bus good only to talk from one machine, that will
self destruct after a set period of time. This means the bus does not allow management of any kind after the time interval has expired.
Forks
+++++
Ansible talks to remote nodes in parallel, the level of parallelism can be set either by passing --forks, or editing the default in a configuration
file. The default is a very conservative 5 forks, though if you have a lot of RAM, you can easily set this to a value like 50 for increased
parallelism.
Gather Facts (Boolean)
++++++++++++++++++++++
Facts are mentioned above. Sometimes in running a multi-play playbook it is deseriable to have some plays that don't bother with fact
computation as they aren't going to need any values from facts. Setting `gather_facts: False` on a playbook allows this implicit
fact gathering to be skipped.
Globbing
++++++++
Globbing is a way to select lots of hosts based on wildcard, rather than the name of the host specifically, or the name of the group
they are in. For instance, it is possible to select "www*" to match all hosts starting with "www". This concept is pulled directly
from Func, one of Michael's earlier projects. In addition to basic globbing, various set operations are also possible, such as
hosts in this group and not in another group, and so on.
Group
+++++
A group consists of several hosts assigned to a pool that can be targetted conviently together, and also given variables that they share in
common.
Group Vars
++++++++++
The "group_vars/" files are files that live in a directory alongside an inventory file, with an optional filename named after each group.
This is a convient place to put variables that will be provided to a given group, especially complex datastructures, so that these
variables do not have to be embedded in the inventory file or playbook.
Handlers
++++++++
Handlers are just like regular tasks in an ansible playbok (see Tasks), but are only run if the Task contains a "notify" directive and
also indicates that it changed something. An example is if a config file is changed, the task referencing the config file templating
operation may notify a service restart handler when it changes. This means services can be bounced only if they need to be restarted.
Handlers can be used for things other than service restarts, but service restarts are the most common usage.
Host
++++
A host is simply a remote machine that ansible manages. They can have individual variables assigned to them, and can also be organized
in groups. All hosts have a name they can be reached at (which is either an IP address or a domain name) and optionally a port number,
if they are not to be accessed on the default SSH port.
Host Specifier
++++++++++++++
Each Play in Ansbile maps a series of tasks (which define the role, purpose, or orders of a system) to a set of systems.
This "hosts:" directive in each play is often called the hosts specifier.
It may select one system, many systems, one or more groups, or even some hosts that in one group and explicitly not in another.
Host Vars
+++++++++
Just like "Group Vars", a directory alongside the inventory file named "host_vars/" can contain a file named after each hostname in
the inventory file, in YAML format. This provides a convient place to assign variables to the host without having to embed
them in the inventory file. The Host Vars file can also be used to define complex datastructures that can't be represented in the
inventory file.
Lazy Evalution
++++++++++++++
In general Ansible evaluates any variables in playbook content at the last possible second, which means that if you define a datastructure
that datastructure itself can define variable values within it, and everything "just works" as you would expect. This also means variable
strings can include other variables inside of those strings.
Lookup Plugin
+++++++++++++
A lookup plugin is a way to get data into Ansible from the outside world. These are how such things as "with_items" are implemented, which is a
basic looping plugin, but there are also things like "with_file" which loads data from a file, and even things for querying environment variables,
DNS text records, or key value stores. Lookup plugins can also be accessed in templates using an all caps form, such as the contents of a file
on the local machine can be accessed like ``$FILE(/path/to/file)``.
Multi-Tier
++++++++++
The concept that IT systems are not managed one system at a time, but by interactions between multiple systems, and groups of systems, in
well defined orders. For instance, a web server may need to be updated before a database server, and pieces on the web server may need
to be updated after *THAT* database server, and various load balancers and monitoring servers may need to be contacted. Ansible models
entire IT topologies and workflows rather than looking at configuration in a "one system at a time" perspective.
Idempotency
+++++++++++
The concept that change commands should only be applied when they need to be applied, and that it is better to describe the desired
state of a system than the process of how to get to that state. As an analogy, the path from North Carolina in the United States to
California involves driving a very long way West, but if I were instead in Anchorage, Alaska, driving a long ways west is no longer
the right way to get to California. Ansible's Resources like you to say "put me in California" and then decide how to get there. If
you were already in California, nothing needs to happen, and it will let you know it didn't need to change anything.
Includes
++++++++
The idea that playbook files (which are nothing more than list of plays) can include other lists of plays, and task lists
can externalize lists of tasks in other files, and similarly with handlers. Includes can be parameterized, which means that the
loaded file can pass variables. For instance, an included play for setting up a wordpress blog may take a parameter called "user"
and thant play could be included more than once to create a blog for both "alice" and "bob".
Inventory
+++++++++
A file (by default, Ansible uses a simple INI format) that describes Hosts and Groups in Ansible. Inventory can also be provided
via an "Inventory Script" (sometimes called an "External Inventory Script").
Inventory Script
++++++++++++++++
A very simple program (or a complicated one) that looks up hosts, group membership for hosts, and variable information from an external
resource -- whether that be a SQL database, a CMDB solution, or something like LDAP. This concept was adapted from Puppet (where it is
called an "External Nodes Classifier") and works more or less exactly the same way.
Jinja2
++++++
Jinja2 is the preferred templating language of Ansbile's template module. It is a very simple Python template language that is generally
readable and easy to write.
JSON
++++
Ansible uses JSON for return data from remote modules. This allows modules to be written in any language, not just Python.
only_if
+++++++
A conditional statement that decides if a task is going to be executed in a playbook based on whether if the following expression
given is true or false. The newer 'when_' statements provide a cleaner way to express conditionals, 'only_if' is an older
construct. Though it may be still be useful in advanced situations.
Library
+++++++
A collection of modules made availabe to /usr/bin/ansible or an ansible playbook.
Limit Groups
++++++++++++
By passing "--limit somegroup" to ansible or ansible playbook, the commands can be limited to a subset of hosts. For instance,
this can be used to run a playbook that normally targets an entire set of servers to one particular server.
Local Connection
++++++++++++++++
By using "connection: local" in a playbook, or "-c local" to /usr/bin/ansible, this indicates that we are managing the local
host and not a remote machine.
Local Action
++++++++++++
A local_action directive in a playbook targetting remote machines means that the given step will actually occur on local
machine, but that the variable '$ansible_hostname' can be passed in to reference the remote hostname being referred to in
that step. This can be used to trigger, for example, an rsync operation.
Loops
+++++
Generally Ansible is not a programming language, it prefers to be more declarative, though various constructs like "with_items"
allow a particular task to be repeated for multiple items in a list. Certain modules, like yum and apt, are actually optimized
for this, and can install all packages given in those lists within a single transaction, dramatically speaking up total
time to configuration.
Modules
+++++++
Modules are the units of work that Ansible ships out to remote machines. Modules are kicked off by either /usr/bin/ansible or
/usr/bin/ansible-playbook (where multiple tasks use lots of different modules in conjunction). Modules can be implemented in any
language including Perl, Bash, or Ruby -- but can leverage some useful communal library code if written in Python. Modules just
have to return JSON or simple key=value pairs. Once modules are executed on remote machines, they are removed, so no long running
daemons are used. Ansible refers to the collection of available modules as a 'library'.
Notify
++++++
The act of a task registering a change event and informing a handler task that another action needs to be run at the end of the play.
If a handler is notified by multiple tasks, it will still be run only once. Handlers are run in the order they are listed, not
in the order that they are notified.
Orchestration
+++++++++++++
Many software automation systems use this word to mean different things. Ansible uses it as a conductor would conduct an orchestra.
A datacenter or cloud architecture is full of many systems, playing many parts -- web servers, database servers, maybe load balancers,
monitoring systems, continuous integration systems, etc. In performing any process, it is neccessary to touch systems in particular orders,
often to simulate rolling updates or deploy software correctly. Some system may perform some steps, then others, then previous systems
already processed may need to perform more steps. Along the way, email may need to be sent or web services contacted. Ansible
orchestration is all about modelling that kind of process.
Paramiko
++++++++
Ansible by default manages machines over SSH. The library that ansible uses by default to do this is a python-powered library called
Paramiko. Paramiko is generally fast and easy to manage, though users desiring Kerberos or Jump Host support may wish to switch
to the native SSH connection type, by specifying the connection type in their playbook or using the "-c ssh" flag.
Playbooks
+++++++++
Playbooks are the language by which Ansible orchestrates, configures, administers, or deploys systems. They are called playbooks partially because it's a sports analogy, and it's supposed to be fun using them. They aren't workbooks :)
Plays
+++++
A playbook is a list of plays. A play is minimally a mapping between a set of hosts (usually chosen by groups, but sometimes my hostname
globs), selected by a host specifier -- and the tasks which run on those hosts to define the role at which those systems will perform. There
can be one or many plays in a playbook.
Pull Mode
+++++++++
Ansible by default runs in push mode, which allows it very fine grained control over when it talks to what kinds of systems. Pull mode is
provided for when you would rather have nodes check in every N minutes on a particular schedule. It uses a program called ansible-pull and can also be set up (or reconfigured) using a push-mode playbook. Most ansible users use push mode, but it is included for variety and the sake
of having choices.
ansible-pull works by checking configuration orders out of git on a crontab and then managing the machine locally, using the local
connection plugin.
Push Mode
+++++++++
Push mode is the default mode of ansible, in fact, it's not really a mode at all -- it's just how ansible works when you aren't
thinking about it. Push mode allows ansible to be fine grained and conduct nodes in complex orchestration processes without
waiting for them to check in.
Register Variable
+++++++++++++++++
The result of running any task in ansible can be stored in a variable for use in a template or a conditional statement.
The keyword used to name the variable to use is called 'register', taking it's name from the idea of registers in assembly
programming, though Ansible will never feel like assembly programming. There are an infinite number of variable names
you can use for registration.
Resource Model
++++++++++++++
Ansible modules work in terms of resources. For instance the file module will select a particular file, say, /etc/motd
and ensure that attributes of that resource match a particular model, for instance, we might wish to set the ownership
to 'root' if not already set to root, or set the mode to '0644' if not already set to '0644'. The resource models
are 'idempotent' meaning change commands are not run unless needed, and ansible will bring the system back to a desired
state regardless of the actual state -- rather than you having to tell it how to get to the state.
Rolling Update
++++++++++++++
The act of addressing a number of nodes in a group N at a time to avoid updating them all at once and bringing the system
offline. For instance, in a web topology of 500 nodes handling very large volume, it may be reasonable to update 10 or 20
machines at a time, moving on to the next 10 or 20 when done. The "serial:" keyword in an ansible playbook controls the
size of the rolling update pool. The default is to address the batch size all at once, so this is something that you must
opt-in to. OS configuration (such as making sure config files are correct) does not typically have to use the rolling update
model, but can if desired.
Runner
++++++
A core software component of ansible that is the power behind /usr/bin/ansible directly -- and corresponds to the invocation
of each task in a playbook. The Runner is something ansible developers may talk about, but it's not really userland
vocabulary.
Serial
++++++
See "Rolling Update".
Sudo
++++
Ansible does not require root logins, and since it's daemonless, definitely does not require root level daemons (which can
be a security concern in sensitive environments). Ansible can log in and perform many operations wrapped in a sudo command,
and can work with both passwordless and passworded sudo. Some operations that don't normally work with sudo (like scp
file transfer) can be achieved with Ansible's copy, template, and fetch resources while running in sudo mode.
SSH (Native)
++++++++++++
Ansible by default uses Paramiko. Native openssh is specified with "-c ssh" (or a config file, or a directive in the playbook)
and can be useful if wanting to login via Kerberized SSH or use SSH jump hosts, etc. Using a client that supports ControlMaster
and ControlPersist is recommended for maximum performance -- if you don't have that and don't need Kerberos, jump hosts, or other
features, paramiko (the default) is a fine choice. Ansible will warn you if it doesn't detect ControlMaster/ControlPersist capability.
Tags
++++
Ansbile allows tagging resources in a playbook with arbitrary keywords, and then running only the parts of the playbook that
correspond to those certain keywords. For instance, it is possible to have an entire OS configuration, and have certain steps
labelled "ntp", and then run just the "ntp" steps to reconfigure the time server information on a remote server.
Tasks
+++++
Playbooks exist to run tasks. Tasks combine an action (a module combined with what variables to pass) with a name and optionally some other keywords (like looping directives). Handlers are also Tasks, but they are a special kind of task that do not run unless they are notified by name when a task reports an underlying change on a remote system.
Templates
+++++++++
Ansible can easily transfer remote files to remote systems, but often it is desirable to substitute variables in other files. Variables
may come from the inventory file, Host Vars, Group Vars, or Facts -- templates use the Jinja2 template engine and can also include logical
constructs like loops and if statements.
Transport
+++++++++
Ansible uses "Connection Plugins" to define types of available transports. These are simply how ansible will reach out to managed systems. Transports included are paramiko (the default SSH transport), SSH (using openssh), fireball (an SSH bootstrapped accelerated connection plugin), and local.
When
++++
When statements (when_string, when_changed, when_boolean, when_integer, etc) are easier to write forms of the only_if conditional. They can be affixed to any task to make that task decide to run only when an expression involving variables or facts is actually true.
Van Halen
+++++++++
For no particular reason other than Michael really likes them, all Ansible releases are code named after Van Halen songs. There is no preference given to David Lee Roth vs Sammy Lee Hagar era songs, and instrumentals are also allowed. It is unlikely there will never be a Jump release, but it may be there is going to be a Van Halen III codenamed release. You never know.
Vars (Variables)
++++++++++++++++
As opposed to Facts, variables are names of values (they can be simple scalar values --integers, booleans, strings) or complex ones (dictionaries/hashes, lists) that can be used in templates and playbooks. They are declared things, not things that are inferred from the remote systems current state or nature (which is what Facts are).
YAML
++++
Ansible does not want to force people to write programming language code to automate infrastructure, so Ansible uses YAML to define playbook configuration languages and also variable files. YAML is nice because it has a minimum of syntax and is very clean and easy for people to skim. It is a good data format for configuration files and humans, but also machine readable. Ansible's usage of YAML stemmed from Michael's first use of it inside of Cobbler around 2006. YAML is fairly popular in the dynamic language community and the format has libraries available
for serialization in many different languages (Python, Perl, Ruby, etc).
Before we dive into playbooks, configuration management, deployment, and orchestration, we'll learn how to get Ansible installed and some
basic information. We'll go over how to execute ad-hoc commands in parallel across your nodes using /usr/bin/ansible. We'll also see
what sort of modules are available in Ansible's core (though you can also write your own, which we'll also show later).
..toctree::
:maxdepth:1
gettingstarted
patterns
examples
modules
Overview
````````
..image:: http://ansible.cc/img/ansible_arch.png
:alt:ansible architecture diagram
:width:566px
:height:439px
Playbooks
`````````
Playbooks are Ansible's orchestration language. At a basic level, playbooks can be used to manage configurations and deployments
of remote machines. At a more advanced level, they can sequence multi-tier rollouts involving rolling updates, and can delegate actions
to other hosts, interacting with monitoring servers and load balancers along the way. You can start small and pick up more features
over time as you need them. Playbooks are designed to be human-readable and are developed in a basic text language. There are multiple
ways to organize playbooks and the files they include, and we'll offer up some suggestions on that and making the most out of Ansible.
..toctree::
:maxdepth:1
playbooks
playbooks2
bestpractices
YAMLSyntax
Example Playbooks <https://github.com/ansible/ansible-examples>
Developer Information
`````````````````````
Learn how to build modules of your own in any language. Explore Ansible's Python API and write Python plugins to integrate
with other solutions in your environment.
..toctree::
:maxdepth:1
api
moduledev
Miscellaneous
`````````````
`Learn and share neat Ansible tricks on Coderwall <https://coderwall.com/p/t/ansible>`_ - sign-in using GitHub or Twitter to vote on top tips and add your own!
`A list of some Ansible users and quotes about Ansible <http://www.ansibleworks.com/users>`_.
The 'setup' module that ships with Ansible provides many variables about a system that can be used in playbooks
and templates. However, it's possible to also add your own facts without modifying the system module. To do
this, just have the module return a `ansible_facts` key, like so, along with other return data::
{
"changed" : True,
"rc" : 5,
"ansible_facts" : {
"leptons" : 5000
"colors" : {
"red" : "FF0000",
"white" : "FFFFFF"
}
}
}
These 'facts' will be available to all statements called after that module (but not before) in the playbook.
A good idea might be make a module called 'site_facts' and always call it at the top of each playbook, though
we're always open to improving the selection of core facts in Ansible as well.
Common Module Boilerplate
`````````````````````````
As mentioned, if you are writing a module in Python, there are some very powerful shortcuts you can use.
Modules are still transferred as one file, but an arguments file is no longer needed, so these are not
only shorter in terms of code, they are actually FASTER in terms of execution time.
Rather than mention these here, the best way to learn is to read some of the `source of the modules <https://github.com/ansible/ansible/tree/devel/library>`_ that come with Ansible.
The 'group' and 'user' modules are reasonably non-trival and showcase what this looks like.
Key parts include always ending the module file with::
# include magic from lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()
And instantiating the module class like::
module = AnsibleModule(
argument_spec = dict(
state = dict(default='present', choices=['present', 'absent']),
name = dict(required=True),
enabled = dict(required=True, choices=BOOLEANS),
something = dict(aliases=['whatever'])
)
)
The AnsibleModule provides lots of common code for handling returns, parses your arguments
Remember that, as module developer, you are responsible for ensuring that no
system state is altered when the user enables check mode.
If your module does not support check mode, when the user runs Ansible in check
mode, your module will simply be skipped.
Common Pitfalls
```````````````
You should also never do this in a module::
print "some status message"
Because the output is supposed to be valid JSON. Except that's not quite true,
but we'll get to that later.
Modules must not output anything on standard error, because the system will merge
standard out with standard error and prevent the JSON from parsing. Capturing standard
error and returning it as a variable in the JSON on standard out is fine, and is, in fact,
how the command module is implemented.
If a module returns stderr or otherwise fails to produce valid JSON, the actual output
will still be shown in Ansible, but the command will not succeed.
Always use the hacking/test-module script when developing modules and it will warn
you about these kind of things.
Conventions/Recommendations
```````````````````````````
As a reminder from the example code above, here are some basic conventions
and guidelines:
* If the module is addressing an object, the parameter for that object should be called 'name' whenever possible, or accept 'name' as an alias.
* If you have a company module that returns facts specific to your installations, a good name for this module is `site_facts`.
* Modules accepting boolean status should generally accept 'yes', 'no', 'true', 'false', or anything else a user may likely throw at them. The AnsibleModule common code supports this with "choices=BOOLEANS" and a module.boolean(value) casting function.
* Include a minimum of dependencies if possible. If there are dependencies, document them at the top of the module file, and have the module raise JSON error messages when the import fails.
* Modules must be self contained in one file to be auto-transferred by ansible.
* If packaging modules in an RPM, they only need to be installed on the control machine and should be dropped into /usr/share/ansible. This is entirely optional and up to you.
* Modules should return JSON or key=value results all on one line. JSON is best if you can do JSON. All return types must be hashes (dictionaries) although they can be nested. Lists or simple scalar values are not supported, though they can be trivially contained inside a dictionary.
* In the event of failure, a key of 'failed' should be included, along with a string explanation in 'msg'. Modules that raise tracebacks (stacktraces) are generally considered 'poor' modules, though Ansible can deal with these returns and will automatically convert anything unparseable into a failed result. If you are using the AnsibleModule common Python code, the 'failed' element will be included for you automatically when you call 'fail_json'.
* Return codes from modules are not actually not signficant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
* As results from many hosts will be aggregrated at once, modules should return only relevant output. Returning the entire contents of a log file is generally bad form.
Shorthand Vs JSON
`````````````````
To make it easier to write modules in bash and in cases where a JSON
module might not be available, it is acceptable for a module to return
key=value output all on one line, like this. The Ansible parser
will know what to do::
somekey=1 somevalue=2 rc=3 favcolor=red
If you're writing a module in Python or Ruby or whatever, though, returning
JSON is probably the simplest way to go.
Documenting Your Module
```````````````````````
All modules included in the CORE distribution must have a
``DOCUMENTATION`` string. This string MUST be a valid YAML document
which conforms to the schema defined below. You may find it easier to
start writing your ``DOCUMENTATION`` string in an editor with YAML
syntax highlighting before you include it in your Python file.
Example
+++++++
Here's a correctly formatted YAML document we could use for a
Ansible works against multiple systems in your infrastructure at the
same time. It does this by selecting portions of systems listed in
Ansible's inventory file, which defaults to /etc/ansible/hosts.
..contents::`Table of contents`
:depth:2
:backlinks:top
.._inventoryformat:
Hosts and Groups
++++++++++++++++
The format for /etc/ansible/hosts is an INI format and looks like this::
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
The things in brackets are group names. You don't have to have them,
but they are useful.
If you have hosts that run on non-standard SSH ports you can put the port number
after the hostname with a colon. Ports listed in any SSH config file won't be read,
so it is important that you set them if things are not running on the default port::
badwolf.example.com:5309
Suppose you have just static IPs and want to set up some aliases that don't live in your host file, or you are connecting through tunnels. You can do things like this::
In the above example, trying to ansible against the host alias "jumper" (which may not even be a real hostname) will contact 192.168.1.50 on port 5555.
Adding a lot of hosts? In 0.6 and later, if you have a lot of hosts following similar patterns you can do this rather than listing each hostname::
[webservers]
www[01:50].example.com
In 1.0 and later, you can also do this for alphabetic ranges::
[databases]
db-[a:f].example.com
For numeric patterns, leading zeros can be included or removed, as desired. Ranges are inclusive.
In 1.1 and later, you can also select the connection type and user on a per host basis::
# Use the ec2_vol module to create volumes for attachment to each instance. Use with_items to attach to each instance (by returned id) launched previously.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.