Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ce4883bcc5 | |||
| a75a84b44a | |||
| f132e99b2a | |||
| 4d0ce5bd41 | |||
| b01da1b780 | |||
| 1248d2ce8a | |||
| d72cd70cc8 | |||
| 362626d07c | |||
| a54b8764fa | |||
| 6b4584d004 | |||
| cb0842ab49 | |||
| 2432b45eb1 | |||
| d6214c5d56 | |||
| c5b6d23c63 | |||
| e83f14200c | |||
| 7c0431b1e4 | |||
| 1c5055a401 | |||
| 24d885e368 | |||
| 8851ceaa9e | |||
| 854bf14222 | |||
| d8526a6c80 | |||
| e0fe6ca5d8 | |||
| ca2a12aa5b | |||
| 29018cf2a7 | |||
| 9d8eee633d | |||
| 8cc71a6eec | |||
| 3565249471 | |||
| 595813a1fe | |||
| 0de306574e | |||
| d33486d52a | |||
| 0dabb37337 | |||
| 9a930fb481 | |||
| d4e11c5c69 | |||
| 08f4984d92 | |||
| 7daaabdedb | |||
| 9943c50863 | |||
| ce15813e70 | |||
| f05d457560 |
@ -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"
|
||||
26
.coveragerc
26
.coveragerc
@ -1,26 +0,0 @@
|
||||
# This configuration file is used for manual execution of coverage
|
||||
# as well as for tests run through ansible-test.
|
||||
|
||||
[run]
|
||||
branch = True
|
||||
|
||||
# Enable concurrency. This also enables parallel mode, which results in
|
||||
# multiple coverage files being created. Concurrency allows us to collect
|
||||
# results from multiple tests simultaneously, as well as supporting multiple
|
||||
# test runs, such as from integration tests.
|
||||
concurrency = multiprocessing
|
||||
parallel = True
|
||||
|
||||
# When running tests through ansible-test, this option is overridden by
|
||||
# the COVERAGE_FILE environment variable. This option is present for
|
||||
# convenience when running coverage manually from this directory.
|
||||
data_file = test/results/coverage/coverage
|
||||
|
||||
# Don't collect or report code coverage from files matching these patterns.
|
||||
omit =
|
||||
*/python*/dist-packages/*
|
||||
*/python*/site-packages/*
|
||||
*/python*/distutils/*
|
||||
*/pyshared/*
|
||||
*/pytest
|
||||
*/AnsiballZ_*.py
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
||||
.github/ export-ignore
|
||||
hacking/ export-ignore
|
||||
922
.github/BOTMETA.yml
vendored
922
.github/BOTMETA.yml
vendored
@ -1,922 +0,0 @@
|
||||
# BOTMETA V2.0
|
||||
#
|
||||
# Data used by ansibot to identify who works on each file in the repo.
|
||||
# If you have questions about this data format, please join #ansible-devel
|
||||
# on irc.freenode and ping anyone who is op'ed.
|
||||
#
|
||||
# There are 3 primary sections of the data
|
||||
#
|
||||
# automerge
|
||||
# During release freezes, the bot uses this key to know if
|
||||
# automerging should be on or off. It is a boolean value.
|
||||
#
|
||||
# macros
|
||||
# Macros are used to shorten and group some strings and lists.
|
||||
# Any macro with a prefix of "team_" is a maintainer group for
|
||||
# various files.
|
||||
#
|
||||
# files
|
||||
# Each key represents a specific file in the repository.
|
||||
# If a module is not listed, it's maintainers default to the authors
|
||||
# If the file has no maintainers key, the value of the key is
|
||||
# presumed to be the maintainers.
|
||||
#
|
||||
# Keys:
|
||||
# maintainers - these people can shipit and automerge
|
||||
# notified - these people are always subscribed to relevant issues
|
||||
# ignored - these people should never be notified
|
||||
# deprecated - this file is deprecated but probably not yet renamed
|
||||
# keywords - used to identify this file based on the issue description
|
||||
# support - used for files without internal metadata
|
||||
# labels - list of GitHub labels to apply. Path components of 'file' parent key
|
||||
# which are valid GitHub labels are automatically added.
|
||||
#
|
||||
|
||||
automerge: True
|
||||
files:
|
||||
.github/BOTMETA.yml:
|
||||
labels: botmeta
|
||||
$modules/cloud/amazon/:
|
||||
ignored: erydo seiffert simplesteph
|
||||
$modules/cloud/amazon/aws_api_gateway.py: willthames
|
||||
$modules/cloud/amazon/aws_kms.py: willthames
|
||||
$modules/cloud/amazon/cloudformation.py: ryansb tedder
|
||||
$modules/cloud/amazon/cloudfront_facts.py: willthames
|
||||
$modules/cloud/amazon/cloudtrail.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_ami.py: willthames
|
||||
$modules/cloud/amazon/ec2_asg.py: $team_ansible s-hertel ryansb
|
||||
$modules/cloud/amazon/ec2_group.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_group_facts.py: willthames
|
||||
$modules/cloud/amazon/ec2_instance.py: Shaps
|
||||
$modules/cloud/amazon/ec2_instance_facts.py: willthames
|
||||
$modules/cloud/amazon/ec2_key.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_lc.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_lc_facts.py: willthames
|
||||
$modules/cloud/amazon/ec2_metric_alarm.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_tag.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_vol.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_vpc_endpoint.py: willthames
|
||||
$modules/cloud/amazon/ec2_vpc_endpoint_facts.py: willthames
|
||||
$modules/cloud/amazon/ec2_vpc_igw.py: willthames
|
||||
$modules/cloud/amazon/ec2_vpc_igw_facts.py: willthames
|
||||
$modules/cloud/amazon/ec2_vpc_nat_gateway_facts.py: willthames
|
||||
$modules/cloud/amazon/ec2_vpc_net.py: $team_ansible
|
||||
$modules/cloud/amazon/ec2_vpc_net_facts.py: whiter
|
||||
$modules/cloud/amazon/ec2_vpc_peering_facts.py: willthames
|
||||
$modules/cloud/amazon/ec2_vpc_subnet.py: willthames
|
||||
$modules/cloud/amazon/ecs_cluster.py: willthames
|
||||
$modules/cloud/amazon/ecs_ecr.py: willthames
|
||||
$modules/cloud/amazon/ecs_service.py: willthames
|
||||
$modules/cloud/amazon/ecs_service_facts.py: willthames
|
||||
$modules/cloud/amazon/ecs_task.py: willthames
|
||||
$modules/cloud/amazon/ecs_taskdefinition.py: willthames
|
||||
$modules/cloud/amazon/ecs_taskdefinition_facts.py: willthames
|
||||
$modules/cloud/amazon/elasticache.py: alachaum
|
||||
$modules/cloud/amazon/elb_target_group_facts.py: willthames
|
||||
$modules/cloud/amazon/iam.py: $team_ansible
|
||||
$modules/cloud/amazon/iam_cert.py: $team_ansible
|
||||
$modules/cloud/amazon/iam_group.py: willthames
|
||||
$modules/cloud/amazon/iam_managed_policy.py: willthames
|
||||
$modules/cloud/amazon/iam_policy.py: $team_ansible
|
||||
$modules/cloud/amazon/rds_param_group.py: scottanderson42
|
||||
$modules/cloud/amazon/rds_subnet_group.py: scottanderson42
|
||||
$modules/cloud/amazon/route53_health_check.py: willthames
|
||||
$modules/cloud/amazon/sns.py: willthames
|
||||
$modules/cloud/amazon/sns_topic.py: willthames
|
||||
$modules/cloud/atomic/: krsacme
|
||||
$modules/cloud/azure/:
|
||||
ignored: chouseknecht jwhitbeck
|
||||
maintainers: $team_azure
|
||||
$modules/cloud/azure/azure_rm_dnsrecordset.py:
|
||||
ignored: ozboms
|
||||
$modules/cloud/centurylink/: clc-runner
|
||||
$modules/cloud/cloudstack/: $team_cloudstack
|
||||
$modules/cloud/digital_ocean/: BondAnthony
|
||||
$modules/cloud/digital_ocean/digital_ocean.py: alukovenko
|
||||
$modules/cloud/digital_ocean/digital_ocean_domain.py: alukovenko
|
||||
$modules/cloud/digital_ocean/digital_ocean_sshkey.py: alukovenko mgregson
|
||||
$modules/cloud/dimensiondata/dimensiondata_network.py: tintoy
|
||||
$modules/cloud/docker/:
|
||||
ignored: ThomasSteinbach
|
||||
$modules/cloud/docker/docker_container.py: $team_ansible felixfontein
|
||||
$modules/cloud/docker/docker_image.py: $team_ansible
|
||||
$modules/cloud/docker/docker_image_facts.py: $team_ansible
|
||||
$modules/cloud/docker/docker_network.py: olsaki
|
||||
$modules/cloud/docker/docker_service.py: $team_ansible
|
||||
$modules/cloud/google/:
|
||||
maintainers: rambleraptor erjohnso
|
||||
ignored: supertom
|
||||
$modules/cloud/google/gc_storage.py: supertom
|
||||
$modules/cloud/linode/linode.py: intheclouddan rwaweber
|
||||
$modules/cloud/lxd/: hnakamur
|
||||
$modules/cloud/memset/: analbeard
|
||||
$modules/cloud/misc/ovirt.py:
|
||||
ignored: vincentvdk
|
||||
maintainers: joshainglis karmab machacekondra mwperina
|
||||
$modules/cloud/misc/virt.py: $team_ansible
|
||||
$modules/cloud/misc/xenserver_facts.py:
|
||||
ignored: andyhky
|
||||
$modules/cloud/opennebula/: ilicmilan kustodian
|
||||
$modules/cloud/openstack/: $team_openstack
|
||||
$modules/cloud/ovirt/: machacekondra mwperina
|
||||
$modules/cloud/profitbricks/: baldwinSPC
|
||||
$modules/cloud/rackspace/:
|
||||
ignored: sivel angstwad
|
||||
$modules/cloud/univention/: 2-B
|
||||
$modules/cloud/vmware/:
|
||||
maintainers: $team_vmware
|
||||
ignored: jcpowermac mtnbikenc
|
||||
$modules/cloud/vmware/vmware_host.py: dagwieers
|
||||
$modules/cloud/vmware/vmware_vm_shell.py: chrrrles
|
||||
$modules/cloud/vmware/_vsphere_guest.py: dagwieers
|
||||
$modules/cloud/vultr/: $team_vultr
|
||||
$modules/cloud/webfaction/: quentinsf
|
||||
$modules/clustering/k8s/: chouseknecht maxamillion fabianvf flaper87 willthames
|
||||
$modules/clustering/k8s/_kubernetes.py: supertom
|
||||
$modules/clustering/openshift/: chouseknecht maxamillion fabianvf flaper87
|
||||
$modules/commands/command.py: $team_ansible
|
||||
$modules/commands/raw.py: $team_ansible
|
||||
$modules/commands/script.py: $team_ansible
|
||||
$modules/commands/shell.py: $team_ansible
|
||||
$modules/crypto/: Spredzy
|
||||
$modules/crypto/acme/: resmo felixfontein
|
||||
$modules/database/influxdb/: kamsz
|
||||
$modules/database/mssql/mssql_db.py: Jmainguy kenichi-ogawa-1988
|
||||
$modules/database/postgresql/: matburt
|
||||
$modules/database/postgresql/postgresql_db.py: $team_ansible
|
||||
$modules/database/postgresql/postgresql_user.py: $team_ansible nerzhul
|
||||
$modules/database/proxysql/: bmildren
|
||||
$modules/database/vertica/: dareko
|
||||
$modules/files/acl.py:
|
||||
ignored: astorije
|
||||
maintainers: $team_ansible
|
||||
$modules/files/assemble.py: $team_ansible
|
||||
$modules/files/copy.py: $team_ansible
|
||||
$modules/files/fetch.py: $team_ansible
|
||||
$modules/files/file.py: $team_ansible
|
||||
$modules/files/find.py: $team_ansible
|
||||
$modules/files/lineinfile.py: $team_ansible samdoran
|
||||
$modules/files/synchronize.py: $team_ansible
|
||||
$modules/files/template.py: $team_ansible
|
||||
$modules/files/unarchive.py:
|
||||
ignored: dagwieers
|
||||
labels: m:unarchive
|
||||
maintainers: pileofrogs
|
||||
$modules/files/xattr.py: $team_ansible
|
||||
$modules/files/xml.py:
|
||||
ignored: magnus919
|
||||
labels: m:xml
|
||||
maintainers: sm4rk0 cmprescott
|
||||
$modules/identity/cyberark/:
|
||||
notified: cyberark-bizdev
|
||||
$modules/identity/ipa/: $team_ipa
|
||||
$modules/identity/keycloak/: eikef
|
||||
$modules/inventory/add_host.py: $team_ansible
|
||||
$modules/inventory/group_by.py: $team_ansible
|
||||
$modules/messaging/rabbitmq_binding.py: $team_rabbitmq
|
||||
$modules/messaging/rabbitmq_exchange.py: $team_rabbitmq
|
||||
$modules/messaging/rabbitmq_parameter.py: $team_rabbitmq
|
||||
$modules/messaging/rabbitmq_plugin.py: $team_rabbitmq
|
||||
$modules/messaging/rabbitmq_policy.py: retr0h
|
||||
$modules/messaging/rabbitmq_queue.py: $team_rabbitmq
|
||||
$modules/messaging/rabbitmq_user.py: $team_rabbitmq
|
||||
$modules/messaging/rabbitmq_vhost.py:
|
||||
ignored: choffman
|
||||
maintainers: $team_rabbitmq
|
||||
$modules/monitoring/datadog_event.py:
|
||||
ignored: arturaz
|
||||
$modules/monitoring/logentries.py:
|
||||
ignored: ivanvanderbyl
|
||||
$modules/monitoring/monit.py: brian-brazil
|
||||
$modules/monitoring/zabbix/: eikef D3DeFi
|
||||
$modules/net_tools/basics/get_url.py: ptux
|
||||
$modules/net_tools/basics/slurp.py: $team_ansible
|
||||
$modules/net_tools/basics/uri.py: $team_ansible
|
||||
$modules/net_tools/cloudflare_dns.py: andreaso
|
||||
$modules/net_tools/exoscale/: resmo
|
||||
$modules/net_tools/ldap/: jtyr
|
||||
$modules/net_tools/lldp.py:
|
||||
ignored: andyhky
|
||||
$modules/net_tools/nios/:
|
||||
maintainers: $team_networking sganesh-infoblox
|
||||
labels:
|
||||
- networking
|
||||
- infoblox
|
||||
$modules/network/a10/: ericchou1 mischapeters
|
||||
$modules/network/aci/: $team_aci
|
||||
$modules/network/aireos/: jmighion
|
||||
$modules/network/aos/: dgarros jeremyschulman
|
||||
$modules/network/aruba/: jmighion
|
||||
$modules/network/asa/: ogenstad gdpak
|
||||
$modules/network/avi/: $team_avi
|
||||
$modules/network/bigswitch/: jayakody tedelhourani vuile
|
||||
$modules/network/citrix/netscaler.py: $team_ansible
|
||||
$modules/network/cloudengine/: QijunPan
|
||||
$modules/network/cnos/: dkasberg amuraleedhar
|
||||
$modules/network/cumulus/: $team_cumulus
|
||||
$modules/network/dellos10/: skg-net
|
||||
$modules/network/dellos6/: abirami-n skg-net
|
||||
$modules/network/dellos9/: dhivyap skg-net
|
||||
$modules/network/edgeos/: samdoran
|
||||
$modules/network/enos/: amuraleedhar
|
||||
$modules/network/eos/: trishnaguha
|
||||
$modules/network/exos/: rdvencioneck
|
||||
$modules/network/f5/:
|
||||
ignored: Etienne-Carriere mhite mryanlam perzizzle srvg wojtek0806 JoeReifel $team_networking
|
||||
maintainers: caphrim007
|
||||
$modules/network/files/: $team_networking
|
||||
$modules/network/fortios/: bjolivot
|
||||
$modules/network/illumos/: xen0l
|
||||
$modules/network/interface/: $team_networking
|
||||
$modules/network/ios/: rcarrillocruz
|
||||
$modules/network/iosxr/: rcarrillocruz gdpak
|
||||
$modules/network/ironware/: paulquack
|
||||
$modules/network/junos/: Qalthos ganeshrn
|
||||
$modules/network/layer2/: $team_networking
|
||||
$modules/network/layer3/: $team_networking
|
||||
$modules/network/meraki/: $team_meraki
|
||||
$modules/network/netconf/netconf_config.py: userlerueda $team_networking
|
||||
$modules/network/netconf/netconf_get.py: $team_networking
|
||||
$modules/network/netconf/netconf_rpc.py: $team_networking
|
||||
$modules/network/netscaler/: $team_netscaler
|
||||
$modules/network/netvisor/: $team_netvisor
|
||||
$modules/network/nos/: $team_extreme
|
||||
$modules/network/nuage/: pdellaert
|
||||
$modules/network/nxos/: $team_nxos
|
||||
$modules/network/nso/: $team_nso
|
||||
$modules/network/onyx/: $team_onyx
|
||||
$modules/network/openvswitch/:
|
||||
ignored: stygstra
|
||||
maintainers: $team_networking
|
||||
$modules/network/ordnance/: alexanderturner djh00t
|
||||
$modules/network/opx/: $team_dell
|
||||
$modules/network/ovs/:
|
||||
ignored: stygstra
|
||||
maintainers: rcarrillocruz
|
||||
$modules/network/panos/: ivanbojer jtschichold
|
||||
$modules/network/panos/panos_address.py: itdependsnetworks ivanbojer jtschichold
|
||||
$modules/network/protocol/: $team_networking
|
||||
$modules/network/routeros/: heuels
|
||||
$modules/network/routing/: $team_networking
|
||||
$modules/network/slxos/: $team_extreme
|
||||
$modules/network/sros/: privateip
|
||||
$modules/network/system/: $team_networking
|
||||
$modules/network/voss/: $team_extreme
|
||||
$modules/network/vyos/: Qalthos samdoran
|
||||
$modules/notification/osx_say.py: $team_ansible
|
||||
$modules/notification/rocketchat.py:
|
||||
ignored: ramondelafuente
|
||||
maintainers: Deepakkothandan
|
||||
$modules/packaging/language/gem.py: $team_ansible
|
||||
$modules/packaging/language/maven_artifact.py:
|
||||
ignored: chrisisbeef
|
||||
maintainers: tumbl3w33d turb
|
||||
$modules/packaging/language/npm.py:
|
||||
ignored: chrishoffman
|
||||
maintainers: shane-walker xcambar
|
||||
$modules/packaging/language/pip.py: lujeni robinro
|
||||
$modules/packaging/os/apk.py:
|
||||
ignored: kbrebanov
|
||||
maintainers: tdtrask
|
||||
$modules/packaging/os/apt.py: $team_ansible
|
||||
$modules/packaging/os/apt_repository.py: $team_ansible
|
||||
$modules/packaging/os/package.py: $team_ansible
|
||||
$modules/packaging/os/pacman.py:
|
||||
ignored: elasticdog
|
||||
$modules/packaging/os/pkgin.py: troy2914
|
||||
$modules/packaging/os/pkgng.py:
|
||||
ignored: bleader
|
||||
maintainers: JoergFiedler
|
||||
$modules/packaging/os/pkgutil.py: scathatheworm
|
||||
$modules/packaging/os/portage.py:
|
||||
ignored: sayap
|
||||
$modules/packaging/os/redhat_subscription.py: alikins kahowell
|
||||
$modules/packaging/os/rhn_channel.py: alikins
|
||||
$modules/packaging/os/rhn_register.py: $team_rhn
|
||||
$modules/packaging/os/yum.py: $team_ansible kustodian
|
||||
$modules/packaging/os/zypper.py:
|
||||
ignored: dirtyharrycallahan
|
||||
$modules/packaging/os/zypper_repository.py: robinro
|
||||
$modules/remote_management/foreman/: ehelms
|
||||
$modules/remote_management/hpilo/: dagwieers haad
|
||||
$modules/remote_management/imc/: dagwieers
|
||||
$modules/remote_management/ipmi/: cloudnull
|
||||
$modules/remote_management/manageiq/: $team_manageiq
|
||||
$modules/remote_management/stacki/stacki_host.py: bbyhuy bsanders
|
||||
$modules/remote_management/ucs/: $team_ucs
|
||||
$modules/source_control/git.py: $team_ansible
|
||||
$modules/source_control/github_key.py:
|
||||
ignored: erydo
|
||||
$modules/storage/infinidat/: GR360RY vmalloc
|
||||
$modules/storage/netapp/: $team_netapp
|
||||
$modules/storage/purestorage/: sdodsley
|
||||
$modules/system/at.py: $team_ansible
|
||||
$modules/system/authorized_key.py: $team_ansible
|
||||
$modules/system/facter.py: $team_ansible
|
||||
$modules/system/filesystem.py: pilou-
|
||||
$modules/system/gconftool2.py: Akasurde
|
||||
$modules/system/group.py: $team_ansible
|
||||
$modules/system/interfaces_file.py: obourdon
|
||||
$modules/system/modprobe.py:
|
||||
ignored: stygstra
|
||||
$modules/system/mount.py: $team_ansible jtyr
|
||||
$modules/system/ohai.py: $team_ansible
|
||||
$modules/system/osx_defaults.py:
|
||||
ignored: frenck
|
||||
maintainers: $team_ansible
|
||||
$modules/system/pam_limits.py:
|
||||
ignored: usawa
|
||||
maintainers: giovannisciortino
|
||||
$modules/system/ping.py: $team_ansible
|
||||
$modules/system/puppet.py: nibalizer
|
||||
$modules/system/seboolean.py: $team_ansible
|
||||
$modules/system/selinux.py: samdoran
|
||||
$modules/system/service.py: $team_ansible
|
||||
$modules/system/setup.py:
|
||||
ignored: david_obrien
|
||||
maintainers: $team_ansible
|
||||
$modules/system/sysctl.py: Akasurde
|
||||
$modules/system/systemd.py: $team_ansible
|
||||
$modules/system/user.py: $team_ansible samdoran
|
||||
$modules/utilities/helper/meta.py: $team_ansible
|
||||
$modules/utilities/logic/assert.py: $team_ansible
|
||||
$modules/utilities/logic/async_status.py: $team_ansible
|
||||
$modules/utilities/logic/async_wrapper.py: $team_ansible
|
||||
$modules/utilities/logic/include.py: $team_ansible
|
||||
$modules/utilities/logic/include_role.py: $team_ansible
|
||||
$modules/utilities/logic/include_vars.py: $team_ansible
|
||||
$modules/utilities/logic/pause.py: samdoran
|
||||
$modules/utilities/logic/wait_for.py: gregswift
|
||||
$modules/web_infrastructure/ansible_tower/: $team_tower
|
||||
$modules/web_infrastructure/django_manage.py: scottanderson42
|
||||
$modules/web_infrastructure/htpasswd.py: $team_ansible
|
||||
$modules/web_infrastructure/jboss/: $team_jboss
|
||||
$modules/web_infrastructure/jira.py: Slezhuk
|
||||
$modules/windows/:
|
||||
maintainers: $team_windows
|
||||
ignored: angstwad georgefrank h0nIg
|
||||
$modules/windows/win_security_policy.py: rndmh3ro defionscode
|
||||
bin/ansible-connection:
|
||||
keywords:
|
||||
- persistent connection
|
||||
labels:
|
||||
- networking
|
||||
maintainers: $team_networking
|
||||
contrib/inventory:
|
||||
keywords:
|
||||
- dynamic inventory script
|
||||
- dynamic inventory
|
||||
- inventory script
|
||||
labels: c:inventory/contrib_script
|
||||
support: community
|
||||
contrib/inventory/digital_ocean.py:
|
||||
keywords:
|
||||
- digital_ocean dynamic inventory script
|
||||
maintainers: BondAnthony
|
||||
labels:
|
||||
- cloud
|
||||
support: community
|
||||
contrib/inventory/linode.py:
|
||||
keywords:
|
||||
- linode dynamic inventory script
|
||||
maintainers: intheclouddan rwaweber zbal
|
||||
labels: cloud
|
||||
contrib/inventory/openstack.py:
|
||||
keywords:
|
||||
- openstack dynamic inventory script
|
||||
maintainers: $team_openstack
|
||||
labels:
|
||||
- cloud
|
||||
contrib/inventory/infoblox.py:
|
||||
keywords:
|
||||
- infoblox dynamic inventory script
|
||||
labels:
|
||||
- ipam
|
||||
- networking
|
||||
maintainers: $team_networking
|
||||
contrib/inventory/azure_rm.py:
|
||||
keywords:
|
||||
- azure inventory
|
||||
- azure rm inventory
|
||||
- azure azure_rm dynamic inventory script
|
||||
labels:
|
||||
- cloud
|
||||
- azure
|
||||
maintainers: $team_azure
|
||||
contrib/inventory/ec2:
|
||||
keywords:
|
||||
- aws dynamic inventory
|
||||
- aws inventory
|
||||
- ec2 inventory
|
||||
- ec2 dynamic inventory
|
||||
- ec2.py dynamic inventory script
|
||||
- ec2.py inventory script
|
||||
- ec2.py inventory
|
||||
labels:
|
||||
- cloud
|
||||
- aws
|
||||
notify: ryansb s-hertel willthames
|
||||
contrib/inventory/vmware.py:
|
||||
keywords:
|
||||
- vmware inventory
|
||||
- vmware dynamic inventory script
|
||||
labels:
|
||||
- cloud
|
||||
maintainers: $team_vmware
|
||||
contrib/inventory/vmware_inventory.py:
|
||||
keywords:
|
||||
- vmware inventory
|
||||
- vmware dynamic inventory script
|
||||
labels:
|
||||
- cloud
|
||||
- vmware
|
||||
maintainers: $team_vmware
|
||||
lib/ansible/inventory:
|
||||
keywords:
|
||||
- core inventory
|
||||
- inventory
|
||||
- inventory parsing
|
||||
$module_utils/net_tools/nios/:
|
||||
labels:
|
||||
- networking
|
||||
- infoblox
|
||||
maintainers: $team_networking sganesh-infoblox
|
||||
$module_utils/network/a10:
|
||||
maintainers: ericchou1 mischapeters
|
||||
labels: networking
|
||||
$module_utils/network/aci:
|
||||
maintainers: $team_aci
|
||||
labels: networking
|
||||
support: community
|
||||
$module_utils/acme.py:
|
||||
maintainers: resmo felixfontein
|
||||
$module_utils/ipa.py:
|
||||
maintainers: $team_ipa
|
||||
$module_utils/network/aireos:
|
||||
maintainers: jmighion
|
||||
labels: networking
|
||||
$module_utils/network/aos:
|
||||
maintainers: dgarros jeremyschulman
|
||||
labels: networking
|
||||
$module_utils/azure_rm_common.py:
|
||||
maintainers: $team_azure
|
||||
labels:
|
||||
- azure
|
||||
- cloud
|
||||
$module_utils/network/aruba:
|
||||
maintainers: jmighion
|
||||
labels: networking
|
||||
$module_utils/network/asa:
|
||||
maintainers: ogenstad gdpak
|
||||
labels: networking
|
||||
$module_utils/network/avi:
|
||||
maintainers: $team_avi
|
||||
labels: networking
|
||||
$module_utils/network/bigswitch:
|
||||
maintainers: jayakody tedelhourani vuile
|
||||
labels: networking
|
||||
$module_utils/network/cloudengine:
|
||||
maintainers: QijunPan
|
||||
labels: networking
|
||||
$module_utils/cloudstack.py:
|
||||
maintainers: $team_cloudstack
|
||||
labels: cloudstack
|
||||
$module_utils/network/cnos:
|
||||
maintainers: dkasberg amuraleedhar
|
||||
labels: networking
|
||||
$module_utils/crypto.py:
|
||||
maintainers: Spredzy
|
||||
$module_utils/network/dellos6:
|
||||
maintainers: skg-net
|
||||
labels: networking
|
||||
$module_utils/network/dellos9:
|
||||
maintainers: skg-net
|
||||
labels: networking
|
||||
$module_utils/network/dellos10:
|
||||
maintainers: skg-net
|
||||
labels: networking
|
||||
$module_utils/network/enos:
|
||||
maintainers: amuraleedhar
|
||||
labels: networking
|
||||
$module_utils/network/exos:
|
||||
maintainers: rdvencioneck
|
||||
labels: networking
|
||||
$module_utils/f5_utils.py:
|
||||
maintainers: caphrim007
|
||||
labels:
|
||||
- f5
|
||||
- networking
|
||||
$module_utils/network/fortios:
|
||||
maintainers: bjolivot
|
||||
labels: networking
|
||||
$module_utils/network/ironware:
|
||||
maintainers: paulquack
|
||||
labels: networking
|
||||
$module_utils/k8s:
|
||||
maintainers: chouseknecht maxamillion fabianvf flaper87 willthames
|
||||
labels: clustering
|
||||
$module_utils/keycloak.py:
|
||||
maintainers: eikef
|
||||
$module_utils/manageiq.py:
|
||||
maintainers: $team_manageiq
|
||||
$module_utils/network/meraki:
|
||||
maintainers: $team_meraki
|
||||
labels: networking
|
||||
support: community
|
||||
$module_utils/network/netconf:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
$module_utils/network/netscaler:
|
||||
maintainers: $team_netscaler
|
||||
labels: networking
|
||||
$module_utils/network/nos:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
$module_utils/network/nso:
|
||||
maintainers: $team_nso
|
||||
labels: networking
|
||||
$module_utils/network/onyx:
|
||||
maintainers: $team_onyx
|
||||
labels: networking
|
||||
$module_utils/network/routeros:
|
||||
maintainers: heuels
|
||||
labels: networking
|
||||
$module_utils/network/slxos:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
$module_utils/openstack.py:
|
||||
maintainers: $team_openstack
|
||||
labels:
|
||||
- cloud
|
||||
$module_utils/network/ordnance:
|
||||
maintainers: alexanderturner djh00t
|
||||
labels: networking
|
||||
$module_utils/ovirt.py:
|
||||
maintainers: joshainglis karmab machacekondra
|
||||
labels:
|
||||
- cloud
|
||||
$module_utils/powershell:
|
||||
maintainers: $team_windows_core
|
||||
labels:
|
||||
- windows
|
||||
$module_utils/remote_management/ucs:
|
||||
maintainers: $team_ucs
|
||||
labels: ucs
|
||||
$module_utils/netapp: $team_netapp
|
||||
$module_utils/vultr.py: &vultr
|
||||
maintainers: $team_vultr
|
||||
labels:
|
||||
- cloud
|
||||
$module_utils/vmware:
|
||||
maintainers: $team_vmware
|
||||
support: community
|
||||
$module_utils/network/voss:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
$module_utils/network:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
$module_utils/onepassword.py:
|
||||
maintainers: samdoran
|
||||
$module_utils/memset.py:
|
||||
maintainers: analbeard
|
||||
labels: cloud
|
||||
$module_utils/jboss/:
|
||||
maintainers: $team_jboss
|
||||
$module_utils/scaleway.py: &scaleway
|
||||
maintainers: $team_scaleway
|
||||
labels:
|
||||
- cloud
|
||||
support: community
|
||||
lib/ansible/playbook/handler.py:
|
||||
keywords:
|
||||
- handlers
|
||||
lib/ansible/playbook/role:
|
||||
keywords:
|
||||
- roles path
|
||||
- roles_path
|
||||
- role
|
||||
- role path
|
||||
lib/ansible/playbook/role/include.py:
|
||||
keywords:
|
||||
- include role
|
||||
- include_role
|
||||
- role include
|
||||
lib/ansible/playbook/role/requirement.py:
|
||||
keywords:
|
||||
- role dependencies
|
||||
- role dep
|
||||
- role dependency
|
||||
lib/ansible/plugins/action/asa:
|
||||
maintainers: ogenstad gdpak
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/aireos:
|
||||
maintainers: jmighion
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/aruba:
|
||||
maintainers: jmighion
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/dellos:
|
||||
maintainers: skg-net
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/eos:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/ios:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/ironware:
|
||||
maintainers: paulquack
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/junos:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/net:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/nxos:
|
||||
maintainers: $team_networking
|
||||
labels:
|
||||
- networking
|
||||
- nxos
|
||||
lib/ansible/plugins/action/onyx_config.py:
|
||||
maintainers: $team_onyx
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/sros:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/action/vyos:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/callback/unixy.py:
|
||||
support: community
|
||||
maintainers: akatch
|
||||
lib/ansible/plugins/callback/grafana_annotations.py:
|
||||
support: community
|
||||
maintainers: rrey
|
||||
lib/ansible/plugins/callback/sumologic.py:
|
||||
support: community
|
||||
maintainers: ryancurrah
|
||||
lib/ansible/plugins/cliconf/:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/cliconf/exos.py:
|
||||
maintainers: rdvencioneck
|
||||
labels: networking
|
||||
lib/ansible/plugins/cliconf/ironware.py:
|
||||
maintainers: paulquack
|
||||
labels: networking
|
||||
lib/ansible/plugins/cliconf/nos.py:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
lib/ansible/plugins/cliconf/nxos.py:
|
||||
maintainers: $team_nxos
|
||||
labels:
|
||||
- networking
|
||||
lib/ansible/plugins/cliconf/onyx.py:
|
||||
maintainers: $team_onyx
|
||||
labels: networking
|
||||
lib/ansible/plugins/cliconf/routeros.py:
|
||||
maintainers: heuels
|
||||
labels: networking
|
||||
lib/ansible/plugins/cliconf/slxos.py:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
lib/ansible/plugins/connection/lxd.py:
|
||||
maintainers: mattclay
|
||||
lib/ansible/plugins/connection/netconf.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/connection/network_cli.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/connection/persistent.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/httpapi/ftd.py:
|
||||
maintainers: annikulin $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/inventory/openstack.py:
|
||||
maintainers: $team_openstack
|
||||
keywords:
|
||||
- openstack
|
||||
- inventory
|
||||
labels:
|
||||
- cloud
|
||||
lib/ansible/plugins/cliconf/voss.py:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
lib/ansible/plugins/connection/winrm.py:
|
||||
maintainers: $team_windows_core
|
||||
labels:
|
||||
- windows
|
||||
lib/ansible/plugins/inventory/ovirt4.py:
|
||||
maintainers: machacekondra
|
||||
labels:
|
||||
- ovirt
|
||||
- cloud
|
||||
lib/ansible/plugins/inventory/vultr.py: *vultr
|
||||
lib/ansible/plugins/inventory/scaleway.py: *scaleway
|
||||
lib/ansible/plugins/filter/network.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/lookup/nios.py:
|
||||
maintainers: $team_networking sganesh-infoblox
|
||||
labels:
|
||||
- networking
|
||||
- infoblox
|
||||
lib/ansible/plugins/lookup/nios_next_ip.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/lookup/dig:
|
||||
maintainers: jpmens
|
||||
labels: community
|
||||
lib/ansible/plugins/lookup/conjur_variable.py:
|
||||
maintainers: $team_cyberark_conjur
|
||||
notified: cyberark-bizdev
|
||||
lib/ansible/plugins/lookup/cyberarkpassword.py:
|
||||
notified: cyberark-bizdev
|
||||
lib/ansible/plugins/netconf/:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/lookup/onepassword.py:
|
||||
maintainers: samdoran
|
||||
ignored: azenk
|
||||
lib/ansible/plugins/lookup/onepassword_raw.py:
|
||||
maintainers: samdoran
|
||||
ignored: azenk
|
||||
lib/ansible/plugins/netconf/sros.py:
|
||||
maintainers: wisotzky $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/shell/powershell.py:
|
||||
maintainers: $team_windows_core
|
||||
labels:
|
||||
- windows
|
||||
lib/ansible/plugins/terminal/aireos.py:
|
||||
maintainers: jmighion
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/aruba.py:
|
||||
maintainers: jmighion
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/asa.py:
|
||||
maintainers: ogenstad gdpak
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/dellos10:
|
||||
maintainers: skg-net
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/edgeos.py:
|
||||
maintainers: samdoran
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/eos.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/exos.py:
|
||||
maintainers: rdvencioneck
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/ios.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/iosxr.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/ironware.py:
|
||||
maintainers: paulquack
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/junos.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/nos.py:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/nxos.py:
|
||||
maintainers: $team_networking
|
||||
labels:
|
||||
- networking
|
||||
lib/ansible/plugins/terminal/onyx.py:
|
||||
maintainers: $team_onyx
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/routeros.py:
|
||||
maintainers: heuels
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/slxos.py:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/sros.py:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/voss.py:
|
||||
maintainers: $team_extreme
|
||||
labels: networking
|
||||
lib/ansible/plugins/terminal/vyos.py:
|
||||
maintainers: $team_networking samdoran
|
||||
labels: networking
|
||||
lib/ansible/release.py:
|
||||
notify: mattclay nitzmahone
|
||||
lib/ansible/template:
|
||||
keywords:
|
||||
- jinja
|
||||
- jinja2
|
||||
lib/ansible/utils/module_docs_fragments/acme.py:
|
||||
maintainers: resmo felixfontein
|
||||
test/sanity/validate-modules:
|
||||
keywords:
|
||||
- validate-modules
|
||||
docs/:
|
||||
maintainers:
|
||||
- acozine
|
||||
docs/docsite/rst/network/:
|
||||
labels: networking
|
||||
maintainers:
|
||||
- samccann
|
||||
- gundalow
|
||||
docs/docsite/rst/scenario_guides/guide_aci.rst:
|
||||
maintainers: $team_aci
|
||||
labels:
|
||||
- aci
|
||||
- networking
|
||||
packaging/:
|
||||
test/:
|
||||
# 'test' is a component path, then 'test' label will be automatically added
|
||||
test/runner/:
|
||||
notify: mattclay
|
||||
test/sanity/:
|
||||
notify: mattclay
|
||||
test/utils/shippable/:
|
||||
notify: mattclay
|
||||
test/integration/group_vars/:
|
||||
notify: mattclay
|
||||
test/integration/host_vars/:
|
||||
notify: mattclay
|
||||
test/integration/roles/:
|
||||
notify: mattclay
|
||||
test/integration/targets/aci:
|
||||
maintainers: $team_aci
|
||||
labels:
|
||||
- networking
|
||||
test/integration/targets/meraki:
|
||||
maintainers: $team_meraki
|
||||
labels:
|
||||
- networking
|
||||
test/integration/targets/nxos:
|
||||
maintainers: $team_nxos
|
||||
labels:
|
||||
- networking
|
||||
test/integration/targets/setup_acme:
|
||||
maintainers: resmo felixfontein
|
||||
test/integration/targets/setup_zabbix:
|
||||
maintainers: eikef D3DeFi
|
||||
test/integration/targets/ucs:
|
||||
maintainers: $team_ucs
|
||||
labels:
|
||||
- remote_management
|
||||
test/units/modules/network:
|
||||
maintainers: $team_networking
|
||||
labels: networking
|
||||
test/units/modules/network/nxos:
|
||||
maintainers: $team_nxos
|
||||
labels:
|
||||
- networking
|
||||
test/sanity/pep8/legacy-files.txt:
|
||||
hacking/report.py:
|
||||
notify: mattclay
|
||||
shippable.yml:
|
||||
notify: mattclay
|
||||
.yamllint:
|
||||
notify: mattclay
|
||||
tox.ini:
|
||||
notify: mattclay
|
||||
macros:
|
||||
module_utils: lib/ansible/module_utils
|
||||
modules: lib/ansible/modules
|
||||
team_aci: brunocalogero dagwieers jmcgill298 schunduri
|
||||
team_ansible: []
|
||||
team_avi: ericsysmin grastogi23 khaltore
|
||||
team_azure: haroldwongms nitzmahone trstringer yuwzho xscript zikalino
|
||||
team_cloudstack: resmo dpassante
|
||||
team_cumulus: isharacomix jrrivers
|
||||
team_cyberark_conjur: jvanderhoof ryanprior
|
||||
team_dell: skg-net manjuv1 dhivyap abirami-n
|
||||
team_extreme: bigmstone LindsayHill
|
||||
team_ipa: Nosmoht Akasurde fxfitz
|
||||
team_jboss: jairojunior wbrefvem Wolfant
|
||||
team_manageiq: gtanzillo abellotti zgalor yaacov cben
|
||||
team_meraki: dagwieers kbreit
|
||||
team_netapp: hulquest lmprice ndswartz amit0701 schmots1 carchi8py
|
||||
team_netscaler: chiradeep giorgos-nikolopoulos
|
||||
team_netvisor: Qalthos amitsi
|
||||
team_networking: Qalthos ganeshrn rcarrillocruz trishnaguha gdpak justjais
|
||||
team_nso: cmoberg cnasten tbjurman
|
||||
team_nxos: mikewiebe rahushen rcarrillocruz trishnaguha tstoner
|
||||
team_onyx: samerd
|
||||
team_openstack: emonty omgjlk juliakreger rcarrillocruz shrews thingee dagnello
|
||||
team_openswitch: Qalthos gdpak
|
||||
team_rabbitmq: chrishoffman manuel-sousa hyperized
|
||||
team_rhn: alikins barnabycourt flossware vritant
|
||||
team_scaleway: sieben hekonsek Spredzy
|
||||
team_tower: ghjm jlaska matburt wwitzel3 simfarm ryanpetrello rooftopcellist AlanCoding
|
||||
team_ucs: dsoper2 johnamcdonough SDBrett vallard vvb dagwieers
|
||||
team_vmware: Akasurde dav1x warthog9
|
||||
team_vultr: resmo Spredzy
|
||||
team_windows: dagwieers jborean93 jhawkesworth nitzmahone
|
||||
team_windows_core: nitzmahone jborean93
|
||||
3
.github/CODE_OF_CONDUCT.md
vendored
3
.github/CODE_OF_CONDUCT.md
vendored
@ -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).
|
||||
25
.github/CONTRIBUTING.md
vendored
25
.github/CONTRIBUTING.md
vendored
@ -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!
|
||||
58
.github/ISSUE_TEMPLATE.md
vendored
58
.github/ISSUE_TEMPLATE.md
vendored
@ -1,58 +0,0 @@
|
||||
<!---
|
||||
Verify first that your issue/request is not already reported on GitHub.
|
||||
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
|
||||
Also test if the latest release, and devel branch are affected too.
|
||||
ALWAYS add information AFTER (OUTSIDE) these html comments.
|
||||
Otherwise it may end up being automatically closed by our bot. -->
|
||||
|
||||
##### SUMMARY
|
||||
<!--- Explain the problem briefly -->
|
||||
|
||||
##### ISSUE TYPE
|
||||
<!--- Pick one below and delete the rest -->
|
||||
- Bug Report
|
||||
- Feature Idea
|
||||
- Documentation Report
|
||||
|
||||
##### COMPONENT NAME
|
||||
<!--- Insert, BELOW THIS COMMENT, the name of the module, plugin, task or feature.
|
||||
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path-->
|
||||
|
||||
##### ANSIBLE VERSION
|
||||
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
##### CONFIGURATION
|
||||
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, the results of "ansible-config dump --only-changed"
|
||||
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
|
||||
(or using the ANSIBLE_* environment variables).-->
|
||||
|
||||
##### OS / ENVIRONMENT
|
||||
<!--- Mention, BELOW THIS COMMENT, the OS you are running Ansible from, and the OS you are
|
||||
managing, or say "N/A" for anything that is not platform-specific.
|
||||
Also mention the specific version of what you are trying to control,
|
||||
e.g. if this is a network bug the version of firmware on the network device.-->
|
||||
|
||||
##### STEPS TO REPRODUCE
|
||||
<!--- For bugs, show exactly how to reproduce the problem, using a minimal test-case.
|
||||
For new features, show how the feature would be used. -->
|
||||
|
||||
<!--- Paste example playbooks or commands between quotes below -->
|
||||
```yaml
|
||||
|
||||
```
|
||||
|
||||
<!--- You can also paste gist.github.com links for larger files -->
|
||||
|
||||
##### EXPECTED RESULTS
|
||||
<!--- What did you expect to happen when running the steps above? -->
|
||||
|
||||
##### ACTUAL RESULTS
|
||||
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
|
||||
|
||||
<!--- Paste verbatim command output between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
61
.github/ISSUE_TEMPLATE/bug_report.md
vendored
61
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,61 +0,0 @@
|
||||
---
|
||||
name: 🐛 Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
<!---
|
||||
Verify first that your issue/request is not already reported on GitHub.
|
||||
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
|
||||
Also test if the latest release, and devel branch are affected too.
|
||||
ALWAYS add information AFTER (OUTSIDE) these html comments.
|
||||
Otherwise it may end up being automatically closed by our bot. -->
|
||||
|
||||
##### SUMMARY
|
||||
<!--- Explain the problem briefly -->
|
||||
|
||||
##### ISSUE TYPE
|
||||
- Bug Report
|
||||
|
||||
##### COMPONENT NAME
|
||||
<!--- Insert, BELOW THIS COMMENT, the name of the module, plugin, task or feature.
|
||||
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path-->
|
||||
|
||||
##### ANSIBLE VERSION
|
||||
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
##### CONFIGURATION
|
||||
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, the results of "ansible-config dump --only-changed"
|
||||
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
|
||||
(or using the ANSIBLE_* environment variables).-->
|
||||
|
||||
##### OS / ENVIRONMENT
|
||||
<!--- Mention, BELOW THIS COMMENT, the OS you are running Ansible from, and the OS you are
|
||||
managing, or say "N/A" for anything that is not platform-specific.
|
||||
Also mention the specific version of what you are trying to control,
|
||||
e.g. if this is a network bug the version of firmware on the network device.-->
|
||||
|
||||
##### STEPS TO REPRODUCE
|
||||
<!--- For bugs, show exactly how to reproduce the problem, using a minimal test-case.
|
||||
For new features, show how the feature would be used. -->
|
||||
|
||||
<!--- Paste example playbooks or commands between quotes below -->
|
||||
```yaml
|
||||
|
||||
```
|
||||
|
||||
<!--- You can also paste gist.github.com links for larger files -->
|
||||
|
||||
##### EXPECTED RESULTS
|
||||
<!--- What did you expect to happen when running the steps above? -->
|
||||
|
||||
##### ACTUAL RESULTS
|
||||
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
|
||||
|
||||
<!--- Paste verbatim command output between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
61
.github/ISSUE_TEMPLATE/documentation_report.md
vendored
61
.github/ISSUE_TEMPLATE/documentation_report.md
vendored
@ -1,61 +0,0 @@
|
||||
---
|
||||
name: 📝 Documentation Report
|
||||
about: Ask us about docs
|
||||
|
||||
---
|
||||
|
||||
<!---
|
||||
Verify first that your issue/request is not already reported on GitHub.
|
||||
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
|
||||
Also test if the latest release, and devel branch are affected too.
|
||||
ALWAYS add information AFTER (OUTSIDE) these html comments.
|
||||
Otherwise it may end up being automatically closed by our bot. -->
|
||||
|
||||
##### SUMMARY
|
||||
<!--- Explain the problem briefly -->
|
||||
|
||||
##### ISSUE TYPE
|
||||
- Documentation Report
|
||||
|
||||
##### COMPONENT NAME
|
||||
<!--- Insert, BELOW THIS COMMENT, the name of the module, plugin, task or feature.
|
||||
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path-->
|
||||
|
||||
##### ANSIBLE VERSION
|
||||
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
##### CONFIGURATION
|
||||
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, the results of "ansible-config dump --only-changed"
|
||||
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
|
||||
(or using the ANSIBLE_* environment variables).-->
|
||||
|
||||
##### OS / ENVIRONMENT
|
||||
<!--- Mention, BELOW THIS COMMENT, the OS you are running Ansible from, and the OS you are
|
||||
managing, or say "N/A" for anything that is not platform-specific.
|
||||
Also mention the specific version of what you are trying to control,
|
||||
e.g. if this is a network bug the version of firmware on the network device.-->
|
||||
|
||||
##### STEPS TO REPRODUCE
|
||||
<!--- For bugs, show exactly how to reproduce the problem, using a minimal test-case.
|
||||
For new features, show how the feature would be used. -->
|
||||
|
||||
<!--- Paste example playbooks or commands between quotes below -->
|
||||
```yaml
|
||||
|
||||
```
|
||||
|
||||
<!--- You can also paste gist.github.com links for larger files -->
|
||||
|
||||
##### EXPECTED RESULTS
|
||||
<!--- What did you expect to happen when running the steps above? -->
|
||||
|
||||
##### ACTUAL RESULTS
|
||||
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
|
||||
|
||||
<!--- Paste verbatim command output between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
61
.github/ISSUE_TEMPLATE/feature_request.md
vendored
61
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,61 +0,0 @@
|
||||
---
|
||||
name: ✨ Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
<!---
|
||||
Verify first that your issue/request is not already reported on GitHub.
|
||||
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
|
||||
Also test if the latest release, and devel branch are affected too.
|
||||
ALWAYS add information AFTER (OUTSIDE) these html comments.
|
||||
Otherwise it may end up being automatically closed by our bot. -->
|
||||
|
||||
##### SUMMARY
|
||||
<!--- Explain the problem briefly -->
|
||||
|
||||
##### ISSUE TYPE
|
||||
- Feature Idea
|
||||
|
||||
##### COMPONENT NAME
|
||||
<!--- Insert, BELOW THIS COMMENT, the name of the module, plugin, task or feature.
|
||||
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path-->
|
||||
|
||||
##### ANSIBLE VERSION
|
||||
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
##### CONFIGURATION
|
||||
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, the results of "ansible-config dump --only-changed"
|
||||
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
|
||||
(or using the ANSIBLE_* environment variables).-->
|
||||
|
||||
##### OS / ENVIRONMENT
|
||||
<!--- Mention, BELOW THIS COMMENT, the OS you are running Ansible from, and the OS you are
|
||||
managing, or say "N/A" for anything that is not platform-specific.
|
||||
Also mention the specific version of what you are trying to control,
|
||||
e.g. if this is a network bug the version of firmware on the network device.-->
|
||||
|
||||
##### STEPS TO REPRODUCE
|
||||
<!--- For bugs, show exactly how to reproduce the problem, using a minimal test-case.
|
||||
For new features, show how the feature would be used. -->
|
||||
|
||||
<!--- Paste example playbooks or commands between quotes below -->
|
||||
```yaml
|
||||
|
||||
```
|
||||
|
||||
<!--- You can also paste gist.github.com links for larger files -->
|
||||
|
||||
##### EXPECTED RESULTS
|
||||
<!--- What did you expect to happen when running the steps above? -->
|
||||
|
||||
##### ACTUAL RESULTS
|
||||
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
|
||||
|
||||
<!--- Paste verbatim command output between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
@ -1,8 +0,0 @@
|
||||
---
|
||||
name: 🔥 Security bug report
|
||||
about: How to report security vulnerabilities
|
||||
---
|
||||
|
||||
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
|
||||
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,33 +0,0 @@
|
||||
##### SUMMARY
|
||||
<!--- Describe the change, including rationale and design decisions -->
|
||||
|
||||
<!--- If you are fixing an existing issue, please include "Fixes #nnn" in your
|
||||
commit message and your description; but you should still explain what
|
||||
the change does.-->
|
||||
|
||||
##### ISSUE TYPE
|
||||
<!--- Pick one below and delete the rest: -->
|
||||
- Feature Pull Request
|
||||
- New Module Pull Request
|
||||
- Bugfix Pull Request
|
||||
- Docs Pull Request
|
||||
|
||||
##### COMPONENT NAME
|
||||
<!--- Name of the module, plugin, task or feature -->
|
||||
|
||||
##### ANSIBLE VERSION
|
||||
<!--- Paste verbatim output from "ansible --version" between quotes below -->
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
|
||||
##### ADDITIONAL INFORMATION
|
||||
<!--- Include additional information to help people understand the change here.
|
||||
For bugs that don't have a linked bug report, a step-by-step reproduction
|
||||
of the problem is helpful. -->
|
||||
|
||||
<!--- Paste verbatim command output below, e.g. before and after your change -->
|
||||
```
|
||||
|
||||
```
|
||||
78
.gitignore
vendored
78
.gitignore
vendored
@ -2,10 +2,9 @@
|
||||
*.py[co]
|
||||
build
|
||||
AUTHORS.TXT
|
||||
# Emacs backup and autosave files...
|
||||
# Emacs backup files...
|
||||
*~
|
||||
.\#*
|
||||
\#*
|
||||
# RPM stuff...
|
||||
MANIFEST
|
||||
dist
|
||||
@ -17,90 +16,37 @@ 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/cli/ansible-*.rst
|
||||
docs/docsite/rst/cli/ansible.rst
|
||||
docs/docsite/rst/dev_guide/testing/sanity/index.rst.new
|
||||
docs/docsite/rst/modules/*.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/
|
||||
deb-build
|
||||
debian/
|
||||
# Vim swap files
|
||||
*.swp
|
||||
*.swo
|
||||
credentials.yml
|
||||
# test output
|
||||
*.retry
|
||||
*.out
|
||||
.pytest_cache/
|
||||
.tox
|
||||
.cache
|
||||
.pytest_cache
|
||||
.coverage
|
||||
results.xml
|
||||
coverage.xml
|
||||
/test/units/cover-html
|
||||
/test/integration/targets/*/backup/
|
||||
/test/cache/*
|
||||
# Development
|
||||
/test/develop
|
||||
venv
|
||||
Vagrantfile
|
||||
.vagrant
|
||||
ansible.egg-info/
|
||||
/shippable/
|
||||
/test/integration/cloud-config-*.*
|
||||
!/test/integration/cloud-config-*.*.template
|
||||
.python-version
|
||||
# Release directory
|
||||
packaging/release/ansible_release
|
||||
/.cache/
|
||||
/test/results/coverage/*=coverage.*
|
||||
/test/results/coverage/coverage*
|
||||
/test/results/reports/coverage*.xml
|
||||
/test/results/reports/coverage*/
|
||||
/test/results/bot/*.json
|
||||
/test/results/junit/*.xml
|
||||
/test/results/logs/*.log
|
||||
/test/results/data/*.json
|
||||
/test/integration/inventory.remote
|
||||
/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
|
||||
|
||||
36
.mailmap
36
.mailmap
@ -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>
|
||||
1281
CHANGELOG.md
Normal file
1281
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,319 @@
|
||||
Coding Guidelines
|
||||
=================
|
||||
|
||||
Hi! Thanks for your interest in contributing to Ansible. We document our Coding Guidelines in the [Developer Guide](https://docs.ansible.com/ansible/devel/dev_guide/). We particularly suggest you review:
|
||||
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!
|
||||
|
||||
|
||||
* [Contributing your module to Ansible](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_checklist.html)
|
||||
|
||||
* [Development conventions, tips and pitfalls](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_best_practices.html)
|
||||
|
||||
Our [Community Guide](https://docs.ansible.com/ansible/devel/community/) may also help you connect with the community of Ansible developers.
|
||||
|
||||
224
CONTRIBUTING.md
Normal file
224
CONTRIBUTING.md
Normal file
@ -0,0 +1,224 @@
|
||||
Ansible Community Information
|
||||
==============================
|
||||
|
||||
The purpose of the Ansible community is to unite developers, system administrators, operations, and
|
||||
IT managers to share and build great automation solutions. This document contains all sorts of
|
||||
information about how to contribute and interact with Ansible. Welcome!
|
||||
|
||||
Ways to Interact
|
||||
================
|
||||
|
||||
There are a lot of ways to join and be a part of the Ansible community, such as:
|
||||
|
||||
Sharing Ansible with Others
|
||||
---------------------------
|
||||
|
||||
You can help share Ansible with others by telling friends and colleagues, writing a blog post,
|
||||
or presenting at user groups (like DevOps groups or the local LUG or BUG). You are also
|
||||
welcome to share slides on speakerdeck, sign up for a free account and tag it “Ansible”. On Twitter,
|
||||
you can also share things with #ansible and may wish
|
||||
to follow [@Ansible](https://twitter.com/ansible).
|
||||
|
||||
Sharing Content and Tips
|
||||
------------------------
|
||||
|
||||
Join the [Ansible project mailing list](https://groups.google.com/forum/#!forum/ansible-project) and you
|
||||
can share playbooks you may have written and other interesting implementation stories. Put your Ansible
|
||||
content up on places like github to share with others.
|
||||
|
||||
Sharing A Feature Idea
|
||||
----------------------
|
||||
|
||||
Ideas are very welcome and the best place to share them is the [Ansible project mailing list](https://groups.google.com/forum/#!forum/ansible-project) ([Subscribe](https://groups.google.com/forum/#!forum/ansible-project/join)) or #ansible on irc.freenode.net.
|
||||
|
||||
While you can file a feature request on GitHub, pull requests are a much better way to get your feature added than submitting a feature request. Open source is all about itch scratching, and it's less likely that someone else will have the same itches as yourself. We keep code reasonably simple on purpose so it's easy to dive in and make additions, but be sure to read the "Contributing Code" section below too -- as it doesn't hurt to have a discussion about a feature first -- we're inclined to have preferences about how incoming features might be implemented, and that can save confusion later.
|
||||
|
||||
Helping with Documentation
|
||||
--------------------------
|
||||
|
||||
Ansible documentation is a community project too! If you would like to help with the
|
||||
documentation, whether correcting a typo or improving a section, or maybe even
|
||||
documenting a new feature, submit a github pull request to the code that
|
||||
lives in the “docsite/rst” subdirectory of the project. Docs are in restructured text
|
||||
format. If you aren’t comfortable with restructured text, you can also open a ticket on
|
||||
github about any errors you spot or sections you would like to see added. For more information
|
||||
on creating pull requests, please refer to the
|
||||
[github help guide](https://help.github.com/articles/using-pull-requests).
|
||||
|
||||
|
||||
Contributing Code (Features or Bugfixes)
|
||||
----------------------------------------
|
||||
|
||||
The Ansible project keeps it’s source on github at
|
||||
[github.com/ansible/ansible](http://github.com/ansible/ansible)
|
||||
and takes contributions through
|
||||
[github pull requests](https://help.github.com/articles/using-pull-requests).
|
||||
|
||||
It is usually a good idea to join the ansible-devel list to discuss any large features prior to submission, and this especially helps in avoiding duplicate work or efforts where we decide, upon seeing a pull request for the first time, that revisions are needed. (This is not usually needed for module development)
|
||||
|
||||
Note that we do keep Ansible to a particular aesthetic, so if you are unclear about whether a feature
|
||||
is a good fit or not, having the discussion on the development list is often a lot easier than having
|
||||
to modify a pull request later.
|
||||
|
||||
When submitting patches, be sure to run the unit tests first “make tests” and always use
|
||||
“git rebase” vs “git merge” (aliasing git pull to git pull --rebase is a great idea) to
|
||||
avoid merge commits in your submissions. There are also integration tests that can be run in the "tests/integration" directory.
|
||||
|
||||
In order to keep the history clean and better audit incoming code, we will require resubmission of pull requests that contain merge commits. Use "git pull --rebase" vs "git pull" and "git rebase" vs "git merge". Also be sure to use topic branches to keep your additions on different branches, such that they won't pick up stray commits later.
|
||||
|
||||
We’ll then review your contributions and engage with you about questions and so on.
|
||||
|
||||
As we have a very large and active community, so it may take awhile to get your contributions
|
||||
in! See the notes about priorities in a later section for understanding our work queue.
|
||||
|
||||
Patches should be made against the 'devel' branch.
|
||||
|
||||
Contributions can be for new features like modules, or to fix bugs you or others have found. If you
|
||||
are interested in writing new modules to be included in the core Ansible distribution, please refer
|
||||
to the [Module Developers documentation on our website](http://docs.ansible.com/developing_modules.html).
|
||||
|
||||
Ansible's aesthetic encourages simple, readable code and consistent, conservatively extending,
|
||||
backwards-compatible improvements. Code developed for Ansible needs to support Python 2.6+,
|
||||
while code in modules must run under Python 2.4 or higher. Please also use a 4-space indent
|
||||
and no tabs.
|
||||
|
||||
Tip: To easily run from a checkout, source "./hacking/env-setup" and that's it -- no install
|
||||
required. You're now live!
|
||||
|
||||
|
||||
Reporting A Bug
|
||||
---------------
|
||||
|
||||
Ansible practices responsible disclosure - if this is a security related bug, email security@ansible.com instead of filing a ticket or posting to the Google Group and you will recieve a prompt response.
|
||||
|
||||
Bugs should be reported to [github.com/ansible/ansible](http://github.com/ansible/ansible) after
|
||||
signing up for a free github account. Before reporting a bug, please use the bug/issue search
|
||||
to see if the issue has already been reported.
|
||||
|
||||
When filing a bug, please use the [issue template](https://raw2.github.com/ansible/ansible/devel/examples/issues/ISSUE_TEMPLATE.md) to provide all relevant information.
|
||||
|
||||
Do not use the issue tracker for "how do I do this" type questions. These are great candidates
|
||||
for IRC or the mailing list instead where things are likely to be more of a discussion.
|
||||
|
||||
To be respectful of reviewers time and allow us to help everyone efficiently, please
|
||||
provide minimal well-reduced and well-commented examples versus sharing your entire production
|
||||
playbook. Include playbook snippets and output where possible.
|
||||
|
||||
Content in the GitHub bug tracker can be indented four spaces to preserve formatting.
|
||||
For multiple-file content, we encourage use of gist.github.com. Online pastebin content can expire.
|
||||
|
||||
If you are not sure if something is a bug yet, you are welcome to ask about something on
|
||||
the mailing list or IRC first. As we are a very high volume project, if you determine that
|
||||
you do have a bug, please be sure to open the issue yourself to ensure we have a record of
|
||||
it. Don’t rely on someone else in the community to file the bug report for you.
|
||||
|
||||
It may take some time to get to your report, see "A Note About Priorities" below.
|
||||
|
||||
A Note About Priorities
|
||||
=======================
|
||||
|
||||
Ansible was one of the top 5 projects with the most OSS contributors on GitHub in 2013, and well over
|
||||
600 people have added code to the project. As a result, we have a LOT of incoming activity to process.
|
||||
|
||||
In the interest of transparency, we're telling you how we do this.
|
||||
|
||||
In our bug tracker you'll notice some labels - P1, P2, P3, P4, and P5. These are our internal
|
||||
priority orders that we use to sort tickets.
|
||||
|
||||
With some exceptions for easy merges (like documentation typos for instance),
|
||||
we're going to spend most of our time working on P1 and P2 items first, including pull requests.
|
||||
These usually relate to important
|
||||
bugs or features affecting large segments of the userbase. So if you see something categorized
|
||||
"P3 or P4", and it's not appearing to get a lot of immediate attention, this is why.
|
||||
|
||||
These labels don't really have definition - they are a simple ordering. However something
|
||||
affecting a major module (yum, apt, etc) is likely to be prioritized higher than a module
|
||||
affecting a smaller number of users.
|
||||
|
||||
Since we place a strong emphasis on testing and code review, it may take a few months for a minor feature to get merged.
|
||||
|
||||
Don't worry though -- we'll also take periodic sweeps through the lower priority queues and give
|
||||
them some attention as well, particularly in the area of new module changes. So it doesn't neccessarily
|
||||
mean that we'll be exhausting all of the higher-priority queues before getting to your ticket.
|
||||
|
||||
Release Numbering
|
||||
=================
|
||||
|
||||
Releases ending in ".0" are major releases and this is where all new features land. Releases ending
|
||||
in another integer, like "0.X.1" and "0.X.2" are dot releases, and these are only going to contain
|
||||
bugfixes. Typically we don't do dot releases for minor releases, but may occasionally decide to cut
|
||||
dot releases containing a large number of smaller fixes if it's still a fairly long time before
|
||||
the next release comes out.
|
||||
|
||||
Online Resources
|
||||
================
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The main ansible documentation can be found at [docs.ansible.com](http://docs.ansible.com).
|
||||
As mentioned above this is an open source project, so we accept contributions to the documentation.
|
||||
You can also find some best practices examples that we recommend reading at
|
||||
[ansible-examples](http://github.com/ansible/ansible-examples).
|
||||
|
||||
Mailing lists
|
||||
-------------
|
||||
|
||||
Ansible has several mailing lists. Your first post to the mailing list will be
|
||||
moderated (to reduce spam), so please allow a day or less for your first post.
|
||||
|
||||
[ansible-announce](https://groups.google.com/forum/#!forum/ansible-announce) is for release
|
||||
announcements and major news. It is a low traffic read-only list and you should only get a few
|
||||
emails a month.
|
||||
|
||||
[ansible-project](https://groups.google.com/forum/#!forum/ansible-project) is the main list, and is
|
||||
used for sharing cool projects you may have built, talking about Ansible ideas, and for users to ask
|
||||
questions or to help other users.
|
||||
|
||||
[ansible-devel](https://groups.google.com/forum/#!forum/ansible-devel) is a technical list for
|
||||
developers working on Ansible and Ansible modules. Join here to discuss how to build modules,
|
||||
prospective feature implementations, or technical challenges.
|
||||
|
||||
To subscribe to a group from a non-google account, you can email the subscription address, for
|
||||
example ansible-devel+subscribe@googlegroups.com.
|
||||
|
||||
IRC
|
||||
---
|
||||
|
||||
Ansible has a general purpose IRC channel available at #ansible on irc.freenode.net.
|
||||
Use this channel for all types of conversations, including sharing tips, coordinating
|
||||
development work, or getting help from other users.
|
||||
|
||||
Miscellaneous Information
|
||||
=========================
|
||||
|
||||
Staff
|
||||
-----
|
||||
|
||||
Ansible, Inc is a company supporting Ansible and building additional solutions based on
|
||||
Ansible. We also do services and support for those that are interested. Our most
|
||||
important task however is enabling all the great things that happen in the Ansible
|
||||
community, including organizing software releases of Ansible. For more information about
|
||||
any of these things, contact info@ansible.com
|
||||
|
||||
On IRC, you can find us as mdehaan, jimi_c, Tybstar, and others. On the mailing list,
|
||||
we post with an @ansible.com address.
|
||||
|
||||
Community Code of Conduct
|
||||
-------------------------
|
||||
|
||||
Ansible’s community welcomes users of all types, backgrounds, and skill levels. Please
|
||||
treat others as you expect to be treated, keep discussions positive, and avoid discrimination, profanity, allegations of Cthulhu worship, or engaging in controversial debates (except vi vs emacs is cool).
|
||||
|
||||
Posts to mailing lists should remain focused around Ansible and IT automation. Abuse of these community guidelines will not be tolerated and may result in banning from community resources.
|
||||
|
||||
Contributors License Agreement
|
||||
------------------------------
|
||||
|
||||
By contributing you agree that these contributions are your own (or approved by your employer)
|
||||
and you grant a full, complete, irrevocable
|
||||
copyright license to all users and developers of the project, present and future, pursuant
|
||||
to the license of the project.
|
||||
|
||||
|
||||
|
||||
25
MANIFEST.in
25
MANIFEST.in
@ -1,25 +1,8 @@
|
||||
include README.rst
|
||||
include COPYING
|
||||
include SYMLINK_CACHE.json
|
||||
include requirements.txt
|
||||
include .coveragerc
|
||||
include shippable.yml
|
||||
include tox.ini
|
||||
include bin/ansible-test
|
||||
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 *
|
||||
recursive-include lib/ansible/module_utils/powershell *
|
||||
recursive-include lib/ansible/modules *
|
||||
recursive-include lib/ansible/galaxy/data *
|
||||
graft examples/playbooks
|
||||
include packaging/distutils/setup.py
|
||||
recursive-include docs *
|
||||
recursive-include licenses *
|
||||
recursive-include packaging *
|
||||
recursive-include test *
|
||||
recursive-include library *
|
||||
include Makefile
|
||||
include MANIFEST.in
|
||||
include changelogs/CHANGELOG*.rst
|
||||
include contrib/README.md
|
||||
recursive-include contrib/inventory *
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
# Module Maintainer Guidelines
|
||||
|
||||
The Ansible Module Maintainer Guidelines can now be found in the [official Ansible community guide](https://docs.ansible.com/ansible/latest/community/maintainers.html).
|
||||
|
||||
See also the [Developers Guide](https://docs.ansible.com/ansible/latest/dev_guide/)
|
||||
310
Makefile
310
Makefile
@ -1,211 +1,110 @@
|
||||
#!/usr/bin/make
|
||||
# WARN: gmake syntax
|
||||
########################################################
|
||||
# Makefile for Ansible
|
||||
#
|
||||
# useful targets:
|
||||
# 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
|
||||
# make pyflakes, make pep8 -- source code checks
|
||||
|
||||
########################################################
|
||||
# variable section
|
||||
|
||||
NAME = ansible
|
||||
NAME = "ansible"
|
||||
OS = $(shell uname -s)
|
||||
PREFIX ?= '/usr/local'
|
||||
|
||||
# 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
|
||||
GENERATE_CLI = docs/bin/generate_man.py
|
||||
|
||||
PYTHON=python
|
||||
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
|
||||
|
||||
MAJOR_VERSION := $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --majorversion)
|
||||
CODENAME := $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --codename)
|
||||
|
||||
# if a specific release was not requested, set to 1 (RPMs have "fancier" logic for this further down)
|
||||
RELEASE ?= 1
|
||||
# VERSION file provides one place to update the software version
|
||||
VERSION := $(shell cat VERSION)
|
||||
|
||||
# Get the branch information from git
|
||||
ifneq ($(shell which git),)
|
||||
GIT_DATE := $(shell git log -n 1 --format="%ai")
|
||||
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 = ""
|
||||
endif
|
||||
|
||||
ifeq ($(shell echo $(OS) | egrep -c 'Darwin|FreeBSD|OpenBSD|DragonFly'),1)
|
||||
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)
|
||||
CPUS ?= $(shell sysctl hw.ncpu|awk '{print $$2}')
|
||||
else
|
||||
DATE := $(shell date --utc --date="$(GIT_DATE)" +%Y%m%d%H%M)
|
||||
CPUS ?= $(shell nproc)
|
||||
endif
|
||||
|
||||
# DEB build parameters
|
||||
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)
|
||||
ifeq ($(OFFICIAL),yes)
|
||||
DEB_RELEASE ?= $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --debrelease)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)
|
||||
# Do not sign unofficial builds
|
||||
DEBUILD_OPTS += -uc -us
|
||||
DPUT_OPTS += -u
|
||||
endif
|
||||
DEBUILD = $(DEBUILD_BIN) $(DEBUILD_OPTS)
|
||||
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}')
|
||||
|
||||
ifneq ($(OFFICIAL),yes)
|
||||
RPMRELEASE = 100.git$(DATE)$(GITINFO)
|
||||
endif
|
||||
ifeq ($(PUBLISH),nightly)
|
||||
# https://fedoraproject.org/wiki/Packaging:Versioning#Snapshots
|
||||
RPMRELEASE = $(RELEASE).$(DATE)git.$(GIT_HASH)
|
||||
RPMRELEASE = 1
|
||||
ifeq ($(OFFICIAL),)
|
||||
RPMRELEASE = 0.git$(DATE)
|
||||
endif
|
||||
RPMNVR = "$(NAME)-$(VERSION)-$(RPMRELEASE)$(RPMDIST)"
|
||||
|
||||
RPMVERSION ?= $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --baseversion)
|
||||
RPMRELEASE ?= $(shell $(PYTHON) packaging/release/versionhelper/version_helper.py --rpmrelease)
|
||||
RPMNVR = "$(NAME)-$(RPMVERSION)-$(RPMRELEASE)$(RPMDIST)$(REPOTAG)"
|
||||
|
||||
# MOCK build parameters
|
||||
MOCK_BIN ?= mock
|
||||
MOCK_CFG ?=
|
||||
|
||||
# dynamically add repotag define only if specified
|
||||
ifneq ($(REPOTAG),)
|
||||
EXTRA_RPM_DEFINES += --define "repotag $(REPOTAG)"
|
||||
endif
|
||||
|
||||
# ansible-test parameters
|
||||
ANSIBLE_TEST ?= bin/ansible-test
|
||||
TEST_FLAGS ?=
|
||||
|
||||
# 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])')
|
||||
|
||||
# ansible-test integration parameters (make integration)
|
||||
IMAGE ?= centos7
|
||||
TARGET ?=
|
||||
NOSETESTS ?= nosetests
|
||||
|
||||
########################################################
|
||||
|
||||
.PHONY: all
|
||||
all: clean python
|
||||
|
||||
.PHONY: tests
|
||||
tests:
|
||||
$(ANSIBLE_TEST) units -v --python $(PYTHON_VERSION) $(TEST_FLAGS)
|
||||
PYTHONPATH=./lib ANSIBLE_LIBRARY=./library $(NOSETESTS) -d -w test/units -v
|
||||
|
||||
.PHONY: tests-py3
|
||||
tests-py3:
|
||||
$(ANSIBLE_TEST) units -v --python $(PYTHON3_VERSION) $(TEST_FLAGS)
|
||||
|
||||
.PHONY: tests-nonet
|
||||
tests-nonet:
|
||||
$(ANSIBLE_TEST) units -v --python $(PYTHON_VERSION) $(TEST_FLAGS) --exclude test/units/modules/network/
|
||||
|
||||
.PHONY: integration
|
||||
integration:
|
||||
$(ANSIBLE_TEST) integration -v --docker $(IMAGE) $(TARGET) $(TEST_FLAGS)
|
||||
|
||||
.PHONY: authors
|
||||
authors:
|
||||
sh hacking/authors.sh
|
||||
|
||||
# Regenerate %.1.rst if %.1.rst.in has been modified more
|
||||
# recently than %.1.rst.
|
||||
%.1.rst: %.1.rst.in
|
||||
# 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: loc
|
||||
loc:
|
||||
sloccount lib library bin
|
||||
|
||||
.PHONY: pep8
|
||||
pep8:
|
||||
$(ANSIBLE_TEST) sanity --test pep8 --python $(PYTHON_VERSION) $(TEST_FLAGS)
|
||||
@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/
|
||||
|
||||
.PHONY: pyflakes
|
||||
pyflakes:
|
||||
pyflakes lib/ansible/*.py lib/ansible/*/*.py bin/*
|
||||
|
||||
.PHONY: clean
|
||||
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"
|
||||
@ -215,64 +114,21 @@ clean:
|
||||
rm -rf docs/js
|
||||
@echo "Cleaning up authors file"
|
||||
rm -f AUTHORS.TXT
|
||||
@echo "Cleaning up docsite"
|
||||
$(MAKE) -C docs/docsite clean
|
||||
|
||||
.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/
|
||||
|
||||
.PHONY: sdist
|
||||
sdist: clean docs
|
||||
$(PYTHON) setup.py sdist
|
||||
|
||||
.PHONY: sdist_upload
|
||||
sdist_upload: clean docs
|
||||
$(PYTHON) setup.py sdist upload 2>&1 |tee upload.log
|
||||
|
||||
.PHONY: changelog
|
||||
changelog:
|
||||
packaging/release/changelogs/changelog.py release -vv && packaging/release/changelogs/changelog.py generate -vv
|
||||
|
||||
.PHONY: rpmcommon
|
||||
rpmcommon: sdist
|
||||
rpmcommon: $(MANPAGES) sdist
|
||||
@mkdir -p rpm-build
|
||||
@cp dist/*.gz rpm-build/
|
||||
@cp $(RPMSPEC) rpm-build/$(NAME).spec
|
||||
@sed -e 's#^Version:.*#Version: $(VERSION)#' -e 's#^Release:.*#Release: $(RPMRELEASE)%{?dist}#' $(RPMSPEC) >rpm-build/$(NAME).spec
|
||||
|
||||
.PHONY: mock-srpm
|
||||
mock-srpm: /etc/mock/$(MOCK_CFG).cfg rpmcommon
|
||||
$(MOCK_BIN) -r $(MOCK_CFG) $(MOCK_ARGS) --resultdir rpm-build/ --bootstrap-chroot --old-chroot --buildsrpm --spec rpm-build/$(NAME).spec --sources rpm-build/ \
|
||||
--define "rpmversion $(RPMVERSION)" \
|
||||
--define "upstream_version $(VERSION)" \
|
||||
--define "rpmrelease $(RPMRELEASE)" \
|
||||
$(EXTRA_RPM_DEFINES)
|
||||
@echo "#############################################"
|
||||
@echo "Ansible SRPM is built:"
|
||||
@echo rpm-build/*.src.rpm
|
||||
@echo "#############################################"
|
||||
|
||||
.PHONY: mock-rpm
|
||||
mock-rpm: /etc/mock/$(MOCK_CFG).cfg mock-srpm
|
||||
$(MOCK_BIN) -r $(MOCK_CFG) $(MOCK_ARGS) --resultdir rpm-build/ --bootstrap-chroot --old-chroot --rebuild rpm-build/$(NAME)-*.src.rpm \
|
||||
--define "rpmversion $(RPMVERSION)" \
|
||||
--define "upstream_version $(VERSION)" \
|
||||
--define "rpmrelease $(RPMRELEASE)" \
|
||||
$(EXTRA_RPM_DEFINES)
|
||||
@echo "#############################################"
|
||||
@echo "Ansible RPM is built:"
|
||||
@echo rpm-build/*.noarch.rpm
|
||||
@echo "#############################################"
|
||||
|
||||
.PHONY: srpm
|
||||
srpm: rpmcommon
|
||||
@rpmbuild --define "_topdir %(pwd)/rpm-build" \
|
||||
--define "_builddir %{_topdir}" \
|
||||
@ -280,10 +136,6 @@ srpm: rpmcommon
|
||||
--define "_srcrpmdir %{_topdir}" \
|
||||
--define "_specdir $(RPMSPECDIR)" \
|
||||
--define "_sourcedir %{_topdir}" \
|
||||
--define "upstream_version $(VERSION)" \
|
||||
--define "rpmversion $(RPMVERSION)" \
|
||||
--define "rpmrelease $(RPMRELEASE)" \
|
||||
$(EXTRA_RPM_DEFINES) \
|
||||
-bs rpm-build/$(NAME).spec
|
||||
@rm -f rpm-build/$(NAME).spec
|
||||
@echo "#############################################"
|
||||
@ -291,7 +143,6 @@ srpm: rpmcommon
|
||||
@echo " rpm-build/$(RPMNVR).src.rpm"
|
||||
@echo "#############################################"
|
||||
|
||||
.PHONY: rpm
|
||||
rpm: rpmcommon
|
||||
@rpmbuild --define "_topdir %(pwd)/rpm-build" \
|
||||
--define "_builddir %{_topdir}" \
|
||||
@ -299,12 +150,8 @@ rpm: rpmcommon
|
||||
--define "_srcrpmdir %{_topdir}" \
|
||||
--define "_specdir $(RPMSPECDIR)" \
|
||||
--define "_sourcedir %{_topdir}" \
|
||||
--define "_rpmfilename $(RPMNVR).%%{ARCH}.rpm" \
|
||||
--define "_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \
|
||||
--define "__python `which $(PYTHON)`" \
|
||||
--define "upstream_version $(VERSION)" \
|
||||
--define "rpmversion $(RPMVERSION)" \
|
||||
--define "rpmrelease $(RPMRELEASE)" \
|
||||
$(EXTRA_RPM_DEFINES) \
|
||||
-ba rpm-build/$(NAME).spec
|
||||
@rm -f rpm-build/$(NAME).spec
|
||||
@echo "#############################################"
|
||||
@ -312,88 +159,17 @@ rpm: rpmcommon
|
||||
@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 ; \
|
||||
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
|
||||
@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 ; \
|
||||
done
|
||||
@echo "#############################################"
|
||||
|
||||
.PHONY: deb-src
|
||||
deb-src: debian
|
||||
@for DIST in $(DEB_DIST) ; do \
|
||||
(cd deb-build/$${DIST}/$(NAME)-$(VERSION)/ && $(DEBUILD) -S) ; \
|
||||
done
|
||||
@echo "#############################################"
|
||||
@echo "Ansible DEB artifacts:"
|
||||
@for DIST in $(DEB_DIST) ; do \
|
||||
echo deb-build/$${DIST}/$(NAME)_$(DEB_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 ; \
|
||||
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 ; \
|
||||
done
|
||||
|
||||
.PHONY: epub
|
||||
epub:
|
||||
(cd docs/docsite/; CPUS=$(CPUS) $(MAKE) epub)
|
||||
deb: debian
|
||||
cp -r packaging/debian ./
|
||||
chmod 755 debian/rules
|
||||
fakeroot debian/rules clean
|
||||
fakeroot dh_install
|
||||
fakeroot debian/rules binary
|
||||
|
||||
# for arch or gentoo, read instructions in the appropriate 'packaging' subdirectory directory
|
||||
.PHONY: webdocs
|
||||
webdocs:
|
||||
(cd docs/docsite/; CPUS=$(CPUS) $(MAKE) docs)
|
||||
|
||||
.PHONY: generate_rst
|
||||
generate_rst: lib/ansible/cli/*.py
|
||||
mkdir -p ./docs/man/man1/ ; \
|
||||
PYTHONPATH=./lib $(GENERATE_CLI) --template-file=docs/templates/man.j2 --output-dir=docs/man/man1/ --output-format man lib/ansible/cli/*.py
|
||||
webdocs: $(MANPAGES)
|
||||
(cd docsite/; make docs)
|
||||
|
||||
|
||||
docs: generate_rst
|
||||
$(MAKE) $(MANPAGES)
|
||||
|
||||
.PHONY: alldocs
|
||||
alldocs: docs webdocs
|
||||
|
||||
version:
|
||||
@echo $(VERSION)
|
||||
docs: $(MANPAGES)
|
||||
|
||||
48
README.md
Normal file
48
README.md
Normal file
@ -0,0 +1,48 @@
|
||||
[](http://badge.fury.io/py/ansible) [](https://pypi.python.org/pypi/ansible)
|
||||
|
||||
|
||||
Ansible
|
||||
=======
|
||||
|
||||
Ansible is a radically simple configuration-management, application deployment, task-execution, and multinode orchestration engine.
|
||||
|
||||
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 want a tarball of the last release, go to [releases.ansible.com](http://releases.ansible.com/ansible) and you can also install with pip.
|
||||
|
||||
Design Principles
|
||||
=================
|
||||
|
||||
* Have a dead simple setup process and a minimal learning curve
|
||||
* Be super fast & parallel by default
|
||||
* Require no server or client daemons; use existing SSHd
|
||||
* Use a language that is both machine and human friendly
|
||||
* Focus on security and easy auditability/review/rewriting of content
|
||||
* Manage remote machines instantly, without bootstrapping
|
||||
* 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 [Contributing.md](https://github.com/ansible/ansible/blob/devel/CONTRIBUTING.md) 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.
|
||||
* irc.freenode.net: #ansible
|
||||
|
||||
Branch Info
|
||||
===========
|
||||
|
||||
* Releases are named after Van Halen songs.
|
||||
* The devel branch corresponds to the release actively under development.
|
||||
* Various release-X.Y branches exist for previous releases
|
||||
* We'd love to have your contributions, read "CONTRIBUTING.md" for process notes.
|
||||
|
||||
Author
|
||||
======
|
||||
|
||||
Michael DeHaan -- michael@ansible.com
|
||||
|
||||
[Ansible, Inc](http://ansible.com)
|
||||
|
||||
113
README.rst
113
README.rst
@ -1,113 +0,0 @@
|
||||
|PyPI version| |Docs badge| |Chat badge| |Build Status|
|
||||
|
||||
*******
|
||||
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 https://ansible.com/
|
||||
|
||||
You can find installation instructions
|
||||
`here <https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html>`_ for a
|
||||
variety of platforms.
|
||||
|
||||
Most users should probably install a released version of Ansible from ``pip``, a package manager or
|
||||
our `release repository <https://releases.ansible.com/ansible/>`_. `Officially supported
|
||||
<https://www.ansible.com/ansible-engine>`_ builds of Ansible are also available. Some power users
|
||||
run directly from the development branch - while significant efforts are made to ensure that
|
||||
``devel`` is reasonably stable, you're more likely to encounter breaking changes when running
|
||||
Ansible this way.
|
||||
|
||||
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 <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.
|
||||
* All code submissions are done through pull requests to the ``devel`` branch.
|
||||
* Feel free to talk to us before making larger changes
|
||||
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 <https://groups.google.com/group/ansible-project>`_
|
||||
* Development list:
|
||||
`ansible-devel <https://groups.google.com/group/ansible-devel>`_
|
||||
* Announcement list:
|
||||
`ansible-announce <https://groups.google.com/group/ansible-announce>`_
|
||||
-- read only
|
||||
* irc.freenode.net: #ansible
|
||||
* For the full list of Email Lists, IRC channels see the
|
||||
`Communication page <https://docs.ansible.com/ansible/latest/community/communication.html>`_
|
||||
|
||||
Branch Info
|
||||
===========
|
||||
|
||||
* Releases are named after Led Zeppelin songs. (Releases prior to 2.0
|
||||
were named after Van Halen songs.)
|
||||
* The ``devel`` branch corresponds to the release actively under
|
||||
development.
|
||||
* The ``stable-2.x`` branches exist for current releases.
|
||||
* Various release-X.Y branches exist for previous releases.
|
||||
* For information about the active branches see the
|
||||
`Ansible release and maintenance <https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html>`_ page.
|
||||
* We'd love to have your contributions, read the `Community
|
||||
Guide <https://docs.ansible.com/ansible/latest/community>`_ for notes on
|
||||
how to get started.
|
||||
|
||||
Roadmap
|
||||
=======
|
||||
|
||||
Based on team and community feedback, an initial roadmap will be published for a major or minor version (ex: 2.0, 2.1).
|
||||
Subminor versions will generally not have roadmaps published.
|
||||
|
||||
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>`_
|
||||
(michael.dehaan/gmail/com) and has contributions from over 3700 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
|
||||
|
||||
See `COPYING <COPYING>`_ to see the full text.
|
||||
|
||||
.. |PyPI version| image:: https://img.shields.io/pypi/v/ansible.svg
|
||||
:target: https://pypi.org/project/ansible
|
||||
.. |Docs badge| image:: https://img.shields.io/badge/docs-latest-brightgreen.svg
|
||||
:target: https://docs.ansible.com/ansible/latest/
|
||||
.. |Build Status| image:: https://api.shippable.com/projects/573f79d02a8192902e20e34b/badge?branch=devel
|
||||
:target: https://app.shippable.com/projects/573f79d02a8192902e20e34b
|
||||
.. |Chat badge| image:: https://img.shields.io/badge/chat-IRC-brightgreen.svg
|
||||
:target: https://docs.ansible.com/ansible/latest/community/communication.html
|
||||
45
RELEASES.txt
Normal file
45
RELEASES.txt
Normal file
@ -0,0 +1,45 @@
|
||||
Ansible Releases at a Glance
|
||||
============================
|
||||
|
||||
Active Development
|
||||
++++++++++++++++++
|
||||
|
||||
1.7 "Summer Nights" -------- CURRENT DEVEL BRANCH
|
||||
|
||||
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
|
||||
|
||||
|
||||
328
bin/ansible
328
bin/ansible
@ -18,146 +18,214 @@
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
########################################################
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
__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 shutil
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
|
||||
from ansible.module_utils._text import to_text
|
||||
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()
|
||||
|
||||
# ----------------------------------------------
|
||||
|
||||
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)
|
||||
|
||||
# su and sudo command line arguments need to be mutually exclusive
|
||||
if (options.su or options.su_user or options.ask_su_pass) and \
|
||||
(options.sudo or options.sudo_user or options.ask_sudo_pass):
|
||||
parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') "
|
||||
"and su arguments ('-su', '--su-user', and '--ask-su-pass') are "
|
||||
"mutually exclusive")
|
||||
|
||||
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]
|
||||
|
||||
"""
|
||||
inventory_manager = inventory.Inventory(options.inventory)
|
||||
if options.subset:
|
||||
inventory_manager.subset(options.subset)
|
||||
hosts = inventory_manager.list_hosts(pattern)
|
||||
if len(hosts) == 0:
|
||||
callbacks.display("No hosts matched")
|
||||
sys.exit(0)
|
||||
|
||||
if options.listhosts:
|
||||
for host in hosts:
|
||||
callbacks.display(' %s' % host)
|
||||
sys.exit(0)
|
||||
|
||||
if ((options.module_name == 'command' or options.module_name == 'shell')
|
||||
and not options.module_args):
|
||||
callbacks.display("No argument passed to %s module" % options.module_name, color='red', stderr=True)
|
||||
sys.exit(1)
|
||||
"""
|
||||
|
||||
sshpass = None
|
||||
sudopass = None
|
||||
su_pass = None
|
||||
vault_pass = None
|
||||
|
||||
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
|
||||
options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS
|
||||
options.ask_su_pass = options.ask_su_pass or C.DEFAULT_ASK_SU_PASS
|
||||
options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
|
||||
|
||||
(sshpass, sudopass, su_pass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass)
|
||||
|
||||
# read vault_pass from a file
|
||||
if options.vault_password_file:
|
||||
this_path = os.path.expanduser(options.vault_password_file)
|
||||
try:
|
||||
f = open(this_path, "rb")
|
||||
tmp_vault_pass=f.read().strip()
|
||||
f.close()
|
||||
except (OSError, IOError), e:
|
||||
raise errors.AnsibleError("Could not read %s: %s" % (this_path, e))
|
||||
|
||||
if not options.ask_vault_pass:
|
||||
vault_pass = tmp_vault_pass
|
||||
|
||||
inventory_manager = inventory.Inventory(options.inventory)
|
||||
if options.subset:
|
||||
inventory_manager.subset(options.subset)
|
||||
hosts = inventory_manager.list_hosts(pattern)
|
||||
if len(hosts) == 0:
|
||||
callbacks.display("No hosts matched")
|
||||
sys.exit(0)
|
||||
|
||||
if options.listhosts:
|
||||
for host in hosts:
|
||||
callbacks.display(' %s' % host)
|
||||
sys.exit(0)
|
||||
|
||||
if ((options.module_name == 'command' or options.module_name == 'shell')
|
||||
and not options.module_args):
|
||||
callbacks.display("No argument passed to %s module" % options.module_name, color='red', stderr=True)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Used for determining if the system is running a new enough python version
|
||||
# and should only restrict on our documented minimum versions
|
||||
_PY3_MIN = sys.version_info[:2] >= (3, 5)
|
||||
_PY2_MIN = (2, 6) <= sys.version_info[:2] < (3,)
|
||||
_PY_MIN = _PY3_MIN or _PY2_MIN
|
||||
if not _PY_MIN:
|
||||
raise SystemExit('ERROR: Ansible requires a minimum of Python2 version 2.6 or Python3 version 3.5. Current version: %s' % ''.join(sys.version.splitlines()))
|
||||
if options.su_user or options.ask_su_pass:
|
||||
options.su = True
|
||||
options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER
|
||||
options.su_user = options.su_user or C.DEFAULT_SU_USER
|
||||
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,
|
||||
sudo=options.sudo,
|
||||
sudo_pass=sudopass,
|
||||
sudo_user=options.sudo_user,
|
||||
transport=options.connection,
|
||||
subset=options.subset,
|
||||
check=options.check,
|
||||
diff=options.check,
|
||||
su=options.su,
|
||||
su_pass=su_pass,
|
||||
su_user=options.su_user,
|
||||
vault_pass=vault_pass
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
|
||||
class LastResort(object):
|
||||
# OUTPUT OF LAST RESORT
|
||||
def display(self, msg, log_only=None):
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
def error(self, msg, wrap_text=None):
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
########################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
callbacks.display("", log_only=True)
|
||||
callbacks.display(" ".join(sys.argv), log_only=True)
|
||||
callbacks.display("", log_only=True)
|
||||
|
||||
display = LastResort()
|
||||
|
||||
try: # bad ANSIBLE_CONFIG or config options can force ugly stacktrace
|
||||
import ansible.constants as C
|
||||
from ansible.utils.display import Display
|
||||
except AnsibleOptionsError as e:
|
||||
display.error(to_text(e), wrap_text=False)
|
||||
sys.exit(5)
|
||||
|
||||
cli = None
|
||||
me = os.path.basename(sys.argv[0])
|
||||
|
||||
cli = Cli()
|
||||
(options, args) = cli.parse()
|
||||
try:
|
||||
display = Display()
|
||||
display.debug("starting run")
|
||||
(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)
|
||||
|
||||
sub = None
|
||||
target = me.split('-')
|
||||
if target[-1][0].isdigit():
|
||||
# Remove any version or python version info as downstreams
|
||||
# sometimes add that
|
||||
target = target[:-1]
|
||||
|
||||
if len(target) > 1:
|
||||
sub = target[1]
|
||||
myclass = "%sCLI" % sub.capitalize()
|
||||
elif target[0] == 'ansible':
|
||||
sub = 'adhoc'
|
||||
myclass = 'AdHocCLI'
|
||||
else:
|
||||
raise AnsibleError("Unknown Ansible alias: %s" % me)
|
||||
|
||||
try:
|
||||
mycli = getattr(__import__("ansible.cli.%s" % sub, fromlist=[myclass]), myclass)
|
||||
except ImportError as e:
|
||||
# ImportError members have changed in py3
|
||||
if 'msg' in dir(e):
|
||||
msg = e.msg
|
||||
else:
|
||||
msg = e.message
|
||||
if msg.endswith(' %s' % sub):
|
||||
raise AnsibleError("Ansible sub-program not implemented: %s" % me)
|
||||
else:
|
||||
raise
|
||||
|
||||
try:
|
||||
args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv]
|
||||
except UnicodeError:
|
||||
display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
|
||||
display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
|
||||
exit_code = 6
|
||||
else:
|
||||
cli = mycli(args)
|
||||
cli.parse()
|
||||
exit_code = cli.run()
|
||||
|
||||
except AnsibleOptionsError as e:
|
||||
cli.parser.print_help()
|
||||
display.error(to_text(e), wrap_text=False)
|
||||
exit_code = 5
|
||||
except AnsibleParserError as e:
|
||||
display.error(to_text(e), wrap_text=False)
|
||||
exit_code = 4
|
||||
# TQM takes care of these, but leaving comment to reserve the exit codes
|
||||
# except AnsibleHostUnreachable as e:
|
||||
# display.error(str(e))
|
||||
# exit_code = 3
|
||||
# except AnsibleHostFailed as e:
|
||||
# display.error(str(e))
|
||||
# exit_code = 2
|
||||
except AnsibleError as e:
|
||||
display.error(to_text(e), wrap_text=False)
|
||||
exit_code = 1
|
||||
except KeyboardInterrupt:
|
||||
display.error("User interrupted execution")
|
||||
exit_code = 99
|
||||
except Exception as e:
|
||||
if C.DEFAULT_DEBUG:
|
||||
# Show raw stacktraces in debug mode, It also allow pdb to
|
||||
# enter post mortem mode.
|
||||
raise
|
||||
have_cli_options = cli is not None and cli.options is not None
|
||||
display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
|
||||
if not have_cli_options or have_cli_options and cli.options.verbosity > 2:
|
||||
log_only = False
|
||||
if hasattr(e, 'orig_exc'):
|
||||
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
|
||||
why = to_text(e.orig_exc)
|
||||
if to_text(e) != why:
|
||||
display.vvv('\noriginal msg: %s' % why)
|
||||
else:
|
||||
display.display("to see the full traceback, use -vvv")
|
||||
log_only = True
|
||||
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
|
||||
exit_code = 250
|
||||
finally:
|
||||
# Remove ansible tmpdir
|
||||
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)
|
||||
|
||||
sys.exit(exit_code)
|
||||
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
@ -1,328 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright: (c) 2017, Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
__requires__ = ['ansible']
|
||||
|
||||
try:
|
||||
import pkg_resources
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
import fcntl
|
||||
import hashlib
|
||||
import os
|
||||
import signal
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
import errno
|
||||
import json
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.module_utils._text import to_bytes, to_text
|
||||
from ansible.module_utils.six import PY3
|
||||
from ansible.module_utils.six.moves import cPickle, StringIO
|
||||
from ansible.module_utils.connection import Connection, ConnectionError, send_data, recv_data
|
||||
from ansible.module_utils.service import fork_process
|
||||
from ansible.playbook.play_context import PlayContext
|
||||
from ansible.plugins.loader import connection_loader
|
||||
from ansible.utils.path import unfrackpath, makedirs_safe
|
||||
from ansible.utils.display import Display
|
||||
from ansible.utils.jsonrpc import JsonRpcServer
|
||||
|
||||
|
||||
def read_stream(byte_stream):
|
||||
size = int(byte_stream.readline().strip())
|
||||
|
||||
data = byte_stream.read(size)
|
||||
if len(data) < size:
|
||||
raise Exception("EOF found before data was complete")
|
||||
|
||||
data_hash = to_text(byte_stream.readline().strip())
|
||||
if data_hash != hashlib.sha1(data).hexdigest():
|
||||
raise Exception("Read {0} bytes, but data did not match checksum".format(size))
|
||||
|
||||
# restore escaped loose \r characters
|
||||
data = data.replace(br'\r', b'\r')
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@contextmanager
|
||||
def file_lock(lock_path):
|
||||
"""
|
||||
Uses contextmanager to create and release a file lock based on the
|
||||
given path. This allows us to create locks using `with file_lock()`
|
||||
to prevent deadlocks related to failure to unlock properly.
|
||||
"""
|
||||
|
||||
lock_fd = os.open(lock_path, os.O_RDWR | os.O_CREAT, 0o600)
|
||||
fcntl.lockf(lock_fd, fcntl.LOCK_EX)
|
||||
yield
|
||||
fcntl.lockf(lock_fd, fcntl.LOCK_UN)
|
||||
os.close(lock_fd)
|
||||
|
||||
|
||||
class ConnectionProcess(object):
|
||||
'''
|
||||
The connection process wraps around a Connection object that manages
|
||||
the connection to a remote device that persists over the playbook
|
||||
'''
|
||||
def __init__(self, fd, play_context, socket_path, original_path, ansible_playbook_pid=None):
|
||||
self.play_context = play_context
|
||||
self.socket_path = socket_path
|
||||
self.original_path = original_path
|
||||
|
||||
self.fd = fd
|
||||
self.exception = None
|
||||
|
||||
self.srv = JsonRpcServer()
|
||||
self.sock = None
|
||||
|
||||
self.connection = None
|
||||
self._ansible_playbook_pid = ansible_playbook_pid
|
||||
|
||||
def start(self, variables):
|
||||
try:
|
||||
messages = list()
|
||||
result = {}
|
||||
|
||||
messages.append('control socket path is %s' % self.socket_path)
|
||||
|
||||
# If this is a relative path (~ gets expanded later) then plug the
|
||||
# key's path on to the directory we originally came from, so we can
|
||||
# find it now that our cwd is /
|
||||
if self.play_context.private_key_file and self.play_context.private_key_file[0] not in '~/':
|
||||
self.play_context.private_key_file = os.path.join(self.original_path, self.play_context.private_key_file)
|
||||
self.connection = connection_loader.get(self.play_context.connection, self.play_context, '/dev/null',
|
||||
ansible_playbook_pid=self._ansible_playbook_pid)
|
||||
self.connection.set_options(var_options=variables)
|
||||
self.connection._connect()
|
||||
|
||||
self.connection._socket_path = self.socket_path
|
||||
self.srv.register(self.connection)
|
||||
messages.extend(sys.stdout.getvalue().splitlines())
|
||||
messages.append('connection to remote device started successfully')
|
||||
|
||||
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
self.sock.bind(self.socket_path)
|
||||
self.sock.listen(1)
|
||||
messages.append('local domain socket listeners started successfully')
|
||||
except Exception as exc:
|
||||
result['error'] = to_text(exc)
|
||||
result['exception'] = traceback.format_exc()
|
||||
finally:
|
||||
result['messages'] = messages
|
||||
self.fd.write(json.dumps(result))
|
||||
self.fd.close()
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
while self.connection.connected:
|
||||
signal.signal(signal.SIGALRM, self.connect_timeout)
|
||||
signal.signal(signal.SIGTERM, self.handler)
|
||||
signal.alarm(self.connection.get_option('persistent_connect_timeout'))
|
||||
|
||||
self.exception = None
|
||||
(s, addr) = self.sock.accept()
|
||||
signal.alarm(0)
|
||||
|
||||
signal.signal(signal.SIGALRM, self.command_timeout)
|
||||
while True:
|
||||
data = recv_data(s)
|
||||
if not data:
|
||||
break
|
||||
|
||||
signal.alarm(self.connection.get_option('persistent_command_timeout'))
|
||||
resp = self.srv.handle_request(data)
|
||||
signal.alarm(0)
|
||||
|
||||
send_data(s, to_bytes(resp))
|
||||
|
||||
s.close()
|
||||
|
||||
except Exception as e:
|
||||
# socket.accept() will raise EINTR if the socket.close() is called
|
||||
if hasattr(e, 'errno'):
|
||||
if e.errno != errno.EINTR:
|
||||
self.exception = traceback.format_exc()
|
||||
else:
|
||||
self.exception = traceback.format_exc()
|
||||
|
||||
finally:
|
||||
# allow time for any exception msg send over socket to receive at other end before shutting down
|
||||
time.sleep(0.1)
|
||||
|
||||
# when done, close the connection properly and cleanup the socket file so it can be recreated
|
||||
self.shutdown()
|
||||
|
||||
def connect_timeout(self, signum, frame):
|
||||
msg = 'persistent connection idle timeout triggered, timeout value is %s secs.\nSee the timeout setting options in the Network Debug and ' \
|
||||
'Troubleshooting Guide.' % self.connection.get_option('persistent_connect_timeout')
|
||||
display.display(msg, log_only=True)
|
||||
raise Exception(msg)
|
||||
|
||||
def command_timeout(self, signum, frame):
|
||||
msg = 'command timeout triggered, timeout value is %s secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide.'\
|
||||
% self.connection.get_option('persistent_command_timeout')
|
||||
display.display(msg, log_only=True)
|
||||
raise Exception(msg)
|
||||
|
||||
def handler(self, signum, frame):
|
||||
msg = 'signal handler called with signal %s.' % signum
|
||||
display.display(msg, log_only=True)
|
||||
raise Exception(msg)
|
||||
|
||||
def shutdown(self):
|
||||
""" Shuts down the local domain socket
|
||||
"""
|
||||
lock_path = unfrackpath("%s/.ansible_pc_lock_%s" % os.path.split(self.socket_path))
|
||||
if os.path.exists(self.socket_path):
|
||||
try:
|
||||
if self.sock:
|
||||
self.sock.close()
|
||||
if self.connection:
|
||||
self.connection.close()
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
if os.path.exists(self.socket_path):
|
||||
os.remove(self.socket_path)
|
||||
setattr(self.connection, '_socket_path', None)
|
||||
setattr(self.connection, '_connected', False)
|
||||
|
||||
if os.path.exists(lock_path):
|
||||
os.remove(lock_path)
|
||||
|
||||
display.display('shutdown complete', log_only=True)
|
||||
|
||||
|
||||
def main():
|
||||
""" Called to initiate the connect to the remote device
|
||||
"""
|
||||
rc = 0
|
||||
result = {}
|
||||
messages = list()
|
||||
socket_path = None
|
||||
|
||||
# Need stdin as a byte stream
|
||||
if PY3:
|
||||
stdin = sys.stdin.buffer
|
||||
else:
|
||||
stdin = sys.stdin
|
||||
|
||||
# Note: update the below log capture code after Display.display() is refactored.
|
||||
saved_stdout = sys.stdout
|
||||
sys.stdout = StringIO()
|
||||
|
||||
try:
|
||||
# read the play context data via stdin, which means depickling it
|
||||
vars_data = read_stream(stdin)
|
||||
init_data = read_stream(stdin)
|
||||
|
||||
if PY3:
|
||||
pc_data = cPickle.loads(init_data, encoding='bytes')
|
||||
variables = cPickle.loads(vars_data, encoding='bytes')
|
||||
else:
|
||||
pc_data = cPickle.loads(init_data)
|
||||
variables = cPickle.loads(vars_data)
|
||||
|
||||
play_context = PlayContext()
|
||||
play_context.deserialize(pc_data)
|
||||
display.verbosity = play_context.verbosity
|
||||
|
||||
except Exception as e:
|
||||
rc = 1
|
||||
result.update({
|
||||
'error': to_text(e),
|
||||
'exception': traceback.format_exc()
|
||||
})
|
||||
|
||||
if rc == 0:
|
||||
ssh = connection_loader.get('ssh', class_only=True)
|
||||
ansible_playbook_pid = sys.argv[1]
|
||||
cp = ssh._create_control_path(play_context.remote_addr, play_context.port, play_context.remote_user, play_context.connection, ansible_playbook_pid)
|
||||
|
||||
# create the persistent connection dir if need be and create the paths
|
||||
# which we will be using later
|
||||
tmp_path = unfrackpath(C.PERSISTENT_CONTROL_PATH_DIR)
|
||||
makedirs_safe(tmp_path)
|
||||
|
||||
socket_path = unfrackpath(cp % dict(directory=tmp_path))
|
||||
lock_path = unfrackpath("%s/.ansible_pc_lock_%s" % os.path.split(socket_path))
|
||||
|
||||
with file_lock(lock_path):
|
||||
if not os.path.exists(socket_path):
|
||||
messages.append('local domain socket does not exist, starting it')
|
||||
original_path = os.getcwd()
|
||||
r, w = os.pipe()
|
||||
pid = fork_process()
|
||||
|
||||
if pid == 0:
|
||||
try:
|
||||
os.close(r)
|
||||
wfd = os.fdopen(w, 'w')
|
||||
process = ConnectionProcess(wfd, play_context, socket_path, original_path, ansible_playbook_pid)
|
||||
process.start(variables)
|
||||
except Exception:
|
||||
messages.append(traceback.format_exc())
|
||||
rc = 1
|
||||
|
||||
if rc == 0:
|
||||
process.run()
|
||||
else:
|
||||
process.shutdown()
|
||||
|
||||
sys.exit(rc)
|
||||
|
||||
else:
|
||||
os.close(w)
|
||||
rfd = os.fdopen(r, 'r')
|
||||
data = json.loads(rfd.read())
|
||||
messages.extend(data.pop('messages'))
|
||||
result.update(data)
|
||||
|
||||
else:
|
||||
messages.append('found existing local domain socket, using it!')
|
||||
conn = Connection(socket_path)
|
||||
conn.set_options(var_options=variables)
|
||||
pc_data = to_text(init_data)
|
||||
try:
|
||||
messages.extend(conn.update_play_context(pc_data))
|
||||
except Exception as exc:
|
||||
# Only network_cli has update_play context, so missing this is
|
||||
# not fatal e.g. netconf
|
||||
if isinstance(exc, ConnectionError) and getattr(exc, 'code', None) == -32601:
|
||||
pass
|
||||
else:
|
||||
result.update({
|
||||
'error': to_text(exc),
|
||||
'exception': traceback.format_exc()
|
||||
})
|
||||
|
||||
messages.append(sys.stdout.getvalue())
|
||||
result.update({
|
||||
'messages': messages,
|
||||
'socket_path': socket_path
|
||||
})
|
||||
|
||||
sys.stdout = saved_stdout
|
||||
if 'exception' in result:
|
||||
rc = 1
|
||||
sys.stderr.write(json.dumps(result))
|
||||
else:
|
||||
rc = 0
|
||||
sys.stdout.write(json.dumps(result))
|
||||
|
||||
sys.exit(rc)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
display = Display()
|
||||
main()
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
291
bin/ansible-doc
Executable file
291
bin/ansible-doc
Executable file
@ -0,0 +1,291 @@
|
||||
#!/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
|
||||
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 = ('.swp', '.bak', '~', '.rpm')
|
||||
|
||||
_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 hasattr(os, 'system') and os.system('(less) 2> /dev/null') == 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 + ")"
|
||||
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(doc['plainexamples'])
|
||||
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):
|
||||
text = []
|
||||
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 os.path.isdir(filename):
|
||||
continue
|
||||
|
||||
try:
|
||||
doc, plainexamples = module_docs.get_docstring(filename)
|
||||
desc = tty_ify(doc.get('short_description', '?'))
|
||||
if len(desc) > 55:
|
||||
desc = desc + '...'
|
||||
text.append("%-20s %-60.60s" % (module, desc))
|
||||
except:
|
||||
traceback.print_exc()
|
||||
sys.stderr.write("ERROR: module %s has a documentation error formatting or is missing documentation\n" % module)
|
||||
pass
|
||||
return "\n".join(text)
|
||||
|
||||
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 all modules
|
||||
paths = utils.plugins.module_finder._get_paths()
|
||||
module_list = []
|
||||
for path in paths:
|
||||
# os.system("ls -C %s" % (path))
|
||||
if os.path.isdir(path):
|
||||
for module in os.listdir(path):
|
||||
if any(module.endswith(x) for x in BLACKLIST_EXTS):
|
||||
continue
|
||||
module_list.append(module)
|
||||
|
||||
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 = 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
|
||||
|
||||
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()
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
814
bin/ansible-galaxy
Executable file
814
bin/ansible-galaxy
Executable file
@ -0,0 +1,814 @@
|
||||
#!/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 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
|
||||
|
||||
default_meta_template = """---
|
||||
galaxy_info:
|
||||
author: {{ author }}
|
||||
description: {{description}}
|
||||
company: {{ company }}
|
||||
# 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. Only
|
||||
# dependencies available via galaxy should be listed here.
|
||||
# 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")
|
||||
|
||||
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.')
|
||||
elif action == "install":
|
||||
parser.set_usage("usage: %prog install [options] [-r FILE | role_name(s)[,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):
|
||||
"""
|
||||
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]
|
||||
print " downloading role '%s', owned by %s" % (role_name, user_name)
|
||||
except:
|
||||
parser.print_help()
|
||||
print "Invalid role name (%s). You must specify 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
|
||||
|
||||
#-------------------------------------------------------------------------------------
|
||||
# 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
|
||||
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:
|
||||
role_tar_file = tarfile.open(role_filename, "r:gz")
|
||||
# verify the role's meta file
|
||||
meta_file = None
|
||||
members = role_tar_file.getmembers()
|
||||
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', '/etc/ansible/roles'), 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
|
||||
if member.isreg():
|
||||
member.name = "/".join(member.name.split("/")[1:])
|
||||
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)
|
||||
|
||||
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 ""
|
||||
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 = api_get_list(api_server, "platforms")
|
||||
if not platforms:
|
||||
platforms = []
|
||||
categories = api_get_list(api_server, "categories")
|
||||
if not categories:
|
||||
categories = []
|
||||
|
||||
# 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)',
|
||||
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.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
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)
|
||||
api_server = get_opt(options, "api_server", "galaxy.ansible.com")
|
||||
no_deps = get_opt(options, "no_deps", False)
|
||||
|
||||
if len(args) == 0 and not role_file:
|
||||
# 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 role_file:
|
||||
# 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_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)
|
||||
|
||||
roles_done = []
|
||||
if role_file:
|
||||
# roles listed in a file, one per line
|
||||
# so we'll go through and grab them all
|
||||
f = open(role_file, 'r')
|
||||
roles_left = 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 = args
|
||||
|
||||
while len(roles_left) > 0:
|
||||
# query the galaxy API for the role data
|
||||
role_name = roles_left.pop(0).strip()
|
||||
role_version = None
|
||||
|
||||
if role_name == "" or role_name.startswith("#"):
|
||||
continue
|
||||
elif ',' in role_name:
|
||||
role_name,role_version = role_name.split(',',1)
|
||||
role_name = role_name.strip()
|
||||
role_version = role_version.strip()
|
||||
|
||||
if os.path.isfile(role_name):
|
||||
# installing a local tar.gz
|
||||
tar_file = role_name
|
||||
role_name = os.path.basename(role_name).replace('.tar.gz','')
|
||||
if tarfile.is_tarfile(tar_file):
|
||||
print " - installing %s as %s" % (tar_file, role_name)
|
||||
if not install_role(role_name, role_version, tar_file, options):
|
||||
exit_without_ignore(options)
|
||||
else:
|
||||
print "%s (%s) was NOT installed successfully." % (role_name,tar_file)
|
||||
exit_without_ignore(options)
|
||||
else:
|
||||
# installing remotely
|
||||
role_data = api_lookup_role_by_name(api_server, role_name)
|
||||
if not role_data:
|
||||
print "Sorry, %s was not found on %s." % (role_name, api_server)
|
||||
continue
|
||||
|
||||
role_versions = api_fetch_role_related(api_server, 'versions', role_data['id'])
|
||||
if not 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'
|
||||
print " no version specified, installing %s" % role_version
|
||||
else:
|
||||
if role_versions and role_version not in [a.get('name',None) for a in role_versions]:
|
||||
print "The specified version (%s) was not found in the list of available versions." % role_version
|
||||
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_name, role_version, role_data, options)
|
||||
if tmp_file and install_role(role_name, role_version, tmp_file, options):
|
||||
# we're done with the temp file, clean it up
|
||||
os.unlink(tmp_file)
|
||||
# install dependencies, if we want them
|
||||
if not no_deps:
|
||||
role_dependencies = role_data['summary_fields']['dependencies'] # api_fetch_role_related(api_server, 'dependencies', role_data['id'])
|
||||
for dep_name in role_dependencies:
|
||||
#dep_name = "%s.%s" % (dep['owner'], dep['name'])
|
||||
if not get_role_metadata(dep_name, options):
|
||||
print ' adding dependency: %s' % dep_name
|
||||
roles_left.append(dep_name)
|
||||
else:
|
||||
print ' dependency %s is already installed, skipping.' % dep_name
|
||||
else:
|
||||
if tmp_file:
|
||||
os.unlink(tmp_file)
|
||||
print "%s was NOT installed successfully." % role_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()
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
324
bin/ansible-playbook
Executable file
324
bin/ansible-playbook
Executable file
@ -0,0 +1,324 @@
|
||||
#!/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']
|
||||
#import pkg_resources
|
||||
|
||||
import sys
|
||||
import os
|
||||
import stat
|
||||
|
||||
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('-e', '--extra-vars', dest="extra_vars", action="append",
|
||||
help="set additional variables as key=value or YAML/JSON", default=[])
|
||||
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('--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', action='store_true',
|
||||
help="run handlers even if a task fails")
|
||||
|
||||
options, args = parser.parse_args(args)
|
||||
|
||||
if len(args) == 0:
|
||||
parser.print_help(file=sys.stderr)
|
||||
return 1
|
||||
|
||||
# su and sudo command line arguments need to be mutually exclusive
|
||||
if (options.su or options.su_user or options.ask_su_pass) and \
|
||||
(options.sudo or options.sudo_user or options.ask_sudo_pass):
|
||||
parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') "
|
||||
"and su arguments ('-su', '--su-user', and '--ask-su-pass') are "
|
||||
"mutually exclusive")
|
||||
|
||||
if (options.ask_vault_pass and options.vault_password_file):
|
||||
parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
|
||||
|
||||
inventory = ansible.inventory.Inventory(options.inventory)
|
||||
inventory.subset(options.subset)
|
||||
if len(inventory.list_hosts()) == 0:
|
||||
raise errors.AnsibleError("provided hosts list is empty")
|
||||
|
||||
sshpass = None
|
||||
sudopass = None
|
||||
su_pass = None
|
||||
vault_pass = None
|
||||
|
||||
if not options.listhosts and not options.syntax and not options.listtasks:
|
||||
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
|
||||
# Never ask for an SSH password when we run with local connection
|
||||
if options.connection == "local":
|
||||
options.ask_pass = False
|
||||
options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS
|
||||
options.ask_su_pass = options.ask_su_pass or C.DEFAULT_ASK_SU_PASS
|
||||
options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
|
||||
(sshpass, sudopass, su_pass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass)
|
||||
options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER
|
||||
options.su_user = options.su_user or C.DEFAULT_SU_USER
|
||||
|
||||
if options.vault_password_file:
|
||||
this_path = os.path.expanduser(options.vault_password_file)
|
||||
try:
|
||||
f = open(this_path, "rb")
|
||||
tmp_vault_pass=f.read().strip()
|
||||
f.close()
|
||||
except (OSError, IOError), e:
|
||||
raise errors.AnsibleError("Could not read %s: %s" % (this_path, e))
|
||||
|
||||
if not options.ask_vault_pass:
|
||||
vault_pass = tmp_vault_pass
|
||||
|
||||
extra_vars = {}
|
||||
for extra_vars_opt in options.extra_vars:
|
||||
if extra_vars_opt.startswith("@"):
|
||||
# Argument is a YAML file (JSON is a subset of YAML)
|
||||
extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml_from_file(extra_vars_opt[1:], vault_password=vault_pass))
|
||||
elif extra_vars_opt and extra_vars_opt[0] in '[{':
|
||||
# Arguments as YAML
|
||||
extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml(extra_vars_opt))
|
||||
else:
|
||||
# Arguments as Key-value
|
||||
extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt))
|
||||
|
||||
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)
|
||||
|
||||
# run all playbooks specified on the command line
|
||||
for playbook in args:
|
||||
|
||||
# let inventory know which playbooks are using so it can know the basedirs
|
||||
inventory.set_playbook_basedir(os.path.dirname(playbook))
|
||||
|
||||
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,
|
||||
sudo=options.sudo,
|
||||
sudo_user=options.sudo_user,
|
||||
sudo_pass=sudopass,
|
||||
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,
|
||||
su=options.su,
|
||||
su_pass=su_pass,
|
||||
su_user=options.su_user,
|
||||
vault_password=vault_pass,
|
||||
force_handlers=options.force_handlers
|
||||
)
|
||||
|
||||
if options.listhosts or options.listtasks or options.syntax:
|
||||
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)
|
||||
label = play.name
|
||||
hosts = pb.inventory.list_hosts(play.hosts)
|
||||
|
||||
# Filter all tasks by given tags
|
||||
if pb.only_tags != 'all':
|
||||
if options.subset and not hosts:
|
||||
continue
|
||||
matched_tags, unmatched_tags = play.compare_tags(pb.only_tags)
|
||||
|
||||
# Remove skipped tasks
|
||||
matched_tags = matched_tags - set(pb.skip_tags)
|
||||
|
||||
unmatched_tags.discard('all')
|
||||
unknown_tags = ((set(pb.only_tags) | set(pb.skip_tags)) -
|
||||
(matched_tags | unmatched_tags))
|
||||
|
||||
if unknown_tags:
|
||||
continue
|
||||
|
||||
if options.listhosts:
|
||||
print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts))
|
||||
for host in hosts:
|
||||
print ' %s' % host
|
||||
|
||||
if options.listtasks:
|
||||
print ' play #%d (%s):' % (playnum, label)
|
||||
|
||||
for task in play.tasks():
|
||||
if (set(task.tags).intersection(pb.only_tags) and not
|
||||
set(task.tags).intersection(pb.skip_tags)):
|
||||
if getattr(task, 'name', None) is not None:
|
||||
# meta tasks have no names
|
||||
print ' %s' % task.name
|
||||
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 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)
|
||||
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
230
bin/ansible-pull
Executable file
230
bin/ansible-pull
Executable file
@ -0,0 +1,230 @@
|
||||
#!/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 subprocess
|
||||
import sys
|
||||
import datetime
|
||||
import socket
|
||||
import random
|
||||
import time
|
||||
from ansible import utils
|
||||
from ansible.utils import cmd_functions
|
||||
from ansible import errors
|
||||
|
||||
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')
|
||||
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 >>sys.stderr, now.strftime("Starting ansible-pull at %F %T")
|
||||
|
||||
inv_opts = 'localhost,'
|
||||
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
|
||||
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
|
||||
cmd = 'ansible all -i "%s" %s -m %s -a "%s"' % (
|
||||
inv_opts, base_opts, options.module_name, repo_opts
|
||||
)
|
||||
|
||||
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 "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 = 'ansible-playbook %s %s' % (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'
|
||||
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)
|
||||
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# PYTHON_ARGCOMPLETE_OK
|
||||
"""Primary entry point for ansible-test."""
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'test', 'runner')))
|
||||
import lib.cli
|
||||
lib.cli.main()
|
||||
@ -1 +0,0 @@
|
||||
ansible
|
||||
219
bin/ansible-vault
Executable file
219
bin/ansible-vault
Executable file
@ -0,0 +1,219 @@
|
||||
#!/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-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.
|
||||
|
||||
#__requires__ = ['ansible']
|
||||
#import pkg_resources
|
||||
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
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")
|
||||
|
||||
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")
|
||||
|
||||
# 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 == "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 _read_password(filename):
|
||||
f = open(filename, "rb")
|
||||
data = f.read()
|
||||
f.close
|
||||
data = data.strip()
|
||||
return data
|
||||
|
||||
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 = _read_password(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 = _read_password(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("create 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 = _read_password(options.password_file)
|
||||
|
||||
cipher = None
|
||||
|
||||
for f in args:
|
||||
this_editor = VaultEditor(cipher, password, f)
|
||||
this_editor.edit_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 = _read_password(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 = _read_password(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()
|
||||
|
||||
# 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()
|
||||
|
||||
@ -1,821 +0,0 @@
|
||||
releases:
|
||||
2.7.0:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- v2.7.0_summary.yaml
|
||||
release_date: '2018-10-03'
|
||||
2.7.0.a1:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 32738-native-jinja-types.yaml
|
||||
- 42042-inventory_with_no_region.yaml
|
||||
- 42170-acme-backend-selection.yaml
|
||||
- 42647-win_updates.yaml
|
||||
- 42669-add_ssl_zabbix_inventory.yaml
|
||||
- 43024-nclu-empty-net-commands.yaml
|
||||
- 43931-strip-trailing-comments.yml
|
||||
- 44500-win_domain_computer.yaml
|
||||
- 44508-win_lineinfile.yaml
|
||||
- 44552-mail-py370-compat.yml
|
||||
- add_file_lock_feature.yaml
|
||||
- add_random_mac_filtter.yaml
|
||||
- admin-users-default-change.yaml
|
||||
- alternative_facts.yml
|
||||
- ansiballz_one_interpreter.yml
|
||||
- ansiballz_streamline_imports.yaml
|
||||
- any_unparsed_is_failed.yaml
|
||||
- authorized_key_symlinks.yaml
|
||||
- avoid_cwd_vars.yml
|
||||
- aws_caller_facts_add_account_alias.yaml
|
||||
- aws_core_is_boto3_error_code.yml
|
||||
- aws_rds_inventory_plugin_added.yaml
|
||||
- aws_s3_async_fix.yaml
|
||||
- aws_s3_decryption_fix.yaml
|
||||
- aws_s3_fix_custom_endpoints.yaml
|
||||
- basic_booleans_backward_compat.yaml
|
||||
- batch_mode_elasticsearch_plugin.yaml
|
||||
- callback_plugin_merge.yml
|
||||
- clarify_error_message.yml
|
||||
- cleanup__file__.yaml
|
||||
- command_shell_check_mode.yaml
|
||||
- connection_reset.yaml
|
||||
- console_color.yml
|
||||
- deepcopy-alternative.yaml
|
||||
- deprecated-__file__.yaml
|
||||
- docker-default-ssl.yml
|
||||
- drop-python-2.6-controller.yaml
|
||||
- ec2-facts.yaml
|
||||
- ec2_group_diff_mode_support.yml
|
||||
- elasticsearch_plugin-showSTDERRonFailure.yaml
|
||||
- elb_application_lb_fix_state_default.yml
|
||||
- ensure_text_source.yaml
|
||||
- env_inject.yml
|
||||
- file_attributes.yaml
|
||||
- file_touch_check_mode.yaml
|
||||
- file_touch_diff.yaml
|
||||
- fips_md5_import.yaml
|
||||
- fix-255-exit-code.yaml
|
||||
- fix-config-from-environment.yaml
|
||||
- fix-open-url.yml
|
||||
- fix-os_router.yaml
|
||||
- fix-selectors-error-condition.yaml
|
||||
- fix-swap-mount-module.yaml
|
||||
- fix-world-readable-skip-message.yaml
|
||||
- fix_no_log_loop.yml
|
||||
- flatten-better-type-check.yml
|
||||
- from_yaml_all_filter_plugin.yaml
|
||||
- galaxy_list_all_roles.yaml
|
||||
- gce-sort-fix.yaml
|
||||
- get_url.yaml
|
||||
- grafana_5_dashboard_compatible.yaml
|
||||
- hashing-changes.yaml
|
||||
- ignore_unreachable.yml
|
||||
- inventory_dir_ext_compare_fix.yaml
|
||||
- irc_py3_compat.yaml
|
||||
- lineinfile-empty-regexp.yml
|
||||
- lxd-idempotent-config.yaml
|
||||
- mass-remove-deprecated.yaml
|
||||
- missing_interpreter.yml
|
||||
- module_defaults_groups.yml
|
||||
- more-world-readable-warning-skips.yaml
|
||||
- no_log_fix_for_connection_exceptions.yaml
|
||||
- password_sanity_check.yml
|
||||
- passwordstore-lookup-backup.yaml
|
||||
- pause-stdout-redirection.yaml
|
||||
- pause-try-except-curses.yaml
|
||||
- preserve_delegate_nolog.yml
|
||||
- puppet_debugging_options.yaml
|
||||
- remote_tmp_de-escalated_user.yaml
|
||||
- remove-merge-multiple-tags.yaml
|
||||
- remove-simplejson.yaml
|
||||
- remove-unused-ansible-remote-temp.yaml
|
||||
- s3.yaml
|
||||
- service.yml
|
||||
- sns_topic_boto3_port.yaml
|
||||
- syslog_facility-for-journald.yml
|
||||
- template_output_encoding.yml
|
||||
- to-nice-json-separators.yaml
|
||||
- user-freebsd-createhome-name-fix.yaml
|
||||
- user-module-backup-shadow.yaml
|
||||
- user_freebsd_always_changed_bugfix.yaml
|
||||
- v2.7.0-initial-commit.yaml
|
||||
- v2.7.0a1_summary.yaml
|
||||
- vars_prompt-allow-prompting-for-play-vars.yaml
|
||||
- vault-errors.yaml
|
||||
- vultr_modules_renamed.yml
|
||||
- win_become_async_older_hosts.yml
|
||||
- win_chocoalatey_install_tls12.yml
|
||||
- win_chocolatey-bugfixes.yaml
|
||||
- win_chocolatey-return-rc-always.yml
|
||||
- win_domain-dns-typo-fix.yml
|
||||
- win_domain_controller-netlogon.yaml
|
||||
- win_iis_webapppool-output-fix.yml
|
||||
- win_privilege_util.yaml
|
||||
- win_reboot-fixes.yml
|
||||
- win_security_policy-empty-value.yaml
|
||||
- win_updates-async-fix.yml
|
||||
- win_user-validate-fixes.yaml
|
||||
- winrm_kinit-remove-pass-log.yml
|
||||
- wrcwd_ansible.cfg.yml
|
||||
- yum4_dnf_yum_action_plugin.yml
|
||||
- zypper-on-ubuntu.yaml
|
||||
modules:
|
||||
- aci_interface_policy_ospf
|
||||
- acme_account_facts
|
||||
- acme_certificate_revoke
|
||||
- acme_challenge_cert_helper
|
||||
- aws_eks_cluster
|
||||
- azure_rm_appgateway
|
||||
- azure_rm_appserviceplan
|
||||
- azure_rm_appserviceplan_facts
|
||||
- azure_rm_mysqldatabase_facts
|
||||
- azure_rm_mysqlserver_facts
|
||||
- azure_rm_postgresqldatabase_facts
|
||||
- azure_rm_postgresqlserver_facts
|
||||
- azure_rm_route
|
||||
- azure_rm_routetable
|
||||
- azure_rm_routetable_facts
|
||||
- azure_rm_virtualmachine_facts
|
||||
- azure_rm_webapp
|
||||
- bigip_appsvcs_extension
|
||||
- bigip_cli_alias
|
||||
- bigip_cli_script
|
||||
- bigip_device_auth
|
||||
- bigip_device_facts
|
||||
- bigip_firewall_dos_profile
|
||||
- bigip_firewall_policy
|
||||
- bigip_firewall_rule
|
||||
- bigip_firewall_rule_list
|
||||
- bigip_monitor_dns
|
||||
- bigip_profile_http
|
||||
- bigip_profile_http_compression
|
||||
- bigip_profile_oneconnect
|
||||
- bigip_profile_persistence_src_addr
|
||||
- bigip_remote_role
|
||||
- bigip_software_image
|
||||
- bigip_software_install
|
||||
- bigip_tunnel
|
||||
- bigiq_utility_license_assignment
|
||||
- certificate_complete_chain
|
||||
- cli_command
|
||||
- cli_config
|
||||
- cloudformation_stack_set
|
||||
- cobbler_sync
|
||||
- cobbler_system
|
||||
- cs_disk_offering
|
||||
- docker_swarm
|
||||
- docker_swarm_service
|
||||
- emc_vnx_sg_member
|
||||
- exos_config
|
||||
- exos_facts
|
||||
- gcp_compute_address_facts
|
||||
- gcp_compute_backend_bucket_facts
|
||||
- gcp_compute_backend_service_facts
|
||||
- gcp_compute_disk_facts
|
||||
- gcp_compute_firewall_facts
|
||||
- gcp_compute_forwarding_rule_facts
|
||||
- gcp_compute_global_address_facts
|
||||
- gcp_compute_global_forwarding_rule_facts
|
||||
- gcp_compute_health_check_facts
|
||||
- gcp_compute_http_health_check_facts
|
||||
- gcp_compute_https_health_check_facts
|
||||
- gcp_compute_image_facts
|
||||
- gcp_compute_instance_facts
|
||||
- gcp_compute_instance_group_facts
|
||||
- gcp_compute_instance_group_manager_facts
|
||||
- gcp_compute_instance_template_facts
|
||||
- gcp_compute_network_facts
|
||||
- gcp_compute_route_facts
|
||||
- gcp_compute_router_facts
|
||||
- gcp_compute_ssl_certificate_facts
|
||||
- gcp_compute_ssl_policy
|
||||
- gcp_compute_ssl_policy_facts
|
||||
- gcp_compute_subnetwork_facts
|
||||
- gcp_compute_target_http_proxy_facts
|
||||
- gcp_compute_target_https_proxy_facts
|
||||
- gcp_compute_target_pool_facts
|
||||
- gcp_compute_target_ssl_proxy_facts
|
||||
- gcp_compute_target_tcp_proxy_facts
|
||||
- gcp_compute_target_vpn_gateway
|
||||
- gcp_compute_target_vpn_gateway_facts
|
||||
- gcp_compute_url_map_facts
|
||||
- gcp_compute_vpn_tunnel
|
||||
- gcp_compute_vpn_tunnel_facts
|
||||
- ibm_sa_vol
|
||||
- ipa_config
|
||||
- ipa_vault
|
||||
- java_keystore
|
||||
- k8s_facts
|
||||
- meraki_config_template
|
||||
- meraki_device
|
||||
- meraki_mr_l3_firewall
|
||||
- meraki_mx_l3_firewall
|
||||
- meraki_ssid
|
||||
- meraki_switchport
|
||||
- meraki_vlan
|
||||
- na_elementsw_backup
|
||||
- na_elementsw_cluster_pair
|
||||
- na_elementsw_snapshot_schedule
|
||||
- na_elementsw_vlan
|
||||
- na_elementsw_volume
|
||||
- na_elementsw_volume_pair
|
||||
- na_ontap_cg_snapshot
|
||||
- na_ontap_dns
|
||||
- na_ontap_fcp
|
||||
- na_ontap_snapmirror
|
||||
- na_ontap_software_update
|
||||
- na_ontap_svm_options
|
||||
- na_ontap_vserver_peer
|
||||
- netcup_dns
|
||||
- nios_a_record
|
||||
- nios_cname_record
|
||||
- nios_mx_record
|
||||
- nios_naptr_record
|
||||
- nios_ptr_record
|
||||
- nios_srv_record
|
||||
- nios_txt_record
|
||||
- nos_command
|
||||
- nos_config
|
||||
- nos_facts
|
||||
- nxos_rpm
|
||||
- onyx_igmp
|
||||
- openssl_pkcs12
|
||||
- os_coe_cluster_template
|
||||
- os_listener
|
||||
- os_loadbalancer
|
||||
- os_member
|
||||
- os_pool
|
||||
- panos_set
|
||||
- python_requirements_facts
|
||||
- reboot
|
||||
- redfish_facts
|
||||
- routeros_command
|
||||
- scaleway_image_facts
|
||||
- scaleway_ip_facts
|
||||
- scaleway_organization_facts
|
||||
- scaleway_security_group_facts
|
||||
- scaleway_server_facts
|
||||
- scaleway_snapshot_facts
|
||||
- scaleway_volume
|
||||
- scaleway_volume_facts
|
||||
- slxos_lldp
|
||||
- tower_inventory_source
|
||||
- ucs_ntp_server
|
||||
- ucs_storage_profile
|
||||
- ucs_timezone
|
||||
- ucs_uuid_pool
|
||||
- vmware_about_facts
|
||||
- vmware_category
|
||||
- vmware_category_facts
|
||||
- vmware_deploy_ovf
|
||||
- vmware_guest_boot_facts
|
||||
- vmware_guest_boot_manager
|
||||
- vmware_guest_custom_attribute_defs
|
||||
- vmware_guest_custom_attributes
|
||||
- vmware_guest_move
|
||||
- vmware_host_ssl_facts
|
||||
- vmware_local_role_facts
|
||||
- voss_command
|
||||
- voss_facts
|
||||
- vultr_block_storage
|
||||
- vultr_block_storage_facts
|
||||
- vultr_dns_domain_facts
|
||||
- vultr_firewall_group_facts
|
||||
- vultr_network
|
||||
- vultr_network_facts
|
||||
- vultr_os_facts
|
||||
- vultr_plan_facts
|
||||
- vultr_region_facts
|
||||
- vultr_server_facts
|
||||
- vultr_ssh_key_facts
|
||||
- vultr_startup_script_facts
|
||||
- vultr_user_facts
|
||||
- win_chocolatey_config
|
||||
- win_chocolatey_feature
|
||||
- win_chocolatey_source
|
||||
- zabbix_host_facts
|
||||
plugins:
|
||||
callback:
|
||||
- counter_enabled
|
||||
- logdna
|
||||
- splunk
|
||||
connection:
|
||||
- psrp
|
||||
inventory:
|
||||
- tower
|
||||
lookup:
|
||||
- cpm_status
|
||||
- grafana_dashboard
|
||||
- nios_next_network
|
||||
release_date: '2018-08-27'
|
||||
2.7.0b1:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- blockdoc.yml
|
||||
- delegate-to-get-vars-no-task.yaml
|
||||
- gcp_service_account_home_path.yaml
|
||||
- include-apply-insert-order.yaml
|
||||
- include-double-handler.yaml
|
||||
- loop-cache-fix.yaml
|
||||
- no-dynamic-import-tasks.yaml
|
||||
- onepassword_unlock_vault.yaml
|
||||
- plugins-accept-only-valid-args.yaml
|
||||
- urls-if-modified-since.yaml
|
||||
- v2.7.0b1_summary.yaml
|
||||
- win_disk_image-mount-paths.yaml
|
||||
- win_psexec_command_arg.yaml
|
||||
- win_psexec_session-selection.yaml
|
||||
- win_uri-json.yml
|
||||
- win_wait_for-timeout.yaml
|
||||
modules:
|
||||
- azure_rm_autoscale
|
||||
- azure_rm_autoscale_facts
|
||||
- azure_rm_containerregistry_facts
|
||||
- azure_rm_sqlfirewallrule
|
||||
- azure_rm_trafficmanagerendpoint
|
||||
- azure_rm_trafficmanagerendpoint_facts
|
||||
- azure_rm_trafficmanagerprofile
|
||||
- azure_rm_trafficmanagerprofile_facts
|
||||
- azure_rm_webapp_facts
|
||||
- cpm_user
|
||||
- elb_target_facts
|
||||
- fmgr_provisioning
|
||||
- ftd_configuration
|
||||
- ftd_file_download
|
||||
- ftd_file_upload
|
||||
- gcp_compute_router
|
||||
- gcp_spanner_database
|
||||
- gcp_spanner_instance
|
||||
- gcp_sql_database
|
||||
- gcp_sql_instance
|
||||
- gcp_sql_user
|
||||
- ibm_sa_host
|
||||
- ibm_sa_pool
|
||||
- na_elementsw_access_group
|
||||
- na_elementsw_account
|
||||
- na_elementsw_admin_users
|
||||
- na_elementsw_check_connections
|
||||
- na_elementsw_cluster
|
||||
- na_elementsw_drive
|
||||
- na_elementsw_ldap
|
||||
- na_elementsw_network_interfaces
|
||||
- na_elementsw_node
|
||||
- na_elementsw_snapshot
|
||||
- na_elementsw_snapshot_restore
|
||||
- na_elementsw_volume_clone
|
||||
- na_ontap_autosupport
|
||||
- na_ontap_cluster_peer
|
||||
- na_ontap_command
|
||||
- na_ontap_disks
|
||||
- na_ontap_firewall_policy
|
||||
- na_ontap_gather_facts
|
||||
- na_ontap_motd
|
||||
- na_ontap_node
|
||||
- netapp_e_alerts
|
||||
- netapp_e_asup
|
||||
- netapp_e_auditlog
|
||||
- netapp_e_global
|
||||
- netapp_e_iscsi_interface
|
||||
- netapp_e_iscsi_target
|
||||
- netapp_e_ldap
|
||||
- netapp_e_mgmt_interface
|
||||
- netapp_e_syslog
|
||||
- onepassword_facts
|
||||
- opx_cps
|
||||
- purefb_facts
|
||||
- rds_instance
|
||||
- redfish_command
|
||||
- redfish_config
|
||||
- tower_credential_type
|
||||
- tower_settings
|
||||
- tower_workflow_template
|
||||
- vmware_host_ntp_facts
|
||||
- win_wait_for_process
|
||||
- win_xml
|
||||
plugins:
|
||||
lookup:
|
||||
- cpm_metering
|
||||
release_date: '2018-08-31'
|
||||
2.7.0rc1:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 16748-docker_container-memory.yaml
|
||||
- 33579-docker_container-log_driver.yaml
|
||||
- 42380-docker_container-check-mode.yaml
|
||||
- 42641-44812-docker-env-variables.yaml
|
||||
- 42857-docker_container-working_dir.yaml
|
||||
- 44808-docker_container-idempotency.yaml
|
||||
- aws_bugfix_backports.yml
|
||||
- cb_fix_config.yml
|
||||
- dnf-group-removal.yaml
|
||||
- ec2_vpc_route_table_replace_route_fix.yaml
|
||||
- elb_target_group_fix_KeyError.yaml
|
||||
- systemd_user_dep_fixes.yml
|
||||
- terminal_plugin_nxos_iosxr.yaml
|
||||
- v2.7.0rc1_summary.yaml
|
||||
modules:
|
||||
- online_user_facts
|
||||
release_date: '2018-09-06'
|
||||
2.7.0rc2:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 45501-get_url-better_checksums.yaml
|
||||
- aws_cloudfront_distribution_fix_nonexistent_method_name.yaml
|
||||
- azure-storage-cloud-environment.yaml
|
||||
- azure_autoscale.yaml
|
||||
- get-url-fix-idempotency.yaml
|
||||
- loop_undefined_delegate_to.yaml
|
||||
- nxos_ambiguous_command_check.yaml
|
||||
- script-module-no-file-path.yaml
|
||||
- v2.7.0rc2_summary.yaml
|
||||
- vmware_wait_for_task_fix.yaml
|
||||
- win_group_membership-com-marshal.yaml
|
||||
- win_say-fix.yaml
|
||||
plugins:
|
||||
strategy:
|
||||
- host_pinned
|
||||
release_date: '2018-09-13'
|
||||
2.7.0rc3:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- ec2_group_fix_target_containing_list_within_list.yaml
|
||||
- fix_nxos_facts_indefinite_hang.yaml
|
||||
- v2.7.0rc3_summary.yaml
|
||||
release_date: '2018-09-20'
|
||||
2.7.0rc4:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- v2.7.0rc4_summary.yaml
|
||||
release_date: '2018-09-27'
|
||||
2.7.1:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 33156-vmware_guest-resource_pool.yaml
|
||||
- 34863-rabbitmq_user_unpack_fix.yaml
|
||||
- 35120-redis_inventory_plugin_flush_cache.yaml
|
||||
- 38679-vmware_guest-refactor_disk_logic.yml
|
||||
- 42322-nmcli_fix_vlan_mod_function.yaml
|
||||
- 42456-consul_kv-lookup.yaml
|
||||
- 43997-docker_network-inspect.yaml
|
||||
- 44755-win_nssm_fixes.yaml
|
||||
- 45226-vmware_wait_for_ip_address.yaml
|
||||
- 45417-ldap_entry-list_conversion.yml
|
||||
- 45508-parse-docker-service-parameter.yaml
|
||||
- 45543-rabbitmq_bindings-fix-quote.yaml
|
||||
- 45628-fetch_url-error-headers.yaml
|
||||
- 45700-docker_container-dont-parse-absent.yml
|
||||
- 45712-45753-vultr-timeout.yml
|
||||
- 45830-fixed-assigning-ssl-certificate.yaml
|
||||
- 45921-os_router-ignores-enable_snat-no.yml
|
||||
- 46049-route53-caa-ordering.txt
|
||||
- 46115-46035-cs_instance-fixes.yml
|
||||
- 46245-systemd-fix-service-enable-logic.yaml
|
||||
- 46322-docker_container-image-not-given.yaml
|
||||
- 46521-zabbix_host-fix-link-template-error.yml
|
||||
- 46594-docker_container-publish-all-ports.yml
|
||||
- 46595-docker_container-expected_ports.yml
|
||||
- 46743-fix-native-jinja-newlines.yaml
|
||||
- 46800-ec2_vol_facts-handle-missing-tags.yml
|
||||
- 46961_fix_aws_ec2_cache.yaml
|
||||
- 47046-docker-versions.yaml
|
||||
- 47096-junos-terminal-regex-fix.yml
|
||||
- 47109-fail-space-separated-string-pkgs.yaml
|
||||
- 47133-pamd_use_module_tmpdir.yml
|
||||
- 47281-pamd-dont-delete-named_temporary_file_on_close.yaml
|
||||
- 47296-docker_container-memory_swappiness.yaml
|
||||
- 47307-handler-include-task.yml
|
||||
- 47395-docker_container-ipvX_address.yaml
|
||||
- 47396-docker_container-detach-auto-remove.yaml
|
||||
- 54434-iam-role-arn-parsing.yml
|
||||
- ajson-nested-decode.yaml
|
||||
- ansible-connection-cleanup-when-failed.yaml
|
||||
- ansible-doc-fixes.yml
|
||||
- aws_parameter_store_pagination.yaml
|
||||
- azure-version.yaml
|
||||
- azure_rm_autoscale-fixed_date.yml
|
||||
- azure_rm_deployment_fix_45941.yaml
|
||||
- blockinfile-bytes-fix.yaml
|
||||
- callback_fixes.yml
|
||||
- cliconf-get-bugfixes.yaml
|
||||
- dd-put-empty-files.yaml
|
||||
- delegate_to_loop_hostvars.yaml
|
||||
- dnf-immutable-mutable.yaml
|
||||
- dnf-localgpgcheck.yaml
|
||||
- dnfyum-disable-excludes.yaml
|
||||
- docker_container-idempotency.yaml
|
||||
- docker_volume-force-change-detection.yaml
|
||||
- fix_calling_deprecate_with_correct_arguments.yaml
|
||||
- fix_ec2_group_target_vpc_precedence.yaml
|
||||
- fix_flatten.yml
|
||||
- fix_vyos_version.yaml
|
||||
- free-strategy-include-var-tags.yaml
|
||||
- ftd-http-api-plugin-refresh-token.yaml
|
||||
- get_url-remove-fragile-code.yaml
|
||||
- inv_fixes.yml
|
||||
- ios-prompt-fix.yaml
|
||||
- ip_netns-fix-exists.yaml
|
||||
- issue46937-pr46519-pr47449-fix-pip-multiple-extras.yaml
|
||||
- k8s_auth_kubeconfig.yml
|
||||
- k8s_facts_fix.yaml
|
||||
- lineinfile-insertbefore-index-out-of-range.yaml
|
||||
- mail-fix-regression.yaml
|
||||
- mysql-migrate_to_pymysql.yaml
|
||||
- netconf_config_comfirm_commit_fix.yaml
|
||||
- netconf_config_default_operation.yaml
|
||||
- netconf_module_utils_py3_fix.yaml
|
||||
- no-mutable-fieldattribute-defaults.yaml
|
||||
- no-overwrite-roles.yaml
|
||||
- nxos_file_copy_PY3_fix.yaml
|
||||
- nxos_ospf_vrf_idempotence.yaml
|
||||
- openssl-python3.yaml
|
||||
- ovirt_host_network_check_for_empty_user_opts.yaml
|
||||
- ovirt_vm__Fix_initialization_of_cloud_init.yaml
|
||||
- ovirt_vm_check_next_run_configuration_update_if_exist.yaml
|
||||
- ovirt_vm_fix_issue_in_SSO_option.yaml
|
||||
- ovirt_vm_fix_issue_in_setting_the_custom_compatibility_version_to_NULL.yaml
|
||||
- piped-transfer-empty-files.yaml
|
||||
- plugin-docs-list-fix.yaml
|
||||
- plugin-filters-cfg.yaml
|
||||
- postgresql_user-not-sup-error.yaml
|
||||
- psexec-handle-socket-errors.yaml
|
||||
- psexec-imp-error.yaml
|
||||
- psrp-utf8-stdio.yaml
|
||||
- psrp-utf8.yaml
|
||||
- reboot-unicode-string.yaml
|
||||
- reboot-var-fix-bare-linux.yaml
|
||||
- reboot_missing_parameter.yaml
|
||||
- reboot_openbsd_support.yaml
|
||||
- restore_sigpipe_dfl.yml
|
||||
- solaris-prtdiag-path.yaml
|
||||
- telent-prompt-fix.yaml
|
||||
- unsafe-set-wrap.yaml
|
||||
- user-do-not-pass-ssh_key_passphrase-on-cmdline.yaml
|
||||
- user-docs-underlying-tools.yaml
|
||||
- v2.7.1
|
||||
- win_copy-dest-quote.yaml
|
||||
- win_reboot-post-reboot-delay.yaml
|
||||
- winrm_pexpect.yaml
|
||||
- yum-proxy-userpass.yaml
|
||||
- yum_bugfux.yml
|
||||
- yum_bugfux_conf_file_none_type.yml
|
||||
release_date: '2018-10-25'
|
||||
2.7.2:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 44324-ini_file-options-with-no-section-managed.yaml
|
||||
- 44988-acme-post-as-get.yaml
|
||||
- 45151-fix-os-exception.yaml
|
||||
- 45704-fix-redfish_facts-http-redirect.yaml
|
||||
- 46148-provide-redfish_facts-gathering-flexibility.yaml
|
||||
- 46658-plugin_filter-improve_error_handling.yaml
|
||||
- 46665-plugin_filter_doc_fix.yaml
|
||||
- 46700-vmware_doc-standalone_esxi.yaml
|
||||
- 47030-assert-add-success_msg-to-valid-args.yaml
|
||||
- 47117-vmware_doc-http_api_usage.yaml
|
||||
- 47300-ios-check_rc.yaml
|
||||
- 47313-vmware_utils-handle_requests_import_error.yaml
|
||||
- 47459_grafana_dashboard_consistency_fix.yaml
|
||||
- 47462-fix-redfish_config-idempotency.yaml
|
||||
- 47563-vmware_host-refactor_SSL_thumbprint.yaml
|
||||
- 47608-docker_swarm-advertise_addr.yml
|
||||
- 47621-bugfix-for-na-ontap-snapmirror.yaml
|
||||
- 47668-aci_switch_leaf_selector-support_empty_policy_group.yaml
|
||||
- 47689-yum-fix-version-syntax.yaml
|
||||
- 47693-fix-argument-spec-for-netapp-modules.yaml
|
||||
- 47695-pamd-fix-idempotence-and-parsing-issues.yml
|
||||
- 47711-docker_container-minimal-version-checks.yml
|
||||
- 47712-docker_container-detach-auto-remove.yml
|
||||
- 47722-vmware_guest_powerstate-restore_timeout.yaml
|
||||
- 47889-vmware_doc-fix_privilege_names.yaml
|
||||
- 47900-docker_container-paused.yml
|
||||
- 47920-vmware_guest-handle_no_root_snapshot.yaml
|
||||
- 47938-docker_swarm_service-requirements.yaml
|
||||
- 47997-docker_container-ipc-pid-mode.yml
|
||||
- 48009-ldap_attr-list.yml
|
||||
- 48036-vultr-fix-empty-list-handling.yaml
|
||||
- 48061-docker_container-auto_removal.yml
|
||||
- 48148_net_put_cleanup.yaml
|
||||
- 48317-do-not-auto-reboot-with-redfish_config-bios-changes
|
||||
- 48341-ebs-optimized-ec2-instance.yaml
|
||||
- 48342-vultr_server_facts-fix-firewall-group.yml
|
||||
- 48474-k8s-module-docs-update.yaml
|
||||
- 48536-docker_volume-labels.yml
|
||||
- 48551-docker_container-idempotency.yml
|
||||
- 48590-docker_container-unpause-stop.yml
|
||||
- aci_access_port_to_interface_policy_leaf_profile-missing_policy_group.yaml
|
||||
- aci_interface_policy_leaf_policy_group-missing_aep.yaml
|
||||
- django_manage_status.yaml
|
||||
- fix-password-lookup-on-fips.yaml
|
||||
- galaxy-metea-yaml-extension.yaml
|
||||
- loop-cache-include-apply.yml
|
||||
- lvg_fix_47301.yaml
|
||||
- nxos_evpn_vni_check_mode.yaml
|
||||
- nxos_facts_trailing_comma.yaml
|
||||
- nxos_install_os_force_disruptive.yaml
|
||||
- os_router_enable_snat_fix.yaml
|
||||
- ovirt_host_network_fix_type_conversion.yaml
|
||||
- ovirt_host_pm_bug_fixes_for_power_management.yaml
|
||||
- pip-fix-idempotence-in-check-mode.yaml
|
||||
- reboot-change-default-boot-command.yaml
|
||||
- remove_redundant_md5.yml
|
||||
- tls_mail.yml
|
||||
- uri-supports-async.yaml
|
||||
- user-fix-zero-negative-expiration.yaml
|
||||
- user-password_lock-change-fix.yaml
|
||||
- user-restore-disabled-account.yaml
|
||||
- v2.7.2_summary.yaml
|
||||
- win_uri-junk-data.yaml
|
||||
- yum-handle-obsoletes-check-update.yaml
|
||||
- yumdnf-autoremove.yaml
|
||||
release_date: '2018-11-15'
|
||||
2.7.3:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 15732-wait_for-documentation_fix.yaml
|
||||
- 46044-puppet-puppet6-fix.yaml
|
||||
- 47198-fix-setuptools-distutils.yaml
|
||||
- 47747-ftd-http-api-fixes.yaml
|
||||
- 48580-apt_key-no-tty.yaml
|
||||
- 48673-fix-omit-on-play-keywords.yaml
|
||||
- 48675-cs_template-fix-keyerror-state-extracted.yml
|
||||
- 48809-sysvinit_defaults_if_no_runlevels.yaml
|
||||
- 48836-proxymox_kvm-dictionary.yaml
|
||||
- 49078-docker_container-min-version-fix.yml
|
||||
- cfg_mgr_fix.yml
|
||||
- deal_with_bad_config_types.yml
|
||||
- dnf-modularity.yaml
|
||||
- docker_network-driver_options.yaml
|
||||
- ec2_group-rule-purge-fix.yaml
|
||||
- ps_sb_logging.yaml
|
||||
- v2.7.3_summary.yaml
|
||||
- win_security_policy-rights.yaml
|
||||
release_date: '2018-11-29'
|
||||
2.7.4:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- powershell-bootstrap.yaml
|
||||
- v2.7.4_summary.yaml
|
||||
release_date: '2018-11-30'
|
||||
2.7.5:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 33239-sensu-expire-cast-int.yaml
|
||||
- 45122-fix-unarchive-excluded_files.yaml
|
||||
- 45155-vmware-handle_exception.yaml
|
||||
- 45155-vmware_host_service_facts-update_docs.yaml
|
||||
- 46604-ontap-cifs-server-no-log-password.yaml
|
||||
- 46740-gcp-utils-credentials-scoping.yaml
|
||||
- 47019-mail-fix-py27-regression.yaml
|
||||
- 47313-vmware-fix_module_error.yaml
|
||||
- 48728-win_nssm-credential-quoting.yml
|
||||
- 48730-zabbix_hostmacro-fixes.yml
|
||||
- 48792-templar-fix-AttributeError.yml
|
||||
- 48950-vault-encrypted-data-native-jinja.yaml
|
||||
- 49096-ansible-galaxy-fix_info_typo.yaml
|
||||
- 49113-iam-role-arn-parsing-updated.yml
|
||||
- 49123-backport-devuan-support.yml
|
||||
- 49212-require-git-ansible-galaxy.yaml
|
||||
- 49235-docker_swarm_service-user-default.yaml
|
||||
- 49266-acme-error-messages.yml
|
||||
- 49299-openshift-inventory-plugin-empty-pods-and-serialization.yaml
|
||||
- 49394_azure_image.yml
|
||||
- 49407-acme-disabled-accounts.yml
|
||||
- 49474-network_utils_dict_merge_fix.yaml
|
||||
- 49553-aci_rest-fix-ignoring-custom-port.yaml
|
||||
- avoid_ssh_retry_discolsures.yml
|
||||
- azure_rm_subnet_route_table.yaml
|
||||
- clear_system_variablse.yml
|
||||
- detect_interpreter_stdout.yml
|
||||
- dnf-fix-plugin-loading.yaml
|
||||
- docker-swarm-min-ver.yaml
|
||||
- iosxr_netconf_plugin_fix.yaml
|
||||
- jinja2_native-fallback-warning.yaml
|
||||
- nxos_facts_multiple_bugfixes.yaml
|
||||
- nxos_install_os_nxapi_fix.yaml
|
||||
- nxos_interface_linkagg_idempotence.yaml
|
||||
- openstack-fixes-for-2.7.5.yaml
|
||||
- ovirt_storage_connection_password-comparison.yaml
|
||||
- parimko_ssh-log-message.yaml
|
||||
- reboot-fix-exception-type.yaml
|
||||
- redis-3-compat.yaml
|
||||
- squash-deprecation-message.yml
|
||||
- v2.7.5_summary.yaml
|
||||
- vm_fix.yml
|
||||
release_date: '2018-12-13'
|
||||
2.7.6:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 46739-gcp-compute-instance-metadata.yaml
|
||||
- 46774-ec2_instance_check_mode_fix.yaml
|
||||
- 49084-influxdb_user-default-password-fix.yaml
|
||||
- 49194-grafana_string_handling_fix.yml
|
||||
- 49409-lineinfile_must_not_insert_lines_multiples_times_with_insertbefore_insertafter.yml
|
||||
- 49758-azure_vmss_update_image_reference_fix.yaml
|
||||
- 49794-docker_container-network-mode.yml
|
||||
- 49843-docker_container-wrap-env.yaml
|
||||
- 49922-network-cli-timeout.yaml
|
||||
- 49987-certificate_complete_chain-error.yml
|
||||
- 50034-move-import-errors.yaml
|
||||
- 50076-os-sec-group-rule-proper-module-exit.yaml
|
||||
- 50134-influxdb_user-invalid_auth_fix.yml
|
||||
- 50143-win_firewall_rule-invalid-bypass.yml
|
||||
- 50169-netconf-connection-log.yaml
|
||||
- 50185-win_updates-report-changes-correctly.yml
|
||||
- 50249-vmware_vm_inventory-fix_host_ip.yaml
|
||||
- 50298-redfish_utils_fix_reference_to_local_variable_systems_service.yaml
|
||||
- 50322-openssl-path-error.yml
|
||||
- 50337-fix-vultr_server-ssh_keys-handling.yml
|
||||
- 50361-openssl_csr-idempotency.yml
|
||||
- 50448-paramiko_ssh_add_auth_timeout.yaml
|
||||
- 50540-fix-lastpass-lookup-error.yaml
|
||||
- 50654-docker-swarm-service-docker-api-fix.yaml
|
||||
- 50655-docker_swarm_service-update_order-idempotency.yml
|
||||
- 50697-openssl_pkcs12-ca_certificates.yaml
|
||||
- 50861-docker_swarm_service-documentation-fixes.yml
|
||||
- acl_doc_fix.yml
|
||||
- callback-keep-more-debug-keys.yml
|
||||
- copy-diff-text.yaml
|
||||
- dnf-conf-file.yaml
|
||||
- dnf-update-cache-broken-transaction.yaml
|
||||
- docker_volume-force-change-detection-revert.yaml
|
||||
- firewalld-missing-port-protocol.yml
|
||||
- fix_vmware_inv.yml
|
||||
- flatpak-compatibility-fixes.yaml
|
||||
- icinga2_host-47671-fix-use_proxy.yaml
|
||||
- junos_commit_error_fix.yaml
|
||||
- openstack_inventory_fix.yml
|
||||
- os-family_distro_variable_clearlinux.yaml
|
||||
- persistent-socket-lock-name.yaml
|
||||
- playbook-order-reverse_inventory.yaml
|
||||
- pure_facts_fix.yaml
|
||||
- reboot-add-aix-support.yml
|
||||
- reboot-path-alpine-solaris.yaml
|
||||
- reboot-vmware-esxi.yaml
|
||||
- v2.7.6_summary.yaml
|
||||
- win_copy-empty-dir.yaml
|
||||
- win_lineinfile-output.yaml
|
||||
- windows_setup_memtotal.yml
|
||||
- yumdnf-better-uri-handling.yaml
|
||||
release_date: '2019-01-17'
|
||||
2.7.7:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 24633-copy-coherency-between-check-normal-mode.yaml
|
||||
- 47213-onepassword_facts_fix_password_lookup.yaml
|
||||
- 49444_fix_check_if_archive_is_created_in_path_to_be_removed.yml
|
||||
- 50006-azure_rm_inventory_batchrequest_fix.yaml
|
||||
- 50248-fix-coonfig-backup-glob.yaml
|
||||
- 51232-docker_swarm_service-endpoint_mode.yaml
|
||||
- 51406-aci_aaa_user-description.yaml
|
||||
- 51495-k8s-load-envvars.yaml
|
||||
- 51602-ec2_instance_single_iface_description.yaml
|
||||
- cli_config_diff_fix.yaml
|
||||
- delegate_facts_fix.yaml
|
||||
- file-touch-non-owner.yaml
|
||||
- fix_ansible_connect_timeout.yaml
|
||||
- fix_ir_dupes.yml
|
||||
- fix_pull_extra.yml
|
||||
- nios_a_record_delete_failure_with_uppercase_name.yaml
|
||||
- py37_misc_module_backports.yaml
|
||||
- reboot-conn-timeout-reset.yaml
|
||||
- ssh_connection_invalid_password.yaml
|
||||
- systemd-warn-on-chroot.yaml
|
||||
- v2.7.7_summary.yaml
|
||||
- vmware_guest-documentation_fix.yaml
|
||||
- win_chocolatey.yaml
|
||||
- win_power_plan-windows10.yaml
|
||||
- xdg_systemd_fix.yml
|
||||
release_date: '2019-02-07'
|
||||
2.7.8:
|
||||
codename: In the Light
|
||||
fragments:
|
||||
- 45269-fix-vm-crashing.yaml
|
||||
- 45378-fix-sql-tags.yml
|
||||
- 46478-haproxy-fix-drain-mode.yaml
|
||||
- 49485-ios-retry-section.yaml
|
||||
- 49704-fix-vm-facts-crash.yaml
|
||||
- 50120-fix-vm-facts-managed-disk.yaml
|
||||
- 50402-ufw-check-direction.yml
|
||||
- 51028-get-standard-redfish-properties-for-firmware-entries.yaml
|
||||
- 51473-openssl_csr-idempotence.yaml
|
||||
- 51535-ec2-fix-spot-request-end-date.yaml
|
||||
- 51653-fixing-azure-postgresql-parameters.yaml
|
||||
- 51661-fixing-azure-mysql-parameters.yaml
|
||||
- 51697-disable_excludes-errors-with-disable-includes-message.yaml
|
||||
- 51764-update-getbiosbootorder-to-standard-redfish-resources.yaml
|
||||
- 51781-fixing-managed-disk-facts.yaml
|
||||
- 51795-acme_challenge_cert_helper-module-fail.yaml
|
||||
- 51827-openstack_logs_to_stderr.yml
|
||||
- 52130-win_psmodule-update_nuget.yaml
|
||||
- 52158-jinja2-native-types-contructed-keyed-groups.yaml
|
||||
- 52388-postgresqldatabase-fix-force-update.yml
|
||||
- 52389-mysqldatabase-fix-force-update.yaml
|
||||
- allow_regions_aws_invp.yml
|
||||
- disallow-relative-homedir.yaml
|
||||
- psrp-display-exec-output.yaml
|
||||
- ufw-reset-check-mode.yaml
|
||||
- v2.7.8_summary.yaml
|
||||
- win-become-elevation.yaml
|
||||
- winrm-ansible-conn-error.yaml
|
||||
- yum-unauthenticated-proxy.yaml
|
||||
release_date: '2019-02-21'
|
||||
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
@ -1,13 +0,0 @@
|
||||
---
|
||||
release_tag_re: '(v(?:[\d.ab\-]|rc)+)'
|
||||
pre_release_tag_re: '(?P<pre_release>(?:[ab]|rc)+\d*)$'
|
||||
notesdir: fragments
|
||||
prelude_section_name: release_summary
|
||||
new_plugins_after_name: removed_features
|
||||
sections:
|
||||
- ['major_changes', 'Major Changes']
|
||||
- ['minor_changes', 'Minor Changes']
|
||||
- ['deprecated_features', 'Deprecated Features']
|
||||
- ['removed_features', 'Removed Features (previously deprecated)']
|
||||
- ['bugfixes', 'Bugfixes']
|
||||
- ['known_issues', 'Known Issues']
|
||||
@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- Document Path and Port are mutually exclusive parameters in wait_for module.
|
||||
@ -1,5 +0,0 @@
|
||||
bugfixes:
|
||||
- "docker_container: makes unit parsing for memory sizes more consistent, and
|
||||
fixes idempotency problem when ``kernel_memory`` is set (see
|
||||
https://github.com/ansible/ansible/pull/16748 and
|
||||
https://github.com/ansible/ansible/issues/42692)"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- copy - align invocation in return value between check and normal mode
|
||||
@ -1,2 +0,0 @@
|
||||
major_changes:
|
||||
- Allow config to enable native jinja types (https://github.com/ansible/ansible/pull/32738)
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- Rewrite get_resource_pool method for correct resource_pool selection.
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- sensu_silence - Cast int for expire field to avoid call failure to sensu API.
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "Allow arbitrary ``log_driver`` for docker_container (https://github.com/ansible/ansible/pull/33579)."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- Ignore empty result of rabbitmqctl list_user_permissions.
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- Only delete host key from redis in-memory cache if present.
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- Refactor virtual machine disk logic.
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- plugins/inventory/openstack.py - Do not create group with empty name if region is not set
|
||||
@ -1,8 +0,0 @@
|
||||
---
|
||||
minor_changes:
|
||||
- "The acme_account and acme_certificate modules now support two backends:
|
||||
the Python cryptograpy module or the OpenSSL binary. By default, the
|
||||
modules detect if a new enough cryptography module is available and
|
||||
use it, with the OpenSSL binary being a fallback. If the detection
|
||||
fails for some reason, the OpenSSL binary backend can be explicitly
|
||||
selected by setting select_crypto_backend to openssl."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "nmcli - fix syntax of vlan modification command (https://github.com/ansible/ansible/issues/42322)"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "fixes docker_container check and debug mode (https://github.com/ansible/ansible/pull/42380)"
|
||||
@ -1,3 +0,0 @@
|
||||
minor_changes:
|
||||
- added capability to set the scheme for the consul_kv lookup.
|
||||
- added optional certificate and certificate verification for consul_kv lookups
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "The docker_* modules respect the DOCKER_* environment variables again (https://github.com/ansible/ansible/pull/42641)."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- win_updates - fixed module return value is lost in error in some cases (https://github.com/ansible/ansible/pull/42647)
|
||||
@ -1,4 +0,0 @@
|
||||
---
|
||||
minor_changes:
|
||||
- Added capability to skip ssl verification
|
||||
on zabbix host with dynamic inventory
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "docker_container: fixing ``working_dir`` idempotency problem (https://github.com/ansible/ansible/pull/42857)"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- nclu - no longer runs net on empty lines in templates (https://github.com/ansible/ansible/pull/43024)
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- user - Strip trailing comments in /etc/default/passwd (https://github.com/ansible/ansible/pull/43931)
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "docker_network - fixes idempotency issues (https://github.com/ansible/ansible/issues/33045) and name substring issue (https://github.com/ansible/ansible/issues/32926)."
|
||||
@ -1,4 +0,0 @@
|
||||
---
|
||||
bugfixes:
|
||||
- "ini_file: Options within no sections aren't included, deleted or modified. These are just unmanged. This pull request solves this.
|
||||
(see https://github.com/ansible/ansible/pull/44324)"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- win_domain_computer - fixed deletion of computer active directory object that have dependent objects (https://github.com/ansible/ansible/pull/44500)
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- win_lineinfile - changed `-Path` to `-LiteralPath` so that square brackes in the path are interpreted literally - https://github.com/ansible/ansible/issues/44508
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- fix mail module for python 3.7.0 (https://github.com/ansible/ansible/pull/44552)
|
||||
@ -1,10 +0,0 @@
|
||||
bugfixes:
|
||||
- win_nssm - Fix several issues and idempotency problems (https://github.com/ansible/ansible/pull/44755)
|
||||
- win_nssm - Fix service not started when ``state=started`` (https://github.com/ansible/ansible/issues/35442)
|
||||
- win_nssm - Correctly escape argument line when a parameter contains spaces, quotes or backslashes
|
||||
- win_nssm - Add missing space between parameters with ``app_parameters``
|
||||
- win_nssm - Fix extra space added in argument line with ``app_parameters`` or ``app_parameters_free_form`` when a parameter start by a dash and is followed by a period (https://github.com/ansible/ansible/issues/44079)
|
||||
- win_nssm - Fix error when several services were given to the ``dependencies`` option
|
||||
|
||||
minor_changes:
|
||||
- win_nssm - Drop support of literal YAML dictionnary for ``app_parameters`` option. Use the ``key=value;`` string form instead
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "improves docker_container idempotency (https://github.com/ansible/ansible/pull/44808)"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "ACME modules support `POST-as-GET <https://community.letsencrypt.org/t/acme-v2-scheduled-deprecation-of-unauthenticated-resource-gets/74380>`__ and will be able to access Let's Encrypt ACME v2 endpoint after November 1st, 2019."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "Fixed: Make sure that the files excluded when extracting the archive are not checked. https://github.com/ansible/ansible/pull/45122"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- replace renamed exceptions in multiple openstack modules
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- vmware_host_service_facts - handle exception when service package does not have package name.
|
||||
@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- Update docs and return section of vmware_host_service_facts module.
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- vmware - honor "wait_for_ip_address" when powering on a VM
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- azure_rm_virtualmachine - fixed several crashes in module
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- azure_rm_sqlserver - fix for tags support
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- Fix iterator to list conversion in ldap_entry module.
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- get_url - support remote checksum files with paths specified with leading dots (`./path/to/file`)
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- docker_service - correctly parse string values for the `scale` parameter https://github.com/ansible/ansible/pull/45508
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- Fix the quoting of vhost and other names in rabbitmq_binding
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "fetch_url did not always return lower-case header names in case of HTTP errors (https://github.com/ansible/ansible/pull/45628)."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "Don't parse parameters and options when ``state`` is ``absent`` (https://github.com/ansible/ansible/pull/45700)."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "Fix issue with HTTP redirects with redfish_facts module (https://github.com/ansible/ansible/pull/45704)"
|
||||
@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- Vultr - fix for unreliable API behaviors resulting in timeouts (https://github.com/ansible/ansible/pull/45712/).
|
||||
- vultr_server - fix diff for user data (https://github.com/ansible/ansible/pull/45753/).
|
||||
@ -1,4 +0,0 @@
|
||||
bugfixes:
|
||||
- "Fixed: Appropriate code to expand value was missing so assigning SSL
|
||||
certificate is not working as described in the documentation.
|
||||
https://github.com/ansible/ansible/pull/45830"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "os_router - ``enable_snat: no`` was ignored."
|
||||
@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- Puppet module remove ``--ignorecache`` to allow Puppet 6 support
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "route53 - fix CAA record ordering for idempotency."
|
||||
@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- cs_instance - Fix host migration without volume (https://github.com/ansible/ansible/pull/46115).
|
||||
- cs_instance - Fix docs and typo in examples (https://github.com/ansible/ansible/pull/46035).
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "Provides flexibility when retrieving redfish facts by not assuming that certains keys exist. Checks first if key exists before attempting to read from it."
|
||||
@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- In systemd module, allow scope to default to 'system'
|
||||
- In systemd module, fix check if a systemd+initd service is enabled - disabled in systemd means disabled
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "docker_container - the behavior is improved in case ``image`` is not specified, but needed for (re-)creating the container."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- Backport of https://github.com/ansible/ansible/pull/46478 , fixes name collision in haproxy module
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "zabbix_host - module was failing when zabbix host was updated with new interface and template depending on that interface at the same time"
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "docker_container - ``publish_ports: all`` was not used correctly when checking idempotency."
|
||||
@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- "docker_container - fix idempotency check for published_ports in some special cases."
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user