Compare commits

..

175 Commits

Author SHA1 Message Date
f974ff6972 Merge pull request #11390 from j2sol/pin-to-stable
Pin modules to the matching stable-1.9 branch
2015-06-25 11:39:15 -07:00
3e5add9ea1 Pin modules to the matching stable-1.9 branch
This is to keep module changes on devel from breaking when ran on
stable-1.9 Ansible.
2015-06-25 11:24:06 -07:00
aeb194d4ff Vendorize match_hostname code so that ansible can push it out to clients along with the code that uses it. 2015-06-25 08:20:15 -07:00
705ab6c1e2 Version bump for 1.9.2-1 release 2015-06-24 13:35:44 -04:00
8fe06a3bbd Add changelog for the chroot/jail/zone fixes 2015-06-24 09:02:50 -07:00
30ff9270ac Use BUFSIZE when putting file as well as fetching file. 2015-06-24 08:54:06 -07:00
784fb8ff8e Fix exec_command to not use a shell 2015-06-24 08:54:00 -07:00
480ad7413a Fix fetch_file() method 2015-06-24 08:53:54 -07:00
8564dbaf95 Fix problem with chroot connection plugin and symlinks from within the chroot.
Manually apply changes from 952166f48e
because git won't cherry-pick successfully
2015-06-24 08:52:46 -07:00
0845151c9c Better error messages when the file to be transferred does not exist. 2015-06-24 08:51:55 -07:00
0056f025c3 Bumpt the BUFSIZE to 64k for better performance 2015-06-24 08:51:45 -07:00
f0302f2e2d Fix problem with jail and zone connection plugins and symlinks from within the jail/zone. 2015-06-24 08:51:38 -07:00
a431098fc5 Fix for symlink problem in jail and zone
Manually pull in changes from ca2f2c4ebd
as git won't cherry-pick those files successfully.
2015-06-24 08:49:19 -07:00
24fd4719cc Fix forwarding the user-given params from fetch_url() to open_url() 2015-06-23 15:21:14 -07:00
9bf06bfe84 Update the submodule refs for stable-1.9 2015-06-19 09:17:42 -07:00
65fc0161a8 Don't panic if AIX's uname doesn't support -W
The current code expects "uname -W" on AIX to always succeed. The AIX 5
instance I have doesn't support the -W flag and facts gathering always
crashes on it.

This skips some WPAR handling code if "uname -W" doesn't work.
2015-06-16 19:10:28 -04:00
e3e4f7af6b Test is a bit different in v1 as the lookup generates a failure in v2 but a warning in v1 2015-06-15 16:52:36 -07:00
968070729a Add test that url lookup checks tls certificates 2015-06-15 16:46:29 -07:00
2829d0f6ca Add etcd and url lookup plugin security fixes to changelog 2015-06-15 16:14:24 -07:00
73c7e98260 Backport security fixes to etcd and url lookup plugins 2015-06-15 16:13:05 -07:00
08c1ddd24e Split the fetch_url() function into fetch_url and open_url().
open_url() is suitable for use outside of a module environment.  Will
let us use open_url to do SSL cert verification in other, non-module
code.
2015-06-15 12:30:15 -07:00
4a5a8ed963 Add dnf to the list of module that we squash loop items for 2015-06-11 08:58:12 -07:00
0868679f13 Get-FileChecksum allways returns a string now,
and the test_win_copy integration tests that depend on the checksum
have been updated in this change too.
2015-06-10 20:48:15 -04:00
74afd24387 added test for notify in case it is defined as an empty keyword 2015-06-10 18:52:50 -04:00
b70caac618 updated submodule refs 2015-06-03 14:38:51 -04:00
7661f86c05 backported fix of missing import 2015-06-03 14:36:30 -04:00
54103d23fc updated banners as per marketing's request 2015-06-03 11:22:35 -04:00
7c428d1f51 added google addwords tag 2015-06-03 11:22:34 -04:00
8a4deba013 Merge pull request #11139 from wenottingham/galaxy-fix
Handle when role_dependencies is None.
2015-06-03 09:48:24 -04:00
2a003cba88 Handle when role_dependencies is None. 2015-06-02 22:31:53 -04:00
43385e2683 Add CVE number 2015-06-01 08:54:12 -07:00
35ca1dd073 Merge pull request #11110 from myniva/t/11109-fix-keyerror
Fix KeyError which occurs when not-existing entry is tried to be removed.
2015-06-01 11:34:20 -04:00
bc44e85f58 Merge pull request #11112 from jkleckner/apply-10563
Apply #10563 to stable-1.9
2015-06-01 09:33:03 -04:00
2945a462f6 Fix KeyError which occurs when not-existing entry is tried to be removed. Fixes #11109 2015-06-01 11:02:54 +02:00
873d01dfe2 egg_info is now written directly to lib 2015-05-30 08:39:31 -07:00
2c9337157b Update stable submodule refs 2015-05-29 18:58:41 -07:00
1f972c697f Add dnf fix to CHANGELOG 2015-05-29 13:49:11 -07:00
867a119425 Update core module ref to pull in yum fix 2015-05-29 13:47:54 -07:00
4716f3f268 Add yum module fixes 2015-05-29 13:47:12 -07:00
8a4a342996 Oops, accidentally updated the submodule refs to devel instead of the
stable-1.9 branch
2015-05-29 13:27:17 -07:00
870afac287 Add defaults and a link to os-client-config docs
Conflicts:
	lib/ansible/utils/module_docs_fragments/openstack.py
2015-05-29 13:22:13 -07:00
7a76d4e03b Remove unneeded required_one_of for openstack
We're being too strict - there is a third possibility, which is that a
user will have defined the OS_* environment variables and expect them to
pass through.

Conflicts:
	lib/ansible/module_utils/openstack.py
	lib/ansible/utils/module_docs_fragments/openstack.py
	v2/ansible/module_utils/openstack.py
2015-05-29 13:18:14 -07:00
8286253c81 Test on fields that exist 2015-05-28 17:02:01 -07:00
b5b5e7afba Add uri to modules that have been fixed to check server certificates 2015-05-28 15:40:01 -07:00
9caedb1f63 Add test that validate_certs=no works 2015-05-28 15:38:44 -07:00
b5e25a57af Changelog entry for get_url fixes 2015-05-28 13:38:20 -07:00
be7c59c7bb Make fetch_url check the server's certificate on https connections 2015-05-28 13:28:05 -07:00
c0265f80fb Allow the use of HTTP on custom ports in the fetch_url function 2015-05-28 13:27:59 -07:00
54fb04afc4 made sequence more flexible, can handle descending and negative sequences and is skipped if start==end 2015-05-22 12:48:29 -07:00
f18a128f12 Add entry for sequence fix 2015-05-22 12:27:00 -07:00
2816b8679b fixed corner case when counting backwards, added test cases for count=0 and backwards counts 2015-05-22 12:14:17 -07:00
196d9e2893 Version update for release candidate 1.9.2-0.2.rc2 2015-05-22 14:01:16 -05:00
8fab8aedc0 Submodule update for stable-1.9 2015-05-22 13:30:45 -05:00
982bad7886 Version bump for release candidate 1.9.2-0.1.rc1 2015-05-15 21:02:17 -05:00
127a669a23 made special treatment of certain filesystem for selinux configurable 2015-05-15 18:12:06 -04:00
3a7cb413d1 Merge pull request #10985 from jmhodges/correct_unbound_error
correct unbound error in ec2.py's RDS code path
2015-05-11 23:01:55 -04:00
c2c56eefa8 correct unbound error variable in rds code path
Fixes #10910
2015-05-11 15:54:32 -07:00
4eff3d5dc1 now properly inherit data from ansible.cfg for sudo/su ask pass
fixes #10891
2015-05-04 16:57:46 -04:00
e79535d42f Update core module ref to pull in docker module fixes for 1.9 2015-05-01 08:00:54 -07:00
b47d1d7e69 Version bump for release 1.9.1-1 2015-04-27 16:16:27 -05:00
99af3a8dc1 version update for release candidate 1.9.1-0.4.rc4 2015-04-23 10:31:57 -05:00
286d9be512 avoid path issues by determining the path of ansible-pull and using its path to run ansible and ansible-playbook 2015-04-23 10:37:17 -04:00
3a5a6685a0 Consistently use "OracleLinux" in OS detection.
Previously, a mixture of "OracleLinux" and "Oracle Linux" was used,
causing the `ansible_os_family` fact not to be set to `RedHat`.

Fixes #10742.
2015-04-20 18:54:37 -04:00
09a6c0c906 Fix traceback with using GCE on EL6 with python-crypto2.6
This fix resolves an issue on EL6 systems where there may be multiple versions
of pycrypto installed.  EPEL provides both `python-crypto` and
`python-crypto2.6`.  These packages are co-installable.  However, modules
importing the `Crypto` library must specify which version to use, otherwise the
default will be used.

This change follows the same pattern established in `bin/ansible` for
specifying python library requirements.
2015-04-20 15:51:07 -04:00
9a07855151 Version bump for release candidate 1.9.1-0.3.rc3 2015-04-17 14:47:21 -05:00
763f44a52b Fix tag handling on meta:flush_handlers tasks
Fixes #10758
2015-04-17 13:01:39 -05:00
8f4c97fdbe adjusted for the posibolity of lsblk not existing for fact gathering 2015-04-17 11:16:09 -04:00
a7a218349a Add -ExecutionPolicy Unrestricted back, was removed by #9602. 2015-04-16 08:47:45 -04:00
1cbc45700e Only try kerberos auth when username contains @ and pass realm to pywinrm. Alternative to #10644, fixes #10577. 2015-04-16 08:47:45 -04:00
baa6426c57 Remove winrm connection cache (only useful when running against one host). Also fixes #10391. 2015-04-16 08:47:45 -04:00
e16e2b171c Version bump for 1.9.1-0.2.rc2 release candidate 2015-04-15 10:31:12 -05:00
ea9db2a0cc bad hack to maybe fix some corner cases with pbrun custom prompts 2015-04-15 11:18:02 -04:00
2e5bad3385 fixed indent when looking at delegate_to vars 2015-04-14 19:00:15 -04:00
b1b78a4fd6 fixed another typo 2015-04-13 10:58:36 -04:00
f8b5e0814c typo fix 2015-04-13 10:49:31 -04:00
e609670fee fix for when calling bootinfo throws permmission errors (AIX)
fixes https://github.com/ansible/ansible-modules-core/issues/1108
2015-04-13 10:26:08 -04:00
d13646dcc5 Fix --force-handlers, and allow it in plays and ansible.cfg
The --force-handlers command line argument was not correctly running
handlers on hosts which had tasks that later failed. This corrects that,
and also allows you to specify force_handlers in ansible.cfg or in a
play.
2015-04-13 10:20:11 -04:00
efa93d4239 Reverse the error messages from jsonfile get and set 2015-04-09 10:41:29 -07:00
9bd2e3b752 Use codecs module while reading & writing json cache file 2015-04-09 10:41:23 -07:00
7923a1a2c5 Improve generation of debian changelog 2015-04-09 09:49:06 -04:00
8d703c459e Merge pull request #10639 from detiber/module_utils_facts_1_9
Fix indentation
2015-04-08 03:19:36 -04:00
626b2fc7ef Fix indentation 2015-04-07 23:00:54 -04:00
b186f7b85e Version bump for 1.9.1-0.1.rc1 2015-04-06 13:38:33 -05:00
b855456844 updated submodule refs 2015-04-02 16:00:22 -04:00
277658835a capture IOErrors on backup_local (happens on non posix filesystems)
fixes #10591
2015-04-02 15:58:21 -04:00
97a4483c7c removed folding sudo/su to become logic from constants as it is already present downstream in playbook/play/tasks 2015-04-02 15:57:26 -04:00
b965d12f1e now ansible ignores tempate errors on passwords
they could be caused by random character combinations, fixes #10468
2015-04-02 15:53:58 -04:00
84b8a80aa7 converted error on play var initialization into warning with more information 2015-04-02 15:53:16 -04:00
1d4b96479f dont break everything when one of the vars in inject does not template correctly, wait till its used 2015-04-02 15:53:16 -04:00
81e4a74c89 added note that custom connection plugins need update with this version 2015-03-31 11:14:02 -04:00
6ab57081ec readded sudo/su vars to allow role/includes to work with passed sudo/su 2015-03-29 10:17:41 -04:00
b4662c3eda Merge pull request #10556 from kristous/patch-1
Update README.md
2015-03-27 08:22:05 -04:00
d5dded43da Update README.md
I think since ansible and the ansible-modules have been splitted --recursive should be added
2015-03-27 06:20:13 +01:00
c0afe27e2f updated sumbmodule refs 2015-03-26 18:02:59 -04:00
290c74d4f4 fix consul inventory issue (missing method param) 2015-03-26 18:02:06 -04:00
a00056723f Make run_command() work when we get byte str with non-ascii characters (instead of unicode type like we were expecting)
Fix and test.

Fixes #10536
2015-03-26 07:52:05 -07:00
d6afb5d80e Fix assert to work with unicode values 2015-03-26 07:52:05 -07:00
29809bb83d Version bump for 1.9.0.1-1 2015-03-25 18:44:56 -05:00
717ffe2bea Version bump for 1.9.0-2 2015-03-25 17:07:21 -05:00
a0c7381a37 updated ref to extras 2015-03-25 18:05:09 -04:00
d76f8deed5 Submodule updates for 1.9 2015-03-25 14:57:16 -05:00
b268970564 Updating submodule pointers for 1.9 2015-03-25 14:46:54 -05:00
03c6492726 cleaning up CHANGELOG with incorrect entries 2015-03-25 14:43:02 -05:00
4ca9fc7e6f Version bump for 1.9.0 final release 2015-03-25 14:37:22 -05:00
3798a6623a tweaking the CHANGELOG 2015-03-25 14:18:15 -05:00
dc8b7bc8d2 And all of core module changes added 2015-03-25 14:18:10 -05:00
0a334a160d updated to latest ref 2015-03-24 15:16:09 -04:00
cf3313be0c makes raw module have quiet ssh so as to avoid extra output when not requried 2015-03-24 15:00:51 -04:00
5d28d46b16 VERSION bump and submodule update for 1.9.0-0.2.rc2 2015-03-20 14:52:50 -05:00
30af3166af Update core modules for asg tag fix 2015-03-20 11:39:12 -07:00
22b10a8f6e Patch for bug #10485 - ansible_distribution fact populates as 'RedHat' on Oracle Linux systems 2015-03-20 14:07:24 -04:00
bb58cbcd91 now use combine vars to preserve existing cached host vars 2015-03-20 11:34:53 -04:00
608496dbd3 removed debug play from tests 2015-03-20 11:24:35 -04:00
e3e97f6e06 now correctly aplies add_host passed variables last to override existing vars. 2015-03-20 11:23:50 -04:00
6dca95b309 now add_host loads hostvars 2015-03-20 10:34:51 -04:00
fd47c4d687 Pull ec2_asg fixes by updating core modules 2015-03-19 22:47:14 -07:00
0551f36d6b Have selinux allow docker<=>nginx communication 2015-03-19 13:53:35 -07:00
cfda56908a Okay, let's see if these pauses are enough to get this passing 2015-03-19 13:53:26 -07:00
4009c053f7 Fix the removal of busybox image 2015-03-19 13:53:10 -07:00
c571a0e6ea Some debugging for why docker tests are failing in jenkins 2015-03-19 13:53:02 -07:00
9082905a62 Add more tests for private docker registries 2015-03-19 13:52:54 -07:00
f4878a2bec Remove debug statements 2015-03-19 13:52:41 -07:00
67a559ed2b Add tests using a docker private registry 2015-03-19 13:52:33 -07:00
cfc90dff4b And ran into a different problem with centos6. Sigh. 2015-03-19 13:52:19 -07:00
e02fbcdb0f Attempt to enable docker tests for rhel/centos6 as well 2015-03-19 13:52:09 -07:00
2fbfe5cdb2 Would help if I added these files in the right directory 2015-03-19 13:52:01 -07:00
dc6a1f42af Ugh, looks like very few distros have the proper packages to run the docker module.
break up the tests so that we can maybe  run this on at least one
platform
2015-03-19 13:51:43 -07:00
af90817622 Initial test of the docker module 2015-03-19 13:51:29 -07:00
6a803f6582 Pull another fix in from core modules 2015-03-19 12:49:42 -07:00
2459eb6dbc updated module ref for core 2015-03-19 15:20:28 -04:00
b34b50d8d1 updated core to latests stable 1.9 2015-03-19 14:47:47 -04:00
da62887233 ignore PE methods that are not sudo for checksums until we get them working universally 2015-03-19 14:46:40 -04:00
824fc036e7 removed bare variable detection as this confuses people and forced us to allow for bare expressions 2015-03-19 09:28:04 -04:00
7d2915442e Update the extras module pointer 2015-03-18 20:25:06 -07:00
ebc8193c48 Update core module pointer 2015-03-18 19:55:55 -07:00
dbe0c4f771 Update docker module 2015-03-18 18:29:18 -07:00
a4f2407328 added missing become method inventory override 2015-03-17 19:20:21 -04:00
e819263820 Update core modules pointer 2015-03-17 11:02:53 -07:00
2a229bdb6c fixed issue with su in plays 2015-03-16 19:39:16 -04:00
7fba952a9e slight changes to allow for checksum and other commands to work correctly with quoting 2015-03-16 19:10:10 -04:00
103dc01817 log errors and explicitly exit rather than raising exceptions 2015-03-16 15:12:40 -07:00
5488bc395e fix for issue #10422. outputs informative error message when AWS credentials are not available 2015-03-16 15:12:32 -07:00
0898920eb0 Enable assert_raises_regexp on py26 2015-03-16 12:43:05 -07:00
fd4f541ded Add tox and travis-ci support
Add tox integration to run unittests in supported python releases.
Travis-CI is used for test execution.

Additionally, the unittest TestQuotePgIdentifier was updated to support
using assert_raises_regexp on python-2.6.

Sample travis-ci output available at
https://travis-ci.org/ansible/ansible/builds/54189977
2015-03-16 12:16:02 -07:00
dc434dd74e Update core pointer to make use of DOCKER_TLS_VERIFY env var:
https://github.com/ansible/ansible-modules-core/issues/946
2015-03-16 11:45:27 -07:00
29407752c5 Update core modules pointer 2015-03-16 11:35:51 -07:00
2823c8c987 fixed raw return check for privilege escalation 2015-03-16 14:00:50 -04:00
28892cca14 Update core module pointer 2015-03-13 13:54:08 -07:00
41c892baf4 Fix detect of docker as virtualization_type.
Not only match`/docker/`, but also `docker-` followed by a hex-id.

Example (shortened):
```
$ cat /proc/1/cgroup
8:blkio:/system.slice/docker-de73f4d207861cf8757b69213ee67bb234b897a18bea7385964b6ed2d515da94.scope
7:net_cls:/
```
2015-03-13 11:43:25 -07:00
7ba49ed430 added test requirements for pip 2015-03-12 14:00:39 -07:00
1cf533f8df Comma is also dependent on position within the hash 2015-03-12 13:21:46 -07:00
7768ab2b5c fixed and reintroduced syncronize test, fakerunner object needed become_method to be it's default 'sudo' 2015-03-12 14:48:21 -04:00
6aaf77ac76 Hash randomization makes one of the heuristic_log_sanitize checks not work.
Nothing we can do, when it sanitizes ssh_urls it's simply overzealous.
2015-03-12 11:40:19 -07:00
8d847efa37 Fix issue with unarchive disabling pipelining mode
Was using persist_files=True when specifying the create paramater,
which breaks pipelining. Switched to use delete_remote_tmp=False instead,
which is the proper way to preserve the remove tmp dir when running
other modules from the action plugin.
2015-03-12 10:24:38 -05:00
0e2a21f1fa Update core pointer to pick up docker fix 2015-03-12 08:21:39 -07:00
5f7cc8f0c1 changed from hash_merge to combine vars which resets default to
overwrite and not merge hashing
corrected merge vs combined in all pertinent sections
fixed typoe in combined_Vars
removed redundant inventory call, moved grousp to proper priority
readded inventory vars to runner's vars
correclty added inventory this time
2015-03-12 11:03:35 -04:00
4db4fcd5a6 fixed missed conversion of su to become 2015-03-12 10:02:03 -04:00
4941755851 Test case for #10426 2015-03-11 20:59:02 -07:00
1c09660c44 set 'nonstring' arg to passthru. 2015-03-11 20:42:40 -07:00
a388cd69c0 use to_unicode() in _jinja2_vars if type is str. 2015-03-11 20:42:31 -07:00
c33d2fa283 Generic package_dir mapping in setup.py (closes #10437) 2015-03-11 19:17:02 -07:00
8f05824dda Update for another 3c2 fix 2015-03-11 19:09:07 -07:00
7ea7279080 Update core modules to pull in fixes 2015-03-11 18:43:02 -07:00
c997228896 fixed missed su to become conversion 2015-03-11 19:24:03 -04:00
839d2a2a79 fixes password error detection for ssh connection plugin
removes sycnronize test that does not work with current sudo setup
Fixes #10434
2015-03-11 19:09:34 -04:00
4459686099 fix tag test that broke with new tag info displayed in list tasks 2015-03-11 16:29:31 -04:00
435371d3fc Fix deb packaging version in the changelog 2015-03-11 14:50:45 -05:00
a2ff6cd5d0 removed uneeded reference to su_user 2015-03-11 11:58:49 -05:00
44d9c02ba5 fixed traceback when x_user implicitly sets the become method
Fixes #10430

Also removed redundant resolution of sudo/su for backwards compatibility which
confused the conflict detection code.
2015-03-11 11:58:32 -05:00
4478ed60b4 Typo: lead --> led 2015-03-11 11:53:36 -05:00
63469fceaa fix issue with ask pass signature 2015-03-11 10:29:18 -04:00
f0bdf0145a fixed bad paren in connection plugin 2015-03-11 09:31:24 -04:00
bce4bb2ce2 preliminary privlege escalation unification + pbrun
- become constants inherit existing sudo/su ones
- become command line options, marked sudo/su as deprecated and moved sudo/su passwords to runas group
- changed method signatures as privlege escalation is collapsed to become
- added tests for su and become, diabled su for lack of support in local.py
- updated playbook,play and task objects to become
- added become to runner
- added whoami test for become/sudo/su
- added home override dir for plugins
- removed useless method from ask pass
- forced become pass to always be string also uses to_bytes
- fixed fakerunner for tests
- corrected reference in synchronize action plugin
- added pfexec (needs testing)
- removed unused sudo/su in runner init
- removed deprecated info
- updated pe tests to allow to run under sudo and not need root
- normalized become options into a funciton to avoid duplication and inconsistencies
- pushed suppored list to connection classs property
- updated all connection plugins to latest 'become' pe

- includes fixes from feedback (including typos)
- added draft docs
- stub of become_exe, leaving for future v2 fixes
2015-03-10 17:42:52 -05:00
f4329c8977 Submodule update for stable-1.9 branch 2015-03-10 17:27:58 -05:00
6d5a5883fe Setting up new release candidate versioning 2015-03-10 17:16:33 -05:00
6177 changed files with 120004 additions and 459499 deletions

View File

@ -1,256 +0,0 @@
trigger:
batch: true
branches:
include:
- devel
- stable-*
pr:
autoCancel: true
branches:
include:
- devel
- stable-*
schedules:
- cron: 0 7 * * *
displayName: Nightly
always: true
branches:
include:
- devel
- stable-*
variables:
- name: checkoutPath
value: ansible
- name: coverageBranches
value: devel
- name: pipelinesCoverage
value: coverage
- name: entryPoint
value: test/utils/shippable/shippable.sh
- name: fetchDepth
value: 500
resources:
containers:
- container: default
image: quay.io/ansible/azure-pipelines-test-container:1.8.0
pool: Standard
stages:
- stage: Sanity
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
- test: 5
- stage: Units
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: units/{0}
targets:
- test: 2.6
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9
- stage: Windows
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Server {0}
testFormat: windows/{0}/1
targets:
- test: 2012
- test: 2012-R2
- test: 2016
- test: 2019
- stage: Remote
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
targets:
- name: macOS 11.1
test: macos/11.1
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.2
test: rhel/8.2
- name: FreeBSD 11.1
test: freebsd/11.1
- name: FreeBSD 12.1
test: freebsd/12.1
groups:
- 1
- 2
- 3
- 4
- 5
- stage: Docker
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: linux/{0}
targets:
- name: CentOS 6
test: centos6
- name: CentOS 7
test: centos7
- name: CentOS 8
test: centos8
- name: Fedora 31
test: fedora31
- name: Fedora 32
test: fedora32
- name: openSUSE 15 py2
test: opensuse15py2
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 16.04
test: ubuntu1604
- name: Ubuntu 18.04
test: ubuntu1804
- name: Ubuntu 20.04
test: ubuntu2004
groups:
- 1
- 2
- 3
- 4
- 5
- stage: Fallaxy
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: fallaxy/{0}/1
targets:
- test: 2.7
- test: 3.6
- stage: Generic
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: generic/{0}/1
targets:
- test: 2.7
- test: 3.6
- stage: Incidental_Remote
displayName: Incidental Remote
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: i/{0}
targets:
- name: OS X 10.11
test: osx/10.11
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.2
test: rhel/8.2
- name: FreeBSD 11.1
test: freebsd/11.1
- name: FreeBSD 12.1
test: freebsd/12.1
- stage: Incidental_Docker
displayName: Incidental Docker
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: i/linux/{0}
targets:
- name: CentOS 6
test: centos6
- name: CentOS 7
test: centos7
- name: CentOS 8
test: centos8
- name: Fedora 31
test: fedora31
- name: Fedora 32
test: fedora32
- name: openSUSE 15 py2
test: opensuse15py2
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 16.04
test: ubuntu1604
- name: Ubuntu 18.04
test: ubuntu1804
- name: Ubuntu 20.04
test: ubuntu2004
- stage: Incidental_Windows
displayName: Incidental Windows
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Server {0}
testFormat: i/windows/{0}
targets:
- test: 2012
- test: 2012-R2
- test: 2016
- test: 2019
- stage: Incidental
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: i/{0}/1
targets:
- name: IOS Python
test: ios/csr1000v/
- name: VyOS Python 2.7
test: vyos/1.1.8/2.7
- name: VyOS Python 3.6
test: vyos/1.1.8/3.6
- name: AWS Python 2.7
test: aws/2.7
- name: AWS Python 3.6
test: aws/3.6
- name: Azure Python 2.7
test: azure/2.7
- name: Azure Python 3.6
test: azure/3.6
- name: Cloud Python
test: cloud/
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- Sanity
- Units
- Windows
- Remote
- Docker
- Fallaxy
- Generic
- Incidental_Remote
- Incidental_Docker
- Incidental_Windows
- Incidental
jobs:
- template: templates/coverage.yml

View File

@ -1,20 +0,0 @@
#!/usr/bin/env bash
# Aggregate code coverage results for later processing.
set -o pipefail -eu
agent_temp_directory="$1"
PATH="${PWD}/bin:${PATH}"
mkdir "${agent_temp_directory}/coverage/"
options=(--venv --venv-system-site-packages --color -v)
ansible-test coverage combine --export "${agent_temp_directory}/coverage/" "${options[@]}"
if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then
# Only analyze coverage if the installed version of ansible-test supports it.
# Doing so allows this script to work unmodified for multiple Ansible versions.
ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}"
fi

View File

@ -1,60 +0,0 @@
#!/usr/bin/env python
"""
Combine coverage data from multiple jobs, keeping the data only from the most recent attempt from each job.
Coverage artifacts must be named using the format: "Coverage $(System.JobAttempt) {StableUniqueNameForEachJob}"
The recommended coverage artifact name format is: Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)
Keep in mind that Azure Pipelines does not enforce unique job display names (only names).
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
"""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import re
import shutil
import sys
def main():
"""Main program entry point."""
source_directory = sys.argv[1]
if '/ansible_collections/' in os.getcwd():
output_path = "tests/output"
else:
output_path = "test/results"
destination_directory = os.path.join(output_path, 'coverage')
if not os.path.exists(destination_directory):
os.makedirs(destination_directory)
jobs = {}
count = 0
for name in os.listdir(source_directory):
match = re.search('^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$', name)
label = match.group('label')
attempt = int(match.group('attempt'))
jobs[label] = max(attempt, jobs.get(label, 0))
for label, attempt in jobs.items():
name = 'Coverage {attempt} {label}'.format(label=label, attempt=attempt)
source = os.path.join(source_directory, name)
source_files = os.listdir(source)
for source_file in source_files:
source_path = os.path.join(source, source_file)
destination_path = os.path.join(destination_directory, source_file + '.' + label)
print('"%s" -> "%s"' % (source_path, destination_path))
shutil.copyfile(source_path, destination_path)
count += 1
print('Coverage file count: %d' % count)
print('##vso[task.setVariable variable=coverageFileCount]%d' % count)
print('##vso[task.setVariable variable=outputPath]%s' % output_path)
if __name__ == '__main__':
main()

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
# Check the test results and set variables for use in later steps.
set -o pipefail -eu
if [[ "$PWD" =~ /ansible_collections/ ]]; then
output_path="tests/output"
else
output_path="test/results"
fi
echo "##vso[task.setVariable variable=outputPath]${output_path}"
if compgen -G "${output_path}"'/junit/*.xml' > /dev/null; then
echo "##vso[task.setVariable variable=haveTestResults]true"
fi
if compgen -G "${output_path}"'/bot/ansible-test-*' > /dev/null; then
echo "##vso[task.setVariable variable=haveBotResults]true"
fi
if compgen -G "${output_path}"'/coverage/*' > /dev/null; then
echo "##vso[task.setVariable variable=haveCoverageData]true"
fi

View File

@ -1,27 +0,0 @@
#!/usr/bin/env bash
# Upload code coverage reports to codecov.io.
# Multiple coverage files from multiple languages are accepted and aggregated after upload.
# Python coverage, as well as PowerShell and Python stubs can all be uploaded.
set -o pipefail -eu
output_path="$1"
curl --silent --show-error https://codecov.io/bash > codecov.sh
for file in "${output_path}"/reports/coverage*.xml; do
name="${file}"
name="${name##*/}" # remove path
name="${name##coverage=}" # remove 'coverage=' prefix if present
name="${name%.xml}" # remove '.xml' suffix
bash codecov.sh \
-f "${file}" \
-n "${name}" \
-X coveragepy \
-X gcov \
-X fix \
-X search \
-X xcode \
|| echo "Failed to upload code coverage report to codecov.io: ${file}"
done

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
# Generate code coverage reports for uploading to Azure Pipelines and codecov.io.
set -o pipefail -eu
PATH="${PWD}/bin:${PATH}"
if ! ansible-test --help >/dev/null 2>&1; then
# Install the devel version of ansible-test for generating code coverage reports.
# This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
# Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used.
pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
fi
ansible-test coverage xml --stub --venv --venv-system-site-packages --color -v

View File

@ -1,34 +0,0 @@
#!/usr/bin/env bash
# Configure the test environment and run the tests.
set -o pipefail -eu
entry_point="$1"
test="$2"
read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds
export COMMIT_MESSAGE
export COMPLETE
export COVERAGE
export IS_PULL_REQUEST
if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then
IS_PULL_REQUEST=true
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2)
else
IS_PULL_REQUEST=
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD)
fi
COMPLETE=
COVERAGE=
if [ "${BUILD_REASON}" = "Schedule" ]; then
COMPLETE=yes
if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then
COVERAGE=yes
fi
fi
"${entry_point}" "${test}" 2>&1 | "$(dirname "$0")/time-command.py"

View File

@ -1,25 +0,0 @@
#!/usr/bin/env python
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import sys
import time
def main():
"""Main program entry point."""
start = time.time()
sys.stdin.reconfigure(errors='surrogateescape')
sys.stdout.reconfigure(errors='surrogateescape')
for line in sys.stdin:
seconds = time.time() - start
sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
sys.stdout.flush()
if __name__ == '__main__':
main()

View File

@ -1,39 +0,0 @@
# This template adds a job for processing code coverage data.
# It will upload results to Azure Pipelines and codecov.io.
# Use it from a job stage that completes after all other jobs have completed.
# This can be done by placing it in a separate summary stage that runs after the test stage(s) have completed.
jobs:
- job: Coverage
displayName: Code Coverage
container: default
workspace:
clean: all
steps:
- checkout: self
fetchDepth: $(fetchDepth)
path: $(checkoutPath)
- task: DownloadPipelineArtifact@2
displayName: Download Coverage Data
inputs:
path: coverage/
patterns: "Coverage */*=coverage.combined"
- bash: .azure-pipelines/scripts/combine-coverage.py coverage/
displayName: Combine Coverage Data
- bash: .azure-pipelines/scripts/report-coverage.sh
displayName: Generate Coverage Report
condition: gt(variables.coverageFileCount, 0)
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
# Azure Pipelines only accepts a single coverage data file.
# That means only Python or PowerShell coverage can be uploaded, but not both.
# Set the "pipelinesCoverage" variable to determine which type is uploaded.
# Use "coverage" for Python and "coverage-powershell" for PowerShell.
summaryFileLocation: "$(outputPath)/reports/$(pipelinesCoverage).xml"
displayName: Publish to Azure Pipelines
condition: gt(variables.coverageFileCount, 0)
- bash: .azure-pipelines/scripts/publish-codecov.sh "$(outputPath)"
displayName: Publish to codecov.io
condition: gt(variables.coverageFileCount, 0)
continueOnError: true

View File

@ -1,55 +0,0 @@
# This template uses the provided targets and optional groups to generate a matrix which is then passed to the test template.
# If this matrix template does not provide the required functionality, consider using the test template directly instead.
parameters:
# A required list of dictionaries, one per test target.
# Each item in the list must contain a "test" or "name" key.
# Both may be provided. If one is omitted, the other will be used.
- name: targets
type: object
# An optional list of values which will be used to multiply the targets list into a matrix.
# Values can be strings or numbers.
- name: groups
type: object
default: []
# An optional format string used to generate the job name.
# - {0} is the name of an item in the targets list.
- name: nameFormat
type: string
default: "{0}"
# An optional format string used to generate the test name.
# - {0} is the name of an item in the targets list.
- name: testFormat
type: string
default: "{0}"
# An optional format string used to add the group to the job name.
# {0} is the formatted name of an item in the targets list.
# {{1}} is the group -- be sure to include the double "{{" and "}}".
- name: nameGroupFormat
type: string
default: "{0} - {{1}}"
# An optional format string used to add the group to the test name.
# {0} is the formatted test of an item in the targets list.
# {{1}} is the group -- be sure to include the double "{{" and "}}".
- name: testGroupFormat
type: string
default: "{0}/{{1}}"
jobs:
- template: test.yml
parameters:
jobs:
- ${{ if eq(length(parameters.groups), 0) }}:
- ${{ each target in parameters.targets }}:
- name: ${{ format(parameters.nameFormat, coalesce(target.name, target.test)) }}
test: ${{ format(parameters.testFormat, coalesce(target.test, target.name)) }}
- ${{ if not(eq(length(parameters.groups), 0)) }}:
- ${{ each group in parameters.groups }}:
- ${{ each target in parameters.targets }}:
- name: ${{ format(format(parameters.nameGroupFormat, parameters.nameFormat), coalesce(target.name, target.test), group) }}
test: ${{ format(format(parameters.testGroupFormat, parameters.testFormat), coalesce(target.test, target.name), group) }}

View File

@ -1,45 +0,0 @@
# This template uses the provided list of jobs to create test one or more test jobs.
# It can be used directly if needed, or through the matrix template.
parameters:
# A required list of dictionaries, one per test job.
# Each item in the list must contain a "job" and "name" key.
- name: jobs
type: object
jobs:
- ${{ each job in parameters.jobs }}:
- job: test_${{ replace(replace(replace(job.test, '/', '_'), '.', '_'), '-', '_') }}
displayName: ${{ job.name }}
container: default
workspace:
clean: all
steps:
- checkout: self
fetchDepth: $(fetchDepth)
path: $(checkoutPath)
- bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)"
displayName: Run Tests
- bash: .azure-pipelines/scripts/process-results.sh
condition: succeededOrFailed()
displayName: Process Results
- bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
condition: eq(variables.haveCoverageData, 'true')
displayName: Aggregate Coverage Data
- task: PublishTestResults@2
condition: eq(variables.haveTestResults, 'true')
inputs:
testResultsFiles: "$(outputPath)/junit/*.xml"
displayName: Publish Test Results
- task: PublishPipelineArtifact@1
condition: eq(variables.haveBotResults, 'true')
displayName: Publish Bot Results
inputs:
targetPath: "$(outputPath)/bot/"
artifactName: "Bot $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
- task: PublishPipelineArtifact@1
condition: eq(variables.haveCoverageData, 'true')
displayName: Publish Coverage Data
inputs:
targetPath: "$(Agent.TempDirectory)/coverage/"
artifactName: "Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"

View File

@ -1,5 +0,0 @@
team = "ansible"
repo = "ansible"
check_sha = "f31421576b00f0b167cdbe61217c31c21a41ac02" # the very first commit in repo
fix_commit_msg = false # Don't replace "#" with "GH-"
default_branch = "devel"

4
.coveragerc Normal file
View File

@ -0,0 +1,4 @@
[report]
omit =
*/python?.?/*
*/site-packages/nose/*

3
.gitattributes vendored
View File

@ -1,2 +1 @@
.github/ export-ignore
hacking/ export-ignore
CHANGELOG.md merge=union

30229
.github/BOTMETA.yml vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
# Community Code of Conduct
Please see the official [Ansible Community Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).

View File

@ -1,25 +0,0 @@
# WELCOME TO ANSIBLE GITHUB
Hi! Nice to see you here!
## QUESTIONS ?
Please see the [Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for information on how to ask questions on the [mailing lists](https://docs.ansible.com/ansible/latest/community/communication.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, as the community page explains best.
## CONTRIBUTING ?
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. You can also read the same [CLA](https://docs.ansible.com/ansible/latest/community/contributor_license_agreement.html) on the Ansible docsite.
Please review the [Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for more information on contributing to Ansible.
## BUG TO REPORT ?
First and foremost, also check the [Community Guide](https://docs.ansible.com/ansible/latest/community/index.html).
You can report bugs or make enhancement requests at the [Ansible GitHub issue page](http://github.com/ansible/ansible/issues/new/choose) 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; see the [Installation Guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) for details.
Thanks!

View File

@ -1 +0,0 @@
Please raise issues via the [new interface](https://github.com/ansible/ansible/issues/new/choose)

View File

@ -1,54 +0,0 @@
---
name: 🐛 Bug report
about: Create a report to help us improve
---
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->
##### SUMMARY
<!--- Explain the problem briefly below -->
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
```
##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below
```
##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->
<!--- Paste example playbooks or commands between quotes below -->
```yaml
```
<!--- HINT: You can paste gist.github.com links for larger files -->
##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->
##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->
<!--- Paste verbatim command output between quotes -->
```paste below
```

View File

@ -1,26 +0,0 @@
# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
blank_issues_enabled: true # default
contact_links:
- name: 🔐 Security bug report 🔥
url: https://docs.ansible.com/ansible/latest/community/reporting_bugs_and_features.html?utm_medium=github&utm_source=issue_template_chooser
about: |
Please learn how to report security vulnerabilities here.
For all security related bugs, email security@ansible.com
instead of using this issue tracker and you will receive
a prompt response.
For more information, see
https://docs.ansible.com/ansible/latest/community/reporting_bugs_and_features.html
- name: 📝 Ansible Code of Conduct
url: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html?utm_medium=github&utm_source=issue_template_chooser
about: ❤ Be nice to other members of the community. ☮ Behave.
- name: 💬 Talks to the community
url: https://docs.ansible.com/ansible/latest/community/communication.html?utm_medium=github&utm_source=issue_template_chooser#mailing-list-information
about: Please ask and answer usage questions here
- name: ⚡ Working groups
url: https://github.com/ansible/community/wiki
about: Interested in improving a specific area? Become a part of a working group!
- name: 💼 For Enterprise
url: https://www.ansible.com/products/engine?utm_medium=github&utm_source=issue_template_chooser
about: Red Hat offers support for the Ansible Automation Platform

View File

@ -1,38 +0,0 @@
---
name: 📝 Documentation Report
about: Ask us about docs
---
<!--- Verify first that your improvement is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->
##### SUMMARY
<!--- Explain the problem briefly below, add suggestions to wording or structure -->
<!--- HINT: Did you know the documentation has an "Edit on GitHub" link on every page ? -->
##### ISSUE TYPE
- Documentation Report
##### COMPONENT NAME
<!--- Write the short name of the rst file, module, plugin, task or feature below, use your best guess if unsure -->
##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
```
##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below
```
##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. OS version, browser, etc. -->
##### ADDITIONAL INFORMATION
<!--- Describe how this improves the documentation, e.g. before/after situation or screenshots -->
<!--- HINT: You can paste gist.github.com links for larger files -->

View File

@ -1,25 +0,0 @@
---
name: ✨ Feature request
about: Suggest an idea for this project
---
<!--- Verify first that your feature was not already discussed on GitHub -->
<!--- Complete *all* sections as described, this form is processed automatically -->
##### SUMMARY
<!--- Describe the new feature/improvement briefly below -->
##### ISSUE TYPE
- Feature Idea
##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->
##### ADDITIONAL INFORMATION
<!--- Describe how the feature would be used, why it is needed and what it would solve -->
<!--- Paste example playbooks or commands between quotes below -->
```yaml
```
<!--- HINT: You can also paste gist.github.com links for larger files -->

View File

@ -1,23 +0,0 @@
##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
- Bugfix Pull Request
- Docs Pull Request
- Feature Pull Request
- New Module Pull Request
##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below -->
##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->
<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below
```

View File

@ -1,12 +0,0 @@
---
- 2.10.0 When the Levee Breaks
- 2.9.0 Immigrant Song
- 2.8.0 How Many More Times
- 2.7.0 In the Light
- 2.6.0 Heartbreaker
- 2.5.0 Kashmir
- 2.4.0 Dancing Days
- 2.3.0 Ramble On
- 2.2.0 The Battle of Evermore
- 2.1.0 The Song Remains the Same
- 2.0.0 Over the Hills and Far Away

15
.github/SECURITY.md vendored
View File

@ -1,15 +0,0 @@
# Security Policy
## Supported Versions
Ansible applies security fixes according to the 3-versions-back support
policy. Please find more information in [our docs](
https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#release-status
).
## Reporting a Vulnerability
We encourage responsible disclosure practices for security
vulnerabilities. Please read our [policies for reporting bugs](
https://docs.ansible.com/ansible/devel/community/reporting_bugs_and_features.html#reporting-a-bug
) if you want to report a security issue that might affect Ansible.

85
.gitignore vendored
View File

@ -2,10 +2,9 @@
*.py[co]
build
AUTHORS.TXT
# Emacs backup and autosave files...
# Emacs backup files...
*~
.\#*
\#*
# RPM stuff...
MANIFEST
dist
@ -17,97 +16,39 @@ rpm-build
.idea
#IntelliJ IDEA stuff..
*.iml
#VSCode stuff..
.vscode/
# Mac OS X stuff...
.DS_Store
# manpage build stuff...
docs/man/man1/ansible*.1
docs/man/man1/ansible*.1.asciidoc.in
docs/man/man3/*
# Sublime stuff
*.sublime-project
*.sublime-workspace
# docsite stuff...
docs/docsite/_build
docs/docsite/*.html
docs/docsite/htmlout
docs/docsite/rst/conf.py
docs/docsite/rst/index.rst
docs/docsite/rst/cli/ansible-*.rst
docs/docsite/rst/cli/ansible.rst
docs/docsite/rst/dev_guide/collections_galaxy_meta.rst
docs/docsite/rst/dev_guide/testing/sanity/index.rst.new
docs/docsite/rst/modules/*.rst
docs/docsite/rst/collections/*.rst
!docs/docsite/rst/collections/all_plugins.rst
docs/docsite/rst/collections/*/*.rst
docs/docsite/rst/playbooks_directives.rst
docs/docsite/rst/plugins_by_category.rst
docs/docsite/rst/plugins/*/*.rst
docs/docsite/rst/reference_appendices/config.rst
docs/docsite/rst/reference_appendices/playbooks_keywords.rst
docs/docsite/rst_warnings
docs/docsite/searchindex.js
docs/docsite/_static/*.gif
docs/docsite/_static/*.png
docs/docsite/_static/websupport.js
docsite/rst/modules_by_category.rst
docsite/rst/list_of_*.rst
docsite/rst/*_module.rst
docsite/*.html
docsite/_static/*.gif
docsite/_static/*.png
docsite/_static/websupport.js
docsite/searchindex.js
docsite/htmlout
# deb building stuff...
/debian/
debian/
deb-build
# Vim swap files
*.swp
*.swo
credentials.yml
# test output
*.retry
*.out
.pytest_cache/
.coverage
.tox
.cache
.pytest_cache
results.xml
coverage.xml
/test/units/cover-html
/test/integration/inventory
/test/integration/targets/*/backup/
/test/cache/*
# Development
/test/develop
venv
Vagrantfile
.vagrant
# Backwards compatibility with `stable-2.9` and earlier branches.
# Also used in the `devel` branch during early Ansible 2.10 development.
/lib/ansible.egg-info/
# First used in the `devel` branch during Ansible 2.10 development.
/lib/ansible_base.egg-info/
/shippable/
/test/integration/cloud-config-*.*
!/test/integration/cloud-config-*.*.template
.python-version
/hacking/tests/selinux/*.mod
/hacking/tests/selinux/*.pp
# Release directory
packaging/release/ansible_release
/.cache/
/test/results/
/test/integration/cloud-config-aws.yml
/test/integration/inventory.networking
/test/integration/inventory.winrm
/test/integration/cloud-config-aws.yml
/test/integration/cloud-config-cs.ini
# python 'rope' stuff
.ropeproject
# local 'ack' config files
.ackrc
# default 'coverage html' results
htmlcov/
# default 'coverage' tool data
.coverage
# ansible-test coverage results
test/units/.coverage.*
/test/integration/cloud-config-azure.yml
/SYMLINK_CACHE.json
changelogs/.plugin-cache.yaml
.ansible-test-timeout.json
ansible.egg-info/

16
.gitmodules vendored Normal file
View File

@ -0,0 +1,16 @@
[submodule "lib/ansible/modules/core"]
path = lib/ansible/modules/core
url = https://github.com/ansible/ansible-modules-core.git
branch = stable-1.9
[submodule "lib/ansible/modules/extras"]
path = lib/ansible/modules/extras
url = https://github.com/ansible/ansible-modules-extras.git
branch = stable-1.9
[submodule "v2/ansible/modules/core"]
path = v2/ansible/modules/core
url = https://github.com/ansible/ansible-modules-core.git
branch = stable-1.9
[submodule "v2/ansible/modules/extras"]
path = v2/ansible/modules/extras
url = https://github.com/ansible/ansible-modules-extras.git
branch = stable-1.9

View File

@ -1,36 +0,0 @@
Michael DeHaan <michael.dehaan@gmail.com> <michael@ansibleworks.com>
Michael DeHaan <michael.dehaan@gmail.com> 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>
Will Thames <will@thames.id.au> Will Thames <will.thames@xvt.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>
Rene Moser <mail@renemoser.net> René Moser <mail@renemoser.net>
Rene Moser <mail@renemoser.net> Rene Moser <rene.moser@swisstxt.ch>

11
.travis.yml Normal file
View File

@ -0,0 +1,11 @@
sudo: false
language: python
env:
- TOXENV=py26
- TOXENV=py27
install:
- pip install tox
script:
- tox
after_success:
- coveralls

1653
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

319
CODING_GUIDELINES.md Normal file
View File

@ -0,0 +1,319 @@
Coding Guidelines
=================
Hi! Thanks for interest in contributing to Ansible.
Here are some guidelines for contributing code. The purpose of this document are to establish what we're looking for in code contributions, and to make sure
new contributions know some of the conventions that we've been using.
We don't think much of this should be too strange to readers familiar with contributing to Python projects, though it helps if we all get on the same page.
Language
========
* While not all components of Ansible must be in Python, core contributions to the Ansible repo must be written in Python. This is to maximize the ability of everyone to contribute.
* If you want to write non-Python ansible modules or inventory scripts, that's fine, but they are not going to get merged in most likely. Sorry!!
PEP8 and basic style checks
===========================
* PEP8 is a great Python style guide, which you should read.
* PEP8 must not be strictly followed in all aspects, but most of it is good advice
* In particular, we don't really care about line lengths. Buy a bigger monitor!
* To run checks for things we care about, run "make pep8"
* Similarly, additional checks can be made with "make pyflakes"
* There is no need to submit code changes for pep8 and pyflake fixes, as these break attribution history. Project leadership will make these periodically.
* Do not submit pull requests that simply adjust whitespace in the code
Testing
=======
* Much of ansible's testing needs are in integration, not unit tests. Add module tests there.
* That being said, there are unit tests too!
* Code written must absolutely pass tests (i.e. "make tests")
* You should anticipate any error paths in your code and test down those error paths.
* Additions to tests for core code is welcome, but not always possible. Be sure things are at least well tested manually in that case.
Whitespace
==========
* Four space indent is strictly required
* Include meaningful whitespace between lines of code
Shebang Lines
=============
* /usr/bin/scripts should start with '/usr/bin/env python'
* module code should still use '/usr/bin/python' as this is replaced automatically by 'ansible_python_interpreter', see the FAQ in the docs for more info.
Comments
========
* Readability is one of the most important goals for this project
* Comment any non-trivial code where someone might not know why you are doing something in a particular way
* Though if something should be commented, that's often a sign someone should write a function
* All new functions must have a basic docstring comment
* Commenting above a line is preferable to commenting at the end of a line
Classes
=======
* With the exception of module code (where inline is better), it is desirable to see classes in their own files.
* Classes should generally not cause side effects as soon as they are instantiated, move meaningful behavior to methods rather than constructors.
Functions and Methods
=====================
* In general, functions should not be 'too long' and should describe a meaningful amount of work
* When code gets too nested, that's usually the sign the loop body could benefit from being a function
* Parts of our existing code are not the best examples of this at times.
* Functions should have names that describe what they do, along with docstrings
* Functions should be named with_underscores
* "Don't repeat yourself" is generally a good philosophy
Variables
=========
* Use descriptive variable names instead of variables like 'x', unless x is a obvious loop index
* Ansible python code uses identifiers like 'ClassesLikeThis and variables_like_this
* Module parameters should also use_underscores and not runtogether
Module Security
===============
* Modules must take steps to avoid passing user input from the shell and always check return codes
* always use module.run_command instead of subprocess or Popen or os.system -- this is mandatory
* if you use need the shell you must pass use_unsafe_shell=True to module.run_command
* if you do not need the shell, avoid using the shell
* any variables that can come from the user input with use_unsafe_shell=True must be wrapped by pipes.quote(x)
* downloads of https:// resource urls must import module_utils.urls and use the fetch_url method
Misc Preferences
================
Use the dict constructor where possible when allocating dictionaries:
# not this:
foo = {
'a' : 12,
'b' : 34
}
# this:
foo = dict(
a = 12,
b = 34
)
Line up variables
# not this
a = 12
foosball = 34
xyz = 'dog'
# this
a = 12
foosball = 34
xyz = 'dog'
Don't use line continuations:
# no
if (this_is_a_very_long_line and foo and \
i_am_going_to_continue_it):
bar()
# better:
if (this_is_a_very_long_line and foo and i_am_going_to_continue_it):
bar()
Spacing:
# no
x=[1,2,3]
# no
x = [1,2,3]
# yes
x = [ 1, 2, 3 ]
Spacing continued:
# no
x=foo(12)
# no
x = foo( 12 )
# yes
x = foo(12)
Licenses
========
Every file should have a license header, including the copyright of the original author. Major additions to the module are allowed
to add an additional copyright line, and this is especially true of rewrites, but original authorship copyright messages should be preserved.
All contributions to the core repo should preserve original licenses and new contributions must include the GPLv3 header.
Module Documentation
====================
All module pull requests must include a DOCUMENTATION docstring (YAML format,
see other modules for examples) as well as an EXAMPLES docstring, which is free form.
When adding new modules, any new parameter must have a "version_added" attribute.
When submitting a new module, the module should have a "version_added" attribute in the
pull request as well, set to the current development version.
Be sure to check grammar and spelling.
It's frequently the case that modules get submitted with YAML that isn't valid,
so you can run "make webdocs" from the checkout to preview your module's documentation.
If it fails to build, take a look at your DOCUMENTATION string
or you might have a Python syntax error in there too.
Python Imports
==============
To make it clear what a module is importing, imports should not be sprinkled throughout the code.
Python Imports should happen at the top of the file, exempting code from module_utils.
When a conditional runtime import is required, do so something like this instead:
HAS_FOO = False
try:
import foo
HAS_FOO = True
except ImportError:
pass
...
if not HAS_FOO:
raise Exception("the foo library is required")
This makes it clear what optional dependencies are but allows this to be deferred until runtime. In the case of module code, the raising of the Exception will be replaced
with a "module.exit_json" call.
Exceptions
==========
In the main body of the code, use typed exceptions where possible:
# not this
raise Exception("panic!")
# this
from ansible import errors
...
raise errors.AnsibleError("panic!")
Similarly, exception checking should be fine grained:
# not this
try:
foo()
except:
bar()
# but this
try:
foo()
except SomeTypedException:
bar()
List Comprehensions
===================
In general list comprehensions are always preferred to map() and filter() calls.
However, they can be abused. Optimize for readability, and avoid nesting them too deeply.
Regexes
=======
There is a time and place for them, but here's an illustrative joke.
"A developer had a problem, and used a regular expression to solve it. Now the developer had two problems".
Often regexes are difficult to maintain, and a trusty call to other string operations can be a great solution, faster,
and more readable.
File Conventions
================
If a piece of code looks for a named YAML file in a directory, it should assume it can take no extension, or an extension of '.yml' or '.yaml'.
This should be true against all code that loads files.
Any code that uses directories should consider the possibility that the directory may be symlink.
New Ansible language parameters
===============================
If adding a new parameter, like 'can_fizzbuzz: True/False' be sure the value of the parameter is templated somewhere in the Runner code, as if anything can be parameterized in Ansible,
there is a user that will try to parameterize it.
String Find
===========
Use 'in':
# not this:
if x.find('foo') != -1:
# this:
if 'foo' in x:
String checks
=============
To test if something is a string, consider that it may be unicode.
# no
if type(x) == str:
# yes
if isinstance(x, basestring):
Cleverness
==========
Ansible's code is intended to be read by as many people as possible, so we don't particularly encourage clever or heavily idiomatic code.
In particular, metaclasses are probably not appropriate, however entertaining they may be to add.
Git Practices
=============
Pull requests cannot be accepted that contain merge commits.
Always do "git pull --rebase" and "git rebase" vs "git pull" or "git merge".
Always create a new branch for each pull request to avoid intertwingling different features or fixes on the same branch.
Python Version Compliance
=========================
All code in Ansible core must support a minimum version of Python 2.6.
Module code must support a minimum of Python 2.4, with occasional exception for modules that require code that themselves require 2.6 and later.
A quick reminder is that list comprehensions in Python 2.4 are not as fully fleshed out, there are no 'dict' comprehensions, and there is no 'with' statement.
But otherwise it's pretty much all the same.
The End
=======
This was not meant to be a scary document, so we hope it wasn't, but we also hope this helps you write code that is easier to maintain by others in the future.
If you have questions about this document, please ask on the ansible-devel mailing list.
Thank you!

27
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,27 @@
Welcome To Ansible GitHub
=========================
Hi! Nice to see you here!
If you'd like to ask a question
===============================
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.
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.
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.
If you'd like to file a bug
===========================
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.
Also please make sure you are testing on the latest released version of Ansible or the development branch.
Thanks!

28
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,28 @@
##### 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”, or “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!
##### 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

@ -1,39 +1,18 @@
include README.rst
include COPYING
include SYMLINK_CACHE.json
include requirements.txt
recursive-include docs *
include docs/docsite/rst/collections/all_plugins.rst
exclude docs/docsite/rst_warnings
exclude docs/docsite/rst/conf.py
exclude docs/docsite/rst/index.rst
recursive-exclude docs/docsite/_build *
recursive-exclude docs/docsite/_extensions *.pyc *.pyo
prune v2
prune docsite
prune ticket_stubs
prune packaging
prune test
prune hacking
include README.md packaging/rpm/ansible.spec COPYING
include examples/hosts
include examples/ansible.cfg
include examples/scripts/ConfigureRemotingForAnsible.ps1
include examples/scripts/upgrade_to_ps3.ps1
recursive-include lib/ansible/executor/powershell *.ps1
recursive-include lib/ansible/module_utils/csharp *.cs
recursive-include lib/ansible/module_utils/powershell *.psm1
recursive-include lib/ansible/modules/windows *.ps1
recursive-include lib/ansible/galaxy/data *.yml *.j2 README.md ansible.cfg inventory .git_keep
recursive-include lib/ansible/config *.yml
recursive-include licenses *.txt
recursive-include packaging *
recursive-include test/ansible_test *.py Makefile
recursive-include test/integration *
recursive-include test/lib/ansible_test/config *.template
recursive-include test/lib/ansible_test/_data *.cfg *.ini *.json *.ps1 *.psd1 *.py *.sh *.txt *.yml coveragerc inventory
recursive-include test/lib/ansible_test/_data/injector ansible ansible-config ansible-connection ansible-console ansible-doc ansible-galaxy ansible-playbook ansible-pull ansible-test ansible-vault pytest
recursive-include test/lib/ansible_test/_data/sanity/validate-modules validate-modules
recursive-include test/sanity *.json *.py *.txt
recursive-include test/support *.py *.ps1 *.psm1 *.cs
exclude test/sanity/code-smell/botmeta.*
recursive-include test/units *
include lib/ansible/module_utils/powershell.ps1
recursive-include lib/ansible/modules *
recursive-include docs *
recursive-include plugins *
include Makefile
include VERSION
include MANIFEST.in
include changelogs/CHANGELOG*.rst
include changelogs/changelog.yaml
recursive-include hacking/build_library *.py
include hacking/build-ansible.py
prune lib/ansible/modules/core/.git
prune lib/ansible/modules/extras/.git

282
Makefile
View File

@ -1,61 +1,51 @@
#!/usr/bin/make
# WARN: gmake syntax
########################################################
# Makefile for Ansible
#
# useful targets:
# make clean ---------------- clean up
# make webdocs -------------- produce ansible doc at docs/docsite/_build/html
# make coredocs ------------- produce core doc at docs/docsite/_build/html
# make sdist ---------------- produce a tarball
# make srpm ----------------- produce a SRPM
# make rpm ----------------- produce RPMs
# make deb-src -------------- produce a DEB source
# make deb ------------------ produce a DEB
# make docs ----------------- rebuild the manpages (results are checked in)
# make tests ---------------- run the tests (see https://docs.ansible.com/ansible/devel/dev_guide/testing_units.html for requirements)
# make tests ---------------- run the tests (see test/README.md for requirements)
# make pyflakes, make pep8 -- source code checks
########################################################
# variable section
NAME = ansible-base
NAME = ansible
OS = $(shell uname -s)
PREFIX ?= '/usr/local'
SDIST_DIR ?= 'dist'
# Manpages are currently built with asciidoc -- would like to move to markdown
# This doesn't evaluate until it's called. The -D argument is the
# directory of the target file ($@), kinda like `dirname`.
MANPAGES ?= $(patsubst %.rst.in,%,$(wildcard ./docs/man/man1/ansible*.1.rst.in))
ifneq ($(shell which rst2man 2>/dev/null),)
ASCII2MAN = rst2man $< $@
else ifneq ($(shell which rst2man.py 2>/dev/null),)
ASCII2MAN = rst2man.py $< $@
MANPAGES := docs/man/man1/ansible.1 docs/man/man1/ansible-playbook.1 docs/man/man1/ansible-pull.1 docs/man/man1/ansible-doc.1 docs/man/man1/ansible-galaxy.1 docs/man/man1/ansible-vault.1
ifneq ($(shell which a2x 2>/dev/null),)
ASCII2MAN = a2x -D $(dir $@) -d manpage -f manpage $<
ASCII2HTMLMAN = a2x -D docs/html/man/ -d manpage -f xhtml
else
ASCII2MAN = @echo "ERROR: rst2man from docutils command is not installed but is required to build $(MANPAGES)" && exit 1
ASCII2MAN = @echo "ERROR: AsciiDoc 'a2x' command is not installed but is required to build $(MANPAGES)" && exit 1
endif
PYTHON=python
GENERATE_CLI = hacking/build-ansible.py generate-man
SITELIB = $(shell $(PYTHON) -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
# fetch version from project release.py as single source-of-truth
VERSION := $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --raw || echo error)
ifeq ($(findstring error,$(VERSION)), error)
$(error "version_helper failed")
endif
# VERSION file provides one place to update the software version
VERSION := $(shell cat VERSION | cut -f1 -d' ')
RELEASE := $(shell cat VERSION | cut -f2 -d' ')
# Get the branch information from git
ifneq ($(shell which git),)
GIT_DATE := $(shell git log -n 1 --format="%ci")
GIT_HASH := $(shell git log -n 1 --format="%h")
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD | sed 's/[-_.\/]//g')
GITINFO = .$(GIT_HASH).$(GIT_BRANCH)
else
GITINFO = ""
GIT_DATE := $(shell git log -n 1 --format="%ai")
endif
ifeq ($(shell echo $(OS) | egrep -c 'Darwin|FreeBSD|OpenBSD|DragonFly'),1)
DATE := $(shell date -j -r $(shell git log -n 1 --format="%ct") +%Y%m%d%H%M)
CPUS ?= $(shell sysctl hw.ncpu|awk '{print $$2}')
ifeq ($(shell echo $(OS) | egrep -c 'Darwin|FreeBSD|OpenBSD'),1)
DATE := $(shell date -j -r $(shell git log -n 1 --format="%at") +%Y%m%d%H%M)
else
DATE := $(shell date --utc --date="$(GIT_DATE)" +%Y%m%d%H%M)
CPUS ?= $(shell nproc)
endif
# DEB build parameters
@ -63,17 +53,16 @@ DEBUILD_BIN ?= debuild
DEBUILD_OPTS = --source-option="-I"
DPUT_BIN ?= dput
DPUT_OPTS ?=
DEB_DATE := $(shell LC_TIME=C date +"%a, %d %b %Y %T %z")
DEB_VERSION ?= $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --debversion)
DEB_DATE := $(shell date +"%a, %d %b %Y %T %z")
ifeq ($(OFFICIAL),yes)
DEB_RELEASE ?= $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --debrelease)ppa
DEB_RELEASE = $(RELEASE)ppa
# Sign OFFICIAL builds using 'DEBSIGN_KEYID'
# DEBSIGN_KEYID is required when signing
ifneq ($(DEBSIGN_KEYID),)
DEBUILD_OPTS += -k$(DEBSIGN_KEYID)
endif
else
DEB_RELEASE ?= 100.git$(DATE)$(GITINFO)
DEB_RELEASE = 0.git$(DATE)
# Do not sign unofficial builds
DEBUILD_OPTS += -uc -us
DPUT_OPTS += -u
@ -83,160 +72,166 @@ DEB_PPA ?= ppa
# Choose the desired Ubuntu release: lucid precise saucy trusty
DEB_DIST ?= unstable
# pbuilder parameters
PBUILDER_ARCH ?= amd64
PBUILDER_CACHE_DIR = /var/cache/pbuilder
PBUILDER_BIN ?= pbuilder
PBUILDER_OPTS ?= --debootstrapopts --variant=buildd --architecture $(PBUILDER_ARCH) --debbuildopts -b
# RPM build parameters
RPMSPECDIR= packaging/rpm
RPMSPEC = $(RPMSPECDIR)/ansible.spec
RPMDIST = $(shell rpm --eval '%{?dist}')
RPMRELEASE = $(RELEASE)
ifneq ($(OFFICIAL),yes)
RPMRELEASE = 0.git$(DATE)
endif
RPMNVR = "$(NAME)-$(VERSION)-$(RPMRELEASE)$(RPMDIST)"
# ansible-test parameters
ANSIBLE_TEST ?= bin/ansible-test
TEST_FLAGS ?=
# MOCK build parameters
MOCK_BIN ?= mock
MOCK_CFG ?=
# ansible-test units parameters (make test / make test-py3)
PYTHON_VERSION ?= $(shell python2 -c 'import sys; print("%s.%s" % sys.version_info[:2])')
PYTHON3_VERSION ?= $(shell python3 -c 'import sys; print("%s.%s" % sys.version_info[:2])')
NOSETESTS ?= nosetests
# ansible-test integration parameters (make integration)
IMAGE ?= centos7
TARGET ?=
NOSETESTS3 ?= nosetests-3.3
########################################################
.PHONY: all
all: clean python
.PHONY: tests
tests:
$(ANSIBLE_TEST) units -v --python $(PYTHON_VERSION) $(TEST_FLAGS)
PYTHONPATH=./lib $(NOSETESTS) -d -w test/units -v --with-coverage --cover-package=ansible --cover-branches
.PHONY: tests-py3
tests-py3:
$(ANSIBLE_TEST) units -v --python $(PYTHON3_VERSION) $(TEST_FLAGS)
newtests:
PYTHONPATH=./v2:./lib $(NOSETESTS) -d -w v2/test -v --with-coverage --cover-package=ansible --cover-branches
.PHONY: integration
integration:
$(ANSIBLE_TEST) integration -v --docker $(IMAGE) $(TARGET) $(TEST_FLAGS)
newtests-py3:
PYTHONPATH=./v2:./lib $(NOSETESTS3) -d -w v2/test -v --with-coverage --cover-package=ansible --cover-branches
# Regenerate %.1.rst if %.1.rst.in has been modified more
# recently than %.1.rst.
%.1.rst: %.1.rst.in
authors:
sh hacking/authors.sh
# Regenerate %.1.asciidoc if %.1.asciidoc.in has been modified more
# recently than %.1.asciidoc.
%.1.asciidoc: %.1.asciidoc.in
sed "s/%VERSION%/$(VERSION)/" $< > $@
rm $<
# Regenerate %.1 if %.1.rst or release.py has been modified more
# recently than %.1. (Implicitly runs the %.1.rst recipe)
%.1: %.1.rst lib/ansible/release.py
# Regenerate %.1 if %.1.asciidoc or VERSION has been modified more
# recently than %.1. (Implicitly runs the %.1.asciidoc recipe)
%.1: %.1.asciidoc VERSION
$(ASCII2MAN)
.PHONY: clean
loc:
sloccount lib library bin
pep8:
@echo "#############################################"
@echo "# Running PEP8 Compliance Tests"
@echo "#############################################"
-pep8 -r --ignore=E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 lib/ bin/
# -pep8 -r --ignore=E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 --filename "*" library/
pyflakes:
pyflakes lib/ansible/*.py lib/ansible/*/*.py bin/*
clean:
@echo "Cleaning up distutils stuff"
rm -rf build
rm -rf dist
rm -rf lib/ansible*.egg-info/
@echo "Cleaning up byte compiled python stuff"
find . -type f -regex ".*\.py[co]$$" -delete
find . -type d -name "__pycache__" -delete
@echo "Cleaning up editor backup files"
find . -type f -not -path ./test/units/inventory_test_data/group_vars/noparse/all.yml~ \( -name "*~" -or -name "#*" \) -delete
find . -type f \( -name "*~" -or -name "#*" \) -delete
find . -type f \( -name "*.swp" \) -delete
@echo "Cleaning up manpage stuff"
find ./docs/man -type f -name "*.xml" -delete
find ./docs/man -type f -name "*.rst" -delete
find ./docs/man -type f -name "*.asciidoc" -delete
find ./docs/man/man3 -type f -name "*.3" -delete
rm -f ./docs/man/man1/*
@echo "Cleaning up output from test runs"
rm -rf test/test_data
rm -rf shippable/
rm -rf logs/
rm -rf .cache/
rm -f test/units/.coverage*
rm -rf test/results/*/*
find test/ -type f -name '*.retry' -delete
@echo "Cleaning up RPM building stuff"
rm -rf MANIFEST rpm-build
@echo "Cleaning up Debian building stuff"
rm -rf debian
rm -rf deb-build
rm -rf docs/json
rm -rf docs/js
@echo "Cleaning up docsite"
$(MAKE) -C docs/docsite clean
@echo "Cleaning up authors file"
rm -f AUTHORS.TXT
find . -type f -name '*.pyc' -delete
.PHONY: python
python:
$(PYTHON) setup.py build
.PHONY: install
install:
$(PYTHON) setup.py install
install_manpages:
gzip -9 $(wildcard ./docs/man/man1/ansible*.1)
cp $(wildcard ./docs/man/man1/ansible*.1.gz) $(PREFIX)/man/man1/
sdist: clean docs
$(PYTHON) setup.py sdist
.PHONY: sdist_check
sdist_check:
$(PYTHON) -c 'import setuptools, sys; sys.exit(int(not (tuple(map(int, setuptools.__version__.split("."))) > (39, 2, 0))))'
$(PYTHON) packaging/sdist/check-link-behavior.py
rpmcommon: $(MANPAGES) sdist
@mkdir -p rpm-build
@cp dist/*.gz rpm-build/
@sed -e 's#^Version:.*#Version: $(VERSION)#' -e 's#^Release:.*#Release: $(RPMRELEASE)%{?dist}#' $(RPMSPEC) >rpm-build/$(NAME).spec
.PHONY: sdist
sdist: sdist_check clean docs
_ANSIBLE_SDIST_FROM_MAKEFILE=1 $(PYTHON) setup.py sdist --dist-dir=$(SDIST_DIR)
mock-srpm: /etc/mock/$(MOCK_CFG).cfg rpmcommon
$(MOCK_BIN) -r $(MOCK_CFG) --resultdir rpm-build/ --buildsrpm --spec rpm-build/$(NAME).spec --sources rpm-build/
@echo "#############################################"
@echo "Ansible SRPM is built:"
@echo rpm-build/*.src.rpm
@echo "#############################################"
# Official releases generate the changelog as the last commit before the release.
# Snapshots shouldn't result in new checkins so the changelog is generated as
# part of creating the tarball.
.PHONY: snapshot
snapshot: sdist_check clean docs changelog
_ANSIBLE_SDIST_FROM_MAKEFILE=1 $(PYTHON) setup.py sdist --dist-dir=$(SDIST_DIR)
mock-rpm: /etc/mock/$(MOCK_CFG).cfg mock-srpm
$(MOCK_BIN) -r $(MOCK_CFG) --resultdir rpm-build/ --rebuild rpm-build/$(NAME)-*.src.rpm
@echo "#############################################"
@echo "Ansible RPM is built:"
@echo rpm-build/*.noarch.rpm
@echo "#############################################"
.PHONY: sdist_upload
sdist_upload: clean docs
$(PYTHON) setup.py sdist upload 2>&1 |tee upload.log
srpm: rpmcommon
@rpmbuild --define "_topdir %(pwd)/rpm-build" \
--define "_builddir %{_topdir}" \
--define "_rpmdir %{_topdir}" \
--define "_srcrpmdir %{_topdir}" \
--define "_specdir $(RPMSPECDIR)" \
--define "_sourcedir %{_topdir}" \
-bs rpm-build/$(NAME).spec
@rm -f rpm-build/$(NAME).spec
@echo "#############################################"
@echo "Ansible SRPM is built:"
@echo " rpm-build/$(RPMNVR).src.rpm"
@echo "#############################################"
.PHONY: changelog
changelog:
PYTHONPATH=./lib antsibull-changelog release -vv --use-ansible-doc && PYTHONPATH=./lib antsibull-changelog generate -vv --use-ansible-doc
rpm: rpmcommon
@rpmbuild --define "_topdir %(pwd)/rpm-build" \
--define "_builddir %{_topdir}" \
--define "_rpmdir %{_topdir}" \
--define "_srcrpmdir %{_topdir}" \
--define "_specdir $(RPMSPECDIR)" \
--define "_sourcedir %{_topdir}" \
--define "_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \
--define "__python `which $(PYTHON)`" \
-ba rpm-build/$(NAME).spec
@rm -f rpm-build/$(NAME).spec
@echo "#############################################"
@echo "Ansible RPM is built:"
@echo " rpm-build/$(RPMNVR).noarch.rpm"
@echo "#############################################"
.PHONY: debian
debian: sdist
@for DIST in $(DEB_DIST) ; do \
mkdir -p deb-build/$${DIST} ; \
tar -C deb-build/$${DIST} -xvf dist/$(NAME)-$(VERSION).tar.gz ; \
cp -a packaging/debian deb-build/$${DIST}/$(NAME)-$(VERSION)/ ; \
sed -ie "s|%VERSION%|$(DEB_VERSION)|g;s|%RELEASE%|$(DEB_RELEASE)|;s|%DIST%|$${DIST}|g;s|%DATE%|$(DEB_DATE)|g" deb-build/$${DIST}/$(NAME)-$(VERSION)/debian/changelog ; \
sed -ie "s|%VERSION%|$(VERSION)|g;s|%RELEASE%|$(DEB_RELEASE)|;s|%DIST%|$${DIST}|g;s|%DATE%|$(DEB_DATE)|g" deb-build/$${DIST}/$(NAME)-$(VERSION)/debian/changelog ; \
done
.PHONY: deb
deb: deb-src
@for DIST in $(DEB_DIST) ; do \
PBUILDER_OPTS="$(PBUILDER_OPTS) --distribution $${DIST} --basetgz $(PBUILDER_CACHE_DIR)/$${DIST}-$(PBUILDER_ARCH)-base.tgz --buildresult $(CURDIR)/deb-build/$${DIST}" ; \
$(PBUILDER_BIN) create $${PBUILDER_OPTS} --othermirror "deb http://archive.ubuntu.com/ubuntu $${DIST} universe" ; \
$(PBUILDER_BIN) update $${PBUILDER_OPTS} ; \
$(PBUILDER_BIN) build $${PBUILDER_OPTS} deb-build/$${DIST}/$(NAME)_$(DEB_VERSION)-$(DEB_RELEASE)~$${DIST}.dsc ; \
done
@echo "#############################################"
@echo "Ansible DEB artifacts:"
@for DIST in $(DEB_DIST) ; do \
echo deb-build/$${DIST}/$(NAME)_$(DEB_VERSION)-$(DEB_RELEASE)~$${DIST}_amd64.changes ; \
done
@echo "#############################################"
# Build package outside of pbuilder, with locally installed dependencies.
# Install BuildRequires as noted in packaging/debian/control.
.PHONY: local_deb
local_deb: debian
deb: debian
@for DIST in $(DEB_DIST) ; do \
(cd deb-build/$${DIST}/$(NAME)-$(VERSION)/ && $(DEBUILD) -b) ; \
done
@echo "#############################################"
@echo "Ansible DEB artifacts:"
@for DIST in $(DEB_DIST) ; do \
echo deb-build/$${DIST}/$(NAME)_$(DEB_VERSION)-$(DEB_RELEASE)~$${DIST}_amd64.changes ; \
echo deb-build/$${DIST}/$(NAME)_$(VERSION)-$(DEB_RELEASE)~$${DIST}_amd64.changes ; \
done
@echo "#############################################"
.PHONY: deb-src
deb-src: debian
@for DIST in $(DEB_DIST) ; do \
(cd deb-build/$${DIST}/$(NAME)-$(VERSION)/ && $(DEBUILD) -S) ; \
@ -244,50 +239,23 @@ deb-src: debian
@echo "#############################################"
@echo "Ansible DEB artifacts:"
@for DIST in $(DEB_DIST) ; do \
echo deb-build/$${DIST}/$(NAME)_$(DEB_VERSION)-$(DEB_RELEASE)~$${DIST}_source.changes ; \
echo deb-build/$${DIST}/$(NAME)_$(VERSION)-$(DEB_RELEASE)~$${DIST}_source.changes ; \
done
@echo "#############################################"
.PHONY: deb-upload
deb-upload: deb
@for DIST in $(DEB_DIST) ; do \
$(DPUT_BIN) $(DPUT_OPTS) $(DEB_PPA) deb-build/$${DIST}/$(NAME)_$(DEB_VERSION)-$(DEB_RELEASE)~$${DIST}_amd64.changes ; \
$(DPUT_BIN) $(DPUT_OPTS) $(DEB_PPA) deb-build/$${DIST}/$(NAME)_$(VERSION)-$(DEB_RELEASE)~$${DIST}_amd64.changes ; \
done
.PHONY: deb-src-upload
deb-src-upload: deb-src
@for DIST in $(DEB_DIST) ; do \
$(DPUT_BIN) $(DPUT_OPTS) $(DEB_PPA) deb-build/$${DIST}/$(NAME)_$(DEB_VERSION)-$(DEB_RELEASE)~$${DIST}_source.changes ; \
$(DPUT_BIN) $(DPUT_OPTS) $(DEB_PPA) deb-build/$${DIST}/$(NAME)_$(VERSION)-$(DEB_RELEASE)~$${DIST}_source.changes ; \
done
.PHONY: epub
epub:
(cd docs/docsite/; CPUS=$(CPUS) $(MAKE) epub)
# for arch or gentoo, read instructions in the appropriate 'packaging' subdirectory directory
.PHONY: webdocs
webdocs:
(cd docs/docsite/; CPUS=$(CPUS) $(MAKE) docs)
.PHONY: coredocs
coredocs:
(cd docs/docsite/; CPUS=$(CPUS) $(MAKE) coredocs)
webdocs: $(MANPAGES)
(cd docsite/; make docs)
.PHONY: linkcheckdocs
linkcheckdocs:
(cd docs/docsite/; CPUS=$(CPUS) $(MAKE) linkcheckdocs)
.PHONY: generate_rst
generate_rst: lib/ansible/cli/*.py
mkdir -p ./docs/man/man1/ ; \
$(GENERATE_CLI) --template-file=docs/templates/man.j2 --output-dir=docs/man/man1/ --output-format man lib/ansible/cli/*.py
docs: generate_rst
$(MAKE) $(MANPAGES)
.PHONY: alldocs
alldocs: docs webdocs
version:
@echo $(VERSION)
docs: $(MANPAGES)

57
README.md Normal file
View File

@ -0,0 +1,57 @@
[![PyPI version](https://badge.fury.io/py/ansible.png)](http://badge.fury.io/py/ansible)
[![PyPI downloads](https://pypip.in/d/ansible/badge.png)](https://pypi.python.org/pypi/ansible)
[![Build Status](https://travis-ci.org/ansible/ansible.svg?branch=tox_and_travis)](https://travis-ci.org/ansible/ansible)
Ansible
=======
Ansible is a radically simple IT automation system. It handles configuration-management, application deployment, cloud provisioning, ad-hoc task-execution, and multinode orchestration - including trivializing things like zero downtime rolling updates with load balancers.
Read the documentation and more at http://ansible.com/
Many users run straight from the development branch (it's generally fine to do so), but you might also wish to consume a release.
You can find instructions [here](http://docs.ansible.com/intro_getting_started.html) for a variety of platforms. If you decide to go with the development branch, be sure to run "git submodule update --init --recursive" after doing a checkout.
If you want to download a tarball of a release, go to [releases.ansible.com](http://releases.ansible.com/ansible), though most users use yum (using the EPEL instructions linked above), apt (using the PPA instructions linked above), or "pip install ansible".
Design Principles
=================
* Have a dead simple setup process and a minimal learning curve
* Manage machines very quickly and in parallel
* Avoid custom-agents and additional open ports, be agentless by leveraging the existing SSH daemon
* Describe infrastructure in a language that is both machine and human friendly
* Focus on security and easy auditability/review/rewriting of content
* Manage new remote machines instantly, without bootstrapping any software
* Allow module development in any dynamic language, not just Python
* Be usable as non-root
* Be the easiest IT automation system to use, ever.
Get Involved
============
* Read [Community Information](http://docs.ansible.com/community.html) for all kinds of ways to contribute to and interact with the project, including mailing list information and how to submit bug reports and code to Ansible.
* All code submissions are done through pull requests. Take care to make sure no merge commits are in the submission, and use "git rebase" vs "git merge" for this reason. If submitting a large code change (other than modules), it's probably a good idea to join ansible-devel and talk about what you would like to do or add first and to avoid duplicate efforts. This not only helps everyone know what's going on, it also helps save time and effort if we decide some changes are needed.
* Users list: [ansible-project](http://groups.google.com/group/ansible-project)
* Development list: [ansible-devel](http://groups.google.com/group/ansible-devel)
* Announcement list: [ansible-announce](http://groups.google.com/group/ansible-announce) - read only
* irc.freenode.net: #ansible
Branch Info
===========
* Releases are named after Van Halen songs.
* The devel branch corresponds to the release actively under development.
* As of 1.8, modules are kept in different repos, you'll want to follow [core](https://github.com/ansible/ansible-modules-core) and [extras](https://github.com/ansible/ansible-modules-extras)
* Various release-X.Y branches exist for previous releases.
* We'd love to have your contributions, read [Community Information](http://docs.ansible.com/community.html) for notes on how to get started.
Authors
=======
Ansible was created by [Michael DeHaan](https://github.com/mpdehaan) (michael.dehaan/gmail/com) and has contributions from over 900 users (and growing). Thanks everyone!
Ansible is sponsored by [Ansible, Inc](http://ansible.com)

View File

@ -1,115 +0,0 @@
|PyPI version| |Docs badge| |Chat badge| |Build Status| |Code Of Conduct| |Mailing Lists| |License|
*******
Ansible
*******
Ansible is a radically simple IT automation system. It handles
configuration management, application deployment, cloud provisioning,
ad-hoc task execution, network automation, and multi-node orchestration. Ansible makes complex
changes like zero-downtime rolling updates with load balancers easy. More information on `the Ansible website <https://ansible.com/>`_.
Design Principles
=================
* Have a dead simple setup process and a minimal learning curve.
* Manage machines very quickly and in parallel.
* Avoid custom-agents and additional open ports, be agentless by
leveraging the existing SSH daemon.
* Describe infrastructure in a language that is both machine and human
friendly.
* Focus on security and easy auditability/review/rewriting of content.
* Manage new remote machines instantly, without bootstrapping any
software.
* Allow module development in any dynamic language, not just Python.
* Be usable as non-root.
* Be the easiest IT automation system to use, ever.
Use Ansible
===========
You can install a released version of Ansible via ``pip``, a package manager, or
our `release repository <https://releases.ansible.com/ansible/>`_. See our
`installation guide <https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html>`_ for details on installing Ansible
on a variety of platforms.
Red Hat offers supported builds of `Ansible Engine <https://www.ansible.com/ansible-engine>`_.
Power users and developers can run the ``devel`` branch, which has the latest
features and fixes, directly. Although it is reasonably stable, you are more likely to encounter
breaking changes when running the ``devel`` branch. We recommend getting involved
in the Ansible community if you want to run the ``devel`` branch.
Get Involved
============
* Read `Community
Information <https://docs.ansible.com/ansible/latest/community>`_ for all
kinds of ways to contribute to and interact with the project,
including mailing list information and how to submit bug reports and
code to Ansible.
* Join a `Working Group
<https://github.com/ansible/community/wiki>`_, an organized community devoted to a specific technology domain or platform.
* Submit a proposed code update through a pull request to the ``devel`` branch.
* Talk to us before making larger changes
to avoid duplicate efforts. This not only helps everyone
know what is going on, it also helps save time and effort if we decide
some changes are needed.
* For a list of email lists, IRC channels and Working Groups, see the
`Communication page <https://docs.ansible.com/ansible/latest/community/communication.html>`_
Coding Guidelines
=================
We document our Coding Guidelines in the `Developer Guide <https://docs.ansible.com/ansible/devel/dev_guide/>`_. We particularly suggest you review:
* `Contributing your module to Ansible <https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_checklist.html>`_
* `Conventions, tips and pitfalls <https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_best_practices.html>`_
Branch Info
===========
* The ``devel`` branch corresponds to the release actively under development.
* The ``stable-2.X`` branches correspond to stable releases.
* Create a branch based on ``devel`` and set up a `dev environment <https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html#common-environment-setup>`_ if you want to open a PR.
* See the `Ansible release and maintenance <https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html>`_ page for information about active branches.
Roadmap
=======
Based on team and community feedback, an initial roadmap will be published for a major or minor version (ex: 2.7, 2.8).
The `Ansible Roadmap page <https://docs.ansible.com/ansible/devel/roadmap/>`_ details what is planned and how to influence the roadmap.
Authors
=======
Ansible was created by `Michael DeHaan <https://github.com/mpdehaan>`_
and has contributions from over 4700 users (and growing). Thanks everyone!
`Ansible <https://www.ansible.com>`_ is sponsored by `Red Hat, Inc.
<https://www.redhat.com>`_
License
=======
GNU General Public License v3.0 or later
See `COPYING <COPYING>`_ to see the full text.
.. |PyPI version| image:: https://img.shields.io/pypi/v/ansible-base.svg
:target: https://pypi.org/project/ansible-base
.. |Docs badge| image:: https://img.shields.io/badge/docs-latest-brightgreen.svg
:target: https://docs.ansible.com/ansible/latest/
.. |Build Status| image:: https://dev.azure.com/ansible/ansible/_apis/build/status/CI?branchName=stable-2.10
:target: https://dev.azure.com/ansible/ansible/_build/latest?definitionId=20&branchName=stable-2.10
.. |Chat badge| image:: https://img.shields.io/badge/chat-IRC-brightgreen.svg
:target: https://docs.ansible.com/ansible/latest/community/communication.html
.. |Code Of Conduct| image:: https://img.shields.io/badge/code%20of%20conduct-Ansible-silver.svg
:target: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html
:alt: Ansible Code of Conduct
.. |Mailing Lists| image:: https://img.shields.io/badge/mailing%20lists-Ansible-orange.svg
:target: https://docs.ansible.com/ansible/latest/community/communication.html#mailing-list-information
:alt: Ansible mailing lists
.. |License| image:: https://img.shields.io/badge/license-GPL%20v3.0-brightgreen.svg
:target: COPYING
:alt: Repository License

67
RELEASES.txt Normal file
View File

@ -0,0 +1,67 @@
Ansible Releases at a Glance
============================
Active Development
++++++++++++++++++
2.0 "TBD" - in progress
Released
++++++++
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.8 "You Really Got Me" ---- 11-25-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

1
VERSION Normal file
View File

@ -0,0 +1 @@
1.9.2 1

View File

@ -1 +0,0 @@
../lib/ansible/cli/scripts/ansible_cli_stub.py

207
bin/ansible Executable file
View File

@ -0,0 +1,207 @@
#!/usr/bin/env python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.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/>.
########################################################
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import sys
from ansible.runner import Runner
import ansible.constants as C
from ansible import utils
from ansible import errors
from ansible import callbacks
from ansible import inventory
########################################################
class Cli(object):
''' code behind bin/ansible '''
# ----------------------------------------------
def __init__(self):
self.stats = callbacks.AggregateStats()
self.callbacks = callbacks.CliRunnerCallbacks()
if C.DEFAULT_LOAD_CALLBACK_PLUGINS:
callbacks.load_callback_plugins()
# ----------------------------------------------
def parse(self):
''' create an options parser for bin/ansible '''
parser = utils.base_parser(
constants=C,
runas_opts=True,
subset_opts=True,
async_opts=True,
output_opts=True,
connect_opts=True,
check_opts=True,
diff_opts=False,
usage='%prog <host-pattern> [options]'
)
parser.add_option('-a', '--args', dest='module_args',
help="module arguments", default=C.DEFAULT_MODULE_ARGS)
parser.add_option('-m', '--module-name', dest='module_name',
help="module name to execute (default=%s)" % C.DEFAULT_MODULE_NAME,
default=C.DEFAULT_MODULE_NAME)
options, args = parser.parse_args()
self.callbacks.options = options
if len(args) == 0 or len(args) > 1:
parser.print_help()
sys.exit(1)
# privlege escalation command line arguments need to be mutually exclusive
utils.check_mutually_exclusive_privilege(options, parser)
if (options.ask_vault_pass and options.vault_password_file):
parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
return (options, args)
# ----------------------------------------------
def run(self, options, args):
''' use Runner lib to do SSH things '''
pattern = args[0]
sshpass = becomepass = vault_pass = become_method = None
# Never ask for an SSH password when we run with local connection
if options.connection == "local":
options.ask_pass = False
else:
options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS
options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
# become
utils.normalize_become_options(options)
prompt_method = utils.choose_pass_prompt(options)
(sshpass, becomepass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, become_ask_pass=options.become_ask_pass, ask_vault_pass=options.ask_vault_pass, become_method=prompt_method)
# read vault_pass from a file
if not options.ask_vault_pass and options.vault_password_file:
vault_pass = utils.read_vault_file(options.vault_password_file)
extra_vars = utils.parse_extra_vars(options.extra_vars, vault_pass)
inventory_manager = inventory.Inventory(options.inventory, vault_password=vault_pass)
if options.subset:
inventory_manager.subset(options.subset)
hosts = inventory_manager.list_hosts(pattern)
if len(hosts) == 0:
callbacks.display("No hosts matched", stderr=True)
sys.exit(0)
if options.listhosts:
for host in hosts:
callbacks.display(' %s' % host)
sys.exit(0)
if options.module_name in ['command','shell'] and not options.module_args:
callbacks.display("No argument passed to %s module" % options.module_name, color='red', stderr=True)
sys.exit(1)
if options.tree:
utils.prepare_writeable_dir(options.tree)
runner = Runner(
module_name=options.module_name,
module_path=options.module_path,
module_args=options.module_args,
remote_user=options.remote_user,
remote_pass=sshpass,
inventory=inventory_manager,
timeout=options.timeout,
private_key_file=options.private_key_file,
forks=options.forks,
pattern=pattern,
callbacks=self.callbacks,
transport=options.connection,
subset=options.subset,
check=options.check,
diff=options.check,
vault_pass=vault_pass,
become=options.become,
become_method=options.become_method,
become_pass=becomepass,
become_user=options.become_user,
extra_vars=extra_vars,
)
if options.seconds:
callbacks.display("background launch...\n\n", color='cyan')
results, poller = runner.run_async(options.seconds)
results = self.poll_while_needed(poller, options)
else:
results = runner.run()
return (runner, results)
# ----------------------------------------------
def poll_while_needed(self, poller, options):
''' summarize results from Runner '''
# BACKGROUND POLL LOGIC when -B and -P are specified
if options.seconds and options.poll_interval > 0:
poller.wait(options.seconds, options.poll_interval)
return poller.results
########################################################
if __name__ == '__main__':
callbacks.display("", log_only=True)
callbacks.display(" ".join(sys.argv), log_only=True)
callbacks.display("", log_only=True)
cli = Cli()
(options, args) = cli.parse()
try:
(runner, results) = cli.run(options, args)
for result in results['contacted'].values():
if 'failed' in result or result.get('rc', 0) != 0:
sys.exit(2)
if results['dark']:
sys.exit(3)
except errors.AnsibleError, e:
# Generic handler for ansible specific errors
callbacks.display("ERROR: %s" % str(e), stderr=True, color='red')
sys.exit(1)

View File

@ -1 +0,0 @@
ansible

View File

@ -1 +0,0 @@
../lib/ansible/cli/scripts/ansible_connection_cli_stub.py

View File

@ -1 +0,0 @@
ansible

View File

@ -1 +0,0 @@
ansible

337
bin/ansible-doc Executable file
View File

@ -0,0 +1,337 @@
#!/usr/bin/env python
# (c) 2012, Jan-Piet Mens <jpmens () gmail.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/>.
#
import os
import sys
import textwrap
import re
import optparse
import datetime
import subprocess
import fcntl
import termios
import struct
from ansible import utils
from ansible.utils import module_docs
import ansible.constants as C
from ansible.utils import version
import traceback
MODULEDIR = C.DEFAULT_MODULE_PATH
BLACKLIST_EXTS = ('.pyc', '.swp', '.bak', '~', '.rpm')
IGNORE_FILES = [ "COPYING", "CONTRIBUTING", "LICENSE", "README", "VERSION"]
_ITALIC = re.compile(r"I\(([^)]+)\)")
_BOLD = re.compile(r"B\(([^)]+)\)")
_MODULE = re.compile(r"M\(([^)]+)\)")
_URL = re.compile(r"U\(([^)]+)\)")
_CONST = re.compile(r"C\(([^)]+)\)")
PAGER = 'less'
LESS_OPTS = 'FRSX' # -F (quit-if-one-screen) -R (allow raw ansi control chars)
# -S (chop long lines) -X (disable termcap init and de-init)
def pager_print(text):
''' just print text '''
print text
def pager_pipe(text, cmd):
''' pipe text through a pager '''
if 'LESS' not in os.environ:
os.environ['LESS'] = LESS_OPTS
try:
cmd = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=sys.stdout)
cmd.communicate(input=text)
except IOError:
pass
except KeyboardInterrupt:
pass
def pager(text):
''' find reasonable way to display text '''
# this is a much simpler form of what is in pydoc.py
if not sys.stdout.isatty():
pager_print(text)
elif 'PAGER' in os.environ:
if sys.platform == 'win32':
pager_print(text)
else:
pager_pipe(text, os.environ['PAGER'])
elif subprocess.call('(less --version) 2> /dev/null', shell = True) == 0:
pager_pipe(text, 'less')
else:
pager_print(text)
def tty_ify(text):
t = _ITALIC.sub("`" + r"\1" + "'", text) # I(word) => `word'
t = _BOLD.sub("*" + r"\1" + "*", t) # B(word) => *word*
t = _MODULE.sub("[" + r"\1" + "]", t) # M(word) => [word]
t = _URL.sub(r"\1", t) # U(word) => word
t = _CONST.sub("`" + r"\1" + "'", t) # C(word) => `word'
return t
def get_man_text(doc):
opt_indent=" "
text = []
text.append("> %s\n" % doc['module'].upper())
desc = " ".join(doc['description'])
text.append("%s\n" % textwrap.fill(tty_ify(desc), initial_indent=" ", subsequent_indent=" "))
if 'option_keys' in doc and len(doc['option_keys']) > 0:
text.append("Options (= is mandatory):\n")
for o in sorted(doc['option_keys']):
opt = doc['options'][o]
if opt.get('required', False):
opt_leadin = "="
else:
opt_leadin = "-"
text.append("%s %s" % (opt_leadin, o))
desc = " ".join(opt['description'])
if 'choices' in opt:
choices = ", ".join(str(i) for i in opt['choices'])
desc = desc + " (Choices: " + choices + ")"
if 'default' in opt:
default = str(opt['default'])
desc = desc + " [Default: " + default + "]"
text.append("%s\n" % textwrap.fill(tty_ify(desc), initial_indent=opt_indent,
subsequent_indent=opt_indent))
if 'notes' in doc and len(doc['notes']) > 0:
notes = " ".join(doc['notes'])
text.append("Notes:%s\n" % textwrap.fill(tty_ify(notes), initial_indent=" ",
subsequent_indent=opt_indent))
if 'requirements' in doc and doc['requirements'] is not None and len(doc['requirements']) > 0:
req = ", ".join(doc['requirements'])
text.append("Requirements:%s\n" % textwrap.fill(tty_ify(req), initial_indent=" ",
subsequent_indent=opt_indent))
if 'examples' in doc and len(doc['examples']) > 0:
text.append("Example%s:\n" % ('' if len(doc['examples']) < 2 else 's'))
for ex in doc['examples']:
text.append("%s\n" % (ex['code']))
if 'plainexamples' in doc and doc['plainexamples'] is not None:
text.append("EXAMPLES:")
text.append(doc['plainexamples'])
if 'returndocs' in doc and doc['returndocs'] is not None:
text.append("RETURN VALUES:")
text.append(doc['returndocs'])
text.append('')
return "\n".join(text)
def get_snippet_text(doc):
text = []
desc = tty_ify(" ".join(doc['short_description']))
text.append("- name: %s" % (desc))
text.append(" action: %s" % (doc['module']))
for o in sorted(doc['options'].keys()):
opt = doc['options'][o]
desc = tty_ify(" ".join(opt['description']))
if opt.get('required', False):
s = o + "="
else:
s = o
text.append(" %-20s # %s" % (s, desc))
text.append('')
return "\n".join(text)
def get_module_list_text(module_list):
tty_size = 0
if os.isatty(0):
tty_size = struct.unpack('HHHH',
fcntl.ioctl(0, termios.TIOCGWINSZ, struct.pack('HHHH', 0, 0, 0, 0)))[1]
columns = max(60, tty_size)
displace = max(len(x) for x in module_list)
linelimit = columns - displace - 5
text = []
deprecated = []
for module in sorted(set(module_list)):
if module in module_docs.BLACKLIST_MODULES:
continue
filename = utils.plugins.module_finder.find_plugin(module)
if filename is None:
continue
if filename.endswith(".ps1"):
continue
if os.path.isdir(filename):
continue
try:
doc, plainexamples, returndocs = module_docs.get_docstring(filename)
desc = tty_ify(doc.get('short_description', '?')).strip()
if len(desc) > linelimit:
desc = desc[:linelimit] + '...'
if module.startswith('_'): # Handle deprecated
deprecated.append("%-*s %-*.*s" % (displace, module[1:], linelimit, len(desc), desc))
else:
text.append("%-*s %-*.*s" % (displace, module, linelimit, len(desc), desc))
except:
traceback.print_exc()
sys.stderr.write("ERROR: module %s has a documentation error formatting or is missing documentation\n" % module)
if len(deprecated) > 0:
text.append("\nDEPRECATED:")
text.extend(deprecated)
return "\n".join(text)
def find_modules(path, module_list):
if os.path.isdir(path):
for module in os.listdir(path):
if module.startswith('.'):
continue
elif os.path.isdir(module):
find_modules(module, module_list)
elif any(module.endswith(x) for x in BLACKLIST_EXTS):
continue
elif module.startswith('__'):
continue
elif module in IGNORE_FILES:
continue
elif module.startswith('_'):
fullpath = '/'.join([path,module])
if os.path.islink(fullpath): # avoids aliases
continue
module = os.path.splitext(module)[0] # removes the extension
module_list.append(module)
def main():
p = optparse.OptionParser(
version=version("%prog"),
usage='usage: %prog [options] [module...]',
description='Show Ansible module documentation',
)
p.add_option("-M", "--module-path",
action="store",
dest="module_path",
default=MODULEDIR,
help="Ansible modules/ directory")
p.add_option("-l", "--list",
action="store_true",
default=False,
dest='list_dir',
help='List available modules')
p.add_option("-s", "--snippet",
action="store_true",
default=False,
dest='show_snippet',
help='Show playbook snippet for specified module(s)')
p.add_option('-v', action='version', help='Show version number and exit')
(options, args) = p.parse_args()
if options.module_path is not None:
for i in options.module_path.split(os.pathsep):
utils.plugins.module_finder.add_directory(i)
if options.list_dir:
# list modules
paths = utils.plugins.module_finder._get_paths()
module_list = []
for path in paths:
find_modules(path, module_list)
pager(get_module_list_text(module_list))
sys.exit()
if len(args) == 0:
p.print_help()
def print_paths(finder):
''' Returns a string suitable for printing of the search path '''
# Uses a list to get the order right
ret = []
for i in finder._get_paths():
if i not in ret:
ret.append(i)
return os.pathsep.join(ret)
text = ''
for module in args:
filename = utils.plugins.module_finder.find_plugin(module)
if filename is None:
sys.stderr.write("module %s not found in %s\n" % (module, print_paths(utils.plugins.module_finder)))
continue
if any(filename.endswith(x) for x in BLACKLIST_EXTS):
continue
try:
doc, plainexamples, returndocs = module_docs.get_docstring(filename)
except:
traceback.print_exc()
sys.stderr.write("ERROR: module %s has a documentation error formatting or is missing documentation\n" % module)
continue
if doc is not None:
all_keys = []
for (k,v) in doc['options'].iteritems():
all_keys.append(k)
all_keys = sorted(all_keys)
doc['option_keys'] = all_keys
doc['filename'] = filename
doc['docuri'] = doc['module'].replace('_', '-')
doc['now_date'] = datetime.date.today().strftime('%Y-%m-%d')
doc['plainexamples'] = plainexamples
doc['returndocs'] = returndocs
if options.show_snippet:
text += get_snippet_text(doc)
else:
text += get_man_text(doc)
else:
# this typically means we couldn't even parse the docstring, not just that the YAML is busted,
# probably a quoting issue.
sys.stderr.write("ERROR: module %s missing documentation (or could not parse documentation)\n" % module)
pager(text)
if __name__ == '__main__':
main()

View File

@ -1 +0,0 @@
ansible

959
bin/ansible-galaxy Executable file
View File

@ -0,0 +1,959 @@
#!/usr/bin/env python
########################################################################
#
# (C) 2013, James Cammarata <jcammarata@ansible.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/>.
#
########################################################################
import datetime
import json
import os
import os.path
import shutil
import subprocess
import sys
import tarfile
import tempfile
import urllib
import urllib2
import yaml
from collections import defaultdict
from distutils.version import LooseVersion
from jinja2 import Environment
from optparse import OptionParser
import ansible.constants as C
import ansible.utils
from ansible.errors import AnsibleError
default_meta_template = """---
galaxy_info:
author: {{ author }}
description: {{description}}
company: {{ company }}
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: {{ issue_tracker_url }}
# Some suggested licenses:
# - BSD (default)
# - MIT
# - GPLv2
# - GPLv3
# - Apache
# - CC-BY
license: {{ license }}
min_ansible_version: {{ min_ansible_version }}
#
# Below are all platforms currently available. Just uncomment
# the ones that apply to your role. If you don't see your
# platform on this list, let us know and we'll get it added!
#
#platforms:
{%- for platform,versions in platforms.iteritems() %}
#- name: {{ platform }}
# versions:
# - all
{%- for version in versions %}
# - {{ version }}
{%- endfor %}
{%- endfor %}
#
# Below are all categories currently available. Just as with
# the platforms above, uncomment those that apply to your role.
#
#categories:
{%- for category in categories %}
#- {{ category.name }}
{%- endfor %}
dependencies: []
# List your role dependencies here, one per line.
# Be sure to remove the '[]' above if you add dependencies
# to this list.
{% for dependency in dependencies %}
#- {{ dependency }}
{% endfor %}
"""
default_readme_template = """Role Name
=========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
"""
#-------------------------------------------------------------------------------------
# Utility functions for parsing actions/options
#-------------------------------------------------------------------------------------
VALID_ACTIONS = ("init", "info", "install", "list", "remove")
SKIP_INFO_KEYS = ("platforms","readme_html", "related", "summary_fields", "average_aw_composite", "average_aw_score", "url" )
def get_action(args):
"""
Get the action the user wants to execute from the
sys argv list.
"""
for i in range(0,len(args)):
arg = args[i]
if arg in VALID_ACTIONS:
del args[i]
return arg
return None
def build_option_parser(action):
"""
Builds an option parser object based on the action
the user wants to execute.
"""
usage = "usage: %%prog [%s] [--help] [options] ..." % "|".join(VALID_ACTIONS)
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
OptionParser.format_epilog = lambda self, formatter: self.epilog
parser = OptionParser(usage=usage, epilog=epilog)
if not action:
parser.print_help()
sys.exit()
# options for all actions
# - none yet
# options specific to actions
if action == "info":
parser.set_usage("usage: %prog info [options] role_name[,version]")
elif action == "init":
parser.set_usage("usage: %prog init [options] role_name")
parser.add_option(
'-p', '--init-path', dest='init_path', default="./",
help='The path in which the skeleton role will be created. '
'The default is the current working directory.')
parser.add_option(
'--offline', dest='offline', default=False, action='store_true',
help="Don't query the galaxy API when creating roles")
elif action == "install":
parser.set_usage("usage: %prog install [options] [-r FILE | role_name(s)[,version] | scm+role_repo_url[,version] | tar_file(s)]")
parser.add_option(
'-i', '--ignore-errors', dest='ignore_errors', action='store_true', default=False,
help='Ignore errors and continue with the next specified role.')
parser.add_option(
'-n', '--no-deps', dest='no_deps', action='store_true', default=False,
help='Don\'t download roles listed as dependencies')
parser.add_option(
'-r', '--role-file', dest='role_file',
help='A file containing a list of roles to be imported')
elif action == "remove":
parser.set_usage("usage: %prog remove role1 role2 ...")
elif action == "list":
parser.set_usage("usage: %prog list [role_name]")
# options that apply to more than one action
if action != "init":
parser.add_option(
'-p', '--roles-path', dest='roles_path', default=C.DEFAULT_ROLES_PATH,
help='The path to the directory containing your roles. '
'The default is the roles_path configured in your '
'ansible.cfg file (/etc/ansible/roles if not configured)')
if action in ("info","init","install"):
parser.add_option(
'-s', '--server', dest='api_server', default="galaxy.ansible.com",
help='The API server destination')
if action in ("init","install"):
parser.add_option(
'-f', '--force', dest='force', action='store_true', default=False,
help='Force overwriting an existing role')
# done, return the parser
return parser
def get_opt(options, k, defval=""):
"""
Returns an option from an Optparse values instance.
"""
try:
data = getattr(options, k)
except:
return defval
if k == "roles_path":
if os.pathsep in data:
data = data.split(os.pathsep)[0]
return data
def exit_without_ignore(options, rc=1):
"""
Exits with the specified return code unless the
option --ignore-errors was specified
"""
if not get_opt(options, "ignore_errors", False):
print '- you can use --ignore-errors to skip failed roles.'
sys.exit(rc)
#-------------------------------------------------------------------------------------
# Galaxy API functions
#-------------------------------------------------------------------------------------
def api_get_config(api_server):
"""
Fetches the Galaxy API current version to ensure
the API server is up and reachable.
"""
try:
url = 'https://%s/api/' % api_server
data = json.load(urllib2.urlopen(url))
if not data.get("current_version",None):
return None
else:
return data
except:
return None
def api_lookup_role_by_name(api_server, role_name, notify=True):
"""
Uses the Galaxy API to do a lookup on the role owner/name.
"""
role_name = urllib.quote(role_name)
try:
parts = role_name.split(".")
user_name = ".".join(parts[0:-1])
role_name = parts[-1]
if notify:
print "- downloading role '%s', owned by %s" % (role_name, user_name)
except:
parser.print_help()
print "- invalid role name (%s). Specify role as format: username.rolename" % role_name
sys.exit(1)
url = 'https://%s/api/v1/roles/?owner__username=%s&name=%s' % (api_server,user_name,role_name)
try:
data = json.load(urllib2.urlopen(url))
if len(data["results"]) == 0:
return None
else:
return data["results"][0]
except:
return None
def api_fetch_role_related(api_server, related, role_id):
"""
Uses the Galaxy API to fetch the list of related items for
the given role. The url comes from the 'related' field of
the role.
"""
try:
url = 'https://%s/api/v1/roles/%d/%s/?page_size=50' % (api_server, int(role_id), related)
data = json.load(urllib2.urlopen(url))
results = data['results']
done = (data.get('next', None) == None)
while not done:
url = 'https://%s%s' % (api_server, data['next'])
print url
data = json.load(urllib2.urlopen(url))
results += data['results']
done = (data.get('next', None) == None)
return results
except:
return None
def api_get_list(api_server, what):
"""
Uses the Galaxy API to fetch the list of items specified.
"""
try:
url = 'https://%s/api/v1/%s/?page_size' % (api_server, what)
data = json.load(urllib2.urlopen(url))
if "results" in data:
results = data['results']
else:
results = data
done = True
if "next" in data:
done = (data.get('next', None) == None)
while not done:
url = 'https://%s%s' % (api_server, data['next'])
print url
data = json.load(urllib2.urlopen(url))
results += data['results']
done = (data.get('next', None) == None)
return results
except:
print "- failed to download the %s list" % what
return None
#-------------------------------------------------------------------------------------
# scm repo utility functions
#-------------------------------------------------------------------------------------
def scm_archive_role(scm, role_url, role_version, role_name):
if scm not in ['hg', 'git']:
print "- scm %s is not currently supported" % scm
return False
tempdir = tempfile.mkdtemp()
clone_cmd = [scm, 'clone', role_url, role_name]
with open('/dev/null', 'w') as devnull:
try:
print "- executing: %s" % " ".join(clone_cmd)
popen = subprocess.Popen(clone_cmd, cwd=tempdir, stdout=devnull, stderr=devnull)
except:
raise AnsibleError("error executing: %s" % " ".join(clone_cmd))
rc = popen.wait()
if rc != 0:
print "- command %s failed" % ' '.join(clone_cmd)
print " in directory %s" % tempdir
return False
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.tar')
if scm == 'hg':
archive_cmd = ['hg', 'archive', '--prefix', "%s/" % role_name]
if role_version:
archive_cmd.extend(['-r', role_version])
archive_cmd.append(temp_file.name)
if scm == 'git':
archive_cmd = ['git', 'archive', '--prefix=%s/' % role_name, '--output=%s' % temp_file.name]
if role_version:
archive_cmd.append(role_version)
else:
archive_cmd.append('HEAD')
with open('/dev/null', 'w') as devnull:
print "- executing: %s" % " ".join(archive_cmd)
popen = subprocess.Popen(archive_cmd, cwd=os.path.join(tempdir, role_name),
stderr=devnull, stdout=devnull)
rc = popen.wait()
if rc != 0:
print "- command %s failed" % ' '.join(archive_cmd)
print " in directory %s" % tempdir
return False
shutil.rmtree(tempdir, ignore_errors=True)
return temp_file.name
#-------------------------------------------------------------------------------------
# Role utility functions
#-------------------------------------------------------------------------------------
def get_role_path(role_name, options):
"""
Returns the role path based on the roles_path option
and the role name.
"""
roles_path = get_opt(options,'roles_path')
roles_path = os.path.join(roles_path, role_name)
roles_path = os.path.expanduser(roles_path)
return roles_path
def get_role_metadata(role_name, options):
"""
Returns the metadata as YAML, if the file 'meta/main.yml'
exists in the specified role_path
"""
role_path = os.path.join(get_role_path(role_name, options), 'meta/main.yml')
try:
if os.path.isfile(role_path):
f = open(role_path, 'r')
meta_data = yaml.safe_load(f)
f.close()
return meta_data
else:
return None
except:
return None
def get_galaxy_install_info(role_name, options):
"""
Returns the YAML data contained in 'meta/.galaxy_install_info',
if it exists.
"""
try:
info_path = os.path.join(get_role_path(role_name, options), 'meta/.galaxy_install_info')
if os.path.isfile(info_path):
f = open(info_path, 'r')
info_data = yaml.safe_load(f)
f.close()
return info_data
else:
return None
except:
return None
def write_galaxy_install_info(role_name, role_version, options):
"""
Writes a YAML-formatted file to the role's meta/ directory
(named .galaxy_install_info) which contains some information
we can use later for commands like 'list' and 'info'.
"""
info = dict(
version = role_version,
install_date = datetime.datetime.utcnow().strftime("%c"),
)
try:
info_path = os.path.join(get_role_path(role_name, options), 'meta/.galaxy_install_info')
f = open(info_path, 'w+')
info_data = yaml.safe_dump(info, f)
f.close()
except:
return False
return True
def remove_role(role_name, options):
"""
Removes the specified role from the roles path. There is a
sanity check to make sure there's a meta/main.yml file at this
path so the user doesn't blow away random directories
"""
if get_role_metadata(role_name, options):
role_path = get_role_path(role_name, options)
shutil.rmtree(role_path)
return True
else:
return False
def fetch_role(role_name, target, role_data, options):
"""
Downloads the archived role from github to a temp location, extracts
it, and then copies the extracted role to the role library path.
"""
# first grab the file and save it to a temp location
if '://' in role_name:
archive_url = role_name
else:
archive_url = 'https://github.com/%s/%s/archive/%s.tar.gz' % (role_data["github_user"], role_data["github_repo"], target)
print "- downloading role from %s" % archive_url
try:
url_file = urllib2.urlopen(archive_url)
temp_file = tempfile.NamedTemporaryFile(delete=False)
data = url_file.read()
while data:
temp_file.write(data)
data = url_file.read()
temp_file.close()
return temp_file.name
except Exception, e:
# TODO: better urllib2 error handling for error
# messages that are more exact
print "- error: failed to download the file."
return False
def install_role(role_name, role_version, role_filename, options):
# the file is a tar, so open it that way and extract it
# to the specified (or default) roles directory
if not tarfile.is_tarfile(role_filename):
print "- error: the file downloaded was not a tar.gz"
return False
else:
if role_filename.endswith('.gz'):
role_tar_file = tarfile.open(role_filename, "r:gz")
else:
role_tar_file = tarfile.open(role_filename, "r")
# verify the role's meta file
meta_file = None
members = role_tar_file.getmembers()
# next find the metadata file
for member in members:
if "/meta/main.yml" in member.name:
meta_file = member
break
if not meta_file:
print "- error: this role does not appear to have a meta/main.yml file."
return False
else:
try:
meta_file_data = yaml.safe_load(role_tar_file.extractfile(meta_file))
except:
print "- error: this role does not appear to have a valid meta/main.yml file."
return False
# we strip off the top-level directory for all of the files contained within
# the tar file here, since the default is 'github_repo-target', and change it
# to the specified role's name
role_path = os.path.join(get_opt(options, 'roles_path'), role_name)
role_path = os.path.expanduser(role_path)
print "- extracting %s to %s" % (role_name, role_path)
try:
if os.path.exists(role_path):
if not os.path.isdir(role_path):
print "- error: the specified roles path exists and is not a directory."
return False
elif not get_opt(options, "force", False):
print "- error: the specified role %s appears to already exist. Use --force to replace it." % role_name
return False
else:
# using --force, remove the old path
if not remove_role(role_name, options):
print "- error: %s doesn't appear to contain a role." % role_path
print " please remove this directory manually if you really want to put the role here."
return False
else:
os.makedirs(role_path)
# now we do the actual extraction to the role_path
for member in members:
# we only extract files, and remove any relative path
# bits that might be in the file for security purposes
# and drop the leading directory, as mentioned above
if member.isreg():
parts = member.name.split("/")[1:]
final_parts = []
for part in parts:
if part != '..' and '~' not in part and '$' not in part:
final_parts.append(part)
member.name = os.path.join(*final_parts)
role_tar_file.extract(member, role_path)
# write out the install info file for later use
write_galaxy_install_info(role_name, role_version, options)
except OSError, e:
print "- error: you do not have permission to modify files in %s" % role_path
return False
# return the parsed yaml metadata
print "- %s was installed successfully" % role_name
return meta_file_data
#-------------------------------------------------------------------------------------
# Action functions
#-------------------------------------------------------------------------------------
def execute_init(args, options, parser):
"""
Executes the init action, which creates the skeleton framework
of a role that complies with the galaxy metadata format.
"""
init_path = get_opt(options, 'init_path', './')
api_server = get_opt(options, "api_server", "galaxy.ansible.com")
force = get_opt(options, 'force', False)
offline = get_opt(options, 'offline', False)
if not offline:
api_config = api_get_config(api_server)
if not api_config:
print "- the API server (%s) is not responding, please try again later." % api_server
sys.exit(1)
try:
role_name = args.pop(0).strip()
if role_name == "":
raise Exception("")
role_path = os.path.join(init_path, role_name)
if os.path.exists(role_path):
if os.path.isfile(role_path):
print "- the path %s already exists, but is a file - aborting" % role_path
sys.exit(1)
elif not force:
print "- the directory %s already exists." % role_path
print " you can use --force to re-initialize this directory,\n" + \
" however it will reset any main.yml files that may have\n" + \
" been modified there already."
sys.exit(1)
except Exception, e:
parser.print_help()
print "- no role name specified for init"
sys.exit(1)
ROLE_DIRS = ('defaults','files','handlers','meta','tasks','templates','vars')
# create the default README.md
if not os.path.exists(role_path):
os.makedirs(role_path)
readme_path = os.path.join(role_path, "README.md")
f = open(readme_path, "wb")
f.write(default_readme_template)
f.close
for dir in ROLE_DIRS:
dir_path = os.path.join(init_path, role_name, dir)
main_yml_path = os.path.join(dir_path, 'main.yml')
# create the directory if it doesn't exist already
if not os.path.exists(dir_path):
os.makedirs(dir_path)
# now create the main.yml file for that directory
if dir == "meta":
# create a skeleton meta/main.yml with a valid galaxy_info
# datastructure in place, plus with all of the available
# tags/platforms included (but commented out) and the
# dependencies section
platforms = []
if not offline:
platforms = api_get_list(api_server, "platforms") or []
categories = []
if not offline:
categories = api_get_list(api_server, "categories") or []
# group the list of platforms from the api based
# on their names, with the release field being
# appended to a list of versions
platform_groups = defaultdict(list)
for platform in platforms:
platform_groups[platform['name']].append(platform['release'])
platform_groups[platform['name']].sort()
inject = dict(
author = 'your name',
company = 'your company (optional)',
license = 'license (GPLv2, CC-BY, etc)',
issue_tracker_url = 'http://example.com/issue/tracker',
min_ansible_version = '1.2',
platforms = platform_groups,
categories = categories,
)
rendered_meta = Environment().from_string(default_meta_template).render(inject)
f = open(main_yml_path, 'w')
f.write(rendered_meta)
f.close()
pass
elif dir not in ('files','templates'):
# just write a (mostly) empty YAML file for main.yml
f = open(main_yml_path, 'w')
f.write('---\n# %s file for %s\n' % (dir,role_name))
f.close()
print "- %s was created successfully" % role_name
def execute_info(args, options, parser):
"""
Executes the info action. This action prints out detailed
information about an installed role as well as info available
from the galaxy API.
"""
if len(args) == 0:
# the user needs to specify a role
parser.print_help()
print "- you must specify a user/role name"
sys.exit(1)
api_server = get_opt(options, "api_server", "galaxy.ansible.com")
api_config = api_get_config(api_server)
roles_path = get_opt(options, "roles_path")
for role in args:
role_info = {}
install_info = get_galaxy_install_info(role, options)
if install_info:
if 'version' in install_info:
install_info['intalled_version'] = install_info['version']
del install_info['version']
role_info.update(install_info)
remote_data = api_lookup_role_by_name(api_server, role, False)
if remote_data:
role_info.update(remote_data)
metadata = get_role_metadata(role, options)
if metadata:
role_info.update(metadata)
role_spec = ansible.utils.role_spec_parse(role)
if role_spec:
role_info.update(role_spec)
if role_info:
print "- %s:" % (role)
for k in sorted(role_info.keys()):
if k in SKIP_INFO_KEYS:
continue
if isinstance(role_info[k], dict):
print "\t%s: " % (k)
for key in sorted(role_info[k].keys()):
if key in SKIP_INFO_KEYS:
continue
print "\t\t%s: %s" % (key, role_info[k][key])
else:
print "\t%s: %s" % (k, role_info[k])
else:
print "- the role %s was not found" % role
def execute_install(args, options, parser):
"""
Executes the installation action. The args list contains the
roles to be installed, unless -f was specified. The list of roles
can be a name (which will be downloaded via the galaxy API and github),
or it can be a local .tar.gz file.
"""
role_file = get_opt(options, "role_file", None)
if len(args) == 0 and role_file is None:
# the user needs to specify one of either --role-file
# or specify a single user/role name
parser.print_help()
print "- you must specify a user/role name or a roles file"
sys.exit()
elif len(args) == 1 and not role_file is None:
# using a role file is mutually exclusive of specifying
# the role name on the command line
parser.print_help()
print "- please specify a user/role name, or a roles file, but not both"
sys.exit(1)
api_server = get_opt(options, "api_server", "galaxy.ansible.com")
no_deps = get_opt(options, "no_deps", False)
roles_path = get_opt(options, "roles_path")
roles_done = []
if role_file:
f = open(role_file, 'r')
if role_file.endswith('.yaml') or role_file.endswith('.yml'):
roles_left = map(ansible.utils.role_yaml_parse, yaml.safe_load(f))
else:
# roles listed in a file, one per line
roles_left = map(ansible.utils.role_spec_parse, f.readlines())
f.close()
else:
# roles were specified directly, so we'll just go out grab them
# (and their dependencies, unless the user doesn't want us to).
roles_left = map(ansible.utils.role_spec_parse, args)
while len(roles_left) > 0:
# query the galaxy API for the role data
role_data = None
role = roles_left.pop(0)
role_src = role.get("src")
role_scm = role.get("scm")
role_path = role.get("path")
if role_path:
options.roles_path = role_path
else:
options.roles_path = roles_path
if os.path.isfile(role_src):
# installing a local tar.gz
tmp_file = role_src
else:
if role_scm:
# create tar file from scm url
tmp_file = scm_archive_role(role_scm, role_src, role.get("version"), role.get("name"))
elif '://' in role_src:
# just download a URL - version will probably be in the URL
tmp_file = fetch_role(role_src, None, None, options)
else:
# installing from galaxy
api_config = api_get_config(api_server)
if not api_config:
print "- the API server (%s) is not responding, please try again later." % api_server
sys.exit(1)
role_data = api_lookup_role_by_name(api_server, role_src)
if not role_data:
print "- sorry, %s was not found on %s." % (role_src, api_server)
exit_without_ignore(options)
continue
role_versions = api_fetch_role_related(api_server, 'versions', role_data['id'])
if "version" not in role or role['version'] == '':
# convert the version names to LooseVersion objects
# and sort them to get the latest version. If there
# are no versions in the list, we'll grab the head
# of the master branch
if len(role_versions) > 0:
loose_versions = [LooseVersion(a.get('name',None)) for a in role_versions]
loose_versions.sort()
role["version"] = str(loose_versions[-1])
else:
role["version"] = 'master'
elif role['version'] != 'master':
if role_versions and role["version"] not in [a.get('name', None) for a in role_versions]:
print 'role is %s' % role
print "- the specified version (%s) was not found in the list of available versions (%s)." % (role['version'], role_versions)
exit_without_ignore(options)
continue
# download the role. if --no-deps was specified, we stop here,
# otherwise we recursively grab roles and all of their deps.
tmp_file = fetch_role(role_src, role["version"], role_data, options)
installed = False
if tmp_file:
installed = install_role(role.get("name"), role.get("version"), tmp_file, options)
# we're done with the temp file, clean it up
if tmp_file != role_src:
os.unlink(tmp_file)
# install dependencies, if we want them
if not no_deps and installed:
if not role_data:
role_data = get_role_metadata(role.get("name"), options)
role_dependencies = role_data['dependencies']
else:
role_dependencies = role_data['summary_fields']['dependencies'] # api_fetch_role_related(api_server, 'dependencies', role_data['id'])
if not role_dependencies:
role_dependencies = []
for dep in role_dependencies:
if isinstance(dep, basestring):
dep = ansible.utils.role_spec_parse(dep)
else:
dep = ansible.utils.role_yaml_parse(dep)
if not get_role_metadata(dep["name"], options):
if dep not in roles_left:
print '- adding dependency: %s' % dep["name"]
roles_left.append(dep)
else:
print '- dependency %s already pending installation.' % dep["name"]
else:
print '- dependency %s is already installed, skipping.' % dep["name"]
if not tmp_file or not installed:
print "- %s was NOT installed successfully." % role.get("name")
exit_without_ignore(options)
sys.exit(0)
def execute_remove(args, options, parser):
"""
Executes the remove action. The args list contains the list
of roles to be removed. This list can contain more than one role.
"""
if len(args) == 0:
parser.print_help()
print '- you must specify at least one role to remove.'
sys.exit()
for role in args:
if get_role_metadata(role, options):
if remove_role(role, options):
print '- successfully removed %s' % role
else:
print "- failed to remove role: %s" % role
else:
print '- %s is not installed, skipping.' % role
sys.exit(0)
def execute_list(args, options, parser):
"""
Executes the list action. The args list can contain zero
or one role. If one is specified, only that role will be
shown, otherwise all roles in the specified directory will
be shown.
"""
if len(args) > 1:
print "- please specify only one role to list, or specify no roles to see a full list"
sys.exit(1)
if len(args) == 1:
# show only the request role, if it exists
role_name = args[0]
metadata = get_role_metadata(role_name, options)
if metadata:
install_info = get_galaxy_install_info(role_name, options)
version = None
if install_info:
version = install_info.get("version", None)
if not version:
version = "(unknown version)"
# show some more info about single roles here
print "- %s, %s" % (role_name, version)
else:
print "- the role %s was not found" % role_name
else:
# show all valid roles in the roles_path directory
roles_path = get_opt(options, 'roles_path')
roles_path = os.path.expanduser(roles_path)
if not os.path.exists(roles_path):
parser.print_help()
print "- the path %s does not exist. Please specify a valid path with --roles-path" % roles_path
sys.exit(1)
elif not os.path.isdir(roles_path):
print "- %s exists, but it is not a directory. Please specify a valid path with --roles-path" % roles_path
parser.print_help()
sys.exit(1)
path_files = os.listdir(roles_path)
for path_file in path_files:
if get_role_metadata(path_file, options):
install_info = get_galaxy_install_info(path_file, options)
version = None
if install_info:
version = install_info.get("version", None)
if not version:
version = "(unknown version)"
print "- %s, %s" % (path_file, version)
sys.exit(0)
#-------------------------------------------------------------------------------------
# The main entry point
#-------------------------------------------------------------------------------------
def main():
# parse the CLI options
action = get_action(sys.argv)
parser = build_option_parser(action)
(options, args) = parser.parse_args()
# execute the desired action
if 1: #try:
fn = globals()["execute_%s" % action]
fn(args, options, parser)
#except KeyError, e:
# print "- error: %s is not a valid action. Valid actions are: %s" % (action, ", ".join(VALID_ACTIONS))
# sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1 +0,0 @@
ansible

View File

@ -1 +0,0 @@
ansible

330
bin/ansible-playbook Executable file
View File

@ -0,0 +1,330 @@
#!/usr/bin/env python
# (C) 2012, Michael DeHaan, <michael.dehaan@gmail.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/>.
#######################################################
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import sys
import os
import stat
# Augment PYTHONPATH to find Python modules relative to this file path
# This is so that we can find the modules when running from a local checkout
# installed as editable with `pip install -e ...` or `python setup.py develop`
local_module_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'lib')
)
sys.path.append(local_module_path)
import ansible.playbook
import ansible.constants as C
import ansible.utils.template
from ansible import errors
from ansible import callbacks
from ansible import utils
from ansible.color import ANSIBLE_COLOR, stringc
from ansible.callbacks import display
def colorize(lead, num, color):
""" Print 'lead' = 'num' in 'color' """
if num != 0 and ANSIBLE_COLOR and color is not None:
return "%s%s%-15s" % (stringc(lead, color), stringc("=", color), stringc(str(num), color))
else:
return "%s=%-4s" % (lead, str(num))
def hostcolor(host, stats, color=True):
if ANSIBLE_COLOR and color:
if stats['failures'] != 0 or stats['unreachable'] != 0:
return "%-37s" % stringc(host, 'red')
elif stats['changed'] != 0:
return "%-37s" % stringc(host, 'yellow')
else:
return "%-37s" % stringc(host, 'green')
return "%-26s" % host
def main(args):
''' run ansible-playbook operations '''
# create parser for CLI options
parser = utils.base_parser(
constants=C,
usage = "%prog playbook.yml",
connect_opts=True,
runas_opts=True,
subset_opts=True,
check_opts=True,
diff_opts=True
)
#parser.add_option('--vault-password', dest="vault_password",
# help="password for vault encrypted files")
parser.add_option('-t', '--tags', dest='tags', default='all',
help="only run plays and tasks tagged with these values")
parser.add_option('--skip-tags', dest='skip_tags',
help="only run plays and tasks whose tags do not match these values")
parser.add_option('--syntax-check', dest='syntax', action='store_true',
help="perform a syntax check on the playbook, but do not execute it")
parser.add_option('--list-tasks', dest='listtasks', action='store_true',
help="list all tasks that would be executed")
parser.add_option('--list-tags', dest='listtags', action='store_true',
help="list all available tags")
parser.add_option('--step', dest='step', action='store_true',
help="one-step-at-a-time: confirm each task before running")
parser.add_option('--start-at-task', dest='start_at',
help="start the playbook at the task matching this name")
parser.add_option('--force-handlers', dest='force_handlers',
default=C.DEFAULT_FORCE_HANDLERS, action='store_true',
help="run handlers even if a task fails")
parser.add_option('--flush-cache', dest='flush_cache', action='store_true',
help="clear the fact cache")
options, args = parser.parse_args(args)
if len(args) == 0:
parser.print_help(file=sys.stderr)
return 1
# privlege escalation command line arguments need to be mutually exclusive
utils.check_mutually_exclusive_privilege(options, parser)
if (options.ask_vault_pass and options.vault_password_file):
parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
sshpass = None
becomepass = None
vault_pass = None
options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
if options.listhosts or options.syntax or options.listtasks or options.listtags:
(_, _, vault_pass) = utils.ask_passwords(ask_vault_pass=options.ask_vault_pass)
else:
options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS
# Never ask for an SSH password when we run with local connection
if options.connection == "local":
options.ask_pass = False
# set pe options
utils.normalize_become_options(options)
prompt_method = utils.choose_pass_prompt(options)
(sshpass, becomepass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass,
become_ask_pass=options.become_ask_pass,
ask_vault_pass=options.ask_vault_pass,
become_method=prompt_method)
# read vault_pass from a file
if not options.ask_vault_pass and options.vault_password_file:
vault_pass = utils.read_vault_file(options.vault_password_file)
extra_vars = utils.parse_extra_vars(options.extra_vars, vault_pass)
only_tags = options.tags.split(",")
skip_tags = options.skip_tags
if options.skip_tags is not None:
skip_tags = options.skip_tags.split(",")
for playbook in args:
if not os.path.exists(playbook):
raise errors.AnsibleError("the playbook: %s could not be found" % playbook)
if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)):
raise errors.AnsibleError("the playbook: %s does not appear to be a file" % playbook)
inventory = ansible.inventory.Inventory(options.inventory, vault_password=vault_pass)
# Note: slightly wrong, this is written so that implicit localhost
# (which is not returned in list_hosts()) is taken into account for
# warning if inventory is empty. But it can't be taken into account for
# checking if limit doesn't match any hosts. Instead we don't worry about
# limit if only implicit localhost was in inventory to start with.
#
# Fix this in v2
no_hosts = False
if len(inventory.list_hosts()) == 0:
# Empty inventory
utils.warning("provided hosts list is empty, only localhost is available")
no_hosts = True
inventory.subset(options.subset)
if len(inventory.list_hosts()) == 0 and no_hosts is False:
# Invalid limit
raise errors.AnsibleError("Specified --limit does not match any hosts")
# run all playbooks specified on the command line
for playbook in args:
stats = callbacks.AggregateStats()
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
if options.step:
playbook_cb.step = options.step
if options.start_at:
playbook_cb.start_at = options.start_at
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
pb = ansible.playbook.PlayBook(
playbook=playbook,
module_path=options.module_path,
inventory=inventory,
forks=options.forks,
remote_user=options.remote_user,
remote_pass=sshpass,
callbacks=playbook_cb,
runner_callbacks=runner_cb,
stats=stats,
timeout=options.timeout,
transport=options.connection,
become=options.become,
become_method=options.become_method,
become_user=options.become_user,
become_pass=becomepass,
extra_vars=extra_vars,
private_key_file=options.private_key_file,
only_tags=only_tags,
skip_tags=skip_tags,
check=options.check,
diff=options.diff,
vault_password=vault_pass,
force_handlers=options.force_handlers,
)
if options.flush_cache:
display(callbacks.banner("FLUSHING FACT CACHE"))
pb.SETUP_CACHE.flush()
if options.listhosts or options.listtasks or options.syntax or options.listtags:
print ''
print 'playbook: %s' % playbook
print ''
playnum = 0
for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs):
playnum += 1
play = ansible.playbook.Play(pb, play_ds, play_basedir,
vault_password=pb.vault_password)
label = play.name
hosts = pb.inventory.list_hosts(play.hosts)
if options.listhosts:
print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts))
for host in hosts:
print ' %s' % host
if options.listtags or options.listtasks:
print ' play #%d (%s):\tTAGS: [%s]' % (playnum, label,','.join(sorted(set(play.tags))))
if options.listtags:
tags = []
for task in pb.tasks_to_run_in_play(play):
tags.extend(task.tags)
print ' TASK TAGS: [%s]' % (', '.join(sorted(set(tags).difference(['untagged']))))
if options.listtasks:
for task in pb.tasks_to_run_in_play(play):
if getattr(task, 'name', None) is not None:
# meta tasks have no names
print ' %s\tTAGS: [%s]' % (task.name, ', '.join(sorted(set(task.tags).difference(['untagged']))))
if options.listhosts or options.listtasks or options.listtags:
print ''
continue
if options.syntax:
# if we've not exited by now then we are fine.
print 'Playbook Syntax is fine'
return 0
failed_hosts = []
unreachable_hosts = []
try:
pb.run()
hosts = sorted(pb.stats.processed.keys())
display(callbacks.banner("PLAY RECAP"))
playbook_cb.on_stats(pb.stats)
for h in hosts:
t = pb.stats.summarize(h)
if t['failures'] > 0:
failed_hosts.append(h)
if t['unreachable'] > 0:
unreachable_hosts.append(h)
retries = failed_hosts + unreachable_hosts
if C.RETRY_FILES_ENABLED and len(retries) > 0:
filename = pb.generate_retry_inventory(retries)
if filename:
display(" to retry, use: --limit @%s\n" % filename)
for h in hosts:
t = pb.stats.summarize(h)
display("%s : %s %s %s %s" % (
hostcolor(h, t),
colorize('ok', t['ok'], 'green'),
colorize('changed', t['changed'], 'yellow'),
colorize('unreachable', t['unreachable'], 'red'),
colorize('failed', t['failures'], 'red')),
screen_only=True
)
display("%s : %s %s %s %s" % (
hostcolor(h, t, False),
colorize('ok', t['ok'], None),
colorize('changed', t['changed'], None),
colorize('unreachable', t['unreachable'], None),
colorize('failed', t['failures'], None)),
log_only=True
)
print ""
if len(failed_hosts) > 0:
return 2
if len(unreachable_hosts) > 0:
return 3
except errors.AnsibleError, e:
display("ERROR: %s" % e, color='red')
return 1
return 0
if __name__ == "__main__":
display(" ", log_only=True)
display(" ".join(sys.argv), log_only=True)
display(" ", log_only=True)
try:
sys.exit(main(sys.argv[1:]))
except errors.AnsibleError, e:
display("ERROR: %s" % e, color='red', stderr=True)
sys.exit(1)
except KeyboardInterrupt, ke:
display("ERROR: interrupted", color='red', stderr=True)
sys.exit(1)

View File

@ -1 +0,0 @@
ansible

257
bin/ansible-pull Executable file
View File

@ -0,0 +1,257 @@
#!/usr/bin/env python
# (c) 2012, Stephen Fromm <sfromm@gmail.com>
#
# 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/>.
#
# ansible-pull is a script that runs ansible in local mode
# after checking out a playbooks directory from source repo. There is an
# example playbook to bootstrap this script in the examples/ dir which
# installs ansible and sets it up to run on cron.
# usage:
# ansible-pull -d /var/lib/ansible \
# -U http://example.net/content.git [-C production] \
# [path/playbook.yml]
#
# the -d and -U arguments are required; the -C argument is optional.
#
# ansible-pull accepts an optional argument to specify a playbook
# location underneath the workdir and then searches the source repo
# for playbooks in the following order, stopping at the first match:
#
# 1. $workdir/path/playbook.yml, if specified
# 2. $workdir/$fqdn.yml
# 3. $workdir/$hostname.yml
# 4. $workdir/local.yml
#
# the source repo must contain at least one of these playbooks.
import os
import shutil
import sys
import datetime
import socket
import random
import time
from ansible import utils
from ansible.utils import cmd_functions
from ansible import errors
from ansible import inventory
DEFAULT_REPO_TYPE = 'git'
DEFAULT_PLAYBOOK = 'local.yml'
PLAYBOOK_ERRORS = {1: 'File does not exist',
2: 'File is not readable'}
VERBOSITY=0
def increment_debug(option, opt, value, parser):
global VERBOSITY
VERBOSITY += 1
def try_playbook(path):
if not os.path.exists(path):
return 1
if not os.access(path, os.R_OK):
return 2
return 0
def select_playbook(path, args):
playbook = None
if len(args) > 0 and args[0] is not None:
playbook = "%s/%s" % (path, args[0])
rc = try_playbook(playbook)
if rc != 0:
print >>sys.stderr, "%s: %s" % (playbook, PLAYBOOK_ERRORS[rc])
return None
return playbook
else:
fqdn = socket.getfqdn()
hostpb = "%s/%s.yml" % (path, fqdn)
shorthostpb = "%s/%s.yml" % (path, fqdn.split('.')[0])
localpb = "%s/%s" % (path, DEFAULT_PLAYBOOK)
errors = []
for pb in [hostpb, shorthostpb, localpb]:
rc = try_playbook(pb)
if rc == 0:
playbook = pb
break
else:
errors.append("%s: %s" % (pb, PLAYBOOK_ERRORS[rc]))
if playbook is None:
print >>sys.stderr, "\n".join(errors)
return playbook
def main(args):
""" Set up and run a local playbook """
usage = "%prog [options] [playbook.yml]"
parser = utils.SortedOptParser(usage=usage)
parser.add_option('--purge', default=False, action='store_true',
help='purge checkout after playbook run')
parser.add_option('-o', '--only-if-changed', dest='ifchanged', default=False, action='store_true',
help='only run the playbook if the repository has been updated')
parser.add_option('-s', '--sleep', dest='sleep', default=None,
help='sleep for random interval (between 0 and n number of seconds) before starting. this is a useful way to disperse git requests')
parser.add_option('-f', '--force', dest='force', default=False,
action='store_true',
help='run the playbook even if the repository could '
'not be updated')
parser.add_option('-d', '--directory', dest='dest', default=None,
help='directory to checkout repository to')
#parser.add_option('-l', '--live', default=True, action='store_live',
# help='Print the ansible-playbook output while running')
parser.add_option('-U', '--url', dest='url', default=None,
help='URL of the playbook repository')
parser.add_option('-C', '--checkout', dest='checkout',
help='branch/tag/commit to checkout. '
'Defaults to behavior of repository module.')
parser.add_option('-i', '--inventory-file', dest='inventory',
help="location of the inventory host file")
parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append",
help="set additional variables as key=value or YAML/JSON", default=[])
parser.add_option('-v', '--verbose', default=False, action="callback",
callback=increment_debug,
help='Pass -vvvv to ansible-playbook')
parser.add_option('-m', '--module-name', dest='module_name',
default=DEFAULT_REPO_TYPE,
help='Module name used to check out repository. '
'Default is %s.' % DEFAULT_REPO_TYPE)
parser.add_option('--vault-password-file', dest='vault_password_file',
help="vault password file")
parser.add_option('-K', '--ask-sudo-pass', default=False, dest='ask_sudo_pass', action='store_true',
help='ask for sudo password')
parser.add_option('-t', '--tags', dest='tags', default=False,
help='only run plays and tasks tagged with these values')
parser.add_option('--accept-host-key', default=False, dest='accept_host_key', action='store_true',
help='adds the hostkey for the repo url if not already added')
parser.add_option('--key-file', dest='key_file',
help="Pass '-i <key_file>' to the SSH arguments used by git.")
options, args = parser.parse_args(args)
hostname = socket.getfqdn()
if not options.dest:
# use a hostname dependent directory, in case of $HOME on nfs
options.dest = utils.prepare_writeable_dir('~/.ansible/pull/%s' % hostname)
options.dest = os.path.abspath(options.dest)
if not options.url:
parser.error("URL for repository not specified, use -h for help")
return 1
now = datetime.datetime.now()
print now.strftime("Starting ansible-pull at %F %T")
# Attempt to use the inventory passed in as an argument
# It might not yet have been downloaded so use localhost if note
if not options.inventory or not os.path.exists(options.inventory):
inv_opts = 'localhost,'
else:
inv_opts = options.inventory
limit_opts = 'localhost:%s:127.0.0.1' % hostname
repo_opts = "name=%s dest=%s" % (options.url, options.dest)
if VERBOSITY == 0:
base_opts = '-c local --limit "%s"' % limit_opts
elif VERBOSITY > 0:
debug_level = ''.join([ "v" for x in range(0, VERBOSITY) ])
base_opts = '-%s -c local --limit "%s"' % (debug_level, limit_opts)
if options.checkout:
repo_opts += ' version=%s' % options.checkout
# Only git module is supported
if options.module_name == DEFAULT_REPO_TYPE:
if options.accept_host_key:
repo_opts += ' accept_hostkey=yes'
if options.key_file:
repo_opts += ' key_file=%s' % options.key_file
path = utils.plugins.module_finder.find_plugin(options.module_name)
if path is None:
sys.stderr.write("module '%s' not found.\n" % options.module_name)
return 1
bin_path = os.path.dirname(os.path.abspath(__file__))
cmd = '%s/ansible localhost -i "%s" %s -m %s -a "%s"' % (
bin_path, inv_opts, base_opts, options.module_name, repo_opts
)
for ev in options.extra_vars:
cmd += ' -e "%s"' % ev
if options.sleep:
try:
secs = random.randint(0,int(options.sleep));
except ValueError:
parser.error("%s is not a number." % options.sleep)
return 1
print >>sys.stderr, "Sleeping for %d seconds..." % secs
time.sleep(secs);
# RUN THe CHECKOUT COMMAND
rc, out, err = cmd_functions.run_cmd(cmd, live=True)
if rc != 0:
if options.force:
print >>sys.stderr, "Unable to update repository. Continuing with (forced) run of playbook."
else:
return rc
elif options.ifchanged and '"changed": true' not in out:
print "Repository has not changed, quitting."
return 0
playbook = select_playbook(options.dest, args)
if playbook is None:
print >>sys.stderr, "Could not find a playbook to run."
return 1
cmd = '%s/ansible-playbook %s %s' % (bin_path, base_opts, playbook)
if options.vault_password_file:
cmd += " --vault-password-file=%s" % options.vault_password_file
if options.inventory:
cmd += ' -i "%s"' % options.inventory
for ev in options.extra_vars:
cmd += ' -e "%s"' % ev
if options.ask_sudo_pass:
cmd += ' -K'
if options.tags:
cmd += ' -t "%s"' % options.tags
os.chdir(options.dest)
# RUN THE PLAYBOOK COMMAND
rc, out, err = cmd_functions.run_cmd(cmd, live=True)
if options.purge:
os.chdir('/')
try:
shutil.rmtree(options.dest)
except Exception, e:
print >>sys.stderr, "Failed to remove %s: %s" % (options.dest, str(e))
return rc
if __name__ == '__main__':
try:
sys.exit(main(sys.argv[1:]))
except KeyboardInterrupt, e:
print >>sys.stderr, "Exit on user request.\n"
sys.exit(1)

View File

@ -1 +0,0 @@
../test/lib/ansible_test/_data/cli/ansible_test_cli_stub.py

View File

@ -1 +0,0 @@
ansible

241
bin/ansible-vault Executable file
View File

@ -0,0 +1,241 @@
#!/usr/bin/env python
# (c) 2014, James Tanner <tanner.jc@gmail.com>
#
# 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/>.
#
# ansible-vault is a script that encrypts/decrypts YAML files. See
# http://docs.ansible.com/playbooks_vault.html for more details.
__requires__ = ['ansible']
try:
import pkg_resources
except Exception:
# Use pkg_resources to find the correct versions of libraries and set
# sys.path appropriately when there are multiversion installs. But we
# have code that better expresses the errors in the places where the code
# is actually used (the deps are optional for many code paths) so we don't
# want to fail here.
pass
import os
import sys
import traceback
import ansible.constants as C
from ansible import utils
from ansible import errors
from ansible.utils.vault import VaultEditor
from optparse import OptionParser
#-------------------------------------------------------------------------------------
# Utility functions for parsing actions/options
#-------------------------------------------------------------------------------------
VALID_ACTIONS = ("create", "decrypt", "edit", "encrypt", "rekey", "view")
def build_option_parser(action):
"""
Builds an option parser object based on the action
the user wants to execute.
"""
usage = "usage: %%prog [%s] [--help] [options] file_name" % "|".join(VALID_ACTIONS)
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
OptionParser.format_epilog = lambda self, formatter: self.epilog
parser = OptionParser(usage=usage, epilog=epilog)
if not action:
parser.print_help()
sys.exit()
# options for all actions
#parser.add_option('-c', '--cipher', dest='cipher', default="AES256", help="cipher to use")
parser.add_option('--debug', dest='debug', action="store_true", help="debug")
parser.add_option('--vault-password-file', dest='password_file',
help="vault password file", default=C.DEFAULT_VAULT_PASSWORD_FILE)
# options specific to actions
if action == "create":
parser.set_usage("usage: %prog create [options] file_name")
elif action == "decrypt":
parser.set_usage("usage: %prog decrypt [options] file_name")
elif action == "edit":
parser.set_usage("usage: %prog edit [options] file_name")
elif action == "view":
parser.set_usage("usage: %prog view [options] file_name")
elif action == "encrypt":
parser.set_usage("usage: %prog encrypt [options] file_name")
elif action == "rekey":
parser.set_usage("usage: %prog rekey [options] file_name")
# done, return the parser
return parser
def get_action(args):
"""
Get the action the user wants to execute from the
sys argv list.
"""
for i in range(0,len(args)):
arg = args[i]
if arg in VALID_ACTIONS:
del args[i]
return arg
return None
def get_opt(options, k, defval=""):
"""
Returns an option from an Optparse values instance.
"""
try:
data = getattr(options, k)
except:
return defval
if k == "roles_path":
if os.pathsep in data:
data = data.split(os.pathsep)[0]
return data
#-------------------------------------------------------------------------------------
# Command functions
#-------------------------------------------------------------------------------------
def execute_create(args, options, parser):
if len(args) > 1:
raise errors.AnsibleError("'create' does not accept more than one filename")
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True, confirm_vault=True)
else:
password = utils.read_vault_file(options.password_file)
cipher = 'AES256'
if hasattr(options, 'cipher'):
cipher = options.cipher
this_editor = VaultEditor(cipher, password, args[0])
this_editor.create_file()
def execute_decrypt(args, options, parser):
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True)
else:
password = utils.read_vault_file(options.password_file)
cipher = 'AES256'
if hasattr(options, 'cipher'):
cipher = options.cipher
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.decrypt_file()
print "Decryption successful"
def execute_edit(args, options, parser):
if len(args) > 1:
raise errors.AnsibleError("edit does not accept more than one filename")
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True)
else:
password = utils.read_vault_file(options.password_file)
cipher = None
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.edit_file()
def execute_view(args, options, parser):
if len(args) > 1:
raise errors.AnsibleError("view does not accept more than one filename")
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True)
else:
password = utils.read_vault_file(options.password_file)
cipher = None
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.view_file()
def execute_encrypt(args, options, parser):
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True, confirm_vault=True)
else:
password = utils.read_vault_file(options.password_file)
cipher = 'AES256'
if hasattr(options, 'cipher'):
cipher = options.cipher
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.encrypt_file()
print "Encryption successful"
def execute_rekey(args, options, parser):
if not options.password_file:
password, __ = utils.ask_vault_passwords(ask_vault_pass=True)
else:
password = utils.read_vault_file(options.password_file)
__, new_password = utils.ask_vault_passwords(ask_vault_pass=False, ask_new_vault_pass=True, confirm_new=True)
cipher = None
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.rekey_file(new_password)
print "Rekey successful"
#-------------------------------------------------------------------------------------
# MAIN
#-------------------------------------------------------------------------------------
def main():
action = get_action(sys.argv)
parser = build_option_parser(action)
(options, args) = parser.parse_args()
if not len(args):
raise errors.AnsibleError(
"The '%s' command requires a filename as the first argument" % action
)
# execute the desired action
try:
fn = globals()["execute_%s" % action]
fn(args, options, parser)
except Exception, err:
if options.debug:
print traceback.format_exc()
print "ERROR:",err
sys.exit(1)
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
Placeholder changelog
=====================
This file is a placeholder; a version-specific ``CHANGELOG-vX.Y.rst`` will be generated during releases from fragments
under changelogs/fragments. On release branches once a release has been created, consult the branch's version-specific
file for changes that have occurred in that branch.

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
---
title: Ansible Base
release_tag_re: '(v(?:[\d.ab\-]|rc)+)'
pre_release_tag_re: '(?P<pre_release>(?:[ab]|rc)+\d*)$'
changes_file: changelog.yaml
changes_format: combined
keep_fragments: true
always_refresh: true
ignore_other_fragment_extensions: true
mention_ancestor: false
notesdir: fragments
prelude_section_name: release_summary
new_plugins_after_name: removed_features
sections:
- ['major_changes', 'Major Changes']
- ['minor_changes', 'Minor Changes']
- ['breaking_changes', 'Breaking Changes / Porting Guide']
- ['deprecated_features', 'Deprecated Features']
- ['removed_features', 'Removed Features (previously deprecated)']
- ['security_fixes', 'Security Fixes']
- ['bugfixes', 'Bugfixes']
- ['known_issues', 'Known Issues']

View File

@ -1,2 +0,0 @@
bugfixes:
- display correct error information when an error exists in the last line of the file (https://github.com/ansible/ansible/issues/16456)

View File

@ -1,3 +0,0 @@
bugfixes:
- uri - Don't return the body even if it failed
(https://github.com/ansible/ansible/issues/21003)

View File

@ -1,4 +0,0 @@
bugfixes:
- >
pause - Fix indefinite hang when using a pause task on a background
process (https://github.com/ansible/ansible/issues/32142)

View File

@ -1,2 +0,0 @@
minor_changes:
- debconf - add a note about no_log=True since module might expose sensitive information to logs (https://github.com/ansible/ansible/issues/32386).

View File

@ -1,2 +0,0 @@
minor_changes:
- ssh - connection plugin now supports a new variable ``sshpass_prompt`` which gets passed to ``sshpass`` allowing the user to set a custom substring to search for a password prompt (requires sshpass 1.06+)

View File

@ -1,2 +0,0 @@
minor_changes:
- subelements - clarify the lookup plugin documentation for parameter handling (https://github.com/ansible/ansible/issues/38182).

View File

@ -1,2 +0,0 @@
bugfixes:
- facts - account for Slackware OS with ``+`` in the name (https://github.com/ansible/ansible/issues/38760)

View File

@ -1,3 +0,0 @@
---
bugfixes:
- copy - Fixed copy module not working in case that remote_src is enabled and dest ends in a / (https://github.com/ansible/ansible/pull/47238)

View File

@ -1,4 +0,0 @@
---
bugfixes:
- apt - Fixed the issue the cache being updated while auto-installing its
dependencies even when ``update_cache`` is set to false.

View File

@ -1,2 +0,0 @@
minor_changes:
- Raise error when no task file is provided to import_tasks (https://github.com/ansible/ansible/issues/54095).

View File

@ -1,2 +0,0 @@
bugfixes:
- Provide more information in AnsibleUndefinedVariable (https://github.com/ansible/ansible/issues/55152)

View File

@ -1,2 +0,0 @@
minor_changes:
- default_callback - moving 'check_mode_markers' documentation in default_callback doc_fragment (https://github.com/ansible-collections/community.general/issues/565).

View File

@ -1,6 +0,0 @@
bugfixes:
- synchronize - fix password authentication on Python 2 (https://github.com/ansible/ansible/issues/56629)
- >
AnsibleModule.run_command() - set ``close_fds`` to ``False`` on Python 2 if ``pass_fds`` are passed to
``run_command()``. Since ``subprocess.Popen()`` on Python 2 does not have the ``pass_fds`` option,
there is no way to exclude a specific list of file descriptors from being closed.

View File

@ -1,2 +0,0 @@
bugfixes:
- Remove the unnecessary warning about aptitude not being installed (https://github.com/ansible/ansible/issues/56832).

View File

@ -1,2 +0,0 @@
minor_changes:
- apt_repository - Implemented an exponential backoff behaviour when retrying to update the apt cache with new params ``update_cache_retry_max_delay`` and ``update_cache_retries`` to control the behavior.

View File

@ -1,5 +0,0 @@
bugfixes:
- Strategy - When building the task in the Strategy from the Worker,
ensure it is properly marked as finalized and squashed. Addresses an
issue with ``ansible_failed_task``.
(https://github.com/ansible/ansible/issues/57399)

View File

@ -1,3 +0,0 @@
---
bugfixes:
- Add missing gcp modules to gcp module defaults group

View File

@ -1,4 +0,0 @@
bugfixes:
- combine filter - ``[dict1, [dict2]] | combine`` now raise an error; previously ``combine`` had an undocumented behaviour where it was flattening the list before combining it (https://github.com/ansible/ansible/pull/57894#discussion_r339517518).
minor_changes:
- combine filter - now accept a ``list_merge`` argument which modifies its behaviour when the hashes to merge contain arrays/lists.

View File

@ -1,2 +0,0 @@
bugfixes:
- copy - recursive copy with ``remote_src=yes`` now recurses beyond first level. (Fixes https://github.com/ansible/ansible/issues/58284)

View File

@ -1,5 +0,0 @@
bugfixes:
- "ansible-test - during module validation, improve alias handling."
- "ansible-test - during module validation, handle add_file_common_args only for top-level arguments."
minor_changes:
- "ansible-test - extend alias validation."

View File

@ -1,2 +0,0 @@
bugfixes:
- Use hostnamectl command to get current hostname for host while using systemd strategy (https://github.com/ansible/ansible/issues/59438).

View File

@ -1,2 +0,0 @@
bugfixes:
- CLI - the `ANSIBLE_PLAYBOOK_DIR` envvar or `playbook_dir` config can now substitute for the --playbook-dir arg on CLIs that support it (https://github.com/ansible/ansible/issues/59464)

View File

@ -1,2 +0,0 @@
bugfixes:
- cron and cronvar - use get_bin_path utility to locate the default crontab executable instead of the hardcoded /usr/bin/crontab. (https://github.com/ansible/ansible/pull/59765)

View File

@ -1,5 +0,0 @@
bugfixes:
- >
group - The group module was not correctly detecting whether a local
group is existing or not with local set to yes if the same group
exists in a non local group repository e.g. LDAP. (https://github.com/ansible/ansible/issues/58619)

View File

@ -1,4 +0,0 @@
bugfixes:
- template lookup - ensure changes to the templar in the lookup, do not
affect the templar context outside of the lookup
(https://github.com/ansible/ansible/issues/60106)

View File

@ -1,2 +0,0 @@
minor_changes:
- apt - Implemented an exponential backoff behaviour when retrying to update the cache with new params ``update_cache_retry_max_delay`` and ``update_cache_retries`` to control the behavior.

View File

@ -1,2 +0,0 @@
bugfixes:
- Handle exception encountered while parsing the argument description in module when invoked via ansible-doc command (https://github.com/ansible/ansible/issues/60587).

View File

@ -1,2 +0,0 @@
minor_changes:
- Add an additional check for importing journal from systemd-python module (https://github.com/ansible/ansible/issues/60595).

View File

@ -1,6 +0,0 @@
---
minor_changes:
- vars plugins - Support vars plugins in collections by adding the ability to whitelist plugins.
- host_group_vars plugin - Require whitelisting and whitelist by default.
- Add a global toggle to control when vars plugins are executed (per task by default for backward compatibility or after importing inventory).
- Add a per-plugin stage option to override the global toggle to control the execution of individual vars plugins (per task, after inventory, or both).

View File

@ -1,4 +0,0 @@
bugfixes:
- ansible-inventory - Properly hide arguments that should not be shown
(https://github.com/ansible/ansible/issues/61604)
- ansible-inventory - Restore functionality to allow ``--graph`` to be limited by a host pattern

View File

@ -1,2 +0,0 @@
bugfixes:
- ansible-galaxy - Fix url building to not truncate the URL (https://github.com/ansible/ansible/issues/61624)

View File

@ -1,2 +0,0 @@
minor_changes:
- "``AnsibleModule.load_file_common_arguments`` now allows to simply override ``path``."

View File

@ -1,2 +0,0 @@
minor_changes:
- Remove the deprecation message for the ``TRANSFORM_INVALID_GROUP_CHARS`` setting. (https://github.com/ansible/ansible/issues/61889)

View File

@ -1,2 +0,0 @@
minor_changes:
- get_url - Remove deprecated string format support for the headers option (https://github.com/ansible/ansible/issues/61891)

View File

@ -1,3 +0,0 @@
bugfixes:
- get_url - Don't treat no checksum as a checksum match
(https://github.com/ansible/ansible/issues/61978)

View File

@ -1,2 +0,0 @@
bugfixes:
- ansible-test coverage - Fix the ``--all`` argument when generating coverage reports - https://github.com/ansible/ansible/issues/62096

View File

@ -1,2 +0,0 @@
minor_changes:
- user - allow groups, append parameters with local

View File

@ -1,5 +0,0 @@
security_fixes:
- >
**security issue** - TaskExecutor - Ensure we don't erase unsafe context in TaskExecutor.run on bytes.
Only present in 2.9.0beta1
(https://github.com/ansible/ansible/issues/62237)

View File

@ -1,2 +0,0 @@
bugfixes:
- Remove a temp directory created by wait_for_connection action plugin (https://github.com/ansible/ansible/issues/62407).

View File

@ -1,4 +0,0 @@
minor_changes:
- callbacks - Allow modules to return `None` as before/after entries for diff.
This should make it easier for modules to report the "not existing" state of
the entity they touched.

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