diff --git a/doc/ref/beacons/all/index.rst b/doc/ref/beacons/all/index.rst index 7fccfc5b1518..60bec8416bf4 100644 --- a/doc/ref/beacons/all/index.rst +++ b/doc/ref/beacons/all/index.rst @@ -11,12 +11,14 @@ beacon modules :template: autosummary.rst.tmpl adb + aix_account avahi_announce bonjour_announce btmp diskusage glxinfo haproxy + http_status inotify journald load @@ -32,7 +34,10 @@ beacon modules sensehat service sh + smartos_imgadm + smartos_vmadm status telegram_bot_msg twilio_txt_msg + watchdog wtmp diff --git a/doc/ref/beacons/all/salt.beacons.aix_account.rst b/doc/ref/beacons/all/salt.beacons.aix_account.rst new file mode 100644 index 000000000000..f7467322ac5c --- /dev/null +++ b/doc/ref/beacons/all/salt.beacons.aix_account.rst @@ -0,0 +1,5 @@ +salt.beacons.aix_account module +=============================== + +.. automodule:: salt.beacons.aix_account + :members: diff --git a/doc/ref/beacons/all/salt.beacons.http_status.rst b/doc/ref/beacons/all/salt.beacons.http_status.rst new file mode 100644 index 000000000000..518379975d4e --- /dev/null +++ b/doc/ref/beacons/all/salt.beacons.http_status.rst @@ -0,0 +1,5 @@ +salt.beacons.http_status module +=============================== + +.. automodule:: salt.beacons.http_status + :members: diff --git a/doc/ref/beacons/all/salt.beacons.smartos_imgadm.rst b/doc/ref/beacons/all/salt.beacons.smartos_imgadm.rst new file mode 100644 index 000000000000..abbf5b918efb --- /dev/null +++ b/doc/ref/beacons/all/salt.beacons.smartos_imgadm.rst @@ -0,0 +1,5 @@ +salt.beacons.smartos_imgadm module +================================== + +.. automodule:: salt.beacons.smartos_imgadm + :members: diff --git a/doc/ref/beacons/all/salt.beacons.smartos_vmadm.rst b/doc/ref/beacons/all/salt.beacons.smartos_vmadm.rst new file mode 100644 index 000000000000..852c327f3744 --- /dev/null +++ b/doc/ref/beacons/all/salt.beacons.smartos_vmadm.rst @@ -0,0 +1,5 @@ +salt.beacons.smartos_vmadm module +================================= + +.. automodule:: salt.beacons.smartos_vmadm + :members: diff --git a/doc/ref/beacons/all/salt.beacons.watchdog.rst b/doc/ref/beacons/all/salt.beacons.watchdog.rst new file mode 100644 index 000000000000..8cea358f6575 --- /dev/null +++ b/doc/ref/beacons/all/salt.beacons.watchdog.rst @@ -0,0 +1,5 @@ +salt.beacons.watchdog module +============================ + +.. automodule:: salt.beacons.watchdog + :members: diff --git a/doc/ref/clouds/all/index.rst b/doc/ref/clouds/all/index.rst index 1f7a97bf02c1..3a9c383987e5 100644 --- a/doc/ref/clouds/all/index.rst +++ b/doc/ref/clouds/all/index.rst @@ -12,6 +12,7 @@ cloud modules aliyun azurearm + clc cloudstack digitalocean dimensiondata @@ -19,12 +20,14 @@ cloud modules gce gogrid joyent + libvirt linode lxc msazure oneandone opennebula openstack + packet parallels profitbricks proxmox diff --git a/doc/ref/clouds/all/salt.cloud.clouds.clc.rst b/doc/ref/clouds/all/salt.cloud.clouds.clc.rst new file mode 100644 index 000000000000..03991947dbd1 --- /dev/null +++ b/doc/ref/clouds/all/salt.cloud.clouds.clc.rst @@ -0,0 +1,6 @@ +===================== +salt.cloud.clouds.clc +===================== + +.. automodule:: salt.cloud.clouds.clc + :members: diff --git a/doc/ref/clouds/all/salt.cloud.clouds.libvirt.rst b/doc/ref/clouds/all/salt.cloud.clouds.libvirt.rst new file mode 100644 index 000000000000..32342f932ec5 --- /dev/null +++ b/doc/ref/clouds/all/salt.cloud.clouds.libvirt.rst @@ -0,0 +1,6 @@ +========================= +salt.cloud.clouds.libvirt +========================= + +.. automodule:: salt.cloud.clouds.libvirt + :members: diff --git a/doc/ref/clouds/all/salt.cloud.clouds.packet.rst b/doc/ref/clouds/all/salt.cloud.clouds.packet.rst new file mode 100644 index 000000000000..7898814742f6 --- /dev/null +++ b/doc/ref/clouds/all/salt.cloud.clouds.packet.rst @@ -0,0 +1,6 @@ +======================== +salt.cloud.clouds.packet +======================== + +.. automodule:: salt.cloud.clouds.packet + :members: diff --git a/doc/ref/engines/all/index.rst b/doc/ref/engines/all/index.rst index f54245e23a2c..461a891cc79b 100644 --- a/doc/ref/engines/all/index.rst +++ b/doc/ref/engines/all/index.rst @@ -15,11 +15,13 @@ engine modules http_logstash ircbot junos_syslog + libvirt_events logentries logstash_engine napalm_syslog reactor redis_sentinel + script slack sqs_events stalekey diff --git a/doc/ref/engines/all/salt.engines.libvirt_events.rst b/doc/ref/engines/all/salt.engines.libvirt_events.rst new file mode 100644 index 000000000000..b8de412614f2 --- /dev/null +++ b/doc/ref/engines/all/salt.engines.libvirt_events.rst @@ -0,0 +1,6 @@ +salt.engines.libvirt_events module +================================== + +.. automodule:: salt.engines.libvirt_events + :members: + :undoc-members: diff --git a/doc/ref/engines/all/salt.engines.script.rst b/doc/ref/engines/all/salt.engines.script.rst new file mode 100644 index 000000000000..20f742dc1b36 --- /dev/null +++ b/doc/ref/engines/all/salt.engines.script.rst @@ -0,0 +1,6 @@ +salt.engines.script module +========================== + +.. automodule:: salt.engines.script + :members: + :undoc-members: diff --git a/doc/ref/grains/all/index.rst b/doc/ref/grains/all/index.rst index 9fd6a0171e6c..8bce54765423 100644 --- a/doc/ref/grains/all/index.rst +++ b/doc/ref/grains/all/index.rst @@ -16,13 +16,23 @@ grains modules disks esxi extra + fibre_channel fx2 + iscsi junos marathon mdadm + mdata metadata + minion_process napalm + nvme + nxos + onyx opts panos philips_hue + smartos + ssh_sample rest_sample + zfs diff --git a/doc/ref/grains/all/salt.grains.fibre_channel.rst b/doc/ref/grains/all/salt.grains.fibre_channel.rst new file mode 100644 index 000000000000..9c4d3045eaf5 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.fibre_channel.rst @@ -0,0 +1,6 @@ +========================= +salt.grains.fibre_channel +========================= + +.. automodule:: salt.grains.fibre_channel + :members: diff --git a/doc/ref/grains/all/salt.grains.iscsi.rst b/doc/ref/grains/all/salt.grains.iscsi.rst new file mode 100644 index 000000000000..11d16faf3d34 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.iscsi.rst @@ -0,0 +1,6 @@ +================= +salt.grains.iscsi +================= + +.. automodule:: salt.grains.iscsi + :members: diff --git a/doc/ref/grains/all/salt.grains.mdata.rst b/doc/ref/grains/all/salt.grains.mdata.rst new file mode 100644 index 000000000000..34599b7329f0 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.mdata.rst @@ -0,0 +1,6 @@ +================= +salt.grains.mdata +================= + +.. automodule:: salt.grains.mdata + :members: diff --git a/doc/ref/grains/all/salt.grains.minion_process.rst b/doc/ref/grains/all/salt.grains.minion_process.rst new file mode 100644 index 000000000000..254e646416c6 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.minion_process.rst @@ -0,0 +1,6 @@ +========================== +salt.grains.minion_process +========================== + +.. automodule:: salt.grains.minion_process + :members: diff --git a/doc/ref/grains/all/salt.grains.nvme.rst b/doc/ref/grains/all/salt.grains.nvme.rst new file mode 100644 index 000000000000..519fe755505c --- /dev/null +++ b/doc/ref/grains/all/salt.grains.nvme.rst @@ -0,0 +1,6 @@ +================ +salt.grains.nvme +================ + +.. automodule:: salt.grains.nvme + :members: diff --git a/doc/ref/grains/all/salt.grains.nxos.rst b/doc/ref/grains/all/salt.grains.nxos.rst new file mode 100644 index 000000000000..79b7448a56f3 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.nxos.rst @@ -0,0 +1,6 @@ +================ +salt.grains.nxos +================ + +.. automodule:: salt.grains.nxos + :members: diff --git a/doc/ref/grains/all/salt.grains.onyx.rst b/doc/ref/grains/all/salt.grains.onyx.rst new file mode 100644 index 000000000000..c634c2d3b399 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.onyx.rst @@ -0,0 +1,6 @@ +================ +salt.grains.onyx +================ + +.. automodule:: salt.grains.onyx + :members: diff --git a/doc/ref/grains/all/salt.grains.smartos.rst b/doc/ref/grains/all/salt.grains.smartos.rst new file mode 100644 index 000000000000..0b5a9a28efc9 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.smartos.rst @@ -0,0 +1,6 @@ +=================== +salt.grains.smartos +=================== + +.. automodule:: salt.grains.smartos + :members: diff --git a/doc/ref/grains/all/salt.grains.ssh_sample.rst b/doc/ref/grains/all/salt.grains.ssh_sample.rst new file mode 100644 index 000000000000..84828a517144 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.ssh_sample.rst @@ -0,0 +1,6 @@ +====================== +salt.grains.ssh_sample +====================== + +.. automodule:: salt.grains.ssh_sample + :members: diff --git a/doc/ref/grains/all/salt.grains.zfs.rst b/doc/ref/grains/all/salt.grains.zfs.rst new file mode 100644 index 000000000000..f0875ecb1d07 --- /dev/null +++ b/doc/ref/grains/all/salt.grains.zfs.rst @@ -0,0 +1,6 @@ +=============== +salt.grains.zfs +=============== + +.. automodule:: salt.grains.zfs + :members: diff --git a/doc/ref/modules/all/index.rst b/doc/ref/modules/all/index.rst index 310953284858..ce189305482d 100644 --- a/doc/ref/modules/all/index.rst +++ b/doc/ref/modules/all/index.rst @@ -23,6 +23,7 @@ execution modules acme aix_group + aix_shadow aixpkg aliases alternatives @@ -32,6 +33,7 @@ execution modules apf apkpkg aptpkg + aptly archive arista_pyeapi artifactory @@ -40,9 +42,11 @@ execution modules augeas_cfg aws_sqs azurearm_compute + azurearm_dns azurearm_network azurearm_resource bamboohr + baredoc bcache beacons bigip @@ -50,6 +54,7 @@ execution modules boto3_elasticache boto3_elasticsearch boto3_route53 + boto3_sns boto_apigateway boto_asg boto_cfn @@ -73,10 +78,12 @@ execution modules boto_lambda boto_rds boto_route53 + boto_s3 boto_s3_bucket boto_secgroup boto_sns boto_sqs + boto_ssm boto_vpc bower bridge @@ -92,6 +99,7 @@ execution modules chef chocolatey chronos + chroot cimc ciscoconfparse_mod cisconso @@ -104,6 +112,7 @@ execution modules cp cpan cron + cryptdev csf cyg daemontools @@ -136,7 +145,10 @@ execution modules elasticsearch environ eselect + esxcluster + esxdatacenter esxi + esxvm etcd_mod ethtool event @@ -150,6 +162,8 @@ execution modules freebsdpkg freebsdports freebsdservice + freezer + gcp_addon gem genesis gentoo_service @@ -158,6 +172,7 @@ execution modules github glance glanceng + glassfish glusterfs gnomedesktop google_chat @@ -172,6 +187,7 @@ execution modules hashutil heat hg + highstate_doc hosts http ifttt @@ -202,6 +218,7 @@ execution modules jenkinsmod jinja jira_mod + jsonnet junos k8s kapacitor @@ -302,6 +319,8 @@ execution modules network neutron neutronng + nexus + nxos_upgrade nfs3 nftables nginx @@ -313,6 +332,7 @@ execution modules nxos nxos_api omapi + onyx openbsd_sysctl openbsdpkg openbsdrcctl_service @@ -388,8 +408,10 @@ execution modules s3 s6 salt_proxy + salt_version saltcheck saltcloudmod + saltsupport saltutil schedule scp_mod @@ -468,12 +490,14 @@ execution modules vault vbox_guest vboxmanage + vcenter victorops virt virtualenv_mod vmctl vsphere webutil + win_auditpol win_autoruns win_certutil win_dacl @@ -508,6 +532,7 @@ execution modules win_useradd win_wua win_wusa + wordpress x509 xapi_virt xbpspkg diff --git a/doc/ref/modules/all/salt.modules.aix_shadow.rst b/doc/ref/modules/all/salt.modules.aix_shadow.rst new file mode 100644 index 000000000000..a3159fd0fd63 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.aix_shadow.rst @@ -0,0 +1,6 @@ +salt.modules.aix_shadow module +============================== + +.. automodule:: salt.modules.aix_shadow + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.aptly.rst b/doc/ref/modules/all/salt.modules.aptly.rst new file mode 100644 index 000000000000..8ecbc8ced018 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.aptly.rst @@ -0,0 +1,6 @@ +salt.modules.aptly module +========================= + +.. automodule:: salt.modules.aptly + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.azurearm_dns.rst b/doc/ref/modules/all/salt.modules.azurearm_dns.rst new file mode 100644 index 000000000000..fe216be18d9e --- /dev/null +++ b/doc/ref/modules/all/salt.modules.azurearm_dns.rst @@ -0,0 +1,6 @@ +salt.modules.azurearm_dns module +================================ + +.. automodule:: salt.modules.azurearm_dns + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.baredoc.rst b/doc/ref/modules/all/salt.modules.baredoc.rst new file mode 100644 index 000000000000..990b7baaebe5 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.baredoc.rst @@ -0,0 +1,6 @@ +salt.modules.baredoc module +=========================== + +.. automodule:: salt.modules.baredoc + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.boto3_sns.rst b/doc/ref/modules/all/salt.modules.boto3_sns.rst new file mode 100644 index 000000000000..3031c5c65b3e --- /dev/null +++ b/doc/ref/modules/all/salt.modules.boto3_sns.rst @@ -0,0 +1,6 @@ +salt.modules.boto3_sns module +============================= + +.. automodule:: salt.modules.boto3_sns + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.boto_s3.rst b/doc/ref/modules/all/salt.modules.boto_s3.rst new file mode 100644 index 000000000000..8f930bbc0d65 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.boto_s3.rst @@ -0,0 +1,6 @@ +salt.modules.boto_s3 module +=========================== + +.. automodule:: salt.modules.boto_s3 + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.boto_ssm.rst b/doc/ref/modules/all/salt.modules.boto_ssm.rst new file mode 100644 index 000000000000..66c763cb9179 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.boto_ssm.rst @@ -0,0 +1,6 @@ +salt.modules.boto_ssm module +============================ + +.. automodule:: salt.modules.boto_ssm + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.chroot.rst b/doc/ref/modules/all/salt.modules.chroot.rst new file mode 100644 index 000000000000..f8da99aaf01e --- /dev/null +++ b/doc/ref/modules/all/salt.modules.chroot.rst @@ -0,0 +1,6 @@ +salt.modules.chroot module +========================== + +.. automodule:: salt.modules.chroot + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.cryptdev.rst b/doc/ref/modules/all/salt.modules.cryptdev.rst new file mode 100644 index 000000000000..c62ebb2d748a --- /dev/null +++ b/doc/ref/modules/all/salt.modules.cryptdev.rst @@ -0,0 +1,6 @@ +salt.modules.cryptdev module +============================ + +.. automodule:: salt.modules.cryptdev + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.esxcluster.rst b/doc/ref/modules/all/salt.modules.esxcluster.rst new file mode 100644 index 000000000000..8c086929ba36 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.esxcluster.rst @@ -0,0 +1,6 @@ +salt.modules.esxcluster module +============================== + +.. automodule:: salt.modules.esxcluster + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.esxdatacenter.rst b/doc/ref/modules/all/salt.modules.esxdatacenter.rst new file mode 100644 index 000000000000..4fb8d8109697 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.esxdatacenter.rst @@ -0,0 +1,6 @@ +salt.modules.esxdatacenter module +================================= + +.. automodule:: salt.modules.esxdatacenter + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.esxvm.rst b/doc/ref/modules/all/salt.modules.esxvm.rst new file mode 100644 index 000000000000..5d9305247cc1 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.esxvm.rst @@ -0,0 +1,6 @@ +salt.modules.esxvm module +========================= + +.. automodule:: salt.modules.esxvm + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.freezer.rst b/doc/ref/modules/all/salt.modules.freezer.rst new file mode 100644 index 000000000000..4b077e148df7 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.freezer.rst @@ -0,0 +1,6 @@ +salt.modules.freezer module +=========================== + +.. automodule:: salt.modules.freezer + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.gcp_addon.rst b/doc/ref/modules/all/salt.modules.gcp_addon.rst new file mode 100644 index 000000000000..415cacfb84c2 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.gcp_addon.rst @@ -0,0 +1,6 @@ +salt.modules.gcp_addon module +============================= + +.. automodule:: salt.modules.gcp_addon + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.glassfish.rst b/doc/ref/modules/all/salt.modules.glassfish.rst new file mode 100644 index 000000000000..8297783c1228 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.glassfish.rst @@ -0,0 +1,6 @@ +salt.modules.glassfish module +============================= + +.. automodule:: salt.modules.glassfish + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.highstate_doc.rst b/doc/ref/modules/all/salt.modules.highstate_doc.rst new file mode 100644 index 000000000000..ccf7ea4f7b40 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.highstate_doc.rst @@ -0,0 +1,6 @@ +salt.modules.highstate_doc module +================================= + +.. automodule:: salt.modules.highstate_doc + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.jsonnet.rst b/doc/ref/modules/all/salt.modules.jsonnet.rst new file mode 100644 index 000000000000..56447159298d --- /dev/null +++ b/doc/ref/modules/all/salt.modules.jsonnet.rst @@ -0,0 +1,6 @@ +salt.modules.jsonnet module +=========================== + +.. automodule:: salt.modules.jsonnet + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.nexus.rst b/doc/ref/modules/all/salt.modules.nexus.rst new file mode 100644 index 000000000000..09d619c15dec --- /dev/null +++ b/doc/ref/modules/all/salt.modules.nexus.rst @@ -0,0 +1,6 @@ +salt.modules.nexus module +========================= + +.. automodule:: salt.modules.nexus + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.nxos_upgrade.rst b/doc/ref/modules/all/salt.modules.nxos_upgrade.rst new file mode 100644 index 000000000000..a9df13748ac5 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.nxos_upgrade.rst @@ -0,0 +1,6 @@ +salt.modules.nxos_upgrade module +================================ + +.. automodule:: salt.modules.nxos_upgrade + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.onyx.rst b/doc/ref/modules/all/salt.modules.onyx.rst new file mode 100644 index 000000000000..7ae083ab62a4 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.onyx.rst @@ -0,0 +1,6 @@ +salt.modules.onyx module +======================== + +.. automodule:: salt.modules.onyx + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.pkg.rst b/doc/ref/modules/all/salt.modules.pkg.rst index 09ca1b88542d..88db6e06f443 100644 --- a/doc/ref/modules/all/salt.modules.pkg.rst +++ b/doc/ref/modules/all/salt.modules.pkg.rst @@ -39,4 +39,3 @@ Execution Module Used for .. _Homebrew: http://brew.sh/ .. _OpenCSW: http://www.opencsw.org/ - diff --git a/doc/ref/modules/all/salt.modules.salt_version.rst b/doc/ref/modules/all/salt.modules.salt_version.rst new file mode 100644 index 000000000000..f1cdb3e978ed --- /dev/null +++ b/doc/ref/modules/all/salt.modules.salt_version.rst @@ -0,0 +1,6 @@ +salt.modules.salt_version module +================================ + +.. automodule:: salt.modules.salt_version + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.saltsupport.rst b/doc/ref/modules/all/salt.modules.saltsupport.rst new file mode 100644 index 000000000000..70098558868e --- /dev/null +++ b/doc/ref/modules/all/salt.modules.saltsupport.rst @@ -0,0 +1,6 @@ +salt.modules.saltsupport module +=============================== + +.. automodule:: salt.modules.saltsupport + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.shadow.rst b/doc/ref/modules/all/salt.modules.shadow.rst index 3b03032d28eb..3212cf1029bf 100644 --- a/doc/ref/modules/all/salt.modules.shadow.rst +++ b/doc/ref/modules/all/salt.modules.shadow.rst @@ -13,6 +13,7 @@ modules: ====================================== ======================================== Execution Module Used for ====================================== ======================================== +:py:mod:`~salt.modules.aix_shadow` AIX :py:mod:`~salt.modules.shadow` Linux :py:mod:`~salt.modules.bsd_shadow` FreeBSD, OpenBSD, NetBSD :py:mod:`~salt.modules.solaris_shadow` Solaris-based OSes diff --git a/doc/ref/modules/all/salt.modules.vcenter.rst b/doc/ref/modules/all/salt.modules.vcenter.rst new file mode 100644 index 000000000000..863f92e85d46 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.vcenter.rst @@ -0,0 +1,6 @@ +salt.modules.vcenter module +=========================== + +.. automodule:: salt.modules.vcenter + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.win_auditpol.rst b/doc/ref/modules/all/salt.modules.win_auditpol.rst new file mode 100644 index 000000000000..a5fabb2e3ce7 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.win_auditpol.rst @@ -0,0 +1,6 @@ +salt.modules.win_auditpol module +================================ + +.. automodule:: salt.modules.win_auditpol + :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.win_wusa.rst b/doc/ref/modules/all/salt.modules.win_wusa.rst index 7eb615ee23a1..b2dbe8be608d 100644 --- a/doc/ref/modules/all/salt.modules.win_wusa.rst +++ b/doc/ref/modules/all/salt.modules.win_wusa.rst @@ -4,3 +4,4 @@ salt.modules.win_wusa .. automodule:: salt.modules.win_wusa :members: + :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.wordpress.rst b/doc/ref/modules/all/salt.modules.wordpress.rst new file mode 100644 index 000000000000..d21aba9e5b75 --- /dev/null +++ b/doc/ref/modules/all/salt.modules.wordpress.rst @@ -0,0 +1,6 @@ +salt.modules.wordpress module +============================= + +.. automodule:: salt.modules.wordpress + :members: + :undoc-members: diff --git a/doc/ref/output/all/index.rst b/doc/ref/output/all/index.rst index 23c8f85b90d6..5f0a8bc74936 100644 --- a/doc/ref/output/all/index.rst +++ b/doc/ref/output/all/index.rst @@ -12,6 +12,7 @@ Follow one of the below links for further information and examples :toctree: :template: autosummary.rst.tmpl + dson highstate json_out key diff --git a/doc/ref/output/all/salt.output.dson.rst b/doc/ref/output/all/salt.output.dson.rst new file mode 100644 index 000000000000..fa9553ff4fb0 --- /dev/null +++ b/doc/ref/output/all/salt.output.dson.rst @@ -0,0 +1,6 @@ +================ +salt.output.dson +================ + +.. automodule:: salt.output.dson + :members: diff --git a/doc/ref/pillar/all/index.rst b/doc/ref/pillar/all/index.rst index b4c578228ab4..341d3786aa19 100644 --- a/doc/ref/pillar/all/index.rst +++ b/doc/ref/pillar/all/index.rst @@ -21,6 +21,7 @@ pillar modules django_orm ec2_pillar etcd_pillar + extra_minion_data_in_pillar file_tree foreman git_pillar @@ -33,15 +34,18 @@ pillar modules makostack mongo mysql + nacl netbox neutron nodegroups + nsot pepa pillar_ldap postgres puppet reclass_adapter redismod + rethinkdb_pillar s3 saltclass sql_base diff --git a/doc/ref/pillar/all/salt.pillar.extra_minion_data_in_pillar.rst b/doc/ref/pillar/all/salt.pillar.extra_minion_data_in_pillar.rst new file mode 100644 index 000000000000..16ff48a62717 --- /dev/null +++ b/doc/ref/pillar/all/salt.pillar.extra_minion_data_in_pillar.rst @@ -0,0 +1,6 @@ +======================================= +salt.pillar.extra_minion_data_in_pillar +======================================= + +.. automodule:: salt.pillar.extra_minion_data_in_pillar + :members: diff --git a/doc/ref/pillar/all/salt.pillar.nacl.rst b/doc/ref/pillar/all/salt.pillar.nacl.rst new file mode 100644 index 000000000000..7d245c0d7ea9 --- /dev/null +++ b/doc/ref/pillar/all/salt.pillar.nacl.rst @@ -0,0 +1,6 @@ +================ +salt.pillar.nacl +================ + +.. automodule:: salt.pillar.nacl + :members: diff --git a/doc/ref/pillar/all/salt.pillar.nsot.rst b/doc/ref/pillar/all/salt.pillar.nsot.rst new file mode 100644 index 000000000000..fa7c66f988c3 --- /dev/null +++ b/doc/ref/pillar/all/salt.pillar.nsot.rst @@ -0,0 +1,6 @@ +================ +salt.pillar.nsot +================ + +.. automodule:: salt.pillar.nsot + :members: diff --git a/doc/ref/pillar/all/salt.pillar.rethinkdb_pillar.rst b/doc/ref/pillar/all/salt.pillar.rethinkdb_pillar.rst new file mode 100644 index 000000000000..bc6acb7203c8 --- /dev/null +++ b/doc/ref/pillar/all/salt.pillar.rethinkdb_pillar.rst @@ -0,0 +1,6 @@ +============================ +salt.pillar.rethinkdb_pillar +============================ + +.. automodule:: salt.pillar.rethinkdb_pillar + :members: diff --git a/doc/ref/proxy/all/index.rst b/doc/ref/proxy/all/index.rst index 33ae5f4df3ac..e7de5839d7f2 100644 --- a/doc/ref/proxy/all/index.rst +++ b/doc/ref/proxy/all/index.rst @@ -15,8 +15,12 @@ proxy modules chronos cimc cisconso + docker dummy + esxcluster + esxdatacenter esxi + esxvm fx2 junos marathon @@ -24,7 +28,9 @@ proxy modules netmiko_px nxos nxos_api + onyx panos philips_hue rest_sample ssh_sample + vcenter diff --git a/doc/ref/proxy/all/salt.proxy.docker.rst b/doc/ref/proxy/all/salt.proxy.docker.rst new file mode 100644 index 000000000000..b83652be4439 --- /dev/null +++ b/doc/ref/proxy/all/salt.proxy.docker.rst @@ -0,0 +1,6 @@ +salt.proxy.docker module +======================== + +.. automodule:: salt.proxy.docker + :members: + :undoc-members: diff --git a/doc/ref/proxy/all/salt.proxy.esxcluster.rst b/doc/ref/proxy/all/salt.proxy.esxcluster.rst new file mode 100644 index 000000000000..38a6331bbbc4 --- /dev/null +++ b/doc/ref/proxy/all/salt.proxy.esxcluster.rst @@ -0,0 +1,6 @@ +salt.proxy.esxcluster module +============================ + +.. automodule:: salt.proxy.esxcluster + :members: + :undoc-members: diff --git a/doc/ref/proxy/all/salt.proxy.esxdatacenter.rst b/doc/ref/proxy/all/salt.proxy.esxdatacenter.rst new file mode 100644 index 000000000000..f190574f8f52 --- /dev/null +++ b/doc/ref/proxy/all/salt.proxy.esxdatacenter.rst @@ -0,0 +1,6 @@ +salt.proxy.esxdatacenter module +=============================== + +.. automodule:: salt.proxy.esxdatacenter + :members: + :undoc-members: diff --git a/doc/ref/proxy/all/salt.proxy.esxvm.rst b/doc/ref/proxy/all/salt.proxy.esxvm.rst new file mode 100644 index 000000000000..fbbf2fc821d0 --- /dev/null +++ b/doc/ref/proxy/all/salt.proxy.esxvm.rst @@ -0,0 +1,6 @@ +salt.proxy.esxvm module +======================= + +.. automodule:: salt.proxy.esxvm + :members: + :undoc-members: diff --git a/doc/ref/proxy/all/salt.proxy.onyx.rst b/doc/ref/proxy/all/salt.proxy.onyx.rst new file mode 100644 index 000000000000..edc1a421e53b --- /dev/null +++ b/doc/ref/proxy/all/salt.proxy.onyx.rst @@ -0,0 +1,6 @@ +salt.proxy.onyx module +====================== + +.. automodule:: salt.proxy.onyx + :members: + :undoc-members: diff --git a/doc/ref/proxy/all/salt.proxy.vcenter.rst b/doc/ref/proxy/all/salt.proxy.vcenter.rst new file mode 100644 index 000000000000..264c38d68857 --- /dev/null +++ b/doc/ref/proxy/all/salt.proxy.vcenter.rst @@ -0,0 +1,6 @@ +salt.proxy.vcenter module +========================= + +.. automodule:: salt.proxy.vcenter + :members: + :undoc-members: diff --git a/doc/ref/renderers/all/index.rst b/doc/ref/renderers/all/index.rst index 5bc34d41f059..1ef8f32fb232 100644 --- a/doc/ref/renderers/all/index.rst +++ b/doc/ref/renderers/all/index.rst @@ -10,6 +10,7 @@ renderer modules :toctree: :template: autosummary.rst.tmpl + aws_kms cheetah dson genshi @@ -20,6 +21,7 @@ renderer modules json5 mako msgpack + nacl pass py pydsl diff --git a/doc/ref/renderers/all/salt.renderers.aws_kms.rst b/doc/ref/renderers/all/salt.renderers.aws_kms.rst new file mode 100644 index 000000000000..af048a96156d --- /dev/null +++ b/doc/ref/renderers/all/salt.renderers.aws_kms.rst @@ -0,0 +1,6 @@ +====================== +salt.renderers.aws_kms +====================== + +.. automodule:: salt.renderers.aws_kms + :members: diff --git a/doc/ref/renderers/all/salt.renderers.nacl.rst b/doc/ref/renderers/all/salt.renderers.nacl.rst new file mode 100644 index 000000000000..41c5da00108f --- /dev/null +++ b/doc/ref/renderers/all/salt.renderers.nacl.rst @@ -0,0 +1,6 @@ +=================== +salt.renderers.nacl +=================== + +.. automodule:: salt.renderers.nacl + :members: diff --git a/doc/ref/returners/all/index.rst b/doc/ref/returners/all/index.rst index 68831349e34c..54e4555544d4 100644 --- a/doc/ref/returners/all/index.rst +++ b/doc/ref/returners/all/index.rst @@ -10,6 +10,7 @@ returner modules :toctree: :template: autosummary.rst.tmpl + appoptics_return carbon_return cassandra_cql_return cassandra_return @@ -40,6 +41,7 @@ returner modules redis_return sentry_return slack_returner + slack_webhook_return sms_return smtp_return splunk diff --git a/doc/ref/returners/all/salt.returners.appoptics_return.rst b/doc/ref/returners/all/salt.returners.appoptics_return.rst new file mode 100644 index 000000000000..836830abce30 --- /dev/null +++ b/doc/ref/returners/all/salt.returners.appoptics_return.rst @@ -0,0 +1,6 @@ +=============================== +salt.returners.appoptics_return +=============================== + +.. automodule:: salt.returners.appoptics_return + :members: diff --git a/doc/ref/returners/all/salt.returners.slack_webhook_return.rst b/doc/ref/returners/all/salt.returners.slack_webhook_return.rst new file mode 100644 index 000000000000..3d3d71253891 --- /dev/null +++ b/doc/ref/returners/all/salt.returners.slack_webhook_return.rst @@ -0,0 +1,6 @@ +=================================== +salt.returners.slack_webhook_return +=================================== + +.. automodule:: salt.returners.slack_webhook_return + :members: diff --git a/doc/ref/runners/all/index.rst b/doc/ref/runners/all/index.rst index ebbab3a420d5..3a9409b4e374 100644 --- a/doc/ref/runners/all/index.rst +++ b/doc/ref/runners/all/index.rst @@ -15,6 +15,7 @@ runner modules bgp cache cloud + config ddns digicertapi doc diff --git a/doc/ref/runners/all/salt.runners.config.rst b/doc/ref/runners/all/salt.runners.config.rst new file mode 100644 index 000000000000..cc8a4463bc89 --- /dev/null +++ b/doc/ref/runners/all/salt.runners.config.rst @@ -0,0 +1,6 @@ +=================== +salt.runners.config +=================== + +.. automodule:: salt.runners.config + :members: diff --git a/doc/ref/states/all/index.rst b/doc/ref/states/all/index.rst index 0c71b922810a..2b678af3f513 100644 --- a/doc/ref/states/all/index.rst +++ b/doc/ref/states/all/index.rst @@ -25,6 +25,7 @@ state modules augeas aws_sqs azurearm_compute + azurearm_dns azurearm_network azurearm_resource beacon @@ -33,6 +34,7 @@ state modules boto3_elasticache boto3_elasticsearch boto3_route53 + boto3_sns boto_apigateway boto_asg boto_cfn @@ -57,12 +59,14 @@ state modules boto_lc boto_rds boto_route53 + boto_s3 boto_s3_bucket boto_secgroup boto_sns boto_sqs boto_vpc bower + btrfs cabal ceph chef @@ -74,6 +78,7 @@ state modules cmd composer cron + cryptdev csf cyg ddns @@ -85,6 +90,8 @@ state modules docker_network docker_volume drac + dracr + dvs elasticsearch elasticsearch_index elasticsearch_index_template @@ -92,7 +99,10 @@ state modules eselect etcd_mod ethtool + esxcluster + esxdatacenter esxi + esxvm event file firewall @@ -102,6 +112,7 @@ state modules github glance glance_image + glassfish glusterfs gnomedesktop gpg @@ -116,6 +127,7 @@ state modules group heat hg + highstate_doc host http icinga2 @@ -167,6 +179,10 @@ state modules lvs_server lvs_service lxc + lxd + lxd_container + lxd_image + lxd_profile mac_assistive macdefaults mac_keychain @@ -183,6 +199,10 @@ state modules mongodb_user monit mount + mssql_database + mssql_login + mssql_role + mssql_user msteams mysql_database mysql_grants @@ -199,13 +219,18 @@ state modules neutron_secgroup neutron_secgroup_rule neutron_subnet + nexus nfs_export nftables + nova npm ntp nxos + nxos_upgrade + onyx openstack_config openvswitch_bridge + openvswitch_db openvswitch_port opsgenie pagerduty @@ -214,6 +239,7 @@ state modules pagerduty_service pagerduty_user panos + pbm pcs pecl pdbedit @@ -226,6 +252,7 @@ state modules ports postgres_cluster postgres_database + postgres_default_privileges postgres_extension postgres_group postgres_initdb @@ -257,6 +284,7 @@ state modules rvm salt_proxy saltmod + saltsupport saltutil schedule selinux @@ -313,9 +341,11 @@ state modules win_smtp_server win_snmp win_system + win_task win_wua win_wusa winrepo + wordpress x509 xml xmpp @@ -324,8 +354,10 @@ state modules zabbix_hostgroup zabbix_mediatype zabbix_template + zabbix_service zabbix_user zabbix_usergroup + zabbix_usermacro zabbix_valuemap zcbuildout zenoss diff --git a/doc/ref/states/all/salt.states.azurearm_dns.rst b/doc/ref/states/all/salt.states.azurearm_dns.rst new file mode 100644 index 000000000000..c068de777bf9 --- /dev/null +++ b/doc/ref/states/all/salt.states.azurearm_dns.rst @@ -0,0 +1,5 @@ +salt.states.azurearm_dns module +=============================== + +.. automodule:: salt.states.azurearm_dns + :members: diff --git a/doc/ref/states/all/salt.states.boto3_sns.rst b/doc/ref/states/all/salt.states.boto3_sns.rst new file mode 100644 index 000000000000..65248061d287 --- /dev/null +++ b/doc/ref/states/all/salt.states.boto3_sns.rst @@ -0,0 +1,5 @@ +salt.states.boto3_sns module +============================ + +.. automodule:: salt.states.boto3_sns + :members: diff --git a/doc/ref/states/all/salt.states.boto_s3.rst b/doc/ref/states/all/salt.states.boto_s3.rst new file mode 100644 index 000000000000..cdb00afaf062 --- /dev/null +++ b/doc/ref/states/all/salt.states.boto_s3.rst @@ -0,0 +1,5 @@ +salt.states.boto_s3 module +========================== + +.. automodule:: salt.states.boto_s3 + :members: diff --git a/doc/ref/states/all/salt.states.btrfs.rst b/doc/ref/states/all/salt.states.btrfs.rst new file mode 100644 index 000000000000..a7e45540e11f --- /dev/null +++ b/doc/ref/states/all/salt.states.btrfs.rst @@ -0,0 +1,5 @@ +salt.states.btrfs module +======================== + +.. automodule:: salt.states.btrfs + :members: diff --git a/doc/ref/states/all/salt.states.cryptdev.rst b/doc/ref/states/all/salt.states.cryptdev.rst new file mode 100644 index 000000000000..3672c9c90363 --- /dev/null +++ b/doc/ref/states/all/salt.states.cryptdev.rst @@ -0,0 +1,5 @@ +salt.states.cryptdev module +=========================== + +.. automodule:: salt.states.cryptdev + :members: diff --git a/doc/ref/states/all/salt.states.dracr.rst b/doc/ref/states/all/salt.states.dracr.rst new file mode 100644 index 000000000000..d9200ab8ac0d --- /dev/null +++ b/doc/ref/states/all/salt.states.dracr.rst @@ -0,0 +1,5 @@ +salt.states.dracr module +======================== + +.. automodule:: salt.states.dracr + :members: diff --git a/doc/ref/states/all/salt.states.dvs.rst b/doc/ref/states/all/salt.states.dvs.rst new file mode 100644 index 000000000000..8b7887bb3fed --- /dev/null +++ b/doc/ref/states/all/salt.states.dvs.rst @@ -0,0 +1,5 @@ +salt.states.dvs module +====================== + +.. automodule:: salt.states.dvs + :members: diff --git a/doc/ref/states/all/salt.states.esxcluster.rst b/doc/ref/states/all/salt.states.esxcluster.rst new file mode 100644 index 000000000000..fd0baaf20827 --- /dev/null +++ b/doc/ref/states/all/salt.states.esxcluster.rst @@ -0,0 +1,5 @@ +salt.states.esxcluster module +============================= + +.. automodule:: salt.states.esxcluster + :members: diff --git a/doc/ref/states/all/salt.states.esxdatacenter.rst b/doc/ref/states/all/salt.states.esxdatacenter.rst new file mode 100644 index 000000000000..4ffaf2b65a35 --- /dev/null +++ b/doc/ref/states/all/salt.states.esxdatacenter.rst @@ -0,0 +1,5 @@ +salt.states.esxdatacenter module +================================ + +.. automodule:: salt.states.esxdatacenter + :members: diff --git a/doc/ref/states/all/salt.states.esxvm.rst b/doc/ref/states/all/salt.states.esxvm.rst new file mode 100644 index 000000000000..b20f6b060bcf --- /dev/null +++ b/doc/ref/states/all/salt.states.esxvm.rst @@ -0,0 +1,5 @@ +salt.states.esxvm module +======================== + +.. automodule:: salt.states.esxvm + :members: diff --git a/doc/ref/states/all/salt.states.glassfish.rst b/doc/ref/states/all/salt.states.glassfish.rst new file mode 100644 index 000000000000..663ccfdf95ff --- /dev/null +++ b/doc/ref/states/all/salt.states.glassfish.rst @@ -0,0 +1,5 @@ +salt.states.glassfish module +============================ + +.. automodule:: salt.states.glassfish + :members: diff --git a/doc/ref/states/all/salt.states.highstate_doc.rst b/doc/ref/states/all/salt.states.highstate_doc.rst new file mode 100644 index 000000000000..fbaee623a5d6 --- /dev/null +++ b/doc/ref/states/all/salt.states.highstate_doc.rst @@ -0,0 +1,5 @@ +salt.states.highstate_doc module +================================ + +.. automodule:: salt.states.highstate_doc + :members: diff --git a/doc/ref/states/all/salt.states.lxd.rst b/doc/ref/states/all/salt.states.lxd.rst new file mode 100644 index 000000000000..758e71b682de --- /dev/null +++ b/doc/ref/states/all/salt.states.lxd.rst @@ -0,0 +1,5 @@ +salt.states.lxd module +====================== + +.. automodule:: salt.states.lxd + :members: diff --git a/doc/ref/states/all/salt.states.lxd_container.rst b/doc/ref/states/all/salt.states.lxd_container.rst new file mode 100644 index 000000000000..72228e3ad189 --- /dev/null +++ b/doc/ref/states/all/salt.states.lxd_container.rst @@ -0,0 +1,5 @@ +salt.states.lxd_container module +================================ + +.. automodule:: salt.states.lxd_container + :members: diff --git a/doc/ref/states/all/salt.states.lxd_image.rst b/doc/ref/states/all/salt.states.lxd_image.rst new file mode 100644 index 000000000000..ec40159930f2 --- /dev/null +++ b/doc/ref/states/all/salt.states.lxd_image.rst @@ -0,0 +1,5 @@ +salt.states.lxd_image module +============================ + +.. automodule:: salt.states.lxd_image + :members: diff --git a/doc/ref/states/all/salt.states.lxd_profile.rst b/doc/ref/states/all/salt.states.lxd_profile.rst new file mode 100644 index 000000000000..f3f4e2fcbd51 --- /dev/null +++ b/doc/ref/states/all/salt.states.lxd_profile.rst @@ -0,0 +1,5 @@ +salt.states.lxd_profile module +============================== + +.. automodule:: salt.states.lxd_profile + :members: diff --git a/doc/ref/states/all/salt.states.mssql_database.rst b/doc/ref/states/all/salt.states.mssql_database.rst new file mode 100644 index 000000000000..6e11650298bc --- /dev/null +++ b/doc/ref/states/all/salt.states.mssql_database.rst @@ -0,0 +1,5 @@ +salt.states.mssql_database module +================================= + +.. automodule:: salt.states.mssql_database + :members: diff --git a/doc/ref/states/all/salt.states.mssql_login.rst b/doc/ref/states/all/salt.states.mssql_login.rst new file mode 100644 index 000000000000..d579f056ca3f --- /dev/null +++ b/doc/ref/states/all/salt.states.mssql_login.rst @@ -0,0 +1,5 @@ +salt.states.mssql_login module +============================== + +.. automodule:: salt.states.mssql_login + :members: diff --git a/doc/ref/states/all/salt.states.mssql_role.rst b/doc/ref/states/all/salt.states.mssql_role.rst new file mode 100644 index 000000000000..48aef6908b0e --- /dev/null +++ b/doc/ref/states/all/salt.states.mssql_role.rst @@ -0,0 +1,5 @@ +salt.states.mssql_role module +============================= + +.. automodule:: salt.states.mssql_role + :members: diff --git a/doc/ref/states/all/salt.states.mssql_user.rst b/doc/ref/states/all/salt.states.mssql_user.rst new file mode 100644 index 000000000000..ac335693cebe --- /dev/null +++ b/doc/ref/states/all/salt.states.mssql_user.rst @@ -0,0 +1,5 @@ +salt.states.mssql_user module +============================= + +.. automodule:: salt.states.mssql_user + :members: diff --git a/doc/ref/states/all/salt.states.nexus.rst b/doc/ref/states/all/salt.states.nexus.rst new file mode 100644 index 000000000000..41e6aa415b35 --- /dev/null +++ b/doc/ref/states/all/salt.states.nexus.rst @@ -0,0 +1,5 @@ +salt.states.nexus module +======================== + +.. automodule:: salt.states.nexus + :members: diff --git a/doc/ref/states/all/salt.states.nova.rst b/doc/ref/states/all/salt.states.nova.rst new file mode 100644 index 000000000000..73742f65c4a3 --- /dev/null +++ b/doc/ref/states/all/salt.states.nova.rst @@ -0,0 +1,5 @@ +salt.states.nova module +======================= + +.. automodule:: salt.states.nova + :members: diff --git a/doc/ref/states/all/salt.states.nxos_upgrade.rst b/doc/ref/states/all/salt.states.nxos_upgrade.rst new file mode 100644 index 000000000000..8a3a38c85a73 --- /dev/null +++ b/doc/ref/states/all/salt.states.nxos_upgrade.rst @@ -0,0 +1,5 @@ +salt.states.nxos_upgrade module +=============================== + +.. automodule:: salt.states.nxos_upgrade + :members: diff --git a/doc/ref/states/all/salt.states.onyx.rst b/doc/ref/states/all/salt.states.onyx.rst new file mode 100644 index 000000000000..a762d43c7f5a --- /dev/null +++ b/doc/ref/states/all/salt.states.onyx.rst @@ -0,0 +1,5 @@ +salt.states.onyx module +======================= + +.. automodule:: salt.states.onyx + :members: diff --git a/doc/ref/states/all/salt.states.openvswitch_db.rst b/doc/ref/states/all/salt.states.openvswitch_db.rst new file mode 100644 index 000000000000..f6ca8b2bdce0 --- /dev/null +++ b/doc/ref/states/all/salt.states.openvswitch_db.rst @@ -0,0 +1,5 @@ +salt.states.openvswitch_db module +================================= + +.. automodule:: salt.states.openvswitch_db + :members: diff --git a/doc/ref/states/all/salt.states.pbm.rst b/doc/ref/states/all/salt.states.pbm.rst new file mode 100644 index 000000000000..e5b2d9a6b67a --- /dev/null +++ b/doc/ref/states/all/salt.states.pbm.rst @@ -0,0 +1,5 @@ +salt.states.pbm module +====================== + +.. automodule:: salt.states.pbm + :members: diff --git a/doc/ref/states/all/salt.states.postgres_default_privileges.rst b/doc/ref/states/all/salt.states.postgres_default_privileges.rst new file mode 100644 index 000000000000..bcdf492b4cb6 --- /dev/null +++ b/doc/ref/states/all/salt.states.postgres_default_privileges.rst @@ -0,0 +1,5 @@ +salt.states.postgres_default_privileges module +============================================== + +.. automodule:: salt.states.postgres_default_privileges + :members: diff --git a/doc/ref/states/all/salt.states.saltsupport.rst b/doc/ref/states/all/salt.states.saltsupport.rst new file mode 100644 index 000000000000..48ce69d21ea1 --- /dev/null +++ b/doc/ref/states/all/salt.states.saltsupport.rst @@ -0,0 +1,5 @@ +salt.states.saltsupport module +============================== + +.. automodule:: salt.states.saltsupport + :members: diff --git a/doc/ref/states/all/salt.states.saltutil.rst b/doc/ref/states/all/salt.states.saltutil.rst index f9e0360eb832..7536ae36146f 100644 --- a/doc/ref/states/all/salt.states.saltutil.rst +++ b/doc/ref/states/all/salt.states.saltutil.rst @@ -1,6 +1,5 @@ -==================== -salt.states.saltutil -==================== +salt.states.saltutil module +=========================== .. automodule:: salt.states.saltutil :members: \ No newline at end of file diff --git a/doc/ref/states/all/salt.states.win_task.rst b/doc/ref/states/all/salt.states.win_task.rst new file mode 100644 index 000000000000..a5768a129e2a --- /dev/null +++ b/doc/ref/states/all/salt.states.win_task.rst @@ -0,0 +1,6 @@ +salt.states.win_task module +=========================== + +.. automodule:: salt.states.win_task + :members: + :undoc-members: diff --git a/doc/ref/states/all/salt.states.wordpress.rst b/doc/ref/states/all/salt.states.wordpress.rst new file mode 100644 index 000000000000..ac5f78bd9699 --- /dev/null +++ b/doc/ref/states/all/salt.states.wordpress.rst @@ -0,0 +1,5 @@ +salt.states.wordpress module +============================ + +.. automodule:: salt.states.wordpress + :members: diff --git a/doc/ref/states/all/salt.states.zabbix_service.rst b/doc/ref/states/all/salt.states.zabbix_service.rst new file mode 100644 index 000000000000..3ac80f59ba02 --- /dev/null +++ b/doc/ref/states/all/salt.states.zabbix_service.rst @@ -0,0 +1,5 @@ +salt.states.zabbix_service module +================================= + +.. automodule:: salt.states.zabbix_service + :members: diff --git a/doc/ref/states/all/salt.states.zabbix_usermacro.rst b/doc/ref/states/all/salt.states.zabbix_usermacro.rst new file mode 100644 index 000000000000..08c758551a6f --- /dev/null +++ b/doc/ref/states/all/salt.states.zabbix_usermacro.rst @@ -0,0 +1,5 @@ +salt.states.zabbix_usermacro module +=================================== + +.. automodule:: salt.states.zabbix_usermacro + :members: diff --git a/salt/cloud/clouds/clc.py b/salt/cloud/clouds/clc.py index 70bd6367177c..2624add9f602 100644 --- a/salt/cloud/clouds/clc.py +++ b/salt/cloud/clouds/clc.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ''' CenturyLink Cloud Module -=================== +======================== .. versionadded:: Oyxgen @@ -29,9 +29,12 @@ For sdk reference see: https://github.com/CenturyLinkCloud/clc-python-sdk Flask -------- +----- + flask can be installed via pip: + .. code-block:: bash + pip install flask Configuration diff --git a/salt/cloud/clouds/packet.py b/salt/cloud/clouds/packet.py index 6c3396db2625..713f2b954262 100644 --- a/salt/cloud/clouds/packet.py +++ b/salt/cloud/clouds/packet.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ''' Packet Cloud Module Using Packet's Python API Client -=========================================== +==================================================== The Packet cloud module is used to control access to the Packet VPS system. @@ -13,17 +13,18 @@ Optional profile parameters: - - ``storage_size`` - min value is 10, defines Gigabytes of storage that will be attached to device. - - ``storage_tier`` - storage_1 - Standard Plan, storage_2 - Performance Plan - - ``snapshot_count`` - int - - ``snapshot_frequency`` - string - possible values: - - 1min - - 15min - - 1hour - - 1day - - 1week - - 1month - - 1year +- ``storage_size`` - min value is 10, defines Gigabytes of storage that will be attached to device. +- ``storage_tier`` - storage_1 - Standard Plan, storage_2 - Performance Plan +- ``snapshot_count`` - int +- ``snapshot_frequency`` - string - possible values: + + - 1min + - 15min + - 1hour + - 1day + - 1week + - 1month + - 1year This driver requires Packet's client library: https://pypi.python.org/pypi/packet-python @@ -516,7 +517,9 @@ def list_nodes(call=None): ''' Returns a list of devices, keeping only a brief listing. CLI Example: + .. code-block:: bash + salt-cloud -Q salt-cloud --query salt-cloud -f list_nodes packet-provider diff --git a/salt/cloud/clouds/saltify.py b/salt/cloud/clouds/saltify.py index 00ed2dc96965..f3a39d1cfa8f 100644 --- a/salt/cloud/clouds/saltify.py +++ b/salt/cloud/clouds/saltify.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ''' -.. _`saltify-module`: +.. _saltify-module: Saltify Module ============== diff --git a/salt/engines/script.py b/salt/engines/script.py index a88b87bf7104..ec6ec7d5d4b0 100644 --- a/salt/engines/script.py +++ b/salt/engines/script.py @@ -73,16 +73,18 @@ def start(cmd, output='json', interval=1): Given the following json output from a script: - { "tag" : "lots/of/tacos", - "data" : { "toppings" : "cilantro" } - } + .. code-block:: json + + { "tag" : "lots/of/tacos", + "data" : { "toppings" : "cilantro" } + } This will fire the event 'lots/of/tacos' on the event bus with the data obj as is. :param cmd: The command to execute :param output: How to deserialize stdout of the script - :param interval: How often to execute the script. + :param interval: How often to execute the script ''' try: cmd = shlex.split(cmd) diff --git a/salt/modules/azurearm_dns.py b/salt/modules/azurearm_dns.py index 7001215a8acb..cf053c139ce5 100644 --- a/salt/modules/azurearm_dns.py +++ b/salt/modules/azurearm_dns.py @@ -18,32 +18,37 @@ * `azure-mgmt-web `_ >= 0.32.0 * `azure-storage `_ >= 0.34.3 * `msrestazure `_ >= 0.4.21 -:platform: linux -:configuration: This module requires Azure Resource Manager credentials to be passed as keyword arguments -to every function in order to work properly. +:platform: linux +:configuration: + This module requires Azure Resource Manager credentials to be passed as keyword arguments + to every function in order to work properly. - Required provider parameters: +Required provider parameters: if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` + + * ``subscription_id`` + * ``username`` + * ``password`` if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - Optional provider parameters: + * ``subscription_id`` + * ``tenant`` + * ``client_id`` + * ``secret`` + +Optional provider parameters: **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. + Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` + + * ``AZURE_PUBLIC_CLOUD`` (default) + * ``AZURE_CHINA_CLOUD`` + * ``AZURE_US_GOV_CLOUD`` + * ``AZURE_GERMAN_CLOUD`` ''' @@ -90,9 +95,10 @@ def record_set_create_or_update(name, zone_name, resource_group, record_type, ** :param resource_group: The name of the resource group. - :param record_type: The type of DNS record in this record set. Record sets of type SOA can be - updated but not created (they are created when the DNS zone is created). - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' + :param record_type: + The type of DNS record in this record set. Record sets of type SOA can be + updated but not created (they are created when the DNS zone is created). + Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' CLI Example: @@ -142,9 +148,10 @@ def record_set_delete(name, zone_name, resource_group, record_type, **kwargs): :param resource_group: The name of the resource group. - :param record_type: The type of DNS record in this record set. Record sets of type SOA cannot be - deleted (they are deleted when the DNS zone is deleted). - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' + :param record_type: + The type of DNS record in this record set. Record sets of type SOA cannot be + deleted (they are deleted when the DNS zone is deleted). + Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' CLI Example: @@ -182,8 +189,9 @@ def record_set_get(name, zone_name, resource_group, record_type, **kwargs): :param resource_group: The name of the resource group. - :param record_type: The type of DNS record in this record set. - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' + :param record_type: + The type of DNS record in this record set. + Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' CLI Example: @@ -219,14 +227,17 @@ def record_sets_list_by_type(zone_name, resource_group, record_type, top=None, r :param resource_group: The name of the resource group. - :param record_type: The type of record sets to enumerate. - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' + :param record_type: + The type of record sets to enumerate. + Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' - :param top: The maximum number of record sets to return. If not specified, - returns up to 100 record sets. + :param top: + The maximum number of record sets to return. If not specified, + returns up to 100 record sets. - :param recordsetnamesuffix: The suffix label of the record set name that has - to be used to filter the record set enumerations. + :param recordsetnamesuffix: + The suffix label of the record set name that has + to be used to filter the record set enumerations. CLI Example: @@ -267,11 +278,13 @@ def record_sets_list_by_dns_zone(zone_name, resource_group, top=None, recordsetn :param resource_group: The name of the resource group. - :param top: The maximum number of record sets to return. If not specified, - returns up to 100 record sets. + :param top: + The maximum number of record sets to return. If not specified, + returns up to 100 record sets. - :param recordsetnamesuffix: The suffix label of the record set name that has - to be used to filter the record set enumerations. + :param recordsetnamesuffix: + The suffix label of the record set name that has + to be used to filter the record set enumerations. CLI Example: @@ -428,8 +441,9 @@ def zones_list_by_resource_group(resource_group, top=None, **kwargs): :param resource_group: The name of the resource group. - :param top: The maximum number of DNS zones to return. If not specified, - returns up to 100 zones. + :param top: + The maximum number of DNS zones to return. If not specified, + returns up to 100 zones. CLI Example: @@ -463,8 +477,9 @@ def zones_list(top=None, **kwargs): Lists the DNS zones in all resource groups in a subscription. - :param top: The maximum number of DNS zones to return. If not specified, - returns up to 100 zones. + :param top: + The maximum number of DNS zones to return. If not specified, + eturns up to 100 zones. CLI Example: diff --git a/salt/modules/baredoc.py b/salt/modules/baredoc.py new file mode 100644 index 000000000000..59d1d40f082d --- /dev/null +++ b/salt/modules/baredoc.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +''' +Baredoc walks the installed module and state directories and generates +dictionaries and lists of the function names and their arguments. + +.. versionadded:: Neon + +''' +from __future__ import absolute_import, unicode_literals, print_function + +# Import python libs +import logging +import os +import re + +# Import salt libs +import salt.loader +import salt.runner +import salt.state +import salt.utils.data +import salt.utils.files +import salt.utils.args +import salt.utils.schema + +# Import 3rd-party libs +from salt.ext import six +from salt.utils.odict import OrderedDict + +log = logging.getLogger(__name__) + + +def _parse_function_definition(fn_def, modulename, ret): + args = [] + match = re.match(r'def\s+(.*?)\((.*)\):$', fn_def) + if match is None: + return + fn_name = match.group(1) + if fn_name.startswith('_'): + return + if fn_name.endswith('_'): + fn_name = fn_name[0:-1] + fn_name = fn_name.strip('"') + fn_name = fn_name.strip("'") + try: + raw_args = match.group(2) + raw_args = re.sub(r'(.*)\(.*\)(.*)', r'\1\2', raw_args) + raw_args = re.sub(r'(.*)\'.*\'(.*)', r'\1\2', raw_args) + individual_args = raw_args.split(',') + for a in individual_args: + if '*' in a: + continue + args.append(a.split('=')[0].strip()) + except AttributeError: + pass + key = '{}.{}'.format(modulename, fn_name) + if key in ret: + ret[key].extend(args) + else: + ret[key] = args + ret[key] = list(set(ret[key])) + + +def _mods_with_args(dirs): + ret = {} + for d in dirs: + for m in os.listdir(d): + if m.endswith('.py'): + with salt.utils.files.fopen(os.path.join(d, m), 'r') as f: + in_def = False + fn_def = u'' + modulename = m.split('.')[0] + virtualname = None + + for l in f: + l = salt.utils.data.decode(l, encoding='utf-8').rstrip() + l = re.sub(r'(.*)#(.*)', r'\1', l) + if '__virtualname__ =' in l and not virtualname: + virtualname = l.split()[2].strip("'").strip('"') + continue + if l.startswith(u'def '): + in_def = True + fn_def = l + if ':' in l: + if in_def: + if not l.startswith(u'def '): + fn_def = fn_def + l + _parse_function_definition(fn_def, virtualname or modulename, ret) + fn_def = u'' + in_def = False + continue + if in_def and not l.startswith(u'def '): + fn_def = fn_def + l + return ret + + +def modules_and_args(modules=True, states=False, names_only=False): + ''' + Walk the Salt install tree and return a dictionary or a list + of the functions therein as well as their arguments. + + :param modules: Walk the modules directory if True + :param states: Walk the states directory if True + :param names_only: Return only a list of the callable functions instead of a dictionary with arguments + :return: An OrderedDict with callable function names as keys and lists of arguments as + values (if ``names_only`` == False) or simply an ordered list of callable + function nanes (if ``names_only`` == True). + + CLI Example: + (example truncated for brevity) + + .. code-block:: bash + + salt myminion baredoc.modules_and_args + + myminion: + ---------- + [...] + at.atrm: + at.jobcheck: + at.mod_watch: + - name + at.present: + - unique_tag + - name + - timespec + - job + - tag + - user + at.watch: + - unique_tag + - name + - timespec + - job + - tag + - user + [...] + ''' + dirs = [] + module_dir = os.path.dirname(os.path.realpath(__file__)) + state_dir = os.path.join(os.path.dirname(module_dir), 'states') + + if modules: + dirs.append(module_dir) + if states: + dirs.append(state_dir) + + ret = _mods_with_args(dirs) + if names_only: + return sorted(ret.keys()) + else: + return OrderedDict(sorted(ret.items())) + + +def modules_with_test(): + ''' + Return a list of callable functions that have a ``test=`` flag. + + CLI Example: + + (results trimmed for brevity) + + .. code-block:: bash + + salt myminion baredoc.modules_with_test + + myminion: + ---------- + - boto_elb.set_instances + - netconfig.managed + - netconfig.replace_pattern + - pkg.install + - salt.state + - state.high + - state.highstate + + ''' + mods = modules_and_args() + testmods = [] + for module_name, module_args in six.iteritems(mods): + if 'test' in module_args: + testmods.append(module_name) + + return sorted(testmods) diff --git a/salt/modules/boto_ssm.py b/salt/modules/boto_ssm.py index 7b98f4221aff..d99f7c70e546 100644 --- a/salt/modules/boto_ssm.py +++ b/salt/modules/boto_ssm.py @@ -107,6 +107,7 @@ def delete_parameter(Name, region=None, key=None, keyid=None, profile=None): .. versionadded:: Neon .. code-block:: text + salt-call boto_ssm.delete_parameter test-param ''' conn = __utils__['boto3.get_connection']('ssm', region=region, key=key, keyid=keyid, profile=profile) diff --git a/salt/modules/gcp_addon.py b/salt/modules/gcp_addon.py index 6a587de4b506..a80cb672927b 100644 --- a/salt/modules/gcp_addon.py +++ b/salt/modules/gcp_addon.py @@ -11,7 +11,7 @@ This module will create a route to send traffic destined to the Internet through your gateway instance. -:codeauthor: :email:`Pratik Bandarkar ` +:codeauthor: `Pratik Bandarkar ` :maturity: new :depends: google-api-python-client :platform: Linux diff --git a/salt/modules/highstate_doc.py b/salt/modules/highstate_doc.py index cda08337162f..4d3ecf6360ea 100644 --- a/salt/modules/highstate_doc.py +++ b/salt/modules/highstate_doc.py @@ -6,13 +6,13 @@ How it works: - `highstate or lowstate` data is parsed with a `proccesser` this defaults to `highstate_doc.proccesser_markdown`. - The proccessed data is passed to a `jinja` template that builds up the document content. +`highstate or lowstate` data is parsed with a `proccesser` this defaults to `highstate_doc.proccesser_markdown`. +The proccessed data is passed to a `jinja` template that builds up the document content. configuration: Pillar -.. code-block:: yaml +.. code-block:: none # the following defaults can be overrided highstate_doc.config: @@ -145,7 +145,7 @@ If you wish to customize the document format: -.. code-block:: yaml +.. code-block:: none # you could also create a new `proccesser` for perhaps reStructuredText # highstate_doc.config: @@ -178,40 +178,51 @@ - mode: '0640' -Some `replace_text_regex` values that might be helpful. - - ## CERTS - '-----BEGIN RSA PRIVATE KEY-----[\r\n\t\f\S]{0,2200}': 'XXXXXXX' - '-----BEGIN CERTIFICATE-----[\r\n\t\f\S]{0,2200}': 'XXXXXXX' - '-----BEGIN DH PARAMETERS-----[\r\n\t\f\S]{0,2200}': 'XXXXXXX' - '-----BEGIN PRIVATE KEY-----[\r\n\t\f\S]{0,2200}': 'XXXXXXX' - '-----BEGIN OPENSSH PRIVATE KEY-----[\r\n\t\f\S]{0,2200}': 'XXXXXXX' - 'ssh-rsa .* ': 'ssh-rsa XXXXXXX ' - 'ssh-dss .* ': 'ssh-dss XXXXXXX ' - ## DB - 'DB_PASS.*': 'DB_PASS = XXXXXXX' - '5432:*:*:.*': '5432:*:XXXXXXX' - "'PASSWORD': .*": "'PASSWORD': 'XXXXXXX'," - " PASSWORD '.*'": " PASSWORD 'XXXXXXX'" - 'PGPASSWORD=.* ': 'PGPASSWORD=XXXXXXX' - "_replication password '.*'": "_replication password 'XXXXXXX'" - ## OTHER - 'EMAIL_HOST_PASSWORD =.*': 'EMAIL_HOST_PASSWORD =XXXXXXX' - "net ads join -U '.*@MFCFADS.MATH.EXAMPLE.CA.* ": "net ads join -U '.*@MFCFADS.MATH.EXAMPLE.CA%XXXXXXX " - "net ads join -U '.*@NEXUS.EXAMPLE.CA.* ": "net ads join -U '.*@NEXUS.EXAMPLE.CA%XXXXXXX " - 'install-uptrack .* --autoinstall': 'install-uptrack XXXXXXX --autoinstall' - 'accesskey = .*': 'accesskey = XXXXXXX' - 'auth_pass .*': 'auth_pass XXXXXXX' - 'PSK "0x.*': 'PSK "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - 'SECRET_KEY.*': 'SECRET_KEY = XXXXXXX' - "password=.*": "password=XXXXXXX" - '.*': 'XXXXXXX' - '.*': 'XXXXXXX' - 'application.secret = ".*"': 'application.secret = "XXXXXXX"' - 'url = "postgres://.*"': 'url = "postgres://XXXXXXX"' - 'PASS_.*_PASS': 'PASS_XXXXXXX_PASS' - ## HTACCESS - ':{PLAIN}.*': ':{PLAIN}XXXXXXX' +Some `replace_text_regex` values that might be helpful:: + + CERTS + ----- + + ``'-----BEGIN RSA PRIVATE KEY-----[\\r\\n\\t\\f\\S]{0,2200}': 'XXXXXXX'`` + ``'-----BEGIN CERTIFICATE-----[\\r\\n\\t\\f\\S]{0,2200}': 'XXXXXXX'`` + ``'-----BEGIN DH PARAMETERS-----[\\r\\n\\t\\f\\S]{0,2200}': 'XXXXXXX'`` + ``'-----BEGIN PRIVATE KEY-----[\\r\\n\\t\\f\\S]{0,2200}': 'XXXXXXX'`` + ``'-----BEGIN OPENSSH PRIVATE KEY-----[\\r\\n\\t\\f\\S]{0,2200}': 'XXXXXXX'`` + ``'ssh-rsa .* ': 'ssh-rsa XXXXXXX '`` + ``'ssh-dss .* ': 'ssh-dss XXXXXXX '`` + + DB + -- + + ``'DB_PASS.*': 'DB_PASS = XXXXXXX'`` + ``'5432:*:*:.*': '5432:*:XXXXXXX'`` + ``"'PASSWORD': .*": "'PASSWORD': 'XXXXXXX',"`` + ``" PASSWORD '.*'": " PASSWORD 'XXXXXXX'"`` + ``'PGPASSWORD=.* ': 'PGPASSWORD=XXXXXXX'`` + ``"_replication password '.*'": "_replication password 'XXXXXXX'"`` + + OTHER + ----- + + ``'EMAIL_HOST_PASSWORD =.*': 'EMAIL_HOST_PASSWORD =XXXXXXX'`` + ``"net ads join -U '.*@MFCFADS.MATH.EXAMPLE.CA.* ": "net ads join -U '.*@MFCFADS.MATH.EXAMPLE.CA%XXXXXXX "`` + ``"net ads join -U '.*@NEXUS.EXAMPLE.CA.* ": "net ads join -U '.*@NEXUS.EXAMPLE.CA%XXXXXXX "`` + ``'install-uptrack .* --autoinstall': 'install-uptrack XXXXXXX --autoinstall'`` + ``'accesskey = .*': 'accesskey = XXXXXXX'`` + ``'auth_pass .*': 'auth_pass XXXXXXX'`` + ``'PSK "0x.*': 'PSK "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'`` + ``'SECRET_KEY.*': 'SECRET_KEY = XXXXXXX'`` + ``"password=.*": "password=XXXXXXX"`` + ``'.*': 'XXXXXXX'`` + ``'.*': 'XXXXXXX'`` + ``'application.secret = ".*"': 'application.secret = "XXXXXXX"'`` + ``'url = "postgres://.*"': 'url = "postgres://XXXXXXX"'`` + ``'PASS_.*_PASS': 'PASS_XXXXXXX_PASS'`` + + HTACCESS + -------- + + ``':{PLAIN}.*': ':{PLAIN}XXXXXXX'`` ''' @@ -429,10 +440,12 @@ def render(jinja_template_text=None, jinja_template_function='highstate_doc.mark jinja_template_text: jinja text that the render uses to create the document. jinja_template_function: a salt module call that returns template text. - options: - highstate_doc.markdown_basic_jinja_template - highstate_doc.markdown_default_jinja_template - highstate_doc.markdown_full_jinja_template + + :options: + highstate_doc.markdown_basic_jinja_template + highstate_doc.markdown_default_jinja_template + highstate_doc.markdown_full_jinja_template + ''' config = _get_config(**kwargs) lowstates = proccess_lowstates(**kwargs) @@ -584,7 +597,7 @@ def proccesser_markdown(lowstate_item, config, **kwargs): This `lowstate_item_markdown` given a lowstate item, returns a dict like: - .. code-block:: yaml + .. code-block:: none vars: # the raw lowstate_item that was proccessed id: # the 'id' of the state. diff --git a/salt/modules/nxos_upgrade.py b/salt/modules/nxos_upgrade.py new file mode 100644 index 000000000000..5c8340515e37 --- /dev/null +++ b/salt/modules/nxos_upgrade.py @@ -0,0 +1,406 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018 Cisco and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +''' +Execution module to upgrade Cisco NX-OS Switches. + +.. versionadded:: xxxx.xx.x + +This module supports execution using a Proxy Minion or Native Minion:: + + 1. Proxy Minion: Connect over SSH or NX-API HTTP(S). + See :mod:`salt.proxy.nxos ` for proxy minion setup details. + 2. Native Minion: Connect over NX-API Unix Domain Socket (UDS). + Install the minion inside the GuestShell running on the NX-OS device. + +:maturity: new +:platform: nxos +:codeauthor: Michael G Wiebe + +.. note:: + + To use this module over remote NX-API the feature must be enabled on the + NX-OS device by executing ``feature nxapi`` in configuration mode. + + This is not required for NX-API over UDS. + + Configuration example: + + .. code-block:: bash + + switch# conf t + switch(config)# feature nxapi + + To check that NX-API is properly enabled, execute ``show nxapi``. + + Output example: + + .. code-block:: bash + + switch# show nxapi + nxapi enabled + HTTPS Listen on port 443 +''' +from __future__ import absolute_import, print_function, unicode_literals + +# Import python stdlib +import logging +import re +import ast +import time +from salt.ext.six import string_types + +# Import Salt libs +from salt.exceptions import (NxosError, CommandExecutionError) +from salt.ext.six.moves import range + +__virtualname__ = 'nxos' +__virtual_aliases__ = ('nxos_upgrade',) + +log = logging.getLogger(__name__) + + +def __virtual__(): + return __virtualname__ + + +def check_upgrade_impact(system_image, kickstart_image=None, issu=True, **kwargs): + ''' + Display upgrade impact information without actually upgrading the device. + + system_image (Mandatory Option) + Path on bootflash: to system image upgrade file. + + kickstart_image + Path on bootflash: to kickstart image upgrade file. + (Not required if using combined system/kickstart image file) + Default: None + + issu + When True: Attempt In Service Software Upgrade. (non-disruptive) + The upgrade will abort if issu is not possible. + When False: Force (disruptive) Upgrade/Downgrade. + Default: True + + timeout + Timeout in seconds for long running 'install all' impact command. + Default: 900 + + error_pattern + Use the option to pass in a regular expression to search for in the + output of the 'install all impact' command that indicates an error + has occurred. This option is only used when proxy minion connection + type is ssh and otherwise ignored. + + .. code-block:: bash + + salt 'n9k' nxos.check_upgrade_impact system_image=nxos.9.2.1.bin + salt 'n7k' nxos.check_upgrade_impact system_image=n7000-s2-dk9.8.1.1.bin \\ + kickstart_image=n7000-s2-kickstart.8.1.1.bin issu=False + ''' + # Input Validation + if not isinstance(issu, bool): + return 'Input Error: The [issu] parameter must be either True or False' + + si = system_image + ki = kickstart_image + dev = 'bootflash' + cmd = 'terminal dont-ask ; show install all impact' + + if ki is not None: + cmd = cmd + ' kickstart {0}:{1} system {0}:{2}'.format(dev, ki, si) + else: + cmd = cmd + ' nxos {0}:{1}'.format(dev, si) + + if issu and ki is None: + cmd = cmd + ' non-disruptive' + + log.info("Check upgrade impact using command: '%s'", cmd) + kwargs.update({'timeout': kwargs.get('timeout', 900)}) + error_pattern_list = ['Another install procedure may be in progress', + 'Pre-upgrade check failed'] + kwargs.update({'error_pattern': error_pattern_list}) + + # Execute Upgrade Impact Check + try: + impact_check = __salt__['nxos.sendline'](cmd, **kwargs) + except CommandExecutionError as e: + impact_check = ast.literal_eval(e.message) + return _parse_upgrade_data(impact_check) + + +def upgrade(system_image, kickstart_image=None, issu=True, **kwargs): + ''' + Upgrade NX-OS switch. + + system_image (Mandatory Option) + Path on bootflash: to system image upgrade file. + + kickstart_image + Path on bootflash: to kickstart image upgrade file. + (Not required if using combined system/kickstart image file) + Default: None + + issu + Set this option to True when an In Service Software Upgrade or + non-disruptive upgrade is required. The upgrade will abort if issu is + not possible. + Default: True + + timeout + Timeout in seconds for long running 'install all' upgrade command. + Default: 900 + + error_pattern + Use the option to pass in a regular expression to search for in the + output of the 'install all upgrade command that indicates an error + has occurred. This option is only used when proxy minion connection + type is ssh and otherwise ignored. + + .. code-block:: bash + + salt 'n9k' nxos.upgrade system_image=nxos.9.2.1.bin + salt 'n7k' nxos.upgrade system_image=n7000-s2-dk9.8.1.1.bin \\ + kickstart_image=n7000-s2-kickstart.8.1.1.bin issu=False + ''' + # Input Validation + if not isinstance(issu, bool): + return 'Input Error: The [issu] parameter must be either True or False' + + impact = None + upgrade = None + maxtry = 60 + for attempt in range(1, maxtry): + # Gather impact data first. It's possible to loose upgrade data + # when the switch reloads or switches over to the inactive supervisor. + # The impact data will be used if data being collected during the + # upgrade is lost. + if impact is None: + log.info('Gathering impact data') + impact = check_upgrade_impact(system_image, kickstart_image, + issu, **kwargs) + if impact['installing']: + log.info('Another show impact in progress... wait and retry') + time.sleep(30) + continue + # If we are upgrading from a system running a separate system and + # kickstart image to a combined image or vice versa then the impact + # check will return a syntax error as it's not supported. + # Skip the impact check in this case and attempt the upgrade. + if impact['invalid_command']: + impact = False + continue + log.info('Impact data gathered:\n%s', impact) + + # Check to see if conditions are sufficent to return the impact + # data and not proceed with the actual upgrade. + # + # Impact data indicates the upgrade or downgrade will fail + if impact['error_data']: + return impact + # Requested ISSU but ISSU is not possible + if issu and not impact['upgrade_non_disruptive']: + impact['error_data'] = impact['upgrade_data'] + return impact + # Impact data indicates a failure and no module_data collected + if not impact['succeeded'] and not impact['module_data']: + impact['error_data'] = impact['upgrade_data'] + return impact + # Impact data indicates switch already running desired image + if not impact['upgrade_required']: + impact['succeeded'] = True + return impact + # If we get here, impact data indicates upgrade is needed. + upgrade = _upgrade(system_image, kickstart_image, issu, **kwargs) + if upgrade['installing']: + log.info('Another install is in progress... wait and retry') + time.sleep(30) + continue + # If the issu option is False and this upgrade request includes a + # kickstart image then the 'force' option is used. This option is + # only available in certain image sets. + if upgrade['invalid_command']: + log_msg = 'The [issu] option was set to False for this upgrade.' + log_msg = log_msg + ' Attempt was made to ugrade using the force' + log_msg = log_msg + ' keyword which is not supported in this' + log_msg = log_msg + ' image. Set [issu=True] and re-try.' + upgrade['upgrade_data'] = log_msg + break + break + + # Check for errors and return upgrade result: + if upgrade['backend_processing_error']: + # This means we received a backend processing error from the transport + # and lost the upgrade data. This also indicates that the upgrade + # is in progress so use the impact data for logging purposes. + impact['upgrade_in_progress'] = True + return impact + return upgrade + + +def _upgrade(system_image, kickstart_image, issu, **kwargs): + ''' + Helper method that does the heavy lifting for upgrades. + ''' + si = system_image + ki = kickstart_image + dev = 'bootflash' + cmd = 'terminal dont-ask ; install all' + + if ki is None: + logmsg = 'Upgrading device using combined system/kickstart image.' + logmsg += '\nSystem Image: {}'.format(si) + cmd = cmd + ' nxos {0}:{1}'.format(dev, si) + if issu: + cmd = cmd + ' non-disruptive' + else: + logmsg = 'Upgrading device using separate system/kickstart images.' + logmsg += '\nSystem Image: {}'.format(si) + logmsg += '\nKickstart Image: {}'.format(ki) + if not issu: + log.info('Attempting upgrade using force option') + cmd = cmd + ' force' + cmd = cmd + ' kickstart {0}:{1} system {0}:{2}'.format(dev, ki, si) + + if issu: + logmsg += '\nIn Service Software Upgrade/Downgrade (non-disruptive) requested.' + else: + logmsg += '\nDisruptive Upgrade/Downgrade requested.' + + log.info(logmsg) + log.info("Begin upgrade using command: '%s'", cmd) + + kwargs.update({'timeout': kwargs.get('timeout', 900)}) + error_pattern_list = ['Another install procedure may be in progress'] + kwargs.update({'error_pattern': error_pattern_list}) + + # Begin Actual Upgrade + try: + upgrade_result = __salt__['nxos.sendline'](cmd, **kwargs) + except CommandExecutionError as e: + upgrade_result = ast.literal_eval(e.message) + except NxosError as e: + if re.search('Code: 500', e.message): + upgrade_result = e.message + else: + upgrade_result = ast.literal_eval(e.message) + return _parse_upgrade_data(upgrade_result) + + +def _parse_upgrade_data(data): + ''' + Helper method to parse upgrade data from the NX-OS device. + ''' + upgrade_result = {} + upgrade_result['upgrade_data'] = None + upgrade_result['succeeded'] = False + upgrade_result['upgrade_required'] = False + upgrade_result['upgrade_non_disruptive'] = False + upgrade_result['upgrade_in_progress'] = False + upgrade_result['installing'] = False + upgrade_result['module_data'] = {} + upgrade_result['error_data'] = None + upgrade_result['backend_processing_error'] = False + upgrade_result['invalid_command'] = False + + # Error handling + if isinstance(data, string_types) and re.search('Code: 500', data): + log.info('Detected backend processing error') + upgrade_result['error_data'] = data + upgrade_result['backend_processing_error'] = True + return upgrade_result + + if isinstance(data, dict): + if 'code' in data and data['code'] == '400': + log.info('Detected client error') + upgrade_result['error_data'] = data['cli_error'] + + if re.search('install.*may be in progress', data['cli_error']): + log.info('Detected install in progress...') + upgrade_result['installing'] = True + + if re.search('Invalid command', data['cli_error']): + log.info('Detected invalid command...') + upgrade_result['invalid_command'] = True + else: + # If we get here then it's likely we lost access to the device + # but the upgrade succeeded. We lost the actual upgrade data so + # set the flag such that impact data is used instead. + log.info('Probable backend processing error') + upgrade_result['backend_processing_error'] = True + return upgrade_result + + # Get upgrade data for further parsing + # Case 1: Command terminal dont-ask returns empty {} that we don't need. + if isinstance(data, list) and len(data) == 2: + data = data[1] + # Case 2: Command terminal dont-ask does not get included. + if isinstance(data, list) and len(data) == 1: + data = data[0] + + log.info('Parsing NX-OS upgrade data') + upgrade_result['upgrade_data'] = data + for line in data.split('\n'): + + log.info('Processing line: (%s)', line) + + # Check to see if upgrade is disruptive or non-disruptive + if re.search(r'non-disruptive', line): + log.info('Found non-disruptive line') + upgrade_result['upgrade_non_disruptive'] = True + + # Example: + # Module Image Running-Version(pri:alt) New-Version Upg-Required + # 1 nxos 7.0(3)I7(5a) 7.0(3)I7(5a) no + # 1 bios v07.65(09/04/2018) v07.64(05/16/2018) no + mo = re.search(r'(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(yes|no)', line) + if mo: + log.info('Matched Module Running/New Version Upg-Req Line') + bk = 'module_data' # base key + g1 = mo.group(1) + g2 = mo.group(2) + g3 = mo.group(3) + g4 = mo.group(4) + g5 = mo.group(5) + mk = 'module {0}:image {1}'.format(g1, g2) # module key + upgrade_result[bk][mk] = {} + upgrade_result[bk][mk]['running_version'] = g3 + upgrade_result[bk][mk]['new_version'] = g4 + if g5 == 'yes': + upgrade_result['upgrade_required'] = True + upgrade_result[bk][mk]['upgrade_required'] = True + continue + + # The following lines indicate a successfull upgrade. + if re.search(r'Install has been successful', line): + log.info('Install successful line') + upgrade_result['succeeded'] = True + continue + + if re.search(r'Finishing the upgrade, switch will reboot in', line): + log.info('Finishing upgrade line') + upgrade_result['upgrade_in_progress'] = True + continue + + if re.search(r'Switch will be reloaded for disruptive upgrade', line): + log.info('Switch will be reloaded line') + upgrade_result['upgrade_in_progress'] = True + continue + + if re.search(r'Switching over onto standby', line): + log.info('Switching over onto standby line') + upgrade_result['upgrade_in_progress'] = True + continue + + return upgrade_result diff --git a/salt/modules/saltsupport.py b/salt/modules/saltsupport.py new file mode 100644 index 000000000000..bfb1db3a5afc --- /dev/null +++ b/salt/modules/saltsupport.py @@ -0,0 +1,381 @@ +# -*- coding: utf-8 -*- +# +# Author: Bo Maryniuk +# +# Copyright 2018 SUSE LLC +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +''' +:codeauthor: `Bo Maryniuk ` + +Module to run salt-support within Salt. +''' +# pylint: disable=W0231,W0221 + +from __future__ import unicode_literals, print_function, absolute_import + +import tempfile +import re +import os +import sys +import time +import datetime +import logging + +import salt.cli.support.intfunc +import salt.utils.decorators +import salt.utils.path +import salt.cli.support +import salt.exceptions +import salt.utils.stringutils +import salt.defaults.exitcodes +import salt.utils.odict +import salt.utils.dictupdate + +from salt.cli.support.collector import SaltSupport, SupportDataCollector + +__virtualname__ = 'support' +log = logging.getLogger(__name__) + + +class LogCollector(object): + ''' + Output collector. + ''' + INFO = 'info' + WARNING = 'warning' + ERROR = 'error' + + class MessagesList(list): + def append(self, obj): + list.append(self, '{} - {}'.format(datetime.datetime.utcnow().strftime('%H:%M:%S.%f')[:-3], obj)) + __call__ = append + + def __init__(self): + self.messages = { + self.INFO: self.MessagesList(), + self.WARNING: self.MessagesList(), + self.ERROR: self.MessagesList(), + } + + def msg(self, message, *args, **kwargs): + title = kwargs.get('title') + if title: + message = '{}: {}'.format(title, message) + self.messages[self.INFO](message) + + def info(self, message, *args, **kwargs): + self.msg(message) + + def warning(self, message, *args, **kwargs): + self.messages[self.WARNING](message) + + def error(self, message, *args, **kwargs): + self.messages[self.ERROR](message) + + def put(self, message, *args, **kwargs): + self.messages[self.INFO](message) + + def highlight(self, message, *values, **kwargs): + self.msg(message.format(*values)) + + +class SaltSupportModule(SaltSupport): + ''' + Salt Support module class. + ''' + def __init__(self): + ''' + Constructor + ''' + self.config = self.setup_config() + + def setup_config(self): + ''' + Return current configuration + :return: + ''' + return __opts__ + + def _get_archive_name(self, archname=None): + ''' + Create default archive name. + + :return: + ''' + archname = re.sub('[^a-z0-9]', '', (archname or '').lower()) or 'support' + for grain in ['fqdn', 'host', 'localhost', 'nodename']: + host = __grains__.get(grain) + if host: + break + if not host: + host = 'localhost' + + return os.path.join(tempfile.gettempdir(), + '{hostname}-{archname}-{date}-{time}.bz2'.format(archname=archname, + hostname=host, + date=time.strftime('%Y%m%d'), + time=time.strftime('%H%M%S'))) + + @salt.utils.decorators.external + def profiles(self): + ''' + Get list of profiles. + + :return: + ''' + return { + 'standard': salt.cli.support.get_profiles(self.config), + 'custom': [], + } + + @salt.utils.decorators.external + def archives(self): + ''' + Get list of existing archives. + :return: + ''' + arc_files = [] + tmpdir = tempfile.gettempdir() + for filename in os.listdir(tmpdir): + mtc = re.match(r'\w+-\w+-\d+-\d+\.bz2', filename) + if mtc and len(filename) == mtc.span()[-1]: + arc_files.append(os.path.join(tmpdir, filename)) + + return arc_files + + @salt.utils.decorators.external + def last_archive(self): + ''' + Get the last available archive + :return: + ''' + archives = {} + for archive in self.archives(): + archives[int(archive.split('.')[0].split('-')[-1])] = archive + + return archives and archives[max(archives)] or None + + @salt.utils.decorators.external + def delete_archives(self, *archives): + ''' + Delete archives + :return: + ''' + # Remove paths + _archives = [] + for archive in archives: + _archives.append(os.path.basename(archive)) + archives = _archives[:] + + ret = {'files': {}, 'errors': {}} + for archive in self.archives(): + arc_dir = os.path.dirname(archive) + archive = os.path.basename(archive) + if archives and archive in archives or not archives: + archive = os.path.join(arc_dir, archive) + try: + os.unlink(archive) + ret['files'][archive] = 'removed' + except Exception as err: + ret['errors'][archive] = str(err) + ret['files'][archive] = 'left' + + return ret + + def format_sync_stats(self, cnt): + ''' + Format stats of the sync output. + + :param cnt: + :return: + ''' + stats = salt.utils.odict.OrderedDict() + if cnt.get('retcode') == salt.defaults.exitcodes.EX_OK: + for line in cnt.get('stdout', '').split(os.linesep): + line = line.split(': ') + if len(line) == 2: + stats[line[0].lower().replace(' ', '_')] = line[1] + cnt['transfer'] = stats + del cnt['stdout'] + + # Remove empty + empty_sections = [] + for section in cnt: + if not cnt[section] and section != 'retcode': + empty_sections.append(section) + for section in empty_sections: + del cnt[section] + + return cnt + + @salt.utils.decorators.depends('rsync') + @salt.utils.decorators.external + def sync(self, group, name=None, host=None, location=None, move=False, all=False): + ''' + Sync the latest archive to the host on given location. + + CLI Example: + + .. code-block:: bash + + salt '*' support.sync group=test + salt '*' support.sync group=test name=/tmp/myspecial-12345-67890.bz2 + salt '*' support.sync group=test name=/tmp/myspecial-12345-67890.bz2 host=allmystuff.lan + salt '*' support.sync group=test name=/tmp/myspecial-12345-67890.bz2 host=allmystuff.lan location=/opt/ + + :param group: name of the local directory to which sync is going to put the result files + :param name: name of the archive. Latest, if not specified. + :param host: name of the destination host for rsync. Default is master, if not specified. + :param location: local destination directory, default temporary if not specified + :param move: move archive file[s]. Default is False. + :param all: work with all available archives. Default is False (i.e. latest available) + + :return: + ''' + tfh, tfn = tempfile.mkstemp() + processed_archives = [] + src_uri = uri = None + + last_arc = self.last_archive() + if name: + archives = [name] + elif all: + archives = self.archives() + elif last_arc: + archives = [last_arc] + else: + archives = [] + + for name in archives: + err = None + if not name: + err = 'No support archive has been defined.' + elif not os.path.exists(name): + err = 'Support archive "{}" was not found'.format(name) + if err is not None: + log.error(err) + raise salt.exceptions.SaltInvocationError(err) + + if not uri: + src_uri = os.path.dirname(name) + uri = '{host}:{loc}'.format(host=host or __opts__['master'], + loc=os.path.join(location or tempfile.gettempdir(), group)) + + os.write(tfh, salt.utils.stringutils.to_bytes(os.path.basename(name))) + os.write(tfh, salt.utils.stringutils.to_bytes(os.linesep)) + processed_archives.append(name) + log.debug('Syncing %s to %s', name, uri) + os.close(tfh) + + if not processed_archives: + raise salt.exceptions.SaltInvocationError('No archives found to transfer.') + + ret = __salt__['rsync.rsync'](src=src_uri, dst=uri, additional_opts=['--stats', '--files-from={}'.format(tfn)]) + ret['files'] = {} + for name in processed_archives: + if move: + salt.utils.dictupdate.update(ret, self.delete_archives(name)) + log.debug('Deleting %s', name) + ret['files'][name] = 'moved' + else: + ret['files'][name] = 'copied' + + try: + os.unlink(tfn) + except (OSError, IOError) as err: + log.error('Cannot remove temporary rsync file %s: %s', tfn, err) + + return self.format_sync_stats(ret) + + @salt.utils.decorators.external + def run(self, profile='default', pillar=None, archive=None, output='nested'): + ''' + Run Salt Support on the minion. + + profile + Set available profile name. Default is "default". + + pillar + Set available profile from the pillars. + + archive + Override archive name. Default is "support". This results to "hostname-support-YYYYMMDD-hhmmss.bz2". + + output + Change the default outputter. Default is "nested". + + CLI Example: + + .. code-block:: bash + + salt '*' support.run + salt '*' support.run profile=network + salt '*' support.run pillar=something_special + ''' + class outputswitch(object): + ''' + Output switcher on context + ''' + def __init__(self, output_device): + self._tmp_out = output_device + self._orig_out = None + + def __enter__(self): + self._orig_out = salt.cli.support.intfunc.out + salt.cli.support.intfunc.out = self._tmp_out + + def __exit__(self, *args): + salt.cli.support.intfunc.out = self._orig_out + + self.out = LogCollector() + with outputswitch(self.out): + self.collector = SupportDataCollector(archive or self._get_archive_name(archname=archive), output) + self.collector.out = self.out + self.collector.open() + self.collect_local_data(profile=profile, profile_source=__pillar__.get(pillar)) + self.collect_internal_data() + self.collector.close() + + return {'archive': self.collector.archive_path, + 'messages': self.out.messages} + + +def __virtual__(): + ''' + Set method references as module functions aliases + :return: + ''' + support = SaltSupportModule() + + def _set_function(obj): + ''' + Create a Salt function for the SaltSupport class. + ''' + def _cmd(*args, **kwargs): + ''' + Call support method as a function from the Salt. + ''' + _kwargs = {} + for kw in kwargs: + if not kw.startswith('__'): + _kwargs[kw] = kwargs[kw] + return obj(*args, **_kwargs) + _cmd.__doc__ = obj.__doc__ + return _cmd + + for m_name in dir(support): + obj = getattr(support, m_name) + if getattr(obj, 'external', False): + setattr(sys.modules[__name__], m_name, _set_function(obj)) + + return __virtualname__ diff --git a/salt/modules/win_auditpol.py b/salt/modules/win_auditpol.py index 755b58aed4a8..892dc3a94e1a 100644 --- a/salt/modules/win_auditpol.py +++ b/salt/modules/win_auditpol.py @@ -169,6 +169,7 @@ def set_setting(name, value): CLI Example: .. code-block:: bash + # Set the state of the "Credential Validation" setting to Success and # Failure salt * auditpol.set_setting "Credential Validation" "Success and Failure" diff --git a/salt/pillar/extra_minion_data_in_pillar.py b/salt/pillar/extra_minion_data_in_pillar.py index bbedec68666d..2937c18465a8 100644 --- a/salt/pillar/extra_minion_data_in_pillar.py +++ b/salt/pillar/extra_minion_data_in_pillar.py @@ -11,7 +11,7 @@ Complete example in etc/salt/master ===================================== -.. code-block:: yaml +.. code-block:: none ext_pillar: - extra_minion_data_in_pillar: diff --git a/salt/pillar/nsot.py b/salt/pillar/nsot.py new file mode 100644 index 000000000000..f815e5890fb9 --- /dev/null +++ b/salt/pillar/nsot.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +''' +A module that adds data to the Pillar structure from the NSoT API. + +.. versionadded:: Neon + +Configuring the NSoT ext_pillar +--------------------------------- + +The following fields are required: + +.. code-block:: yaml + + ext_pillar: + - nsot: + api_url: http://nsot_url.com/api/ + email: 'user@site.com' + secret_key: abc123 + +.. note:: + + Note the trailing slash on the api_url field. Although NSoT gives the option + of whether or not to use the tailing slash, this module assumes that the + APPEND_SLASH option is set to True (the default) + +The following fields are optional: + +fqdn_separator: ``str`` + This is in case a minion_id contains a dot. Because NSoT + doesn't allow hostnmes with dots, this option allows you to look up a device + with this character replacing dots. For example, with this option set to + '-', the minion rtr1.lax1 would be looked up in NSoT as rtr1-lax1. + +all_devices_regex: ``list`` + This is a list of minions that will receive all device + information in NSoT, given in the form of regular expressions. These minions + do not need to be in nsot in order to retrieve all device info from nsot. + +minion_regex: ``list`` + This is in case you only want certain minions being looked + up in NSoT. For example, if you have 500 minions on a single master, you may + not want all of them hitting the NSoT endpoint. With this list of regular + expressions, only minions that match will be queried. This is + assumed to be a network device that exists in nsot. + +Here's an example config with all options: + +.. code-block:: yaml + + ext_pillar: + - nsot: + api_url: http://nsot_url.com/api/ + email: 'user@site.com' + secret_key: abc234 + fqdn_separator: '-' + all_devices_regex: + - 'server*' + - '^cent*' + minion_regex: + - 'rtr*' + - 'sw*' + - '^router*' + +''' + +from __future__ import absolute_import, print_function, unicode_literals +import logging +import re +try: + import urlparse +except ImportError: + from urllib import parse as urlparse + +# Import Salt libs +import salt.utils.http + +log = logging.getLogger(__name__) + + +def _get_token(url, email, secret_key): + ''' + retrieve the auth_token from nsot + + :param url: str + :param email: str + :param secret_key: str + :return: str + ''' + url = urlparse.urljoin(url, 'authenticate') + data_dict = {"email": email, "secret_key": secret_key} + query = salt.utils.http.query(url, data=data_dict, method='POST', + decode=True) + error = query.get('error') + if error: + log.error('Cannot obtain NSoT authentication token due to: %s.', error) + log.debug('Please verify NSoT URL %s is reachable and email %s is valid', url, email) + return False + else: + log.debug('successfully obtained token from nsot!') + return query['dict'].get('auth_token') + + +def _check_regex(minion_id, regex): + ''' + check whether or not this minion should have this external pillar returned + + :param minion_id: str + :param minion_regex: list + :return: bool + ''' + get_pillar = False + for pattern in regex: + log.debug('nsot external pillar comparing %s with %s', minion_id, regex) + match = re.search(pattern, minion_id) + if match and match.string == minion_id: + log.debug('nsot external pillar found a match!') + get_pillar = True + break + log.debug('nsot external pillar unable to find a match!') + return get_pillar + + +def _query_nsot(url, headers, device=None): + ''' + if a device is given, query nsot for that specific device, otherwise return + all devices + + :param url: str + :param headers: dict + :param device: None or str + :return: + ''' + url = urlparse.urljoin(url, 'devices') + ret = {} + if not device: + query = salt.utils.http.query(url, header_dict=headers, decode=True) + else: + url = urlparse.urljoin(url, device) + query = salt.utils.http.query(url, header_dict=headers, + decode=True) + error = query.get('error') + if error: + log.error('can\'t get device(s) from nsot! reason: %s', error) + else: + ret = query['dict'] + + return ret + + +def _proxy_info(minion_id, api_url, email, secret_key, fqdn_separator): + ''' + retrieve a dict of a device that exists in nsot + + :param minion_id: str + :param api_url: str + :param email: str + :param secret_key: str + :param fqdn_separator: str + :return: dict + ''' + device_info = {} + if fqdn_separator: + minion_id = minion_id.replace('.', fqdn_separator) + token = _get_token(api_url, email, secret_key) + if token: + headers = {'Authorization': 'AuthToken {}:{}'.format(email, token)} + device_info = _query_nsot(api_url, headers, device=minion_id) + + return device_info + + +def _all_nsot_devices(api_url, email, secret_key): + ''' + retrieve a list of all devices that exist in nsot + + :param api_url: str + :param email: str + :param secret_key: str + :return: dict + ''' + token = _get_token(api_url, email, secret_key) + all_devices = {} + if token: + headers = {'Authorization': 'AuthToken {}:{}'.format(email, token)} + all_devices = _query_nsot(api_url, headers) + + return all_devices + + +def ext_pillar(minion_id, + pillar, + api_url, + email, + secret_key, + fqdn_separator=None, + all_devices_regex=None, + minion_regex=None): + ''' + Query NSoT API for network devices + ''' + ret = {} + if minion_id == '*': + log.info('There\'s no data to collect from NSoT for the Master') + return ret + + if minion_regex: + get_ext_pillar = _check_regex(minion_id, minion_regex) + if get_ext_pillar: + ret['nsot'] = _proxy_info(minion_id, + api_url, + email, + secret_key, + fqdn_separator) + + if all_devices_regex: + get_ext_pillar = _check_regex(minion_id, all_devices_regex) + if get_ext_pillar: + if not ret.get('nsot'): + ret['nsot'] = {} + ret['nsot']['devices'] = _all_nsot_devices(api_url, + email, + secret_key) + + return ret diff --git a/salt/pillar/rethinkdb_pillar.py b/salt/pillar/rethinkdb_pillar.py index 85d35af4ceb2..1a31a1fa6617 100644 --- a/salt/pillar/rethinkdb_pillar.py +++ b/salt/pillar/rethinkdb_pillar.py @@ -85,6 +85,7 @@ def ext_pillar(minion_id, Collect minion external pillars from a RethinkDB database Arguments: + * `table`: The RethinkDB table containing external pillar information. Defaults to ``'pillar'`` * `id_field`: Field in document containing the minion id. diff --git a/salt/proxy/esxcluster.py b/salt/proxy/esxcluster.py index 19a8bc4cf594..3c159db319a1 100644 --- a/salt/proxy/esxcluster.py +++ b/salt/proxy/esxcluster.py @@ -67,7 +67,7 @@ should be managed. Required. mechanism -^^^^^^^^ +^^^^^^^^^ The mechanism used to connect to the vCenter server. Supported values are ``userpass`` and ``sspi``. Required. @@ -91,7 +91,7 @@ User domain. Required if mechanism is ``sspi``. principal -^^^^^^^^ +^^^^^^^^^ Kerberos principal. Rquired if mechanism is ``sspi``. protocol diff --git a/salt/proxy/esxdatacenter.py b/salt/proxy/esxdatacenter.py index b360ce60f5cc..3933110c6c28 100644 --- a/salt/proxy/esxdatacenter.py +++ b/salt/proxy/esxdatacenter.py @@ -61,7 +61,7 @@ should be managed. Required. mechanism -^^^^^^^^ +^^^^^^^^^ The mechanism used to connect to the vCenter server. Supported values are ``userpass`` and ``sspi``. Required. @@ -85,7 +85,7 @@ User domain. Required if mechanism is ``sspi``. principal -^^^^^^^^ +^^^^^^^^^ Kerberos principal. Rquired if mechanism is ``sspi``. protocol diff --git a/salt/proxy/esxvm.py b/salt/proxy/esxvm.py index cbc8ca5f6b6a..d7cbb655035c 100644 --- a/salt/proxy/esxvm.py +++ b/salt/proxy/esxvm.py @@ -85,7 +85,7 @@ User realm domain. Required if mechanism is ``sspi``. principal -^^^^^^^^ +^^^^^^^^^ Kerberos principal. Rquired if mechanism is ``sspi``. protocol diff --git a/salt/proxy/vcenter.py b/salt/proxy/vcenter.py index d09d9416efef..45d351bbe86e 100644 --- a/salt/proxy/vcenter.py +++ b/salt/proxy/vcenter.py @@ -2,8 +2,8 @@ ''' Proxy Minion interface module for managing VMWare vCenters. -:codeauthor: :email:`Rod McKenzie (roderick.mckenzie@morganstanley.com)` -:codeauthor: :email:`Alexandru Bleotu (alexandru.bleotu@morganstanley.com)` +:codeauthor: `Rod McKenzie (roderick.mckenzie@morganstanley.com)` +:codeauthor: `Alexandru Bleotu (alexandru.bleotu@morganstanley.com)` Dependencies ============ @@ -67,7 +67,7 @@ principal: proxytype -^^^^^^^^^ +--------- The ``proxytype`` key and value pair is critical, as it tells Salt which interface to load from the ``proxy`` directory in Salt's install hierarchy, or from ``/srv/salt/_proxy`` on the Salt Master (if you have created your @@ -75,47 +75,47 @@ ``vcenter``. vcenter -^^^^^^^ +------- The location of the VMware vCenter server (host of ip). Required username -^^^^^^^^ +-------- The username used to login to the vcenter, such as ``root``. Required only for userpass. mechanism -^^^^^^^^ +--------- The mechanism used to connect to the vCenter server. Supported values are ``userpass`` and ``sspi``. Required. passwords -^^^^^^^^^ +--------- A list of passwords to be used to try and login to the vCenter server. At least one password in this list is required if mechanism is ``userpass`` The proxy integration will try the passwords listed in order. domain -^^^^^^ +------ User domain. Required if mechanism is ``sspi`` principal -^^^^^^^^ +--------- Kerberos principal. Rquired if mechanism is ``sspi`` protocol -^^^^^^^^ +-------- If the vCenter is not using the default protocol, set this value to an alternate protocol. Default is ``https``. port -^^^^ +---- If the ESXi host is not using the default port, set this value to an alternate port. Default is ``443``. Salt Proxy ----------- +========== After your pillar is in place, you can test the proxy. The proxy can run on any machine that has network connectivity to your Salt Master and to the @@ -173,13 +173,13 @@ :mod:`Salt.modules.vsphere ` is a standard Salt execution module. - If you pull up the docs for it you'll see -that almost every function in the module takes credentials and a targets either -a vcenter or a host. When credentials and a host aren't passed, Salt runs commands -through ``pyVmomi`` against the local machine. If you wanted, you could run -functions from this module on any host where an appropriate version of -``pyVmomi`` is installed, and that host would reach out over the network -and communicate with the ESXi host. +If you pull up the docs for it you'll see that almost every function in the +module takes credentials and a targets either a vcenter or a host. When +credentials and a host aren't passed, Salt runs commands through ``pyVmomi`` +against the local machine. If you wanted, you could run functions from this +module on any host where an appropriate version of ``pyVmomi`` is installed, +and that host would reach out over the network and communicate with the ESXi +host. ''' # Import Python Libs diff --git a/salt/renderers/aws_kms.py b/salt/renderers/aws_kms.py index 19d0e9bc323d..d4ad248bf462 100644 --- a/salt/renderers/aws_kms.py +++ b/salt/renderers/aws_kms.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- r''' -Renderer that will decrypt ciphers encrypted using `AWS KMS Envelope Encryption`_. - .. _`AWS KMS Envelope Encryption`: https://docs.aws.amazon.com/kms/latest/developerguide/workflow.html +Renderer that will decrypt ciphers encrypted using `AWS KMS Envelope Encryption`_. + Any key in the data to be rendered can be a urlsafe_b64encoded string, and this renderer will attempt to decrypt it before passing it off to Salt. This allows you to safely store secrets in source control, in such a way that only your Salt master can decrypt them and diff --git a/salt/renderers/nacl.py b/salt/renderers/nacl.py index 5c05383666a8..f85ca84314ed 100644 --- a/salt/renderers/nacl.py +++ b/salt/renderers/nacl.py @@ -26,7 +26,7 @@ Using encrypted pillar ---------------------- +---------------------- To encrypt secrets, copy the public key to your local machine and run: diff --git a/salt/returners/appoptics_return.py b/salt/returners/appoptics_return.py new file mode 100644 index 000000000000..f69afa8bb541 --- /dev/null +++ b/salt/returners/appoptics_return.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +'''Salt returner to return highstate stats to AppOptics Metrics + +To enable this returner the minion will need the AppOptics Metrics +client importable on the Python path and the following +values configured in the minion or master config. + +The AppOptics python client can be found at: + +https://github.com/appoptics/python-appoptics-metrics + +.. code-block:: yaml + + appoptics.api_token: abc12345def + +An example configuration that returns the total number of successes +and failures for your salt highstate runs (the default) would look +like this: + +.. code-block:: yaml + + return: appoptics + appoptics.api_token: + + +The returner publishes the following metrics to AppOptics: + +- saltstack.failed +- saltstack.passed +- saltstack.retcode +- saltstack.runtime +- saltstack.total + + +You can add a tags section to specify which tags should be attached to +all metrics created by the returner. + +.. code-block:: yaml + + appoptics.tags: + host_hostname_alias: + tier: + cluster: + + +If no tags are explicitly configured, then the tag key ``host_hostname_alias`` +will be set, with the minion's ``id`` grain being the value. + +In addition to the requested tags, for a highstate run each of these +will be tagged with the ``key:value`` of ``state_type: highstate``. + +In order to return metrics for ``state.sls`` runs (distinct from highstates), you can +specify a list of state names to the key ``appoptics.sls_states`` like so: + +.. code-block:: yaml + + appoptics.sls_states: + - role_salt_master.netapi + - role_redis.config + - role_smarty.dummy + + +This will report success and failure counts on runs of the +``role_salt_master.netapi``, ``role_redis.config``, and +``role_smarty.dummy`` states in addition to highstates. + +This will report the same metrics as above, but for these runs the +metrics will be tagged with ``state_type: sls`` and ``state_name`` set to +the name of the state that was invoked, e.g. ``role_salt_master.netapi``. + +''' + +# Import python libs +from __future__ import absolute_import, print_function, unicode_literals +import logging + +# Import Salt libs +import salt.utils.jid +import salt.returners + +# Import third party libs +try: + import appoptics_metrics + HAS_APPOPTICS = True +except ImportError: + HAS_APPOPTICS = False + +# Define the module's Virtual Name +__virtualname__ = 'appoptics' + +log = logging.getLogger(__name__) + + +def __virtual__(): + if not HAS_APPOPTICS: + return False, 'Could not import appoptics_metrics module; ' \ + 'appoptics-metrics python client is not installed.' + return __virtualname__ + + +def _get_options(ret=None): + ''' + Get the appoptics options from salt. + ''' + attrs = { + 'api_token': 'api_token', + 'api_url': 'api_url', + 'tags': 'tags', + 'sls_states': 'sls_states' + } + + _options = salt.returners.get_returner_options( + __virtualname__, + ret, + attrs, + __salt__=__salt__, + __opts__=__opts__) + + _options['api_url'] = _options.get('api_url', 'api.appoptics.com') + _options['sls_states'] = _options.get('sls_states', []) + _options['tags'] = _options.get('tags', { + 'host_hostname_alias': __salt__['grains.get']('id') + }) + + log.debug('Retrieved appoptics options: %s', _options) + return _options + + +def _get_appoptics(options): + ''' + Return an appoptics connection object. + ''' + conn = appoptics_metrics.connect( + options.get('api_token'), + sanitizer=appoptics_metrics.sanitize_metric_name, + hostname=options.get('api_url')) + log.info("Connected to appoptics.") + return conn + + +def _calculate_runtimes(states): + results = { + 'runtime': 0.00, + 'num_failed_states': 0, + 'num_passed_states': 0 + } + + for state, resultset in states.items(): + if isinstance(resultset, dict) and 'duration' in resultset: + # Count the pass vs failures + if resultset['result']: + results['num_passed_states'] += 1 + else: + results['num_failed_states'] += 1 + + # Count durations + results['runtime'] += resultset['duration'] + + log.debug('Parsed state metrics: %s', results) + return results + + +def _state_metrics(ret, options, tags): + # Calculate the runtimes and number of failed states. + stats = _calculate_runtimes(ret['return']) + log.debug('Batching Metric retcode with %s', ret['retcode']) + appoptics_conn = _get_appoptics(options) + q = appoptics_conn.new_queue(tags=tags) + + q.add('saltstack.retcode', ret['retcode']) + log.debug('Batching Metric num_failed_jobs with %s', stats['num_failed_states']) + q.add('saltstack.failed', stats['num_failed_states']) + + log.debug('Batching Metric num_passed_states with %s', + stats['num_passed_states']) + q.add('saltstack.passed', stats['num_passed_states']) + + log.debug('Batching Metric runtime with %s', stats['runtime']) + q.add('saltstack.runtime', stats['runtime']) + + log.debug('Batching with Metric total states %s', + (stats['num_failed_states'] + stats['num_passed_states'])) + q.add('saltstack.highstate.total_states', + (stats['num_failed_states'] + stats['num_passed_states'])) + log.info('Sending metrics to appoptics.') + q.submit() + + +def returner(ret): + ''' + Parse the return data and return metrics to AppOptics. + + For each state that's provided in the configuration, return tagged metrics for + the result of that state if it's present. + ''' + + options = _get_options(ret) + states_to_report = ['state.highstate'] + if options.get('sls_states'): + states_to_report.append('state.sls') + if ret['fun'] in states_to_report: + tags = options.get('tags', {}).copy() + tags['state_type'] = ret['fun'] + log.info("Tags for this run are %s", tags) + matched_states = set(ret['fun_args']).intersection( + set(options.get('sls_states', []))) + # What can I do if a run has multiple states that match? + # In the mean time, find one matching state name and use it. + if matched_states: + tags['state_name'] = sorted(matched_states)[0] + log.debug('Found returned data from %s.', tags['state_name']) + _state_metrics(ret, options, tags) diff --git a/salt/states/azurearm_dns.py b/salt/states/azurearm_dns.py index e62d5f2038c3..cbbe2c682bde 100644 --- a/salt/states/azurearm_dns.py +++ b/salt/states/azurearm_dns.py @@ -18,32 +18,39 @@ * `azure-mgmt-web `_ >= 0.32.0 * `azure-storage `_ >= 0.34.3 * `msrestazure `_ >= 0.4.21 + :platform: linux -:configuration: This module requires Azure Resource Manager credentials to be passed as a dictionary of -keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication -parameters are sensitive, it's recommended to pass them to the states via pillar. +:configuration: + This module requires Azure Resource Manager credentials to be passed as a dictionary of + keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication + parameters are sensitive, it's recommended to pass them to the states via pillar. - Required provider parameters: +Required provider parameters: if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` + + * ``subscription_id`` + * ``username`` + * ``password`` if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - Optional provider parameters: + * ``subscription_id`` + * ``tenant`` + * ``client_id`` + * ``secret`` + +Optional provider parameters: **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` + + Possible values: + + * ``AZURE_PUBLIC_CLOUD`` (default) + * ``AZURE_CHINA_CLOUD`` + * ``AZURE_US_GOV_CLOUD`` + * ``AZURE_GERMAN_CLOUD`` Example Pillar for Azure Resource Manager authentication: @@ -63,7 +70,7 @@ Example states using Azure Resource Manager authentication: - .. code-block:: yaml + .. code-block:: none {% set profile = salt['pillar.get']('azurearm:mysubscription') %} Ensure DNS zone exists: @@ -392,7 +399,7 @@ def record_set_present(name, zone_name, resource_group, record_type, if_match=No will be ignored. :param etag: - The etag of the record set. `Etags `_ are + The etag of the record set. `Etags `__ are used to handle concurrent changes to the same resource safely. :param metadata: @@ -403,52 +410,52 @@ def record_set_present(name, zone_name, resource_group, record_type, if_match=No :param arecords: The list of A records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param aaaa_records: The list of AAAA records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param mx_records: The list of MX records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param ns_records: The list of NS records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param ptr_records: The list of PTR records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param srv_records: The list of SRV records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param txt_records: The list of TXT records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param cname_record: The CNAME record in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a dictionary representing the record object. :param soa_record: The SOA record in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a dictionary representing the record object. :param caa_records: The list of CAA records in the record set. View the - `Azure SDK documentation `_ + `Azure SDK documentation `__ to create a list of dictionaries representing the record objects. :param connection_auth: diff --git a/salt/states/boto3_sns.py b/salt/states/boto3_sns.py index b70785943d82..ffd58d343f91 100644 --- a/salt/states/boto3_sns.py +++ b/salt/states/boto3_sns.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ''' Manage SNS Topics - +================= Create and destroy SNS topics. Be aware that this interacts with Amazon's services, and so may incur charges. @@ -40,13 +40,21 @@ - keyid: GKTADJGHEIQSXMKKRBJ08H - key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs - # Using a profile from pillars +Using a profile from pillars +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: yaml + mytopic: boto3_sns.topic_present: - region: us-east-1 - profile: mysnsprofile - # Passing in a profile +Passing in a profile +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: yaml + mytopic: boto3_sns.topic_present: - region: us-east-1 @@ -97,6 +105,7 @@ def topic_present(name, subscriptions=None, attributes=None, attributes Dictionary of attributes to set on the SNS topic Valid attribute keys are: + - Policy: the JSON serialization of the topic's access control policy - DisplayName: the human-readable name used in the "From" field for notifications to email and email-json endpoints diff --git a/salt/states/boto_s3.py b/salt/states/boto_s3.py index 49e77510cf6d..6081c16c01ea 100644 --- a/salt/states/boto_s3.py +++ b/salt/states/boto_s3.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ''' Manage S3 Resources -================= +=================== .. versionadded:: 2018.3.0 diff --git a/salt/states/cryptdev.py b/salt/states/cryptdev.py index 92dc08ac2485..fb602e2da736 100644 --- a/salt/states/cryptdev.py +++ b/salt/states/cryptdev.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ''' Opening of Encrypted Devices -======================= +============================ Ensure that an encrypted device is mapped with the `mapped` function: diff --git a/salt/states/dvs.py b/salt/states/dvs.py index 1ff39cde00eb..4bba15b83465 100644 --- a/salt/states/dvs.py +++ b/salt/states/dvs.py @@ -3,7 +3,7 @@ Manage VMware distributed virtual switches (DVSs) and their distributed virtual portgroups (DVportgroups). -:codeauthor: :email:`Alexandru Bleotu ` +:codeauthor: `Alexandru Bleotu ` Examples ======== @@ -121,6 +121,7 @@ --------- .. code-block:: python + 'security_policy': { 'allow_promiscuous': true, 'mac_changes': false, @@ -166,7 +167,6 @@ Dependencies ============ - - pyVmomi Python Module diff --git a/salt/states/esxdatacenter.py b/salt/states/esxdatacenter.py index ae83b4d37174..0a9b6adb8f13 100644 --- a/salt/states/esxdatacenter.py +++ b/salt/states/esxdatacenter.py @@ -2,7 +2,7 @@ ''' Salt states to create and manage VMware vSphere datacenters (datacenters). -:codeauthor: :email:`Alexandru Bleotu ` +:codeauthor: `Alexandru Bleotu ` Dependencies ============ @@ -32,6 +32,7 @@ Proxy minion configuration (connects passthrough to the vCenter): .. code-block:: yaml + proxy: proxytype: esxdatacenter datacenter: target_dc diff --git a/salt/states/glassfish.py b/salt/states/glassfish.py index 813f1e84a498..28a67cf99e5e 100644 --- a/salt/states/glassfish.py +++ b/salt/states/glassfish.py @@ -7,6 +7,7 @@ You can setup connection parameters like this .. code-block:: yaml + - server: - ssl: true - url: localhost diff --git a/salt/states/lxd_container.py b/salt/states/lxd_container.py index ea1a5f6425ee..394807a81f99 100644 --- a/salt/states/lxd_container.py +++ b/salt/states/lxd_container.py @@ -6,7 +6,7 @@ .. note: - - `pylxd`_ version 2 is required to let this work, + - :ref:`pylxd` version 2 is required to let this work, currently only available via pip. To install on Ubuntu: @@ -20,7 +20,7 @@ - for the config_get() and config_get() methods you need to have lxd-client installed. -.. _: https://github.com/lxc/pylxd/blob/master/doc/source/installation.rst +.. _pylxd: https://github.com/lxc/pylxd/blob/master/doc/source/installation.rst :maintainer: René Jochum :maturity: new @@ -81,27 +81,49 @@ def present(name, source : None Can be either a string containing an image alias: + + .. code-block:: none + "xenial/amd64" + or an dict with type "image" with alias: + + .. code-block:: python + {"type": "image", "alias": "xenial/amd64"} + or image with "fingerprint": + + .. code-block:: python + {"type": "image", "fingerprint": "SHA-256"} + or image with "properties": + + .. code-block:: python + {"type": "image", "properties": { "os": "ubuntu", "release": "14.04", "architecture": "x86_64" }} + or none: + + .. code-block:: python + {"type": "none"} + or copy: + + .. code-block:: python + {"type": "copy", "source": "my-old-container"} - profiles : ['default'] List of profiles to apply on this container @@ -109,6 +131,9 @@ def present(name, A config dict or None (None = unset). Can also be a list: + + .. code-block:: python + [{'key': 'boot.autostart', 'value': 1}, {'key': 'security.privileged', 'value': '1'}] @@ -117,15 +142,16 @@ def present(name, architecture : 'x86_64' Can be one of the following: - * unknown - * i686 - * x86_64 - * armv7l - * aarch64 - * ppc - * ppc64 - * ppc64le - * s390x + + * unknown + * i686 + * x86_64 + * armv7l + * aarch64 + * ppc + * ppc64 + * ppc64le + * s390x ephemeral : False Destroy this container after stop? diff --git a/salt/states/lxd_image.py b/salt/states/lxd_image.py index bc3ebf719f9f..dda49b4c9365 100644 --- a/salt/states/lxd_image.py +++ b/salt/states/lxd_image.py @@ -4,9 +4,11 @@ .. versionadded:: 2019.2.0 +.. link: https://github.com/lxc/pylxd/blob/master/doc/source/installation.rst + .. note: - - `pylxd`_ version 2 is required to let this work, + - :role:`pylxd ` version 2 is required to let this work, currently only available via pip. To install on Ubuntu: @@ -20,7 +22,6 @@ - for the config_get() and config_get() methods you need to have lxd-client installed. -.. _: https://github.com/lxc/pylxd/blob/master/doc/source/installation.rst :maintainer: René Jochum :maturity: new diff --git a/salt/states/nova.py b/salt/states/nova.py new file mode 100644 index 000000000000..2e498c7eb847 --- /dev/null +++ b/salt/states/nova.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +''' +.. versionadded:: 2017.7 + +Module for handling OpenStack Nova calls + +:codeauthor: Jakub Sliva +''' +from __future__ import absolute_import +from __future__ import unicode_literals +import logging + +from salt.ext import six + +log = logging.getLogger(__name__) + + +def __virtual__(): + ''' + Only make these states available if nova module is available + ''' + if 'nova.flavor_list' in __salt__: + return True + return False, 'nova execution module not imported properly.' + + +def flavor_present(name, params=None, **kwargs): + ''' + Creates Nova flavor if it does not exist + + :param name: Flavor name + :param params: Definition of the Flavor (see Compute API documentation) + + .. code-block:: yaml + + nova-flavor-present: + nova.flavor_present: + - name: myflavor + - params: + ram: 2 + vcpus: 1 + disk: 10 + is_public: False + ''' + dry_run = __opts__['test'] + ret = {'name': name, 'result': False, 'comment': '', 'changes': {}} + + if params is None: + params = {} + + try: + kwargs.update({'filter': {'is_public': None}}) + object_list = __salt__['nova.flavor_list'](**kwargs) + object_exists = True if object_list[name]['name'] == name else False + except KeyError: + object_exists = False + + if object_exists: + ret['result'] = True + ret['comment'] = 'Flavor "{0}" already exists.'.format(name) + else: + if dry_run: + ret['result'] = None + ret['comment'] = 'Flavor "{0}" would be created.'.format(name) + ret['changes'] = {name: {'old': 'Flavor "{0}" does not exist.'.format(name), + 'new': params}} + else: + combined = kwargs.copy() + combined.update(params) + flavor_create = __salt__['nova.flavor_create'](name, **combined) + + if flavor_create: + ret['result'] = True + ret['comment'] = 'Flavor "{0}" created.'.format(name) + ret['changes'] = {name: {'old': 'Flavor "{0}" does not exist.'.format(name), + 'new': flavor_create}} + + return ret + + +def flavor_access_list(name, projects, **kwargs): + ''' + Grants access of the flavor to a project. Flavor must be private. + + :param name: non-public flavor name + :param projects: list of projects which should have the access to the flavor + + .. code-block:: yaml + + nova-flavor-share: + nova.flavor_project_access: + - name: myflavor + - project: + - project1 + - project2 + + To remove all project from access list: + + .. code-block:: yaml + + - project: [] + ''' + dry_run = __opts__['test'] + ret = {'name': name, 'result': False, 'comment': '', 'changes': {}} + kwargs.update({'filter': {'is_public': False}}) + try: + flavor_list = __salt__['nova.flavor_list'](**kwargs) + flavor_id = flavor_list[name]['id'] + except KeyError: + raise + + project_list = __salt__['keystone.project_list'](**kwargs) + access_list = __salt__['nova.flavor_access_list'](flavor_id, **kwargs) + existing_list = [six.text_type(pname) for pname in project_list + if project_list[pname]['id'] in access_list[flavor_id]] + defined_list = [six.text_type(project) for project in projects] + add_list = set(defined_list) - set(existing_list) + remove_list = set(existing_list) - set(defined_list) + + if not add_list and not remove_list: + ret['result'] = True + ret['comment'] = 'Flavor "{0}" access list corresponds to defined one.'.format(name) + else: + if dry_run: + ret['result'] = None + ret['comment'] = 'Flavor "{0}" access list would be corrected.'.format(name) + ret['changes'] = {name: {'new': defined_list, 'old': existing_list}} + else: + added = [] + removed = [] + if add_list: + for project in add_list: + added.append(__salt__['nova.flavor_access_add'](flavor_id, project_list[project]['id'], **kwargs)) + if remove_list: + for project in remove_list: + removed.append(__salt__['nova.flavor_access_remove'](flavor_id, + project_list[project]['id'], **kwargs)) + if any(add_list) or any(remove_list): + ret['result'] = True + ret['comment'] = 'Flavor "{0}" access list corrected.'.format(name) + ret['changes'] = {name: {'new': defined_list, 'old': existing_list}} + + return ret + + +def flavor_absent(name, **kwargs): + ''' + Makes flavor to be absent + + :param name: flavor name + + .. code-block:: yaml + + nova-flavor-absent: + nova.flavor_absent: + - name: flavor_name + ''' + dry_run = __opts__['test'] + ret = {'name': name, 'result': False, 'comment': '', 'changes': {}} + + try: + object_list = __salt__['nova.flavor_list'](**kwargs) + object_id = object_list[name]['id'] + except KeyError: + object_id = False + + if not object_id: + ret['result'] = True + ret['comment'] = 'Flavor "{0}" does not exist.'.format(name) + else: + if dry_run: + ret['result'] = None + ret['comment'] = 'Flavor "{0}", id: {1} would be deleted.'.format(name, object_id) + ret['changes'] = {name: {'old': 'Flavor "{0}", id: {1} exists.'.format(name, object_id), + 'new': ret['comment']}} + else: + flavor_delete = __salt__['nova.flavor_delete'](object_id, **kwargs) + + if flavor_delete: + ret['result'] = True + ret['comment'] = 'Flavor "{0}", id: {1} deleted.'.format(name, object_id) + ret['changes'] = {name: {'old': 'Flavor "{0}", id: {1} existed.'.format(name, object_id), + 'new': ret['comment']}} + + return ret diff --git a/salt/states/pbm.py b/salt/states/pbm.py index 836c95b807da..45d10b6dd930 100644 --- a/salt/states/pbm.py +++ b/salt/states/pbm.py @@ -11,67 +11,65 @@ .. code-block:: python -{ - "name": "salt_storage_policy" - "description": "Managed by Salt. Random capability values.", - "resource_type": "STORAGE", - "subprofiles": [ - { - "capabilities": [ - { - "setting": { - "type": "scalar", - "value": 2 + { + "name": "salt_storage_policy" + "description": "Managed by Salt. Random capability values.", + "resource_type": "STORAGE", + "subprofiles": [ + { + "capabilities": [ + { + "setting": { + "type": "scalar", + "value": 2 + }, + "namespace": "VSAN", + "id": "hostFailuresToTolerate" }, - "namespace": "VSAN", - "id": "hostFailuresToTolerate" - }, - { - "setting": { - "type": "scalar", - "value": 2 + { + "setting": { + "type": "scalar", + "value": 2 + }, + "namespace": "VSAN", + "id": "stripeWidth" }, - "namespace": "VSAN", - "id": "stripeWidth" - }, - { - "setting": { - "type": "scalar", - "value": true + { + "setting": { + "type": "scalar", + "value": true + }, + "namespace": "VSAN", + "id": "forceProvisioning" }, - "namespace": "VSAN", - "id": "forceProvisioning" - }, - { - "setting": { - "type": "scalar", - "value": 50 + { + "setting": { + "type": "scalar", + "value": 50 + }, + "namespace": "VSAN", + "id": "proportionalCapacity" }, - "namespace": "VSAN", - "id": "proportionalCapacity" - }, - { - "setting": { - "type": "scalar", - "value": 0 - }, - "namespace": "VSAN", - "id": "cacheReservation" - } - ], - "name": "Rule-Set 1: VSAN", - "force_provision": null - } - ], -} + { + "setting": { + "type": "scalar", + "value": 0 + }, + "namespace": "VSAN", + "id": "cacheReservation" + } + ], + "name": "Rule-Set 1: VSAN", + "force_provision": null + } + ], + } Dependencies ============ - - pyVmomi Python Module - pyVmomi ------- @@ -88,9 +86,9 @@ Python 2.7.9, or newer must be present. This is due to an upstream dependency in pyVmomi 6.0 that is not supported in Python versions 2.7 to 2.7.8. If the version of Python is not in the supported range, you will need to install an - earlier version of pyVmomi. See `Issue #29537`_ for more information. - -.. _Issue #29537: https://github.com/saltstack/salt/issues/29537 + earlier version of pyVmomi. See + `Issue #29537 ` for more + information. ''' # Import Python Libs diff --git a/salt/states/postgres_default_privileges.py b/salt/states/postgres_default_privileges.py new file mode 100644 index 000000000000..e3b816a1ad45 --- /dev/null +++ b/salt/states/postgres_default_privileges.py @@ -0,0 +1,315 @@ +# -*- coding: utf-8 -*- +''' +Management of PostgreSQL Default Privileges +=========================================== + +The postgres_default_privileges module is used to manage Postgres privileges by default. +Privileges can be set as either absent or present. They take any and all previously existing +and future objects into account. + +Privileges can be set on the following database object types: + +* schema +* table +* sequence +* group + +Setting the grant option is supported as well. + +.. versionadded:: 2016.3.0 + +.. code-block:: yaml + + baruwa: + postgres_privileges.present: + - object_name: awl + - object_type: table + - privileges: + - SELECT + - INSERT + - DELETE + - grant_option: False + - prepend: public + - maintenance_db: testdb + +.. code-block:: yaml + + andrew: + postgres_privileges.present: + - object_name: admins + - object_type: group + - grant_option: False + - maintenance_db: testdb + +.. code-block:: yaml + + baruwa: + postgres_privileges.absent: + - object_name: awl + - object_type: table + - privileges: + - SELECT + - INSERT + - DELETE + - prepend: public + - maintenance_db: testdb + +.. code-block:: yaml + + andrew: + postgres_privileges.absent: + - object_name: admins + - object_type: group + - maintenance_db: testdb +''' +from __future__ import absolute_import, unicode_literals, print_function + + +def __virtual__(): + ''' + Only load if the postgres module is present + ''' + if 'postgres.default_privileges_grant' not in __salt__: + return (False, 'Unable to load postgres module. Make sure `postgres.bins_dir` is set.') + return True + + +def present(name, + object_name, + object_type, + defprivileges=None, + grant_option=None, + prepend='public', + maintenance_db=None, + user=None, + db_password=None, + db_host=None, + db_port=None, + db_user=None): + ''' + Grant the requested privilege(s) on the specified object to a role + + name + Name of the role to which privileges should be granted + + object_name + Name of the object on which the grant is to be performed. + 'ALL' may be used for objects of type 'table' or 'sequence'. + + object_type + The object type, which can be one of the following: + + - table + - sequence + - schema + - group + - function + + View permissions should specify `object_type: table`. + + privileges + List of privileges to grant, from the list below: + + - INSERT + - CREATE + - TRUNCATE + - CONNECT + - TRIGGER + - SELECT + - USAGE + - TEMPORARY + - UPDATE + - EXECUTE + - REFERENCES + - DELETE + - ALL + + :note: privileges should not be set when granting group membership + + grant_option + If grant_option is set to True, the recipient of the privilege can + in turn grant it to others + + prepend + Table and Sequence object types live under a schema so this should be + provided if the object is not under the default `public` schema + + maintenance_db + The name of the database in which the language is to be installed + + user + System user all operations should be performed on behalf of + + db_user + database username if different from config or default + + db_password + user password if any password for a specified user + + db_host + Database host if different from config or default + + db_port + Database port if different from config or default + ''' + ret = { + 'name': name, + 'changes': {}, + 'result': True, + 'comment': 'The requested default privilege(s) are already set' + } + + defprivileges = ','.join(defprivileges) if defprivileges else None + + kwargs = { + 'defprivileges': defprivileges, + 'grant_option': grant_option, + 'prepend': prepend, + 'maintenance_db': maintenance_db, + 'runas': user, + 'host': db_host, + 'user': db_user, + 'port': db_port, + 'password': db_password, + } + + if not __salt__['postgres.has_default_privileges']( + name, object_name, object_type, **kwargs): + _defprivs = object_name if object_type == 'group' else defprivileges + + if __opts__['test']: + ret['result'] = None + ret['comment'] = ('The default privilege(s): {0} are' + ' set to be granted to {1}').format(_defprivs, name) + return ret + + if __salt__['postgres.default_privileges_grant']( + name, object_name, object_type, **kwargs): + ret['comment'] = ('The default privilege(s): {0} have ' + 'been granted to {1}').format(_defprivs, name) + ret['changes'][name] = 'Present' + else: + ret['comment'] = ('Failed to grant default privilege(s):' + ' {0} to {1}').format(_defprivs, name) + ret['result'] = False + + return ret + + +def absent(name, + object_name, + object_type, + defprivileges=None, + prepend='public', + maintenance_db=None, + user=None, + db_password=None, + db_host=None, + db_port=None, + db_user=None): + ''' + Revoke the requested default privilege(s) on the specificed object(s) + + name + Name of the role whose default privileges should be revoked + + object_name + Name of the object on which the revoke is to be performed + + object_type + The object type, which can be one of the following: + + - table + - sequence + - schema + - tablespace -- to delete + - language -- to delete + - database - to delete + - group + - function + + View permissions should specify `object_type: table`. + + privileges + Comma separated list of default privileges to revoke, from the list below: + + - INSERT + - CREATE + - TRUNCATE + - CONNECT + - TRIGGER + - SELECT + - USAGE + - TEMPORARY + - UPDATE + - EXECUTE + - REFERENCES + - DELETE + - ALL + + :note: default privileges should not be set when revoking group membership + + prepend + Table and Sequence object types live under a schema so this should be + provided if the object is not under the default `public` schema + + maintenance_db + The name of the database in which the language is to be installed + + user + System user all operations should be performed on behalf of + + db_user + database username if different from config or default + + db_password + user password if any password for a specified user + + db_host + Database host if different from config or default + + db_port + Database port if different from config or default + ''' + ret = { + 'name': name, + 'changes': {}, + 'result': True, + 'comment': ('The requested default privilege(s) are ' + 'not set so cannot be revoked') + } + + defprivileges = ','.join(defprivileges) if defprivileges else None + + kwargs = { + 'defprivileges': defprivileges, + 'prepend': prepend, + 'maintenance_db': maintenance_db, + 'runas': user, + 'host': db_host, + 'user': db_user, + 'port': db_port, + 'password': db_password, + } + + if __salt__['postgres.has_default_privileges']( + name, object_name, object_type, **kwargs): + _defprivs = object_name if object_type == 'group' else defprivileges + + if __opts__['test']: + ret['result'] = None + ret['comment'] = ('The default privilege(s): {0} are' + ' set to be revoked from {1}').format(_defprivs, name) + return ret + + if __salt__['postgres.default_privileges_revoke']( + name, object_name, object_type, **kwargs): + ret['comment'] = ('The default privilege(s): {0} have ' + 'been revoked from {1}').format(_defprivs, name) + ret['changes'][name] = 'Absent' + else: + ret['comment'] = ('Failed to revoke default privilege(s):' + ' {0} from {1}').format(_defprivs, name) + ret['result'] = False + + return ret diff --git a/salt/states/saltsupport.py b/salt/states/saltsupport.py new file mode 100644 index 000000000000..66d28d6d4c42 --- /dev/null +++ b/salt/states/saltsupport.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- +# +# Author: Bo Maryniuk +# +# Copyright 2018 SUSE LLC +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +r''' +:codeauthor: `Bo Maryniuk ` + +Execution of Salt Support from within states +============================================ + +State to collect support data from the systems: + +.. code-block:: yaml + + examine_my_systems: + support.taken: + - profile: default + + support.collected: + - group: somewhere + - move: true + +''' +from __future__ import absolute_import, print_function, unicode_literals +import logging +import os +import tempfile + +# Import salt modules +import salt.fileclient +import salt.utils.decorators.path +import salt.exceptions +import salt.utils.odict + +log = logging.getLogger(__name__) +__virtualname__ = 'support' + + +class SaltSupportState(object): + ''' + Salt-support. + ''' + EXPORTED = ['collected', 'taken'] + + def get_kwargs(self, data): + kwargs = {} + for keyset in data: + kwargs.update(keyset) + + return kwargs + + def __call__(self, state): + ''' + Call support. + + :param args: + :param kwargs: + :return: + ''' + ret = { + 'name': state.pop('name'), + 'changes': {}, + 'result': True, + 'comment': '', + } + + out = {} + functions = ['Functions:'] + try: + for ref_func, ref_kwargs in state.items(): + if ref_func not in self.EXPORTED: + raise salt.exceptions.SaltInvocationError('Function {} is not found'.format(ref_func)) + out[ref_func] = getattr(self, ref_func)(**self.get_kwargs(ref_kwargs)) + functions.append(' - {}'.format(ref_func)) + ret['comment'] = '\n'.join(functions) + except Exception as ex: + ret['comment'] = str(ex) + ret['result'] = False + ret['changes'] = out + + return ret + + def check_destination(self, location, group): + ''' + Check destination for the archives. + :return: + ''' + # Pre-create destination, since rsync will + # put one file named as group + try: + destination = os.path.join(location, group) + if os.path.exists(destination) and not os.path.isdir(destination): + raise salt.exceptions.SaltException('Destination "{}" should be directory!'.format(destination)) + if not os.path.exists(destination): + os.makedirs(destination) + log.debug('Created destination directory for archives: %s', destination) + else: + log.debug('Archives destination directory %s already exists', destination) + except OSError as err: + log.error(err) + + def collected(self, group, filename=None, host=None, location=None, move=True, all=True): + ''' + Sync archives to a central place. + + :param name: + :param group: + :param filename: + :param host: + :param location: + :param move: + :param all: + :return: + ''' + ret = { + 'name': 'support.collected', + 'changes': {}, + 'result': True, + 'comment': '', + } + location = location or tempfile.gettempdir() + self.check_destination(location, group) + ret['changes'] = __salt__['support.sync'](group, name=filename, host=host, + location=location, move=move, all=all) + + return ret + + def taken(self, profile='default', pillar=None, archive=None, output='nested'): + ''' + Takes minion support config data. + + :param profile: + :param pillar: + :param archive: + :param output: + :return: + ''' + ret = { + 'name': 'support.taken', + 'changes': {}, + 'result': True, + } + + result = __salt__['support.run'](profile=profile, pillar=pillar, archive=archive, output=output) + if result.get('archive'): + ret['comment'] = 'Information about this system has been saved to {} file.'.format(result['archive']) + ret['changes']['archive'] = result['archive'] + ret['changes']['messages'] = {} + for key in ['info', 'error', 'warning']: + if result.get('messages', {}).get(key): + ret['changes']['messages'][key] = result['messages'][key] + else: + ret['comment'] = '' + + return ret + + +_support_state = SaltSupportState() + + +def __call__(*args, **kwargs): + ''' + SLS single-ID syntax processing. + + module: + This module reference, equals to sys.modules[__name__] + + state: + Compiled state in preserved order. The function supposed to look + at first level array of functions. + + :param cdata: + :param kwargs: + :return: + ''' + return _support_state(kwargs.get('state', {})) + + +def taken(name, profile='default', pillar=None, archive=None, output='nested'): + return _support_state.taken(profile=profile, pillar=pillar, + archive=archive, output=output) + + +def collected(name, group, filename=None, host=None, location=None, move=True, all=True): + return _support_state.collected(group=group, filename=filename, + host=host, location=location, move=move, all=all) + + +def __virtual__(): + ''' + Salt Support state + ''' + return __virtualname__ diff --git a/salt/states/zabbix_service.py b/salt/states/zabbix_service.py new file mode 100644 index 000000000000..f53a437270b4 --- /dev/null +++ b/salt/states/zabbix_service.py @@ -0,0 +1,227 @@ +# -*- coding: utf-8 -*- +''' +Management of Zabbix services. + + +''' +from __future__ import absolute_import, print_function, unicode_literals + + +def __virtual__(): + ''' + Only make these states available if Zabbix module is available. + ''' + return 'zabbix.service_add' in __salt__ + + +def present(host, service_root, trigger_desc, service_name=None, **kwargs): + ''' + .. versionadded:: Fluorine + + Ensure service exists under service root. + + :param host: Technical name of the host + :param service_root: Path of service (path is split by /) + :param service_name: Name of service + :param trigger_desc: Description of trigger in zabbix + :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) + :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring) + :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring) + + .. note:: + If services on path does not exists they are created. + + .. code-block:: yaml + + create_service_icmp: + zabbix_service.present: + - host: server-1 + - service_root: Server-group/server icmp + - service_name: server-1-icmp + - trigger_desc: is unavailable by ICMP + ''' + if not service_name: + service_name = host + + changes_service_added = {host: {'old': 'Service {0} does not exist under {1}.'.format(service_name, service_root), + 'new': 'Service {0} added under {1}.'.format(service_name, service_root), + } + } + + connection_args = {} + if '_connection_user' in kwargs: + connection_args['_connection_user'] = kwargs['_connection_user'] + if '_connection_password' in kwargs: + connection_args['_connection_password'] = kwargs['_connection_password'] + if '_connection_url' in kwargs: + connection_args['_connection_url'] = kwargs['_connection_url'] + + ret = {'name': host, 'changes': {}, 'result': False, 'comment': ''} + + host_exists = __salt__['zabbix.host_exists'](host, **connection_args) + + if not host_exists: + ret['comment'] = 'Host {0} does not exists.'.format(host) + return ret + + host = __salt__['zabbix.host_get'](name=host, **connection_args)[0] + hostid = host['hostid'] + + trigger = __salt__['zabbix.triggerid_get'](hostid=hostid, trigger_desc=trigger_desc, **kwargs) + + if not trigger: + ret['comment'] = 'Trigger with description: "{0}" does not exists for host {1}.'.format( + trigger_desc, host['name']) + return ret + + trigger_id = trigger['result']['triggerid'] + + root_services = service_root.split('/') + root_id = None + + if __opts__['test']: + for root_s in root_services: + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=root_s, **kwargs) + if not service: + ret['result'] = None + ret['comment'] = "Service {0} will be added".format(service_name) + ret['changes'] = changes_service_added + return ret + + root_id = service[0]['serviceid'] + + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=service_name, **kwargs) + if service: + ret['result'] = True + ret['comment'] = "Service {0} already exists".format(service_name) + else: + ret['result'] = None + ret['comment'] = "Service {0} will be added".format(service_name) + ret['changes'] = changes_service_added + return ret + + root_id = None + # ensure that root services exists + for root_s in root_services: + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=root_s, **kwargs) + if not service: + service = __salt__['zabbix.service_add'](service_rootid=root_id, service_name=root_s, **kwargs) + root_id = service['serviceids'][0] + else: + root_id = service[0]['serviceid'] + + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=service_name, **kwargs) + if not service: + service = __salt__['zabbix.service_add']( + service_rootid=root_id, service_name=service_name, triggerid=trigger_id, **kwargs) + if service: + ret['comment'] = "Service {0} added {1} {0} {2}".format(service_name, root_id, trigger_id) + ret['changes'] = changes_service_added + ret['result'] = True + else: + ret['comment'] = "Service {0} could not be added".format(service_name) + ret['result'] = False + + else: + ret['comment'] = "Service {0} already exists".format(service_name) + ret['result'] = True + + return ret + + +def absent(host, service_root, service_name=None, **kwargs): + ''' + .. versionadded:: Fluorine + + Ensure service does not exists under service root. + + :param host: Technical name of the host + :param service_root: Path of service (path is split /) + :param service_name: Name of service + :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring) + :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring) + :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring) + + .. code-block:: yaml + + delete_service_icmp: + zabbix_service.absent: + - host: server-1 + - service_root: server-group/server icmp + - service_name: server-1-icmp + ''' + if not service_name: + service_name = host + + changes_service_deleted = {host: {'old': 'Service {0} exist under {1}.'.format(service_name, service_root), + 'new': 'Service {0} deleted under {1}.'.format(service_name, service_root), + } + } + + connection_args = {} + if '_connection_user' in kwargs: + connection_args['_connection_user'] = kwargs['_connection_user'] + if '_connection_password' in kwargs: + connection_args['_connection_password'] = kwargs['_connection_password'] + if '_connection_url' in kwargs: + connection_args['_connection_url'] = kwargs['_connection_url'] + + ret = {'name': host, 'changes': {}, 'result': False, 'comment': ''} + + host_exists = __salt__['zabbix.host_exists'](host, **connection_args) + + if not host_exists: + ret['comment'] = 'Host {0} does not exists.'.format(host) + return ret + + root_services = service_root.split('/') + root_id = None + + if __opts__['test']: + for root_s in root_services: + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=root_s, **kwargs) + if not service: + ret['result'] = None + ret['comment'] = "Service {0} will be deleted".format(service_name) + ret['changes'] = changes_service_deleted + return ret + + root_id = service[0]['serviceid'] + + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=service_name, **kwargs) + if not service: + ret['result'] = True + ret['comment'] = "Service {0} does not exists".format(service_name) + else: + ret['result'] = None + ret['comment'] = "Service {0} will be deleted".format(service_name) + ret['changes'] = changes_service_deleted + return ret + + root_id = None + # ensure that root services exists + for root_s in root_services: + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=root_s, **kwargs) + if not service: + ret['result'] = True + ret['comment'] = "Service {0} does not exists".format(service_name) + return ret + else: + root_id = service[0]['serviceid'] + + service = __salt__['zabbix.service_get'](service_rootid=root_id, service_name=service_name, **kwargs) + if not service: + ret['result'] = True + ret['comment'] = "Service {0} does not exists".format(service_name) + return ret + else: + service = __salt__['zabbix.service_delete'](service_id=service[0]['serviceid'], **connection_args) + if service: + ret['comment'] = "Service {0} deleted".format(service_name) + ret['changes'] = changes_service_deleted + ret['result'] = True + else: + ret['comment'] = "Service {0} could not be deleted".format(service_name) + ret['result'] = False + + return ret diff --git a/tests/unit/test_doc.py b/tests/unit/test_doc.py index 4f8735f53456..829bff8e2b2f 100644 --- a/tests/unit/test_doc.py +++ b/tests/unit/test_doc.py @@ -97,3 +97,342 @@ def test_check_for_doc_inline_markup(self): # test_ret should be empty, otherwise there are :doc: references present self.assertEqual(test_ret, {}) + + def _check_doc_files(self, module_skip, module_dir, doc_skip, module_doc_dir): + ''' + Ensure various salt modules have associated documentation + ''' + + salt_dir = RUNTIME_VARS.CODE_DIR + + # Build list of module files + module_files = [] + skip_module_files = module_skip + full_module_dir = os.path.join(salt_dir, *module_dir) + for file in os.listdir(full_module_dir): + if file.endswith(".py"): + module_name = os.path.splitext(file)[0] + if module_name not in skip_module_files: + module_files.append(module_name) + + # Build list of beacon documentation files + module_docs = [] + skip_doc_files = doc_skip + full_module_doc_dir = os.path.join(salt_dir, *module_doc_dir) + doc_prefix = '.'.join(module_dir) + '.' + for file in os.listdir(full_module_doc_dir): + if file.endswith(".rst"): + doc_name = os.path.splitext(file)[0] + if doc_name.startswith(doc_prefix): + doc_name = doc_name[len(doc_prefix):] + if doc_name not in skip_doc_files: + module_docs.append(doc_name) + + # Check that every beacon has associated documentaiton file + for module in module_files: + self.assertIn(module, + module_docs, + 'module file {0} is missing documentation in {1}'.format(module, + full_module_doc_dir)) + + for doc_file in module_docs: + self.assertIn(doc_file, + module_files, + 'Doc file {0} is missing associated module in {1}'.format(doc_file, + full_module_dir)) + + def test_auth_doc_files(self): + ''' + Ensure auth modules have associated documentation + + doc example: doc/ref/auth/all/salt.auth.rest.rst + auth module example: salt/auth/rest.py + ''' + + skip_files = ['__init__'] + module_dir = ['salt', 'auth'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'auth', 'all'] + self._check_doc_files(skip_files, module_dir, skip_doc_files, doc_dir) + + def test_beacon_doc_files(self): + ''' + Ensure beacon modules have associated documentation + + doc example: doc/ref/beacons/all/salt.beacon.rest.rst + beacon module example: salt/beacons/rest.py + ''' + + skip_files = ['__init__'] + module_dir = ['salt', 'beacons'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'beacons', 'all'] + self._check_doc_files(skip_files, module_dir, skip_doc_files, doc_dir) + + def test_cache_doc_files(self): + ''' + Ensure cache modules have associated documentation + + doc example: doc/ref/cache/all/salt.cache.consul.rst + cache module example: salt/cache/consul.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'cache'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'cache', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_cloud_doc_files(self): + ''' + Ensure cloud modules have associated documentation + + doc example: doc/ref/clouds/all/salt.cloud.gce.rst + cloud module example: salt/cloud/clouds/gce.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'cloud', 'clouds'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'clouds', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_engine_doc_files(self): + ''' + Ensure engine modules have associated documentation + + doc example: doc/ref/engines/all/salt.engines.docker_events.rst + engine module example: salt/engines/docker_events.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'engines'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'engines', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_fileserver_doc_files(self): + ''' + Ensure fileserver modules have associated documentation + + doc example: doc/ref/fileserver/all/salt.fileserver.gitfs.rst + module example: salt/fileserver/gitfs.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'fileserver'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'file_server', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_grain_doc_files(self): + ''' + Ensure grain modules have associated documentation + + doc example: doc/ref/grains/all/salt.grains.core.rst + module example: salt/grains/core.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'grains'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'grains', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_module_doc_files(self): + ''' + Ensure modules have associated documentation + + doc example: doc/ref/modules/all/salt.modules.zabbix.rst + execution module example: salt/modules/zabbix.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'modules'] + skip_doc_files = ['index', 'group', 'inspectlib', 'inspectlib.collector', 'inspectlib.dbhandle', + 'inspectlib.entities', 'inspectlib.exceptions', 'inspectlib.fsdb', + 'inspectlib.kiwiproc', 'inspectlib.query', 'kernelpkg', 'pkg', 'user'] + doc_dir = ['doc', 'ref', 'modules', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_output_doc_files(self): + ''' + Ensure output modules have associated documentation + + doc example: doc/ref/output/all/salt.output.highstate.rst + module example: salt/output/highstate.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'output'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'output', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_pillar_doc_files(self): + ''' + Ensure pillar modules have associated documentation + + doc example: doc/ref/pillar/all/salt.pillar.cobbler.rst + module example: salt/pillar/cobbler.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'pillar'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'pillar', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_proxy_doc_files(self): + ''' + Ensure proxy modules have associated documentation + + doc example: doc/ref/proxy/all/salt.proxy.docker.rst + module example: salt/proxy/docker.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'proxy'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'proxy', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_queues_doc_files(self): + ''' + Ensure queue modules have associated documentation + + doc example: doc/ref/queues/all/salt.queues.sqlite_queue.rst + module example: salt/queues/sqlite_queue.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'queues'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'queues', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_renderers_doc_files(self): + ''' + Ensure render modules have associated documentation + + doc example: doc/ref/renderers/all/salt.renderers.json.rst + module example: salt/renderers/json.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'renderers'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'renderers', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_returners_doc_files(self): + ''' + Ensure return modules have associated documentation + + doc example: doc/ref/returners/all/salt.returners.cassandra_return.rst + module example: salt/returners/cassandra_return.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'returners'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'returners', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_runners_doc_files(self): + ''' + Ensure runner modules have associated documentation + + doc example: doc/ref/runners/all/salt.runners.auth.rst + module example: salt/runners/auth.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'runners'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'runners', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_sdb_doc_files(self): + ''' + Ensure sdb modules have associated documentation + + doc example: doc/ref/sdb/all/salt.sdb.rest.rst + module example: salt/sdb/rest.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'sdb'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'sdb', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_serializers_doc_files(self): + ''' + Ensure serializer modules have associated documentation + + doc example: doc/ref/serializers/all/salt.serializers.yaml.rst + module example: salt/serializers/yaml.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'serializers'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'serializers', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_states_doc_files(self): + ''' + Ensure states have associated documentation + + doc example: doc/ref/states/all/salt.states.zabbix_host.rst + module example: salt/states/zabbix_host.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'states'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'states', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_thorium_doc_files(self): + ''' + Ensure thorium modules have associated documentation + + doc example: doc/ref/thorium/all/salt.thorium.calc.rst + module example: salt/thorium/calc.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'thorium'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'thorium', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_tops_doc_files(self): + ''' + Ensure top modules have associated documentation + + doc example: doc/ref/tops/all/salt.tops.saltclass.rst + module example: salt/tops/saltclass.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'tops'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'tops', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir) + + def test_wheel_doc_files(self): + ''' + Ensure wheel modules have associated documentation + + doc example: doc/ref/wheel/all/salt.wheel.key.rst + module example: salt/wheel/key.py + ''' + + skip_module_files = ['__init__'] + module_dir = ['salt', 'wheel'] + skip_doc_files = ['index', 'all'] + doc_dir = ['doc', 'ref', 'wheel', 'all'] + self._check_doc_files(skip_module_files, module_dir, skip_doc_files, doc_dir)