Compare commits

..

570 Commits

Author SHA1 Message Date
49f7e6a12c update submodule pointer 2016-02-23 14:22:01 -05:00
d70fd17cf9 Merge pull request #14618 from ogenstad/devel
Fixes authentication error bug when user has rsa keys
2016-02-23 14:20:49 -05:00
5d5abbb898 bump next VERSION for -network 2016-02-18 21:36:16 +00:00
3f7b7a1bb9 update submodule pointer 2016-02-18 21:34:02 +00:00
858a0a2339 bugfix on shared module utils from missed cherry-pick
One of the commits was missed when the branch was created.  This fixes the
modules so they work properly
2016-02-18 21:13:57 +00:00
61989f72cc VERSION rename for the -network release 2016-02-17 17:11:44 -05:00
b3da42a669 Updating submodule pointer for the network branch 2016-02-17 16:30:42 -05:00
e15daf186a minor bugfix that will catch connection errors in eos
This commit fixes a situation where connection errors would be caught
but no useful information display.  The connection error is now caught
and emitted in a call to fail_json
2016-02-17 15:41:44 +00:00
9c4467303f minor bugfix that will catch connection errors in ios
This commit fixes a situation where connection errors would be caught
but no useful information display.  The connection error is now caught
and emitted in a call to fail_json
2016-02-17 15:41:37 +00:00
df3f9345e1 minor bugfix that will catch connection errors in iosxr
This commit fixes a situation where connection errors would be caught
but no useful information display.  The connection error is now caught
and emitted in a call to fail_json
2016-02-17 15:41:30 +00:00
5c7c13b9c1 minor bugfix that will catch connection errors in nxos
This commit fixes a situation where connection errors would be caught
but no useful information display.  The connection error is now caught
and emitted in a call to fail_json
2016-02-17 15:41:23 +00:00
0ef6a7ae98 minor bugfix that will catch connection errors in junos
This commit fixes a situation where connection errors would be caught
but no useful information display.  The connection error is now caught
and emitted in a call to fail_json
2016-02-17 15:41:13 +00:00
1fd5bcdc09 minor bug fixes and updates to shell 2016-02-17 15:40:49 +00:00
d178c4be2a Move Conditional class to netcfg.
Added error handling for connect and execute methods.

Fix comments
2016-02-17 15:40:30 +00:00
be846c7053 initial add of action plugin ops_template
Adds new local action ops_config for handling openswitch configurations using
either dc or cli based configurations.  Implements the common net_config
local action.

Note this refactors the ops_config plugin to ops_template
2016-02-17 15:38:36 +00:00
fa2834d863 initial add of new action plugin junos_template
This adds a new action plugin, junos_template that allows the
the junos_template module to perform the templating function.  It
implements net_template
2016-02-17 15:38:29 +00:00
320e099c12 initial add of action plugin nxos_template
Adds new local action for working with cisco nxos configurations.  Implemements
the net_config local action.

Note this action plugin was refactored from nxos_config to nxos_template
2016-02-17 15:38:23 +00:00
f0ee61925a adds new action plugin iosxr_template
This adds a new action plugin iosxr_template that allows the
iosxr_template module to pass network device configurations through the
template engine.  It also allows configurations to be backed up.
2016-02-17 15:38:17 +00:00
d024517d4b initial add of action plugin ios_template
Adds a new local action ios_config for working with cisco ios configuration
files.  Implements the common net_confing local action

Note this plugin was refactored from ios_config to ios_template
2016-02-17 15:37:32 +00:00
651842a4ef initial add of action plugin eos_template
Adds a new local action for eos_config module to handle templating configs
and backing up running configurations.   Implements the local action
net_config

Note this action was refactored from eos_config to eos_template
2016-02-17 15:37:23 +00:00
ee7de10285 Add safety check on _backup key. 2016-02-17 15:37:11 +00:00
bec698052f New release v2.0.1.0-0.2.rc2 2016-02-15 16:02:44 -05:00
729dbe7e67 removed follow from common file docs 2016-02-15 14:14:22 -05:00
032d917e68 Update changelog for dnf fix 2016-02-13 02:09:26 -08:00
9ecdec0141 Update submodule refs 2016-02-13 02:09:26 -08:00
028c710380 Fix bugs related to task_includes and dep chain inheritance
* Fix the way task_include fields were created and copied
* Have blocks get_dep_chain() look at task_include's blocks for proper
  dep chain inheritance
* Fix the way task_include fields are copied to prevent a recursive
  degradation

Fixes #14460
2016-02-13 01:09:16 -05:00
8ee8872d6b Fixing bugs related to nested blocks inside roles
* Make sure dep chains are checked recursively for nested blocks
* Fixing iterator is_failed() check to make sure we're not in a
  rescue block before returning True
* Use is_failed() to test whether a host should be added to the TQM
  failed_hosts list
* Use is_failed() when compiling the list of hosts left to iterate
  over in both the linear and free strategies

Fixes #14222
2016-02-12 16:41:38 -05:00
caf1537510 Display the string which is causing an exception to be raised.
In the ansible template module, when there is an error while
expanding a templated string, displaying the string causing the
exception is very useful.
2016-02-11 22:51:26 -05:00
6f54b1ae2b removed signal trapping 2016-02-11 22:03:00 -05:00
f77690e652 update extras submodule ref
for ec2_vpc_net_facts and elasticsearch module updates
2016-02-11 13:37:41 -08:00
5336a51a9e Update submodule for fix to mysql_user password 2016-02-11 13:09:59 -08:00
9c049b757f Revert "Module params should default to str in most cases."
This reverts commit 9fae8501e2.

Reverting for 2.0.1 -- this has been broken in the 2.0 tree for long
enough that some modules are relying on the broken behaviour.  This fix
will definitely return for 2.1.0 and may return in 2.0.2 (impact needs
to be evaluated).
2016-02-11 12:58:41 -08:00
0ccbbe0c09 allow skipping tasks due to undefined var
mimic 1.x behaviour but give out big deprecation message, not only
for missing attribute but any undefined error.
2016-02-11 14:32:49 -05:00
43bbd4b6dc termination handling
- moved to base cli class to handle centrally and duplicate less code
- now avoids duplication and reiteration of signal handler by reassigning it
- left note on how to do non-graceful in case we add in future
  as I won't remember everything i did here and don't want to 'relearn' it.
2016-02-11 12:42:12 -05:00
517eec8c49 fix cartesian lookup
it seems that this was not working in 1.9 but we swallowed up the error
fixes #14437
2016-02-11 10:36:04 -05:00
b85d9acc09 update core submodule ref 2016-02-10 22:32:32 -08:00
ba5a3f2f67 Update submodule ref 2016-02-10 17:38:24 -08:00
eafc46512d fix typo 2016-02-10 17:37:18 -08:00
39a53c5623 add ismount function from python Lib/posixpath.py
needed for https://github.com/ansible/ansible-modules-core/pull/2737
2016-02-10 17:37:07 -08:00
9fae8501e2 Module params should default to str in most cases. 2016-02-10 15:33:30 -08:00
724761d2a1 read full file when doing diff
but avoid reading file at all or full file when file is too big for diffing
2016-02-10 15:47:44 -05:00
3e2b2b359c Clarify error message when module replacer encounters a bad import line for module_utils code 2016-02-10 08:47:45 -08:00
5ebd5c548c Catch exceptions during module execution so they don't fail the worker
Fixes #14120
2016-02-10 09:24:44 -05:00
18ffa8a4da avoid termination message when term is internal 2016-02-09 18:11:11 -05:00
fa88d0770c Proposed fix for ansible/ansible-modules-extras#1348 due to datetime.datetime type not being matched 2016-02-09 17:12:36 -05:00
24cae22e0b Submodule pointer update 2016-02-09 13:29:45 -05:00
4f2a2ec884 strip BECOME-SUCCESS at lower level
Fixes #14395
2016-02-09 13:12:46 -05:00
7d44063c1e Filter become success string from the stdout of script results
Fixes #14390
2016-02-09 12:38:31 -05:00
dcc0a2d596 Also hide the before state of files with --diff and no_log 2016-02-08 22:06:38 -08:00
c97afd0c48 fix winrm erorr formatting 2016-02-08 23:00:49 -05:00
7c726d197b correctly handle term signals
- adhoc now terminates gracefully
- avoid race condition on terminations by ignoring errors if
  worker might have been reaped between checking if active and termination call
- ansible-playbook now properly exits on sigint/term
- adhoc and playbook now give exceptions that we should not normally capture
  and rely on top level finally to reap children
- handle systemexit breaks in workers
- added debug to see at which frame we exit
partial fix for #14346
2016-02-08 17:23:13 -05:00
13c379dcd0 Added more info to the no action detected error
Error fix
2016-02-08 16:57:54 -05:00
9196a72c3f Add support ssh configs from /etc/openssh.
In Altlinux system config dir for openssh is /etc/openssh.
2016-02-08 10:32:46 -05:00
0b4a259444 Also chmod the args file path when using become for old-style modules
Fixes #14348
2016-02-08 10:02:34 -05:00
5353b8c3b6 Allowing multiple tags to be specified in include's tags argument. 2016-02-08 08:52:55 -05:00
6869ced587 Update core submodule ref to fix apt locale bug 2016-02-07 14:27:48 -08:00
87414e4fd1 Add locale fixes to changelgo 2016-02-07 13:11:32 -08:00
ef9c27e280 Update submodule refs 2016-02-07 12:56:57 -08:00
76ab1d2afc Allow setting run_command environment overrides for the life of an AnsibleModule 2016-02-07 12:55:58 -08:00
a316891968 tag the setup task with always
fixes #14228
2016-02-05 10:35:31 -05:00
3303f25a0c Fix --diff to respect no_log task parameter. 2016-02-04 12:47:44 -08:00
bee699a33a Update submodule refs 2016-02-04 11:12:10 -08:00
4133cf924a Also add 'null' as a possible JSON value 2016-02-04 11:39:20 -05:00
53559433ef Defined JSON booleans in global context for python eval()
We define 'false' and 'true' as variables so that python eval() recognizes them as False and True.

This fixes #14291.
2016-02-04 11:39:20 -05:00
8ca8459af5 Merge pull request #14214 from dvarrazzo/conflicting-actions-message
Better "conflicting action statements" message
2016-02-03 22:55:35 -05:00
6c559e904a Handle when the lookup-plugin is used in jinja-style
This fixes #14190.
2016-02-03 11:18:51 -05:00
901beeec55 avoid logging color codes 2016-02-03 11:00:08 -05:00
4604deca92 Change $() into backticks. Backticks should work for both POSIX and non-POSIX compatible shells.
Fixes #14176
2016-02-02 12:39:55 -08:00
d001c73699 Establish sh as the default shell plugin.
This is a fix for one of the problems pointed out in #14176
2016-02-02 12:19:43 -08:00
53cfde5096 better fix for ansible-pull inventory handling
now it mirrors what it did in previous versions
and properly uses inventory and limit options
2016-02-02 14:29:47 -05:00
6c9d2cc2b4 Note the dnf fix 2016-02-02 10:51:41 -08:00
4de1e26d5c Update submodule refs 2016-02-02 10:49:20 -08:00
8ac8f4c2ab make executable setting connection dependant
winrm shoudl not use executable, rest should?
fixes #14233
2016-02-02 10:22:09 -08:00
5035e53e80 Revert "load now does not modify the incomming data"
This reverts commit 2126e9fee1.
we judge this to be too big a change for stable, keeping in devel
we may still add part or all back to stable in the future.
2016-02-02 11:22:41 -05:00
2126e9fee1 load now does not modify the incomming data
also removed json loader as yaml loader can do both
2016-02-02 11:22:26 -05:00
93cab88663 Don't mark host as having gathered facts when peeking at next task
Fixes #14243
2016-02-02 11:12:28 -05:00
c5f857ec39 Make sure setup tasks inherit properly from their parent play
Fixes #13602
2016-02-02 11:12:24 -05:00
07dd83bc6e deprecate all bare variable conversions (not debug)
now deprecation message appears with variable name in all spots where this occurs
debug's var= option is excluded as this is only place where bare variables shold actually
be accepted.
2016-02-02 00:01:47 -05:00
acb556b3d4 fix incorrect environment processing
it was assumed it could only be a dict or string (it starts out as a list)
also a 2nd assumption that bare vars only would appear in one of the dict keys.

removed deprecation warnings from here as they should be signaled in the bare conversion itself.
2016-02-02 00:01:36 -05:00
48b20684f2 normalize error message on src != dir when local
now action plugin returns same error as module
2016-02-01 13:44:01 -05:00
d7a6ccc4c2 Use isinstance type checks in bool filter so we can handle unsafe proxy objects. Fixes #14240 2016-02-01 12:34:13 -06:00
7f2bc082fa harcoding inventory/hosts when pulling from repo
return to pre 2.0 behaviour which did not factor inventory into the repo pull
2016-01-30 11:39:51 -05:00
d975f32243 added back --profile to keep backwards compat
this was broken by #12548
2016-01-30 11:36:37 -05:00
e8e388a742 Some attributes of callbacks aren't in v2. Port plugins to the v2 way to do that
Update porting guide with info on callback porting
2016-01-30 08:18:19 -08:00
a6c25f143a Explicitly set validate_certs=False as the boto default is True
Fixes #14089
2016-01-29 16:38:18 -08:00
e957ab5a7f fixed code for v1 callback runtime compatiblity
old exception code obsoleted by exception avoidance
errors on callback produce warnings and don't stop play
2016-01-29 17:01:30 -05:00
46002111bb fix unicode input for template lookup
fixes #14207
2016-01-29 16:46:33 -05:00
05bb1b3cb0 Better "conflicting action statements" message 2016-01-29 18:20:09 +00:00
8d7056220d Fix for SLES 11.4, which has now also an /etc/os-release file. 2016-01-29 09:14:13 -08:00
76c941305b When setting up the local connection for the rsync we need to set the shell as well.
Fixes #13490
2016-01-28 20:32:56 -08:00
48da1b8e85 New release v2.0.1.0-0.1.rc1 2016-01-28 16:39:53 -05:00
1e56daf66c More CHANGELOG updates for 2.0.1 2016-01-28 16:32:19 -05:00
506b0a8b61 New release v2.0.0.2-1 2016-01-28 16:24:01 -05:00
ea1339de18 New release v2.0.0.1-1 2016-01-28 16:24:01 -05:00
d60764bc81 Add more entries to changelog 2016-01-28 13:19:31 -08:00
951fa36fca Return an error when synchronize is used with something other than an ssh connection
Suggested in #2832
2016-01-28 16:05:12 -05:00
43cf527fe7 Don't try to generate retry files if the tqm hasn't been initialized
Fixes #14144
2016-01-28 16:02:54 -05:00
a074ebedbc Make retry file generation not use StringIO 2016-01-28 16:02:23 -05:00
d29dfdc84b Re-implementing the retry file feature for 2.0
Fixes #13944
2016-01-28 16:02:19 -05:00
aac8ea0262 Fix lookup of parent attribute when parent doesn't have the attr
Fixes #14100
2016-01-28 16:02:09 -05:00
3db2073909 Only use os.path.basename if get_file_content returned a value, and ensure that service_mgr has line endings stripped. Fixes #14026 2016-01-28 16:01:43 -05:00
0fddd90f14 Handle the key 'prepared' in the 'diff' result from modules
So far, when a 'diff' dict is returned with module results, it is
checked for 'before' and 'after' texts, which are processed in
_get_diff() by python difflib.  This generates the changes to display
when CLI users specify --diff.

However, some modules will generate changes that cannot easily be
expressed in a conventional diff. One example is the output of the
synchronize module, which presents changed files in a common log format
as in `rsync --itemize-changes`.

Add a check for a diff['prepared'] key, which can contain prepared diff text
from modules.
2016-01-28 16:01:15 -05:00
5fe16bef6f Make sure blocks use their parents dependency chains
Fixes a bug inroduced in fb797a9 where included tasks in a role
were not being executed because the child blocks had no dep chain
set.
2016-01-28 15:59:43 -05:00
86b179d3d7 Allow certain base attributes to be used as role params
Role definitions typically require params to be different from those
which are specified as FieldAttributes on the playbook classes used
for roles, however a certain subset should be allowed (typically those
used for connection stuff).

Fixes #14095
2016-01-28 15:59:43 -05:00
7a8520ac1a Fixing role dependency chain creation
The dep chain for roles created during the compile step had bugs, in
which the dep chain was overwriten and the original tasks in the role
were not assigned a dep chain. This lead to problems in determining
whether roles had already run when in a "diamond" structure, and in
some cases roles were not correctly getting variables from parents.

Fixes #14046
2016-01-28 15:59:43 -05:00
8f7868aead Note bugfix for unicode characters and the pager 2016-01-28 11:48:58 -08:00
9ddb4a985c Changes to convert to unicode at the borders
The module docs and vault changes solve issues where tracebacks can
happen.  The galaxy changes are mostly refactoring to be more pythonic
with a small chance that a unicode traceback could have occurred there
without the changes.  The change in __init__.py when we actually call
the pager makes things more robust but could hide places where we had
bytes coming in already so I didn't want to change that without auditing
where the text was coming from.

Fixes #14178
2016-01-28 11:47:21 -08:00
55db4d9e23 Add squashing fix to the changelog 2016-01-28 11:00:23 -08:00
849def8d6e Squashing was occuring even though pkgs didn't have a template that would be affected by squash
This broke other uses of looping (looping for delegate_to in the
reported bug)

Fixes #13980
2016-01-28 10:58:18 -08:00
c0d6a0c11a Update submodule refs 2016-01-28 09:44:19 -08:00
97cd0bc803 fixed unit test to match new output of become/su 2016-01-27 16:50:06 -05:00
7c7e849a27 fixed issue with vars prompt warning causing error
sometimes display object is not magically available, use it explicitly,
no need to be classmethod anymore
fixes #14147
2016-01-27 16:14:03 -05:00
9eaa5fecc1 fix for so su works in more cases
should not fail anymore on csh, fish nor the BSDs
fixes #14116
2016-01-27 14:13:27 -05:00
a0b7620b8e Add fix for 2831 to the changelog 2016-01-26 15:06:37 -08:00
3906614538 Fix for inventory hosts on localhost with alternate ports.
Fixes https://github.com/ansible/ansible-modules-core/issues/2831
2016-01-26 15:05:40 -08:00
03a89e17b9 fixed permissions check for ansible.log
fixes #13990
2016-01-26 11:23:04 -05:00
c52a35ff34 [hotfix] add missed playbook file 2016-01-26 10:45:58 -05:00
16ee2090bd Adding support for scm-based role source urls (incl. integration test to cover it) 2016-01-26 10:45:58 -05:00
7e1a3da97c Add last few major fixes to the 2.0.1 changelog 2016-01-25 20:07:19 -08:00
625e8f2030 Update submodule refs 2016-01-25 19:58:01 -08:00
826f42a153 For synchronize, fix sudo to execute on the remote end of the connection
* In 2.0.0.x become was reversed for synchronize. It was happening on
  the local machine instead of the remote machine. This restores the
  ansible-1.9.x behaviour of doing become on the remote machine.
  However, there's aspects of this that are hacky (no hackier than
  ansible-1.9 but not using 2.0 features).  The big problem is that it
  does not understand any become method except sudo.  I'm willing to use
  a partial fix now because we don't want people to get used to the
  reversed semantics in their playbooks.
* synchronize copying to the wrong host when inventory_hostname is
  localhost
* Fix problem with unicode arguments (first seen as a bug on synchronize)

Fixes #14041
Fixes #13825
2016-01-25 19:55:56 -08:00
1fdf8bca2a python3 doesn't have raw explicit-unicode literals. Workaround it with a raw native string that we make unicode in py2. 2016-01-25 19:48:17 -08:00
6eaf9b9fa2 Transform tracebacks into unicode before printing
Fixes #14042
2016-01-25 19:22:43 -08:00
9a3515357b raise AnsibleError as an 'expected' exception
fixes #14065
2016-01-25 22:21:31 -05:00
cd0812a187 adhoc now respects limit when listing hosts
also removed cruft about localhost as if used it is specified inline
fixes #13848
2016-01-25 17:39:39 -05:00
864c67cec5 ensure stdout callback alwasy is loaded first
it is now called for every event prior to any other callbacks
fixes #14114
2016-01-25 17:13:37 -05:00
7fe91e1848 better error when host inventory script isnt dict 2016-01-25 16:32:57 -05:00
084bacc4a4 add webdocs as alias 2016-01-25 16:32:38 -05:00
e6c9d9c81b Update CHANGELOG.md 2016-01-25 14:42:31 -05:00
0c250f2b07 Use templated handler name during callback
Fixes #14082
2016-01-23 09:26:25 -05:00
a516f883ac convert winrm put_file script template to Unicode string literal
Fixes traceback on homedirs with non-ascii chars
2016-01-22 13:11:02 -08:00
95f7aa2b53 corrected submodule ref 2016-01-22 08:16:53 -05:00
da4a9d6da0 Fix bug with any_errors_fatal where task was not available 2016-01-21 16:41:05 -05:00
d18cc79873 add detect Altlinux distributive 2016-01-21 16:10:53 -05:00
2b3cd2577a Disallow setting state on template tasks
Fixes #14056
2016-01-21 15:37:31 -05:00
50bb0d08f1 Template the run_once value in the linear strategy as we use it there
This is pre-post_validation, so we have to template it on the fly
as we use it to determine if we bypass the host loop.

Fixes #11876
2016-01-21 15:37:25 -05:00
391420d88f Re-add cache clearing call to Inventory init
This prevents a bug where the existing cache outside of the class
is not cleared when creating a new Inventory object. This only really
affects people using the API directly right now, but wanted to fix it
to prevent weird errors from popping up.
2016-01-21 15:37:19 -05:00
4627b3efbb Standardize removal of BECOME-SUCCESS method and use it for async too
Fixes #13965
Fixes #13971
2016-01-21 15:37:10 -05:00
7d8794daa6 plugins/strategy: added significant details to parser error message.
See discussion at
https://github.com/ansible/ansible/issues/13753
2016-01-21 15:37:02 -05:00
2021362386 Fix incorrect handling of any_errors_fatal in the linear strategy
Instead of bombing out of the strategy, we now properly mark hosts failed
so that the play iterator can handle block rescue/always properly.

Fixes #14024
2016-01-21 15:36:27 -05:00
bb564075b5 Forward conditionals onto included plays when conditional eval errors
When using a playbook-level include, we now catch any errors raised during
the conditional evaluation step and set a flag to indicate we need to pass
those conditionals on to the included play (most likely because they contain
inventory variables for evaluation).

Fixes #14003
2016-01-21 15:36:06 -05:00
09b26b6373 Don't assign both parent blocks and task includes to blocks
This causes problems when fetching parent attributes, as the include
was being skipped because the parent block would fetch the attribute
from the parent play first.

Fixes #13872
2016-01-21 15:35:57 -05:00
8647fdc7f2 go back to defaulting wrapping commands in shell
this was taken out in an effort to default to the user's shell but creates issues as this is not known ahead of time
and its painful to set executable and shell_type for all servers, it should only be needed for those that restrict the user
to specific shells and when /bin/sh is not available. raw and command may still bypass this by explicitly passing None.
fixes #13882

still conditional
2016-01-21 15:35:49 -05:00
7fe0bfd4f9 Revert "Properly look for parent become attribute"
This reverts commit 1b46a422aa.
2016-01-21 15:35:35 -05:00
2b5caa23fb Properly look for parent become attribute
Corrects inheritence of the boolean value, which needs some special
consideration from other (string/int) values.

Fixes #13872
2016-01-21 15:35:16 -05:00
0d2a9d3f53 Relocate use of ERROR to display class, to avoid doubling up 2016-01-21 15:35:09 -05:00
34e3a8e6cb Catch INI section parsing misses and raise an appropriate error
Fixes #13917
2016-01-21 15:35:02 -05:00
1fc35117d3 Fix role hashing failure/traceback when params contain lists
Fixes #13857
2016-01-21 15:34:52 -05:00
fb81447581 Don't clear start at task flag until all hosts are advanced
Clearing the flag after the first host was advanced caused all other
hosts to not advance at all.

Fixes #13864
2016-01-21 15:34:23 -05:00
2dfcb218dc Fix with loop + delegate issues
* Don't re-use the existing connection if the remote_addr field of
  the play context has changed
* When overriding variables in PlayContext (from task/variables),
  don't set the same attribute based on a different variable name
  if we had already previously set it from another variable name

Fixes #13880
2016-01-21 15:33:44 -05:00
44ab6db535 Fix any_errors_fatal incorrect implementation in 2.0
Also adds that flag to blocks.

Fixes #13744
2016-01-21 15:32:33 -05:00
d9f03cf014 Update submodule refs to pull in doc fixes 2016-01-21 11:11:32 -08:00
c5e46efbd9 Avoid recursively checking JSON inventory for Unicode
by moving to en-bloc unicode conversion to act on scripts stdout

Both python-json and simplejson always return unicode strings when using
their loads() method on unicode strings. This is true at least since
2009. This makes checking each substring unnecessary, because we do not
need to recursively check the strings contained in the inventory dict
later one-by-one

This commit makes parsing of large dynamic inventory at least 2 seconds
faster.

cf: https://github.com/towolf/ansible-large-inventory-testcase
2016-01-21 08:43:52 -08:00
92579eb48f avoid shredding empty files, also x/0
also cleaned up unused import and exception var
2016-01-21 10:56:24 -05:00
d56e2fb80e corrected host/group match in inventory_hostnames
now the lookup works when using ! and & operators
fixes #13997
2016-01-20 18:33:00 -05:00
1f930f098f Update core submodule to bring in yum fix 2016-01-20 12:18:03 -08:00
63404821da rework run_command's env setting to not change os.environ for the rest of the module.
New param to run_command to modify the environment for just this invocation.
Documentation and comment adjustments.
2016-01-20 12:17:14 -08:00
cf75521bc8 updated submodule refs 2016-01-20 15:02:04 -05:00
50d34f90e7 clarified with_file 2016-01-19 21:20:54 -05:00
089f17bfc8 Don't tracback trying to retore settings
Can occur if we exit the timeout before the settings were changed
2016-01-19 14:11:16 -08:00
27bf701260 Set decoding of path to unicode to raise an exception if non-utf8
Letting it pass would just cause an error later on (no such file found)
so it's better to catch it here and know that we have users dealing with
non-utf8 pathnames than to have to track it down from later on.
2016-01-19 05:50:46 -08:00
299e42bc28 Make all parts of messages and pathnames into unicode so that we don't get UnicodeError tracebacks.
Note that the fix for display normalizing to unicode is correct but the
fix for pathnames is probably not.  Changing pathnames to unicode type
means that we will handle utf8 pathnames fine but pathnames can be any
sequence of bytes that do not contain null.  We do not handle sequences
of bytes that are not valid utf8 here.  To do that we need to revamp the
handling of basedir and paths to transform to bytes instead of unicode.
Didn't want to do that in 2.0.x as it will potentially introduce other
bugs as we find all the places that we combine basedir with other path
elements.  Since no one has raised that as an issue thus far so it's not
something we need to handle yet.  But it's something to keep in mind for
the future.

To test utf8 handling, create a utf8 directory and run a playbook from
within there.

To test non-utf8 handling (currently doesn't work as stated above), create
a directory with non-utf8 chars an run a playbook from there.  In bash,
create that directory like this: mkdir $'\377'

Fixes #13937
2016-01-19 05:45:56 -08:00
2f40903397 clarify role include paths 2016-01-19 08:48:55 -05:00
2ec31c2c79 fixed exception handling to be 2.4 compatible
previous 'fix' broke on 2.4
2016-01-19 08:33:37 -05:00
7afd8e9640 added missed ec2_vpc_net_facts 2016-01-18 22:06:05 -05:00
93781e0b05 be consistent about conversion to_str 2016-01-18 21:56:09 -05:00
edff4a9219 updated submodule refs 2016-01-18 21:15:30 -05:00
69b8a48ed1 Turn results that come from traceback messages into unicode, not str.
Fixes #13964
Fixes #13967
2016-01-18 14:44:57 -08:00
8f45660398 Update submodule refs 2016-01-18 13:59:46 -08:00
c8ffe94bf4 Fix proposed by @Yannig to fix become success detection when the output is multiline
See the Bug report for a specific error case with local connection,
sudo, and the raw module

Fixes #13728
2016-01-18 13:52:23 -08:00
c06b2e4622 correctly deals with non serializable type
combine_vars shoudl really be data types, but some just get in
in test, add dict to mock and avoid combine_vars using object
2016-01-18 15:18:18 -05:00
1394cdf6b9 Fix set_fact + run_once to assign variables to all hosts in the list
Fixes #13921
2016-01-18 11:55:39 -08:00
38a272b004 Allow module args as k=v pairs when using the module: option with local_action
This task format is valid in 1.x, but was broken in 2.x:
  - local_action:
     module: shell echo "hello world"
2016-01-18 11:55:30 -08:00
97a5804a2c Minor cleanup when reassigning play context to reused connections
* Relocate the assignment of the host address to the remote_addr field
  in the play context, which was only done when the connection was created
  (it's now done after the post_validate() is called on the play context)
* Make the assignment of the play context to the connection an else, since
  it's not required if the connection is not reused
2016-01-18 11:55:21 -08:00
8436a88b5d Fixes #13763 Update connections _play_context on every iteration
If this isnt updated, the _connection is reused, and thus has an outdated _play_context
This results in outdated `success_key` and `prompt` causing issues if sudo is run in a loop
Refer to the issue #13763 for more debugging and details
2016-01-18 11:55:12 -08:00
0bf20fab84 Fix erroneous fetch fail when fail_on_missing is set to False
Fixes #13832
2016-01-15 16:29:04 -08:00
22272fe5b8 Fix typos. 2016-01-15 15:10:44 -05:00
7d8afbd83d fix issue with add_hosts overwriting existing vars
fixes github.com/ansible/ansible-modules-core/issues/2799 and is alternative to #13841
2016-01-15 14:27:15 -05:00
f11e54bcff update core submodule ref 2016-01-15 09:36:08 -08:00
46a3a6a03e Non-newstyle modules can't use pipelining
This is because we pass arguments to non-newstyle modules via an
external file.  If we pipeline, then the interpreter thinks it has to
run the arguments as the script instead of what is piped in via stdin.
2016-01-14 17:24:25 -08:00
e29ae99b50 overwrite/merge not remove prev inventory data 2016-01-14 18:42:10 -05:00
363b74e498 Allow Ansible to return error with unicode within it.
Fix for https://github.com/ansible/ansible/issues/13899
2016-01-14 15:07:19 -08:00
17b60f4fbf Fix typo in 0b86aa6 2016-01-14 16:49:46 -05:00
b89f211ed4 Hack to work around callback API change for v2_playbook_on_start 2016-01-14 16:49:46 -05:00
cde5d8444d When setting fail state skip RESCUE/ALWAYS if cur_block doesn't have them
Fixes #13749
2016-01-14 15:59:40 -05:00
6cf0386a52 Tweak how strategies evaluate failed hosts via the iterator and bug fixes
* Added additional methods to the iterator code to assess host failures
  while also taking into account the block rescue/always states
* Fixed bugs in the free strategy, where results were not always being
  processed after being collected
* Added some prettier printing to the state output from iterator

Fixes #13699
2016-01-14 15:59:40 -05:00
b09f756195 now combine vars errors dump vars
very hard to debug w/o knowing what vars were being merged at the time of the error
2016-01-14 11:00:54 -05:00
27f9b9dc43 md5 now uses smaller salt
fixes #13891
2016-01-14 11:00:34 -05:00
31a951c4f7 only send event if tqm exists
fixes #13843
2016-01-14 11:00:18 -05:00
fe55e87ab4 Prevent traceback.
https://github.com/ansible/ansible/issues/13743#issuecomment-171520585

In some circumstance, the file fails to open.  When that occurs, we
can't try to close it in the finally clause.  Using a context manager is
the cleanest way to change the code to account for that case.
2016-01-13 20:52:22 -08:00
2ed31fc818 Add python-setuptools to the requirements for running ansible as
python-setuptools contains the egginfo needed to make pkg_resources
work.
2016-01-13 17:22:43 -08:00
be087575cc Fix circular import 2016-01-13 14:05:24 -08:00
79931041e2 do_encrypt import needed to move as well
Fixes #13861
2016-01-13 13:09:19 -08:00
832a739331 use integer division instead of floating point division.
Fixes #13855
2016-01-13 12:35:44 -08:00
b83ef89f09 Add windows/unix newline change to the changelog 2016-01-13 08:49:48 -08:00
419bd389d8 move core submodule ref for win_msi fix 2016-01-12 09:38:34 -08:00
e497e2b5c0 made loading of galaxy data files lazy 2016-01-12 12:28:47 -05:00
16ae952888 re-adding the dummy debian changlog entry for packaging 2016-01-12 12:20:23 -05:00
954eba8605 added galaxy data
not tested, but something like this seems to be missing in the Manifest.in
2016-01-12 11:31:54 -05:00
e4b701c00a added module name to missing interpreter error
fixes #13816
2016-01-12 11:26:18 -05:00
21c22a2416 Allow InventoryScript JSON with childgroups only
and without hosts and vars

Without this patch, the simplified syntax is triggered when a group
is defined like this:

    "platforms": {
        "children": [
            "cloudstack"
        ]
    }

Which results in a group 'platforms' with 1 host 'platforms'.

more details in https://github.com/ansible/ansible/issues/13655
2016-01-12 11:26:11 -05:00
4e98cc351c Update submodule refs so that new integration tests will pass 2016-01-12 08:02:47 -08:00
f53cb5f63e Integration tests for https://github.com/ansible/ansible-modules-core/pull/558 2016-01-12 08:02:05 -08:00
1cae019c79 cloudstack: fix case insensitivity
cloudstack: fix has_change reports changed for case insensitivity values
2016-01-12 08:02:05 -08:00
f3470c1062 cleaner implementation and random chunk length. 2016-01-12 08:02:05 -08:00
21a4c1380c use unix shred if possible, otherwise fast custom impl; do not shred encrypted file 2016-01-12 08:02:05 -08:00
4811504a6e add docs, remove unnecessary int() cast 2016-01-12 08:02:05 -08:00
08fee9bfc5 add os.fsync() so that the shredding data (hopefully) hits the drive 2016-01-12 08:02:05 -08:00
2cb2994371 shred ansible-vault tmp_file. Also when editor is interruped. 2016-01-12 08:02:05 -08:00
2eb59bedcf New release v2.0.0.0-1 2016-01-12 08:43:33 -05:00
14bf6b016c Split up comma-separated tags properly
Fixes #13795
2016-01-12 08:18:37 -05:00
28fecc9ce1 bugfix in nxos shared module for including defaults 2016-01-11 22:49:01 -05:00
2c647f18e5 bugfix in ios shared module for including defaults 2016-01-11 22:48:54 -05:00
4e087bb14f bugfix in eos shared module for including defaults 2016-01-11 22:48:43 -05:00
1f7fbf29f9 updated new windows module list in changelog 2016-01-11 16:24:30 -08:00
0681c2fd8f deletes nxapi from shared modules
The nxapi module has been superseded by the nxos shared module and is not longer needed. This commit removes (deletes) nxapi from module_utils.  All custom modules that have used nxapi should be using nxos instead.
2016-01-10 15:13:18 -05:00
4a6235e320 adds network config file parser to shared modules
This commit adds a new shared module that parses network device configuration
files.  It is used to build modules that work with the various supported
network device operating systems
2016-01-10 15:12:45 -05:00
94f13c7271 adds shared module shell for creating cli based transports
This commit add a new shared module shell that is used to build connections
to network devices that operate in a CLI environment.  This commit supercedes
the issh.py and cli.py commits and removes them from module_utils.
2016-01-10 15:12:29 -05:00
93eb60161c initial add of openswitch shared module
This commit adds a new shared module openswitch for building modules that
work with OpenSwitch.  This shared module supports connectivity to
OpenSwitch devices over SSH, CLI or REST.  It also adds an openswitch
documentation fragment for use in modules
2016-01-10 15:12:15 -05:00
2f1fc85002 adds shared module nxos for building cisco nxos modules
This commit refactors the nxapi into a new shared module nxos that supports
connectivity over both ssh (cli) and nxapi.  It supercedes the nxapi shared
module and removes it from module_utils.  This commit also adds a
documentation fragement supporting the nxos shared module
2016-01-10 15:12:05 -05:00
91f35363a2 adds new iosxr shared module for developing modules that work with IOS XR devices
This commit adds a new shared module for working with Cisco IOS XR devices over
CLI (SSH).  It also provides a documentation fragement for the commmon arguments
provided by the iosxr module.
2016-01-10 15:11:55 -05:00
f76633b347 updates the ios shared module with new shell
This update refactor the ios shared module to use the new shell shared
library instead of issh and cli.  It also adds the ios documentation
fragment to be used when building ios based modules.
2016-01-10 15:11:37 -05:00
9c9bfb962e initial add of eos shared module
This adds a shared module for communicating with Arista EOS devices over
SSH (cli) or JSON-RPC (eapi).  This modules replaces the eapi.py module
previously added to module_utils.  This commit includes a documentation
fragment that describes the eos common arguments
2016-01-10 15:11:08 -05:00
0e27fa4540 restructure vars_prompt and fix regression
pushed it to use the existing propmpt from display and moved the vars prompt code there also for uniformity
changed vars_prompt to check extra vars vs the empty play.vars to restore 1.9 behaviour
sipmlified the code as it didn't need to check for syntax again (tqm is made none prior based on that)
fixes #13770
2016-01-08 17:56:13 -05:00
3a972c9170 Restore ability for a module to specify WANT_JSON 2016-01-08 12:49:08 -05:00
91c7691a92 noted that regex_escape was added in 2.0
fixes #13759
2016-01-07 19:02:08 -05:00
502ad88506 New release v2.0.0-0.9.rc4 2016-01-07 13:41:47 -05:00
80f0380312 Fix typo 2016-01-07 06:01:44 -08:00
a8f160d2fd More fixes for unicode handling in the connection plugins.
Tested that ssh, docker, local, lxc-libvirt, chroot all work with the
updated unicode integration test.
2016-01-07 06:01:34 -08:00
6be48dd14c Revert "Show version without supplying a dummy action"
This reverts commit 21775d7866.
Parsing before action will fail if one of the action specific options is used
As per issue #13743
2016-01-07 08:29:43 -05:00
fcd074d40f Merge branch 'ktosiek-fix-playbook-hanging' into stable-2.0 2016-01-06 14:01:35 -05:00
21775d7866 Show version without supplying a dummy action
fixes #12004
parsing x2 does not seem to break anything
2016-01-06 11:54:19 -05:00
ab536c8aa8 Strip string terms before templating
The earlier code did call terms.strip(), but ignored the return value
instead of passing that in to templar.template(). Clearly an oversight.
2016-01-06 11:25:55 -05:00
93f37f5969 Don't drop noops from task counting code in linear strategy 2016-01-06 09:58:20 -05:00
ec3b7b7de8 linear strategy: don't look at tasks from the next block 2016-01-05 21:49:08 +01:00
7a4914aa9b Fix exception catching to be importable on python3 2016-01-05 12:04:22 -08:00
9ca5da82ff move hostvars.vars to vars
this fixes duplication under hostvars and exposes all vars in the vars dict
which makes dynamic reference possible on 'non hostvars'
2016-01-05 14:36:21 -05:00
3d608ef9fa simplified diff handling in callback
no need for the copy or other complexity
2016-01-05 14:27:33 -05:00
c14e099dd7 now handles 'non file diffs'
this allows modules to pass back a 'diff' dict and it will still show using the file interface
2016-01-05 14:27:33 -05:00
7e318e8398 Update extras submodule ref 2016-01-05 07:52:44 -08:00
add2e9cbd1 Fix problems with non-ascii values passed as part of the command to connection plugins
@drybjed discovered this with non-ascii environment variables and
command line arguments to script and raw module.
2016-01-05 07:46:24 -08:00
9f93c9c84b Clean up debug logging around _low_level_execute_command
We were logging the command to be executed many times, which made debug
logs very hard to read. Now we do it only once.

Also makes the logged ssh command line cut-and-paste-able (the lack of
which has confused a number of people by now; the problem being that we
pass the command as a single argument to execve(), so it doesn't need an
extra level of quoting as it does when you try to run it by hand).
2016-01-05 07:46:13 -08:00
b4e0b5503c move core submodule pointer 2016-01-04 16:10:29 -08:00
5536ddd118 Do not set 'changed' to True when using group_by
Since group_by is not changing in any way to the remote
system, there is no change. This also make things more consistent
with the set_fact plugin.
2016-01-04 16:23:25 -05:00
021ed1aa8b Replace to_string by to_unicode.
Fix https://github.com/ansible/ansible/issues/13707
2016-01-01 08:18:18 -08:00
a703f3a6d2 added newer vars to 'reset_vars'
these vars pass back info to the task about the connection
moved to their own block at start at file for readability and
added the newer standard vars
2015-12-28 12:50:04 -05:00
f7ea8b32a9 minor fix to become docs 2015-12-28 10:25:35 -05:00
ba7d2db8ad clarify idempotence explanation
Small typo; wasn't sure what to replace it with.
2015-12-28 10:24:55 -05:00
b50ed10a84 updated release cycle to 4 months instead of 2 2015-12-27 14:17:58 -05:00
b4fae25a96 CHANGELOG entry for bigip* validate_certs change 2015-12-25 12:24:19 -08:00
6142736946 Oops, core needs to stay on stable-2.0 2015-12-25 12:16:18 -08:00
25fc4217df Update submodule refs 2015-12-25 12:15:49 -08:00
d71e8fb870 bigip changes as requested by bcoca and abadger:
* Fix to error if validate_cert is True and python doesn't support it.
* Only globally disable certificate checking if really needed.  Use
  bigip verify parameter if available instead.
* Remove public disable certificate function to make it less likely
  people will attempt to reuse that
2015-12-25 12:15:24 -08:00
369ed9feed cloudstack: test_cs_instance: more integration tests
cloudstack: extend test_cs_instance addressing recovering

cloudstack: test_cs_instance: add tests for using display_name as indentifier.
2015-12-23 17:48:49 -08:00
ebd3b35d02 Update submodule refs 2015-12-23 14:29:36 -08:00
82df9041e7 Going to do this in the connection plugin
Revert "Transform the command we pass to subprocess into a byte string in _low_level-exec_command"

This reverts commit 6d76cb40c5.
2015-12-23 13:28:42 -08:00
dd59fc176e Going to do this in the connection plugin
Revert "Fix make tests-py3 on devel. Fix for https://github.com/ansible/ansible/issues/13638."

This reverts commit 725e40c5e6.
2015-12-23 13:28:42 -08:00
9af054addf Going to do this in the connection plugin
Revert "Convert to bytes later so that make_become_command can jsut operate on text type."

This reverts commit bfc082fb07.
2015-12-23 13:28:42 -08:00
7f29cb9dc6 corrected role path search order
the unfraking was matching roles in current dir as it always returns a full path,
pushed to the bottom as match of last resort
fixes #13645
2015-12-23 15:15:58 -05:00
2786908bac fixed tests to follow new invocation structure
also added maxdiff setting to see issues clearly when they happen
2015-12-23 11:45:50 -05:00
43331d8c31 better module error handling
* now module errors clearly state msg=MODULE FAILURE
* module's stdout and stderr go into module_stdout and module_stderr keys
which only appear during parsing failure
* invocation module_args are deleted from results provided by action
plugin as errors can keep us from overwriting and then disclosing info that
was meant to be kept hidden due to no_log
* fixed invocation module_args set by basic.py as it was creating different
keys as the invocation in action plugin base.
* results now merge
2015-12-23 10:59:01 -05:00
579a2ff739 fix no_log disclosure when using aliases 2015-12-22 17:17:06 -05:00
bfc082fb07 Convert to bytes later so that make_become_command can jsut operate on text type.
Conflicts:
	lib/ansible/plugins/action/__init__.py
2015-12-22 08:33:36 -08:00
725e40c5e6 Fix make tests-py3 on devel. Fix for https://github.com/ansible/ansible/issues/13638. 2015-12-22 08:33:36 -08:00
8216a659fa Also convert ints to bool for type=bool 2015-12-22 10:25:25 -05:00
a2120a3d63 Version bump for 2.0.0-0.8.rc3 2015-12-21 17:59:27 -05:00
6d76cb40c5 Transform the command we pass to subprocess into a byte string in _low_level-exec_command 2015-12-21 13:55:06 -08:00
b0e7ea78af Actually disable parallel makes for integration runner 2015-12-21 16:12:27 -05:00
6a0d2116b8 Delete new_inventory from stable-2.0 as it isn't used there.
leaving in devel for now as some people are planning on using it as
a starting place to update inventory in 2.1
2015-12-21 13:11:16 -08:00
37908735d4 Dropping instance size back down since we're not doing parallel builds 2015-12-21 15:55:16 -05:00
c0248873da Integration test runner tweaks 2015-12-21 15:53:19 -05:00
75695f5c70 Kick up the integration runner test image size 2015-12-21 15:53:19 -05:00
0a6bc57fa5 Parallelize make command for integration test runner
Also adds a new var, used by the prepare_tests role, to prevent it from
deleting the temp test directory at the start of each play to avoid any
potential race conditions
2015-12-21 14:09:02 -05:00
1d18964daa Merge role params into variables separately from other variables
Fixes #13617
2015-12-21 13:55:17 -05:00
8eb3963cd9 Adding documentation for the 'dig' lookup (#13126). 2015-12-21 13:49:49 -05:00
c605cd37f6 allow for non standard hostnames
* Changed parse_addresses to throw exceptions instead of passing None
* Switched callers to trap and pass through the original values.
* Added very verbose notice
* Look at deprecating this and possibly validate at plugin instead
fixes #13608
2015-12-21 13:42:47 -05:00
e1698fb4bf role search path clarified 2015-12-21 13:16:48 -05:00
81f09f3fbd Disable docker test for Fedora, due to broken packaging 2015-12-21 10:58:49 -05:00
b77d834239 Uncomment docker test for stable-2.0 2015-12-21 10:58:35 -05:00
7607e55a5a Save output of integration test results to files we can archive 2015-12-21 10:58:02 -05:00
d512717cd2 Fix logic in PlayIterator when inserting tasks during rescue/always
Because the fail_state is potentially non-zero in these block sections,
the prior logic led to included tasks not being inserted at all.

Related issue: #13605
2015-12-21 10:57:24 -05:00
ce17557b84 Fixed import typo for memcache module in tests.
The typo caused the test for the memcached cache plugin to be skipped
even when the necessary memcache python module was installed.
2015-12-21 10:27:36 -05:00
80e109e1ad And change the task a little more since different shlex versions are handling the quotes differently 2015-12-20 11:52:50 -08:00
fdc562e3c3 Fix test playbook syntax 2015-12-20 11:47:17 -08:00
1dcfd7ba02 Since the velox test server seems to be dropping using iptables to drop requests from aws, test via a different website instead 2015-12-20 11:38:54 -08:00
9cfa2d7e28 Fixing bugs in conditional testing with until and some integration runner tweaks 2015-12-20 12:45:33 -05:00
5bd01c09d6 Troubleshooting has reduced us to this 2015-12-20 12:45:28 -05:00
61bd0e1310 Fix the fedora host detection 2015-12-20 12:45:09 -05:00
bb1047c483 What is going on here 2015-12-20 12:45:03 -05:00
c2a29a01a2 Removing update all for test deps, it didn't fix the problem 2015-12-20 12:44:20 -05:00
6a1ebaa1bc Fix typo in integration test runner role 2015-12-20 12:44:10 -05:00
1d1a04008e Update mysql setup to handle installing mysql with dnf too. 2015-12-20 12:43:47 -05:00
1cde02058f Make integration tests run in parallel with async 2015-12-20 12:41:53 -05:00
48675550bf Try updating the centos7 image to a newer version (trying to resolve issue being unable to connect to some webservers) 2015-12-20 09:13:03 -08:00
3955ea5a8a Fixes for tests that assumed yum as package manager for systems that
have dnf
2015-12-20 08:11:05 -08:00
454c8ff5b8 Switch from yum to package when installing sudo so that dnf is handled as well 2015-12-20 08:10:58 -08:00
ba0b4afb6b Revert "removed invocation info as it is not no_log aware"
This reverts commit 6127a8585e.
2015-12-19 15:51:29 -08:00
76507bd567 Make return invocation information so that our sanitized copy will take precedence over what the executor knows. 2015-12-19 15:51:22 -08:00
d2bf615780 Fix unittests for return of invocation from fail_json and exit_json 2015-12-19 15:50:43 -08:00
3840fb267c corrected service detection in docker versions
now if 1 == bash it falls back into tool detection
2015-12-19 16:16:28 -05:00
fbccfc8b61 Add package module to squash list 2015-12-19 13:01:48 -08:00
2d179b376b Remove args from get_name() as we can't tell if any of the args are no_log 2015-12-19 11:51:51 -08:00
a0add9dda5 Comment to explain why we strip _ansible_notify specially 2015-12-19 11:32:31 -08:00
de9517dcc8 Also need redhat-rpm-config to compile pycrypto 2015-12-19 11:27:55 -08:00
bef2b70eae Make sure that yum is present on redhat family systems (makes things also work on fedora systems where dnf is the default) 2015-12-19 11:24:27 -08:00
df08ba37fe removed invocation info as it is not no_log aware
This was added in 1.9 and 2.0 tried to copy, but since it cannot
obey no_log restrictions I commented it out. I did not remove as
it is still very useful for module invocation debugging.
2015-12-19 11:45:59 -05:00
6dc42e376f update submodule refs 2015-12-18 22:18:25 -08:00
9689f00bb1 Add a Fedora latest host into the mix 2015-12-18 22:15:29 -08:00
2f0e8d9654 Make integration runner ec2 add_hosts use valid host names 2015-12-18 16:04:54 -08:00
6d9235e36d Fix the fedora host detection 2015-12-18 15:43:39 -08:00
eb606cc18b What is going on here 2015-12-18 15:43:32 -08:00
85ef768d51 Bugfix the fedora 23 install task 2015-12-18 14:39:27 -08:00
457e32128f Ubuntu images with hvm ssd 2015-12-18 14:39:20 -08:00
e8ce341f9c Fedora 23 needs to have python2 packages installed 2015-12-18 14:08:43 -08:00
87214005d2 Make tests that use kennethreitz retry. 2015-12-18 11:51:16 -08:00
dc0a4e74d6 added note about add_hosts 2015-12-18 13:57:58 -05:00
43409fa16c added missing features to changelog 2015-12-18 12:15:08 -05:00
b912923ef2 Do a full yum update to make sure packages are latest version
For the deps setup of integration tests, as we sometimes see odd
errors we can't reproduce, which may be related to slightly out of
date package dependencies.
2015-12-18 08:51:57 -08:00
46bc8253e1 Add awk to integration test deps list 2015-12-18 08:51:42 -08:00
1f70fc6424 Add state=latest to pip install of pycrypto 2015-12-18 08:51:34 -08:00
ed4ad5f6fb Add ca-certificates update to the integration deps playbook 2015-12-18 08:51:25 -08:00
69eb22c652 Install an updated version of pycrypto on Ubuntu12 from pip 2015-12-18 08:51:14 -08:00
dca880d04a kennetreitz.org times out but www.kennethreitz.org is fine 2015-12-18 08:34:07 -08:00
0c6364c771 debug line needs var not msg 2015-12-18 08:33:55 -08:00
c9cf07e3b5 Fixing bugs with {changed,failed}_when and until with registered vars
* Saving of the registered variable was occuring after the tests for
  changed/failed_when.
* Each of the above fields and until were being post_validated too early,
  so variables which were not defined at that time were causing task
  failures.

Fixes #13591
2015-12-18 11:08:06 -05:00
bcd66059ae Use --source instead of -e for awk in integration Makefile 2015-12-17 20:53:43 -05:00
72e6dbcd12 Fix get_url tests in light of distros backporting SNI support 2015-12-17 17:53:38 -08:00
184c2985fc Consolidating package lines for virtualenv install in test deps integration 2015-12-17 17:46:12 -05:00
4abbe8a989 Moving apt cache update to top to ensure cache is updated before deps installed 2015-12-17 17:46:12 -05:00
ce159ce2eb Switch virtualenv dep installation from pip to package manager 2015-12-17 17:46:12 -05:00
fdb94b9a7a Adding pip install of virtualenv to test deps integration role 2015-12-17 17:45:59 -05:00
be0e826091 remove .gitignore 2015-12-17 14:18:12 -08:00
f12ed5eba8 symbolic link role for testing 2015-12-17 14:18:06 -08:00
b1d5e9ff3c removed ansible_python_interpreter
* added missed renames of ansible_deps to ansible_test_deps
* removed acidential inventory.dynamic file
* modified README for ansible_test_deps role
2015-12-17 14:17:58 -08:00
dcb732b416 rename role ansible_deps to ansible_test_deps 2015-12-17 14:17:49 -08:00
ad6ec9610e playbook that Ansible jenkins runs moved into core
The playbook is already running in jenkins and works. This moves the
assets into core for ease of maintenance going forward.
2015-12-17 14:17:41 -08:00
fcceac5ff2 trigger jenkins integration tests 2015-12-17 14:17:35 -08:00
0a319a28f2 Update submodule for mysql_user fix 2015-12-17 13:47:07 -08:00
17fe156016 Fixing a mistake from tweaking list stuff too much
Use the action only if the task name is not set
2015-12-17 16:34:03 -05:00
5824a6d9bb Further tweaks to the output format of list tasks/tags 2015-12-17 16:31:02 -05:00
59cac03d3b Make --list-tasks respect tags
Also makes the output closer to the appearance of v1

Fixes #13260
2015-12-17 16:11:00 -05:00
cc2e0c1e3d Update submodule to pull in mysqldump fix 2015-12-17 13:02:11 -08:00
624556eb16 Add recent bugfixes to changelog 2015-12-17 10:35:24 -08:00
64737c80f9 Update submodule refs 2015-12-17 10:21:50 -08:00
5e9d182229 changed test to use filter for accurate reporting 2015-12-17 12:28:17 -05:00
1f7ed5d8ee Fix handling of environment inheritence, and template each inherited env
Environments were not being templated individually, so a variable environment
value was causing the exception regarding dicts to be hit. Also, environments
as inherited were coming through with the tasks listed first, followed by the
parents, so they were being merged backwards. Reversing the list of environments
fixed this.
2015-12-17 09:46:41 -05:00
f41dd578b3 Make sure we're using the original host when processing include results
Also fixes a bug where we were passing an incorrect number of parameters to
_do_handler_run() when processing an include file in a handler task/block.

Fixes #13560
2015-12-16 19:13:03 -05:00
407d76b8d5 Fixing template integration test for python 2.6 versions
No longer immediately fallback to to_json if simplejson is not installed
2015-12-16 18:24:12 -05:00
d2c43c421f Update core module ref for mysql_user fix 2015-12-16 14:10:00 -08:00
6c509b5364 Updating the porting guide to note the complex args/bare vars change
Related to #13518
2015-12-16 16:37:55 -05:00
4bce9947e5 fixed formating issues with rst 2015-12-16 16:37:55 -05:00
4ad7135690 Add first draft of porting guide for 2.0 2015-12-16 16:37:55 -05:00
bf9f6ce09c All variables in complex args again
Also updates the CHANGELOG to note the slight change, where bare variables
in args are no longer allowed to be bare variables

Fixes #13518
2015-12-16 16:37:55 -05:00
84a6b543a9 ensure additional args are a dict
They should already be templated before hitting this point?
otherwise the class needs the task variables passed into it.
relates to #13518 and  https://groups.google.com/forum/#!msg/ansible-project/esoBcphHwHs/Ghgi_M-MCQAJ
2015-12-16 15:32:26 -05:00
6cf7b792a3 Fix docs. The search command works with both galaxy.ansible.com and galaxy-qa.ansible.com. 2015-12-16 15:11:45 -05:00
abec9331d8 Fixed documentation typos and bits that needed clarification. Fixed missing spaces in VALID_ACTIONS. 2015-12-16 15:11:41 -05:00
ba16f2ae95 Add a section to intro_configuration for Galaxy. 2015-12-16 15:11:34 -05:00
1e605d727c Define and handle ignore_certs correctly. Preserve search term order. Tweak to Galaxy docsite. 2015-12-16 15:11:30 -05:00
6c48d52b4a Make sure it is clear that new commands require using the Galaxy 2.0 Beta site. 2015-12-16 15:11:26 -05:00
8bb598daa2 Updated ansible-galaxy man page. Removed -b option for import. 2015-12-16 15:11:22 -05:00
21edd6a5ab Fix overloaded options. Show an error when no action given. Don't show a helpful list of commands and descriptions. 2015-12-16 15:11:05 -05:00
e10e03f4d9 added releases doc 2015-12-16 15:10:48 -05:00
d5bdea0bab fix plugin loading for Windows modules
force plugin loader to only consider .py files, since that's the only place docs can live ATM...
2015-12-16 11:47:52 -08:00
cd1bdaa61d Update submodule refs for mysql refactor 2015-12-16 11:14:39 -08:00
9f69b6b585 Add shared connection code for mysql modules 2015-12-16 11:06:21 -08:00
9e52a7c769 Attempt at fixing strategy unit test failures on py2.6 and py3 2015-12-16 13:57:13 -05:00
8fd438000a Update url to site that has an invalid certificate 2015-12-16 09:47:56 -08:00
54ce8327cb Disabling docker test for stable-2.0 due to versioning issues 2015-12-16 11:24:29 -05:00
82519ab2a6 Preserve the cumulative path for checking includes which have parents
Otherwise, each relative include path is checked on its own, rather
than in relation to the (possibly relative) path of its parent, meaning
includes multiple level deep may fail to find the correct (or any) file.

Fixes #13472
2015-12-16 11:23:33 -05:00
5761c333a6 Update submodule ref to fix docs build 2015-12-16 08:13:54 -08:00
72b852a814 Update submodule refs 2015-12-16 08:03:34 -08:00
897569c1ca Conditionally create the CustomHTTPSConnection class only if we have the required baseclasses.
Fixes #11918
2015-12-16 08:02:11 -08:00
8e2cb2abb2 Fixes for proxy on RHEL5 2015-12-16 08:02:03 -08:00
b8d9b106de First attempt to fix https certificate errors through a proxy with python-2.7.9+
Fixes #12549
2015-12-16 08:01:56 -08:00
f68c0043de Fix typo 2015-12-16 10:53:10 -05:00
48fb0cdecb debug now validates its params
simplified var handling
made default message the same as in pre 2.0
fixes #13532
2015-12-16 10:42:30 -05:00
28602cddb0 Use the original host rather than the serialized one when processing results
Fixes #13526
Fixes #13564
Fixes #13566
2015-12-16 01:50:14 -05:00
5011d63f7e Fix a part of python 3 tests (make tests-py3, see https://github.com/ansible/ansible/issues/13553 for more details). 2015-12-15 07:57:05 -08:00
5ab25e2dfe clean debug output to match prev versions 2015-12-15 09:28:39 -05:00
6e1bb6c87d renamed ssh.py shared module file to clarify 2015-12-15 08:44:43 -05:00
ac7dc6bd81 the ssh shared module will try to use keys if the password is not supplied
The current ssh shared module forces only password based authentication.  This
change will allow the ssh module to use keys if a password is not provided.
2015-12-15 08:39:17 -05:00
b6dac26224 Make module_utils.known_hosts.get_fqdn work on ipv6 2015-12-14 11:10:02 -08:00
a7a3a34987 Add tests for ansible.module_utils.known_hosts 2015-12-14 11:09:49 -08:00
6df187da84 Fix for template module not creating a file that was not present when force=false 2015-12-14 10:57:34 -08:00
cf95619229 Optionally only use UUIDs for openstack hosts on duplicates
The OpenStack inventory lists hostnames as the UUIDs because hostsnames
are not guarnateed to be unique on OpenStack. However, for the common
case, this is just confusing.

The new behavior is a visible change, so make it an opt-in via config.

Only turn the hostnames to UUIDs if there are duplicate hostnames.
2015-12-14 13:27:33 -05:00
17a37844d4 Fix the refresh flag in openstack inventory
Refresh will update the dogpile cache from shade, but doesn't cause
the ansible side json cache to be invalidated. It's a simple oversight.
2015-12-14 13:27:33 -05:00
gp
0697c6e59d Fix typo in galaxy.rst
Fix typo
2015-12-14 09:15:15 -08:00
66be9d06c4 Minor: Correct type pyhton => python 2015-12-14 08:51:33 -08:00
62b2c9eb4e Update submodule refs 2015-12-14 08:34:49 -08:00
887319f95c add tests for encrypted hash mysql_user 2015-12-14 08:02:11 -08:00
fc233bf3f4 Use an octal representation that works from 2.4->3+ for known_hosts 2015-12-14 10:44:22 -05:00
8dcba63022 Fixing up some non-py3 things for unit tests 2015-12-14 10:44:22 -05:00
60f5fe76a1 use default settings from ansible.cfg 2015-12-14 09:19:15 -05:00
0b66ec0ddd Cleanup strategy tests broken by new forking strategy 2015-12-14 03:07:51 -05:00
e7bf204db4 A few tweaks to improve new forking code 2015-12-14 03:07:48 -05:00
c8e6461dee Changing the way workers are forked 2015-12-14 01:16:55 -05:00
3214ef8832 added that ansible-pull is now shallow to changelog 2015-12-13 12:18:28 -05:00
6a5444c2fe add --full flag to ansible-pull man page
add --full flag that was added in #13502
2015-12-13 12:17:36 -05:00
d4e06695fd Fix Doc mistake
Fix Doc mistake in ansible/docsite/rst/playbooks_variables.rst
2015-12-13 09:50:45 -05:00
d369e3ec72 fix whitespace 2015-12-13 09:37:48 -05:00
bff8db3c8f make shallow clone the default for ansibel-pull 2015-12-13 09:37:48 -05:00
8c6010cc86 add depth option to ansible-pull
Allows shallow checkouts in ansible-pull by adding `--depth 1` (or higher number)
2015-12-13 09:37:48 -05:00
13ffd3ee2d include all packaging in tarball
not juse rpm spec file
2015-12-13 00:34:56 -05:00
f9bff8e488 simplified skippy
thanks agaffney!
2015-12-12 17:51:25 -05:00
6d83bf8ca9 changed shell delimiters for csh
fixes #13459
2015-12-12 16:13:20 -05:00
17f06dd310 removed unused imports in galaxy/cli 2015-12-12 13:43:46 -05:00
82f893d65a Explain how 'run_once' interacts with 'serial' 2015-12-12 00:33:21 -05:00
40b55eda4c avoid set to unique hosts to preserver order
swiched to using a list comp and set to still unique but keep expected order
fixes #13522
2015-12-11 15:40:48 -05:00
7678ab05d8 removed merge conflict 2015-12-11 15:10:48 -05:00
5b801afa38 Don't mark hosts failed if they've moved to a rescue portion of a block
Fixes #13521
2015-12-11 14:58:38 -05:00
71cc791677 narrow down exception catching in block builds
this was obscuring other errors and should have always been narrow scope
2015-12-11 13:13:19 -05:00
3d1b3e2bb8 removed 'bare' example in environment
now shows how to use explicit templating
2015-12-11 09:35:19 -05:00
b0e5556d9a fix make complaint when git is not installed 2015-12-10 21:50:11 -05:00
75e6fb30d5 Fixing up docker integration tests a bit 2015-12-10 13:10:40 -05:00
9b5ec8f359 Update submodule ref 2015-12-10 08:10:13 -08:00
2dbcd8fc9e become_pass needs to be bytes when it is passed to ssh.
Fixes #13240
2015-12-10 07:30:20 -08:00
82789df231 allow custom callbacks with adhoc cli for scripting
missing import of CallbackBase
2015-12-10 07:05:41 -08:00
3fafc6d655 Missed one place we were appending the incorrectly escaped item to raw params 2015-12-09 17:59:06 -05:00
9b864811f8 Note that handlers inside of includes are not possible at the moment 2015-12-09 13:53:04 -08:00
ba62a8d559 Windows doc updates 2015-12-09 16:36:23 -05:00
b793fbc60a Remove the funcd connection plugin 2015-12-09 13:30:37 -08:00
7e6d546632 added winrm CP notes to changelog 2015-12-09 15:50:37 -05:00
45d2f59858 changed deprecation to removal warning 2015-12-09 12:39:11 -08:00
dd6e10ce43 Update submodule refs 2015-12-09 12:11:30 -08:00
6694e97a31 Make on_file_diff callback item-aware 2015-12-09 14:52:06 -05:00
699bb847a0 reenabled --tree for ansible adhoc command
previous fix to avoid callbacks now conflicted with tree optoin
which is implemented as a callback in 2.0
2015-12-09 10:14:43 -08:00
c02ca22894 adhoc avoids callbacks by default as it did before
Previous emptying of whitelist only affected callbacks that were
constructed for need whitelist. This now works for all callbacks.
2015-12-09 10:03:39 -08:00
1f9d66ef60 Clarify language of delegate_facts documentation 2015-12-09 08:46:49 -08:00
8f6f2fc920 Code smell test for specifying both required and default in FieldAttributes 2015-12-09 08:46:49 -08:00
4d7710806e attribute defaults that are containers are a copy
This is simpler way to prevent persistent containers across instances
of classes that use field attributes
2015-12-09 08:42:14 -08:00
c2665da3e8 removed unused 'pattern' from ansible.cfg
also moved the config param to a 'deprecated' list in constants.py
added TODO for producing a deprecation warning for such vars
2015-12-09 08:42:14 -08:00
186259eb80 removed default from hosts to make it requried
prevents writing a play w/o a hosts entry which would default to
all/empty
2015-12-09 08:42:14 -08:00
e571bf94d4 Revert "avoid persistent containers in attribute defaults"
This reverts commit 87969868d4.
found better way to do it
2015-12-09 08:42:14 -08:00
565b5097da clarified warning from tree callback 2015-12-09 08:40:56 -08:00
0a6f8b2bf3 Galaxy 2.0 2015-12-09 11:30:05 -05:00
f649dc71e7 avoid persistent containers in attribute defaults
moved from the field attribute declaration and created a placeholder
which then is resolved in the field attribute class.

this is to avoid unwanted persistent of the defaults across objects which introduces
stealth bugs when multiple objects of the same kind are used in succession while
not overriding the default values.
2015-12-09 11:11:49 -05:00
d93e1f4ccf added delegate_facts docs 2015-12-08 14:18:11 -08:00
9eb9f55a31 keep string type filters as strings
now we don't try to convert types if using a filter that outputs a specifically formated string
made list of filters configurable
2015-12-08 12:52:44 -08:00
dbcfce03d2 Add ssh_host support for MacOSX El Capitan.
OS X El Capitan moved the /etc/ssh_* files into /etc/ssh/. This fix
adds a distribution version check for Darwin to set the keydir
appropriately on El Capitan and later.
2015-12-08 15:36:49 -05:00
b3cfb630dc Make "make webdocs" compatible with Python 3
The `webdocs` make target fails under Python 3. It fails due to a variety of
syntax errors, such as the use of `except Foo, e` and `print 'foo'`. Fix #13463
by making code compatible with both Python 2 and 3.
2015-12-08 15:31:35 -05:00
058e02137a Preserve original token when appending to _raw_params in parse_kv
Fixes #13311
2015-12-08 15:06:01 -05:00
666cb07614 fixed typo in tree callback, added default dir
this would allow it to work with playbooks also
2015-12-08 11:59:51 -08:00
df04955572 updated with delegate_facts directive 2015-12-08 11:53:36 -08:00
422092b8bc Fix typo from 5ae850c 2015-12-08 14:34:37 -05:00
5ae850c3b2 Make fact delegating configurable, defaulting to 1.x behavior 2015-12-08 14:00:17 -05:00
7c8e1b41bb Revert "Fix always_run support in the action plugin for template when copying"
This reverts commit 45670eff81.
2015-12-08 09:26:24 -08:00
43bfd16666 have always_run override check mode for a task
Fixes #13418
2015-12-08 09:26:13 -08:00
45670eff81 Fix always_run support in the action plugin for template when copying
Fixes #13418
2015-12-08 11:55:35 -05:00
50e5b0f8e9 Merge pull request #13467 from bcoca/adhoc_callbk_fix
adhoc does not load plugins by default
2015-12-08 11:28:20 -05:00
e69064d0fc Merge pull request #13451 from bcoca/doas_fix
fixed doas from getting stuck when needing passwords
2015-12-08 11:13:01 -05:00
1aa775196b adds new device argument to nxapi command arguments
The device argument allows a dict of nxapi parameters to be passed to
the module to simplify passing the nxapi parameters
2015-12-08 10:36:47 -05:00
b07451eef8 adhoc does not load plugins by default
reimplemented feature from 1.x which kept additional callbacks from
poluting adhoc unless specifically asked for through configuration.
2015-12-08 06:37:15 -08:00
cc98528ecb Version bump for 2.0.0-0.7.rc2 2015-12-07 13:13:37 -05:00
f241c70740 corrected usage of ec2.py's profile option
this was never introduced into ansible-playbook though the docs
stated otherwise. We still explain how to use the env var to get the
same result.
2015-12-07 09:56:05 -08:00
2ed2c12f60 Fix issue when var name is the same as content.
See https://github.com/ansible/ansible/issues/13453 for more details.
2015-12-07 10:08:13 -05:00
d85b8adba6 More meaningful string representation for meta tasks (like 'noop' and 'flush_handlers') 2015-12-07 10:08:13 -05:00
8e16b481d0 added extract filter to changelog 2015-12-07 10:08:13 -05:00
d89dbf19fb bugfix for ios.py shared module argument creation
This patch fixes a bug in module_utils/ios.py where the the wrong shared
module arguments are being generated.  This bug prevented the shared module
from operating correctly.  This patch should be generally applied.
2015-12-07 06:59:43 -08:00
40c01f3739 Use self.args when we parse arguments that way the arguments can be constructed manually 2015-12-06 22:19:11 -08:00
71ffa5abdc Add representers so we can output yaml for all the types we read in from yaml 2015-12-06 22:19:02 -08:00
0533e0bc96 fixed doas from getting stuck when needing passwords
Also adjusted test to match new doas become output
fixes #13449
2015-12-06 00:35:28 -05:00
3974b13a5a Make no_target_syslog consistent.
no_target_syslog = False --> do log on target
2015-12-05 16:14:36 -05:00
d04d5bf0d5 only set become defaults at last possible moment
tasks were overriding commandline with their defaults, not with the
explicit setting, removed the setting of defaults from task init and
pushed down to play context at last possible moment.
fixes #13362
2015-12-05 15:59:51 -05:00
8a733d990f simplified get_hosts code to have 1 retrun point 2015-12-05 10:13:09 -05:00
895fc48700 Remove duplicates from host list *before* caching it
Ansible previously added hosts to the host list multiple times for commands
like `ansible -i 'localhost,' -c local -m ping 'localhost,localhost'
--list-hosts`.
8d5f36a fixed the obvious error, but still added the un-deduplicated list to a
cache, so all future invocations of get_hosts() would retrieve a
non-deduplicated list.
This caused problems down the line: For some reason, Ansible only ever
schedules "flush_handlers" tasks (instead of scheduling any actual tasks from
the playbook) for hosts that are contained in the host lists multiple times.
This probably happens because the host states are stored in a dictionary
indexed by the hostnames, so duplicate hostname would cause the state to be
overwritten by subsequent invocations of … something.
2015-12-05 10:13:09 -05:00
2068ff8926 updated pull location in changelog
it was in between of backslash description and example
2015-12-05 01:48:41 -05:00
da6670cca4 Add fullstop to make sentence make sense. Touch parargraph while at it. 2015-12-04 21:35:39 -05:00
d0337a8928 comment examples in default hosts file 2015-12-04 16:02:26 -08:00
4c21d58f4c Transform exceptions into ansible messages via to_unicode instead of str to avoid tracebacks.
Fixes #13385
2015-12-04 11:52:07 -08:00
86ca0bf3b1 Correct connection type returned by libvirt_lxc inventory script
The correct connection type for LXC containers managed via libvirt is
libvirt_lxc, not lxc.
2015-12-04 11:00:37 -08:00
627576a955 Adding a uuid field so we can track host equality across serialization too 2015-12-04 13:34:10 -05:00
3aa4db5083 Update submodule refs 2015-12-04 09:59:30 -08:00
cd76552724 Changing up how host (in)equality is checked
Fixes #13397
2015-12-04 12:58:16 -05:00
f630e140d2 fixed ansible-pull broken options
* sudo was not working, now it supports full become
* now default checkout dir works, not only when specifying
* paths for checkout dir get expanded
* fixed limit options for playbook
* added verbose and debug info
2015-12-03 20:51:51 -08:00
c03b8ef0c2 return unique list of hosts 2015-12-03 19:44:31 -08:00
46718ac3f4 reverted to previous pull checkout dir behaviour
This fixes bugs with not finding plays when not specifying checkout dir
Also makes it backwards compatible
2015-12-03 19:44:31 -08:00
3e5c7c540b corrected playbook path, reformated options help
the last just to make the help consistent and readable
2015-12-03 18:24:10 -08:00
7950f09d19 Now and/or shell expressions depend on shell plugin
This should fix issues with fish shell users as && and || are
not valid syntax, fish uses actual 'and' and 'or' programs.
Also updated to allow for fish backticks pushed quotes to subshell,
fish seems to handle spaces w/o them.
Lastly, removed encompassing subshell () for fish compatibility.
fixes #13199
2015-12-03 16:43:02 -08:00
f8911adbbc For now, skip tests of module_utils/basic functions that are failing on
py3 (these are only run on the target hosts, not on the controller).
2015-12-03 14:26:25 -08:00
6aa1b6d9b1 Properly compare object references for Hosts when adding new ones
Fixes #13397
2015-12-03 15:27:10 -05:00
013ace9ab2 fix sorting of groups for host vars
Fixes #13371
2015-12-03 14:23:14 -05:00
0d0ed35ba4 Properly default remote_user for delegated-to hosts
Fixes #13323
2015-12-03 11:33:11 -05:00
b9fbfaf64e Also some unicode tests for return_values() 2015-12-02 21:12:33 -08:00
2c5c7b54f6 Add some test data that has unicode values 2015-12-02 21:12:26 -08:00
c1aeda59bd Don't compare or merge str with unicode
Fixes #13387
2015-12-02 21:12:18 -08:00
0f813fd76a updated docs for 2.0 api 2015-12-02 12:11:58 -08:00
38c11e2239 Default msg param to AnsibleError to avoid serialization problems 2015-12-02 14:18:13 -05:00
ed4a06d8ef Don't use play vars in HostVars
Fixes #13398
2015-12-02 14:18:13 -05:00
65f4cbf487 Fix template test results on python2.6 2015-12-02 10:34:14 -08:00
48a3922d56 Add example for regex_replace using named groups 2015-12-02 09:44:26 -08:00
ca838d75e3 Get v2_playbook_on_start working
* Move self._tqm.load_callbacks() earlier to ensure that v2_on_playbook_start can fire
* Pass the playbook instance to v2_on_playbook_start
* Add a _file_name instance attribute to the playbook
2015-12-02 12:41:18 -05:00
f339184e29 Use CLI.expand_tilde also for the vault --output file 2015-12-02 09:24:36 -08:00
91f71b0ace added remote environment var setting to changelog 2015-12-02 09:09:35 -08:00
f2f310472f Make module_lang default to whatever LANG is set to on the control node 2015-12-02 09:07:26 -08:00
de7dc5d07f Catch additional assertion errors for load_list_of_blocks 2015-12-02 09:04:59 -08:00
ae5cfb2898 better error on invalid task lists 2015-12-02 08:14:37 -08:00
381409140e Minor tweak and comment addition to 974a0ce3 2015-12-02 09:10:20 -05:00
be92f909ee Update debug messages and comments
The comment was taken literally from lib/plugins/strategy/linear.py and
makes no sense in free.py where we have no noop tasks.

Also update the debug messages.
2015-12-02 09:00:27 -05:00
974a0ce3fb Fix issue #13370
all_blocks is referenced after the loop over included_files, so it needs
to be initialized before this loop, not inside.
2015-12-02 09:00:26 -05:00
1f1febaa0d Let PlayIterator.add_tasks accept empty task lists
PlayIterator.add_tasks raised an error when trying to add an empty task
list.  This was the root cause of ansible issue #13370.
2015-12-02 09:00:26 -05:00
3c25ae2e10 updated new module list
added missing modules and fixed alphabetical ordering
2015-12-01 23:53:43 -08:00
d9218ce33f reformated test, changed big assert to with_items
much easier to see the individual condition that causes the failure
when using with_items and evaluating each part of the assert individually
2015-12-01 21:26:36 -08:00
346a9fe87d unconditionally set vars on init to avoid issues with var precedence 2015-12-01 21:25:43 -08:00
5b5c6c4f47 fixes a syntax issue with module_utils/eapi.py
This patch fixes an issue with the common args dict in the eapi shared
module.  This patch is required for the eapi shared module to be properly
imported and is therefore should be applied to all instances.
2015-12-01 20:46:11 -08:00
02d059271c initial add of ssh shared module.
This ssh shared module is used for building modules that require an
interactive shell environment such as those required for connecting
to network devices
2015-12-01 19:15:41 -08:00
a6771b2255 adds module create function for eapi.py shared module
This commit changes the way modules create an instance of AnsibleModule to
now use a common function, eapi_module.  This function will now automatically
append the common argument spec to the module argument_spec.  Module
arguments can override common module arguments
2015-12-01 19:14:38 -08:00
a9e8b54246 initial add of the ios shared module
This adds shared module support for building modules that connect to Cisco
IOS devices.  It builds on the module_utils/ssh.py shared module.
2015-12-01 19:05:14 -08:00
d2108e9ff3 fixed signature for init on callbacks
also removed passing display to base class which already handles this
2015-12-01 14:07:47 -08:00
59dadc4f6b allow shell plugin to affect remote module filename
Fix for 13368, added get_remote_filename to shell plugins, powershell version appends .ps1 if necessary, base shell plugin no-ops
2015-12-01 14:02:01 -08:00
927d28e5d5 added pull's code sig verification to changelog 2015-12-01 09:55:06 -08:00
a61718cfc5 Revert "Note that su now works with local connection"
This reverts commit 93ef35e6a9.

bcoca already added this
2015-12-01 09:49:08 -08:00
93ef35e6a9 Note that su now works with local connection 2015-12-01 09:14:10 -08:00
b0e22d7701 _connect no longer takes a port argument 2015-12-01 09:12:55 -08:00
1b7db6316e updated changelog to show su now works with local 2015-12-01 09:11:30 -08:00
ca8c6e8e1c ignore password flags in become conflict check
since all the --ask pass options end up triggering the same code
and are functionally equivalent, ignore them when it comes to checking
privilege escalation conflicts. This allows using -K when --become-method=su
and so on.
2015-12-01 08:57:33 -08:00
204e27ca66 avoid inheritance issues with default=dict declaration at class level
this should avoid the issue of subsequent plays not prompting for a var
prompted for in a previous play.
fixes #13363
2015-11-30 15:12:53 -08:00
f96730003b Also make sure remote_user is defaulted correctly for delegated hosts
Fixes #13323
2015-11-30 16:16:11 -05:00
4f3f79d37b Call the function :-)
Fixes #13330
2015-11-30 12:34:55 -08:00
89f0207007 Ensure port is (re)set for delegated-to hosts
Fixes #13265
2015-11-30 14:41:05 -05:00
f8ed1c003a fixed typo 2015-11-30 09:21:26 -08:00
c5cd908c33 allow for bad stdout return from make temp dir command
fixes #13359
2015-11-30 09:20:24 -08:00
958da26d18 corrected become_methods class variable in winrm
This should now correctly react when using become with winrm
fixes #13331
2015-11-30 08:35:33 -08:00
a5d6be6dd2 Make sure run_once tasks properly set variables for all active hosts
Fixes #13267
2015-11-30 11:28:28 -05:00
7af506e7cf Use text_type instead of unicode 2015-11-30 11:28:25 -05:00
3a0f2475b2 Make sure the uuid in vars is string 2015-11-30 10:27:21 -05:00
2db3f12027 Re-implement lookup wantlist
Fixes #13285
2015-11-29 23:45:14 -05:00
bb52b45ea0 Do not copy variable_manager each time. Instead, keep host and local variable_manager sync.
Fix https://github.com/ansible/ansible/issues/13221
2015-11-29 23:15:01 -05:00
4114a3097f Tweak location of stats callback execution and properly relocate stats output code 2015-11-28 14:02:50 -05:00
73a269f9a5 Put in trap for args being None
_normalize_old_style_args can return None. If it does, the loop
"for args in args" blows up.
2015-11-28 13:44:44 -05:00
737e467b8a Trigger on_stats just once, not once for each play
Fixes #13271
2015-11-28 13:37:02 -05:00
cac0eea291 Explicitly accept become_success in awaiting_prompt state
If we request escalation with a password, we start in expecting_prompt
state. If the escalation then succeeds without the password, i.e., the
become_success response arrives, we must explicitly move into the next
state (awaiting_escalation, which immediately goes into ready_to_send),
so that we no longer try to apply the timeout.

Otherwise, we would leak the success notification and eventually
timeout. But if the module response did arrive before the timeout
expired, the "process has already exited" test would do the right
thing by accident (which is why it didn't fail more often).

Fixes #13289
2015-11-28 10:22:35 -05:00
54843d88ee Re-adding role_name/role_uuid variables 2015-11-28 10:00:42 -05:00
47651e6c22 More restrictive test against variable name to allow setting variable starting with _. 2015-11-28 10:00:38 -05:00
9e6ec4c6b0 Switch parameters validation after parsing in order to be more consistent between old and new style. 2015-11-28 10:00:34 -05:00
6457f88aab Fix missing word in developing_modules.rst 2015-11-28 10:00:25 -05:00
e210da3659 Fix typo in modules_core.rst 2015-11-28 10:00:22 -05:00
e0ecaac90d changelog: minor formating fix 2015-11-28 10:00:18 -05:00
dbedcd3538 avoids prompting for vars during syntax check
fixes #13319
2015-11-27 11:46:32 -08:00
4e6442fd19 removes editorial
I feel that Ansible is above the "my hosted Git community is better than yours" discussion and thus removed the editorial around Bitbucket
2015-11-27 11:15:57 -08:00
126249d69a Add assertions for ansible_date_time in setup result. 2015-11-27 00:49:02 -05:00
056372690f Do not double transform to unicode 2015-11-25 07:56:06 -08:00
9cee982a62 fixing errors with utf-8 values
removing utf-8 stanza

changing cast to binary_type instead

using to_unicode
2015-11-25 07:55:52 -08:00
b69942a6d2 added missing : 2015-11-25 10:57:55 -08:00
d9858ee73a added missing events to base class 2015-11-25 10:57:55 -08:00
64bcab9253 fixes to fetch action module
* now only runs remote checksum when needed (fixes #12290)
 * unified return points to simplify program flow
2015-11-25 10:57:04 -08:00
fc4326dc0c Fix ssh state issues by simply assuming it's never connected 2015-11-24 12:01:42 -05:00
92ea5c9f7b Properly check for prompting state when re-using ssh connection
Fixes #13278
2015-11-24 09:10:51 -05:00
90021104d5 Use to_unicode instead of str() 2015-11-23 16:49:00 -05:00
8bd5abaf1e Allow debug var parameter to accept a list or dict. Fix https://github.com/ansible/ansible/issues/13252 2015-11-23 16:49:00 -05:00
1ab60564ae Add integration tests for zypper
Modeled after the yum tests but also tests local package installations
as fixed with PR#1256.

This depends on PRs #1256, #1261 and #1262 in ansible-modules-extra.
2015-11-23 15:22:29 -05:00
af2e94e3c7 test_hg fix: remove reference to "head"
ERROR! error while evaluating conditional: head.stat.isreg

This is remnant from earlier change 50e5d81777
which removed stat on head file..
2015-11-23 14:34:21 -05:00
5378a6003a test_svn fix: remove hardcoded "~/ansible_testing/svn" path 2015-11-23 14:33:48 -05:00
2859933a79 We should give pipes.quote() a string every time 2015-11-23 14:27:56 -05:00
42bffeec7c Template (and include vars) PlaybookInclude paths
Fixes #13249
2015-11-23 14:04:14 -05:00
9a8e95bff3 Modify task executor to reuse connection inside a loop. Fix WinRM connection to set _connected properly and display when remote shell is opened/closed. Add integration test using raw + with_items. 2015-11-23 14:04:00 -05:00
54ec2a0b84 docsite: cloudstack: fix missing quotes in example 2015-11-23 14:03:55 -05:00
1e9e6339d1 marked spot that should send per item reulsts 2015-11-23 14:03:51 -05:00
5bc3efe34b Update submodule refs 2015-11-23 09:02:12 -08:00
7d19ad82eb Recommend using pywinrm >= 0.1.1 from PyPI instead of GitHub version. 2015-11-20 15:40:34 -08:00
c1bb3aea06 Documentation: Update the Vagrant Guide
This is an attempt to solve #7665.

Revert the change applied by f56a6e0951
(#12310), as the inventory generated by Vagrant still rely on the legacy
`_ssh` setting names for backwards compatibility reasons.
See also https://github.com/mitchellh/vagrant/issues/6570
2015-11-21 14:03:24 -08:00
011df4ad24 Update docker_login so docs work 2015-11-20 13:59:02 -08:00
c71ef9e3d7 Fix non-module plugins picking up files that did not end in .py.
This was caused by accessing the cache using the passed in mod_type
rather than the suffix that we calculate with knowledge of whether this
is a module or non-module plugin.
2015-11-20 13:51:29 -08:00
e9ed190f7b Update submodule refs 2015-11-20 12:45:27 -08:00
fe090b0fb9 Add docker_login module to the changelog 2015-11-20 12:44:48 -08:00
50a924bb04 Docker cp sets file ownership to root:root so we can't use it.
Fixes #13219
2015-11-20 07:54:07 -08:00
1e968d34cb Simplify code a little 2015-11-19 09:56:58 -08:00
c99fffa936 Use ansible_host in synchronize module
Fixes #13073
2015-11-19 09:56:49 -08:00
f2225395f9 winrm error handling tweaks 2015-11-19 09:58:33 -05:00
c33f60435b fast winrm put_file without size restrictions 2015-11-19 09:58:28 -05:00
ab8bb57f5e Version bump for 2.0.0-0.6.rc1 2015-11-19 09:15:45 -05:00
492 changed files with 5726 additions and 32913 deletions

View File

@ -1,50 +0,0 @@
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
- Bug Report
- Feature Idea
- Documentation Report
##### ANSIBLE VERSION
```
<!--- Paste verbatim output from “ansible --version” between quotes -->
```
##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
##### SUMMARY
<!--- Explain the problem briefly -->
##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->
```
<!--- Paste example playbooks or commands between quotes -->
```
<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with high verbosity (-vvvv) -->
```
<!--- Paste verbatim command output between quotes -->
```

View File

@ -1,24 +0,0 @@
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
- Feature Pull Request
- New Module Pull Request
- Bugfix Pull Request
- Docs Pull Request
##### ANSIBLE VERSION
```
<!--- Paste verbatim output from “ansible --version” between quotes -->
```
##### SUMMARY
<!--- Describe the change, including rationale and design decisions -->
<!---
If you are fixing an existing issue, please include "Fixes #nnn" in your
commit message and your description; but you should still explain what
the change does.
-->
```
<!-- Paste verbatim command output here, e.g. before and after your change -->
```

4
.gitignore vendored
View File

@ -31,7 +31,6 @@ docs/man/man3/*
*.sublime-workspace
# docsite stuff...
docsite/rst/modules_by_category.rst
docsite/rst/playbooks_directives.rst
docsite/rst/list_of_*.rst
docsite/rst/*_module.rst
docsite/*.html
@ -48,8 +47,6 @@ deb-build
*.swo
credentials.yml
# test output
*.retry
*.out
.coverage
.tox
results.xml
@ -61,4 +58,3 @@ venv
Vagrantfile
.vagrant
ansible.egg-info/
/shippable/

View File

@ -1,35 +0,0 @@
Michael DeHaan <michael.dehaan@gmail.com> <michael@ansibleworks.com>
Michael DeHaan <michael.dehaan@gmail.com> Michael DeHaan <Michael DeHaan michael@ansibleworks.com>
Michael DeHaan <michael.dehaan@gmail.com> <michael@ansible.com>
<bcoca@ansible.com> <brian.coca+git@gmail.com>
<bcoca@ansible.com> <briancoca+ansible@gmail.com>
<bcoca@ansible.com> <briancoca+dev@gmail.com>
<bcoca@ansible.com> <bcoca@tablethotels.com>
<a.badger@gmail.com> <toshio@fedoraproject.org>
James Tanner <tanner.jc@gmail.com>
<jimi@sngx.net> <jcammarata@ansibleworks.com>
Michael Scherer <misc@zarb.org> mscherer <misc@zarb.org>
<misc@zarb.org> <misc@ephaone.org>
<misc@zarb.org> <mscherer@users.noreply.github.com>
James Martin <jmartin@ansible.com> <jmartin@basho.com>
James Laska <jlaska@ansible.com> <jlaska@redhat.com>
James Laska <jlaska@ansible.com> <jlaska@ansibleworks.com>
James Laska <jlaska@ansible.com> <jlaska@James-Laskas-MacBook-Pro.local>
James Laska <jlaska@ansible.com> <jlaska@users.noreply.github.com>
Jason McKerr <mckerrj@gmail.com> <jmckerr@jmckerr-OSX.local>
Chris Houseknecht <chouseknecht@ansible.com>
Chris Houseknecht <chouseknecht@ansible.com> chouseknecht <chouse@ansible.com>
Chris Houseknecht <chouseknecht@ansible.com> Chris Houseknecht <chouse@ansibleworks.com>
Stephen Fromm <sfromm@gmail.com> Stephen Fromm <stephenf@nero.net>
Sandra Wills <docschick@ansible.com> Sandra Wills <swills@ansible.com>
Will Thames <will@thames.id.au> willthames <will@thames.id.au>
Will Thames <will@thames.id.au> Will Thames <willdthames@gmail.com>
Will Thames <will@thames.id.au> willthames <willdthames@gmail.com>
Will Thames <will@thames.id.au> willthames <will@musc.org.uk>
Will Thames <will@thames.id.au> u348095 <will.thames@suncorp.com.au>
Will Thames <will@thames.id.au> willthames <will.thames@suncorp.com.au>
nitzmahone <mdavis@ansible.com> Matt Davis <nitzmahone@users.noreply.github.com>
Dag Wieers <dag@wieers.com> Dag Wieërs <dag@wieers.com>
Dag Wieers <dag@wieers.com> Dag Wieers <dag.wieers@gmail.com>

33
.travis.yml Normal file
View File

@ -0,0 +1,33 @@
sudo: false
language: python
matrix:
include:
- env: TOXENV=py24 INTEGRATION=no
- env: TOXENV=py26 INTEGRATION=yes
python: 2.6
- env: TOXENV=py27 INTEGRATION=yes
python: 2.7
- env: TOXENV=py34 INTEGRATION=no
python: 3.4
- env: TOXENV=py35 INTEGRATION=no
python: 3.5
addons:
apt:
sources:
- deadsnakes
packages:
- python2.4
install:
- pip install tox PyYAML Jinja2 sphinx
script:
# urllib2's defaults are not secure enough for us
- ./test/code-smell/replace-urlopen.sh .
- ./test/code-smell/use-compat-six.sh lib
- ./test/code-smell/boilerplate.sh
- ./test/code-smell/required-and-default-attributes.sh
- if test x"$TOXENV" != x'py24' ; then tox ; fi
- if test x"$TOXENV" = x'py24' ; then python2.4 -V && python2.4 -m compileall -fq -x 'module_utils/(a10|rax|openstack|ec2|gce).py' lib/ansible/module_utils ; fi
#- make -C docsite all
- if test x"$INTEGRATION" = x'yes' ; then source ./hacking/env-setup && cd test/integration/ && make parsing && make test_var_precedence && make unicode ; fi
after_success:
- coveralls

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +1,27 @@
# WELCOME TO ANSIBLE GITHUB
Welcome To Ansible GitHub
=========================
Hi! Nice to see you here!
If you'd like to ask a question
===============================
## QUESTIONS ?
Please see [this web page ](http://docs.ansible.com/community.html) for community information, which includes pointers on how to ask questions on the [mailing lists](http://docs.ansible.com/community.html#mailing-list-information) and IRC.
Please see the [community page](http://docs.ansible.com/community.html) for information on how to ask questions on the [mailing lists](http://docs.ansible.com/community.html#mailing-list-information) and IRC.
The github issue tracker is not the best place for questions for various reasons, but both IRC and the mailing list are very helpful places for those things, and that page has the pointers to those.
The GitHub issue tracker is not the best place for questions for various reasons, but both IRC and the mailing list are very helpful places for those things, as the community page explains best.
If you'd like to contribute code
================================
Please see [this web page](http://docs.ansible.com/community.html) for information about the contribution process. Important license agreement information is also included on that page.
## CONTRIBUTING ?
If you'd like to file a bug
===========================
Please see the [community page](http://docs.ansible.com/community.html) for information regarding the contribution process. Important license agreement information is also included on that page.
I'd also read the community page above, but in particular, make sure you copy [this issue template](https://github.com/ansible/ansible/blob/devel/ISSUE_TEMPLATE.md) into your ticket description. We have a friendly neighborhood bot that will remind you if you forget :) This template helps us organize tickets faster and prevents asking some repeated questions, so it's very helpful to us and we appreciate your help with it.
## BUG TO REPORT ?
First and foremost, also check the [community page](http://docs.ansible.com/community.html).
You can report bugs or make enhancement requests at the [Ansible GitHub issue page](http://github.com/ansible/ansible/issues/new) by filling out the issue template that will be presented.
Also please make sure you are testing on the latest released version of Ansible or the development branch. You can find the latest releases and development branch at:
- https://github.com/ansible/ansible/releases
- https://github.com/ansible/ansible/archive/devel.tar.gz
Also please make sure you are testing on the latest released version of Ansible or the development branch.
Thanks!

39
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,39 @@
##### Issue Type:
Can you help us out in labelling this by telling us what kind of ticket this this? You can say:
- Bug Report
- Feature Idea
- Feature Pull Request
- New Module Pull Request
- Bugfix Pull Request
- Documentation Report
- Docs Pull Request
##### Ansible Version:
Let us know what version of Ansible you are using. Please supply the verbatim output from running “ansible --version”. If you're filing a ticket on a version of Ansible which is not the latest, we'd greatly appreciate it if you could retest on the latest version first. We don't expect you to test against the development branch most of the time, but we may ask for that if you have cycles. Thanks!
##### Ansible Configuration:
What have you changed about your Ansible installation? What configuration settings have you changed/added/removed? Compare your /etc/ansible/ansible.cfg against a clean version from Github and let us know what's different.
##### Environment:
What OS are you running Ansible from and what OS are you managing? Examples include RHEL 5/6, Centos 5/6, Ubuntu 12.04/13.10, *BSD, Solaris. If this is a generic feature request or it doesn’t apply, just say “N/A”. Not all tickets may be about operating system related things and we understand that.
##### Summary:
Please summarize your request in this space. You will earn bonus points for being succinct, but please add enough detail so we can understand the request. Thanks!
##### Steps To Reproduce:
If this is a bug ticket, please enter the steps you use to reproduce the problem in the space below. If this is a feature request, please enter the steps you would use to use the feature. If an example playbook is useful, please include a short reproducer inline, indented by four spaces. If a longer one is necessary, linking to one uploaded to gist.github.com would be great. Much appreciated!
##### Expected Results:
Please enter your expected results in this space. When running the steps supplied above in the previous section, what did you expect to happen? If showing example output, please indent your output by four spaces so it will render correctly in GitHub's viewer thingy.
##### Actual Results:
Please enter your actual results in this space. When running the steps supplied above, what actually happened? If you are showing example output, please indent your output by four spaces so it will render correctly in GitHub. Thanks again!

View File

@ -67,7 +67,7 @@ ifeq ($(OFFICIAL),yes)
DEBUILD_OPTS += -k$(DEBSIGN_KEYID)
endif
else
DEB_RELEASE = 100.git$(DATE)$(GITINFO)
DEB_RELEASE = 0.git$(DATE)$(GITINFO)
# Do not sign unofficial builds
DEBUILD_OPTS += -uc -us
DPUT_OPTS += -u
@ -83,7 +83,7 @@ RPMSPEC = $(RPMSPECDIR)/ansible.spec
RPMDIST = $(shell rpm --eval '%{?dist}')
RPMRELEASE = $(RELEASE)
ifneq ($(OFFICIAL),yes)
RPMRELEASE = 100.git$(DATE)$(GITINFO)
RPMRELEASE = 0.git$(DATE)$(GITINFO)
endif
RPMNVR = "$(NAME)-$(VERSION)-$(RPMRELEASE)$(RPMDIST)"

View File

@ -1,6 +1,7 @@
[![PyPI version](https://img.shields.io/pypi/v/ansible.svg)](https://pypi.python.org/pypi/ansible)
[![PyPI downloads](https://img.shields.io/pypi/dm/ansible.svg)](https://pypi.python.org/pypi/ansible)
[![Build Status](https://api.shippable.com/projects/573f79d02a8192902e20e34b/badge?branch=stable-2.1)](https://app.shippable.com/projects/573f79d02a8192902e20e34b)
[![Build Status](https://travis-ci.org/ansible/ansible.svg?branch=devel)](https://travis-ci.org/ansible/ansible)
Ansible
=======

View File

@ -1,83 +1,70 @@
Ansible Releases at a Glance
============================
VERSION RELEASE CODE NAME
++++++++++++++++++++++++++++++
Active Development
++++++++++++++++++
2.1 "TBD" - in progress
Released
++++++++
2.0.1 "Over the Hills and Far Away" TBD
2.0.0 "Over the Hills and Far Away" 01-12-2015
1.9.4 "Dancing In the Streets" 10-09-2015
1.9.3 "Dancing In the Streets" 09-03-2015
1.9.2 "Dancing In the Streets" 06-24-2015
1.9.1 "Dancing In the Streets" 04-27-2015
1.9.0 "Dancing In the Streets" 03-25-2015
1.8.4 "You Really Got Me" ---- 02-19-2015
1.8.3 "You Really Got Me" ---- 02-17-2015
1.8.2 "You Really Got Me" ---- 12-04-2014
1.8.1 "You Really Got Me" ---- 11-26-2014
1.7.2 "Summer Nights" -------- 09-24-2014
1.7.1 "Summer Nights" -------- 08-14-2014
1.7 "Summer Nights" -------- 08-06-2014
1.6.10 "The Cradle Will Rock" - 07-25-2014
1.6.9 "The Cradle Will Rock" - 07-24-2014
1.6.8 "The Cradle Will Rock" - 07-22-2014
1.6.7 "The Cradle Will Rock" - 07-21-2014
1.6.6 "The Cradle Will Rock" - 07-01-2014
1.6.5 "The Cradle Will Rock" - 06-25-2014
1.6.4 "The Cradle Will Rock" - 06-25-2014
1.6.3 "The Cradle Will Rock" - 06-09-2014
1.6.2 "The Cradle Will Rock" - 05-23-2014
1.6.1 "The Cradle Will Rock" - 05-07-2014
1.6 "The Cradle Will Rock" - 05-05-2014
1.5.5 "Love Walks In" -------- 04-18-2014
1.5.4 "Love Walks In" -------- 04-01-2014
1.5.3 "Love Walks In" -------- 03-13-2014
1.5.2 "Love Walks In" -------- 03-11-2014
1.5.1 "Love Walks In" -------- 03-10-2014
1.5 "Love Walks In" -------- 02-28-2014
1.4.5 "Could This Be Magic?" - 02-12-2014
1.4.4 "Could This Be Magic?" - 01-06-2014
1.4.3 "Could This Be Magic?" - 12-20-2013
1.4.2 "Could This Be Magic?" - 12-18-2013
1.4.1 "Could This Be Magic?" - 11-27-2013
1.4 "Could This Be Magic?" - 11-21-2013
1.3.4 "Top of the World" ----- 10-29-2013
1.3.3 "Top of the World" ----- 10-09-2013
1.3.2 "Top of the World" ----- 09-19-2013
1.3.1 "Top of the World" ----- 09-16-2013
1.3 "Top of the World" ----- 09-13-2013
1.2.3 "Hear About It Later" -- 08-21-2013
1.2.2 "Hear About It Later" -- 07-05-2013
1.2.1 "Hear About It Later" -- 07-04-2013
1.2 "Right Now" ------------ 06-10-2013
1.1 "Mean Street" ---------- 04-02-2013
1.0 "Eruption" ------------- 02-01-2013
0.9 "Dreams" --------------- 11-30-2012
0.8 "Cathedral" ------------ 10-19-2012
0.7 "Panama" --------------- 09-06-2012
0.6 "Cabo" ----------------- 08-06-2012
0.5 "Amsterdam" ------------ 07-04-2012
0.4 "Unchained" ------------ 05-23-2012
0.3 "Baluchitherium" ------- 04-23-2012
0.0.2 Untitled
0.0.1 Untitled
2.4.0 TBD "Dancing Days"
2.3.1 06-01-2017 "Ramble On"
2.3.0 04-12-2017 "Ramble On"
2.2.3 05-09-2017 "The Battle of Evermore"
2.2.2 03-27-2017 "The Battle of Evermore"
2.2.1 01-16-2017 "The Battle of Evermore"
2.2.0 11-01-2016 "The Battle of Evermore"
2.1.6 06-01-2017 "The Song Remains the Same"
2.1.5 03-27-2017 "The Song Remains the Same"
2.1.4 01-16-2017 "The Song Remains the Same"
2.1.3 11-04-2016 "The Song Remains the Same"
2.1.2 09-29-2016 "The Song Remains the Same"
2.1.1 07-28-2016 "The Song Remains the Same"
2.1.0 05-25-2016 "The Song Remains the Same"
2.0.2 04-19-2016 "Over the Hills and Far Away"
2.0.1 02-24-2016 "Over the Hills and Far Away"
2.0.0 01-12-2016 "Over the Hills and Far Away"
1.9.6 04-15-2016 "Dancing In the Streets"
1.9.5 03-21-2016 "Dancing In the Streets"
1.9.4 10-09-2015 "Dancing In the Streets"
1.9.3 09-03-2015 "Dancing In the Streets"
1.9.2 06-24-2015 "Dancing In the Streets"
1.9.1 04-27-2015 "Dancing In the Streets"
1.9.0 03-25-2015 "Dancing In the Streets"
1.8.4 02-19-2015 "You Really Got Me"
1.8.3 02-17-2015 "You Really Got Me"
1.8.2 12-04-2014 "You Really Got Me"
1.8.1 11-26-2014 "You Really Got Me"
1.8.0 11-25-2014 "You Really Got Me"
1.7.2 09-24-2014 "Summer Nights"
1.7.1 08-14-2014 "Summer Nights"
1.7.0 08-06-2014 "Summer Nights"
1.6.10 07-25-2014 "The Cradle Will Rock"
1.6.9 07-24-2014 "The Cradle Will Rock"
1.6.8 07-22-2014 "The Cradle Will Rock"
1.6.7 07-21-2014 "The Cradle Will Rock"
1.6.6 07-01-2014 "The Cradle Will Rock"
1.6.5 06-25-2014 "The Cradle Will Rock"
1.6.4 06-25-2014 "The Cradle Will Rock"
1.6.3 06-09-2014 "The Cradle Will Rock"
1.6.2 05-23-2014 "The Cradle Will Rock"
1.6.1 05-07-2014 "The Cradle Will Rock"
1.6.0 05-05-2014 "The Cradle Will Rock"
1.5.5 04-18-2014 "Love Walks In"
1.5.4 04-01-2014 "Love Walks In"
1.5.3 03-13-2014 "Love Walks In"
1.5.2 03-11-2014 "Love Walks In"
1.5.1 03-10-2014 "Love Walks In"
1.5.0 02-28-2014 "Love Walks In"
1.4.5 02-12-2014 "Could This Be Magic?"
1.4.4 01-06-2014 "Could This Be Magic?"
1.4.3 12-20-2013 "Could This Be Magic?"
1.4.2 12-18-2013 "Could This Be Magic?"
1.4.1 11-27-2013 "Could This Be Magic?"
1.4.0 11-21-2013 "Could This Be Magic?"
1.3.4 10-29-2013 "Top of the World"
1.3.3 10-09-2013 "Top of the World"
1.3.2 09-19-2013 "Top of the World"
1.3.1 09-16-2013 "Top of the World"
1.3.0 09-13-2013 "Top of the World"
1.2.3 08-21-2013 "Right Now"
1.2.2 07-05-2013 "Right Now"
1.2.1 07-04-2013 "Right Now"
1.2.0 06-10-2013 "Right Now"
1.1.0 04-02-2013 "Mean Street"
1.0.0 02-01-2013 "Eruption"
0.9.0 11-30-2012 "Dreams"
0.8.0 10-19-2012 "Cathedral"
0.7.0 09-06-2012 "Panama"
0.6.0 08-06-2012 "Cabo"
0.5.0 07-04-2012 "Amsterdam"
0.4.0 05-23-2012 "Unchained"
0.3.0 04-23-2012 "Baluchitherium"
0.2.0 ? "Untitled"
0.1.0 ? "Untitled"
0.0.2 ? "Untitled"
0.0.1 ? "Untitled"

View File

@ -1,98 +0,0 @@
Roadmap For Ansible by Red Hat
=============
This document is now the location for published Ansible Core roadmaps.
The roadmap will be updated by version. Based on team and community feedback, an initial roadmap will be published for a major or minor version (2.0, 2.1). Subminor versions will generally not have roadmaps published.
This is the first time Ansible has published this and asked for feedback in this manner. So feedback on the roadmap and the new process is quite welcome. The team is aiming for further transparency and better inclusion of both community desires and submissions.
These roadmaps are the team's *best guess* roadmaps based on the Ansible team's experience and are also based on requests and feedback from the community. There are things that may not make it on due to time constraints, lack of community maintainers, etc. And there may be things that got missed, so each roadmap is published both as an idea of what is upcoming in Ansible, and as a medium for seeking further feedback from the community. Here are the good places for you to submit feedback:
* Ansible's google-group: ansible-devel
* Ansible Fest conferences.
* IRC freenode channel: #ansible-devel (this one may have things lost in lots of conversation, so a caution).
2.1 Roadmap, Targeted for the End of April
==========
## Windows, General
* Figuring out privilege escalation (runas w/ username/password)
* Implement kerberos encryption over http
* pywinrm conversion to requests (Some mess here on pywinrm/requests. will need docs etc.)
* NTLM support
## Modules
* Windows
* Finish cleaning up tests and support for post-beta release
* Strict mode cleanup (one module in core)
* Domain user/group management
* Finish win\_host and win\_rm in the domain/workgroup modules.
* Close 2 existing PRs (These were deemed insufficient)
* Replicate python module API in PS/C# (deprecate hodgepodge of stuff from module_utils/powershell.ps1)
* Network
* Cisco modules (ios, iosxr, nxos, iosxe)
* Arista modules (eos)
* Juniper modules (junos)
* OpenSwitch
* Cumulus
* Dell (os10) - At risk
* Netconf shared module
* Hooks for supporting Tower credentials
* VMware (This one is a little at risk due to staffing. We're investigating some community maintainers and shifting some people at Ansible around, but it is a VERY high priority).
* vsphere\_guest brought to parity with other vmware modules (vs Viasat and 'whereismyjetpack' provided modules)
* VMware modules moved to official pyvmomi bindings
* VMware inventory script updates for pyvmomi, adding tagging support
* Azure (Notes: We've made progress here now that Microsoft has swaped out the code generator on the Azure Python SDK. We have basic modules working against all of these resources at this time. Could ship it against current SDK, but may break. Or should the version be pinned?)
* Minimal Azure coverage using new ARM api
* Resource Group
* Virtual Network
* Subnet
* Public IP
* Network Interface
* Storage Account
* Security Group
* Virtual Machine
* Update of inventory script to use new API, adding tagging support
* Docker:
* Start Docker module refactor
* Update to match current docker CLI capabilities
* Docker exec support
* Upgrade other cloud modules or work with community maintainers to upgrade. (In order)
* AWS (Community maintainers)
* Openstack (Community maintainers)
* Google (Google/Community)
* Digital Ocean (Community)
* Ziploader:
* Write code to create the zipfile that gets passed across the wire to be run on the remote python
* Port most of the functionality in module\_utils to be usage in ziploader instead
* Port a few essential modules to use ziploader instead of module-replacer as proof of concept
* New modules will be able to use ziploader. Old modules will need to be ported in future releases (Some modules will not need porting but others will)
* Better testing of modules, caching of modules clientside(Have not yet arrived at an architecture for this that we like), better code sharing between ansible/ansible and modules
* ziploader is a helpful building block for: python3 porting(high priority), better code sharing between modules(medium priority)
* ziploader is a good idea before: enabling users to have custom module_utils directories
* Expand module diff support (already in progress in devel)
* Framework done. Need to add to modules, test etc.
* Coordinate with community to update their modules
* Things being kicking down the road that we said we’d do
* NOT remerging core with ansible/ansible this release cycle
* Community stuff
* Define the process/ETA for reviewing PR’s from community
* Publish better docs and how-tos for submitting code/features/fixes

View File

@ -1 +1 @@
2.1.6.0 1
2.0.1.0 0.2.network

File diff suppressed because it is too large Load Diff

View File

@ -33,15 +33,9 @@ except Exception:
pass
import os
import shutil
import sys
import traceback
# for debug
from multiprocessing import Lock
debug_lock = Lock()
import ansible.constants as C
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
from ansible.utils.display import Display
from ansible.utils.unicode import to_unicode
@ -89,28 +83,28 @@ if __name__ == '__main__':
cli = mycli(sys.argv)
cli.parse()
exit_code = cli.run()
sys.exit(cli.run())
except AnsibleOptionsError as e:
cli.parser.print_help()
display.error(to_unicode(e), wrap_text=False)
exit_code = 5
sys.exit(5)
except AnsibleParserError as e:
display.error(to_unicode(e), wrap_text=False)
exit_code = 4
sys.exit(4)
# TQM takes care of these, but leaving comment to reserve the exit codes
# except AnsibleHostUnreachable as e:
# display.error(str(e))
# exit_code = 3
# sys.exit(3)
# except AnsibleHostFailed as e:
# display.error(str(e))
# exit_code = 2
# sys.exit(2)
except AnsibleError as e:
display.error(to_unicode(e), wrap_text=False)
exit_code = 1
sys.exit(1)
except KeyboardInterrupt:
display.error("User interrupted execution")
exit_code = 99
sys.exit(99)
except Exception as e:
have_cli_options = cli is not None and cli.options is not None
display.error("Unexpected Exception: %s" % to_unicode(e), wrap_text=False)
@ -118,9 +112,4 @@ if __name__ == '__main__':
display.display(u"the full traceback was:\n\n%s" % to_unicode(traceback.format_exc()))
else:
display.display("to see the full traceback, use -vvv")
exit_code = 250
finally:
# Remove ansible tempdir
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
sys.exit(exit_code)
sys.exit(250)

View File

@ -1 +0,0 @@
ansible

View File

@ -1,22 +0,0 @@
#
# Configuration file for azure_rm.py
#
[azure]
# Control which resource groups are included. By default all resources groups are included.
# Set resource_groups to a comma separated list of resource groups names.
#resource_groups=
# Control which tags are included. Set tags to a comma separated list of keys or key:value pairs
#tags=
# Control which locations are included. Set locations to a comma separated list (e.g. eastus,eastus2,westus)
#locations=
# Include powerstate. If you don't need powerstate information, turning it off improves runtime performance.
include_powerstate=yes
# Control grouping with the following boolean flags. Valid values: yes, no, true, false, True, False, 0, 1.
group_by_resource_group=yes
group_by_location=yes
group_by_security_group=yes
group_by_tag=yes

View File

@ -1,802 +0,0 @@
#!/usr/bin/env python
#
# Copyright (c) 2016 Matt Davis, <mdavis@ansible.com>
# Chris Houseknecht, <house@redhat.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
'''
Azure External Inventory Script
===============================
Generates dynamic inventory by making API requests to the Azure Resource
Manager using the Azure Python SDK. For instruction on installing the
Azure Python SDK see http://azure-sdk-for-python.readthedocs.org/
Authentication
--------------
The order of precedence is command line arguments, environment variables,
and finally the [default] profile found in ~/.azure/credentials.
If using a credentials file, it should be an ini formatted file with one or
more sections, which we refer to as profiles. The script looks for a
[default] section, if a profile is not specified either on the command line
or with an environment variable. The keys in a profile will match the
list of command line arguments below.
For command line arguments and environment variables specify a profile found
in your ~/.azure/credentials file, or a service principal or Active Directory
user.
Command line arguments:
- profile
- client_id
- secret
- subscription_id
- tenant
- ad_user
- password
Environment variables:
- AZURE_PROFILE
- AZURE_CLIENT_ID
- AZURE_SECRET
- AZURE_SUBSCRIPTION_ID
- AZURE_TENANT
- AZURE_AD_USER
- AZURE_PASSWORD
Run for Specific Host
-----------------------
When run for a specific host using the --host option, a resource group is
required. For a specific host, this script returns the following variables:
{
"ansible_host": "XXX.XXX.XXX.XXX",
"computer_name": "computer_name2",
"fqdn": null,
"id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Compute/virtualMachines/object-name",
"image": {
"offer": "CentOS",
"publisher": "OpenLogic",
"sku": "7.1",
"version": "latest"
},
"location": "westus",
"mac_address": "00-00-5E-00-53-FE",
"name": "object-name",
"network_interface": "interface-name",
"network_interface_id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Network/networkInterfaces/object-name1",
"network_security_group": null,
"network_security_group_id": null,
"os_disk": {
"name": "object-name",
"operating_system_type": "Linux"
},
"plan": null,
"powerstate": "running",
"private_ip": "172.26.3.6",
"private_ip_alloc_method": "Static",
"provisioning_state": "Succeeded",
"public_ip": "XXX.XXX.XXX.XXX",
"public_ip_alloc_method": "Static",
"public_ip_id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Network/publicIPAddresses/object-name",
"public_ip_name": "object-name",
"resource_group": "galaxy-production",
"security_group": "object-name",
"security_group_id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Network/networkSecurityGroups/object-name",
"tags": {
"db": "database"
},
"type": "Microsoft.Compute/virtualMachines",
"virtual_machine_size": "Standard_DS4"
}
Groups
------
When run in --list mode, instances are grouped by the following categories:
- azure
- location
- resource_group
- security_group
- tag key
- tag key_value
Control groups using azure_rm.ini or set environment variables:
AZURE_GROUP_BY_RESOURCE_GROUP=yes
AZURE_GROUP_BY_LOCATION=yes
AZURE_GROUP_BY_SECURITY_GROUP=yes
AZURE_GROUP_BY_TAG=yes
Select hosts within specific resource groups by assigning a comma separated list to:
AZURE_RESOURCE_GROUPS=resource_group_a,resource_group_b
Select hosts for specific tag key by assigning a comma separated list of tag keys to:
AZURE_TAGS=key1,key2,key3
Select hosts for specific locations:
AZURE_LOCATIONS=eastus,westus,eastus2
Or, select hosts for specific tag key:value pairs by assigning a comma separated list key:value pairs to:
AZURE_TAGS=key1:value1,key2:value2
If you don't need the powerstate, you can improve performance by turning off powerstate fetching:
AZURE_INCLUDE_POWERSTATE=no
azure_rm.ini
------------
As mentioned above, you can control execution using environment variables or a .ini file. A sample
azure_rm.ini is included. The name of the .ini file is the basename of the inventory script (in this case
'azure_rm') with a .ini extension. It also assumes the .ini file is alongside the script. To specify
a different path for the .ini file, define the AZURE_INI_PATH environment variable:
export AZURE_INI_PATH=/path/to/custom.ini
Powerstate:
-----------
The powerstate attribute indicates whether or not a host is running. If the value is 'running', the machine is
up. If the value is anything other than 'running', the machine is down, and will be unreachable.
Examples:
---------
Execute /bin/uname on all instances in the galaxy-qa resource group
$ ansible -i azure_rm.py galaxy-qa -m shell -a "/bin/uname -a"
Use the inventory script to print instance specific information
$ contrib/inventory/azure_rm.py --host my_instance_host_name --pretty
Use with a playbook
$ ansible-playbook -i contrib/inventory/azure_rm.py my_playbook.yml --limit galaxy-qa
Insecure Platform Warning
-------------------------
If you receive InsecurePlatformWarning from urllib3, install the
requests security packages:
pip install requests[security]
author:
- Chris Houseknecht (@chouseknecht)
- Matt Davis (@nitzmahone)
Company: Ansible by Red Hat
Version: 1.0.0
'''
import argparse
import ConfigParser
import json
import os
import re
import sys
from packaging.version import Version
from os.path import expanduser
HAS_AZURE = True
HAS_AZURE_EXC = None
try:
from msrestazure.azure_exceptions import CloudError
from azure.mgmt.compute import __version__ as azure_compute_version
from azure.common import AzureMissingResourceHttpError, AzureHttpError
from azure.common.credentials import ServicePrincipalCredentials, UserPassCredentials
from azure.mgmt.network.network_management_client import NetworkManagementClient
from azure.mgmt.resource.resources.resource_management_client import ResourceManagementClient
from azure.mgmt.compute.compute_management_client import ComputeManagementClient
except ImportError as exc:
HAS_AZURE_EXC = exc
HAS_AZURE = False
AZURE_CREDENTIAL_ENV_MAPPING = dict(
profile='AZURE_PROFILE',
subscription_id='AZURE_SUBSCRIPTION_ID',
client_id='AZURE_CLIENT_ID',
secret='AZURE_SECRET',
tenant='AZURE_TENANT',
ad_user='AZURE_AD_USER',
password='AZURE_PASSWORD'
)
AZURE_CONFIG_SETTINGS = dict(
resource_groups='AZURE_RESOURCE_GROUPS',
tags='AZURE_TAGS',
locations='AZURE_LOCATIONS',
include_powerstate='AZURE_INCLUDE_POWERSTATE',
group_by_resource_group='AZURE_GROUP_BY_RESOURCE_GROUP',
group_by_location='AZURE_GROUP_BY_LOCATION',
group_by_security_group='AZURE_GROUP_BY_SECURITY_GROUP',
group_by_tag='AZURE_GROUP_BY_TAG'
)
AZURE_MIN_VERSION = "0.30.0rc5"
def azure_id_to_dict(id):
pieces = re.sub(r'^\/', '', id).split('/')
result = {}
index = 0
while index < len(pieces) - 1:
result[pieces[index]] = pieces[index + 1]
index += 1
return result
class AzureRM(object):
def __init__(self, args):
self._args = args
self._compute_client = None
self._resource_client = None
self._network_client = None
self.debug = False
if args.debug:
self.debug = True
self.credentials = self._get_credentials(args)
if not self.credentials:
self.fail("Failed to get credentials. Either pass as parameters, set environment variables, "
"or define a profile in ~/.azure/credentials.")
if self.credentials.get('subscription_id', None) is None:
self.fail("Credentials did not include a subscription_id value.")
self.log("setting subscription_id")
self.subscription_id = self.credentials['subscription_id']
if self.credentials.get('client_id') is not None and \
self.credentials.get('secret') is not None and \
self.credentials.get('tenant') is not None:
self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'],
secret=self.credentials['secret'],
tenant=self.credentials['tenant'])
elif self.credentials.get('ad_user') is not None and self.credentials.get('password') is not None:
self.azure_credentials = UserPassCredentials(self.credentials['ad_user'], self.credentials['password'])
else:
self.fail("Failed to authenticate with provided credentials. Some attributes were missing. "
"Credentials must include client_id, secret and tenant or ad_user and password.")
def log(self, msg):
if self.debug:
print (msg + u'\n')
def fail(self, msg):
raise Exception(msg)
def _get_profile(self, profile="default"):
path = expanduser("~")
path += "/.azure/credentials"
try:
config = ConfigParser.ConfigParser()
config.read(path)
except Exception as exc:
self.fail("Failed to access {0}. Check that the file exists and you have read "
"access. {1}".format(path, str(exc)))
credentials = dict()
for key in AZURE_CREDENTIAL_ENV_MAPPING:
try:
credentials[key] = config.get(profile, key, raw=True)
except:
pass
if credentials.get('client_id') is not None or credentials.get('ad_user') is not None:
return credentials
return None
def _get_env_credentials(self):
env_credentials = dict()
for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
env_credentials[attribute] = os.environ.get(env_variable, None)
if env_credentials['profile'] is not None:
credentials = self._get_profile(env_credentials['profile'])
return credentials
if env_credentials['client_id'] is not None or env_credentials['ad_user'] is not None:
return env_credentials
return None
def _get_credentials(self, params):
# Get authentication credentials.
# Precedence: cmd line parameters-> environment variables-> default profile in ~/.azure/credentials.
self.log('Getting credentials')
arg_credentials = dict()
for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
arg_credentials[attribute] = getattr(params, attribute)
# try module params
if arg_credentials['profile'] is not None:
self.log('Retrieving credentials with profile parameter.')
credentials = self._get_profile(arg_credentials['profile'])
return credentials
if arg_credentials['client_id'] is not None:
self.log('Received credentials from parameters.')
return arg_credentials
# try environment
env_credentials = self._get_env_credentials()
if env_credentials:
self.log('Received credentials from env.')
return env_credentials
# try default profile from ~./azure/credentials
default_credentials = self._get_profile()
if default_credentials:
self.log('Retrieved default profile credentials from ~/.azure/credentials.')
return default_credentials
return None
def _register(self, key):
try:
# We have to perform the one-time registration here. Otherwise, we receive an error the first
# time we attempt to use the requested client.
resource_client = self.rm_client
resource_client.providers.register(key)
except Exception as exc:
self.log("One-time registration of {0} failed - {1}".format(key, str(exc)))
self.log("You might need to register {0} using an admin account".format(key))
self.log(("To register a provider using the Python CLI: "
"https://docs.microsoft.com/azure/azure-resource-manager/"
"resource-manager-common-deployment-errors#noregisteredproviderfound"))
@property
def network_client(self):
self.log('Getting network client')
if not self._network_client:
self._network_client = NetworkManagementClient(self.azure_credentials, self.subscription_id)
self._register('Microsoft.Network')
return self._network_client
@property
def rm_client(self):
self.log('Getting resource manager client')
if not self._resource_client:
self._resource_client = ResourceManagementClient(self.azure_credentials, self.subscription_id)
return self._resource_client
@property
def compute_client(self):
self.log('Getting compute client')
if not self._compute_client:
self._compute_client = ComputeManagementClient(self.azure_credentials, self.subscription_id)
self._register('Microsoft.Compute')
return self._compute_client
class AzureInventory(object):
def __init__(self):
self._args = self._parse_cli_args()
try:
rm = AzureRM(self._args)
except Exception as e:
sys.exit("{0}".format(str(e)))
self._compute_client = rm.compute_client
self._network_client = rm.network_client
self._resource_client = rm.rm_client
self._security_groups = None
self.resource_groups = []
self.tags = None
self.locations = None
self.replace_dash_in_groups = False
self.group_by_resource_group = True
self.group_by_location = True
self.group_by_security_group = True
self.group_by_tag = True
self.include_powerstate = True
self._inventory = dict(
_meta=dict(
hostvars=dict()
),
azure=[]
)
self._get_settings()
if self._args.resource_groups:
self.resource_groups = self._args.resource_groups.split(',')
if self._args.tags:
self.tags = self._args.tags.split(',')
if self._args.locations:
self.locations = self._args.locations.split(',')
if self._args.no_powerstate:
self.include_powerstate = False
self.get_inventory()
print (self._json_format_dict(pretty=self._args.pretty))
sys.exit(0)
def _parse_cli_args(self):
# Parse command line arguments
parser = argparse.ArgumentParser(
description='Produce an Ansible Inventory file for an Azure subscription')
parser.add_argument('--list', action='store_true', default=True,
help='List instances (default: True)')
parser.add_argument('--debug', action='store_true', default=False,
help='Send debug messages to STDOUT')
parser.add_argument('--host', action='store',
help='Get all information about an instance')
parser.add_argument('--pretty', action='store_true', default=False,
help='Pretty print JSON output(default: False)')
parser.add_argument('--profile', action='store',
help='Azure profile contained in ~/.azure/credentials')
parser.add_argument('--subscription_id', action='store',
help='Azure Subscription Id')
parser.add_argument('--client_id', action='store',
help='Azure Client Id ')
parser.add_argument('--secret', action='store',
help='Azure Client Secret')
parser.add_argument('--tenant', action='store',
help='Azure Tenant Id')
parser.add_argument('--ad-user', action='store',
help='Active Directory User')
parser.add_argument('--password', action='store',
help='password')
parser.add_argument('--resource-groups', action='store',
help='Return inventory for comma separated list of resource group names')
parser.add_argument('--tags', action='store',
help='Return inventory for comma separated list of tag key:value pairs')
parser.add_argument('--locations', action='store',
help='Return inventory for comma separated list of locations')
parser.add_argument('--no-powerstate', action='store_true', default=False,
help='Do not include the power state of each virtual host')
return parser.parse_args()
def get_inventory(self):
if len(self.resource_groups) > 0:
# get VMs for requested resource groups
for resource_group in self.resource_groups:
try:
virtual_machines = self._compute_client.virtual_machines.list(resource_group)
except Exception as exc:
sys.exit("Error: fetching virtual machines for resource group {0} - {1}".format(resource_group,
str(exc)))
if self._args.host or self.tags:
selected_machines = self._selected_machines(virtual_machines)
self._load_machines(selected_machines)
else:
self._load_machines(virtual_machines)
else:
# get all VMs within the subscription
try:
virtual_machines = self._compute_client.virtual_machines.list_all()
except Exception as exc:
sys.exit("Error: fetching virtual machines - {0}".format(str(exc)))
if self._args.host or self.tags or self.locations:
selected_machines = self._selected_machines(virtual_machines)
self._load_machines(selected_machines)
else:
self._load_machines(virtual_machines)
def _load_machines(self, machines):
for machine in machines:
id_dict = azure_id_to_dict(machine.id)
#TODO - The API is returning an ID value containing resource group name in ALL CAPS. If/when it gets
# fixed, we should remove the .lower(). Opened Issue
# #574: https://github.com/Azure/azure-sdk-for-python/issues/574
resource_group = id_dict['resourceGroups'].lower()
if self.group_by_security_group:
self._get_security_groups(resource_group)
host_vars = dict(
ansible_host=None,
private_ip=None,
private_ip_alloc_method=None,
public_ip=None,
public_ip_name=None,
public_ip_id=None,
public_ip_alloc_method=None,
fqdn=None,
location=machine.location,
name=machine.name,
type=machine.type,
id=machine.id,
tags=machine.tags,
network_interface_id=None,
network_interface=None,
resource_group=resource_group,
mac_address=None,
plan=(machine.plan.name if machine.plan else None),
virtual_machine_size=machine.hardware_profile.vm_size,
computer_name=machine.os_profile.computer_name,
provisioning_state=machine.provisioning_state,
)
host_vars['os_disk'] = dict(
name=machine.storage_profile.os_disk.name,
operating_system_type=machine.storage_profile.os_disk.os_type.value
)
if self.include_powerstate:
host_vars['powerstate'] = self._get_powerstate(resource_group, machine.name)
if machine.storage_profile.image_reference:
host_vars['image'] = dict(
offer=machine.storage_profile.image_reference.offer,
publisher=machine.storage_profile.image_reference.publisher,
sku=machine.storage_profile.image_reference.sku,
version=machine.storage_profile.image_reference.version
)
# Add windows details
if machine.os_profile.windows_configuration is not None:
host_vars['windows_auto_updates_enabled'] = \
machine.os_profile.windows_configuration.enable_automatic_updates
host_vars['windows_timezone'] = machine.os_profile.windows_configuration.time_zone
host_vars['windows_rm'] = None
if machine.os_profile.windows_configuration.win_rm is not None:
host_vars['windows_rm'] = dict(listeners=None)
if machine.os_profile.windows_configuration.win_rm.listeners is not None:
host_vars['windows_rm']['listeners'] = []
for listener in machine.os_profile.windows_configuration.win_rm.listeners:
host_vars['windows_rm']['listeners'].append(dict(protocol=listener.protocol,
certificate_url=listener.certificate_url))
for interface in machine.network_profile.network_interfaces:
interface_reference = self._parse_ref_id(interface.id)
network_interface = self._network_client.network_interfaces.get(
interface_reference['resourceGroups'],
interface_reference['networkInterfaces'])
if network_interface.primary:
if self.group_by_security_group and \
self._security_groups[resource_group].get(network_interface.id, None):
host_vars['security_group'] = \
self._security_groups[resource_group][network_interface.id]['name']
host_vars['security_group_id'] = \
self._security_groups[resource_group][network_interface.id]['id']
host_vars['network_interface'] = network_interface.name
host_vars['network_interface_id'] = network_interface.id
host_vars['mac_address'] = network_interface.mac_address
for ip_config in network_interface.ip_configurations:
host_vars['private_ip'] = ip_config.private_ip_address
host_vars['private_ip_alloc_method'] = ip_config.private_ip_allocation_method
if ip_config.public_ip_address:
public_ip_reference = self._parse_ref_id(ip_config.public_ip_address.id)
public_ip_address = self._network_client.public_ip_addresses.get(
public_ip_reference['resourceGroups'],
public_ip_reference['publicIPAddresses'])
host_vars['ansible_host'] = public_ip_address.ip_address
host_vars['public_ip'] = public_ip_address.ip_address
host_vars['public_ip_name'] = public_ip_address.name
host_vars['public_ip_alloc_method'] = public_ip_address.public_ip_allocation_method
host_vars['public_ip_id'] = public_ip_address.id
if public_ip_address.dns_settings:
host_vars['fqdn'] = public_ip_address.dns_settings.fqdn
self._add_host(host_vars)
def _selected_machines(self, virtual_machines):
selected_machines = []
for machine in virtual_machines:
if self._args.host and self._args.host == machine.name:
selected_machines.append(machine)
if self.tags and self._tags_match(machine.tags, self.tags):
selected_machines.append(machine)
if self.locations and machine.location in self.locations:
selected_machines.append(machine)
return selected_machines
def _get_security_groups(self, resource_group):
''' For a given resource_group build a mapping of network_interface.id to security_group name '''
if not self._security_groups:
self._security_groups = dict()
if not self._security_groups.get(resource_group):
self._security_groups[resource_group] = dict()
for group in self._network_client.network_security_groups.list(resource_group):
if group.network_interfaces:
for interface in group.network_interfaces:
self._security_groups[resource_group][interface.id] = dict(
name=group.name,
id=group.id
)
def _get_powerstate(self, resource_group, name):
try:
vm = self._compute_client.virtual_machines.get(resource_group,
name,
expand='instanceview')
except Exception as exc:
sys.exit("Error: fetching instanceview for host {0} - {1}".format(name, str(exc)))
return next((s.code.replace('PowerState/', '')
for s in vm.instance_view.statuses if s.code.startswith('PowerState')), None)
def _add_host(self, vars):
host_name = self._to_safe(vars['name'])
resource_group = self._to_safe(vars['resource_group'])
security_group = None
if vars.get('security_group'):
security_group = self._to_safe(vars['security_group'])
if self.group_by_resource_group:
if not self._inventory.get(resource_group):
self._inventory[resource_group] = []
self._inventory[resource_group].append(host_name)
if self.group_by_location:
if not self._inventory.get(vars['location']):
self._inventory[vars['location']] = []
self._inventory[vars['location']].append(host_name)
if self.group_by_security_group and security_group:
if not self._inventory.get(security_group):
self._inventory[security_group] = []
self._inventory[security_group].append(host_name)
self._inventory['_meta']['hostvars'][host_name] = vars
self._inventory['azure'].append(host_name)
if self.group_by_tag and vars.get('tags'):
for key, value in vars['tags'].items():
safe_key = self._to_safe(key)
safe_value = safe_key + '_' + self._to_safe(value)
if not self._inventory.get(safe_key):
self._inventory[safe_key] = []
if not self._inventory.get(safe_value):
self._inventory[safe_value] = []
self._inventory[safe_key].append(host_name)
self._inventory[safe_value].append(host_name)
def _json_format_dict(self, pretty=False):
# convert inventory to json
if pretty:
return json.dumps(self._inventory, sort_keys=True, indent=2)
else:
return json.dumps(self._inventory)
def _get_settings(self):
# Load settings from the .ini, if it exists. Otherwise,
# look for environment values.
file_settings = self._load_settings()
if file_settings:
for key in AZURE_CONFIG_SETTINGS:
if key in ('resource_groups', 'tags', 'locations') and file_settings.get(key):
values = file_settings.get(key).split(',')
if len(values) > 0:
setattr(self, key, values)
elif file_settings.get(key):
val = self._to_boolean(file_settings[key])
setattr(self, key, val)
else:
env_settings = self._get_env_settings()
for key in AZURE_CONFIG_SETTINGS:
if key in('resource_groups', 'tags', 'locations') and env_settings.get(key):
values = env_settings.get(key).split(',')
if len(values) > 0:
setattr(self, key, values)
elif env_settings.get(key, None) is not None:
val = self._to_boolean(env_settings[key])
setattr(self, key, val)
def _parse_ref_id(self, reference):
response = {}
keys = reference.strip('/').split('/')
for index in range(len(keys)):
if index < len(keys) - 1 and index % 2 == 0:
response[keys[index]] = keys[index + 1]
return response
def _to_boolean(self, value):
if value in ['Yes', 'yes', 1, 'True', 'true', True]:
result = True
elif value in ['No', 'no', 0, 'False', 'false', False]:
result = False
else:
result = True
return result
def _get_env_settings(self):
env_settings = dict()
for attribute, env_variable in AZURE_CONFIG_SETTINGS.items():
env_settings[attribute] = os.environ.get(env_variable, None)
return env_settings
def _load_settings(self):
basename = os.path.splitext(os.path.basename(__file__))[0]
default_path = os.path.join(os.path.dirname(__file__), (basename + '.ini'))
path = os.path.expanduser(os.path.expandvars(os.environ.get('AZURE_INI_PATH', default_path)))
config = None
settings = None
try:
config = ConfigParser.ConfigParser()
config.read(path)
except:
pass
if config is not None:
settings = dict()
for key in AZURE_CONFIG_SETTINGS:
try:
settings[key] = config.get('azure', key, raw=True)
except:
pass
return settings
def _tags_match(self, tag_obj, tag_args):
'''
Return True if the tags object from a VM contains the requested tag values.
:param tag_obj: Dictionary of string:string pairs
:param tag_args: List of strings in the form key=value
:return: boolean
'''
if not tag_obj:
return False
matches = 0
for arg in tag_args:
arg_key = arg
arg_value = None
if re.search(r':', arg):
arg_key, arg_value = arg.split(':')
if arg_value and tag_obj.get(arg_key, None) == arg_value:
matches += 1
elif not arg_value and tag_obj.get(arg_key, None) is not None:
matches += 1
if matches == len(tag_args):
return True
return False
def _to_safe(self, word):
''' Converts 'bad' characters in a string to underscores so they can be used as Ansible groups '''
regex = "[^A-Za-z0-9\_"
if not self.replace_dash_in_groups:
regex += "\-"
return re.sub(regex + "]", "_", word)
def main():
if not HAS_AZURE:
sys.exit("The Azure python sdk is not installed (try `pip install 'azure>=2.0.0rc5' --upgrade`) - {0}".format(HAS_AZURE_EXC))
if Version(azure_compute_version) < Version(AZURE_MIN_VERSION):
sys.exit("Expecting azure.mgmt.compute.__version__ to be {0}. Found version {1} "
"Do you have Azure >= 2.0.0rc5 installed? (try `pip install 'azure>=2.0.0rc5' --upgrade`)".format(AZURE_MIN_VERSION, azure_compute_version))
AzureInventory()
if __name__ == '__main__':
main()

View File

@ -1,40 +0,0 @@
#!/usr/bin/python
# Copyright 2016 Doalitic.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# The Brook.io inventory script has the following dependencies:
# 1. A working Brook.io account
# See https://brook.io
# 2. A valid token generated through the 'API token' panel of Brook.io
# 3. The libbrook python libray.
# See https://github.com/doalitic/libbrook
#
# Author: Francisco Ros <fjros@doalitic.com>
[brook]
# Valid API token (required).
# E.g. 'Aed342a12A60433697281FeEe1a4037C'
#
api_token =
# Project id within Brook.io, as obtained from the project settings (optional). If provided, the
# generated inventory will just include the hosts that belong to such project. Otherwise, it will
# include all hosts in projects the requesting user has access to. The response includes groups
# 'project_x', being 'x' the project name.
# E.g. '2e8e099e1bc34cc0979d97ac34e9577b'
#
project_id =

View File

@ -1,261 +0,0 @@
#!/usr/bin/env python
# Copyright 2016 Doalitic.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
"""
Brook.io external inventory script
==================================
Generates inventory that Ansible can understand by making API requests to Brook.io via the libbrook
library. Hence, such dependency must be installed in the system to run this script.
The default configuration file is named 'brook.ini' and is located alongside this script. You can
choose any other file by setting the BROOK_INI_PATH environment variable.
If param 'project_id' is left blank in 'brook.ini', the inventory includes all the instances in
projects where the requesting user belongs. Otherwise, only instances from the given project are
included, provided the requesting user belongs to it.
The following variables are established for every host. They can be retrieved from the hostvars
dictionary.
- brook_name: str
- brook_description: str
- brook_project: str
- brook_template: str
- brook_region: str
- brook_status: str
- brook_tags: list(str)
- brook_internal_ips: list(str)
- brook_external_ips: list(str)
- brook_created_at
- brook_updated_at
- ansible_ssh_host
Instances are grouped by the following categories:
- tag:
A group is created for each tag. E.g. groups 'tag_foo' and 'tag_bar' are created if there exist
instances with tags 'foo' and/or 'bar'.
- project:
A group is created for each project. E.g. group 'project_test' is created if a project named
'test' exist.
- status:
A group is created for each instance state. E.g. groups 'status_RUNNING' and 'status_PENDING'
are created if there are instances in running and pending state.
Examples:
Execute uname on all instances in project 'test'
$ ansible -i brook.py project_test -m shell -a "/bin/uname -a"
Install nginx on all debian web servers tagged with 'www'
$ ansible -i brook.py tag_www -m apt -a "name=nginx state=present"
Run site.yml playbook on web servers
$ ansible-playbook -i brook.py site.yml -l tag_www
Support:
This script is tested on Python 2.7 and 3.4. It may work on other versions though.
Author: Francisco Ros <fjros@doalitic.com>
Version: 0.1
"""
import sys
import os
try:
from ConfigParser import SafeConfigParser as ConfigParser
except ImportError:
from configparser import ConfigParser
try:
import json
except ImportError:
import simplejson as json
try:
import libbrook
except:
sys.exit('Brook.io inventory script requires libbrook. See https://github.com/doalitic/libbrook')
class BrookInventory:
_API_ENDPOINT = 'https://api.brook.io'
def __init__(self):
self._configure_from_file()
self.client = self.get_api_client()
self.inventory = self.get_inventory()
def _configure_from_file(self):
"""Initialize from .ini file.
Configuration file is assumed to be named 'brook.ini' and to be located on the same
directory than this file, unless the environment variable BROOK_INI_PATH says otherwise.
"""
brook_ini_default_path = \
os.path.join(os.path.dirname(os.path.realpath(__file__)), 'brook.ini')
brook_ini_path = os.environ.get('BROOK_INI_PATH', brook_ini_default_path)
config = ConfigParser(defaults={
'api_token': '',
'project_id': ''
})
config.read(brook_ini_path)
self.api_token = config.get('brook', 'api_token')
self.project_id = config.get('brook', 'project_id')
if not self.api_token:
print('You must provide (at least) your Brook.io API token to generate the dynamic '
'inventory.')
sys.exit(1)
def get_api_client(self):
"""Authenticate user via the provided credentials and return the corresponding API client.
"""
# Get JWT token from API token
#
unauthenticated_client = libbrook.ApiClient(host=self._API_ENDPOINT)
auth_api = libbrook.AuthApi(unauthenticated_client)
api_token = libbrook.AuthTokenRequest()
api_token.token = self.api_token
jwt = auth_api.auth_token(token=api_token)
# Create authenticated API client
#
return libbrook.ApiClient(host=self._API_ENDPOINT,
header_name='Authorization',
header_value='Bearer %s' % jwt.token)
def get_inventory(self):
"""Generate Ansible inventory.
"""
groups = dict()
meta = dict()
meta['hostvars'] = dict()
instances_api = libbrook.InstancesApi(self.client)
projects_api = libbrook.ProjectsApi(self.client)
templates_api = libbrook.TemplatesApi(self.client)
# If no project is given, get all projects the requesting user has access to
#
if not self.project_id:
projects = [project.id for project in projects_api.index_projects()]
else:
projects = [self.project_id]
# Build inventory from instances in all projects
#
for project_id in projects:
project = projects_api.show_project(project_id=project_id)
for instance in instances_api.index_instances(project_id=project_id):
# Get template used for this instance
template = templates_api.show_template(template_id=instance.template)
# Update hostvars
try:
meta['hostvars'][instance.name] = \
self.hostvars(project, instance, template, instances_api)
except libbrook.rest.ApiException:
continue
# Group by project
project_group = 'project_%s' % project.name
if project_group in groups.keys():
groups[project_group].append(instance.name)
else:
groups[project_group] = [instance.name]
# Group by status
status_group = 'status_%s' % meta['hostvars'][instance.name]['brook_status']
if status_group in groups.keys():
groups[status_group].append(instance.name)
else:
groups[status_group] = [instance.name]
# Group by tags
tags = meta['hostvars'][instance.name]['brook_tags']
for tag in tags:
tag_group = 'tag_%s' % tag
if tag_group in groups.keys():
groups[tag_group].append(instance.name)
else:
groups[tag_group] = [instance.name]
groups['_meta'] = meta
return groups
def hostvars(self, project, instance, template, api):
"""Return the hostvars dictionary for the given instance.
Raise libbrook.rest.ApiException if it cannot retrieve all required information from the
Brook.io API.
"""
hostvars = instance.to_dict()
hostvars['brook_name'] = hostvars.pop('name')
hostvars['brook_description'] = hostvars.pop('description')
hostvars['brook_project'] = hostvars.pop('project')
hostvars['brook_template'] = hostvars.pop('template')
hostvars['brook_region'] = hostvars.pop('region')
hostvars['brook_created_at'] = hostvars.pop('created_at')
hostvars['brook_updated_at'] = hostvars.pop('updated_at')
del hostvars['id']
del hostvars['key']
del hostvars['provider']
del hostvars['image']
# Substitute identifiers for names
#
hostvars['brook_project'] = project.name
hostvars['brook_template'] = template.name
# Retrieve instance state
#
status = api.status_instance(project_id=project.id, instance_id=instance.id)
hostvars.update({'brook_status': status.state})
# Retrieve instance tags
#
tags = api.instance_tags(project_id=project.id, instance_id=instance.id)
hostvars.update({'brook_tags': tags})
# Retrieve instance addresses
#
addresses = api.instance_addresses(project_id=project.id, instance_id=instance.id)
internal_ips = [address.address for address in addresses if address.scope == 'internal']
external_ips = [address.address for address in addresses
if address.address and address.scope == 'external']
hostvars.update({'brook_internal_ips': internal_ips})
hostvars.update({'brook_external_ips': external_ips})
try:
hostvars.update({'ansible_ssh_host': external_ips[0]})
except IndexError:
raise libbrook.rest.ApiException(status='502', reason='Instance without public IP')
return hostvars
# Run the script
#
brook = BrookInventory()
print(json.dumps(brook.inventory))

View File

@ -109,11 +109,11 @@ class CloudStackInventory(object):
project_id = self.get_project_id(options.project)
if options.host:
data = self.get_host(options.host, project_id)
data = self.get_host(options.host)
print(json.dumps(data, indent=2))
elif options.list:
data = self.get_list(project_id)
data = self.get_list()
print(json.dumps(data, indent=2))
else:
print("usage: --list | --host <hostname> [--project <project>]",

View File

@ -3,8 +3,6 @@
[collins]
# You should not have a trailing slash or collins
# will not properly match the URI
host = http://localhost:9000
username = blake

View File

@ -201,8 +201,7 @@ class CollinsInventory(object):
response = open_url(query_url,
timeout=self.collins_timeout_secs,
url_username=self.collins_username,
url_password=self.collins_password,
force_basic_auth=True)
url_password=self.collins_password)
json_response = json.loads(response.read())
# Adds any assets found to the array of assets.
assets += json_response['data']['Data']

View File

@ -129,58 +129,6 @@ import sys
import ConfigParser
import urllib, urllib2, base64
def get_log_filename():
tty_filename = '/dev/tty'
stdout_filename = '/dev/stdout'
if not os.path.exists(tty_filename):
return stdout_filename
if not os.access(tty_filename, os.W_OK):
return stdout_filename
if os.getenv('TEAMCITY_VERSION'):
return stdout_filename
return tty_filename
def setup_logging():
filename = get_log_filename()
import logging.config
logging.config.dictConfig({
'version': 1,
'formatters': {
'simple': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
},
},
'root': {
'level': os.getenv('ANSIBLE_INVENTORY_CONSUL_IO_LOG_LEVEL', 'WARN'),
'handlers': ['console'],
},
'handlers': {
'console': {
'class': 'logging.FileHandler',
'filename': filename,
'formatter': 'simple',
},
},
'loggers': {
'iso8601': {
'qualname': 'iso8601',
'level': 'INFO',
},
},
})
logger = logging.getLogger('consul_io.py')
logger.debug('Invoked with %r', sys.argv)
if os.getenv('ANSIBLE_INVENTORY_CONSUL_IO_LOG_ENABLED'):
setup_logging()
try:
import json
except ImportError:

View File

@ -26,9 +26,3 @@ cache_max_age = 300
# Use the private network IP address instead of the public when available.
#
use_private_network = False
# Pass variables to every group, e.g.:
#
# group_variables = { 'ansible_user': 'root' }
#
group_variables = {}

View File

@ -137,7 +137,6 @@ import re
import argparse
from time import time
import ConfigParser
import ast
try:
import json
@ -169,7 +168,6 @@ class DigitalOceanInventory(object):
self.cache_path = '.'
self.cache_max_age = 0
self.use_private_network = False
self.group_variables = {}
# Read settings, environment variables, and CLI arguments
self.read_settings()
@ -263,10 +261,6 @@ or environment variables (DO_API_TOKEN)''')
if config.has_option('digital_ocean', 'use_private_network'):
self.use_private_network = config.get('digital_ocean', 'use_private_network')
# Group variables
if config.has_option('digital_ocean', 'group_variables'):
self.group_variables = ast.literal_eval(config.get('digital_ocean', 'group_variables'))
def read_environment(self):
''' Reads the settings from environment variables '''
# Setup credentials
@ -365,24 +359,22 @@ or environment variables (DO_API_TOKEN)''')
else:
dest = droplet['ip_address']
dest = { 'hosts': [ dest ], 'vars': self.group_variables }
self.inventory[droplet['id']] = dest
self.inventory[droplet['name']] = dest
self.inventory['region_' + droplet['region']['slug']] = dest
self.inventory['image_' + str(droplet['image']['id'])] = dest
self.inventory['size_' + droplet['size']['slug']] = dest
self.inventory[droplet['id']] = [dest]
self.push(self.inventory, droplet['name'], dest)
self.push(self.inventory, 'region_' + droplet['region']['slug'], dest)
self.push(self.inventory, 'image_' + str(droplet['image']['id']), dest)
self.push(self.inventory, 'size_' + droplet['size']['slug'], dest)
image_slug = droplet['image']['slug']
if image_slug:
self.inventory['image_' + self.to_safe(image_slug)] = dest
self.push(self.inventory, 'image_' + self.to_safe(image_slug), dest)
else:
image_name = droplet['image']['name']
if image_name:
self.inventory['image_' + self.to_safe(image_name)] = dest
self.push(self.inventory, 'image_' + self.to_safe(image_name), dest)
self.inventory['distro_' + self.to_safe(droplet['image']['distribution'])] = dest
self.inventory['status_' + droplet['status']] = dest
self.push(self.inventory, 'distro_' + self.to_safe(droplet['image']['distribution']), dest)
self.push(self.inventory, 'status_' + droplet['status'], dest)
def load_droplet_variables_for_host(self):

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +1,134 @@
# This is the configuration file for the Docker inventory script: docker_inventory.py.
# This is the configuration file for the Ansible plugin for Docker inventory.
#
# You can define the following in this file:
# Author: Paul Durivage <paul.durivage@gmail.com>
#
# defaults
# Defines a default connection. Defaults will be taken from this and applied to any values not provided
# for a host defined in the hosts list.
# Description:
# This module queries local or remote Docker daemons and generates
# inventory information.
#
# hosts
# If you wish to get inventory from more than one Docker host, define a hosts list.
# This plugin does not support targeting of specific hosts using the --host
# flag. Instead, it it queries the Docker API for each container, running
# or not, and returns this data all once.
#
# For the default host and each host in the hosts list define the following attributes:
# The plugin returns the following custom attributes on Docker containers:
# docker_args
# docker_config
# docker_created
# docker_driver
# docker_exec_driver
# docker_host_config
# docker_hostname_path
# docker_hosts_path
# docker_id
# docker_image
# docker_name
# docker_network_settings
# docker_path
# docker_resolv_conf_path
# docker_state
# docker_volumes
# docker_volumes_rw
#
# host:
# description: The URL or Unix socket path used to connect to the Docker API.
# required: yes
# Requirements:
# The docker-py module: https://github.com/dotcloud/docker-py
#
# tls:
# description: Connect using TLS without verifying the authenticity of the Docker host server.
# default: false
# Notes:
# A config file can be used to configure this inventory module, and there
# are several environment variables that can be set to modify the behavior
# of the plugin at runtime:
# DOCKER_CONFIG_FILE
# DOCKER_HOST
# DOCKER_VERSION
# DOCKER_TIMEOUT
# DOCKER_PRIVATE_SSH_PORT
# DOCKER_DEFAULT_IP
#
# Environment Variables:
# environment variable: DOCKER_CONFIG_FILE
# description:
# - A path to a Docker inventory hosts/defaults file in YAML format
# - A sample file has been provided, colocated with the inventory
# file called 'docker.yml'
# required: false
#
# tls_verify:
# description: Connect using TLS without verifying the authenticity of the Docker host server.
# default: false
# default: Uses docker.docker.Client constructor defaults
# environment variable: DOCKER_HOST
# description:
# - The socket on which to connect to a Docker daemon API
# required: false
#
# cert_path:
# description: Path to the client's TLS certificate file.
# default: null
# default: Uses docker.docker.Client constructor defaults
# environment variable: DOCKER_VERSION
# description:
# - Version of the Docker API to use
# default: Uses docker.docker.Client constructor defaults
# required: false
#
# cacert_path:
# description: Use a CA certificate when performing server verification by providing the path to a CA certificate file.
# default: null
# required: false
#
# key_path:
# description: Path to the client's TLS key file.
# default: null
# required: false
#
# version:
# description: The Docker API version.
# required: false
# default: will be supplied by the docker-py module.
#
# timeout:
# description: The amount of time in seconds to wait on an API response.
# required: false
# default: 60
#
# default_ip:
# description: The IP address to assign to ansible_host when the container's SSH port is mapped to interface
# '0.0.0.0'.
# required: false
# default: 127.0.0.1
#
# private_ssh_port:
# description: The port containers use for SSH
# environment variable: DOCKER_TIMEOUT
# description:
# - Timeout in seconds for connections to Docker daemon API
# default: Uses docker.docker.Client constructor defaults
# required: false
# environment variable: DOCKER_PRIVATE_SSH_PORT
# description:
# - The private port (container port) on which SSH is listening
# for connections
# default: 22
# required: false
# environment variable: DOCKER_DEFAULT_IP
# description:
# - This environment variable overrides the container SSH connection
# IP address (aka, 'ansible_ssh_host')
#
# This option allows one to override the ansible_ssh_host whenever
# Docker has exercised its default behavior of binding private ports
# to all interfaces of the Docker host. This behavior, when dealing
# with remote Docker hosts, does not allow Ansible to determine
# a proper host IP address on which to connect via SSH to containers.
# By default, this inventory module assumes all 0.0.0.0-exposed
# ports to be bound to localhost:<port>. To override this
# behavior, for example, to bind a container's SSH port to the public
# interface of its host, one must manually set this IP.
#
# It is preferable to begin to launch Docker containers with
# ports exposed on publicly accessible IP addresses, particularly
# if the containers are to be targeted by Ansible for remote
# configuration, not accessible via localhost SSH connections.
#
# Docker containers can be explicitly exposed on IP addresses by
# a) starting the daemon with the --ip argument
# b) running containers with the -P/--publish ip::containerPort
# argument
# default: 127.0.0.1 if port exposed on 0.0.0.0 by Docker
# required: false
#
# Examples:
# Use the config file:
# DOCKER_CONFIG_FILE=./docker.yml docker.py --list
#
# Connect to docker instance on localhost port 4243
# DOCKER_HOST=tcp://localhost:4243 docker.py --list
#
# Any container's ssh port exposed on 0.0.0.0 will mapped to
# another IP address (where Ansible will attempt to connect via SSH)
# DOCKER_DEFAULT_IP=1.2.3.4 docker.py --list
#
#
#
# The Docker inventory plugin provides several environment variables that
# may be overridden here. This configuration file always takes precedence
# over environment variables.
#
# Variable precedence is: hosts > defaults > environment
#defaults:
# host: unix:///var/run/docker.sock
# private_ssh_port: 22
# default_ip: 127.0.0.1
#hosts:
---
defaults:
host: unix:///var/run/docker.sock
version: 1.9
timeout: 60
private_ssh_port: 22
default_ip: 127.0.0.1
hosts:
# - host: tcp://10.45.5.16:4243
# version: 1.9
# timeout: 60
# private_ssh_port: 2022
# default_ip: 172.16.3.45
# - host: tcp://localhost:4243
# private_ssh_port: 2029

View File

@ -29,32 +29,17 @@ regions_exclude = us-gov-west-1,cn-north-1
# in the event of a collision.
destination_variable = public_dns_name
# This allows you to override the inventory_name with an ec2 variable, instead
# of using the destination_variable above. Addressing (aka ansible_ssh_host)
# will still use destination_variable. Tags should be written as 'tag_TAGNAME'.
#hostname_variable = tag_Name
# For server inside a VPC, using DNS names may not make sense. When an instance
# has 'subnet_id' set, this variable is used. If the subnet is public, setting
# this to 'ip_address' will return the public IP address. For instances in a
# private subnet, this should be set to 'private_ip_address', and Ansible must
# be run from within EC2. The key of an EC2 tag may optionally be used; however
# the boto instance variables hold precedence in the event of a collision.
# WARNING: - instances that are in the private vpc, _without_ public ip address
# WARNING: - instances that are in the private vpc, _without_ public ip address
# will not be listed in the inventory until You set:
# vpc_destination_variable = private_ip_address
# vpc_destination_variable = 'private_ip_address'
vpc_destination_variable = ip_address
# The following two settings allow flexible ansible host naming based on a
# python format string and a comma-separated list of ec2 tags. Note that:
#
# 1) If the tags referenced are not present for some instances, empty strings
# will be substituted in the format string.
# 2) This overrides both destination_variable and vpc_destination_variable.
#
#destination_format = {0}.{1}.example.com
#destination_format_tags = Name,environment
# To tag instances on EC2 with the resource records that point to them from
# Route53, uncomment and set 'route53' to True.
route53 = False
@ -159,7 +144,7 @@ group_by_elasticache_replication_group = True
# You can use wildcards in filter values also. Below will list instances which
# tag Name value matches webservers1*
# (ex. webservers15, webservers1a, webservers123 etc)
# (ex. webservers15, webservers1a, webservers123 etc)
# instance_filters = tag:Name=webservers1*
# A boto configuration profile may be used to separate out credentials

View File

@ -237,19 +237,6 @@ class Ec2Inventory(object):
self.destination_variable = config.get('ec2', 'destination_variable')
self.vpc_destination_variable = config.get('ec2', 'vpc_destination_variable')
if config.has_option('ec2', 'hostname_variable'):
self.hostname_variable = config.get('ec2', 'hostname_variable')
else:
self.hostname_variable = None
if config.has_option('ec2', 'destination_format') and \
config.has_option('ec2', 'destination_format_tags'):
self.destination_format = config.get('ec2', 'destination_format')
self.destination_format_tags = config.get('ec2', 'destination_format_tags').split(',')
else:
self.destination_format = None
self.destination_format_tags = None
# Route53
self.route53_enabled = config.getboolean('ec2', 'route53')
self.route53_excluded_zones = []
@ -331,14 +318,8 @@ class Ec2Inventory(object):
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
cache_name = 'ansible-ec2'
aws_profile = lambda: (self.boto_profile or
os.environ.get('AWS_PROFILE') or
os.environ.get('AWS_ACCESS_KEY_ID'))
if aws_profile():
cache_name = '%s-%s' % (cache_name, aws_profile())
self.cache_path_cache = cache_dir + "/%s.cache" % cache_name
self.cache_path_index = cache_dir + "/%s.index" % cache_name
self.cache_path_cache = cache_dir + "/ansible-ec2.cache"
self.cache_path_index = cache_dir + "/ansible-ec2.index"
self.cache_max_age = config.getint('ec2', 'cache_max_age')
if config.has_option('ec2', 'expand_csv_tags'):
@ -407,10 +388,7 @@ class Ec2Inventory(object):
# Instance filters (see boto and EC2 API docs). Ignore invalid filters.
self.ec2_instance_filters = defaultdict(list)
if config.has_option('ec2', 'instance_filters'):
filters = [f for f in config.get('ec2', 'instance_filters').split(',') if f]
for instance_filter in filters:
for instance_filter in config.get('ec2', 'instance_filters', '').split(','):
instance_filter = instance_filter.strip()
if not instance_filter or '=' not in instance_filter:
continue
@ -513,14 +491,9 @@ class Ec2Inventory(object):
try:
conn = self.connect_to_aws(rds, region)
if conn:
marker = None
while True:
instances = conn.get_all_dbinstances(marker=marker)
marker = instances.marker
for instance in instances:
self.add_rds_instance(instance, region)
if not marker:
break
instances = conn.get_all_dbinstances()
for instance in instances:
self.add_rds_instance(instance, region)
except boto.exception.BotoServerError as e:
error = e.reason
@ -538,7 +511,7 @@ class Ec2Inventory(object):
# that's why we need to call describe directly (it would be called by
# the shorthand method anyway...)
try:
conn = self.connect_to_aws(elasticache, region)
conn = elasticache.connect_to_region(region)
if conn:
# show_cache_node_info = True
# because we also want nodes' information
@ -574,7 +547,7 @@ class Ec2Inventory(object):
# that's why we need to call describe directly (it would be called by
# the shorthand method anyway...)
try:
conn = self.connect_to_aws(elasticache, region)
conn = elasticache.connect_to_region(region)
if conn:
response = conn.describe_replication_groups()
@ -642,9 +615,7 @@ class Ec2Inventory(object):
return
# Select the best destination address
if self.destination_format and self.destination_format_tags:
dest = self.destination_format.format(*[ getattr(instance, 'tags').get(tag, '') for tag in self.destination_format_tags ])
elif instance.subnet_id:
if instance.subnet_id:
dest = getattr(instance, self.vpc_destination_variable, None)
if dest is None:
dest = getattr(instance, 'tags').get(self.vpc_destination_variable, None)
@ -657,46 +628,32 @@ class Ec2Inventory(object):
# Skip instances we cannot address (e.g. private VPC subnet)
return
# Set the inventory name
hostname = None
if self.hostname_variable:
if self.hostname_variable.startswith('tag_'):
hostname = instance.tags.get(self.hostname_variable[4:], None)
else:
hostname = getattr(instance, self.hostname_variable)
# If we can't get a nice hostname, use the destination address
if not hostname:
hostname = dest
else:
hostname = self.to_safe(hostname).lower()
# if we only want to include hosts that match a pattern, skip those that don't
if self.pattern_include and not self.pattern_include.match(hostname):
if self.pattern_include and not self.pattern_include.match(dest):
return
# if we need to exclude hosts that match a pattern, skip those
if self.pattern_exclude and self.pattern_exclude.match(hostname):
if self.pattern_exclude and self.pattern_exclude.match(dest):
return
# Add to index
self.index[hostname] = [region, instance.id]
self.index[dest] = [region, instance.id]
# Inventory: Group by instance ID (always a group of 1)
if self.group_by_instance_id:
self.inventory[instance.id] = [hostname]
self.inventory[instance.id] = [dest]
if self.nested_groups:
self.push_group(self.inventory, 'instances', instance.id)
# Inventory: Group by region
if self.group_by_region:
self.push(self.inventory, region, hostname)
self.push(self.inventory, region, dest)
if self.nested_groups:
self.push_group(self.inventory, 'regions', region)
# Inventory: Group by availability zone
if self.group_by_availability_zone:
self.push(self.inventory, instance.placement, hostname)
self.push(self.inventory, instance.placement, dest)
if self.nested_groups:
if self.group_by_region:
self.push_group(self.inventory, region, instance.placement)
@ -705,28 +662,28 @@ class Ec2Inventory(object):
# Inventory: Group by Amazon Machine Image (AMI) ID
if self.group_by_ami_id:
ami_id = self.to_safe(instance.image_id)
self.push(self.inventory, ami_id, hostname)
self.push(self.inventory, ami_id, dest)
if self.nested_groups:
self.push_group(self.inventory, 'images', ami_id)
# Inventory: Group by instance type
if self.group_by_instance_type:
type_name = self.to_safe('type_' + instance.instance_type)
self.push(self.inventory, type_name, hostname)
self.push(self.inventory, type_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'types', type_name)
# Inventory: Group by key pair
if self.group_by_key_pair and instance.key_name:
key_name = self.to_safe('key_' + instance.key_name)
self.push(self.inventory, key_name, hostname)
self.push(self.inventory, key_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'keys', key_name)
# Inventory: Group by VPC
if self.group_by_vpc_id and instance.vpc_id:
vpc_id_name = self.to_safe('vpc_id_' + instance.vpc_id)
self.push(self.inventory, vpc_id_name, hostname)
self.push(self.inventory, vpc_id_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'vpcs', vpc_id_name)
@ -735,7 +692,7 @@ class Ec2Inventory(object):
try:
for group in instance.groups:
key = self.to_safe("security_group_" + group.name)
self.push(self.inventory, key, hostname)
self.push(self.inventory, key, dest)
if self.nested_groups:
self.push_group(self.inventory, 'security_groups', key)
except AttributeError:
@ -755,7 +712,7 @@ class Ec2Inventory(object):
key = self.to_safe("tag_" + k + "=" + v)
else:
key = self.to_safe("tag_" + k)
self.push(self.inventory, key, hostname)
self.push(self.inventory, key, dest)
if self.nested_groups:
self.push_group(self.inventory, 'tags', self.to_safe("tag_" + k))
if v:
@ -765,21 +722,20 @@ class Ec2Inventory(object):
if self.route53_enabled and self.group_by_route53_names:
route53_names = self.get_instance_route53_names(instance)
for name in route53_names:
self.push(self.inventory, name, hostname)
self.push(self.inventory, name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'route53', name)
# Global Tag: instances without tags
if self.group_by_tag_none and len(instance.tags) == 0:
self.push(self.inventory, 'tag_none', hostname)
self.push(self.inventory, 'tag_none', dest)
if self.nested_groups:
self.push_group(self.inventory, 'tags', 'tag_none')
# Global Tag: tag all EC2 instances
self.push(self.inventory, 'ec2', hostname)
self.push(self.inventory, 'ec2', dest)
self.inventory["_meta"]["hostvars"][hostname] = self.get_host_info_dict_from_instance(instance)
self.inventory["_meta"]["hostvars"][hostname]['ansible_ssh_host'] = dest
self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance)
def add_rds_instance(self, instance, region):
@ -797,38 +753,24 @@ class Ec2Inventory(object):
# Skip instances we cannot address (e.g. private VPC subnet)
return
# Set the inventory name
hostname = None
if self.hostname_variable:
if self.hostname_variable.startswith('tag_'):
hostname = instance.tags.get(self.hostname_variable[4:], None)
else:
hostname = getattr(instance, self.hostname_variable)
# If we can't get a nice hostname, use the destination address
if not hostname:
hostname = dest
hostname = self.to_safe(hostname).lower()
# Add to index
self.index[hostname] = [region, instance.id]
self.index[dest] = [region, instance.id]
# Inventory: Group by instance ID (always a group of 1)
if self.group_by_instance_id:
self.inventory[instance.id] = [hostname]
self.inventory[instance.id] = [dest]
if self.nested_groups:
self.push_group(self.inventory, 'instances', instance.id)
# Inventory: Group by region
if self.group_by_region:
self.push(self.inventory, region, hostname)
self.push(self.inventory, region, dest)
if self.nested_groups:
self.push_group(self.inventory, 'regions', region)
# Inventory: Group by availability zone
if self.group_by_availability_zone:
self.push(self.inventory, instance.availability_zone, hostname)
self.push(self.inventory, instance.availability_zone, dest)
if self.nested_groups:
if self.group_by_region:
self.push_group(self.inventory, region, instance.availability_zone)
@ -837,14 +779,14 @@ class Ec2Inventory(object):
# Inventory: Group by instance type
if self.group_by_instance_type:
type_name = self.to_safe('type_' + instance.instance_class)
self.push(self.inventory, type_name, hostname)
self.push(self.inventory, type_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'types', type_name)
# Inventory: Group by VPC
if self.group_by_vpc_id and instance.subnet_group and instance.subnet_group.vpc_id:
vpc_id_name = self.to_safe('vpc_id_' + instance.subnet_group.vpc_id)
self.push(self.inventory, vpc_id_name, hostname)
self.push(self.inventory, vpc_id_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'vpcs', vpc_id_name)
@ -853,7 +795,7 @@ class Ec2Inventory(object):
try:
if instance.security_group:
key = self.to_safe("security_group_" + instance.security_group.name)
self.push(self.inventory, key, hostname)
self.push(self.inventory, key, dest)
if self.nested_groups:
self.push_group(self.inventory, 'security_groups', key)
@ -864,21 +806,20 @@ class Ec2Inventory(object):
# Inventory: Group by engine
if self.group_by_rds_engine:
self.push(self.inventory, self.to_safe("rds_" + instance.engine), hostname)
self.push(self.inventory, self.to_safe("rds_" + instance.engine), dest)
if self.nested_groups:
self.push_group(self.inventory, 'rds_engines', self.to_safe("rds_" + instance.engine))
# Inventory: Group by parameter group
if self.group_by_rds_parameter_group:
self.push(self.inventory, self.to_safe("rds_parameter_group_" + instance.parameter_group.name), hostname)
self.push(self.inventory, self.to_safe("rds_parameter_group_" + instance.parameter_group.name), dest)
if self.nested_groups:
self.push_group(self.inventory, 'rds_parameter_groups', self.to_safe("rds_parameter_group_" + instance.parameter_group.name))
# Global Tag: all RDS instances
self.push(self.inventory, 'rds', hostname)
self.push(self.inventory, 'rds', dest)
self.inventory["_meta"]["hostvars"][hostname] = self.get_host_info_dict_from_instance(instance)
self.inventory["_meta"]["hostvars"][hostname]['ansible_ssh_host'] = dest
self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance)
def add_elasticache_cluster(self, cluster, region):
''' Adds an ElastiCache cluster to the inventory and index, as long as

View File

@ -45,11 +45,3 @@ gce_service_account_email_address =
gce_service_account_pem_file_path =
gce_project_id =
[inventory]
# The 'inventory_ip_type' parameter specifies whether 'ansible_ssh_host' should
# contain the instance internal or external address. Values may be either
# 'internal' or 'external'. If 'external' is specified but no external instance
# address exists, the internal address will be used.
# The INVENTORY_IP_TYPE environment variable will override this value.
inventory_ip_type =

View File

@ -69,8 +69,7 @@ Examples:
$ contrib/inventory/gce.py --host my_instance
Author: Eric Johnson <erjohnso@google.com>
Contributors: Matt Hite <mhite@hotmail.com>
Version: 0.0.2
Version: 0.0.1
'''
__requires__ = ['pycrypto>=2.6']
@ -84,16 +83,13 @@ except ImportError:
pass
USER_AGENT_PRODUCT="Ansible-gce_inventory_plugin"
USER_AGENT_VERSION="v2"
USER_AGENT_VERSION="v1"
import sys
import os
import argparse
import ConfigParser
import logging
logging.getLogger('libcloud.common.google').addHandler(logging.NullHandler())
try:
import json
except ImportError:
@ -112,11 +108,7 @@ class GceInventory(object):
def __init__(self):
# Read settings and parse CLI arguments
self.parse_cli_args()
self.config = self.get_config()
self.driver = self.get_gce_driver()
self.ip_type = self.get_inventory_options()
if self.ip_type:
self.ip_type = self.ip_type.lower()
# Just display data for specific host
if self.args.host:
@ -130,13 +122,9 @@ class GceInventory(object):
pretty=self.args.pretty))
sys.exit(0)
def get_config(self):
"""
Populates a SafeConfigParser object with defaults and
attempts to read an .ini-style configuration from the filename
specified in GCE_INI_PATH. If the environment variable is
not present, the filename defaults to gce.ini in the current
working directory.
def get_gce_driver(self):
"""Determine the GCE authorization settings and return a
libcloud driver.
"""
gce_ini_default_path = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "gce.ini")
@ -151,32 +139,14 @@ class GceInventory(object):
'gce_service_account_pem_file_path': '',
'gce_project_id': '',
'libcloud_secrets': '',
'inventory_ip_type': '',
})
if 'gce' not in config.sections():
config.add_section('gce')
if 'inventory' not in config.sections():
config.add_section('inventory')
config.read(gce_ini_path)
return config
def get_inventory_options(self):
"""Determine inventory options. Environment variables always
take precedence over configuration files."""
ip_type = self.config.get('inventory', 'inventory_ip_type')
# If the appropriate environment variables are set, they override
# other configuration
ip_type = os.environ.get('INVENTORY_IP_TYPE', ip_type)
return ip_type
def get_gce_driver(self):
"""Determine the GCE authorization settings and return a
libcloud driver.
"""
# Attempt to get GCE params from a configuration file, if one
# exists.
secrets_path = self.config.get('gce', 'libcloud_secrets')
secrets_path = config.get('gce', 'libcloud_secrets')
secrets_found = False
try:
import secrets
@ -202,10 +172,10 @@ class GceInventory(object):
pass
if not secrets_found:
args = [
self.config.get('gce','gce_service_account_email_address'),
self.config.get('gce','gce_service_account_pem_file_path')
config.get('gce','gce_service_account_email_address'),
config.get('gce','gce_service_account_pem_file_path')
]
kwargs = {'project': self.config.get('gce', 'gce_project_id')}
kwargs = {'project': config.get('gce', 'gce_project_id')}
# If the appropriate environment variables are set, they override
# other configuration; process those into our args and kwargs.
@ -245,12 +215,6 @@ class GceInventory(object):
md[entry['key']] = entry['value']
net = inst.extra['networkInterfaces'][0]['network'].split('/')[-1]
# default to exernal IP unless user has specified they prefer internal
if self.ip_type == 'internal':
ssh_host = inst.private_ips[0]
else:
ssh_host = inst.public_ips[0] if len(inst.public_ips) >= 1 else inst.private_ips[0]
return {
'gce_uuid': inst.uuid,
'gce_id': inst.id,
@ -266,7 +230,7 @@ class GceInventory(object):
'gce_metadata': md,
'gce_network': net,
# Hosts don't have a public name, so we add an IP
'ansible_ssh_host': ssh_host
'ansible_ssh_host': inst.public_ips[0] if len(inst.public_ips) >= 1 else inst.private_ips[0]
}
def get_instance(self, instance_name):

View File

@ -280,11 +280,6 @@ class LinodeInventory(object):
node_vars["datacenter_city"] = self.get_datacenter_city(node)
node_vars["public_ip"] = [addr.address for addr in node.ipaddresses if addr.is_public][0]
# Set the SSH host information, so these inventory items can be used if
# their labels aren't FQDNs
node_vars['ansible_ssh_host'] = node_vars["public_ip"]
node_vars['ansible_host'] = node_vars["public_ip"]
private_ips = [addr.address for addr in node.ipaddresses if not addr.is_public]
if private_ips:

View File

@ -55,7 +55,7 @@ import os_client_config
import shade
import shade.inventory
CONFIG_FILES = ['/etc/ansible/openstack.yaml', '/etc/ansible/openstack.yml']
CONFIG_FILES = ['/etc/ansible/openstack.yaml']
def get_groups_from_server(server_vars, namegroup=True):
@ -112,14 +112,6 @@ def get_host_groups(inventory, refresh=False):
return groups
def append_hostvars(hostvars, groups, key, server, namegroup=False):
hostvars[key] = dict(
ansible_ssh_host=server['interface_ip'],
openstack=server)
for group in get_groups_from_server(server, namegroup=namegroup):
groups[group].append(key)
def get_host_groups_from_cloud(inventory):
groups = collections.defaultdict(list)
firstpass = collections.defaultdict(list)
@ -138,19 +130,20 @@ def get_host_groups_from_cloud(inventory):
firstpass[server['name']].append(server)
for name, servers in firstpass.items():
if len(servers) == 1 and use_hostnames:
append_hostvars(hostvars, groups, name, servers[0])
server = servers[0]
hostvars[name] = dict(
ansible_ssh_host=server['interface_ip'],
openstack=server)
for group in get_groups_from_server(server, namegroup=False):
groups[group].append(server['name'])
else:
server_ids = set()
# Trap for duplicate results
for server in servers:
server_ids.add(server['id'])
if len(server_ids) == 1 and use_hostnames:
append_hostvars(hostvars, groups, name, servers[0])
else:
for server in servers:
append_hostvars(
hostvars, groups, server['id'], server,
namegroup=True)
server_id = server['id']
hostvars[server_id] = dict(
ansible_ssh_host=server['interface_ip'],
openstack=server)
for group in get_groups_from_server(server, namegroup=True):
groups[group].append(server_id)
groups['_meta'] = {'hostvars': hostvars}
return groups
@ -159,7 +152,7 @@ def is_cache_stale(cache_file, cache_expiration_time, refresh=False):
''' Determines if cache file has expired, or if it is still valid '''
if refresh:
return True
if os.path.isfile(cache_file) and os.path.getsize(cache_file) > 0:
if os.path.isfile(cache_file):
mod_time = os.path.getmtime(cache_file)
current_time = time.time()
if (mod_time + cache_expiration_time) > current_time:

View File

@ -172,9 +172,9 @@ class OVirtInventory(object):
# If the appropriate environment variables are set, they override
# other configuration; process those into our args and kwargs.
kwargs['url'] = os.environ.get('OVIRT_URL', kwargs['url'])
kwargs['username'] = next(val for val in [os.environ.get('OVIRT_EMAIL'), os.environ.get('OVIRT_USERNAME'), kwargs['username']] if val is not None)
kwargs['password'] = next(val for val in [os.environ.get('OVIRT_PASS'), os.environ.get('OVIRT_PASSWORD'), kwargs['password']] if val is not None)
kwargs['url'] = os.environ.get('OVIRT_URL')
kwargs['username'] = os.environ.get('OVIRT_EMAIL')
kwargs['password'] = os.environ.get('OVIRT_PASS')
# Retrieve and return the ovirt driver.
return API(insecure=True, **kwargs)

View File

@ -15,16 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Updated 2016 by Matt Harris <matthaeus.harris@gmail.com>
#
# Added support for Proxmox VE 4.x
# Added support for using the Notes field of a VM to define groups and variables:
# A well-formatted JSON object in the Notes field will be added to the _meta
# section for that VM. In addition, the "groups" key of this JSON object may be
# used to specify group membership:
#
# { "groups": ["utility", "databases"], "a": false, "b": true }
import urllib
try:
import json
@ -42,29 +32,29 @@ class ProxmoxNodeList(list):
def get_names(self):
return [node['node'] for node in self]
class ProxmoxVM(dict):
class ProxmoxQemu(dict):
def get_variables(self):
variables = {}
for key, value in iteritems(self):
variables['proxmox_' + key] = value
return variables
class ProxmoxVMList(list):
class ProxmoxQemuList(list):
def __init__(self, data=[]):
for item in data:
self.append(ProxmoxVM(item))
self.append(ProxmoxQemu(item))
def get_names(self):
return [vm['name'] for vm in self if vm['template'] != 1]
return [qemu['name'] for qemu in self if qemu['template'] != 1]
def get_by_name(self, name):
results = [vm for vm in self if vm['name'] == name]
results = [qemu for qemu in self if qemu['name'] == name]
return results[0] if len(results) > 0 else None
def get_variables(self):
variables = {}
for vm in self:
variables[vm['name']] = vm.get_variables()
for qemu in self:
variables[qemu['name']] = qemu.get_variables()
return variables
@ -115,23 +105,8 @@ class ProxmoxAPI(object):
def nodes(self):
return ProxmoxNodeList(self.get('api2/json/nodes'))
def vms_by_type(self, node, type):
return ProxmoxVMList(self.get('api2/json/nodes/{}/{}'.format(node, type)))
def vm_description_by_type(self, node, vm, type):
return self.get('api2/json/nodes/{}/{}/{}/config'.format(node, type, vm))
def node_qemu(self, node):
return self.vms_by_type(node, 'qemu')
def node_qemu_description(self, node, vm):
return self.vm_description_by_type(node, vm, 'qemu')
def node_lxc(self, node):
return self.vms_by_type(node, 'lxc')
def node_lxc_description(self, node, vm):
return self.vm_description_by_type(node, vm, 'lxc')
return ProxmoxQemuList(self.get('api2/json/nodes/{}/qemu'.format(node)))
def pools(self):
return ProxmoxPoolList(self.get('api2/json/pools'))
@ -156,40 +131,6 @@ def main_list(options):
qemu_list = proxmox_api.node_qemu(node)
results['all']['hosts'] += qemu_list.get_names()
results['_meta']['hostvars'].update(qemu_list.get_variables())
lxc_list = proxmox_api.node_lxc(node)
results['all']['hosts'] += lxc_list.get_names()
results['_meta']['hostvars'].update(lxc_list.get_variables())
for vm in results['_meta']['hostvars']:
vmid = results['_meta']['hostvars'][vm]['proxmox_vmid']
try:
type = results['_meta']['hostvars'][vm]['proxmox_type']
except KeyError:
type = 'qemu'
try:
description = proxmox_api.vm_description_by_type(node, vmid, type)['description']
except KeyError:
description = None
try:
metadata = json.loads(description)
except TypeError:
metadata = {}
except ValueError:
metadata = {
'notes': description
}
if 'groups' in metadata:
# print metadata
for group in metadata['groups']:
if group not in results:
results[group] = {
'hosts': []
}
results[group]['hosts'] += [vm]
results['_meta']['hostvars'][vm].update(metadata)
# pools
for pool in proxmox_api.pools().get_names():

View File

@ -1,80 +0,0 @@
#!/usr/bin/python
import json
import requests
import os
import argparse
import types
RACKHD_URL = 'http://localhost:8080'
class RackhdInventory(object):
def __init__(self, nodeids):
self._inventory = {}
for nodeid in nodeids:
self._load_inventory_data(nodeid)
inventory = {}
for nodeid,info in self._inventory.iteritems():
inventory[nodeid]= (self._format_output(nodeid, info))
print(json.dumps(inventory))
def _load_inventory_data(self, nodeid):
info = {}
info['ohai'] = RACKHD_URL + '/api/common/nodes/{0}/catalogs/ohai'.format(nodeid )
info['lookup'] = RACKHD_URL + '/api/common/lookups/?q={0}'.format(nodeid)
results = {}
for key,url in info.iteritems():
r = requests.get( url, verify=False)
results[key] = r.text
self._inventory[nodeid] = results
def _format_output(self, nodeid, info):
try:
node_info = json.loads(info['lookup'])
ipaddress = ''
if len(node_info) > 0:
ipaddress = node_info[0]['ipAddress']
output = { 'hosts':[ipaddress],'vars':{}}
for key,result in info.iteritems():
output['vars'][key] = json.loads(result)
output['vars']['ansible_ssh_user'] = 'monorail'
except KeyError:
pass
return output
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('--host')
parser.add_argument('--list', action='store_true')
return parser.parse_args()
try:
#check if rackhd url(ie:10.1.1.45:8080) is specified in the environment
RACKHD_URL = 'http://' + str(os.environ['RACKHD_URL'])
except:
#use default values
pass
# Use the nodeid specified in the environment to limit the data returned
# or return data for all available nodes
nodeids = []
if (parse_args().host):
try:
nodeids += parse_args().host.split(',')
RackhdInventory(nodeids)
except:
pass
if (parse_args().list):
try:
url = RACKHD_URL + '/api/common/nodes'
r = requests.get( url, verify=False)
data = json.loads(r.text)
for entry in data:
if entry['type'] == 'compute':
nodeids.append(entry['id'])
RackhdInventory(nodeids)
except:
pass

View File

@ -55,12 +55,3 @@
# will be ignored, and 4 will be used. Accepts a comma separated list,
# the first found wins.
# access_ip_version = 4
# Environment Variable: RAX_CACHE_MAX_AGE
# Default: 600
#
# A configuration the changes the behavior or the inventory cache.
# Inventory listing performed before this value will be returned from
# the cache instead of making a full request for all inventory. Setting
# this value to 0 will force a full request.
# cache_max_age = 600

View File

@ -355,12 +355,9 @@ def get_cache_file_path(regions):
def _list(regions, refresh_cache=True):
cache_max_age = int(get_config(p, 'rax', 'cache_max_age',
'RAX_CACHE_MAX_AGE', 600))
if (not os.path.exists(get_cache_file_path(regions)) or
refresh_cache or
(time() - os.stat(get_cache_file_path(regions))[-1]) > cache_max_age):
(time() - os.stat(get_cache_file_path(regions))[-1]) > 600):
# Cache file doesn't exist or older than 10m or refresh cache requested
_list_into_cache(regions)

View File

@ -70,7 +70,7 @@ if not os.path.exists(SW_REPORT):
# Pre-startup work
if not os.path.exists(CACHE_DIR):
os.mkdir(CACHE_DIR)
os.chmod(CACHE_DIR, 0o2775)
os.chmod(CACHE_DIR, 2775)
# Helper functions
#------------------------------

View File

@ -47,9 +47,13 @@ except ImportError:
import simplejson as json
try:
import azure
from azure import WindowsAzureError
from azure.servicemanagement import ServiceManagementService
except ImportError as e:
sys.exit("ImportError: {0}".format(str(e)))
print("failed=True msg='`azure` library required for this script'")
sys.exit(1)
# Imports for ansible
import ConfigParser
@ -190,8 +194,11 @@ class AzureInventory(object):
try:
for cloud_service in self.sms.list_hosted_services():
self.add_deployments(cloud_service)
except Exception as e:
sys.exit("Error: Failed to access cloud services - {0}".format(str(e)))
except WindowsAzureError as e:
print("Looks like Azure's API is down:")
print("")
print(e)
sys.exit(1)
def add_deployments(self, cloud_service):
"""Makes an Azure API call to get the list of virtual machines
@ -200,8 +207,11 @@ class AzureInventory(object):
try:
for deployment in self.sms.get_hosted_service_properties(cloud_service.service_name,embed_detail=True).deployments.deployments:
self.add_deployment(cloud_service, deployment)
except Exception as e:
sys.exit("Error: Failed to access deployments - {0}".format(str(e)))
except WindowsAzureError as e:
print("Looks like Azure's API is down:")
print("")
print(e)
sys.exit(1)
def add_deployment(self, cloud_service, deployment):
"""Adds a deployment to the inventory and index"""

View File

@ -1,77 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# (c) 2014, Matt Martz <matt@sivel.net>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
#
# Script to be used with vault_password_file or --vault-password-file
# to retrieve the vault password via your OSes native keyring application
#
# This script requires the ``keyring`` python module
#
# Add a [vault] section to your ansible.cfg file,
# the only option is 'username'. Example:
#
# [vault]
# username = 'ansible_vault'
#
# Additionally, it would be a good idea to configure vault_password_file in
# ansible.cfg
#
# [defaults]
# ...
# vault_password_file = /path/to/vault-keyring.py
# ...
#
# To set your password: python /path/to/vault-keyring.py set
#
# If you choose to not configure the path to vault_password_file in ansible.cfg
# your ansible-playbook command may look like:
#
# ansible-playbook --vault-password-file=/path/to/vault-keyring.py site.yml
import sys
import getpass
import keyring
import ansible.constants as C
def main():
parser = C.load_config_file()
try:
username = parser.get('vault', 'username')
except:
sys.stderr.write('No [vault] section configured\n')
sys.exit(1)
if len(sys.argv) == 2 and sys.argv[1] == 'set':
password = getpass.getpass()
confirm = getpass.getpass('Confirm password: ')
if password == confirm:
keyring.set_password('ansible', username, password)
else:
sys.stderr.write('Passwords do not match\n')
sys.exit(1)
else:
sys.stdout.write('%s\n' % keyring.get_password('ansible', username))
sys.exit(0)
if __name__ == '__main__':
main()

View File

@ -34,12 +34,7 @@ The names of one or more YAML format files to run as ansible playbooks.
OPTIONS
-------
*-b*, *--become*::
Use privilege escalation (specific one depends on become_method),
this does not imply prompting for passwords.
*-K*, *--ask-become-pass*::
*--ask-become-pass*::
Ask for privilege escalation password.
@ -52,7 +47,7 @@ For example, using ssh and not having a key-based authentication with ssh-agent
Prompt for su password, used with --su (deprecated, use become).
*--ask-sudo-pass*::
*-K*, *--ask-sudo-pass*::
Prompt for the password to use with --sudo, if any (deprecated, use become).
@ -106,7 +101,7 @@ Alternatively, you can use a comma-separated list of hosts or a single host with
*-l* 'SUBSET', *--limit=*'SUBSET'::
Further limits the selected host/group patterns.
You can prefix it with '~' to indicate that the pattern is a regex.
You can prefix it with '~' to indicate that the pattern in a regex.
*--list-hosts*::
@ -130,6 +125,10 @@ environment variable.
Use this file to authenticate the connection
*--skip-tages=*'SKIP_TAGS'::
Only run plays and tasks whose tags do not match these values.
*--start-at-task=*'START_AT'::
Start the playbook at the task matching this name.
@ -170,7 +169,7 @@ Add the specified arguments to any ssh command-line.
*-U* 'SUDO_USERNAME', *--sudo-user=*'SUDO_USERNAME'::
Sudo to 'SUDO_USERNAME' default is root. (deprecated, use become).
Sudo to 'SUDO_USERNAME' deafult is root. (deprecated, use become).
*--skip-tags=*'SKIP_TAGS'::
@ -205,24 +204,6 @@ up to three times for more output.
Show program's version number and exit.
EXIT STATUS
-----------
*0* -- OK or no hosts matched
*1* -- Error
*2* -- One or more hosts failed
*3* -- One or more hosts were unreachable
*4* -- Parser error
*5* -- Bad or incomplete options
*99* -- User interrupted execution
*250* -- Unexpected error
ENVIRONMENT
-----------

View File

@ -54,12 +54,7 @@ OPTIONS
Adds the hostkey for the repo URL if not already added.
*-b*, *--become*::
Use privilege escalation (specific one depends on become_method),
this does not imply prompting for passwords.
*-K*, *--ask-become-pass*::
*--ask-become-pass*::
Ask for privilege escalation password.
@ -72,7 +67,7 @@ For example, using ssh and not having a key-based authentication with ssh-agent
Prompt for su password, used with --su (deprecated, use become).
*--ask-sudo-pass*::
*-K*, *--ask-sudo-pass*::
Prompt for the password to use with --sudo, if any (deprecated, use become).

View File

@ -63,7 +63,7 @@ CREATE
The *create* sub-command is used to initialize a new encrypted file.
After providing a password, the tool will launch whatever editor you have defined
with $EDITOR, and defaults to vi. Once you are done with the editor session, the
with $EDITOR, and defaults to vim. Once you are done with the editor session, the
file will be saved as encrypted data.
The default cipher is AES (which is shared-secret based).

View File

@ -37,12 +37,7 @@ OPTIONS
The 'ARGUMENTS' to pass to the module.
*-b*, *--become*::
Use privilege escalation (specific one depends on become_method),
this does not imply prompting for passwords.
*-K*, *--ask-become-pass*::
*--ask-become-pass*::
Ask for privilege escalation password.
@ -55,7 +50,7 @@ For example, using ssh and not having a key-based authentication with ssh-agent
Prompt for su password, used with --su (deprecated, use become).
*--ask-sudo-pass*::
*-K*, *--ask-sudo-pass*::
Prompt for the password to use with --sudo, if any (deprecated, use become).
@ -70,7 +65,7 @@ Run commands in the background, killing the task after 'NUM' seconds.
*--become-method=*'BECOME_METHOD'::
Privilege escalation method to use (default=sudo),
valid choices: [ sudo | su | pbrun | pfexec | runas | doas | dzdo ]
valid choices: [ sudo | su | pbrun | pfexec | runas | doas ]
*--become-user=*'BECOME_USER'::
@ -109,7 +104,7 @@ Alternatively you can use a comma separated list of hosts or single host with tr
*-l* 'SUBSET', *--limit=*'SUBSET'::
Further limits the selected host/group patterns.
You can prefix it with '~' to indicate that the pattern is a regex.
You can prefix it with '~' to indicate that the patter in a regex.
*--list-hosts*::

View File

@ -1,11 +1,10 @@
#!/usr/bin/make
SITELIB = $(shell python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
FORMATTER=../hacking/module_formatter.py
DUMPER=../hacking/dump_playbook_attributes.py
all: clean docs
docs: clean directives modules staticmin
docs: clean modules staticmin
./build-site.py
-(cp *.ico htmlout/)
-(cp *.jpg htmlout/)
@ -42,11 +41,8 @@ clean:
.PHONEY: docs clean
directives: $(FORMATTER) ../hacking/templates/rst.j2
PYTHONPATH=../lib $(DUMPER) --template-dir=../hacking/templates --output-dir=rst/
modules: $(FORMATTER) ../hacking/templates/rst.j2
PYTHONPATH=../lib $(FORMATTER) -t rst --template-dir=../hacking/templates --module-dir=../lib/ansible/modules -o rst/
staticmin:
cat _themes/srtd/static/css/theme.css | sed -e 's/^[ ]*//g; s/[ ]*$$//g; s/\([:{;,]\) /\1/g; s/ {/{/g; s/\/\*.*\*\///g; /^$$/d' | sed -e :a -e '$$!N; s/\n\(.\)/\1/; ta' > _themes/srtd/static/css/theme.min.css
cat _themes/srtd/static/css/theme.css | sed -e 's/^[ \t]*//g; s/[ \t]*$$//g; s/\([:{;,]\) /\1/g; s/ {/{/g; s/\/\*.*\*\///g; /^$$/d' | sed -e :a -e '$$!N; s/\n\(.\)/\1/; ta' > _themes/srtd/static/css/theme.min.css

View File

@ -12,17 +12,8 @@
<hr/>
<script type="text/javascript">
(function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
(w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
})(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
_st('install','yABGvz2N8PwcwBxyfzUc','2.0.0');
</script>
<p>
&copy; Copyright 2016 <a href="http://ansible.com">Ansible, Inc.</a>.
&copy; Copyright 2015 <a href="http://ansible.com">Ansible, Inc.</a>.
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}

View File

@ -150,6 +150,11 @@
</a>
</div>
<div class="wy-side-nav-search" style="background-color:#5bbdbf;height=80px;margin:'auto auto auto auto'">
<!-- <a href="{{ pathto(master_doc) }}" class="icon icon-home"> {{ project }}</a> -->
{% include "searchbox.html" %}
</div>
<div id="menu-id" class="wy-menu wy-menu-vertical" data-spy="affix">
{% set toctree = toctree(maxdepth=2, collapse=False) %}
{% if toctree %}
@ -161,9 +166,16 @@
<!-- changeable widget -->
<center>
<br/>
<a href="http://www.ansible.com/docs-left?utm_source=docs">
<img style="border-width:0px;" src="https://cdn2.hubspot.net/hubfs/330046/docs-graphics/ASB-docs-left-rail.png" />
</a>
<span class="hs-cta-wrapper" id="hs-cta-wrapper-71d47584-8ef5-4b06-87ae-8d25bc2a837e">
<span class="hs-cta-node hs-cta-71d47584-8ef5-4b06-87ae-8d25bc2a837e" id="hs-cta-71d47584-8ef5-4b06-87ae-8d25bc2a837e">
<!--[if lte IE 8]><div id="hs-cta-ie-element"></div><![endif]-->
<a href="http://cta-redirect.hubspot.com/cta/redirect/330046/71d47584-8ef5-4b06-87ae-8d25bc2a837e"><img class="hs-cta-img" id="hs-cta-img-71d47584-8ef5-4b06-87ae-8d25bc2a837e" style="border-width:0px;" src="https://no-cache.hubspot.com/cta/default/330046/71d47584-8ef5-4b06-87ae-8d25bc2a837e.png" /></a>
</span>
<script charset="utf-8" src="https://js.hscta.net/cta/current.js"></script>
<script type="text/javascript">
hbspt.cta.load(330046, '71d47584-8ef5-4b06-87ae-8d25bc2a837e');
</script>
</span>
</center>
@ -184,17 +196,15 @@
<div class="wy-nav-content">
<div class="rst-content">
<!-- Banner ads -->
<div class="DocSiteBanner">
<a class="DocSiteBanner-imgWrapper"
href="http://www.ansible.com/docs-top?utm_source=docs">
<img src="https://cdn2.hubspot.net/hubfs/330046/docs-graphics/ASB-docs-top-left.png">
</a>
<a class="DocSiteBanner-imgWrapper"
href="http://www.ansible.com/docs-top?utm_source=docs">
<img src="https://cdn2.hubspot.net/hubfs/330046/docs-graphics/ASB-docs-top-right.png">
</a>
</div>
<!-- Tower ads -->
<a class="DocSiteBanner" href="http://www.ansible.com/tower?utm_source=docs">
<div class="DocSiteBanner-imgWrapper">
<img src="{{ pathto('_static/', 1) }}images/banner_ad_1.png">
</div>
<div class="DocSiteBanner-imgWrapper">
<img src="{{ pathto('_static/', 1) }}images/banner_ad_2.png">
</div>
</a>
{% include "breadcrumbs.html" %}
<div id="page-content">

View File

@ -0,0 +1,205 @@
{#
basic/layout.html
~~~~~~~~~~~~~~~~~
Master layout template for Sphinx themes.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- block doctype -%}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
{%- endblock %}
{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
(sidebars != []) %}
{%- set url_root = pathto('', 1) %}
{# XXX necessary? #}
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
{%- if not embedded and docstitle %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %}
{%- macro relbar() %}
<div class="related">
<h3>{{ _('Navigation') }}</h3>
<ul>
{%- for rellink in rellinks %}
<li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
{%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
{%- endfor %}
{%- block rootrellink %}
<li><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
{%- endblock %}
{%- for parent in parents %}
<li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
{%- endfor %}
{%- block relbaritems %} {% endblock %}
</ul>
</div>
{%- endmacro %}
{%- macro sidebar() %}
{%- if render_sidebar %}
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
{%- block sidebarlogo %}
{%- if logo %}
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
</a></p>
{%- endif %}
{%- endblock %}
{%- if sidebars != None %}
{#- new style sidebar: explicitly include/exclude templates #}
{%- for sidebartemplate in sidebars %}
{%- include sidebartemplate %}
{%- endfor %}
{%- else %}
{#- old style sidebars: using blocks -- should be deprecated #}
{%- block sidebartoc %}
{%- include "localtoc.html" %}
{%- endblock %}
{%- block sidebarrel %}
{%- include "relations.html" %}
{%- endblock %}
{%- block sidebarsourcelink %}
{%- include "sourcelink.html" %}
{%- endblock %}
{%- if customsidebar %}
{%- include customsidebar %}
{%- endif %}
{%- block sidebarsearch %}
{%- include "searchbox.html" %}
{%- endblock %}
{%- endif %}
</div>
</div>
{%- endif %}
{%- endmacro %}
{%- macro script() %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ url_root }}',
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{%- endmacro %}
{%- macro css() %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
{%- for cssfile in css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{%- endfor %}
{%- endmacro %}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
{{ metatags }}
{%- block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
{%- endblock %}
{{ css() }}
{%- if not embedded %}
{{ script() }}
{%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{%- endif %}
{%- if favicon %}
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
{%- endif %}
{%- endif %}
{%- block linktags %}
{%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
{%- endif %}
{%- if hasdoc('genindex') %}
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
{%- endif %}
{%- if hasdoc('search') %}
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
{%- endif %}
{%- if hasdoc('copyright') %}
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
{%- endif %}
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
{%- if parents %}
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
{%- endif %}
{%- if next %}
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
{%- endif %}
{%- if prev %}
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
<body>
{%- block header %}{% endblock %}
{%- block relbar1 %}{{ relbar() }}{% endblock %}
{%- block content %}
{%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
<div class="document">
{%- block document %}
<div class="documentwrapper">
{%- if render_sidebar %}
<div class="bodywrapper">
{%- endif %}
<div class="body">
{% block body %} {% endblock %}
</div>
{%- if render_sidebar %}
</div>
{%- endif %}
</div>
{%- endblock %}
{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
<div class="clearer"></div>
</div>
{%- endblock %}
{%- block relbar2 %}{{ relbar() }}{% endblock %}
{%- block footer %}
<div class="footer">
{%- if show_copyright %}
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
{%- else %}
{% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
{%- endif %}
{%- endif %}
{%- if last_updated %}
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
{%- endif %}
{%- if show_sphinx %}
{% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
{%- endif %}
</div>
<p>asdf asdf asdf asdf 22</p>
{%- endblock %}
</body>
</html>

View File

@ -0,0 +1,61 @@
<!-- <form class="wy-form" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form> -->
<script>
(function() {
var cx = '006019874985968165468:eu5pbnxp4po';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
<form id="search-form-id" action="">
<input type="text" name="query" id="search-box-id" />
<a class="search-reset-start" id="search-reset"><i class="fa fa-times"></i></a>
<a class="search-reset-start" id="search-start"><i class="fa fa-search"></i></a>
</form>
<script type="text/javascript" src="http://www.google.com/cse/brand?form=search-form-id&inputbox=search-box-id"></script>
<script>
function executeQuery() {
var input = document.getElementById('search-box-id');
var element = google.search.cse.element.getElement('searchresults-only0');
element.resultsUrl = '/htmlout/search.html'
if (input.value == '') {
element.clearAllResults();
$('#page-content, .rst-footer-buttons, #search-start').show();
$('#search-results, #search-reset').hide();
} else {
$('#page-content, .rst-footer-buttons, #search-start').hide();
$('#search-results, #search-reset').show();
element.execute(input.value);
}
return false;
}
$('#search-reset').hide();
$('#search-box-id').css('background-position', '1em center');
$('#search-box-id').on('blur', function() {
$('#search-box-id').css('background-position', '1em center');
});
$('#search-start').click(function(e) { executeQuery(); });
$('#search-reset').click(function(e) { $('#search-box-id').val(''); executeQuery(); });
$('#search-form-id').submit(function(e) {
console.log('submitting!');
executeQuery();
e.preventDefault();
});
</script>

View File

@ -4723,13 +4723,16 @@ span[id*='MathJax-Span'] {
padding: 0.4045em 1.618em;
}
.DocSiteBanner {
width: 100%;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
flex-wrap: wrap;
-webkit-flex-wrap: wrap;
justify-content: space-between;
-webkit-justify-content: space-between;
background-color: #ff5850;
margin-bottom: 25px;
}
@ -4737,22 +4740,16 @@ span[id*='MathJax-Span'] {
max-width: 100%;
}
@media print {
* { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; }
#nav,
a, a:visited { text-decoration: underline; }
a[href]:after { content: " (" attr(href) ")"; }
abbr[title]:after { content: " (" attr(title) ")"; }
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } /* Don't show links for images, or javascript/internal links */
pre, blockquote { border: 0px solid #999; page-break-inside: avoid; }
thead { display: table-header-group; } /* h5bp.com/t */
tr, img { page-break-inside: avoid; }
img { max-width: 100% !important; }
@page { margin: 0.5cm; }
p, h2, h3 { orphans: 3; widows: 3; }
h2, h3 { page-break-after: avoid; }
.DocSiteBanner,
#google_image_div {
display: none !important;
@media screen and (max-width: 1403px) {
.DocSiteBanner {
width: 100%;
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
-webkit-flex-wrap: wrap;
justify-content: center;
-webkit-justify-content: center;
background-color: #fff;
margin-bottom: 25px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -100,7 +100,7 @@ exclude_patterns = ['modules']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
highlight_language = 'yaml'
highlight_language = 'YAML'
# Options for HTML output

View File

@ -37,34 +37,17 @@ All members of a list are lines beginning at the same indentation level starting
A dictionary is represented in a simple ``key: value`` form (the colon must be followed by a space)::
# An employee record
martin:
- martin:
name: Martin D'vloper
job: Developer
skill: Elite
More complicated data structures are possible, such as lists of dictionaries, dictionaries whose values are lists or a mix of both::
# Employee records
- martin:
name: Martin D'vloper
job: Developer
skills:
- python
- perl
- pascal
- tabitha:
name: Tabitha Bitumen
job: Developer
skills:
- lisp
- fortran
- erlang
Dictionaries and lists can also be represented in an abbreviated form if you really want to::
---
martin: {name: Martin D'vloper, job: Developer, skill: Elite}
fruits: ['Apple', 'Orange', 'Strawberry', 'Mango']
employees:
- martin: {name: Martin D'vloper, job: Developer, skill: Elite}
fruits: ['Apple', 'Orange', 'Strawberry', 'Mango]
.. _truthiness:
@ -76,20 +59,6 @@ Ansible doesn't really use these too much, but you can also specify a boolean va
likes_emacs: TRUE
uses_cvs: false
Values can span multiple lines using ``|`` or ``>``. Spanning multiple lines using a ``|`` will include the newlines. Using a ``>`` will ignore newlines; it's used to make what would otherwise be a very long line easier to read and edit.
In either case the indentation will be ignored.
Examples are::
include_newlines: |
exactly as you see
will appear these three
lines of poetry
ignore_newlines: >
this is really a
single line of text
despite appearances
Let's combine what we learned so far in an arbitrary YAML example.
This really has nothing to do with Ansible, but will give you a feel for the format::
@ -106,13 +75,9 @@ This really has nothing to do with Ansible, but will give you a feel for the for
- Strawberry
- Mango
languages:
perl: Elite
ruby: Elite
python: Elite
pascal: Lame
education: |
4 GCSEs
3 A-Levels
BSc in the Internet of Things
dotnet: Lame
That's all you really need to know about YAML to start writing `Ansible` playbooks.
@ -151,8 +116,6 @@ In these cases just use quotes::
YAML Lint (online) helps you debug YAML syntax if you are having problems
`Github examples directory <https://github.com/ansible/ansible-examples>`_
Complete playbook files from the github project source
`Wikipedia YAML syntax reference <https://en.wikipedia.org/wiki/YAML>`_
A good guide to YAML syntax
`Mailing List <http://groups.google.com/group/ansible-project>`_
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_

View File

@ -7,171 +7,76 @@ Ansible can use existing privilege escalation systems to allow a user to execute
Become
``````
Ansible allows you 'become' another user, different from the user that logged into the machine (remote user). This is done using existing
privilege escalation tools, which you probably already use or have configured, like 'sudo', 'su', 'pfexec', 'doas', 'pbrun', 'dzdo', and others.
Before 1.9 Ansible mostly allowed the use of `sudo` and a limited use of `su` to allow a login/remote user to become a different user
and execute tasks, create resources with the 2nd user's permissions. As of 1.9 `become` supersedes the old sudo/su, while still
being backwards compatible. This new system also makes it easier to add other privilege escalation tools like `pbrun` (Powerbroker),
`pfexec` and others.
.. note:: Before 1.9 Ansible mostly allowed the use of `sudo` and a limited use of `su` to allow a login/remote user to become a different user
and execute tasks, create resources with the 2nd user's permissions. As of 1.9 `become` supersedes the old sudo/su, while still being backwards compatible.
This new system also makes it easier to add other privilege escalation tools like `pbrun` (Powerbroker), `pfexec`, `dzdo` (Centrify), and others.
.. note:: Setting any var or directive makes no implications on the values of the other related directives, i.e. setting become_user does not set become.
Directives
-----------
These can be set from play to task level, but are overriden by connection variables as they can be host specific.
New directives
--------------
become
set to 'true'/'yes' to activate privilege escalation.
equivalent to adding `sudo:` or `su:` to a play or task, set to 'true'/'yes' to activate privilege escalation
become_user
set to user with desired privileges, the user you 'become', NOT the user you login as. Does NOT imply `become: yes`, to allow it to be set at host level.
equivalent to adding 'sudo_user:' or 'su_user:' to a play or task, set to user with desired privileges
become_method
at play or task level overrides the default method set in ansible.cfg, set to 'sudo'/'su'/'pbrun'/'pfexec'/'doas'/'dzdo'
at play or task level overrides the default method set in ansible.cfg, set to 'sudo'/'su'/'pbrun'/'pfexec'/'doas'
Connection variables
--------------------
Each allows you to set an option per group and/or host, these are normally defined in inventory but can be used as normal variables.
New ansible\_ variables
-----------------------
Each allows you to set an option per group and/or host
ansible_become
equivalent of the become directive, decides if privilege escalation is used or not.
equivalent to ansible_sudo or ansible_su, allows to force privilege escalation
ansible_become_method
allows to set privilege escalation method
ansible_become_user
allows to set the user you become through privilege escalation, does not imply `ansible_become: True`
equivalent to ansible_sudo_user or ansible_su_user, allows to set the user you become through privilege escalation
ansible_become_pass
allows you to set the privilege escalation password
equivalent to ansible_sudo_pass or ansible_su_pass, allows you to set the privilege escalation password
New command line options
------------------------
--ask-become-pass, -K
ask for privilege escalation password, does not imply become will be used
--ask-become-pass
ask for privilege escalation password
--become, -b
--become,-b
run operations with become (no password implied)
--become-method=BECOME_METHOD
privilege escalation method to use (default=sudo),
valid choices: [ sudo | su | pbrun | pfexec | doas | dzdo ]
valid choices: [ sudo | su | pbrun | pfexec | doas ]
--become-user=BECOME_USER
run operations as this user (default=root), does not imply --become/-b
run operations as this user (default=root)
For those from Pre 1.9 , sudo and su still work!
------------------------------------------------
sudo and su still work!
-----------------------
For those using old playbooks will not need to be changed, even though they are deprecated, sudo and su directives, variables and options
will continue to work. It is recommended to move to become as they may be retired at one point.
You cannot mix directives on the same object (become and sudo) though, Ansible will complain if you try to.
Old playbooks will not need to be changed, even though they are deprecated, sudo and su directives will continue to work though it
is recommended to move to become as they may be retired at one point. You cannot mix directives on the same object though, Ansible
will complain if you try to.
Become will default to using the old sudo/su configs and variables if they exist, but will override them if you specify any of the new ones.
Become will default to using the old sudo/su configs and variables if they exist, but will override them if you specify any of the
new ones.
Limitations
-----------
Although privilege escalation is mostly intuitive, there are a few limitations
on how it works. Users should be aware of these to avoid surprises.
.. note:: Privilege escalation methods must also be supported by the connection plugin used, most will warn if they do not, some will just ignore it as they always run as root (jail, chroot, etc).
Becoming an Unprivileged User
=============================
Ansible 2.0.x and below has a limitation with regards to becoming an
unprivileged user that can be a security risk if users are not aware of it.
Ansible modules are executed on the remote machine by first substituting the
parameters into the module file, then copying the file to the remote machine,
and finally executing it there.
Everything is fine if the module file is executed without using ``become``,
when the ``become_user`` is root, or when the connection to the remote machine
is made as root. In these cases the module file is created with permissions
that only allow reading by the user and root.
The problem occurs when the ``become_user`` is an unprivileged user. Ansible
2.0.x and below make the module file world readable in this case as the module
file is written as the user that Ansible connects as but the file needs to
be reasable by the user Ansible is set to ``become``.
.. note:: In Ansible 2.1, this window is further narrowed: If the connection
is made as a privileged user (root) then Ansible 2.1 and above will use
chown to set the file's owner to the unprivileged user being switched to.
This means both the user making the connection and the user being switched
to via ``become`` must be unprivileged in order to trigger this problem.
If any of the parameters passed to the module are sensitive in nature then
those pieces of data are located in a world readable module file for the
duration of the Ansible module execution. Once the module is done executing
Ansible will delete the temporary file. If you trust the client machines then
there's no problem here. If you do not trust the client machines then this is
a potential danger.
Ways to resolve this include:
* Use :ref:`pipelining`. When pipelining is enabled, Ansible doesn't save the
module to a temporary file on the client. Instead it pipes the module to
the remote python interpreter's stdin. Pipelining does not work for
non-python modules.
* (Available in Ansible 2.1) Install filesystem acl support on the managed
host. If the temporary directory on the remote host is mounted with
filesystem acls enabled and the :command:`setfacl` tool is in the remote
``PATH`` then Ansible will use filesystem acls to share the module file with
the second unprivileged instead of having to make the file readable by
everyone.
* Don't perform an action on the remote machine by becoming an unprivileged
user. Temporary files are protected by UNIX file permissions when you
``become`` root or do not use ``become``. In Ansible 2.1 and above, UNIX
file permissions are also secure if you make the connection to the managed
machine as root and then use ``become`` to an unprivileged account.
.. versionchanged:: 2.1
In addition to the additional means of doing this securely, Ansible 2.1 also
makes it harder to unknowingly do this insecurely. Whereas in Ansible 2.0.x
and below, Ansible will silently allow the insecure behaviour if it was unable
to find another way to share the files with the unprivileged user, in Ansible
2.1 and above Ansible defaults to issuing an error if it can't do this
securely. If you can't make any of the changes above to resolve the problem
and you decide that the machine you're running on is secure enough for the
modules you want to run there to be world readable you can turn on
``allow_world_readable_tmpfiles`` in the :file:`ansible.cfg` file. Setting
``allow_world_readable_tmpfiles`` will change this from an error into
a warning and allow the task to run as it did prior to 2.1.
Connection Plugin Support
=========================
Privilege escalation methods must also be supported by the connection plugin
used. Most connection plugins will warn if they do not support become. Some
will just ignore it as they always run as root (jail, chroot, etc).
Only one method may be enabled per host
=======================================
Methods cannot be chained. You cannot use ``sudo /bin/su -`` to become a user,
you need to have privileges to run the command as that user in sudo or be able
to su directly to it (the same for pbrun, pfexec or other supported methods).
Can't limit escalation to certain commands
==========================================
Privilege escalation permissions have to be general. Ansible does not always
use a specific command to do something but runs modules (code) from
a temporary file name which changes every time. If you have '/sbin/service'
or '/bin/chmod' as the allowed commands this will fail with ansible as those
paths won't match with the temporary file that ansible creates to run the
module.
.. note:: Methods cannot be chained, you cannot use 'sudo /bin/su -' to become a user, you need to have privileges to run the command as that user in sudo or be able to su directly to it (the same for pbrun, pfexec or other supported methods).
.. note:: Privilege escalation permissions have to be general, Ansible does not always use a specific command to do something but runs modules (code) from a temporary file name which changes every time. So if you have '/sbin/service' or '/bin/chmod' as the allowed commands this will fail with ansible.
.. seealso::

View File

@ -1,85 +0,0 @@
Committers Guidelines (for people with commit rights to Ansible on GitHub)
``````````````````````````````````````````````````````````````````````````
These are the guidelines for people with commit access to Ansible. Committers are essentially acting as members of the Ansible Core team, although not necessarily as an employee of Ansible and Red Hat. Please read the guidelines before you commit.
These guidelines apply to everyone. At the same time, this ISN’T a process document. So just use good judgement. You’ve been given commit access because we trust your judgement.
That said, use the trust wisely.
If you abuse the trust and break components and builds, etc., the trust level falls and you may be asked not to commit or you may lose access to do so.
Features, High Level Design, and Roadmap
========================================
As a core team member, you are an integral part of the team that develops the roadmap. Please be engaged, and push for the features and fixes that you want to see. Also keep in mind that Red Hat, as a company, will commit to certain features, fixes, APIs, etc. for various releases. Red Hat, the company, and the Ansible team must get these committed features (etc.) completed and released as scheduled. Obligations to users, the community, and customers must come first. Because of these commitments, a feature you want to develop yourself many not get into a release if it impacts a lot of other parts within Ansible.
Any other new features and changes to high level design should go through the proposal process (TBD), to ensure the community and core team have had a chance to review the idea and approve it. The core team has sole responsibility for merging new features based on proposals.
Our Workflow on GitHub
======================
As a committer, you may already know this, but our workflow forms a lot of our team policies. Please ensure you’re aware of the following workflow steps:
* Fork the repository upon which you want to do some work to your own personal repository
* Work on the specific branch upon which you need to commit
* Create a Pull Request back to the Ansible repository and tag the people you would like to review; assign someone as the primary “owner” of your request
* Adjust code as necessary based on the Comments provided
* Ask someone on the Core Team to do a final review and merge
Addendum to workflow for Committers:
------------------------------------
The Core Team is aware that this can be a difficult process at times. Sometimes, the team breaks the rules: Direct commits, merging their own PRs. This section is a set of guidelines. If you’re changing a comma in a doc, or making a very minor change, you can use your best judgement. This is another trust thing. The process is critical for any major change, but for little things or getting something done quickly, use your best judgement and make sure people on the team are aware of your work.
Roles on Core
=============
* Core Committers: Fine to do PRs for most things, but we should have a timebox. Hanging PRs may merge on the judgement of these devs.
* Module Owners: Module Owners own specific modules and have indirect commit access via the current module PR mechanisms.
General Rules
=============
Individuals with direct commit access to ansible/ansible (+core, + extras) are entrusted with powers that allow them to do a broad variety of things--probably more than we can write down. Rather than rules, treat these as general *guidelines*, individuals with this power are expected to use their best judgement.
* Don’t commit directly.
* Don't omit tests. PRs with tests are looked at with more priority than PRs without tests that should have them included. While not all changes require tests, be sure to add them for bug fixes or functionality changes.
* Don't forget the docs! If your PR is a new feature or a change to behavior, make sure you've updated all associated documentation or have notified the right people to do so. It also helps to add the version of Core against which this documentation is compatible (to avoid confusion with stable versus devel docs, for backwards compatibility, etc.).
* Don't merge your own PRs. Someone else should have a chance to review and approve the PR merge. If you are a Core Committer, you have a small amount of leeway here for very minor changes.
* Consider backwards compatibility (don’t break existing playbooks).
* Don't forget about alternate environments. Consider the alternatives--yes, people have bad environments, but they are the ones who need us the most.
* Don't drag your community team members down. Always discuss the technical merits, but you should never address the person’s limitations (you can later go for beers and call them idiots, but not in IRC/Github/etc.).
* Don't forget about the maintenance burden. Some things are really cool to have, but they might not be worth shoehorning in if the maintenance burden is too great.
* Don't break playbooks. Always keep backwards compatibility in mind.
* Don't forget to keep it simple. Complexity breeds all kinds of problems.
* Don't forget to be active. Committers who have no activity on the project (through merges, triage, commits, etc.) will have their permissions suspended.
Committers are expected to continue to follow the same community and contribution guidelines followed by the rest of the Ansible community.
People
======
Individuals who've been asked to become a part of this group have generally been contributing in significant ways to the Ansible community for some time. Should they agree, they are requested to add their names and GitHub IDs to this file, in the section below, via a pull request. Doing so indicates that these individuals agree to act in the ways that their fellow committers trust that they will act.
* James Cammarata
* Brian Coca
* Matt Davis
* Toshio Kuratomi
* Jason McKerr
* Robyn Bergeron
* Greg DeKoenigsberg
* Monty Taylor
* Matt Martz
* Nate Case
* James Tanner
* Peter Sprygada
* Abhijit Menon-Sen
* Michael Scherer
* René Moser
* David Shrewsbury
* Sandra Wills
* Graham Mainwaring
* Jon Davila
* Chris Houseknecht
* Trond Hindenes
* Jon Hawkesworth
* Will Thames

View File

@ -1,5 +1,3 @@
.. _common_return_values:
Common Return Values
====================

View File

@ -68,7 +68,7 @@ to see if the issue has already been reported.
MODULE related bugs however should go to `ansible-modules-core <https://github.com/ansible/ansible-modules-core>`_ or `ansible-modules-extras <https://github.com/ansible/ansible-modules-extras>`_ based on the classification of the module. This is listed on the bottom of the docs page for any module.
When filing a bug, please use the `issue template <https://github.com/ansible/ansible/raw/devel/.github/ISSUE_TEMPLATE.md>`_ to provide all relevant information, regardless of what repo you are filing a ticket against.
When filing a bug, please use the `issue template <https://github.com/ansible/ansible/raw/devel/ISSUE_TEMPLATE.md>`_ to provide all relevant information, regardless of what repo you are filing a ticket against.
Knowing your ansible version and the exact commands you are running, and what you expect, saves time and helps us help everyone with their issues
more quickly.
@ -227,12 +227,6 @@ which is our official conference series.
To subscribe to a group from a non-google account, you can send an email to the subscription address requesting the subscription. For example: ansible-devel+subscribe@googlegroups.com
IRC Meetings
------------
The Ansible community holds regular IRC meetings on various topics, and anyone who is interested is invited to
participate. For more information about Ansible meetings, consult the [Ansible community meeting page](https://github.com/ansible/community/blob/master/MEETINGS.md).
Release Numbering
-----------------
@ -251,18 +245,13 @@ Tower Support Questions
Ansible `Tower <http://ansible.com/tower>`_ is a UI, Server, and REST endpoint for Ansible, produced by Ansible, Inc.
If you have a question about Tower, visit `support.ansible.com <https://support.ansible.com/>`_ rather than using the IRC
If you have a question about tower, email `support@ansible.com <mailto:support@ansible.com>`_ rather than using the IRC
channel or the general project mailing list.
IRC Channel
-----------
Ansible has several IRC channels on Freenode (irc.freenode.net):
- #ansible - For general use questions and support.
- #ansible-devel - For discussions on developer topics and code related to features/bugs.
- #ansible-meeting - For public community meetings. We will generally announce these on one or more of the above mailing lists.
- #ansible-notices - Mostly bot output from things like Github, etc.
Ansible has an IRC channel #ansible on irc.freenode.net.
Notes on Priority Flags
-----------------------
@ -297,146 +286,20 @@ Every bit of effort helps - if you're wishing to expedite the inclusion of a P3
is help close P2 bug reports.
Community Code of Conduct
=========================
-------------------------
Every community can be strengthened by a diverse variety of viewpoints, insights,
opinions, skillsets, and skill levels. However, with diversity comes the potential for
disagreement and miscommunication. The purpose of this Code of Conduct is to ensure that
disagreements and differences of opinion are conducted respectfully and on their own
merits, without personal attacks or other behavior that might create an unsafe or
unwelcoming environment.
Ansible’s community welcomes users of all types, backgrounds, and skill levels. Please treat others as you expect to be treated,
keep discussions positive, and avoid discrimination of all kinds, profanity, allegations of Cthulhu worship, or engaging in
controversial debates (except vi vs emacs is cool).
These policies are not designed to be a comprehensive set of Things You Cannot Do. We ask
that you treat your fellow community members with respect and courtesy, and in general,
Don't Be A Jerk. This Code of Conduct is meant to be followed in spirit as much as in
letter and is not exhaustive.
The same expectations apply to community events as they do to online interactions.
All Ansible events and participants therein are governed by this Code of Conduct and
anti-harassment policy. We expect organizers to enforce these guidelines throughout all events,
and we expect attendees, speakers, sponsors, and volunteers to help ensure a safe
environment for our whole community. Specifically, this Code of Conduct covers
participation in all Ansible-related forums and mailing lists, code and documentation
contributions, public IRC channels, private correspondence, and public meetings.
Posts to mailing lists should remain focused around Ansible and IT automation. Abuse of these community guidelines will not be
tolerated and may result in banning from community resources.
Ansible community members are...
**Considerate**
Contributions of every kind have far-ranging consequences. Just as your work depends on
the work of others, decisions you make surrounding your contributions to the Ansible
community will affect your fellow community members. You are strongly encouraged to take
those consequences into account while making decisions.
**Patient**
Asynchronous communication can come with its own frustrations, even in the most responsive
of communities. Please remember that our community is largely built on volunteered time,
and that questions, contributions, and requests for support may take some time to receive
a response. Repeated "bumps" or "reminders" in rapid succession are not good displays of
patience. Additionally, it is considered poor manners to ping a specific person with
general questions. Pose your question to the community as a whole, and wait patiently for
a response.
**Respectful**
Every community inevitably has disagreements, but remember that it is
possible to disagree respectfully and courteously. Disagreements are never an excuse for
rudeness, hostility, threatening behavior, abuse (verbal or physical), or personal attacks.
**Kind**
Everyone should feel welcome in the Ansible community, regardless of their background.
Please be courteous, respectful and polite to fellow community members. Do not make or
post offensive comments related to skill level, gender, gender identity or expression,
sexual orientation, disability, physical appearance, body size, race, or religion.
Sexualized images or imagery, real or implied violence, intimidation, oppression,
stalking, sustained disruption of activities, publishing the personal information of
others without explicit permission to do so, unwanted physical contact, and unwelcome
sexual attention are all strictly prohibited. Additionally, you are encouraged not to
make assumptions about the background or identity of your fellow community members.
**Inquisitive**
The only stupid question is the one that does not get asked. We
encourage our users to ask early and ask often. Rather than asking whether you can ask a
question (the answer is always yes!), instead, simply ask your question. You are
encouraged to provide as many specifics as possible. Code snippets in the form of Gists or
other paste site links are almost always needed in order to get the most helpful answers.
Refrain from pasting multiple lines of code directly into the IRC channels - instead use
gist.github.com or another paste site to provide code snippets.
**Helpful**
The Ansible community is committed to being a welcoming environment for all users,
regardless of skill level. We were all beginners once upon a time, and our community
cannot grow without an environment where new users feel safe and comfortable asking questions.
It can become frustrating to answer the same questions repeatedly; however, community
members are expected to remain courteous and helpful to all users equally, regardless of
skill or knowledge level. Avoid providing responses that prioritize snideness and snark over
useful information. At the same time, everyone is expected to read the provided
documentation thoroughly. We are happy to answer questions, provide strategic guidance,
and suggest effective workflows, but we are not here to do your job for you.
Anti-harassment policy
----------------------
Harassment includes (but is not limited to) all of the following behaviors:
- Offensive comments related to gender (including gender expression and identity), age, sexual orientation, disability, physical appearance, body size, race, and religion
- Derogatory terminology including words commonly known to be slurs
- Posting sexualized images or imagery in public spaces
- Deliberate intimidation
- Stalking
- Posting others' personal information without explicit permission
- Sustained disruption of talks or other events
- Inappropriate physical contact
- Unwelcome sexual attention
Participants asked to stop any harassing behavior are expected to comply immediately.
Sponsors are also subject to the anti-harassment policy. In particular, sponsors should
not use sexualized images, activities, or other material. Meetup organizing staff and
other volunteer organizers should not use sexualized attire or otherwise create a
sexualized environment at community events.
In addition to the behaviors outlined above, continuing to behave a certain way after you
have been asked to stop also constitutes harassment, even if that behavior is not
specifically outlined in this policy. It is considerate and respectful to stop doing
something after you have been asked to stop, and all community members are expected to
comply with such requests immediately.
Policy violations
-----------------
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting greg@ansible.com, to any channel operator in the community IRC
channels, or to the local organizers of an event. Meetup organizers are encouraged to
prominently display points of contact for reporting unacceptable behavior at local events.
If a participant engages in harassing behavior, the meetup organizers may take any action
they deem appropriate. These actions may include but are not limited to warning the
offender, expelling the offender from the event, and barring the offender from future
community events.
Organizers will be happy to help participants contact security or local law enforcement,
provide escorts to an alternate location, or otherwise assist those experiencing
harassment to feel safe for the duration of the meetup. We value the safety and well-being
of our community members and want everyone to feel welcome at our events, both online and
offline.
We expect all participants, organizers, speakers, and attendees to follow these policies at
our all of our event venues and event-related social events.
The Ansible Community Code of Conduct is licensed under the Creative Commons
Attribution-Share Alike 3.0 license. Our Code of Conduct was adapted from Codes of Conduct
of other open source projects, including:
* Contributor Covenant
* Elastic
* The Fedora Project
* OpenStack
* Puppet Labs
* Ubuntu
Contributors License Agreement
==============================
------------------------------
By contributing you agree that these contributions are your own (or approved by your employer) and you grant a full, complete, irrevocable
copyright license to all users and developers of the project, present and future, pursuant to the license of the project.

View File

@ -10,7 +10,6 @@ Learn how to build modules of your own in any language, and also how to extend A
developing_inventory
developing_modules
developing_plugins
developing_core
developing_test_pr
developing_releases

View File

@ -3,17 +3,10 @@ Python API
.. contents:: Topics
Please note that while we make this API available it is not intended for direct consumption, it is here
for the support of the Ansible command line tools. We try not to make breaking changes but we reserve the
right to do so at any time if it makes sense for the Ansible toolset.
The following documentation is provided for those that still want to use the API directly, but be mindful this is not something the Ansible team supports.
There are several interesting ways to use Ansible from an API perspective. You can use
the Ansible python API to control nodes, you can extend Ansible to respond to various python events, you can
write various plugins, and you can plug in inventory data from external data sources. This document
covers the execution and Playbook API at a basic level.
covers the Runner and Playbook API at a basic level.
If you are looking to use Ansible programmatically from something other than Python, trigger events asynchronously,
or have access control and logging demands, take a look at :doc:`tower`
@ -24,10 +17,8 @@ This chapter discusses the Python API.
.. _python_api:
The Python API is very powerful, and is how the all the ansible CLI tools are implemented.
In version 2.0 the core ansible got rewritten and the API was mostly rewritten.
.. note:: Ansible relies on forking processes, as such the API is not thread safe.
The Python API is very powerful, and is how the ansible CLI and ansible-playbook
are implemented. In version 2.0 the core ansible got rewritten and the API was mostly rewritten.
.. _python_api_20:
@ -46,11 +37,11 @@ In 2.0 things get a bit more complicated to start, but you end up with much more
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check'])
Options = namedtuple('Options', ['connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])
# initialize needed objects
variable_manager = VariableManager()
loader = DataLoader()
options = Options(connection='local', module_path='/path/to/mymodules', forks=100, become=None, become_method=None, become_user=None, check=False)
options = Options(connection='local', module_path='/path/to/mymodules', forks=100, remote_user=None, private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None, become_method=None, become_user=None, verbosity=None, check=False)
passwords = dict(vault_pass='secret')
# create inventory and pass to var manager
@ -62,10 +53,7 @@ In 2.0 things get a bit more complicated to start, but you end up with much more
name = "Ansible Play",
hosts = 'localhost',
gather_facts = 'no',
tasks = [
dict(action=dict(module='shell', args='ls'), register='shell_out'),
dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
]
tasks = [ dict(action=dict(module='debug', args=(msg='Hello Galaxy!'))) ]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

View File

@ -3,28 +3,25 @@ Developing Modules
.. contents:: Topics
Ansible modules are reusable, standalone scripts that can be used by the Ansible API,
or by the :command:`ansible` or :command:`ansible-playbook` programs. They
return information to ansible by printing a JSON string to stdout before
exiting. They take arguments in in one of several ways which we'll go into
as we work through this tutorial.
Ansible modules are reusable units of magic that can be used by the Ansible API,
or by the `ansible` or `ansible-playbook` programs.
See :doc:`modules` for a list of various ones developed in core.
Modules can be written in any language and are found in the path specified
by :envvar:`ANSIBLE_LIBRARY` or the ``--module-path`` command line option.
by `ANSIBLE_LIBRARY` or the ``--module-path`` command line option.
By default, everything that ships with Ansible is pulled from its source tree, but
By default, everything that ships with ansible is pulled from its source tree, but
additional paths can be added.
The directory i:file:`./library`, alongside your top level :term:`playbooks`, is also automatically
The directory "./library", alongside your top level playbooks, is also automatically
added as a search directory.
Should you develop an interesting Ansible module, consider sending a pull request to the
`modules-extras project <https://github.com/ansible/ansible-modules-extras>`_. There's also a core
repo for more established and widely used modules. "Extras" modules may be promoted to core periodically,
but there's no fundamental difference in the end - both ship with Ansible, all in one package, regardless
of how you acquire Ansible.
but there's no fundamental difference in the end - both ship with ansible, all in one package, regardless
of how you acquire ansible.
.. _module_dev_tutorial:
@ -44,14 +41,14 @@ written in any language OTHER than Python are going to have to do exactly this.
way later.
So, here's an example. You would never really need to build a module to set the system time,
the 'command' module could already be used to do this.
the 'command' module could already be used to do this. Though we're going to make one.
Reading the modules that come with Ansible (linked above) is a great way to learn how to write
modules. Keep in mind, though, that some modules in Ansible's source tree are internalisms,
so look at :ref:`service` or :ref:`yum`, and don't stare too close into things like :ref:`async_wrapper` or
you'll turn to stone. Nobody ever executes :ref:`async_wrapper` directly.
Reading the modules that come with ansible (linked above) is a great way to learn how to write
modules. Keep in mind, though, that some modules in ansible's source tree are internalisms,
so look at `service` or `yum`, and don't stare too close into things like `async_wrapper` or
you'll turn to stone. Nobody ever executes async_wrapper directly.
Ok, let's get going with an example. We'll use Python. For starters, save this as a file named :file:`timetest.py`::
Ok, let's get going with an example. We'll use Python. For starters, save this as a file named `timetest.py`::
#!/usr/bin/python
@ -66,15 +63,13 @@ Ok, let's get going with an example. We'll use Python. For starters, save this
.. _module_testing:
Testing Modules
````````````````
```````````````
There's a useful test script in the source checkout for Ansible::
There's a useful test script in the source checkout for ansible::
git clone git://github.com/ansible/ansible.git --recursive
source ansible/hacking/env-setup
For instructions on setting up Ansible from source, please see
:doc:`intro_installation`.
chmod +x ansible/hacking/test-module
Let's run the script you just wrote with that::
@ -82,7 +77,7 @@ Let's run the script you just wrote with that::
You should see output that looks something like this::
{'time': '2012-03-14 22:13:48.539183'}
{u'time': u'2012-03-14 22:13:48.539183'}
If you did not, you might have a typo in your module, so recheck it and try again.
@ -107,7 +102,7 @@ If no time parameter is set, we'll just leave the time as is and return the curr
.. note::
This is obviously an unrealistic idea for a module. You'd most likely just
use the command module. However, it makes for a decent tutorial.
use the shell module. However, it probably makes a decent tutorial.
Let's look at the code. Read the comments as we'll explain as we go. Note that this
is highly verbose because it's intended as an educational example. You can write modules
@ -128,12 +123,10 @@ a lot shorter than this::
args_file = sys.argv[1]
args_data = file(args_file).read()
# For this module, we're going to do key=value style arguments.
# Modules can choose to receive json instead by adding the string:
# WANT_JSON
# Somewhere in the file.
# Modules can also take free-form arguments instead of key-value or json
# but this is not recommended.
# for this module, we're going to do key=value style arguments
# this is up to each module to decide what it wants, but all
# core modules besides 'command' and 'shell' take key=value
# so this is highly recommended
arguments = shlex.split(args_data)
for arg in arguments:
@ -198,7 +191,7 @@ a lot shorter than this::
Let's test that module::
ansible/hacking/test-module -m ./timetest.py -a "time=\"March 14 12:23\""
ansible/hacking/test-module -m ./time -a "time=\"March 14 12:23\""
This should return something like::
@ -207,9 +200,9 @@ This should return something like::
.. _module_provided_facts:
Module Provided 'Facts'
````````````````````````
```````````````````````
The :ref:`setup` module that ships with Ansible provides many variables about a system that can be used in playbooks
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::
@ -242,52 +235,43 @@ Rather than mention these here, the best way to learn is to read some of the `so
The 'group' and 'user' modules are reasonably non-trivial and showcase what this looks like.
Key parts include always importing the boilerplate code from
:mod:`ansible.module_utils.basic` like this::
Key parts include always ending the module file with::
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import *
if __name__ == '__main__':
main()
.. note::
Prior to Ansible-2.1.0, importing only what you used from
:mod:`ansible.module_utils.basic` did not work. You needed to use
a wildcard import like this::
from ansible.module_utils.basic import *
And instantiating the module class like::
def main():
module = AnsibleModule(
argument_spec = dict(
state = dict(default='present', choices=['present', 'absent']),
name = dict(required=True),
enabled = dict(required=True, type='bool'),
something = dict(aliases=['whatever'])
)
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 :class:`AnsibleModule` provides lots of common code for handling returns, parses your arguments
The AnsibleModule provides lots of common code for handling returns, parses your arguments
for you, and allows you to check inputs.
Successful returns are made like this::
module.exit_json(changed=True, something_else=12345)
And failures are just as simple (where `msg` is a required parameter to explain the error)::
And failures are just as simple (where 'msg' is a required parameter to explain the error)::
module.fail_json(msg="Something fatal happened")
There are also other useful functions in the module class, such as :func:`module.sha1(path)`. See
:file:`lib/ansible/module_utils/basic.py` in the source checkout for implementation details.
There are also other useful functions in the module class, such as module.sha1(path). See
lib/ansible/module_common.py in the source checkout for implementation details.
Again, modules developed this way are best tested with the :file:`hacking/test-module` script in the git
Again, modules developed this way are best tested with the hacking/test-module script in the git
source checkout. Because of the magic involved, this is really the only way the scripts
can function outside of Ansible.
If submitting a module to Ansible's core code, which we encourage, use of
:class:`AnsibleModule` is required.
If submitting a module to ansible's core code, which we encourage, use of the AnsibleModule
class is required.
.. _developing_for_check_mode:
@ -351,7 +335,7 @@ and guidelines:
* If you have a company module that returns facts specific to your installations, a good name for this module is `site_facts`.
* Modules accepting boolean status should generally accept 'yes', 'no', 'true', 'false', or anything else a user may likely throw at them. The AnsibleModule common code supports this with "type='bool'".
* 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.
@ -363,7 +347,7 @@ and guidelines:
* In the event of failure, a key of 'failed' should be included, along with a string explanation in 'msg'. Modules that raise tracebacks (stacktraces) are generally considered 'poor' modules, though Ansible can deal with these returns and will automatically convert anything unparseable into a failed result. If you are using the AnsibleModule common Python code, the 'failed' element will be included for you automatically when you call 'fail_json'.
* Return codes from modules are actually not significant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
* Return codes from modules are not actually not significant, but continue on with 0=success and non-zero=failure for reasons of future proofing.
* As results from many hosts will be aggregated at once, modules should return only relevant output. Returning the entire contents of a log file is generally bad form.
@ -397,8 +381,6 @@ Include it in your module file like this::
# ... snip ...
'''
If an argument takes both C(True)/C(False) and C(Yes)/C(No), the documentation should use C(True) and C(False).
The ``description``, and ``notes`` fields
support formatting with some special macros.
@ -462,126 +444,13 @@ built and appear in the 'docsite/' directory.
You can set the environment variable ANSIBLE_KEEP_REMOTE_FILES=1 on the controlling host to prevent ansible from
deleting the remote files so you can debug your module.
.. _debugging_ansiblemodule_based_modules:
Debugging AnsibleModule-based modules
`````````````````````````````````````
.. tip::
If you're using the :file:`hacking/test-module` script then most of this
is taken care of for you. If you need to do some debugging of the module
on the remote machine that the module will actually run on or when the
module is used in a playbook then you may need to use this information
instead of relying on test-module.
Starting with Ansible-2.1.0, AnsibleModule-based modules are put together as
a zip file consisting of the module file and the various python module
boilerplate inside of a wrapper script instead of as a single file with all of
the code concatenated together. Without some help, this can be harder to
debug as the file needs to be extracted from the wrapper in order to see
what's actually going on in the module. Luckily the wrapper script provides
some helper methods to do just that.
If you are using Ansible with the :envvar:`ANSIBLE_KEEP_REMOTE_FILES`
environment variables to keep the remote module file, here's a sample of how
your debugging session will start::
$ ANSIBLE_KEEP_REMOTE_FILES=1 ansible localhost -m ping -a 'data=debugging_session' -vvv
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: badger
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" )'
<127.0.0.1> PUT /var/tmp/tmpjdbJ1w TO /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping
<127.0.0.1> EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping'
localhost | SUCCESS => {
"changed": false,
"invocation": {
"module_args": {
"data": "debugging_session"
},
"module_name": "ping"
},
"ping": "debugging_session"
}
Setting :envvar:`ANSIBLE_KEEP_REMOTE_FILE` to ``1`` tells Ansible to keep the
remote module files instead of deleting them after the module finishes
executing. Giving Ansible the ``-vvv`` optin makes Ansible more verbose.
That way it prints the file name of the temporary module file for you to see.
If you want to examine the wrapper file you can. It will show a small python
script with a large, base64 encoded string. The string contains the module
that is going to be executed. Run the wrapper's explode command to turn the
string into some python files that you can work with::
$ python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping explode
Module expanded into:
/home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/debug_dir
When you look into the debug_dir you'll see a directory structure like this::
├── ansible_module_ping.py
├── args
└── ansible
├── __init__.py
└── module_utils
├── basic.py
└── __init__.py
* :file:`ansible_module_ping.py` is the code for the module itself. The name
is based on the name of the module with a prefix so that we don't clash with
any other python module names. You can modify this code to see what effect
it would have on your module.
* The :file:`args` file contains a JSON string. The string is a dictionary
containing the module arguments and other variables that Ansible passes into
the module to change it's behaviour. If you want to modify the parameters
that are passed to the module, this is the file to do it in.
* The :file:`ansible` directory contains code from
:module:`ansible.module_utils` that is used by the module. Ansible includes
files for any :`module:`ansible.module_utils` imports in the module but not
no files from any other module. So if your module uses
:module:`ansible.module_utils.url` Ansible will include it for you, but if
your module includes :module:`requests` then you'll have to make sure that
the python requests library is installed on the system before running the
module. You can modify files in this directory if you suspect that the
module is having a problem in some of this boilerplate code rather than in
the module code you have written.
Once you edit the code or arguments in the exploded tree you need some way to
run it. There's a separate wrapper subcommand for this::
$ python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping execute
{"invocation": {"module_args": {"data": "debugging_session"}}, "changed": false, "ping": "debugging_session"}
This subcommand takes care of setting the PYTHONPATH to use the exploded
:file:`debug_dir/ansible/module_utils` directory and invoking the script using
the arguments in the :file:`args` file. You can continue to run it like this
until you understand the problem. Then you can copy it back into your real
module file and test that the real module works via :command:`ansible` or
:command:`ansible-playbook`.
.. note::
The wrapper provides one more subcommand, ``excommunicate``. This
subcommand is very similar to ``execute`` in that it invokes the exploded
module on the arguments in the :file:`args`. The way it does this is
different, however. ``excommunicate`` imports the :function:`main`
function from the module and then calls that. This makes excommunicate
execute the module in the wrapper's process. This may be useful for
running the module under some graphical debuggers but it is very different
from the way the module is executed by Ansible itself. Some modules may
not work with ``excommunicate`` or may behave differently than when used
with Ansible normally. Those are not bugs in the module; they're
limitations of ``excommunicate``. Use at your own risk.
.. _module_paths
.. _module_contribution:
Module Paths
````````````
If you are having trouble getting your module "found" by ansible, be
sure it is in the :envvar:`ANSIBLE_LIBRARY` environment variable.
sure it is in the ``ANSIBLE_LIBRARY`` environment variable.
If you have a fork of one of the ansible module projects, do something like this::
@ -594,8 +463,6 @@ To be safe, if you're working on a variant on something in Ansible's normal dist
a bad idea to give it a new name while you are working on it, to be sure you know you're pulling
your version.
.. _module_contribution:
Getting Your Module Into Ansible
````````````````````````````````
@ -611,59 +478,26 @@ gives them slightly higher development priority (though they'll work in exactly
Module checklist
````````````````
The following checklist items are important guidelines for people who want to contribute to the development of modules to Ansible on GitHub. Please read the guidelines before you submit your PR/proposal.
* The shebang should always be ``#!/usr/bin/python``, this allows ansible_python_interpreter to work
* Modules must be written to support Python 2.4. If this is not possible, required minimum python version and rationale should be explained in the requirements section in DOCUMENTATION.
* The shebang should always be #!/usr/bin/python, this allows ansible_python_interpreter to work
* Documentation: Make sure it exists
* Module documentation should briefly and accurately define what each module and option does, and how it works with others in the underlying system. Documentation should be written for broad audience--readable both by experts and non-experts. This documentation is not meant to teach a total novice, but it also should not be reserved for the Illuminati (hard balance).
* If an argument takes both C(True)/C(False) and C(Yes)/C(No), the documentation should use C(True) and C(False).
* Descriptions should always start with a Capital letter and end with a full stop. Consistency always helps.
* The `required` setting should always be present, be it true *or* false
* If `required` is false, you should document `default`, even if the default is 'null' (which is the default if no parameter is supplied). Make sure default parameter in docs matches default parameter in code.
* Documenting `default` is not needed for `required: true`.
* Remove unnecessary doc like `aliases: []` or `choices: []`.
* The version is not a float number and value the current development version.
* Verify that arguments in doc and module spec dict are identical.
* For password / secret arguments no_log=True should be set.
* Requirements should be documented, using the `requirements=[]` field.
* Author should be set, with their name and their github id, at the least.
* Ensure that you make use of U() for urls, C() for files and options, I() for params, M() for modules.
* If an optional parameter is sometimes required this need to be reflected in the documentation, e.g. "Required when C(state=present)."
* Verify that a GPL 3 License header is included.
* Does module use check_mode? Could it be modified to use it? Document it. Documentation is everyone's friend.
* Examples--include them whenever possible and make sure they are reproducible.
* Document the return structure of the module. Refer to :ref:`common_return_values` and :ref:`module_documenting` for additional information.
* Predictable user interface: This is a particularly important section as it is also an area where we need significant improvements.
* Name consistency across modules (we’ve gotten better at this, but we still have many deviations).
* Declarative operation (not CRUD)--this makes it easy for a user not to care what the existing state is, just about the final state. ``started/stopped``, ``present/absent``--don't overload options too much. It is preferable to add a new, simple option than to add choices/states that don't fit with existing ones.
* Keep options small, having them take large data structures might save us a few tasks, but adds a complex requirement that we cannot easily validate before passing on to the module.
* Allow an "expert mode". This may sound like the absolute opposite of the previous one, but it is always best to let expert users deal with complex data. This requires different modules in some cases, so that you end up having one (1) expert module and several 'piecemeal' ones (ec2_vpc_net?). The reason for this is not, as many users express, because it allows a single task and keeps plays small (which just moves the data complexity into vars files, leaving you with a slightly different structure in another YAML file). It does, however, allow for a more 'atomic' operation against the underlying APIs and services.
* Informative responses: Please note, that for >= 2.0, it is required that return data to be documented.
* Always return useful data, even when there is no change.
* Be consistent about returns (some modules are too random), unless it is detrimental to the state/action.
* Make returns reusable--most of the time you don't want to read it, but you do want to process it and re-purpose it.
* Return diff if in diff mode. This is not required for all modules, as it won't make sense for certain ones, but please attempt to include this when applicable).
* Code: This applies to all code in general, but often seems to be missing from modules, so please keep the following in mind as you work.
* Validate upfront--fail fast and return useful and clear error messages.
* Defensive programming--modules should be designed simply enough that this should be easy. Modules should always handle errors gracefully and avoid direct stacktraces. Ansible deals with this better in 2.0 and returns them in the results.
* Fail predictably--if we must fail, do it in a way that is the most expected. Either mimic the underlying tool or the general way the system works.
* Modules should not do the job of other modules, that is what roles are for. Less magic is more.
* Don't reinvent the wheel. Part of the problem is that code sharing is not that easy nor documented, we also need to expand our base functions to provide common patterns (retry, throttling, etc).
* Support check mode. This is not required for all modules, as it won't make sense for certain ones, but please attempt to include this when applicable). For more information, refer to :ref:`check_mode_drift` and :ref:`check_mode_dry`.
* `required` should always be present, be it true or false
* If `required` is false you need to document `default`, even if the default is 'None' (which is the default if no parameter is supplied). Make sure default parameter in docs matches default parameter in code.
* `default` is not needed for `required: true`
* Remove unnecessary doc like `aliases: []` or `choices: []`
* The version is not a float number and value the current development version
* Verify that arguments in doc and module spec dict are identical
* For password / secret arguments no_log=True should be set
* Requirements should be documented, using the `requirements=[]` field
* Author should be set, name and github id at least
* Made use of U() for urls, C() for files and options, I() for params, M() for modules?
* GPL 3 License header
* Does module use check_mode? Could it be modified to use it? Document it
* Examples: make sure they are reproducible
* Return: document the return structure of the module
* Exceptions: The module must handle them. (exceptions are bugs)
* Give out useful messages on what you were doing and you can add the exception message to that.
* Avoid catchall exceptions, they are not very useful unless the underlying API gives very good error messages pertaining the attempted action.
* Module-dependent guidelines: Additional module guidelines may exist for certain families of modules.
* Be sure to check out the modules themselves for additional information.
* Amazon: https://github.com/ansible/ansible-modules-extras/blob/devel/cloud/amazon/GUIDELINES.md
* Modules should make use of the "extends_documentation_fragment" to ensure documentation available. For example, the AWS module should include::
extends_documentation_fragment:
- aws
- ec2
* The module must not use sys.exit() --> use fail_json() from the module object.
* The module must not use sys.exit() --> use fail_json() from the module object
* Import custom packages in try/except and handled with fail_json() in main() e.g.::
try:
@ -673,10 +507,10 @@ The following checklist items are important guidelines for people who want to c
HAS_LIB=False
* The return structure should be consistent, even if NA/None are used for keys normally returned under other options.
* Are module actions idempotent? If not document in the descriptions or the notes.
* Are module actions idempotent? If not document in the descriptions or the notes
* Import module snippets `from ansible.module_utils.basic import *` at the bottom, conserves line numbers for debugging.
* Call your :func:`main` from a conditional so that it would be possible to
import them into unittests in the future example::
test them in the future example::
if __name__ == '__main__':
main()
@ -694,7 +528,6 @@ The following checklist items are important guidelines for people who want to c
* When fetching URLs, please use either fetch_url or open_url from ansible.module_utils.urls
rather than urllib2; urllib2 does not natively verify TLS certificates and so is insecure for https.
Windows modules checklist
`````````````````````````
* Favour native powershell and .net ways of doing things over calls to COM libraries or calls to native executables which may or may not be present in all versions of windows
@ -705,34 +538,24 @@ Windows modules checklist
#!powershell
then::
then::
<GPL header>
then::
then::
# WANT_JSON
# POWERSHELL_COMMON
then, to parse all arguments into a variable modules generally use::
then, to parse all arguments into a variable modules generally use::
$params = Parse-Args $args
* Arguments:
* Try and use state present and state absent like other modules
* You need to check that all your mandatory args are present. You can do this using the builtin Get-AnsibleParam function.
* Required arguments::
$package = Get-AnsibleParam -obj $params -name name -failifempty $true
* Required arguments with name validation::
$state = Get-AnsibleParam -obj $params -name "State" -ValidateSet "Present","Absent" -resultobj $resultobj -failifempty $true
* Optional arguments with name validation::
$state = Get-AnsibleParam -obj $params -name "State" -default "Present" -ValidateSet "Present","Absent"
* the If "FailIfEmpty" is true, the resultobj parameter is used to specify the object returned to fail-json. You can also override the default message
using $emptyattributefailmessage (for missing required attributes) and $ValidateSetErrorMessage (for attribute validation errors)
* Look at existing modules for more examples of argument checking.
@ -759,11 +582,11 @@ Windows modules checklist
Deprecating and making module aliases
``````````````````````````````````````
Starting in 1.8, you can deprecate modules by renaming them with a preceding _, i.e. old_cloud.py to
_old_cloud.py. This keeps the module available, but hides it from the primary docs and listing.
Starting in 1.8 you can deprecate modules by renaming them with a preceding _, i.e. old_cloud.py to
_old_cloud.py, This will keep the module available but hide it from the primary docs and listing.
You can also rename modules and keep an alias to the old name by using a symlink that starts with _.
This example allows the stat module to be called with fileinfo, making the following examples equivalent::
This example allows the stat module to be called with fileinfo, making the following examples equivalent
EXAMPLES = '''
ln -s stat.py _fileinfo.py

View File

@ -88,7 +88,7 @@ and is guaranteed to entertain and/or annoy coworkers.
Configuring
+++++++++++
To activate a callback drop it in a callback directory as configured in :ref:`ansible.cfg <callback_plugins>`. Plugin load order is alphanumeric in nature. If you have a plugin you want to run first consider naming it `1_first.py`, or if you have a plugin you want to run last consider naming it `z_last.py`.
To activate a callback drop it in a callback directory as configured in :ref:`ansible.cfg <callback_plugins>`.
.. _callback_development:
@ -112,7 +112,6 @@ to /usr/share/ansible/plugins, in a subfolder for each plugin type::
* connection_plugins
* filter_plugins
* vars_plugins
* strategy_plugins
To change this path, edit the ansible configuration file.

View File

@ -1,400 +0,0 @@
.. _flow_modules:
=======
Modules
=======
This in-depth dive helps you understand Ansible's program flow to execute
modules. It is written for people working on the portions of the Core Ansible
Engine that execute a module. Those writing Ansible Modules may also find this
in-depth dive to be of interest, but individuals simply using Ansible Modules
will not likely find this to be helpful.
.. _flow_types_of_modules:
Types of Modules
================
Ansible supports several different types of modules in its code base. Some of
these are for backwards compatibility and others are to enable flexibility.
.. _flow_action_plugins:
Action Plugins
--------------
Action Plugins look like modules to end users who are writing :term:`playbooks` but
they're distinct entities for the purposes of this paper. Action Plugins
always execute on the controller and are sometimes able to do all work there
(for instance, the debug Action Plugin which prints some text for the user to
see or the assert Action Plugin which can test whether several values in
a playbook satisfy certain criteria.)
More often, Action Plugins set up some values on the controller, then invoke an
actual module on the managed node that does something with these values. An
easy to understand version of this is the :ref:`template Action Plugin
<template>`. The :ref:`template Action Plugin <template>` takes values from
the user to construct a file in a temporary location on the controller using
variables from the playbook environment. It then transfers the temporary file
to a temporary file on the remote system. After that, it invokes the
:ref:`copy module <copy>` which operates on the remote system to move the file
into its final location, sets file permissions, and so on.
.. _flow_new_style_modules:
New-style Modules
-----------------
All of the modules that ship with Ansible fall into this category.
New-style modules have the arguments to the module embedded inside of them in
some manner. Non-new-style modules must copy a separate file over to the
managed node, which is less efficient as it requires two over-the-wire
connections instead of only one.
.. _flow_python_modules:
Python
^^^^^^
New-style Python modules use the :ref:`ziploader` framework for constructing
modules. All official modules (shipped with Ansible) use either this or the
:ref:`powershell module framework <flow_powershell_modules>`.
These modules use imports from :code:`ansible.module_utils` in order to pull in
boilerplate module code, such as argument parsing, formatting of return
values as :term:`JSON`, and various file operations.
.. note:: In Ansible, up to version 2.0.x, the official Python modules used the
:ref:`module_replacer` framework. For module authors, :ref:`ziploader` is
largely a superset of :ref:`module_replacer` functionality, so you usually
do not need to know about one versus the other.
.. _flow_powershell_modules:
Powershell
^^^^^^^^^^
New-style powershell modules use the :ref:`module_replacer` framework for
constructing modules. These modules get a library of powershell code embedded
in them before being sent to the managed node.
.. _flow_josnargs_modules:
JSONARGS
^^^^^^^^
Scripts can arrange for an argument string to be placed within them by placing
the string ``<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>`` somewhere inside of the
file. The module typically sets a variable to that value like this::
json_arguments = """<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>"""
Which is expanded as::
json_arguments = """{"param1": "test's quotes", "param2": "\"To be or not to be\" - Hamlet"}"""
.. note:: Ansible outputs a :term:`JSON` string with bare quotes. Double quotes are
used to quote string values, double quotes inside of string values are
backslash escaped, and single quotes may appear unescaped inside of
a string value. To use JSONARGS, your scripting language must have a way
to handle this type of string. The example uses Python's triple quoted
strings to do this. Other scripting languages may have a similar quote
character that won't be confused by any quotes in the JSON or it may
allow you to define your own start-of-quote and end-of-quote characters.
If the language doesn't give you any of these then you'll need to write
a :ref:`non-native JSON module <flow_want_json_modules>` or
:ref:`Old-style module <flow_old_style_modules>` instead.
The module typically parses the contents of ``json_arguments`` using a JSON
library and then use them as native variables throughout the rest of its code.
.. _flow_want_json_modules:
Non-native want JSON modules
----------------------------
If a module has the string ``WANT_JSON`` in it anywhere, Ansible treats
it as a non-native module that accepts a filename as its only command line
parameter. The filename is for a temporary file containing a :term:`JSON`
string containing the module's parameters. The module needs to open the file,
read and parse the parameters, operate on the data, and print its return data
as a JSON encoded dictionary to stdout before exiting.
These types of modules are self-contained entities. As of Ansible 2.1, Ansible
only modifies them to change a shebang line if present.
.. seealso:: Examples of Non-native modules written in ruby are in the `Ansible
for Rubyists <https://github.com/ansible/ansible-for-rubyists>`_ repository.
.. _flow_old_style_modules:
Old-style Modules
-----------------
Old-style modules are similar to
:ref:`want JSON modules <flow_want_json_modules>`, except that the file that
they take contains ``key=value`` pairs for their parameters instead of
:term:`JSON`.
Ansible decides that a module is old-style when it doesn't have any of the
markers that would show that it is one of the other types.
.. _flow_how_modules_are_executed:
How modules are executed
========================
When a user uses :program:`ansible` or :program:`ansible-playbook`, they
specify a task to execute. The task is usually the name of a module along
with several parameters to be passed to the module. Ansible takes these
values and processes them in various ways before they are finally executed on
the remote machine.
.. _flow_executor_task_executor:
executor/task_executor
----------------------
The TaskExecutor receives the module name and parameters that were parsed from
the :term:`playbook <playbooks>` (or from the command line in the case of
:command:`/usr/bin/ansible`). It uses the name to decide whether it's looking
at a module or an :ref:`Action Plugin <flow_action_plugins>`. If it's
a module, it loads the :ref:`Normal Action Plugin <flow_normal_action_plugin>`
and passes the name, variables, and other information about the task and play
to that Action Plugin for further processing.
.. _flow_normal_action_plugin:
Normal Action Plugin
--------------------
The ``normal`` Action Plugin executes the module on the remote host. It is
the primary coordinator of much of the work to actually execute the module on
the managed machine.
* It takes care of creating a connection to the managed machine by
instantiating a Connection class according to the inventory configuration for
that host.
* It adds any internal Ansible variables to the module's parameters (for
instance, the ones that pass along ``no_log`` to the module).
* It takes care of creating any temporary files on the remote machine and
cleans up afterwards.
* It does the actual work of pushing the module and module parameters to the
remote host, although the :ref:`module_common <flow_executor_module_common>`
code described next does the work of deciding which format those will take.
* It handles any special cases regarding modules (for instance, various
complications around Windows modules that must have the same names as Python
modules, so that internal calling of modules from other Action Plugins work.)
Much of this functionality comes from the :class:`BaseAction` class,
which lives in :file:`plugins/action/__init__.py`. It makes use of Connection
and Shell objects to do its work.
.. note::
When :term:`tasks <tasks>` are run with the ``async:`` parameter, Ansible
uses the ``async`` Action Plugin instead of the ``normal`` Action Plugin
to invoke it. That program flow is currently not documented. Read the
source for information on how that works.
.. _flow_executor_module_common:
executor/module_common.py
-------------------------
Code in :file:`executor/module_common.py` takes care of assembling the module
to be shipped to the managed node. The module is first read in, then examined
to determine its type. :ref:`PowerShell <flow_powershell_modules>` and
:ref:`JSON-args modules <flow_jsonargs_modules>` are passed through
:ref:`Module Replacer <module_replacer>`. New-style
:ref:`Python modules <flow_python_modules>` are assembled by :ref:`ziploader`.
:ref:`Non-native-want-JSON <flow_want_json_modules>` and
:ref:`Old-Style modules <flow_old_style_modules>` aren't touched by either of
these and pass through unchanged. After the assembling step, one final
modification is made to all modules that have a shebang line. Ansible checks
whether the interpreter in the shebang line has a specific path configured via
an ``ansible_$X_interpreter`` inventory variable. If it does, Ansible
substitutes that path for the interpreter path given in the module. After
this Ansible returns the complete module data and the module type to the
:ref:`Normal Action <_flow_normal_action_plugin>` which continues execution of
the module.
Next we'll go into some details of the two assembler frameworks.
.. _module_replacer:
Module Replacer
^^^^^^^^^^^^^^^
The Module Replacer is essentially a preprocessor (like the C Preprocessor for
those familiar with that language). It does straight substitutions of
specific substring patterns in the module file. There are two types of
substitutions:
* Replacements that only happen in the module file. These are public
replacement strings that modules can utilize to get helpful boilerplate or
access to arguments.
- :code:`from ansible.module_utils.MOD_LIB_NAME import *` is replaced with the
contents of the :file:`ansible/module_utils/MOD_LIB_NAME.py` These should
only be used with :ref:`new-style Python modules <flow_python_modules>`.
- :code:`#<<INCLUDE_ANSIBLE_MODULE_COMMON>>` is equivalent to
:code:`from ansible.module_utils.basic import *` and should also only apply
to new-style Python modules.
- :code:`# POWERSHELL_COMMON` substitutes the contents of
:file:`ansible/module_utils/powershell.ps1`. It should only be used with
:ref:`new-style Powershell modules <flow_powershell_modules>`.
* Replacements that are used by ``ansible.module_utils`` code. These are internal
replacement patterns. They may be used internally, in the above public
replacements, but shouldn't be used directly by modules.
- :code:`"<<ANSIBLE_VERSION>>"` is substituted with the Ansible version. In
a new-style Python module, it's better to use ``from ansible import
__version__`` and then use ``__version__`` instead.
- :code:`"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>"` is substituted with
a string which is the Python ``repr`` of the :term:`JSON` encoded module
parameters. Using ``repr`` on the JSON string makes it safe to embed in
a Python file. In :ref:`new-style Python modules <flow_python_modules>`
under :ref:`ziploader` this is passed in via an environment variable
instead.
- :code:`<<SELINUX_SPECIAL_FILESYSTEMS>>` substitutes a string which is
a comma separated list of file systems which have a file system dependent
security context in SELinux. In new-style Python modules, this is found
by looking up ``SELINUX_SPECIAL_FS`` from the
:envvar:`ANSIBLE_MODULE_CONSTANTS` environment variable. See the
:ref:`ziploader` documentation for details.
- :code:`<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>` substitutes the module
parameters as a JSON string. Care must be taken to properly quote the
string as JSON data may contain quotes. This pattern is not substituted
in new-style Python modules as they can get the module parameters via the
environment variable.
- the string :code:`syslog.LOG_USER` is replaced wherever it occurs with the
value of ``syslog_facility`` from the :file:`ansible.cfg` or any
``ansible_syslog_facility`` inventory variable that applies to this host. In
new-style Python modules, you can get the value of the ``syslog_facility``
by looking up ``SYSLOG_FACILITY`` in the :envvar:`ANSIBLE_MODULE_CONSTANTS`
environment variable. See the :ref:`ziploader` documentation for details.
.. _ziploader:
ziploader
^^^^^^^^^
Ziploader differs from :ref:`module_replacer` in that it uses real Python
imports of things in module_utils instead of merely preprocessing the module.
It does this by constructing a zipfile--which includes the module file, files
in :file:`ansible/module_utils` that are imported by the module, and some
boilerplate to pass in the constants. The zipfile is then Base64 encoded and
wrapped in a small Python script which decodes the Base64 encoding and places
the zipfile into a temp direcrtory on the managed node. It then extracts just
the ansible module script from the zip file and places that in the temporary
directory as well. Then it sets the PYTHONPATH to find python modules inside
of the zip file and invokes :command:`python` on the extracted ansible module.
.. note::
Ansible wraps the zipfile in the Python script for two reasons:
* for compatibility with Python-2.4 and Python-2.6 which have less
featureful versions of Python's ``-m`` command line switch.
* so that pipelining will function properly. Pipelining needs to pipe the
Python module into the Python interpreter on the remote node. Python
understands scripts on stdin but does not understand zip files.
In ziploader, any imports of Python modules from the ``ansible.module_utils``
package trigger inclusion of that Python file into the zipfile. Instances of
:code:`#<<INCLUDE_ANSIBLE_MODULE_COMMON>>` in the module are turned into
:code:`from ansible.module_utils.basic import *` and
:file:`ansible/module-utils/basic.py` is then included in the zipfile. Files
that are included from module_utils are themselves scanned for imports of other
Python modules from module_utils to be included in the zipfile as well.
.. warning::
At present, Ziploader cannot determine whether an import should be
included if it is a relative import. Always use an absolute import that
has ``ansible.module_utils`` in it to allow ziploader to determine that
the file should be included.
.. _flow_passing_module_args:
Passing args
~~~~~~~~~~~~
In :ref:`module_replacer`, module arguments are turned into a JSON-ified
string and substituted into the combined module file. In :ref:`ziploader`,
the JSON-ified string is passed into the module via stdin. When
a :class:`ansible.module_utils.basic.AnsibleModule` is instantiated,
it parses this string and places the args into
:attribute:`AnsibleModule.params` where it can be accessed by the module's
other code.
.. _flow_passing_module_constants:
Passing constants
~~~~~~~~~~~~~~~~~
Currently, there are three constants passed from the controller to the modules:
``ANSIBLE_VERSION``, ``SELINUX_SPECIAL_FS``, and ``SYSLOG_FACILITY``. In
:ref:`module_replacer`, ``ANSIBLE_VERSION`` and ``SELINUX_SPECIAL_FS`` were
substituted into the global variables
:code:`ansible.module_utils.basic.ANSIBLE_VERSION` and
:code:`ansible.module_utils.basic.SELINUX_SPECIAL_FS`. ``SYSLOG_FACILITY`` didn't
get placed into a variable. Instead, any occurrences of the string
``syslog.LOG_USER`` in the combined module file were replaced with ``syslog.``
followed by the string contained in ``SYSLOG_FACILITY``. All of these have
changed in :ref:`ziploader`.
The Ansible verison can now be used by a module by importing ``__version__``
from ansible::
from ansible import __version__
module.exit_json({'msg': 'module invoked by ansible %s' % __version__})
For now, :code:`ANSIBLE_VERSION` is also available at its old location inside of
``ansible.module_utils.basic``, but that will eventually be removed.
``SELINUX_SPECIAL_FS`` and ``SYSLOG_FACILITY`` have changed much more.
:ref:`ziploader` passes these as part of the JSON-ified argument string via stdin.
When
:class:`ansible.module_utils.basic.AnsibleModule` is instantiated, it parses this
string and places the constants into :attribute:`AnsibleModule.constants`
where other code can access it.
Unlike the ``ANSIBLE_VERSION``, where some efforts were made to keep the old
backwards compatible globals available, these two constants are not available
at their old names. This is a combination of the degree to which these are
internal to the needs of ``module_utils.basic`` and, in the case of
``SYSLOG_FACILITY``, how hacky and unsafe the previous implementation was.
Porting code from the :ref:`module_replacer` method of getting
``SYSLOG_FACILITY`` to the new one is a little more tricky than the other
constants and args, due to just how hacky the old way was. Here's an example
of using it in the new way::
import syslog
facility_name = module.constants.get('SYSLOG_FACILITY')
facility = getattr(syslog, facility_name)
syslog.openlog(str(module), 0, facility)
.. _flow_special_considerations:
Special Considerations
----------------------
.. _flow_pipelining:
Pipelining
^^^^^^^^^^
Ansible can transfer a module to a remote machine in one of two ways:
* it can write out the module to a temporary file on the remote host and then
use a second connection to the remote host to execute it with the
interpreter that the module needs
* or it can use what's known as pipelining to execute the module by piping it
into the remote interpreter's stdin.
Pipelining only works with modules written in Python at this time because
Ansible only knows that Python supports this mode of operation. Supporting
pipelining means that whatever format the module payload takes before being
sent over the wire must be executable by Python via stdin.

View File

@ -1,48 +0,0 @@
Releases
========
.. contents:: Topics
:local:
.. _schedule:
Release Schedule
````````````````
Ansible is on a 'flexible' 4 month release schedule, sometimes this can be extended if there is a major change that requires a longer cycle (i.e. 2.0 core rewrite).
Currently modules get released at the same time as the main Ansible repo, even though they are separated into ansible-modules-core and ansible-modules-extras.
The major features and bugs fixed in a release should be reflected in the CHANGELOG.md, minor ones will be in the commit history (FIXME: add git exmaple to list).
When a fix/feature gets added to the `devel` branch it will be part of the next release, some bugfixes can be backported to previous releases and might be part of a minor point release if it is deemed necessary.
Sometimes an RC can be extended by a few days if a bugfix makes a change that can have far reaching consequences, so users have enough time to find any new issues that may stem from this.
.. _methods:
Release methods
````````````````
Ansible normally goes through a 'release candidate', issuing an RC1 for a release, if no major bugs are discovered in it after 5 business days we'll get a final release.
Otherwise fixes will be applied and an RC2 will be provided for testing and if no bugs after 2 days, the final release will be made, iterating this last step and incrementing the candidate number as we find major bugs.
.. _freezing:
Release feature freeze
``````````````````````
During the release candidate process, the focus will be on bugfixes that affect the RC, new features will be delayed while we try to produce a final version. Some bugfixes that are minor or don't affect the RC will also be postponed until after the release is finalized.
.. seealso::
:doc:`developing_api`
Python API to Playbooks and Ad Hoc Task Execution
:doc:`developing_modules`
How to develop modules
:doc:`developing_plugins`
How to develop plugins
`Ansible Tower <http://ansible.com/ansible-tower>`_
REST API endpoint and GUI for Ansible, syncs with dynamic inventory
`Development Mailing List <http://groups.google.com/group/ansible-devel>`_
Mailing list for development topics
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@ -81,34 +81,27 @@ and destination repositories. It will look something like this::
Someuser wants to merge 1 commit into ansible:devel from someuser:feature_branch_name
.. note::
It is important that the PR request target be ansible:devel, as we do not accept pull requests into any other branch. Dot releases are cherry-picked manually by ansible staff.
It is important that the PR request target be ansible:devel, as we do not accept pull requests into any other branch.
Dot releases are cherry-picked manually by ansible staff.
The username and branch at the end are the important parts, which will be turned into git commands as follows::
git checkout -b testing_PRXXXX devel
git pull https://github.com/someuser/ansible.git feature_branch_name
The first command creates and switches to a new branch named testing_PRXXXX, where the XXXX is the actual issue number associated with the pull request (for example, 1234). This branch is based on the devel branch. The second command pulls the new code from the users feature branch into the newly created branch.
The first command creates and switches to a new branch named testing_PRXXXX, where the XXXX is the actual issue number associated
with the pull request (for example, 1234). This branch is based on the devel branch. The second command pulls the new code from the
users feature branch into the newly created branch.
.. note::
If the GitHub user interface shows that the pull request will not merge cleanly, we do not recommend proceeding if you are not somewhat familiar with git and coding, as you will have to resolve a merge conflict. This is the responsibility of the original pull request contributor.
If the GitHub user interface shows that the pull request will not merge cleanly, we do not recommend proceeding if you
are not somewhat familiar with git and coding, as you will have to resolve a merge conflict. This is the responsibility of
the original pull request contributor.
.. note::
Some users do not create feature branches, which can cause problems when they have multiple, un-related commits in their version of `devel`. If the source looks like `someuser:devel`, make sure there is only one commit listed on the pull request.
Finding a Pull Request for Ansible Modules
++++++++++++++++++++++++++++++++++++++++++
Ansible modules are in separate repositories, which are managed as Git submodules. Here's a step by step process for checking out a PR for an Ansible extras module, for instance:
1. git clone https://github.com/ansible/ansible.git
2. cd ansible
3. git submodule init
4. git submodule update --recursive [ fetches the submodules ]
5. cd lib/ansible/modules/extras
6. git fetch origin pull/1234/head:pr/1234 [ fetches the specific PR ]
7. git checkout pr/1234 [ do your testing here ]
8. cd /path/to/ansible/clone
9. git submodule update --recursive
Some users do not create feature branches, which can cause problems when they have multiple, un-related commits in
their version of `devel`. If the source looks like `someuser:devel`, make sure there is only one commit listed on
the pull request.
For Those About To Test, We Salute You
++++++++++++++++++++++++++++++++++++++
@ -152,7 +145,7 @@ Once the files are in place, you can run the provided playbook (if there is one)
ansible-playbook -vvv playbook_name.yml
If there's no playbook, you may have to copy and paste playbook snippets or run an ad-hoc command that was pasted in.
If there's not a playbook, you may have to copy and paste playbook snippets or run a ad-hoc command that was pasted in.
Our issue template also included sections for "Expected Output" and "Actual Output", which should be used to gauge the output
from the provided examples.

View File

@ -15,7 +15,6 @@ Setting environment variables can be done with the `environment` keyword. It can
PATH: "{{ ansible_env.PATH }}:/thingy/bin"
SOME: value
.. note:: starting in 2.0.1 the setup task from gather_facts also inherits the environment directive from the play, you might need to use the `|default` filter to avoid errors if setting this at play level.
How do I handle different machines needing different user accounts or ports to log in with?
@ -39,7 +38,7 @@ You can also dictate the connection type to be used, if you want::
foo.example.com
bar.example.com
You may also wish to keep these in group variables instead, or file them in a group_vars/<groupname> file.
You may also wish to keep these in group variables instead, or file in them in a group_vars/<groupname> file.
See the rest of the documentation for more information about how to organize variables.
.. _use_ssh:
@ -175,9 +174,7 @@ How do I loop over a list of hosts in a group, inside of a template?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A pretty common pattern is to iterate over a list of hosts inside of a host group, perhaps to populate a template configuration
file with a list of servers. To do this, you can just access the "$groups" dictionary in your template, like this:
.. code-block:: jinja
file with a list of servers. To do this, you can just access the "$groups" dictionary in your template, like this::
{% for host in groups['db_servers'] %}
{{ host }}
@ -187,7 +184,7 @@ If you need to access facts about these hosts, for instance, the IP address of e
- hosts: db_servers
tasks:
- debug: msg="doesn't matter what you do, just that they were talked to previously."
- # doesn't matter what you do, just that they were talked to previously.
Then you can use the facts inside your template, like this::
@ -307,6 +304,8 @@ How do I keep secret data in my playbook?
If you would like to keep secret data in your Ansible content and still share it publicly or keep things in source control, see :doc:`playbooks_vault`.
.. _i_dont_see_my_question:
In Ansible 1.8 and later, if you have a task that you don't want to show the results or command given to it when using -v (verbose) mode, the following task or playbook attribute can be useful::
- name: secret task
@ -321,34 +320,9 @@ The no_log attribute can also apply to an entire play::
no_log: True
Though this will make the play somewhat difficult to debug. It's recommended that this
be applied to single tasks only, once a playbook is completed.
be applied to single tasks only, once a playbook is completed.
.. _when_to_use_brackets:
.. _dynamic_variables:
.. _interpolate_variables:
When should I use {{ }}? Also, how to interpolate variables or dynamic variable names
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A steadfast rule is 'always use {{ }} except when `when:`'.
Conditionals are always run through Jinja2 as to resolve the expression,
so `when:`, `failed_when:` and `changed_when:` are always templated and you should avoid adding `{{}}`.
In most other cases you should always use the brackets, even if previouslly you could use variables without specifying (like `with_` clauses),
as this made it hard to distinguish between an undefined variable and a string.
Another rule is 'moustaches don't stack'. We often see this::
{{ somevar_{{other_var}} }}
The above DOES NOT WORK, if you need to use a dynamic variable use the hostvars or vars dictionary as appropriate::
{{ hostvars[inventory_hostname]['somevar_' + other_var] }}
.. _i_dont_see_my_question:
I don't see my question here
++++++++++++++++++++++++++++

View File

@ -85,6 +85,10 @@ And here's an example showing some specific version downloads from multiple sour
# from GitHub
- src: https://github.com/bennojoy/nginx
# from GitHub installing to a relative path
- src: https://github.com/bennojoy/nginx
path: vagrant/roles/
# from GitHub, overriding the name and specifying a specific tag
- src: https://github.com/bennojoy/nginx
version: master
@ -106,6 +110,7 @@ And here's an example showing some specific version downloads from multiple sour
- src: git@gitlab.company.com:mygroup/ansible-base.git
scm: git
version: 0.1.0
path: roles/
As you can see in the above, there are a large amount of controls available
to customize where roles can be pulled from, and what to save roles as.
@ -328,7 +333,7 @@ This only removes the role from Galaxy. It does not impact the actual GitHub rep
`https://galaxy-qa.ansible.com <https://galaxy-qa.ansible.com>`_. You can also add a *server* definition in the [galaxy]
section of your ansible.cfg file.
Setup Travis Integrations
Setup Travis Integerations
--------------------------
Using the setup command you can enable notifications from `travis <http://travis-ci.org>`_. The setup command expects that the user previously authenticated with Galaxy using the login command.

View File

@ -7,477 +7,410 @@ Consult the documentation home page for the full documentation and to see the te
to check your knowledge of Ansible's components and understand how they fit together. It's something you might wish to read for review or
when a term comes up on the mailing list.
.. glossary::
Action
++++++
Action
An action is a part of a task that specifies which of the modules to
run and which arguments to pass to that module. Each task can have
only one action, but it may also have other parameters.
An action is a part of a task that specifies which of the modules to run and the 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 perform some quick command, using
:command:`/usr/bin/ansible`, rather than the :term:`orchestration`
language, which is :command:`/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 can be accomplished by
writing a :term:`playbook <playbooks>` and playbooks can also glue
lots of other operations together.
Ad Hoc
++++++
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
:command:`/usr/bin/ansible` and :command:`/usr/bin/ansible-playbook`.
Refers to running Ansible to perform 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 can be accomplished by writing a playbook, and playbooks can also glue lots of other operations together.
Callback Plugin
Refers to some user-written code that can intercept results from
Ansible and do something with them. Some supplied examples in the
GitHub project perform custom logging, send email, or even play sound
effects.
Async
+++++
Check Mode
Refers to running Ansible with the ``--check`` option, which does not
make any changes on the remote systems, but only outputs the changes
that might occur if the command ran without this flag. This is
analogous to so-called "dry run" modes in other systems, though the
user should be warned that this does not take into account unexpected
command failures or cascade effects (which is true of similar modes in
other systems). Use this to get an idea of what might happen, but do
not substitute it for a good staging environment.
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.
Connection Plugin
By default, Ansible talks to remote machines through pluggable
libraries. Ansible supports native OpenSSH (:term:`SSH (Native)`) or
a Python implementation called :term:`paramiko`. OpenSSH is preferred
if you are using a recent version, and also enables some features like
Kerberos and jump hosts. This is covered in the :ref:`getting
started section <remote_connection_information>`. There are also
other connection types like ``accelerate`` mode, which must be
bootstrapped over one of the SSH-based connection types but is very
fast, and local mode, which acts on the local system. Users can also
write their own connection plugins.
Callback Plugin
+++++++++++++++
Conditionals
A conditional is an expression that evaluates to true or false that
decides whether a given task is executed on a given machine or not.
Ansible's conditionals are powered by the 'when' statement, which are
discussed in the :doc:`playbook documentation <playbooks>`.
Refers to some user-written code that can intercept results from Ansible and do something with them. Some supplied examples
in the GitHub project perform custom logging, send email, or even play sound effects.
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.
Check Mode
++++++++++
Executor
A core software component of Ansible that is the power behind
:command:`/usr/bin/ansible` directly -- and corresponds to the
invocation of each task in a :term:`playbook <playbooks>`. The
Executor is something Ansible developers may talk about, but it's not
really user land vocabulary.
Refers to running Ansible with the ``--check`` option, which does not make any changes on the remote systems, but only outputs the changes that
might occur if the command ran without this flag. This is analogous to so-called "dry run" modes in other systems, though the user should
be warned that this does not take into account unexpected command failures or cascade effects (which is true of similar modes in other
systems). Use this to get an idea of what might happen, but it is not a substitute for a good staging environment.
Facts
Facts are simply things that are discovered about remote nodes. While
they can be used in :term:`playbooks` and templates just like
variables, facts are things that are inferred, rather than set. Facts
are automatically discovered by Ansible when running plays by
executing the internal :ref:`setup module <setup>` 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 or you can tell
ansible to collect only a subset of the full facts via the
``gather_subset:`` option. For the convenience of users who are
switching from other configuration management systems, the fact module
will also pull in facts from the :program:`ohai` and :program:`facter`
tools if they are installed. These are fact libraries from Chef and
Puppet, respectively. (These may also be disabled via
``gather_subset:``)
Connection Type, Connection Plugin
++++++++++++++++++++++++++++++++++
Filter Plugin
A filter plugin is something that most users will never need to
understand. These allow for the creation of new :term:`Jinja2`
filters, which are more or 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 :ref:`API docs section <developing_filter_plugins>`.
By default, Ansible talks to remote machines through pluggable libraries. Ansible supports native OpenSSH ('ssh'), or a Python
implementation called 'paramiko'. OpenSSH is preferred if you are using a recent version, and also enables some features
like Kerberos and jump hosts. This is covered in the getting started section.
There are also other connection types like 'accelerate' mode, which must be bootstrapped
over one of the SSH-based connection types but is very fast, and local mode, which acts on the local system.
Users can also write their own connection plugins.
Forks
Ansible talks to remote nodes in parallel and 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 five (5)
forks, though if you have a lot of RAM, you can easily set this to
a value like 50 for increased parallelism.
Conditionals
++++++++++++
Gather Facts (Boolean)
:term:`Facts` are mentioned above. Sometimes when running a multi-play
:term:`playbook <playbooks>`, it is desirable to have some plays that
don't bother with fact computation if they aren't going to need to
utilize any of these values. Setting ``gather_facts: False`` on
a playbook allows this implicit fact gathering to be skipped.
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 are powered by the 'when' statement, and are
discussed in the playbook documentation.
Globbing
Globbing is a way to select lots of hosts based on wildcards, rather
than the name of the host specifically, or the name of the group they
are in. For instance, it is possible to select ``ww*`` to match all
hosts starting with ``www``. This concept is pulled directly from
:program:`Func`, one of Michael DeHaan's (an Ansible Founder) 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.
Diff Mode
+++++++++
Group
A group consists of several hosts assigned to a pool that can be
conveniently targeted together, as well as given variables that they
share in common.
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.
Group Vars
The :file:`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 convenient place to put variables that are
provided to a given group, especially complex data structures, so that
these variables do not have to be embedded in the :term:`inventory`
file or :term:`playbook <playbooks>`.
Facts
+++++
Handlers
Handlers are just like regular tasks in an Ansible
:term:`playbook <playbooks>` (see :term:`Tasks`) but are only run if
the Task contains a ``notify`` directive and also indicates that it
changed something. For example, if a config file is changed, then the
task referencing the config file templating operation may notify
a service restart handler. 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.
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 automatically discovered by Ansible when running plays by executing 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 the convenience of users who are switching from other configuration management 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, respectively.
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.
Filter Plugin
+++++++++++++
Host Specifier
Each :term:`Play <plays>` in Ansible maps a series of :term:`tasks` (which define the role,
purpose, or orders of a system) to a set of systems.
A filter plugin is something that most users will never need to understand. These allow for the creation of new Jinja2 filters, which
are more or 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.
This ``hosts:`` directive in each play is often called the hosts specifier.
Forks
+++++
It may select one system, many systems, one or more groups, or even
some hosts that are in one group and explicitly not in another.
Ansible talks to remote nodes in parallel and 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.
Host Vars
Just like :term:`Group Vars`, a directory alongside the inventory file named
:file:`host_vars/` can contain a file named after each hostname in the
inventory file, in :term:`YAML` format. This provides a convenient place to
assign variables to the host without having to embed them in the
:term:`inventory` file. The Host Vars file can also be used to define complex
data structures that can't be represented in the inventory file.
Gather Facts (Boolean)
++++++++++++++++++++++
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 way 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.
Facts are mentioned above. Sometimes when running a multi-play playbook, it is desirable to have some plays that don't bother with fact
computation if they aren't going to need to utilize any of these values. Setting `gather_facts: False` on a playbook allows this implicit
fact gathering to be skipped.
Includes
The idea that :term:`playbook <playbooks>` files (which are nothing
more than lists of :term:`plays`) can include other lists of plays,
and task lists can externalize lists of :term:`tasks` in other files,
and similarly with :term:`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 that play could be included more than once to
create a blog for both ``alice`` and ``bob``.
Globbing
++++++++
Inventory
A file (by default, Ansible uses a simple INI format) that describes
:term:`Hosts <Host>` and :term:`Groups <Group>` in Ansible. Inventory
can also be provided via an :term:`Inventory Script` (sometimes called
an "External Inventory Script").
Globbing is a way to select lots of hosts based on wildcards, 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.
Inventory Script
A very simple program (or a complicated one) that looks up
:term:`hosts <Host>`, :term:`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.
Group
+++++
Jinja2
Jinja2 is the preferred templating language of Ansible's template
module. It is a very simple Python template language that is
generally readable and easy to write.
A group consists of several hosts assigned to a pool that can be conveniently targeted together, and also given variables that they share in
common.
JSON
Ansible uses JSON for return data from remote modules. This allows
modules to be written in any language, not just Python.
Group Vars
++++++++++
Lazy Evaluation
In general, Ansible evaluates any variables in
:term:`playbook <playbooks>` content at the last possible second,
which means that if you define a data structure that data structure
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.
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 convenient place to put variables that will be provided to a given group, especially complex data structures, so that these
variables do not have to be embedded in the inventory file or playbook.
Library
A collection of modules made available to :command:`/usr/bin/ansible`
or an Ansible :term:`playbook <playbooks>`.
Handlers
++++++++
Limit Groups
By passing ``--limit somegroup`` to :command:`ansible` or
:command:`ansible-playbook`, the commands can be limited to a subset
of :term:`hosts <Host>`. For instance, this can be used to run
a :term:`playbook <playbooks>` that normally targets an entire set of
servers to one particular server.
Handlers are just like regular tasks in an Ansible playbook (see Tasks), but are only run if the Task contains a "notify" directive and
also indicates that it changed something. For example, if a config file is changed then the task referencing the config file templating
operation may notify a service restart handler. 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.
Local Action
A local_action directive in a :term:`playbook <playbooks>` targeting
remote machines means that the given step will actually occur on the
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.
Host
++++
Local Connection
By using ``connection: local`` in a :term:`playbook <playbooks>`, or
passing ``-c local`` to :command:`/usr/bin/ansible`, this indicates
that we are managing the local host and not a remote machine.
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.
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``, a basic looping
plugin, are implemented. There are also lookup plugins like
``with_file`` which load data from a file and ones for querying
environment variables, DNS text records, or key value stores. Lookup
plugins can also be accessed in templates, e.g.,
``{{ lookup('file','/path/to/file') }}``.
Host Specifier
++++++++++++++
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 :ref:`yum <yum>` and :ref:`apt <apt>`, are actually
optimized for this, and can install all packages given in those lists
within a single transaction, dramatically speeding up total time to
configuration.
Each Play in Ansible maps a series of tasks (which define the role, purpose, or orders of a system) to a set of systems.
Modules
Modules are the units of work that Ansible ships out to remote
machines. Modules are kicked off by either
:command:`/usr/bin/ansible` or :command:`/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 :term:`JSON`. 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 :term:`library`.
This "hosts:" directive in each play is often called the hosts specifier.
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 from a "one system at a time" perspective.
It may select one system, many systems, one or more groups, or even some hosts that are in one group and explicitly not in another.
Notify
The act of a :term:`task <tasks>` registering a change event and
informing a :term:`handler <handlers>` task that another
:term:`action` needs to be run at the end of the :term:`play <plays>`. 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.
Host Vars
+++++++++
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 necessary to touch systems in particular
orders, often to simulate rolling updates or to 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, emails may need to be sent or web services contacted.
Ansible orchestration is all about modeling that kind of process.
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 convenient 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 data structures that can't be represented in the
inventory file.
paramiko
By default, Ansible manages machines over SSH. The library that
Ansible uses by default to do this is a Python-powered library called
paramiko. The paramiko library is generally fast and easy to manage,
though users desiring Kerberos or Jump Host support may wish to switch
to a native SSH binary such as OpenSSH by specifying the connection
type in their :term:`playbooks`, or using the ``-c ssh`` flag.
Idempotency
+++++++++++
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 :)
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 way 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.
Plays
A :term:`playbook <playbooks>` is a list of plays. A play is
minimally a mapping between a set of :term:`hosts <Host>` selected by a host
specifier (usually chosen by :term:`groups <Group>` but sometimes by
hostname :term:`globs <Globbing>`) and the :term:`tasks` which run on those
hosts to define the role that those systems will perform. There can be
one or many plays in a playbook.
Includes
++++++++
Pull Mode
By default, Ansible runs in :term:`push mode`, which allows it very
fine-grained control over when it talks to each system. 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
:command:`ansible-pull` and can also be set up (or reconfigured) using
a push-mode :term:`playbook <playbooks>`. Most Ansible users use push
mode, but pull mode is included for variety and the sake of having
choices.
The idea that playbook files (which are nothing more than lists 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 that play could be included more than once to create a blog for both "alice" and "bob".
:command:`ansible-pull` works by checking configuration orders out of
git on a crontab and then managing the machine locally, using the
:term:`local connection` plugin.
Inventory
+++++++++
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 through complex orchestration processes without waiting for them
to check in.
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").
Register Variable
The result of running any :term:`task <tasks>` in Ansible can be
stored in a variable for use in a template or a conditional statement.
The keyword used to define the variable is called ``register``, taking
its 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.
Inventory Script
++++++++++++++++
Resource Model
Ansible modules work in terms of resources. For instance, the
:ref:`file module <file>` will select a particular file and ensure
that the attributes of that resource match a particular model. As an
example, we might wish to change the owner of :file:`/etc/motd` to
``root`` if it is not already set to ``root``, or set its mode to
``0644`` if it is not already set to ``0644``. The resource models
are :term:`idempotent <idempotency>` 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.
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.
Roles
Roles are units of organization in Ansible. Assigning a role to
a group of :term:`hosts <Host>` (or a set of :term:`groups <group>`,
or :term:`host patterns <Globbing>`, etc.) implies that they should
implement a specific behavior. A role may include applying certain
variable values, certain :term:`tasks`, and certain :term:`handlers`
-- or just one or more of these things. Because of the file structure
associated with a role, roles become redistributable units that allow
you to share behavior among :term:`playbooks` -- or even with other users.
Jinja2
++++++
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
:term:`playbooks` control 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 do so if desired.
Jinja2 is the preferred templating language of Ansible's template module. It is a very simple Python template language that is generally
readable and easy to write.
Serial
.. seealso::
JSON
++++
:term:`Rolling Update`
Ansible uses JSON for return data from remote modules. This allows modules to be written in any language, not just Python.
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 password-less and password-based sudo. Some operations that
don't normally work with sudo (like scp file transfer) can be achieved
with Ansible's :ref:`copy <copy>`, :ref:`template <template>`, and
:ref:`fetch <fetch>` modules while running in sudo mode.
Lazy Evaluation
+++++++++++++++
SSH (Native)
Native OpenSSH as an Ansible transport is specified with ``-c ssh``
(or a config file, or a directive in the :term:`playbook <playbooks>`)
and can be useful if wanting to login via Kerberized SSH or using SSH
jump hosts, etc. In 1.2.1, ``ssh`` will be used by default if the
OpenSSH binary on the control machine is sufficiently new.
Previously, Ansible selected ``paramiko`` as a default. 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`` is
a good choice. Ansible will warn you if it doesn't detect
ControlMaster/ControlPersist capability.
In general, Ansible evaluates any variables in playbook content at the last possible second, which means that if you define a data structure
that data structure 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.
Tags
Ansible allows tagging resources in a :term:`playbook <playbooks>`
with arbitrary keywords, and then running only the parts of the
playbook that correspond to those keywords. For instance, it is
possible to have an entire OS configuration, and have certain steps
labeled ``ntp``, and then run just the ``ntp`` steps to reconfigure
the time server information on a remote host.
Library
+++++++
Tasks
:term:`Playbooks` exist to run tasks. Tasks combine an :term:`action`
(a module and its arguments) with a name and optionally some other
keywords (like :term:`looping directives <loops>`). :term:`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.
A collection of modules made available to /usr/bin/ansible or an Ansible playbook.
Templates
Ansible can easily transfer files to remote systems but often it is
desirable to substitute variables in other files. Variables may come
from the :term:`inventory` file, :term:`Host Vars`, :term:`Group
Vars`, or :term:`Facts`. Templates use the :term:`Jinja2` template
engine and can also include logical constructs like loops and if
statements.
Limit Groups
++++++++++++
Transport
Ansible uses :term:``Connection Plugins`` to define types of available
transports. These are simply how Ansible will reach out to managed
systems. Transports included are :term:`paramiko`,
:term:`ssh <SSH (Native)>` (using OpenSSH), and
:term:`local <Local Connection>`.
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.
When
An optional conditional statement attached to a :term:`task <tasks>` that is used to
determine if the task should run or not. If the expression following
the ``when:`` keyword evaluates to false, the task will be ignored.
Local Action
++++++++++++
Vars (Variables)
As opposed to :term:`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
:term:`playbooks`. They are declared things, not things that are
inferred from the remote system's current state or nature (which is
what Facts are).
A local_action directive in a playbook targeting remote machines means that the given step will actually occur on the 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.
YAML
Ansible does not want to force people to write programming language
code to automate infrastructure, so Ansible uses YAML to define
:term:`playbook <playbooks>` 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 DeHaan'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 languages (Python, Perl, Ruby, etc.).
Local Connection
++++++++++++++++
By using "connection: local" in a playbook, or passing "-c local" to /usr/bin/ansible, this indicates that we are managing the local
host and not a remote machine.
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", a basic looping plugin, are implemented,
but there are also lookup plugins like "with_file" which loads data from a file, and even ones for querying environment variables,
DNS text records, or key value stores. Lookup plugins can also be accessed in templates, e.g., ``{{ lookup('file','/path/to/file') }}``.
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 speeding 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'.
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 from a "one system at a time" perspective.
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 necessary to touch systems in particular orders,
often to simulate rolling updates or to 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, emails may need to be sent or web services contacted. Ansible
orchestration is all about modeling that kind of process.
paramiko
++++++++
By default, Ansible manages machines over SSH. The library that Ansible uses by default to do this is a Python-powered library called
paramiko. The paramiko library is generally fast and easy to manage, though users desiring Kerberos or Jump Host support may wish to switch
to a native SSH binary such as OpenSSH 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 selected by a host specifier (usually chosen by groups, but sometimes by hostname
globs) and the tasks which run on those hosts to define the role that those systems will perform. There
can be one or many plays in a playbook.
Pull Mode
+++++++++
By default, Ansible runs in push mode, which allows it very fine-grained control over when it talks to each system. 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 pull mode 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 through 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 define the variable is called 'register', taking its 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
and ensure that the attributes of that resource match a particular model. As an example, we might wish to change the owner of /etc/motd
to 'root' if it is not already set to root, or set its mode to '0644' if it is 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.
Roles
+++++
Roles are units of organization in Ansible. Assigning a role to a group of hosts (or a set of groups, or host patterns, etc.) implies that they should implement a specific behavior. A role
may include applying certain variable values, certain tasks, and certain handlers -- or just one or more of these things. Because of the file structure associated with a role, roles become
redistributable units that allow you to share behavior among playbooks -- or even with other users.
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 do so 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 user land
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 password-less and password-based sudo. Some operations that don't normally work with sudo (like scp
file transfer) can be achieved with Ansible's copy, template, and fetch modules while running in sudo mode.
SSH (Native)
++++++++++++
Native OpenSSH as an Ansible transport 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 using SSH jump hosts, etc. In 1.2.1, 'ssh' will be used by default if the OpenSSH binary
on the control machine is sufficiently new. Previously, Ansible selected 'paramiko' as a default.
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 is a good choice. Ansible will warn you if it doesn't detect ControlMaster/ControlPersist capability.
Tags
++++
Ansible allows tagging resources in a playbook with arbitrary keywords, and then running only the parts of the playbook that
correspond to those keywords. For instance, it is possible to have an entire OS configuration, and have certain steps
labeled "ntp", and then run just the "ntp" steps to reconfigure the time server information on a remote host.
Tasks
+++++
Playbooks exist to run tasks. Tasks combine an action (a module and its arguments) 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 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, SSH (using OpenSSH), and local.
When
++++
An optional conditional statement attached to a task that is used to determine if the task should run or not. If the expression following the "when:" keyword evaluates to false, the task will be ignored.
Van Halen
+++++++++
For no particular reason, other than the fact that Michael really likes them, all Ansible releases are codenamed 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 that there will ever be a Jump release, but a Van Halen III codename release is possible. 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 system's 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 languages (Python, Perl, Ruby, etc.).
.. seealso::

View File

@ -220,7 +220,7 @@ ec2_ami module.
Generally speaking, we find most users using Packer.
See the Packer documentation of the `Ansible local Packer provisioner <https://www.packer.io/docs/provisioners/ansible-local.html>`_ and `Ansible remote Packer provisioner <https://www.packer.io/docs/provisioners/ansible.html>`_.
`Documentation for the Ansible Packer provisioner can be found here <https://www.packer.io/docs/provisioners/ansible-local.html>`_.
If you do not want to adopt Packer at this time, configuring a base-image with Ansible after provisioning (as shown above) is acceptable.

View File

@ -1,392 +0,0 @@
Getting Started with Azure
==========================
Ansible includes a suite of modules for interacting with Azure Resource Manager, giving you the tools to easily create
and orchestrate infrastructure on the Microsoft Azure Cloud.
Requirements
------------
Using the Azure Resource Manager modules requires having `Azure Python SDK <https://github.com/Azure/azure-sdk-for-python>`_
installed on the host running Ansible. You will need to have == v2.0.0RC5 installed. The simplest way to install the
SDK is via pip:
.. code-block:: bash
$ pip install "azure==2.0.0rc5"
Authenticating with Azure
-------------------------
Using the Azure Resource Manager modules requires authenticating with the Azure API. You can choose from two authentication strategies:
* Active Directory Username/Password
* Service Principal Credentials
Follow the directions for the strategy you wish to use, then proceed to `Providing Credentials to Azure Modules`_ for
instructions on how to actually use the modules and authenticate with the Azure API.
Using Service Principal
.......................
There is now a detailed official tutorial describing `how to create a service principal <https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/>`_.
After stepping through the tutorial you will have:
* Your Client ID, which is found in the “client id” box in the “Configure” page of your application in the Azure portal
* Your Secret key, generated when you created the application. You cannot show the key after creation.
If you lost the key, you must create a new one in the “Configure” page of your application.
* And finally, a tenant ID. It’s a UUID (e.g. ABCDEFGH-1234-ABCD-1234-ABCDEFGHIJKL) pointing to the AD containing your
application. You will find it in the URL from within the Azure portal, or in the “view endpoints” of any given URL.
Using Active Directory Username/Password
........................................
To create an Active Directory username/password:
* Connect to the Azure Classic Portal with your admin account
* Create a user in your default AAD. You must NOT activate Multi-Factor Authentication
* Go to Settings - Administrators
* Click on Add and enter the email of the new user.
* Check the checkbox of the subscription you want to test with this user.
* Login to Azure Portal with this new user to change the temporary password to a new one. You will not be able to use the
temporary password for OAuth login.
Providing Credentials to Azure Modules
......................................
The modules offer several ways to provide your credentials. For a CI/CD tool such as Ansible Tower or Jenkins, you will
most likely want to use environment variables. For local development you may wish to store your credentials in a file
within your home directory. And of course, you can always pass credentials as parameters to a task within a playbook. The
order of precedence is parameters, then environment variables, and finally a file found in your home directory.
Using Environment Variables
```````````````````````````
To pass service principal credentials via the environment, define the following variables:
* AZURE_CLIENT_ID
* AZURE_SECRET
* AZURE_SUBSCRIPTION_ID
* AZURE_TENANT
To pass Active Directory username/password via the environment, define the following variables:
* AZURE_AD_USER
* AZURE_PASSWORD
* AZURE_SUBSCRIPTION_ID
Storing in a File
`````````````````
When working in a development environment, it may be desirable to store credentials in a file. The modules will look
for credentials in $HOME/.azure/credentials. This file is an ini style file. It will look as follows:
.. code-block:: ini
[default]
subscription_id=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_id=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
secret=xxxxxxxxxxxxxxxxx
tenant=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
It is possible to store multiple sets of credentials within the credentials file by creating multiple sections. Each
section is considered a profile. The modules look for the [default] profile automatically. Define AZURE_PROFILE in the
environment or pass a profile parameter to specify a specific profile.
Passing as Parameters
`````````````````````
If you wish to pass credentials as parameters to a task, use the following parameters for service principal:
* client_id
* secret
* subscription_id
* tenant
Or, pass the following parameters for Active Directory username/password:
* ad_user
* password
* subscription_id
Creating Virtual Machines
-------------------------
There are two ways to create a virtual machine, both involving the azure_rm_virtualmachine module. We can either create
a storage account, network interface, security group and public IP address and pass the names of these objects to the
module as parameters, or we can let the module do the work for us and accept the defaults it chooses.
Creating Individual Components
..............................
An Azure module is available to help you create a storage account, virtual network, subnet, network interface,
security group and public IP. Here is a full example of creating each of these and passing the names to the
azure_rm_virtualmachine module at the end:
.. code-block:: yaml
- name: Create storage account
azure_rm_storageaccount:
resource_group: Testing
name: testaccount001
account_type: Standard_LRS
- name: Create virtual network
azure_rm_virtualnetwork:
resource_group: Testing
name: testvn001
address_prefixes: "10.10.0.0/16"
- name: Add subnet
azure_rm_subnet:
resource_group: Testing
name: subnet001
address_prefix: "10.10.0.0/24"
virtual_network: testvn001
- name: Create public ip
azure_rm_publicipaddress:
resource_group: Testing
allocation_method: Static
name: publicip001
- name: Create security group that allows SSH
azure_rm_securitygroup:
resource_group: Testing
name: secgroup001
rules:
- name: SSH
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 101
direction: Inbound
- name: Create NIC
azure_rm_networkinterface:
resource_group: Testing
name: testnic001
virtual_network: testvn001
subnet: subnet001
public_ip_name: publicip001
security_group: secgroup001
- name: Create virtual machine
azure_rm_virtualmachine:
resource_group: Testing
name: testvm001
vm_size: Standard_D1
storage_account: testaccount001
storage_container: testvm001
storage_blob: testvm001.vhd
admin_username: admin
admin_password: Password!
network_interfaces: testnic001
image:
offer: CentOS
publisher: OpenLogic
sku: '7.1'
version: latest
Each of the Azure modules offers a variety of parameter options. Not all options are demonstrated in the above example.
See each individual module for further details and examples.
Creating a Virtual Machine with Default Options
...............................................
If you simply want to create a virtual machine without specifying all the details, you can do that as well. The only
caveat is that you will need a virtual network with one subnet already in your resource group. Assuming you have a
virtual network already with an existing subnet, you can run the following to create a VM:
.. code-block:: yaml
azure_rm_virtualmachine:
resource_group: Testing
name: testvm10
vm_size: Standard_D1
admin_username: chouseknecht
ssh_password: false
ssh_public_keys: "{{ ssh_keys }}"
image:
offer: CentOS
publisher: OpenLogic
sku: '7.1'
version: latest
Dynamic Inventory Script
------------------------
If you are not familiar with Ansible's dynamic inventory scripts, check out `Intro to Dynamic Inventory <http://docs.ansible.com/ansible/intro_dynamic_inventory.html>`_.
The Azure Resource Manager inventory script is called azure_rm.py. It authenticates with the Azure API exactly the same as the
Azure modules, which means you will either define the same environment variables described above in `Using Environment Variables`_,
create a $HOME/.azure/credentials file (also described above in `Storing in a File`_), or pass command line parameters. To see available command
line options execute the following:
.. code-block:: bash
$ ./ansible/contrib/inventory/azure_rm.py --help
As with all dynamic inventory scripts, the script can be executed directly, passed as a parameter to the ansible command,
or passed directly to ansible-playbook using the -i option. No matter how it is executed the script produces JSON representing
all of the hosts found in your Azure subscription. You can narrow this down to just hosts found in a specific set of
Azure resource groups, or even down to a specific host.
For a given host, the inventory script provides the following host variables:
.. code-block:: JSON
{
"ansible_host": "XXX.XXX.XXX.XXX",
"computer_name": "computer_name2",
"fqdn": null,
"id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Compute/virtualMachines/object-name",
"image": {
"offer": "CentOS",
"publisher": "OpenLogic",
"sku": "7.1",
"version": "latest"
},
"location": "westus",
"mac_address": "00-0D-3A-31-2C-EC",
"name": "object-name",
"network_interface": "interface-name",
"network_interface_id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Network/networkInterfaces/object-name1",
"network_security_group": null,
"network_security_group_id": null,
"os_disk": {
"name": "object-name",
"operating_system_type": "Linux"
},
"plan": null,
"powerstate": "running",
"private_ip": "172.26.3.6",
"private_ip_alloc_method": "Static",
"provisioning_state": "Succeeded",
"public_ip": "XXX.XXX.XXX.XXX",
"public_ip_alloc_method": "Static",
"public_ip_id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Network/publicIPAddresses/object-name",
"public_ip_name": "object-name",
"resource_group": "galaxy-production",
"security_group": "object-name",
"security_group_id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Network/networkSecurityGroups/object-name",
"tags": {
"db": "mysql"
},
"type": "Microsoft.Compute/virtualMachines",
"virtual_machine_size": "Standard_DS4"
}
Host Groups
...........
By default hosts are grouped by:
* azure (all hosts)
* location name
* resource group name
* security group name
* tag key
* tag key_value
You can control host groupings and host selection by either defining environment variables or creating an
azure_rm.ini file in your current working directory.
NOTE: An .ini file will take precedence over environment variables.
NOTE: The name of the .ini file is the basename of the inventory script (i.e. 'azure_rm') with a '.ini'
extension. This allows you to copy, rename and customize the inventory script and have matching .ini files all in
the same directory.
Control grouping using the following variables defined in the environment:
* AZURE_GROUP_BY_RESOURCE_GROUP=yes
* AZURE_GROUP_BY_LOCATION=yes
* AZURE_GROUP_BY_SECURITY_GROUP=yes
* AZURE_GROUP_BY_TAG=yes
Select hosts within specific resource groups by assigning a comma separated list to:
* AZURE_RESOURCE_GROUPS=resource_group_a,resource_group_b
Select hosts for specific tag key by assigning a comma separated list of tag keys to:
* AZURE_TAGS=key1,key2,key3
Select hosts for specific locations by assigning a comma separated list of locations to:
* AZURE_LOCATIONS=eastus,eastus2,westus
Or, select hosts for specific tag key:value pairs by assigning a comma separated list key:value pairs to:
* AZURE_TAGS=key1:value1,key2:value2
If you don't need the powerstate, you can improve performance by turning off powerstate fetching:
* AZURE_INCLUDE_POWERSTATE=no
A sample azure_rm.ini file is included along with the inventory script in contrib/inventory. An .ini
file will contain the following:
.. code-block:: ini
[azure]
# Control which resource groups are included. By default all resources groups are included.
# Set resource_groups to a comma separated list of resource groups names.
#resource_groups=
# Control which tags are included. Set tags to a comma separated list of keys or key:value pairs
#tags=
# Control which locations are included. Set locations to a comma separated list of locations.
#locations=
# Include powerstate. If you don't need powerstate information, turning it off improves runtime performance.
# Valid values: yes, no, true, false, True, False, 0, 1.
include_powerstate=yes
# Control grouping with the following boolean flags. Valid values: yes, no, true, false, True, False, 0, 1.
group_by_resource_group=yes
group_by_location=yes
group_by_security_group=yes
group_by_tag=yes
Examples
........
Here are some examples using the inventory script:
.. code-block:: bash
# Execute /bin/uname on all instances in the Testing resource group
$ ansible -i azure_rm.py Testing -m shell -a "/bin/uname -a"
# Use the inventory script to print instance specific information
$ ./ansible/contrib/inventory/azure_rm.py --host my_instance_host_name --resource-groups=Testing --pretty
# Use the inventory script with ansible-playbook
$ ansible-playbook -i ./ansible/contrib/inventory/azure_rm.py test_playbook.yml
Here is a simple playbook to exercise the Azure inventory script:
.. code-block:: yaml
- name: Test the inventory script
hosts: azure
connection: local
gather_facts: no
tasks:
- debug: msg="{{ inventory_hostname }} has powerstate {{ powerstate }}"
You can execute the playbook with something like:
.. code-block:: bash
$ ansible-playbook -i ./ansible/contrib/inventory/azure_rm.py test_azure_inventory.yml

View File

@ -23,10 +23,6 @@ You'll need this Python module installed on the execution host, usually your wor
.. note:: cs also includes a command line interface for ad-hoc interaction with the CloudStack API e.g. ``$ cs listVirtualMachines state=Running``.
Limitations and Known Issues
````````````````````````````
VPC support is not yet fully implemented and tested. The community is working on the VPC integration.
Credentials File
````````````````
You can pass credentials and the endpoint of your cloud as module arguments, however in most cases it is a far less work to store your credentials in the cloudstack.ini file.
@ -196,9 +192,9 @@ In the above play we defined 3 tasks and use the group ``cloud-vm`` as target to
In the first task, we ensure we have a running VM created with the Debian template. If the VM is already created but stopped, it would just start it. If you like to change the offering on an exisiting VM, you must add ``force: yes`` to the task, which would stop the VM, change the offering and start the VM again.
In the second task we ensure the ports are opened if we give a public IP to the VM.
In the second task we ensure the ports are opened if we give a public IP to the VM.
In the third task we add static NAT to the VMs having a public IP defined.
In the third task we add static NAT to the VMs having a public IP defined.
.. Note:: The public IP addresses must have been acquired in advance, also see ``cs_ip_address``

View File

@ -1,317 +0,0 @@
Getting Started with Docker
===========================
Ansible offers the following modules for orchestrating Docker containers:
docker_service
Use your existing Docker compose files to orchestrate containers on a single Docker daemon or on
Swarm. Supports compose versions 1 and 2.
docker_container
Manages the container lifecycle by providing the ability to create, update, stop, start and destroy a
container.
docker_image
Provides full control over images, including: build, pull, push, tag and remove.
docker_image_facts
Inspects one or more images in the Docker host's image cache, providing the information as facts for making
decision or assertions in a playbook.
docker_login
Authenticates with Docker Hub or any Docker registry and updates the Docker Engine config file, which
in turn provides password-free pushing and pulling of images to and from the registry.
docker (dynamic inventory)
Dynamically builds an inventory of all the available containers from a set of one or more Docker hosts.
Ansible 2.1.0 includes major updates to the Docker modules, marking the start of a project to create a complete and
integrated set of tools for orchestrating containers. In addition to the above modules, we are also working on the
following:
Still using Dockerfile to build images? Check out `ansible-container <https://github.com/ansible/ansible-container>`_,
and start building images from your Ansible playbooks.
Use the *shipit* command in `ansible-container <https://github.com/ansible/ansible-container>`_
to launch your docker-compose file on `OpenShift <https://www.openshift.org/>`_. Go from an app on your laptop to a fully
scalable app in the cloud in just a few moments.
There's more planned. See the latest ideas and thinking at the `Ansible proposal repo <https://github.com/ansible/proposals/tree/master/docker>`_.
Requirements
------------
Using the docker modules requires having `docker-py <https://docker-py.readthedocs.org/en/stable/>`_
installed on the host running Ansible. You will need to have >= 1.7.0 installed.
.. code-block:: bash
$ pip install 'docker-py>=1.7.0'
The docker_service module also requires `docker-compose <https://github.com/docker/compose>`_
.. code-block:: bash
$ pip install 'docker-compose>=1.7.0'
Connecting to the Docker API
----------------------------
You can connect to a local or remote API using parameters passed to each task or by setting environment variables.
The order of precedence is command line parameters and then environment variables. If neither a command line
option or an environment variable is found, a default value will be used. The default values are provided under
`Parameters`_
Parameters
..........
Control how modules connect to the Docker API by passing the following parameters:
docker_host
The URL or Unix socket path used to connect to the Docker API. Defaults to ``unix://var/run/docker.sock``.
To connect to a remote host, provide the TCP connection string. For example: ``tcp://192.168.99.100:2376``. If
TLS is used to encrypt the connection to the API, then the module will automatically replace 'tcp' in the
connection URL with 'https'.
api_version
The version of the Docker API running on the Docker Host. Defaults to the latest version of the API supported
by docker-py.
timeout
The maximum amount of time in seconds to wait on a response from the API. Defaults to 60 seconds.
tls
Secure the connection to the API by using TLS without verifying the authenticity of the Docker host server.
Defaults to False.
tls_verify
Secure the connection to the API by using TLS and verifying the authenticity of the Docker host server.
Default is False.
cacert_path
Use a CA certificate when performing server verification by providing the path to a CA certificate file.
cert_path
Path to the client's TLS certificate file.
key_path
Path to the client's TLS key file.
tls_hostname
When verifying the authenticity of the Docker Host server, provide the expected name of the server. Defaults
to 'localhost'.
ssl_version
Provide a valid SSL version number. Default value determined by docker-py, which at the time of this writing
was 1.0
Environment Variables
.....................
Control how the modules connect to the Docker API by setting the following variables in the environment of the host
running Ansible:
DOCKER_HOST
The URL or Unix socket path used to connect to the Docker API.
DOCKER_API_VERSION
The version of the Docker API running on the Docker Host. Defaults to the latest version of the API supported
by docker-py.
DOCKER_TIMEOUT
The maximum amount of time in seconds to wait on a response from the API.
DOCKER_CERT_PATH
Path to the directory containing the client certificate, client key and CA certificate.
DOCKER_SSL_VERSION
Provide a valid SSL version number.
DOCKER_TLS
Secure the connection to the API by using TLS without verifying the authenticity of the Docker Host.
DOCKER_TLS_VERIFY
Secure the connection to the API by using TLS and verify the authenticity of the Docker Host.
Dynamic Inventory Script
------------------------
The inventory script generates dynamic inventory by making API requests to one or more Docker APIs. It's dynamic
because the inventory is generated at run-time rather than being read from a static file. The script generates the
inventory by connecting to one or many Docker APIs and inspecting the containers it finds at each API. Which APIs the
script contacts can be defined using environment variables or a configuration file.
Groups
......
The script will create the following host groups:
- container id
- container name
- container short id
- image_name (image_<image name>)
- docker_host
- running
- stopped
Examples
........
You can run the script interactively from the command line or pass it as the inventory to a playbook. Here are few
examples to get you started:
.. code-block:: bash
# Connect to the Docker API on localhost port 4243 and format the JSON output
DOCKER_HOST=tcp://localhost:4243 ./docker.py --pretty
# Any container's ssh port exposed on 0.0.0.0 will be mapped to
# another IP address (where Ansible will attempt to connect via SSH)
DOCKER_DEFAULT_IP=1.2.3.4 ./docker.py --pretty
# Run as input to a playbook:
ansible-playbook -i ~/projects/ansible/contrib/inventory/docker.py docker_inventory_test.yml
# Simple playbook to invoke with the above example:
- name: Test docker_inventory
hosts: all
connection: local
gather_facts: no
tasks:
- debug: msg="Container - {{ inventory_hostname }}"
Configuration
.............
You can control the behavior of the inventory script by defining environment variables, or
creating a docker.yml file (sample provided in ansible/contrib/inventory). The order of precedence is the docker.yml
file and then environment variables.
Environment Variables
;;;;;;;;;;;;;;;;;;;;;;
To connect to a single Docker API the following variables can be defined in the environment to control the connection
options. These are the same environment variables used by the Docker modules.
DOCKER_HOST
The URL or Unix socket path used to connect to the Docker API. Defaults to unix://var/run/docker.sock.
DOCKER_API_VERSION:
The version of the Docker API running on the Docker Host. Defaults to the latest version of the API supported
by docker-py.
DOCKER_TIMEOUT:
The maximum amount of time in seconds to wait on a response fromm the API. Defaults to 60 seconds.
DOCKER_TLS:
Secure the connection to the API by using TLS without verifying the authenticity of the Docker host server.
Defaults to False.
DOCKER_TLS_VERIFY:
Secure the connection to the API by using TLS and verifying the authenticity of the Docker host server.
Default is False
DOCKER_TLS_HOSTNAME:
When verifying the authenticity of the Docker Host server, provide the expected name of the server. Defaults
to localhost.
DOCKER_CERT_PATH:
Path to the directory containing the client certificate, client key and CA certificate.
DOCKER_SSL_VERSION:
Provide a valid SSL version number. Default value determined by docker-py, which at the time of this writing
was 1.0
In addition to the connection variables there are a couple variables used to control the execution and output of the
script:
DOCKER_CONFIG_FILE
Path to the configuration file. Defaults to ./docker.yml.
DOCKER_PRIVATE_SSH_PORT:
The private port (container port) on which SSH is listening for connections. Defaults to 22.
DOCKER_DEFAULT_IP:
The IP address to assign to ansible_host when the container's SSH port is mapped to interface '0.0.0.0'.
Configuration File
;;;;;;;;;;;;;;;;;;
Using a configuration file provides a means for defining a set of Docker APIs from which to build an inventory.
The default name of the file is derived from the name of the inventory script. By default the script will look for
basename of the script (i.e. docker) with an extension of '.yml'.
You can also override the default name of the script by defining DOCKER_CONFIG_FILE in the environment.
Here's what you can define in docker_inventory.yml:
defaults
Defines a default connection. Defaults will be taken from this and applied to any values not provided
for a host defined in the hosts list.
hosts
If you wish to get inventory from more than one Docker host, define a hosts list.
For the default host and each host in the hosts list define the following attributes:
.. code-block:: yaml
host:
description: The URL or Unix socket path used to connect to the Docker API.
required: yes
tls:
description: Connect using TLS without verifying the authenticity of the Docker host server.
default: false
required: false
tls_verify:
description: Connect using TLS without verifying the authenticity of the Docker host server.
default: false
required: false
cert_path:
description: Path to the client's TLS certificate file.
default: null
required: false
cacert_path:
description: Use a CA certificate when performing server verification by providing the path to a CA certificate file.
default: null
required: false
key_path:
description: Path to the client's TLS key file.
default: null
required: false
version:
description: The Docker API version.
required: false
default: will be supplied by the docker-py module.
timeout:
description: The amount of time in seconds to wait on an API response.
required: false
default: 60
default_ip:
description: The IP address to assign to ansible_host when the container's SSH port is mapped to interface
'0.0.0.0'.
required: false
default: 127.0.0.1
private_ssh_port:
description: The port containers use for SSH
required: false
default: 22

View File

@ -11,7 +11,7 @@ Introduction
Ansible contains modules for managing Google Compute Engine resources, including creating instances, controlling network access, working with persistent disks, and managing
load balancers. Additionally, there is an inventory plugin that can automatically suck down all of your GCE instances into Ansible dynamic inventory, and create groups by tag and other properties.
The GCE modules all require the apache-libcloud module which you can install from pip:
The GCE modules all require the apache-libcloud module, which you can install from pip:
.. code-block:: bash
@ -22,19 +22,16 @@ The GCE modules all require the apache-libcloud module which you can install fro
Credentials
-----------
To work with the GCE modules, you'll first need to get some credentials in the
JSON format:
To work with the GCE modules, you'll first need to get some credentials. You can create new one from the `console <https://console.developers.google.com/>`_ by going to the "APIs and Auth" section and choosing to create a new client ID for a service account. Once you've created a new client ID and downloaded (you must click **Generate new P12 Key**) the generated private key (in the `pkcs12 format <http://en.wikipedia.org/wiki/PKCS_12>`_), you'll need to convert the key by running the following command:
1. `Create a Service Account <https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount>`_
2. `Download JSON credentials <https://support.google.com/cloud/answer/6158849?hl=en&ref_topic=6262490#serviceaccounts>`_
.. code-block:: bash
There are three different ways to provide credentials to Ansible so that it can talk with Google Cloud for provisioning and configuration actions:
$ openssl pkcs12 -in pkey.pkcs12 -passin pass:notasecret -nodes -nocerts | openssl rsa -out pkey.pem
.. note:: If you would like to use JSON credentials you must have libcloud >= 0.17.0
There are two different ways to provide credentials to Ansible so that it can talk with Google Cloud for provisioning and configuration actions:
* by providing to the modules directly
* by populating a ``secrets.py`` file
* by setting environment variables
Calling Modules By Passing Credentials
``````````````````````````````````````
@ -42,7 +39,7 @@ Calling Modules By Passing Credentials
For the GCE modules you can specify the credentials as arguments:
* ``service_account_email``: email associated with the project
* ``credentials_file``: path to the JSON credentials file
* ``pem_file``: path to the pem file
* ``project_id``: id of the project
For example, to create a new instance using the cloud module, you can use the following configuration:
@ -51,12 +48,12 @@ For example, to create a new instance using the cloud module, you can use the fo
- name: Create instance(s)
hosts: localhost
connection: local
connection: local
gather_facts: no
vars:
service_account_email: unique-id@developer.gserviceaccount.com
credentials_file: /path/to/project.json
pem_file: /path/to/project.pem
project_id: project-id
machine_type: n1-standard-1
image: debian-7
@ -64,50 +61,28 @@ For example, to create a new instance using the cloud module, you can use the fo
tasks:
- name: Launch instances
gce:
instance_names: dev
gce:
instance_names: dev
machine_type: "{{ machine_type }}"
image: "{{ image }}"
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
pem_file: "{{ pem_file }}"
project_id: "{{ project_id }}"
When running Ansible inside a GCE VM you can use the service account credentials from the local metadata server by
setting both ``service_account_email`` and ``credentials_file`` to a blank string.
Configuring Modules with secrets.py
```````````````````````````````````
Calling Modules with secrets.py
```````````````````````````````
Create a file ``secrets.py`` looking like following, and put it in some folder which is in your ``$PYTHONPATH``:
.. code-block:: python
GCE_PARAMS = ('i...@project.googleusercontent.com', '/path/to/project.json')
GCE_PARAMS = ('i...@project.googleusercontent.com', '/path/to/project.pem')
GCE_KEYWORD_PARAMS = {'project': 'project_id'}
Ensure to enter the email address from the created services account and not the one from your main account.
Now the modules can be used as above, but the account information can be omitted.
If you are running Ansible from inside a GCE VM with an authorized service account you can set the email address and
credentials path as follows so that get automatically picked up:
.. code-block:: python
GCE_PARAMS = ('', '')
GCE_KEYWORD_PARAMS = {'project': 'project_id'}
Configuring Modules with Environment Variables
``````````````````````````````````````````````
Set the following environment variables before running Ansible in order to configure your credentials:
.. code-block:: bash
GCE_EMAIL
GCE_PROJECT
GCE_CREDENTIALS_FILE_PATH
GCE Dynamic Inventory
---------------------
@ -196,7 +171,7 @@ A playbook would looks like this:
machine_type: n1-standard-1 # default
image: debian-7
service_account_email: unique-id@developer.gserviceaccount.com
credentials_file: /path/to/project.json
pem_file: /path/to/project.pem
project_id: project-id
tasks:
@ -206,7 +181,7 @@ A playbook would looks like this:
machine_type: "{{ machine_type }}"
image: "{{ image }}"
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
pem_file: "{{ pem_file }}"
project_id: "{{ project_id }}"
tags: webserver
register: gce
@ -249,7 +224,7 @@ a basic example of what is possible::
machine_type: n1-standard-1 # default
image: debian-7
service_account_email: unique-id@developer.gserviceaccount.com
credentials_file: /path/to/project.json
pem_file: /path/to/project.pem
project_id: project-id
roles:
@ -263,12 +238,13 @@ a basic example of what is possible::
args:
fwname: "all-http"
name: "default"
allowed: "tcp:80"
state: "present"
service_account_email: "{{ service_account_email }}"
credentials_file: "{{ credentials_file }}"
allowed: "tcp:80"
state: "present"
service_account_email: "{{ service_account_email }}"
pem_file: "{{ pem_file }}"
project_id: "{{ project_id }}"
By pointing your browser to the IP of the server, you should see a page welcoming you.
Upgrades to this documentation are welcome, hit the github link at the top right of this page if you would like to make additions!
Upgrades to this documentation are welcome, hit the github link at the top right of this page if you would like to make additions!

View File

@ -1,18 +1,16 @@
Detailed Guides
```````````````
This section is new and evolving. The idea here is to explore particular use cases in greater depth and provide a more "top down" explanation of some basic features.
This section is new and evolving. The idea here is explore particular use cases in greater depth and provide a more "top down" explanation of some basic features.
.. toctree::
:maxdepth: 1
guide_aws
guide_azure
guide_rax
guide_gce
guide_cloudstack
guide_vagrant
guide_rolling_upgrade
guide_docker
Pending topics may include: Docker, Jenkins, Google Compute Engine, Linode/DigitalOcean, Continuous Deployment, and more.

View File

@ -16,7 +16,7 @@ We believe simplicity is relevant to all sizes of environments, so we design for
Ansible manages machines in an agent-less manner. There is never a question of how to
upgrade remote daemons or the problem of not being able to manage systems because daemons are uninstalled. Because OpenSSH is one of the most peer-reviewed open source components, security exposure is greatly reduced. Ansible is decentralized--it relies on your existing OS credentials to control access to remote machines. If needed, Ansible can easily connect with Kerberos, LDAP, and other centralized authentication management systems.
This documentation covers the current released version of Ansible (2.0.1) and also some development version features (2.1). For recent features, we note in each section the version of Ansible where the feature was added.
This documentation covers the current released version of Ansible (1.9.1) and also some development version features (2.0). For recent features, we note in each section the version of Ansible where the feature was added.
Ansible, Inc. releases a new major release of Ansible approximately every two months. The core application evolves somewhat conservatively, valuing simplicity in language design and setup. However, the community around new modules and plugins being developed and contributed moves very quickly, typically adding 20 or so new modules in each release.
@ -40,5 +40,4 @@ Ansible, Inc. releases a new major release of Ansible approximately every two mo
faq
glossary
YAMLSyntax
porting_guide_2.0

View File

@ -11,11 +11,12 @@ ad hoc tasks.
What's an ad-hoc command?
An ad-hoc command is something that you might type in to do something really
quick, but don't want to save for later.
quick, but don't want to save for later.
This is a good place to start to understand the basics of what Ansible can do
prior to learning the playbooks language -- ad-hoc commands can also be used
to do quick things that you might not necessarily want to write a full playbook for.
to do quick things that you might not necessarily want to write a full playbook
for.
Generally speaking, the true power of Ansible lies in playbooks.
Why would you use ad-hoc tasks versus playbooks?
@ -24,7 +25,7 @@ For instance, if you wanted to power off all of your lab for Christmas vacation,
you could execute a quick one-liner in Ansible without writing a playbook.
For configuration management and deployments, though, you'll want to pick up on
using '/usr/bin/ansible-playbook' -- the concepts you will learn here will
using '/usr/bin/ansible-playbook' -- the concepts you will learn here will
port over directly to the playbook language.
(See :doc:`playbooks` for more information about those)
@ -59,24 +60,25 @@ behavior, pass in "-u username". If you want to run commands as a different use
$ ansible atlanta -a "/usr/bin/foo" -u username
Often you'll not want to just do things from your user account. If you want to run commands through privilege escalation::
Often you'll not want to just do things from your user account. If you want to run commands through sudo::
$ ansible atlanta -a "/usr/bin/foo" -u username --become [--ask-become-pass]
$ ansible atlanta -a "/usr/bin/foo" -u username --sudo [--ask-sudo-pass]
Use ``--ask-become-pass`` (``-K``) if you are not using a passwordless privilege escalation method (sudo/su/pfexec/doas/etc).
This will interactively prompt you for the password to use.
Use of a passwordless setup makes things easier to automate, but it's not required.
Use ``--ask-sudo-pass`` (``-K``) if you are not using passwordless
sudo. This will interactively prompt you for the password to use.
Use of passwordless sudo makes things easier to automate, but it's not
required.
It is also possible to become a user other than root using
``--become-user``::
It is also possible to sudo to a user other than root using
``--sudo-user`` (``-U``)::
$ ansible atlanta -a "/usr/bin/foo" -u username --become-user otheruser [--ask-become-pass]
$ ansible atlanta -a "/usr/bin/foo" -u username -U otheruser [--ask-sudo-pass]
.. note::
Rarely, some users have security rules where they constrain their sudo/pbrun/doas environment to running specific command paths only.
Rarely, some users have security rules where they constrain their sudo environment to running specific command paths only.
This does not work with ansible's no-bootstrapping philosophy and hundreds of different modules.
If doing this, use Ansible from a special account that does not have this constraint.
If doing this, use Ansible from a special account that does not have this constraint.
One way of doing this without sharing access to unauthorized users would be gating Ansible with :doc:`tower`, which
can hold on to an SSH credential and let members of certain organizations use it on their behalf without having direct access.
@ -86,7 +88,7 @@ The ``-f 10`` in the above specifies the usage of 10 simultaneous
processes to use. You can also set this in :doc:`intro_configuration` to avoid setting it again. The default is actually 5, which
is really small and conservative. You are probably going to want to talk to a lot more simultaneous hosts so feel free
to crank this up. If you have more hosts than the value set for the fork count, Ansible will talk to them, but it will
take a little longer. Feel free to push this value as high as your system can handle!
take a little longer. Feel free to push this value as high as your system can handle it!
You can also select what Ansible "module" you want to run. Normally commands also take a ``-m`` for module name, but
the default module name is 'command', so we didn't need to
@ -168,7 +170,7 @@ Ensure a package is not installed::
Ansible has modules for managing packages under many platforms. If your package manager
does not have a module available for it, you can install
packages using the command module or (better!) contribute a module
for other packages using the command module or (better!) contribute a module
for other package managers. Stop by the mailing list for info/details.
.. _users_and_groups:
@ -247,7 +249,7 @@ very quickly. After the time limit (in seconds) runs out (``-B``), the process o
the remote nodes will be terminated.
Typically you'll only be backgrounding long-running
shell commands or software upgrades. Backgrounding the copy module does not do a background file transfer. :doc:`Playbooks <playbooks>` also support polling, and have a simplified syntax for this.
shell commands or software upgrades only. Backgrounding the copy module does not do a background file transfer. :doc:`Playbooks <playbooks>` also support polling, and have a simplified syntax for this.
.. _checking_facts:

View File

@ -1,4 +1,4 @@
BSD Support
BSD support
===========
.. contents:: Topics
@ -8,73 +8,80 @@ BSD Support
Working with BSD
````````````````
Ansible manages Linux/Unix machines using SSH by default. BSD machines are no exception, however this document covers some of the differences you may encounter with Ansible when working with BSD variants.
As you may have already read, Ansible manages Linux/Unix machines using SSH by default. Ansible handles BSD machines in the same manner.
Typically, Ansible will try to default to using OpenSSH as a connection method. This is suitable when when using SSH keys to authenticate, but when using SSH passwords, Ansible relies on sshpass. Most
versions of sshpass do not deal particularly well with BSD login prompts, so when using SSH passwords against BSD machines, it is recommended to change the transport method to paramiko. You can do this in ansible.cfg globally or you can set it as an inventory/group/host variable. For example::
Depending on your control machine, Ansible will try to default to using OpenSSH. This works fine when using SSH keys to authenticate, but when using SSH passwords, Ansible relies on sshpass. Most
versions of sshpass do not deal well with BSD login prompts, so in these cases we recommend changing the transport to paramiko. You can do this in ansible.cfg globaly or set it as
an inventory/group/host variable::
[freebsd]
mybsdhost1 ansible_connection=paramiko
Ansible is agentless by default, however certain software is required on the target machines. Using Python 2.4 on the agents requires an additional py-simplejson package/library to be installed, however this library is already included in Python 2.5 and above.
Operating without Python is possible with the ``raw`` module. Although this module can be used to bootstrap Ansible and install Python on BSD variants (see below), it is very limited and the use of Python is required to make full use of Ansible's features.
Ansible is agentless by default, but it needs some software installed on the target machines, mainly Python 2.4 or higher with an included json library (which is standard in Python 2.5 and above).
Without python you can still use the ``raw`` module to execute commands. This module is very limited, however it can be used to bootstrap Ansible on BSDs.
.. _bootstrap_bsd:
Bootstrapping BSD
`````````````````
As mentioned above, you can bootstrap Ansible with the ``raw`` module and remotely install Python on targets. The following example installs Python 2.7 which includes the json library required for full functionality of Ansible.
For Ansible to effectively manage your machine, we need to install Python along with a json library, in this case we are using Python 2.7 which already has json included.
On your control machine you can simply execute the following for most versions of FreeBSD::
ansible -m raw -a “pkg install -y python27” mybsdhost1
ansible -m raw -a “pkg_add -r python27” mybsdhost1
Once this is done you can now use other Ansible modules apart from the ``raw`` module.
Once this is done you can now use other Ansible modules aside from the ``raw`` module.
.. note::
This example used pkg_add as used on FreeBSD, however you should be able to substitute the appropriate package tool for your BSD; the package name may also differ. Refer to the package list or documentation of the BSD variant you are using for the exact Python package name you intend to install.
This example uses pkg_add, you should be able to substitute for the appropriate tool for your BSD,
also you might need to look up the exact package name you need.
.. _python_location:
Setting the Python interpreter
``````````````````````````````
Setting python interpreter
``````````````````````````
To support a variety of Unix/Linux operating systems and distributions, Ansible cannot always rely on the existing environment or ``env`` variables to locate the correct Python binary. By default, modules point at ``/usr/bin/python`` as this is the most common location. On BSD variants, this path may differ, so it is advised to inform Ansible of the binary's location, through the ``ansible_python_interpreter`` inventory variable. For example::
To support the multitude of Unix/Linux OSs and distributions, Ansible cannot rely on the environment or ``env`` to find the correct Python. By default, modules point at ``/usr/bin/python`` as this is the most common location. On the BSDs you cannot rely on this so you should tell ansible where python is located, through the ``ansible_python_interpreter`` inventory variable::
[freebsd:vars]
ansible_python_interpreter=/usr/local/bin/python2.7
If you use additional plugins beyond those bundled with Ansible, you can set similar variables for ``bash``, ``perl`` or ``ruby``, depending on how the plugin is written. For example::
If you use plugins other than those included with Ansible you might need to set similar variables for ``bash``, ``perl`` or ``ruby``, depending on how the plugin was written::
[freebsd:vars]
ansible_python_interpreter=/usr/local/bin/python
ansible_perl_interpreter=/usr/bin/perl5
Which modules are available?
````````````````````````````
What modules are available
``````````````````````````
The majority of the core Ansible modules are written for a combination of Linux/Unix machines and other generic services, so most should function well on the BSDs with the obvious exception of those that are aimed at Linux-only technologies (such as LVG).
Most of the core Ansible modules are written for a combination of Linux/Unix machines and arbitrary web services; most should work fine on the BSDs with the exception of those that are aimed at Linux specific technologies (i.e. lvg).
Using BSD as the control machine
````````````````````````````````
Using BSD as the control machine is as simple as installing the Ansible package for your BSD variant or by following the ``pip`` or 'from source' instructions.
You can also use a BSD as the control machine
`````````````````````````````````````````````
It should be as simple as installing the Ansible package or follow the ``pip`` or 'from source' instructions.
.. _bsd_facts:
BSD Facts
`````````
Ansible gathers facts from the BSDs in a similar manner to Linux machines, but since the data, names and structures can vary for network, disks and other devices, one should expect the output to be slightly different yet still familiar to a BSD administrator.
Ansible gathers facts from the BSDs as it would from Linux machines, but since the data, names and structures can be different for network, disks and other devices, one should expect the output to be different, but still familiar to a BSD administrator.
.. _bsd_contributions:
BSD Efforts and Contributions
`````````````````````````````
BSD Contributions
`````````````````
BSD support is important to us at Ansible. Even though the majority of our contributors use and target Linux we have an active BSD community and strive to be as BSD friendly as possible.
Please feel free to report any issues or incompatibilities you discover with BSD; pull requests with an included fix are also welcome!
BSD support is important for Ansible. Even though the majority of our contributors use and target Linux we have an active BSD community and will strive to be as BSD friendly as possible.
Report any issues you see with BSD incompatibilities, even better to submit a pull request with the fix!
.. seealso::

View File

@ -60,7 +60,7 @@ General defaults
In the [defaults] section of ansible.cfg, the following settings are tunable:
.. _cfg_action_plugins:
.. _action_plugins:
action_plugins
==============
@ -74,34 +74,6 @@ different locations::
Most users will not need to use this feature. See :doc:`developing_plugins` for more details.
.. _allow_unsafe_lookups:
allow_unsafe_lookups
====================
.. versionadded:: 2.2.3, 2.3.1
When enabled, this option allows lookup plugins (whether used in variables as `{{lookup('foo')}}` or as a loop as `with_foo`) to return data that is **not** marked "unsafe". By default, such data is marked as unsafe to prevent the templating engine from evaluating any jinja2 templating language, as this could represent a security risk.
This option is provided to allow for backwards-compatibility, however users should first consider adding `allow_unsafe=True` to any lookups which may be expected to contain data which may be run through the templating engine later. For example::
{{lookup('pipe', '/path/to/some/command', allow_unsafe=True)}}
.. _allow_world_readable_tmpfiles:
allow_world_readable_tmpfiles
=============================
.. versionadded:: 2.1
This makes the temporary files created on the machine to be world readable and will issue a warning instead of failing the task.
It is useful when becoming an unprivileged user::
allow_world_readable_tmpfiles=True
.. _ansible_managed:
ansible_managed
@ -177,7 +149,7 @@ Callbacks are pieces of code in ansible that get called on specific events, perm
This is a developer-centric feature that allows low-level extensions around Ansible to be loaded from
different locations::
callback_plugins = ~/.ansible/plugins/callback:/usr/share/ansible/plugins/callback
callback_plugins = ~/.ansible/plugins/callback_plugins/:/usr/share/ansible_plugins/callback_plugins
Most users will not need to use this feature. See :doc:`developing_plugins` for more details
@ -256,34 +228,6 @@ Allows disabling of deprecating warnings in ansible-playbook output::
Deprecation warnings indicate usage of legacy features that are slated for removal in a future release of Ansible.
.. _display_args_to_stdout:
display_args_to_stdout
======================
.. versionadded:: 2.1.0
By default, ansible-playbook will print a header for each task that is run to
stdout. These headers will contain the ``name:`` field from the task if you
specified one. If you didn't then ansible-playbook uses the task's action to
help you tell which task is presently running. Sometimes you run many of the
same action and so you want more information about the task to differentiate
it from others of the same action. If you set this variable to ``True`` in
the config then ansible-playbook will also include the task's arguments in the
header.
This setting defaults to ``False`` because there is a chance that you have
sensitive values in your parameters and do not want those to be printed to
stdout::
display_args_to_stdout=False
If you set this to ``True`` you should be sure that you have secured your
environment's stdout (no one can shoulder surf your screen and you aren't
saving stdout to an insecure file) or made sure that all of your playbooks
explicitly added the ``no_log: True`` parameter to tasks which have sensistive
values See :ref:`keep_secret_data` for more information.
.. _display_skipped_hosts:
display_skipped_hosts
@ -317,8 +261,6 @@ This indicates the command to use to spawn a shell under a sudo environment. Us
executable = /bin/bash
Starting in version 2.1 this can be overridden by the inventory var ``ansible_shell_executable``.
.. _filter_plugins:
filter_plugins
@ -383,32 +325,6 @@ This option can be useful for those wishing to save fact gathering time. Both 's
gathering = smart
.. versionadded:: 2.1
You can specify a subset of gathered facts using the following option::
gather_subset = all
:all: gather all subsets (the default)
:network: gather network facts
:hardware: gather hardware facts (longest facts to retrieve)
:virtual: gather facts about virtual machines hosted on the machine
:ohai: gather facts from ohai
:facter: gather facts from facter
You can combine them using a comma separated list (ex: network,virtual,facter)
You can also disable specific subsets by prepending with a `!` like this::
# Don't gather hardware facts, facts from chef's ohai or puppet's facter
gather_subset = !hardware,!ohai,!facter
A set of basic facts are always collected no matter which additional subsets
are selected. If you want to collect the minimal amount of facts, use
`!all`::
gather_subset = !all
hash_behaviour
==============
@ -423,7 +339,7 @@ official examples repos do not use this setting::
The valid values are either 'replace' (the default) or 'merge'.
.. versionadded:: 2.0
.. versionadded: '2.0'
If you want to merge hashes without changing the global settings, use
the `combine` filter described in :doc:`playbooks_filters`.
@ -480,22 +396,6 @@ This is the default location Ansible looks to find modules::
Ansible knows how to look in multiple locations if you feed it a colon separated path, and it also will look for modules in the
"./library" directory alongside a playbook.
.. _local_tmp:
local_tmp
=========
When Ansible gets ready to send a module to a remote machine it usually has to
add a few things to the module: Some boilerplate code, the module's
parameters, and a few constants from the config file. This combination of
things gets stored in a temporary file until ansible exits and cleans up after
itself. The default location is a subdirectory of the user's home directory.
If you'd like to change that, you can do so by altering this setting::
local_tmp = $HOME/.ansible/tmp
Ansible will then choose a random directory name inside this location.
.. _log_path:
log_path
@ -523,22 +423,8 @@ different locations::
Most users will not need to use this feature. See :doc:`developing_plugins` for more details
.. _module_set_locale:
module_set_locale
=================
This boolean value controls whether or not Ansible will prepend locale-specific environment variables (as specified
via the :ref:`module_lang` configuration option). By default this is enabled, and results in the LANG and LC_MESSAGES
being set when the module is executed on the given remote system.
.. note::
The module_set_locale option was added in Ansible 2.1.
.. _module_lang:
module_lang
===========
@ -660,9 +546,9 @@ retry_files_save_path
=====================
The retry files save path is where Ansible will save .retry files when a playbook fails and retry_files_enabled is True (the default).
The default location is adjacent to the play (~/ in versions older than 2.0) and can be changed to any writeable path::
The default location is ~/ and can be changed to any writeable path::
retry_files_save_path = ~/.ansible/retry-files
retry_files_save_path = ~/.ansible-retry
The directory will be created if it does not already exist.
@ -671,7 +557,7 @@ The directory will be created if it does not already exist.
roles_path
==========
.. versionadded:: 1.4
.. versionadded: '1.4'
The roles path indicate additional directories beyond the 'roles/' subdirectory of a playbook project to search to find Ansible
roles. For instance, if there was a source control repository of common roles and a different repository of playbooks, you might
@ -686,37 +572,6 @@ Additional paths can be provided separated by colon characters, in the same way
Roles will be first searched for in the playbook directory. Should a role not be found, it will indicate all the possible paths
that were searched.
.. _cfg_squash_actions:
squash_actions
==============
.. versionadded:: 2.0
Ansible can optimise actions that call modules that support list parameters when using with\_ looping.
Instead of calling the module once for each item, the module is called once with the full list.
The default value for this setting is only for certain package managers, but it can be used for any module::
squash_actions = apk,apt,dnf,package,pacman,pkgng,yum,zypper
Currently, this is only supported for modules that have a name parameter, and only when the item is the
only thing being passed to the parameter.
.. _cfg_strategy_plugins:
strategy_plugins
==================
Strategy plugin allow users to change the way in which Ansible runs tasks on targeted hosts.
This is a developer-centric feature that allows low-level extensions around Ansible to be loaded from
different locations::
strategy_plugins = ~/.ansible/plugins/strategy_plugins/:/usr/share/ansible_plugins/strategy_plugins
Most users will not need to use this feature. See :doc:`developing_plugins` for more details
.. _sudo_exe:
sudo_exe
@ -732,12 +587,11 @@ the sudo implementation is matching CLI flags with the standard sudo::
sudo_flags
==========
Additional flags to pass to sudo when engaging sudo support. The default is '-H -S -n' which sets the HOME environment
variable, prompts for passwords via STDIN, and avoids prompting the user for input of any kind. Note that '-n' will conflict
with using password-less sudo auth, such as pam_ssh_agent_auth. In some situations you may wish to add or remove flags, but
in general most users will not need to change this setting:::
Additional flags to pass to sudo when engaging sudo support. The default is '-H' which preserves the $HOME environment variable
of the original user. In some situations you may wish to add or remove flags, but in general most users
will not need to change this setting::
sudo_flags=-H -S -n
sudo_flags=-H
.. _sudo_user:
@ -885,17 +739,6 @@ instead. Setting it to False will improve performance and is recommended when h
record_host_keys=True
.. _paramiko_proxy_command:
proxy_command
=============
.. versionadded:: 2.1
Use an OpenSSH like ProxyCommand for proxying all Paramiko SSH connections through a bastion or jump host. Requires a minimum of Paramiko version 1.9.0. On Enterprise Linux 6 this is provided by ``python-paramiko1.10`` in the EPEL repository::
proxy_command = ssh -W "%h:%p" bastion
.. _openssh_settings:
OpenSSH Specific Settings
@ -956,7 +799,7 @@ pipelining
==========
Enabling pipelining reduces the number of SSH operations required to
execute a module on the remote server, by executing many ansible modules without actual file transfer.
execute a module on the remote server, by executing many ansible modules without actual file transfer.
This can result in a very significant performance improvement when enabled, however when using "sudo:" operations you must
first disable 'requiretty' in /etc/sudoers on all managed hosts.
@ -971,7 +814,7 @@ recommended if you can enable it, eliminating the need for :doc:`playbooks_accel
Accelerated Mode Settings
-------------------------
Under the [accelerate] header, the following settings are tunable for :doc:`playbooks_acceleration`. Acceleration is
Under the [accelerate] header, the following settings are tunable for :doc:`playbooks_acceleration`. Acceleration is
a useful performance feature to use if you cannot enable :ref:`pipelining` in your environment, but is probably
not needed if you can.
@ -1055,17 +898,6 @@ The default list is: nfs,vboxsf,fuse,ramfs::
special_context_filesystems = nfs,vboxsf,fuse,ramfs,myspecialfs
libvirt_lxc_noseclabel
======================
.. versionadded:: 2.1
This setting causes libvirt to connect to lxc containers by passing --noseclabel to virsh.
This is necessary when running on systems which do not have SELinux.
The default behavior is no::
libvirt_lxc_noseclabel = True
Galaxy Settings
---------------

View File

@ -206,77 +206,6 @@ explicitly clear the cache, you can run the ec2.py script with the ``--refresh-c
# ./ec2.py --refresh-cache
.. _openstack_example:
Example: OpenStack External Inventory Script
````````````````````````````````````````````
If you use an OpenStack based cloud, instead of manually maintaining your own inventory file, you can use the openstack.py dynamic inventory to pull information about your compute instances directly from OpenStack.
You can download the latest version of the OpenStack inventory script at: https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.py
You can use the inventory script explicitly (by passing the `-i openstack.py` argument to Ansible) or implicitly (by placing the script at `/etc/ansible/hosts`).
Explicit use of inventory script
++++++++++++++++++++++++++++++++
Download the latest version of the OpenStack dynamic inventory script and make it executable::
wget https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.py
chmod +x openstack.py
Source an OpenStack RC file::
source openstack.rc
.. note::
An OpenStack RC file contains the environment variables required by the client tools to establish a connection with the cloud provider, such as the authentication URL, user name, password and region name. For more information on how to download, create or source an OpenStack RC file, please refer to http://docs.openstack.org/cli-reference/content/cli_openrc.html.
You can confirm the file has been successfully sourced by running a simple command, such as `nova list` and ensuring it return no errors.
.. note::
The OpenStack command line clients are required to run the `nova list` command. For more information on how to install them, please refer to http://docs.openstack.org/cli-reference/content/install_clients.html.
You can test the OpenStack dynamic inventory script manually to confirm it is working as expected::
./openstack.py --list
After a few moments you should see some JSON output with information about your compute instances.
Once you confirm the dynamic inventory script is working as expected, you can tell Ansible to use the `openstack.py` script as an inventory file, as illustrated below::
ansible -i openstack.py all -m ping
Implicit use of inventory script
++++++++++++++++++++++++++++++++
Download the latest version of the OpenStack dynamic inventory script, make it executable and copy it to `/etc/ansible/hosts`::
wget https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.py
chmod +x openstack.py
sudo cp openstack.py /etc/ansible/hosts
Download the sample configuration file, modify it to suit your needs and copy it to `/etc/ansible/openstack.yml`::
wget https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/openstack.yml
vi openstack.yml
sudo cp openstack.yml /etc/ansible/
You can test the OpenStack dynamic inventory script manually to confirm it is working as expected::
/etc/ansible/hosts --list
After a few moments you should see some JSON output with information about your compute instances.
Refresh the cache
+++++++++++++++++
Note that the OpenStack dynamic inventory script will cache results to avoid repeated API calls. To explicitly clear the cache, you can run the openstack.py (or hosts) script with the --refresh parameter:
./openstack.py --refresh
.. _other_inventory_scripts:
Other inventory scripts
@ -290,8 +219,7 @@ In addition to Cobbler and EC2, inventory scripts are also available for::
Linode
OpenShift
OpenStack Nova
Ovirt
SpaceWalk
Red Hat's SpaceWalk
Vagrant (not to be confused with the provisioner in vagrant, which is preferred)
Zabbix
@ -303,21 +231,13 @@ to include it in the project.
.. _using_multiple_sources:
Using Inventory Directories and Multiple Inventory Sources
``````````````````````````````````````````````````````````
Using Multiple Inventory Sources
````````````````````````````````
If the location given to -i in Ansible is a directory (or as so configured in ansible.cfg), Ansible can use multiple inventory sources
at the same time. When doing so, it is possible to mix both dynamic and statically managed inventory sources in the same ansible run. Instant
hybrid cloud!
In an inventory directory, executable files will be treated as dynamic inventory sources and most other files as static sources. Files which end with any of the following will be ignored::
~, .orig, .bak, .ini, .retry, .pyc, .pyo
You can replace this list with your own selection by configuring an ``inventory_ignore_extensions`` list in ansible.cfg, or setting the ANSIBLE_INVENTORY_IGNORE environment variable. The value in either case should be a comma-separated list of patterns, as shown above.
Any ``group_vars`` and ``host_vars`` subdirectories in an inventory directory will be interpreted as expected, making inventory directories a powerful way to organize different sets of configurations.
.. _static_groups_of_dynamic:
Static Groups of Dynamic Groups

View File

@ -33,7 +33,7 @@ In releases up to and including Ansible 1.2, the default was strictly paramiko.
Occasionally you'll encounter a device that doesn't support SFTP. This is rare, but should it occur, you can switch to SCP mode in :doc:`intro_configuration`.
When speaking with remote machines, Ansible by default assumes you are using SSH keys. SSH keys are encouraged but password authentication can also be used where needed by supplying the option ``--ask-pass``. If using sudo features and when sudo requires a password, also supply ``--ask-become-pass`` (previously ``--ask-sudo-pass`` which has been deprecated).
When speaking with remote machines, Ansible by default assumes you are using SSH keys. SSH keys are encouraged but password authentication can also be used where needed by supplying the option ``--ask-pass``. If using sudo features and when sudo requires a password, also supply ``--ask-sudo-pass``.
While it may be common sense, it is worth sharing: Any management system benefits from being run near the machines being managed. If you are running Ansible in a cloud, consider running it from a machine inside that cloud. In most cases this will work better than on the open Internet.

View File

@ -52,13 +52,9 @@ This includes Red Hat, Debian, CentOS, OS X, any of the BSDs, and so on.
.. note::
As of 2.0 ansible uses a few more file handles to manage its forks, OS X has a very low setting so if you want to use 15 or more forks
you'll need to raise the ulimit, like so ``sudo launchctl limit maxfiles unlimited``. Or just any time you see a "Too many open files" error.
you'll need to raise the ulimit, like so ``sudo launchctl limit maxfiles 1024 2048``. Or just any time you see a "Too many open files" error.
.. warning::
Please note that some modules and plugins have additional requirements, for modules these need to be satisfied on the 'target' machine and should be listed in the module specific docs.
.. _managed_node_requirements:
Managed Node Requirements
@ -201,7 +197,7 @@ Fedora users can install Ansible directly, though if you are using RHEL or CentO
# install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux
$ sudo yum install ansible
You can also build an RPM yourself. From the root of a checkout or tarball, use the ``make rpm`` command to build an RPM you can distribute and install. Make sure you have ``rpm-build``, ``make``, ``asciidoc``, ``git``, ``python-setuptools`` and ``python2-devel`` installed.
You can also build an RPM yourself. From the root of a checkout or tarball, use the ``make rpm`` command to build an RPM you can distribute and install. Make sure you have ``rpm-build``, ``make``, and ``python2-devel`` installed.
.. code-block:: bash
@ -226,7 +222,6 @@ To configure the PPA on your machine and install ansible run these commands:
$ sudo apt-get update
$ sudo apt-get install ansible
.. note:: For the older version 1.9 we use this ppa:ansible/ansible-1.9
.. note:: On older Ubuntu distributions, "software-properties-common" is called "python-software-properties".
Debian/Ubuntu packages can also be built from the source checkout, run:
@ -322,10 +317,6 @@ your version of Python, you can get pip by::
Then install Ansible with [1]_::
$ sudo pip install ansible
Or if you are looking for the latest development version::
pip install git+git://github.com/ansible/ansible.git@devel
If you are installing on OS X Mavericks, you may encounter some noise from your compiler. A workaround is to do the following::

View File

@ -7,7 +7,7 @@ Inventory
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 being saved in
Ansible's inventory file, which defaults to being saved in
the location /etc/ansible/hosts.
Not only is this inventory configurable, but you can also use
@ -35,7 +35,7 @@ The format for /etc/ansible/hosts is an INI-like format and looks like this::
The things in brackets are group names, which are used in classifying systems
and deciding what systems you are controlling at what times and for what purpose.
It is ok to put systems in more than one group, for instance a server could be both a webserver and a dbserver.
It is ok to put systems in more than one group, for instance a server could be both a webserver and a dbserver.
If you do, note that variables will come from all of the groups they are a member of, and variable precedence is detailed in a later chapter.
If you have hosts that run on non-standard SSH ports you can put the port number
@ -149,7 +149,7 @@ The preferred practice in Ansible is actually not to store variables in the main
In addition to storing variables directly in the INI file, host
and group variables can be stored in individual files relative to the
inventory file.
inventory file.
These variable files are in YAML format. Valid file extensions include '.yml', '.yaml', '.json',
or no file extension. See :doc:`YAMLSyntax` if you are new to YAML.
@ -186,7 +186,7 @@ available to them. This can be very useful to keep your variables organized when
file starts to be too big, or when you want to use :doc:`Ansible Vault<playbooks_vault>` on a part of a group's
variables. Note that this only works on Ansible 1.4 or later.
Tip: In Ansible 1.2 or later the group_vars/ and host_vars/ directories can exist in
Tip: In Ansible 1.2 or later the group_vars/ and host_vars/ directories can exist in either
the playbook directory OR the inventory directory. If both paths exist, variables in the playbook
directory will override variables set in the inventory directory.
@ -200,74 +200,64 @@ List of Behavioral Inventory Parameters
As alluded to above, setting the following variables controls how ansible interacts with remote hosts.
Host connection:
Host connection::
ansible_connection
Connection type to the host. This can be the name of any of ansible's connection plugins. SSH protocol types are smart, ssh or paramiko. The default is smart. Non-SSH based types are described in the next section.
ansible_connection
Connection type to the host. Candidates are local, smart, ssh or paramiko. The default is smart.
.. include:: ansible_ssh_changes_note.rst
SSH connection:
SSH connection::
ansible_host
The name of the host to connect to, if different from the alias you wish to give to it.
ansible_port
The ssh port number, if not 22
ansible_user
The default ssh user name to use.
ansible_ssh_pass
The ssh password to use (this is insecure, we strongly recommend using :option:`--ask-pass` or SSH keys)
ansible_ssh_private_key_file
Private key file used by ssh. Useful if using multiple keys and you don't want to use SSH agent.
ansible_ssh_common_args
This setting is always appended to the default command line for :command:`sftp`, :command:`scp`,
and :command:`ssh`. Useful to configure a ``ProxyCommand`` for a certain host (or
group).
ansible_sftp_extra_args
This setting is always appended to the default :command:`sftp` command line.
ansible_scp_extra_args
This setting is always appended to the default :command:`scp` command line.
ansible_ssh_extra_args
This setting is always appended to the default :command:`ssh` command line.
ansible_ssh_pipelining
Determines whether or not to use SSH pipelining. This can override the ``pipelining`` setting in :file:`ansible.cfg`.
ansible_host
The name of the host to connect to, if different from the alias you wish to give to it.
ansible_port
The ssh port number, if not 22
ansible_user
The default ssh user name to use.
ansible_ssh_pass
The ssh password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys)
ansible_ssh_private_key_file
Private key file used by ssh. Useful if using multiple keys and you don't want to use SSH agent.
ansible_ssh_common_args
This setting is always appended to the default command line for
sftp, scp, and ssh. Useful to configure a ``ProxyCommand`` for a
certain host (or group).
ansible_sftp_extra_args
This setting is always appended to the default sftp command line.
ansible_scp_extra_args
This setting is always appended to the default scp command line.
ansible_ssh_extra_args
This setting is always appended to the default ssh command line.
ansible_ssh_pipelining
Determines whether or not to use SSH pipelining. This can override the
``pipelining`` setting in ``ansible.cfg``.
Privilege escalation (see :doc:`Ansible Privilege Escalation<become>` for further details):
Privilege escalation (see :doc:`Ansible Privilege Escalation<become>` for further details)::
ansible_become
Equivalent to ``ansible_sudo`` or ``ansible_su``, allows to force privilege escalation
ansible_become_method
Allows to set privilege escalation method
ansible_become_user
Equivalent to ``ansible_sudo_user`` or ``ansible_su_user``, allows to set the user you become through privilege escalation
ansible_become_pass
Equivalent to ``ansible_sudo_pass`` or ``ansible_su_pass``, allows you to set the privilege escalation password
ansible_become
Equivalent to ansible_sudo or ansible_su, allows to force privilege escalation
ansible_become_method
Allows to set privilege escalation method
ansible_become_user
Equivalent to ansible_sudo_user or ansible_su_user, allows to set the user you become through privilege escalation
ansible_become_pass
Equivalent to ansible_sudo_pass or ansible_su_pass, allows you to set the privilege escalation password
Remote host environment parameters:
Remote host environment parameters::
ansible_shell_type
The shell type of the target system. You should not use this setting unless you have set the ``ansible_shell_executable`` to a non-Bourne (sh) compatible shell.
By default commands are formatted using ``sh``-style syntax.
Setting this to ``csh`` or ``fish`` will cause commands executed on target systems to follow those shell's syntax instead.
ansible_python_interpreter
The target host python path. This is useful for systems with more
than one Python or not located at :command:`/usr/bin/python` such as \*BSD, or where :command:`/usr/bin/python`
is not a 2.X series Python. We do not use the :command:`/usr/bin/env` mechanism as that requires the remote user's
path to be set right and also assumes the :program:`python` executable is named python, where the executable might
be named something like :program:`python2.6`.
ansible_*_interpreter
Works for anything such as ruby or perl and works just like ``ansible_python_interpreter``.
This replaces shebang of modules which will run on that host.
.. versionadded:: 2.1
ansible_shell_executable
This sets the shell the ansible controller will use on the target machine,
overrides ``executable`` in :file:`ansible.cfg` which defaults to
:command:`/bin/sh`. You should really only change it if is not possible
to use :command:`/bin/sh` (i.e. :command:`/bin/sh` is not installed on the target
machine or cannot be run from sudo.).
ansible_shell_type
The shell type of the target system. Commands are formatted using 'sh'-style syntax by default. Setting this to 'csh' or 'fish' will cause commands executed on target systems to follow those shell's syntax instead.
ansible_python_interpreter
The target host python path. This is useful for systems with more
than one Python or not located at "/usr/bin/python" such as \*BSD, or where /usr/bin/python
is not a 2.X series Python. We do not use the "/usr/bin/env" mechanism as that requires the remote user's
path to be set right and also assumes the "python" executable is named python, where the executable might
be named something like "python26".
ansible\_\*\_interpreter
Works for anything such as ruby or perl and works just like ansible_python_interpreter.
This replaces shebang of modules which will run on that host.
Examples from a host file::
@ -276,50 +266,6 @@ Examples from a host file::
freebsd_host ansible_python_interpreter=/usr/local/bin/python
ruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3
Non-SSH connection types
++++++++++++++++++++++++
As stated in the previous section, Ansible is executing playbooks over SSH but is not limited to.
With the host specific parameter ``ansible_connection=<connector>`` the connection type can be changed.
Following non SSH based connectors are available:
**local**
This connector can be used to deploy the playbook to the control machine itself.
**docker**
This connector deploys the playbook directly into Docker containers using the local Docker client. Following parameters are processed by this connector:
ansible_host
The name of the Docker container to connect to.
ansible_user
The user name to operate within the container. The user must exist inside the container.
ansible_become
If set to ``true`` the ``become_user`` will be used to operate within the container.
ansible_docker_extra_args
Could be a string with any additional arguments understood by Docker, which are not command specific. This parameter is mainly used to configure a remote Docker daemon to use.
Here an example of how to instantly depoloy to created containers::
- name: create jenkins container
docker:
name: my_jenkins
image: jenkins
- name: add container to inventory
add_host:
name: my_jenkins
ansible_connection: docker
ansible_docker_extra_args: "--tlsverify --tlscacert=/path/to/ca.pem --tlscert=/path/to/client-cert.pem --tlskey=/path/to/client-key.pem -H=tcp://myserver.net:4243"
ansible_user: jenkins
changed_when: false
- name: create directory for ssh keys
delegate_to: my_jenkins
file:
path: "/var/jenkins_home/.ssh/jupiter"
state: directory
.. seealso::
@ -333,3 +279,4 @@ Here an example of how to instantly depoloy to created containers::
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@ -31,7 +31,7 @@ It is also possible to address a specific host or set of hosts by name::
192.168.1.50
192.168.1.*
The following patterns address one or more groups. Groups separated by a colon indicate an "OR" configuration.
The following patterns address one or more groups. Groups separated by a comma indicate an "OR" configuration.
This means the host may be in either one group or the other::
webservers

View File

@ -8,7 +8,7 @@ Windows Support
Windows: How Does It Work
`````````````````````````
As you may have already read, Ansible manages Linux/Unix machines using SSH by default.
As you may have already read, Ansible manages Linux/Unix machines using SSH by default.
Starting in version 1.7, Ansible also contains support for managing Windows machines. This uses
native PowerShell remoting, rather than SSH.
@ -28,8 +28,6 @@ On a Linux control machine::
pip install "pywinrm>=0.1.1"
Note:: on distributions with multiple python versions, use pip2 or pip2.x, where x matches the python minor version Ansible is running under.
Active Directory Support
++++++++++++++++++++++++
@ -42,22 +40,22 @@ Installing python-kerberos dependencies
# Via Yum
yum -y install python-devel krb5-devel krb5-libs krb5-workstation
# Via Apt (Ubuntu)
sudo apt-get install python-dev libkrb5-dev
# Via Portage (Gentoo)
emerge -av app-crypt/mit-krb5
emerge -av app-crypt/mit-krb5
emerge -av dev-python/setuptools
# Via pkg (FreeBSD)
sudo pkg install security/krb5
# Via OpenCSW (Solaris)
pkgadd -d http://get.opencsw.org/now
/opt/csw/bin/pkgutil -U
/opt/csw/bin/pkgutil -y -i libkrb5_3
/opt/csw/bin/pkgutil -y -i libkrb5_3
# Via Pacman (Arch Linux)
pacman -S krb5
@ -172,8 +170,6 @@ In group_vars/windows.yml, define the following inventory variables::
# The following is necessary for Python 2.7.9+ when using default WinRM self-signed certificates:
ansible_winrm_server_cert_validation: ignore
Attention for the older style variables (``ansible_ssh_*``): ansible_ssh_password doesn't exist, should be ansible_ssh_pass.
Although Ansible is mostly an SSH-oriented system, Windows management will not happen over SSH (`yet <http://blogs.msdn.com/b/powershell/archive/2015/06/03/looking-forward-microsoft-support-for-secure-shell-ssh.aspx>`).
If you have installed the ``kerberos`` module and ``ansible_user`` contains ``@`` (e.g. ``username@realm``), Ansible will first attempt Kerberos authentication. *This method uses the principal you are authenticated to Kerberos with on the control machine and not ``ansible_user``*. If that fails, either because you are not signed into Kerberos on the control machine or because the corresponding domain account on the remote host is not available, then Ansible will fall back to "plain" username/password authentication.
@ -207,23 +203,18 @@ Windows System Prep
In order for Ansible to manage your windows machines, you will have to enable PowerShell remoting configured.
To automate setup of WinRM, you can run `this PowerShell script <https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1>`_ on the remote machine.
To automate setup of WinRM, you can run `this PowerShell script <https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1>`_ on the remote machine.
The example script accepts a few arguments which Admins may choose to use to modify the default setup slightly, which might be appropriate in some cases.
Pass the -CertValidityDays option to customize the expiration date of the generated certificate.
powershell.exe -File ConfigureRemotingForAnsible.ps1 -CertValidityDays 100
Pass the -SkipNetworkProfileCheck switch to configure winrm to listen on PUBLIC zone interfaces. (Without this option, the script will fail if any network interface on device is in PUBLIC zone)
powershell.exe -File ConfigureRemotingForAnsible.ps1 -SkipNetworkProfileCheck
Admins may wish to modify this setup slightly, for instance to increase the timeframe of
the certificate.
.. note::
On Windows 7 and Server 2008 R2 machines, due to a bug in Windows
On Windows 7 and Server 2008 R2 machines, due to a bug in Windows
Management Framework 3.0, it may be necessary to install this
hotfix http://support.microsoft.com/kb/2842230 to avoid receiving
out of memory and stack overflow exceptions. Newly-installed Server 2008
R2 systems which are not fully up to date with windows updates are known
to have this issue.
to have this issue.
Windows 8.1 and Server 2012 R2 are not affected by this issue as they
come with Windows Management Framework 4.0.
@ -242,8 +233,8 @@ Looking at an Ansible checkout, copy the `examples/scripts/upgrade_to_ps3.ps1 <h
What modules are available
``````````````````````````
Most of the Ansible modules in core Ansible are written for a combination of Linux/Unix machines and arbitrary web services, though there are various
Windows modules as listed in the `"windows" subcategory of the Ansible module index <http://docs.ansible.com/list_of_windows_modules.html>`_.
Most of the Ansible modules in core Ansible are written for a combination of Linux/Unix machines and arbitrary web services, though there are various
Windows modules as listed in the `"windows" subcategory of the Ansible module index <http://docs.ansible.com/list_of_windows_modules.html>`_.
Browse this index to see what is available.
@ -265,7 +256,10 @@ Developers: Supported modules and how it works
Developing Ansible modules are covered in a `later section of the documentation <http://docs.ansible.com/developing_modules.html>`_, with a focus on Linux/Unix.
What if you want to write Windows modules for Ansible though?
For Windows, Ansible modules are implemented in PowerShell. Skim those Linux/Unix module development chapters before proceeding. Windows modules in the core and extras repo live in a "windows/" subdir. Custom modules can go directly into the Ansible "library/" directories or those added in ansible.cfg. Documentation lives in a `.py` file with the same name. For example, if a module is named "win_ping", there will be embedded documentation in the "win_ping.py" file, and the actual PowerShell code will live in a "win_ping.ps1" file. Take a look at the sources and this will make more sense.
For Windows, Ansible modules are implemented in PowerShell. Skim those Linux/Unix module development chapters before proceeding.
Windows modules live in a "windows/" subfolder in the Ansible "library/" subtree. For example, if a module is named
"library/windows/win_ping", there will be embedded documentation in the "win_ping" file, and the actual PowerShell code will live in a "win_ping.ps1" file. Take a look at the sources and this will make more sense.
Modules (ps1 files) should start as follows::
@ -328,14 +322,6 @@ Running individual commands uses the 'raw' module, as opposed to the shell or co
register: ipconfig
- debug: var=ipconfig
Running common DOS commands like 'del", 'move', or 'copy" is unlikely to work on a remote Windows Server using Powershell, but they can work by prefacing the commands with "CMD /C" and enclosing the command in double quotes as in this example::
- name: another raw module example
hosts: windows
tasks:
- name: Move file on remote Windows Server from one location to another
raw: CMD /C "MOVE /Y C:\teststuff\myfile.conf C:\builds\smtp.conf"
And for a final example, here's how to use the win_stat module to test for file existence. Note that the data returned by the win_stat module is slightly different than what is provided by the Linux equivalent::
- name: test stat module
@ -377,3 +363,5 @@ form of new modules, tweaks to existing modules, documentation, or something els
Questions? Help? Ideas? Stop by the list on Google Groups
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@ -1,59 +0,0 @@
Advanced Syntax
===============
.. contents:: Topics
This page describes advanced YAML syntax that enables you to have more control over the data placed in YAML files used by Ansible.
.. _yaml_tags_and_python_types:
YAML tags and Python types
``````````````````````````
The documentation covered here is an extension of the documentation that can be found in the `PyYAML Documentation <http://pyyaml.org/wiki/PyYAMLDocumentation#YAMLtagsandPythontypes>`_
.. _unsafe_strings:
Unsafe or Raw Strings
~~~~~~~~~~~~~~~~~~~~~
As of Ansible 2.0, there is an internal data type for declaring variable values as "unsafe". This means that the data held within the variables value should be treated as unsafe preventing unsafe character subsitition and information disclosure.
Jinja2 contains functionality for escaping, or telling Jinja2 to not template data by means of functionality such as ``{% raw %} ... {% endraw %}``, however this uses a more comprehensive implementation to ensure that the value is never templated.
Using YAML tags, you can also mark a value as "unsafe" by using the ``!unsafe`` tag such as::
---
my_unsafe_variable: !unsafe 'this variable has {{ characters that should not be treated as a jinja2 template'
In a playbook, this may look like::
---
hosts: all
vars:
my_unsafe_variable: !unsafe 'unsafe value'
tasks:
...
For complex variables such as hashes or arrays, ``!unsafe`` should be used on the individual elements such as::
---
my_unsafe_array:
- !unsafe 'unsafe element'
- 'safe element'
my_unsafe_hash:
unsafe_key: !unsafe 'unsafe value'
.. seealso::
:doc:`playbooks_variables`
All about variables
`User Mailing List <http://groups.google.com/group/ansible-project>`_
Have a question? Stop by the google group!
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@ -254,8 +254,8 @@ What about just my webservers in Boston?::
What about just the first 10, and then the next 10?::
ansible-playbook -i production webservers.yml --limit boston[1-10]
ansible-playbook -i production webservers.yml --limit boston[11-20]
ansible-playbook -i production webservers.yml --limit boston[0-10]
ansible-playbook -i production webservers.yml --limit boston[10-20]
And of course just basic ad-hoc stuff is also possible.::

View File

@ -27,9 +27,8 @@ to the tasks.
become_user: root
In the example above the each of the 3 tasks will be executed after appending the `when` condition from the block
and evaluating it in the task's context. Also they inherit the privilege escalation directives enabling "become to root"
for all the enclosed tasks.
In the example above the 3 tasks will be executed only when the block's when condition is met and enables
privilege escalation for all the enclosed tasks.
.. _block_error_handling:
@ -61,23 +60,6 @@ with whatever you need to do to recover from the previous error. The ``always``
error did or did not occur in the ``block`` and ``rescue`` sections.
Another example is how to run handlers after an error occurred :
.. code-block:: YAML
:emphasize-lines: 4,8
:caption: Block run handlers in error handling
tasks:
- block:
- debug: msg='i execute normally'
notify: run me even after an error
- command: /bin/false
rescue:
- name: make sure all handlers run
meta: flush_handlers
handlers:
- name: run me even after an error
debug: msg='this handler runs even on error'
.. seealso::

View File

@ -1,5 +1,3 @@
.. _check_mode_dry:
Check Mode ("Dry Run")
======================
@ -40,25 +38,7 @@ Example::
As a reminder, a task with a `when` clause evaluated to false, will
still be skipped even if it has a `always_run` clause evaluated to
true.
Also if you want to skip, or ignore errors on some tasks in check mode
you can use a boolean magic variable `ansible_check_mode` (added in version 2.1)
which will be set to `True` during check mode.
Example::
tasks:
- name: this task will be skipped in check mode
git: repo=ssh://git@github.com/mylogin/hello.git dest=/home/mylogin/hello
when: not ansible_check_mode
- name: this task will ignore errors in check mode
git: repo=ssh://git@github.com/mylogin/hello.git dest=/home/mylogin/hello
ignore_errors: "{{ ansible_check_mode }}"
true.
.. _diff_mode:

View File

@ -47,7 +47,7 @@ decide to do something conditionally based on success or failure::
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|succeeded
when: result|success
- command: /bin/still/something_else
when: result|skipped
@ -95,32 +95,13 @@ If a required variable has not been set, you can skip or fail using Jinja2's
This is especially useful in combination with the conditional import of vars
files (see below).
.. _loops_and_conditionals:
Loops and Conditionals
``````````````````````
Combining `when` with `with_items` (see :doc:`playbooks_loops`), be aware that the `when` statement is processed separately for each item. This is by design::
Note that when combining `when` with `with_items` (see :doc:`playbooks_loops`), be aware that the `when` statement is processed separately for each item. This is by design::
tasks:
- command: echo {{ item }}
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
If you need to skip the whole task depending on the loop variable being defined, used the `|default` filter to provide an empty iterator::
- command: echo {{ item }}
with_items: "{{ mylist|default([]) }}"
when: item > 5
If using `with_dict` which does not take a list::
- command: echo {{ item.key }}
with_dict: "{{ mydict|default({}) }}"
when: item.value > 5
.. _loading_in_custom_facts:
Loading in Custom Facts
```````````````````````
@ -133,9 +114,7 @@ there will be accessible to future tasks::
action: site_facts
- command: /usr/bin/thingy
when: my_custom_fact_just_retrieved_from_the_remote_system == '1234'
.. _when_roles_and_includes:
Applying 'when' to roles and includes
`````````````````````````````````````
@ -156,8 +135,6 @@ Or with a role::
You will note a lot of 'skipped' output by default in Ansible when using this approach on systems that don't match the criteria.
Read up on the 'group_by' module in the :doc:`modules` docs for a more streamlined way to accomplish the same thing.
.. _conditional_imports:
Conditional Imports
```````````````````
@ -271,22 +248,6 @@ fields::
with_items: home_dirs.stdout_lines
# same as with_items: home_dirs.stdout.split()
As shown previously, the registered variable's string contents are accessible with the 'stdout' value.
You may check the registered variable's string contents for emptiness::
- name: check registered variable for emptiness
hosts: all
tasks:
- name: list contents of directory
command: ls mydir
register: contents
- name: check contents for emptiness
debug: msg="Directory is empty"
when: contents.stdout == ""
.. seealso::

View File

@ -1,159 +0,0 @@
Playbook Debugger
=================
.. contents:: Topics
In 2.1 we added a ``debug`` strategy. This strategy enables you to invoke a debugger when a task is
failed, and check several info, such as the value of a variable. Also, it is possible to update module
arguments in the debugger, and run the failed task again with new arguments to consider how you
can fix an issue.
To use ``debug`` strategy, change ``strategy`` attribute like this::
- hosts: test
strategy: debug
tasks:
...
For example, run the playbook below::
- hosts: test
strategy: debug
gather_facts: no
vars:
var1: value1
tasks:
- name: wrong variable
ping: data={{ wrong_var }}
The debugger is invoked since *wrong_var* variable is undefined. Let's change the module's args,
and run the task again::
PLAY ***************************************************************************
TASK [wrong variable] **********************************************************
fatal: [192.168.1.1]: FAILED! => {"failed": true, "msg": "ERROR! 'wrong_var' is undefined"}
Debugger invoked
(debug) p result
{'msg': u"ERROR! 'wrong_var' is undefined", 'failed': True}
(debug) p task.args
{u'data': u'{{ wrong_var }}'}
(debug) task.args['data'] = '{{ var1 }}'
(debug) p task.args
{u'data': '{{ var1 }}'}
(debug) redo
ok: [192.168.1.1]
PLAY RECAP *********************************************************************
192.168.1.1 : ok=1 changed=0 unreachable=0 failed=0
This time, the task runs successfully!
.. _available_commands:
Available Commands
++++++++++++++++++
.. _p_command:
p *task/vars/host/result*
`````````````````````````
Print values used to execute a module::
(debug) p task
TASK: install package
(debug) p task.args
{u'name': u'{{ pkg_name }}'}
(debug) p vars
{u'ansible_all_ipv4_addresses': [u'192.168.1.1'],
u'ansible_architecture': u'x86_64',
...
}
(debug) p vars['pkg_name']
u'bash'
(debug) p host
192.168.1.1
(debug) p result
{'_ansible_no_log': False,
'changed': False,
u'failed': True,
...
u'msg': u"No package matching 'not_exist' is available"}
.. _update_args_command:
task.args[*key*] = *value*
``````````````````````````
Update module's argument.
If you run a playbook like this::
- hosts: test
strategy: debug
gather_facts: yes
vars:
pkg_name: not_exist
tasks:
- name: install package
apt: name={{ pkg_name }}
Debugger is invoked due to wrong package name, so let's fix the module's args::
(debug) p task.args
{u'name': u'{{ pkg_name }}'}
(debug) task.args['name'] = 'bash'
(debug) p task.args
{u'name': 'bash'}
(debug) redo
Then the task runs again with new args.
.. _update_vars_command:
vars[*key*] = *value*
`````````````````````
Update vars.
Let's use the same playbook above, but fix vars instead of args::
(debug) p vars['pkg_name']
u'not_exist'
(debug) vars['pkg_name'] = 'bash'
(debug) p vars['pkg_name']
'bash'
(debug) redo
Then the task runs again with new vars.
.. _redo_command:
r(edo)
``````
Run the task again.
.. _continue_command:
c(ontinue)
``````````
Just continue.
.. _quit_command:
q(uit)
``````
Quit from the debugger. The playbook execution is aborted.
.. seealso::
:doc:`playbooks`
An introduction to playbooks
`User Mailing List <http://groups.google.com/group/ansible-devel>`_
Have a question? Stop by the google group!
`irc.freenode.net <http://irc.freenode.net>`_
#ansible IRC chat channel

View File

@ -130,8 +130,6 @@ Here is an example::
Note that you must have passphrase-less SSH keys or an ssh-agent configured for this to work, otherwise rsync
will need to ask for a passphrase.
The `ansible_host` variable (`ansible_ssh_host` in 1.x) reflects the host a task is delegated to.
.. _delegate_facts:
Delegated facts
@ -149,7 +147,7 @@ In 2.0, the directive `delegate_facts` may be set to `True` to assign the task's
setup:
delegate_to: "{{item}}"
delegate_facts: True
with_items: "{{groups['dbservers']}}"
with_items: "{{groups['dbservers'}}"
The above will gather facts for the machines in the dbservers group and assign the facts to those machines and not to app_servers.
This way you can lookup `hostvars['dbhost1']['default_ipv4_addresses'][0]` even though dbservers were not part of the play, or left out by using `--limit`.

View File

@ -58,17 +58,12 @@ The following tasks are illustrative of how filters can be used with conditional
- debug: msg="it changed"
when: result|changed
- debug: msg="it succeeded in Ansible >= 2.1"
when: result|succeeded
- debug: msg="it succeeded"
when: result|success
- debug: msg="it was skipped"
when: result|skipped
.. note:: From 2.1 You can also use success, failure, change, skip so the grammer matches, for those that want to be strict about it.
.. _forcing_variables_to_be_defined:
Forcing Variables To Be Defined
@ -357,39 +352,6 @@ override those in `b`, and so on.
This behaviour does not depend on the value of the `hash_behaviour`
setting in `ansible.cfg`.
.. _extract_filter:
Extracting values from containers
---------------------------------
.. versionadded:: 2.1
The `extract` filter is used to map from a list of indices to a list of
values from a container (hash or array)::
{{ [0,2]|map('extract', ['x','y','z'])|list }}
{{ ['x','y']|map('extract', {'x': 42, 'y': 31})|list }}
The results of the above expressions would be::
['x', 'z']
[42, 31]
The filter can take another argument::
{{ groups['x']|map('extract', hostvars, 'ec2_ip_address')|list }}
This takes the list of hosts in group 'x', looks them up in `hostvars`,
and then looks up the `ec2_ip_address` of the result. The final result
is a list of IP addresses for the hosts in group 'x'.
The third argument to the filter can also be a list, for a recursive
lookup inside the container::
{{ ['a']|map('extract', b, ['x','y'])|list }}
This would return a list containing the value of `b['a']['x']['y']`.
.. _comment_filter:
Comment Filter

View File

@ -283,37 +283,6 @@ If needed, you can extract subnet and prefix information from 'host/prefix' valu
# {{ host_prefix | ipaddr('host/prefix') | ipaddr('prefix') }}
[64, 24]
Converting subnet masks to CIDR notation
----------------------------------------
Given a subnet in the form of network address and subnet mask, it can be converted into CIDR notation using ``ipaddr()``. This can be useful for converting Ansible facts gathered about network configuration from subnet masks into CIDR format::
ansible_default_ipv4: {
address: "192.168.0.11",
alias: "eth0",
broadcast: "192.168.0.255",
gateway: "192.168.0.1",
interface: "eth0",
macaddress: "fa:16:3e:c4:bd:89",
mtu: 1500,
netmask: "255.255.255.0",
network: "192.168.0.0",
type: "ether"
}
First concatenate network and netmask::
net_mask = "{{ ansible_default_ipv4.network }}/{{ ansible_default_ipv4.netmask }}"
'192.168.0.0/255.255.255.0'
This result can be canonicalised with ``ipaddr()`` to produce a subnet in CIDR format::
# {{ net_mask | ipaddr('prefix') }}
'24'
# {{ net_mask | ipaddr('net') }}
'192.168.0.0/24'
IP address conversion
---------------------

View File

@ -41,7 +41,7 @@ Each playbook is composed of one or more 'plays' in a list.
The goal of a play is to map a group of hosts to some well defined roles, represented by
things ansible calls tasks. At a basic level, a task is nothing more than a call
to an ansible module (see :doc:`modules`).
to an ansible module, which you should have learned about in earlier chapters.
By composing a playbook of multiple 'plays', it is possible to
orchestrate multi-machine deployments, running certain steps on all
@ -180,9 +180,9 @@ Support for running things as another user is also available (see :doc:`become`)
---
- hosts: webservers
remote_user: yourname
become: yes
sudo: yes
You can also use become on a particular task instead of the whole play::
You can also use sudo on a particular task instead of the whole play::
---
- hosts: webservers
@ -382,7 +382,7 @@ Handlers are best used to restart services and trigger reboots. You probably
won't need them for much else.
.. note::
* Notify handlers are always run in the same order they are defined, `not` in the order listed in the notify-statement.
* Notify handlers are always run in the order written.
* Handler names live in a global namespace.
* If two handler tasks have the same name, only one will run.
`* <https://github.com/ansible/ansible/issues/4943>`_

View File

@ -25,7 +25,6 @@ The file lookup is the most basic lookup type.
Contents can be read off the filesystem as follows::
---
- hosts: all
vars:
contents: "{{ lookup('file', '/etc/foo.txt') }}"
@ -135,10 +134,9 @@ appears exactly once in column 0 (the first column, 0-indexed) of the table. All
Field Default Description
---------- ------------ -----------------------------------------------------------------------------------------
file ansible.csv Name of the file to load
col 1 The column to output, indexed by 0
delimiter TAB Delimiter used by CSV file. As a special case, tab can be specified as either TAB or \t.
default empty string Default return value if the key is not in the csv file
encoding utf-8 Encoding (character set) of the used CSV file (added in version 2.1)
col 1 The column to output, indexed by 0
default empty string return value if the key is not in the csv file
========== ============ =========================================================================================
.. note:: The default delimiter is TAB, *not* comma.

View File

@ -204,7 +204,7 @@ It might happen like so::
- authorized_key: "user={{ item.0.name }} key='{{ lookup('file', item.1) }}'"
with_subelements:
- "{{ users }}"
- users
- authorized
Given the mysql hosts and privs subkey lists, you can also iterate over a list in a nested subkey::
@ -212,7 +212,7 @@ Given the mysql hosts and privs subkey lists, you can also iterate over a list i
- name: Setup MySQL users
mysql_user: name={{ item.0.name }} password={{ item.0.mysql.password }} host={{ item.1 }} priv={{ item.0.mysql.privs | join('/') }}
with_subelements:
- "{{ users }}"
- users
- mysql.hosts
Subelements walks a list of hashes (aka dictionaries) and then traverses a list with a given (nested sub-)key inside of those
@ -340,7 +340,7 @@ Iterating Over The Results of a Program Execution
.. note:: This is an uncommon thing to want to do, but we're documenting it for completeness. You probably won't be reaching for this one often.
Sometimes you might want to execute a program, and based on the output of that program, loop over the results of that line by line.
Ansible provides a neat way to do that, though you should remember, this is always executed on the control machine, not the remote
Ansible provides a neat way to do that, though you should remember, this is always executed on the control machine, not the local
machine::
- name: Example of looping over a command result
@ -516,85 +516,28 @@ Subsequent loops over the registered variable to inspect the results may look li
.. _looping_over_the_inventory:
.. _loops_and_includes:
Looping over the inventory
``````````````````````````
Loops and Includes
If you wish to loop over the inventory, or just a subset of it, there is multiple ways.
One can use a regular ``with_items`` with the ``play_hosts`` or ``groups`` variables, like this::
``````````````````
# show all the hosts in the inventory
- debug: msg={{ item }}
with_items: "{{groups['all']}}"
# show all the hosts in the current play
- debug: msg={{ item }}
with_items: play_hosts
There is also a specific lookup plugin ``inventory_hostname`` that can be used like this::
# show all the hosts in the inventory
- debug: msg={{ item }}
with_inventory_hostnames: all
# show all the hosts matching the pattern, ie all but the group www
- debug: msg={{ item }}
with_inventory_hostnames: all:!www
More information on the patterns can be found on :doc:`intro_patterns`
.. _loop_control:
Loop Control
````````````
.. versionadded: 2.1
In 2.0 you are again able to use `with_` loops and task includes (but not playbook includes). This adds the ability to loop over the set of tasks in one shot.
Ansible by default sets the loop variable `item` for each loop, which causes these nested loops to overwrite the value of `item` from the "outer" loops.
As of Ansible 2.1, the `loop_control` option can be used to specify the name of the variable to be used for the loop::
# main.yml
- include: test.yml outer_loop="{{outer_item}}"
with_items:
- 1
- 2
- 3
loop_control:
loop_var: outer_item
# inner.yml
- debug: msg="outer item={{outer_loop}} inner item={{item}}"
with_items:
- a
- b
- c
.. note:: If Ansible detects that the current loop is using a variable which has already been defined, it will raise an error to fail the task.
In 2.0 you are able to use `with_` loops and task includes (but not playbook includes), this adds the ability to loop over the set of tasks in one shot.
There are a couple of things that you need to keep in mind, a included task that has it's own `with_` loop will overwrite the value of the special `item` variable.
So if you want access to both the include's `item` and the current task's `item` you should use `set_fact` to create a alias to the outer one.::
.. _loops_and_includes_2.0:
Loops and Includes in 2.0
`````````````````````````
Because `loop_control` is not available in Ansible 2.0, when using an include with a loop you should use `set_fact` to save the "outer" loops value
for `item`::
# main.yml
- include: test.yml
with_items:
- 1
- 2
- 3
# inner.yml
- set_fact:
outer_item: "{{item}}"
in test.yml::
- debug:
msg: "outer item={{outer_item}} inner item={{item}}"
- set_fact: outer_loop="{{item}}"
- debug: msg="outer item={{outer_loop}} inner item={{item}}"
with_items:
- a
- b

View File

@ -213,8 +213,8 @@ Also, should you wish to parameterize roles, by adding variables, you can do so,
- hosts: webservers
roles:
- common
- { role: foo_app_instance, dir: '/opt/a', app_port: 5000 }
- { role: foo_app_instance, dir: '/opt/b', app_port: 5001 }
- { role: foo_app_instance, dir: '/opt/a', port: 5000 }
- { role: foo_app_instance, dir: '/opt/b', port: 5001 }
While it's probably not something you should do often, you can also conditionally apply roles like so::
@ -227,7 +227,7 @@ While it's probably not something you should do often, you can also conditionall
This works by applying the conditional to every task in the role. Conditionals are covered later on in
the documentation.
Finally, you may wish to assign tags to the roles you specify. You can do so inline::
Finally, you may wish to assign tags to the roles you specify. You can do so inline:::
---
@ -284,7 +284,7 @@ a list of roles and parameters to insert before the specified role, such as the
---
dependencies:
- { role: common, some_parameter: 3 }
- { role: apache, appache_port: 80 }
- { role: apache, port: 80 }
- { role: postgres, dbname: blarg, other_parameter: 12 }
Role dependencies can also be specified as a full path, just like top level roles::

View File

@ -11,14 +11,11 @@ and adopt these only if they seem relevant or useful to your environment.
playbooks_acceleration
playbooks_async
playbooks_checkmode
playbooks_debugger
playbooks_delegation
playbooks_environment
playbooks_error_handling
playbooks_advanced_syntax
playbooks_lookups
playbooks_prompts
playbooks_tags
playbooks_vault
playbooks_startnstep
playbooks_directives

Some files were not shown because too many files have changed in this diff Show More