From 4670e41a303f3a9bc911e672a06a5d381477ee98 Mon Sep 17 00:00:00 2001 From: Dag Wieers Date: Mon, 25 Feb 2019 13:27:35 +0100 Subject: [PATCH] validate-modules: Fix net_tools modules (#52489) This PR includes: * Fixes to open validate-modules issues * Adding parameter types --- .../modules/net_tools/basics/get_url.py | 7 +- lib/ansible/modules/net_tools/basics/slurp.py | 1 + lib/ansible/modules/net_tools/basics/uri.py | 48 ++-- .../modules/net_tools/cloudflare_dns.py | 267 ++++++++++-------- lib/ansible/modules/net_tools/haproxy.py | 144 +++++----- .../modules/net_tools/infinity/infinity.py | 203 +++++++------ lib/ansible/modules/net_tools/ipify_facts.py | 30 +- .../modules/net_tools/ldap/ldap_attr.py | 52 ++-- lib/ansible/modules/net_tools/omapi_host.py | 97 +++---- lib/ansible/modules/net_tools/snmp_facts.py | 100 ++++--- test/sanity/validate-modules/ignore.txt | 16 -- 11 files changed, 499 insertions(+), 466 deletions(-) diff --git a/lib/ansible/modules/net_tools/basics/get_url.py b/lib/ansible/modules/net_tools/basics/get_url.py index 7f9666d049..2ec50284ea 100644 --- a/lib/ansible/modules/net_tools/basics/get_url.py +++ b/lib/ansible/modules/net_tools/basics/get_url.py @@ -7,8 +7,6 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -# see examples/playbooks/get_url.yml - ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['stableinterface'], 'supported_by': 'core'} @@ -162,6 +160,11 @@ options: - If C(client_cert) contains both the certificate and key, this option is not required. type: path version_added: '2.4' + http_agent: + description: + - Header to identify as, generally appears in web server logs. + type: str + default: ansible-httpget # informational: requirements for nodes extends_documentation_fragment: - files diff --git a/lib/ansible/modules/net_tools/basics/slurp.py b/lib/ansible/modules/net_tools/basics/slurp.py index 2bc70c9f2f..c1891eac04 100644 --- a/lib/ansible/modules/net_tools/basics/slurp.py +++ b/lib/ansible/modules/net_tools/basics/slurp.py @@ -27,6 +27,7 @@ options: - The file on the remote system to fetch. This I(must) be a file, not a directory. type: path required: true + aliases: [ path ] notes: - This module returns an 'in memory' base64 encoded version of the file, take into account that this will require at least twice the RAM as the original file size. diff --git a/lib/ansible/modules/net_tools/basics/uri.py b/lib/ansible/modules/net_tools/basics/uri.py index a160b97a56..85483aa142 100644 --- a/lib/ansible/modules/net_tools/basics/uri.py +++ b/lib/ansible/modules/net_tools/basics/uri.py @@ -32,14 +32,16 @@ options: - A path of where to download the file to (if desired). If I(dest) is a directory, the basename of the file on the remote server will be used. type: path - user: + url_username: description: - A username for the module to use for Digest, Basic or WSSE authentication. type: str - password: + aliases: [ user ] + url_password: description: - A password for the module to use for Digest, Basic or WSSE authentication. type: str + aliases: [ password ] body: description: - The body of the http request/response to the web service. If C(body_format) is set @@ -102,7 +104,7 @@ options: description: - A list of valid, numeric, HTTP status codes that signifies success of the request. type: list - default: 200 + default: [ 200 ] timeout: description: - The socket level timeout in seconds @@ -174,6 +176,11 @@ options: description: - Path to Unix domain socket to use for connection version_added: '2.8' + http_agent: + description: + - Header to identify as, generally appears in web server logs. + type: str + default: ansible-httpget notes: - The dependency on httplib2 was removed in Ansible 2.1. - The module returns all the HTTP headers in lower-case. @@ -190,9 +197,8 @@ EXAMPLES = r''' uri: url: http://www.example.com -# Check that a page returns a status 200 and fail if the word AWESOME is not -# in the page contents. -- uri: +- name: Check that a page returns a status 200 and fail if the word AWESOME is not in the page contents + uri: url: http://www.example.com return_content: yes register: this @@ -201,18 +207,16 @@ EXAMPLES = r''' - name: Create a JIRA issue uri: url: https://your.jira.example.com/rest/api/2/issue/ - method: POST user: your_username password: your_pass + method: POST body: "{{ lookup('file','issue.json') }}" force_basic_auth: yes status_code: 201 body_format: json -# Login to a form based webpage, then use the returned cookie to -# access the app in later tasks - -- uri: +- name: Login to a form based webpage, then use the returned cookie to access the app in later tasks + uri: url: https://your.form.based.auth.example.com/index.php method: POST body_format: form-urlencoded @@ -223,8 +227,8 @@ EXAMPLES = r''' status_code: 302 register: login -# Same, but now using a list of tuples -- uri: +- name: Login to a form based webpage using a list of tuples + uri: url: https://your.form.based.auth.example.com/index.php method: POST body_format: form-urlencoded @@ -235,7 +239,8 @@ EXAMPLES = r''' status_code: 302 register: login -- uri: +- name: Connect to website using a previously stored cookie + uri: url: https://your.form.based.auth.example.com/dashboard.php method: GET return_content: yes @@ -245,24 +250,24 @@ EXAMPLES = r''' - name: Queue build of a project in Jenkins uri: url: http://{{ jenkins.host }}/job/{{ jenkins.job }}/build?token={{ jenkins.token }} - method: GET user: "{{ jenkins.user }}" password: "{{ jenkins.password }}" + method: GET force_basic_auth: yes status_code: 201 - name: POST from contents of local file uri: - url: "https://httpbin.org/post" + url: https://httpbin.org/post method: POST src: file.json - name: POST from contents of remote file uri: - url: "https://httpbin.org/post" + url: https://httpbin.org/post method: POST src: /path/to/my/file.json - remote_src: true + remote_src: yes ''' RETURN = r''' @@ -301,7 +306,6 @@ import os import shutil import sys import tempfile -import traceback from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six import PY2, iteritems, string_types @@ -327,7 +331,7 @@ def write_file(module, url, dest, content, resp): except Exception as e: os.remove(tmpsrc) msg = format_message("Failed to create temporary content file: %s" % to_native(e), resp) - module.fail_json(msg=msg, exception=traceback.format_exc(), **resp) + module.fail_json(msg=msg, **resp) f.close() checksum_src = None @@ -368,7 +372,7 @@ def write_file(module, url, dest, content, resp): except Exception as e: os.remove(tmpsrc) msg = format_message("failed to copy %s to %s: %s" % (tmpsrc, dest, to_native(e)), resp) - module.fail_json(msg=msg, exception=traceback.format_exc(), **resp) + module.fail_json(msg=msg, **resp) os.remove(tmpsrc) @@ -449,7 +453,7 @@ def uri(module, url, dest, body, body_format, method, headers, socket_timeout): }) data = open(src, 'rb') except OSError: - module.fail_json(msg='Unable to open source file %s' % src, exception=traceback.format_exc(), elapsed=0) + module.fail_json(msg='Unable to open source file %s' % src, elapsed=0) else: data = body diff --git a/lib/ansible/modules/net_tools/cloudflare_dns.py b/lib/ansible/modules/net_tools/cloudflare_dns.py index 9e1eecd65d..1e1bb6aa4a 100644 --- a/lib/ansible/modules/net_tools/cloudflare_dns.py +++ b/lib/ansible/modules/net_tools/cloudflare_dns.py @@ -1,128 +1,159 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# (c) 2016 Michael Gruener +# Copyright: (c) 2016 Michael Gruener # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type - ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} - -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: cloudflare_dns -author: "Michael Gruener (@mgruener)" +author: +- Michael Gruener (@mgruener) requirements: - - "python >= 2.6" + - python >= 2.6 version_added: "2.1" -short_description: manage Cloudflare DNS records +short_description: Manage Cloudflare DNS records description: - "Manages dns records via the Cloudflare API, see the docs: U(https://api.cloudflare.com/)" options: account_api_token: description: - - > - Account API token. You can obtain your API key from the bottom of the Cloudflare 'My Account' page, found here: U(https://dash.cloudflare.com/) + - Account API token. + - "You can obtain your API key from the bottom of the Cloudflare 'My Account' page, found here: U(https://dash.cloudflare.com/)" + type: str required: true account_email: description: - - "Account email." + - Account email. + type: str required: true algorithm: description: - - Algorithm number. Required for C(type=DS) and C(type=SSHFP) when C(state=present). + - Algorithm number. + - Required for C(type=DS) and C(type=SSHFP) when C(state=present). type: int - version_added: 2.7 + version_added: '2.7' cert_usage: description: - - Certificate usage number. Required for C(type=TLSA) when C(state=present). - choices: [ 0, 1, 2, 3 ] + - Certificate usage number. + - Required for C(type=TLSA) when C(state=present). type: int - version_added: 2.7 + choices: [ 0, 1, 2, 3 ] + version_added: '2.7' hash_type: description: - - Hash type number. Required for C(type=DS), C(type=SSHFP) and C(type=TLSA) when C(state=present). - choices: [ 1, 2 ] + - Hash type number. + - Required for C(type=DS), C(type=SSHFP) and C(type=TLSA) when C(state=present). type: int - version_added: 2.7 + choices: [ 1, 2 ] + version_added: '2.7' key_tag: description: - - DNSSEC key tag. Needed for C(type=DS) when C(state=present). + - DNSSEC key tag. + - Needed for C(type=DS) when C(state=present). type: int - version_added: 2.7 + version_added: '2.7' port: - description: Service port. Required for C(type=SRV) and C(type=TLSA). + description: + - Service port. + - Required for C(type=SRV) and C(type=TLSA). + type: int priority: - description: Record priority. Required for C(type=MX) and C(type=SRV) - default: "1" + description: + - Record priority. + - Required for C(type=MX) and C(type=SRV) + default: 1 proto: description: - Service protocol. Required for C(type=SRV) and C(type=TLSA). - - Common values are tcp and udp. - - Before Ansible 2.6 only tcp and udp were available. + - Common values are TCP and UDP. + - Before Ansible 2.6 only TCP and UDP were available. + type: str proxied: - description: Proxy through cloudflare network or just use DNS + description: + - Proxy through Cloudflare network or just use DNS. type: bool - default: 'no' - version_added: "2.3" + default: no + version_added: '2.3' record: description: - - Record to add. Required if C(state=present). Default is C(@) (e.g. the zone name) - default: "@" - aliases: [ "name" ] + - Record to add. + - Required if C(state=present). + - Default is C(@) (e.g. the zone name). + type: str + default: '@' + aliases: [ name ] selector: description: - - Selector number. Required for C(type=TLSA) when C(state=present). + - Selector number. + - Required for C(type=TLSA) when C(state=present). choices: [ 0, 1 ] type: int - version_added: 2.7 + version_added: '2.7' service: - description: Record service. Required for C(type=SRV) + description: + - Record service. + - Required for C(type=SRV) solo: description: - - Whether the record should be the only one for that record type and record name. Only use with C(state=present) - - This will delete all other records with the same record name and type. + - Whether the record should be the only one for that record type and record name. + - Only use with C(state=present). + - This will delete all other records with the same record name and type. type: bool state: description: - - Whether the record(s) should exist or not - choices: [ 'present', 'absent' ] + - Whether the record(s) should exist or not. + type: str + choices: [ absent, present ] default: present timeout: description: - - Timeout for Cloudflare API calls + - Timeout for Cloudflare API calls. + type: int default: 30 ttl: description: - - The TTL to give the new record. Must be between 120 and 2,147,483,647 seconds, or 1 for automatic. - default: 1 (automatic) + - The TTL to give the new record. + - Must be between 120 and 2,147,483,647 seconds, or 1 for automatic. + type: int + default: 1 type: description: - - The type of DNS record to create. Required if C(state=present) + - The type of DNS record to create. Required if C(state=present). - C(type=DS), C(type=SSHFP) and C(type=TLSA) added in Ansible 2.7. - choices: [ 'A', 'AAAA', 'CNAME', 'TXT', 'SRV', 'MX', 'NS', 'DS', 'SPF', 'SSHFP', 'TLSA' ] + type: str + choices: [ A, AAAA, CNAME, DS, MX, NS, SPF, SRV, SSHFP, TLSA, TXT ] value: description: - - The record value. Required for C(state=present) - aliases: [ "content" ] + - The record value. + - Required for C(state=present). + type: str + aliases: [ content ] weight: - description: Service weight. Required for C(type=SRV) - default: "1" + description: + - Service weight. + - Required for C(type=SRV). + type: int + default: 1 zone: description: - - The name of the Zone to work with (e.g. "example.com"). The Zone must already exist. + - The name of the Zone to work with (e.g. "example.com"). + - The Zone must already exist. + type: str required: true - aliases: ["domain"] + aliases: [ domain ] ''' -EXAMPLES = ''' -# create a test.my.com A record to point to 127.0.0.1 -- cloudflare_dns: +EXAMPLES = r''' +- name: Create a test.my.com A record to point to 127.0.0.1 + cloudflare_dns: zone: my.com record: test type: A @@ -131,58 +162,58 @@ EXAMPLES = ''' account_api_token: dummyapitoken register: record -# create a my.com CNAME record to example.com -- cloudflare_dns: +- name: Create a my.com CNAME record to example.com + cloudflare_dns: zone: my.com type: CNAME value: example.com - state: present account_email: test@example.com account_api_token: dummyapitoken + state: present -# change it's ttl -- cloudflare_dns: +- name: Change its TTL + cloudflare_dns: zone: my.com type: CNAME value: example.com ttl: 600 - state: present account_email: test@example.com account_api_token: dummyapitoken + state: present -# and delete the record -- cloudflare_dns: +- name: Delete the record + cloudflare_dns: zone: my.com type: CNAME value: example.com + account_email: test@example.com + account_api_token: dummyapitoken state: absent - account_email: test@example.com - account_api_token: dummyapitoken -# create a my.com CNAME record to example.com and proxy through cloudflare's network -- cloudflare_dns: +- name: create a my.com CNAME record to example.com and proxy through Cloudflare's network + cloudflare_dns: zone: my.com type: CNAME value: example.com - state: present proxied: yes account_email: test@example.com account_api_token: dummyapitoken + state: present -# create TXT record "test.my.com" with value "unique value" -# delete all other TXT records named "test.my.com" -- cloudflare_dns: +# This deletes all other TXT records named "test.my.com" +- name: Create TXT record "test.my.com" with value "unique value" + cloudflare_dns: domain: my.com record: test type: TXT value: unique value - state: present solo: true account_email: test@example.com account_api_token: dummyapitoken + state: present -# create a SRV record _foo._tcp.my.com -- cloudflare_dns: +- name: Create an SRV record _foo._tcp.my.com + cloudflare_dns: domain: my.com service: foo proto: tcp @@ -192,8 +223,8 @@ EXAMPLES = ''' type: SRV value: fooserver.my.com -# create a SSHFP record login.example.com -- cloudflare_dns: +- name: Create a SSHFP record login.example.com + cloudflare_dns: zone: example.com record: login type: SSHFP @@ -201,8 +232,8 @@ EXAMPLES = ''' hash_type: 2 value: 9dc1d6742696d2f51ca1f1a78b3d16a840f7d111eb9454239e70db31363f33e1 -# create a TLSA record _25._tcp.mail.example.com -- cloudflare_dns: +- name: Create a TLSA record _25._tcp.mail.example.com + cloudflare_dns: zone: example.com record: mail port: 25 @@ -213,8 +244,8 @@ EXAMPLES = ''' hash_type: 1 value: 6b76d034492b493e15a7376fccd08e63befdad0edab8e442562f532338364bf3 -# Create a DS record for subdomain.example.com -- cloudflare_dns: +- name: Create a DS record for subdomain.example.com + cloudflare_dns: zone: example.com record: subdomain type: DS @@ -224,24 +255,24 @@ EXAMPLES = ''' value: B4EB5AC4467D2DFB3BAF9FB9961DC1B6FED54A58CDFAA3E465081EC86F89BFAB ''' -RETURN = ''' +RETURN = r''' record: - description: dictionary containing the record data + description: A dictionary containing the record data. returned: success, except on record deletion type: complex contains: content: - description: the record content (details depend on record type) + description: The record content (details depend on record type). returned: success type: str sample: 192.0.2.91 created_on: - description: the record creation date + description: The record creation date. returned: success type: str sample: 2016-03-25T19:09:42.516553Z data: - description: additional record data + description: Additional record data. returned: success, if type is SRV, DS, SSHFP or TLSA type: dict sample: { @@ -254,62 +285,62 @@ record: weight: 5, } id: - description: the record id + description: The record ID. returned: success type: str sample: f9efb0549e96abcb750de63b38c9576e locked: - description: No documentation available + description: No documentation available. returned: success type: bool sample: False meta: - description: No documentation available + description: No documentation available. returned: success type: dict sample: { auto_added: false } modified_on: - description: record modification date + description: Record modification date. returned: success type: str sample: 2016-03-25T19:09:42.516553Z name: - description: the record name as FQDN (including _service and _proto for SRV) + description: The record name as FQDN (including _service and _proto for SRV). returned: success type: str sample: www.sample.com priority: - description: priority of the MX record + description: Priority of the MX record. returned: success, if type is MX type: int sample: 10 proxiable: - description: whether this record can be proxied through cloudflare + description: Whether this record can be proxied through Cloudflare. returned: success type: bool sample: False proxied: - description: whether the record is proxied through cloudflare + description: Whether the record is proxied through Cloudflare. returned: success type: bool sample: False ttl: - description: the time-to-live for the record + description: The time-to-live for the record. returned: success type: int sample: 300 type: - description: the record type + description: The record type. returned: success type: str sample: A zone_id: - description: the id of the zone containing the record + description: The ID of the zone containing the record. returned: success type: str sample: abcede0bf9f0066f94029d2e6b73856a zone_name: - description: the name of the zone containing the record + description: The name of the zone containing the record. returned: success type: str sample: sample.com @@ -735,27 +766,27 @@ class CloudflareAPI(object): def main(): module = AnsibleModule( argument_spec=dict( - account_api_token=dict(required=True, no_log=True, type='str'), - account_email=dict(required=True, type='str'), - algorithm=dict(required=False, default=None, type='int'), - cert_usage=dict(required=False, default=None, choices=[0, 1, 2, 3], type='int'), - hash_type=dict(required=False, default=None, choices=[1, 2], type='int'), - key_tag=dict(required=False, default=None, type='int'), - port=dict(required=False, default=None, type='int'), - priority=dict(required=False, default=1, type='int'), - proto=dict(required=False, default=None, type='str'), - proxied=dict(required=False, default=False, type='bool'), - record=dict(required=False, default='@', aliases=['name'], type='str'), - selector=dict(required=False, default=None, choices=[0, 1], type='int'), - service=dict(required=False, default=None, type='str'), - solo=dict(required=False, default=None, type='bool'), - state=dict(required=False, default='present', choices=['present', 'absent'], type='str'), - timeout=dict(required=False, default=30, type='int'), - ttl=dict(required=False, default=1, type='int'), - type=dict(required=False, default=None, choices=['A', 'AAAA', 'CNAME', 'TXT', 'SRV', 'MX', 'NS', 'DS', 'SPF', 'SSHFP', 'TLSA'], type='str'), - value=dict(required=False, default=None, aliases=['content'], type='str'), - weight=dict(required=False, default=1, type='int'), - zone=dict(required=True, default=None, aliases=['domain'], type='str'), + account_api_token=dict(type='str', required=True, no_log=True), + account_email=dict(type='str', required=True), + algorithm=dict(type='int'), + cert_usage=dict(type='int', choices=[0, 1, 2, 3]), + hash_type=dict(type='int', choices=[1, 2]), + key_tag=dict(type='int'), + port=dict(type='int'), + priority=dict(type='int', default=1), + proto=dict(type='str'), + proxied=dict(type='bool', default=False), + record=dict(type='str', default='@', aliases=['name']), + selector=dict(type='int', choices=[0, 1]), + service=dict(type='str'), + solo=dict(type='bool'), + state=dict(type='str', default='present', choices=['absent', 'present']), + timeout=dict(type='int', default=30), + ttl=dict(type='int', default=1), + type=dict(type='str', choices=['A', 'AAAA', 'CNAME', 'DS', 'MX', 'NS', 'SPF', 'SRV', 'SSHFP', 'TLSA', 'TXT']), + value=dict(type='str', aliases=['content']), + weight=dict(type='int', default=1), + zone=dict(type='str', required=True, aliases=['domain']), ), supports_check_mode=True, required_if=([ @@ -763,7 +794,7 @@ def main(): ('state', 'absent', ['record']), ('type', 'SRV', ['proto', 'service']), ('type', 'TLSA', ['proto', 'port']), - ] + ], ), ) @@ -811,8 +842,8 @@ def main(): result, changed = cf_api.ensure_dns_record() if isinstance(result, list): module.exit_json(changed=changed, result={'record': result[0]}) - else: - module.exit_json(changed=changed, result={'record': result}) + + module.exit_json(changed=changed, result={'record': result}) else: # force solo to False, just to be sure changed = cf_api.delete_dns_records(solo=False) diff --git a/lib/ansible/modules/net_tools/haproxy.py b/lib/ansible/modules/net_tools/haproxy.py index dcdb6d7502..f7ee651fea 100644 --- a/lib/ansible/modules/net_tools/haproxy.py +++ b/lib/ansible/modules/net_tools/haproxy.py @@ -1,27 +1,25 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# (c) 2014, Ravi Bhure +# Copyright: (c) 2014, Ravi Bhure # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type - ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} - -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: haproxy version_added: "1.9" -short_description: Enable, disable, and set weights for HAProxy backend servers using socket commands. -author: "Ravi Bhure (@ravibhure)" +short_description: Enable, disable, and set weights for HAProxy backend servers using socket commands +author: +- Ravi Bhure (@ravibhure) description: - - Enable, disable, drain and set weights for HAProxy backend servers using socket - commands. + - Enable, disable, drain and set weights for HAProxy backend servers using socket commands. notes: - Enable, disable and drain commands are restricted and can only be issued on sockets configured for level 'admin'. For example, you can add the line @@ -33,90 +31,99 @@ options: backend: description: - Name of the HAProxy backend pool. - default: auto-detected + - If this parameter is unset, it will be auto-detected. + type: str drain: description: - Wait until the server has no active connections or until the timeout - determined by wait_interval and wait_retries is reached. Continue only - after the status changes to 'MAINT'. This overrides the - shutdown_sessions option. + determined by wait_interval and wait_retries is reached. + - Continue only after the status changes to 'MAINT'. + - This overrides the shutdown_sessions option. type: bool version_added: "2.4" host: description: - Name of the backend host to change. + type: str required: true shutdown_sessions: description: - When disabling a server, immediately terminate all the sessions attached - to the specified server. This can be used to terminate long-running - sessions after a server is put into maintenance mode. Overridden by the - drain option. + to the specified server. + - This can be used to terminate long-running sessions after a server is put + into maintenance mode. Overridden by the drain option. type: bool - default: 'no' + default: no socket: description: - Path to the HAProxy socket file. + type: path default: /var/run/haproxy.sock state: description: - Desired state of the provided backend host. - - Note that C(drain) state was added in version 2.4. It is supported only by HAProxy version 1.5 or later, - if used on versions < 1.5, it will be ignored. + - Note that C(drain) state was added in version 2.4. + - It is supported only by HAProxy version 1.5 or later, + - When used on versions < 1.5, it will be ignored. + type: str required: true - choices: [ "enabled", "disabled", "drain" ] + choices: [ disabled, drain, enabled ] fail_on_not_found: description: - Fail whenever trying to enable/disable a backend host that does not exist type: bool - default: 'no' + default: no version_added: "2.2" wait: description: - - Wait until the server reports a status of 'UP' when `state=enabled`, - status of 'MAINT' when `state=disabled` or status of 'DRAIN' when `state=drain` + - Wait until the server reports a status of 'UP' when C(state=enabled), + status of 'MAINT' when C(state=disabled) or status of 'DRAIN' when C(state=drain) type: bool - default: 'no' + default: no version_added: "2.0" wait_interval: description: - Number of seconds to wait between retries. + type: int default: 5 version_added: "2.0" wait_retries: description: - Number of times to check for status after changing the state. + type: int default: 25 version_added: "2.0" weight: description: - - The value passed in argument. If the value ends with the `%` sign, then - the new weight will be relative to the initially configured weight. - Relative weights are only permitted between 0 and 100% and absolute + - The value passed in argument. + - If the value ends with the `%` sign, then the new weight will be + relative to the initially configured weight. + - Relative weights are only permitted between 0 and 100% and absolute weights are permitted between 0 and 256. + type: str ''' -EXAMPLES = ''' -# disable server in 'www' backend pool -- haproxy: +EXAMPLES = r''' +- name: Disable server in 'www' backend pool + haproxy: state: disabled host: '{{ inventory_hostname }}' backend: www -# disable server without backend pool name (apply to all available backend pool) -- haproxy: +- name: Disable server without backend pool name (apply to all available backend pool) + haproxy: state: disabled host: '{{ inventory_hostname }}' -# disable server, provide socket file -- haproxy: +- name: Disable server, provide socket file + haproxy: state: disabled host: '{{ inventory_hostname }}' socket: /var/run/haproxy.sock backend: www -# disable server, provide socket file, wait until status reports in maintenance -- haproxy: +- name: Disable server, provide socket file, wait until status reports in maintenance + haproxy: state: disabled host: '{{ inventory_hostname }}' socket: /var/run/haproxy.sock @@ -136,35 +143,35 @@ EXAMPLES = ''' wait_interval: 1 wait_retries: 60 -# disable backend server in 'www' backend pool and drop open sessions to it -- haproxy: +- name: Disable backend server in 'www' backend pool and drop open sessions to it + haproxy: state: disabled host: '{{ inventory_hostname }}' backend: www socket: /var/run/haproxy.sock - shutdown_sessions: true + shutdown_sessions: yes -# disable server without backend pool name (apply to all available backend pool) but fail when the backend host is not found -- haproxy: +- name: Disable server without backend pool name (apply to all available backend pool) but fail when the backend host is not found + haproxy: state: disabled host: '{{ inventory_hostname }}' fail_on_not_found: yes -# enable server in 'www' backend pool -- haproxy: +- name: Enable server in 'www' backend pool + haproxy: state: enabled host: '{{ inventory_hostname }}' backend: www -# enable server in 'www' backend pool wait until healthy -- haproxy: +- name: Enable server in 'www' backend pool wait until healthy + haproxy: state: enabled host: '{{ inventory_hostname }}' backend: www wait: yes -# enable server in 'www' backend pool wait until healthy. Retry 10 times with intervals of 5 seconds to retrieve the health -- haproxy: +- name: Enable server in 'www' backend pool wait until healthy. Retry 10 times with intervals of 5 seconds to retrieve the health + haproxy: state: enabled host: '{{ inventory_hostname }}' backend: www @@ -172,16 +179,16 @@ EXAMPLES = ''' wait_retries: 10 wait_interval: 5 -# enable server in 'www' backend pool with change server(s) weight -- haproxy: +- name: Enable server in 'www' backend pool with change server(s) weight + haproxy: state: enabled host: '{{ inventory_hostname }}' socket: /var/run/haproxy.sock weight: 10 backend: www -# set the server in 'www' backend pool to drain mode -- haproxy: +- name: Set the server in 'www' backend pool to drain mode + haproxy: state: drain host: '{{ inventory_hostname }}' socket: /var/run/haproxy.sock @@ -395,8 +402,7 @@ class HAProxy(object): Figure out what you want to do from ansible, and then do it. """ # Get the state before the run - state_before = self.get_state_for(self.backend, self.host) - self.command_results['state_before'] = state_before + self.command_results['state_before'] = self.get_state_for(self.backend, self.host) # toggle enable/disbale server if self.state == 'enabled': @@ -411,16 +417,12 @@ class HAProxy(object): self.module.fail_json(msg="unknown state specified: '%s'" % self.state) # Get the state after the run - state_after = self.get_state_for(self.backend, self.host) - self.command_results['state_after'] = state_after + self.command_results['state_after'] = self.get_state_for(self.backend, self.host) # Report change status - if state_before != state_after: - self.command_results['changed'] = True - self.module.exit_json(**self.command_results) - else: - self.command_results['changed'] = False - self.module.exit_json(**self.command_results) + self.command_results['changed'] = (self.command_results['state_before'] != self.command_results['state_after']) + + self.module.exit_json(**self.command_results) def main(): @@ -428,17 +430,17 @@ def main(): # load ansible module object module = AnsibleModule( argument_spec=dict( - state=dict(required=True, default=None, choices=ACTION_CHOICES), - host=dict(required=True, default=None), - backend=dict(required=False, default=None), - weight=dict(required=False, default=None), - socket=dict(required=False, default=DEFAULT_SOCKET_LOCATION), - shutdown_sessions=dict(required=False, default=False, type='bool'), - fail_on_not_found=dict(required=False, default=False, type='bool'), - wait=dict(required=False, default=False, type='bool'), - wait_retries=dict(required=False, default=WAIT_RETRIES, type='int'), - wait_interval=dict(required=False, default=WAIT_INTERVAL, type='int'), - drain=dict(default=False, type='bool'), + state=dict(type='str', required=True, choices=ACTION_CHOICES), + host=dict(type='str', required=True), + backend=dict(type='str'), + weight=dict(type='str'), + socket=dict(type='path', default=DEFAULT_SOCKET_LOCATION), + shutdown_sessions=dict(type='bool', default=False), + fail_on_not_found=dict(type='bool', default=False), + wait=dict(type='bool', default=False), + wait_retries=dict(type='int', default=WAIT_RETRIES), + wait_interval=dict(type='int', default=WAIT_INTERVAL), + drain=dict(type='bool', default=False), ), ) diff --git a/lib/ansible/modules/net_tools/infinity/infinity.py b/lib/ansible/modules/net_tools/infinity/infinity.py index 842831863a..12ae22b72c 100644 --- a/lib/ansible/modules/net_tools/infinity/infinity.py +++ b/lib/ansible/modules/net_tools/infinity/infinity.py @@ -1,105 +1,92 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# -# Copyright (c), meiliu@fusionlayer.com, 2017 -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. + +# Copyright: (c) 2017, +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import (absolute_import, division, print_function) __metaclass__ = type - ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} - -DOCUMENTATION = """ +DOCUMENTATION = r''' module: infinity -short_description: "manage Infinity IPAM using Rest API" +short_description: Manage Infinity IPAM using Rest API description: - - "Manage Infinity IPAM using REST API" + - Manage Infinity IPAM using REST API. version_added: "2.4" author: - - "Meirong Liu (@MeganLiu)" + - Meirong Liu (@MeganLiu) options: server_ip: description: - - Infinity server_ip with IP address + - Infinity server_ip with IP address. + type: str required: true username: description: - - Username to access Infinity - - The user must have Rest API privileges + - Username to access Infinity. + - The user must have REST API privileges. + type: str required: true password: description: - - Infinity password + - Infinity password. + type: str required: true action: description: - Action to perform + type: str required: true - choices: - - reserve_next_available_ip - - release_ip - - delete_network - - add_network - - reserve_network - - release_network - - get_network_id - + choices: [add_network, delete_network, get_network, get_network_id, release_ip, release_network, reserve_network, reserve_next_available_ip ] network_id: description: - - Network ID + - Network ID. + type: str default: '' ip_address: description: - - IP Address for a reservation or a release + - IP Address for a reservation or a release. + type: str default: '' network_address: description: - - Network address with CIDR format (e.g., 192.168.310.0) - required: false - default: "" + - Network address with CIDR format (e.g., 192.168.310.0). + type: str + default: '' network_size: description: - - Network bitmask (e.g. 255.255.255.220) or CIDR format (e.g., /26) + - Network bitmask (e.g. 255.255.255.220) or CIDR format (e.g., /26). + type: str default: '' network_name: description: - - The name of a network + - The name of a network. + type: str default: '' network_location: description: - - the parent network id for a given network + - The parent network id for a given network. + type: int default: -1 network_type: description: - Network type defined by Infinity - choices: - - lan - - shared_lan - - supernet - default: "lan" + type: str + choices: [ lan, shared_lan, supernet ] + default: lan network_family: description: - Network family defined by Infinity, e.g. IPv4, IPv6 and Dual stack - choices: - - 4 - - 6 - - dual - default: "4" + type: str + choices: [ 4, 6, dual ] + default: 4 +''' -""" - - -EXAMPLES = """ +EXAMPLES = r''' --- - hosts: localhost connection: local @@ -107,20 +94,19 @@ EXAMPLES = """ tasks: - name: Reserve network into Infinity IPAM infinity: - server_ip: "80.75.107.12" - username: "username" - password: "password" - action: "reserve_network" - network_name: "reserve_new_ansible_network" - network_family: "4" - network_type: 'lan' - network_id: "1201" - network_size: "/28" + server_ip: 80.75.107.12 + username: username + password: password + action: reserve_network + network_name: reserve_new_ansible_network + network_family: 4 + network_type: lan + network_id: 1201 + network_size: /28 register: infinity +''' -""" - -RETURN = """ +RETURN = r''' network_id: description: id for a given network returned: success @@ -139,11 +125,10 @@ network_info: "network_size": null,"description": null,"network_location": "3085", "ranges": { "id": 0, "name": null,"first_ip": null,"type": null,"last_ip": null}, "network_type": "lan","network_name": "'reserve_new_ansible_network'"} -""" +''' -from ansible.module_utils.basic import json -from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.basic import AnsibleModule, json from ansible.module_utils.urls import open_url @@ -486,61 +471,73 @@ class Infinity(object): def main(): - my_module = AnsibleModule(argument_spec=dict( - server_ip=dict(required=True, type='str'), - username=dict(required=True, type='str'), - password=dict(required=True, type='str', no_log=True), - network_id=dict(type='str'), - ip_address=dict(type='str'), - network_name=dict(type='str'), - network_location=dict(default=-1, type='int'), - network_family=dict(default='4', choices=['4', '6', 'dual']), - network_type=dict(default='lan', choices=['lan', 'shared_lan', 'supernet']), - network_address=dict(type='str'), - network_size=dict(type='str'), - action=dict(required=True, choices=['get_network', 'reserve_next_available_ip', 'release_ip', - 'delete_network', 'reserve_network', 'release_network', - 'add_network', 'get_network_id'],), - ), required_together=(['username', 'password'],),) - server_ip = my_module.params["server_ip"] - username = my_module.params["username"] - password = my_module.params["password"] - action = my_module.params["action"] - network_id = my_module.params["network_id"] - released_ip = my_module.params["ip_address"] - network_name = my_module.params["network_name"] - network_family = my_module.params["network_family"] - network_type = my_module.params["network_type"] - network_address = my_module.params["network_address"] - network_size = my_module.params["network_size"] - network_location = my_module.params["network_location"] - my_infinity = Infinity(my_module, server_ip, username, password) + module = AnsibleModule( + argument_spec=dict( + server_ip=dict(type='str', required=True), + username=dict(type='str', required=True), + password=dict(type='str', required=True, no_log=True), + network_id=dict(type='str'), + ip_address=dict(type='str'), + network_name=dict(type='str'), + network_location=dict(type='int', default=-1), + network_family=dict(type='str', default='4', choices=['4', '6', 'dual']), + network_type=dict(type='str', default='lan', choices=['lan', 'shared_lan', 'supernet']), + network_address=dict(type='str'), + network_size=dict(type='str'), + action=dict(type='str', required=True, choices=[ + 'add_network', + 'delete_network', + 'get_network', + 'get_network_id', + 'release_ip', + 'release_network', + 'reserve_network', + 'reserve_next_available_ip', + ],), + ), + required_together=( + ['username', 'password'], + ), + ) + server_ip = module.params["server_ip"] + username = module.params["username"] + password = module.params["password"] + action = module.params["action"] + network_id = module.params["network_id"] + released_ip = module.params["ip_address"] + network_name = module.params["network_name"] + network_family = module.params["network_family"] + network_type = module.params["network_type"] + network_address = module.params["network_address"] + network_size = module.params["network_size"] + network_location = module.params["network_location"] + my_infinity = Infinity(module, server_ip, username, password) result = '' if action == "reserve_next_available_ip": if network_id: result = my_infinity.reserve_next_available_ip(network_id) if not result: result = 'There is an error in calling method of reserve_next_available_ip' - my_module.exit_json(changed=False, meta=result) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=False, meta=result) + module.exit_json(changed=True, meta=result) elif action == "release_ip": if network_id and released_ip: result = my_infinity.release_ip( network_id=network_id, ip_address=released_ip) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=True, meta=result) elif action == "delete_network": result = my_infinity.delete_network( network_id=network_id, network_name=network_name) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=True, meta=result) elif action == "get_network_id": result = my_infinity.get_network_id( network_name=network_name, network_type=network_type) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=True, meta=result) elif action == "get_network": result = my_infinity.get_network( network_id=network_id, network_name=network_name) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=True, meta=result) elif action == "reserve_network": result = my_infinity.reserve_network( network_id=network_id, @@ -549,13 +546,13 @@ def main(): reserved_network_family=network_family, reserved_network_type=network_type, reserved_network_address=network_address) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=True, meta=result) elif action == "release_network": result = my_infinity.release_network( network_id=network_id, released_network_name=network_name, released_network_type=network_type) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=True, meta=result) elif action == "add_network": result = my_infinity.add_network( @@ -566,7 +563,7 @@ def main(): network_family=network_family, network_type=network_type) - my_module.exit_json(changed=True, meta=result) + module.exit_json(changed=True, meta=result) if __name__ == '__main__': diff --git a/lib/ansible/modules/net_tools/ipify_facts.py b/lib/ansible/modules/net_tools/ipify_facts.py index 0c3d5b8c55..ae51e33b64 100644 --- a/lib/ansible/modules/net_tools/ipify_facts.py +++ b/lib/ansible/modules/net_tools/ipify_facts.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # -# (c) 2015, René Moser +# Copyright: (c) 2015, René Moser # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function @@ -13,51 +13,51 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'supported_by': 'community'} -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: ipify_facts -short_description: Retrieve the public IP of your internet gateway. +short_description: Retrieve the public IP of your internet gateway description: - If behind NAT and need to know the public IP of your internet gateway. version_added: '2.0' -author: "René Moser (@resmo)" +author: +- René Moser (@resmo) options: api_url: description: - URL of the ipify.org API service. - C(?format=json) will be appended per default. - required: false - default: 'https://api.ipify.org' + type: str + default: https://api.ipify.org/ timeout: description: - HTTP connection timeout in seconds. - required: false + type: int default: 10 version_added: "2.3" validate_certs: description: - When set to C(NO), SSL certificates will not be validated. - required: false - default: "yes" type: bool + default: yes version_added: "2.4" notes: - - "Visit https://www.ipify.org to get more information." + - Visit https://www.ipify.org to get more information. ''' -EXAMPLES = ''' +EXAMPLES = r''' # Gather IP facts from ipify.org -- name: get my public IP +- name: Get my public IP ipify_facts: # Gather IP facts from your own ipify service endpoint with a custom timeout -- name: get my public IP +- name: Get my public IP ipify_facts: api_url: http://api.example.com/ipify timeout: 20 ''' -RETURN = ''' +RETURN = r''' --- ipify_public_ip: description: Public IP of the internet gateway. @@ -97,7 +97,7 @@ def main(): global module module = AnsibleModule( argument_spec=dict( - api_url=dict(default='https://api.ipify.org/'), + api_url=dict(type='str', default='https://api.ipify.org/'), timeout=dict(type='int', default=10), validate_certs=dict(type='bool', default=True), ), diff --git a/lib/ansible/modules/net_tools/ldap/ldap_attr.py b/lib/ansible/modules/net_tools/ldap/ldap_attr.py index 848ec24045..d6c43816c9 100644 --- a/lib/ansible/modules/net_tools/ldap/ldap_attr.py +++ b/lib/ansible/modules/net_tools/ldap/ldap_attr.py @@ -3,24 +3,21 @@ # Copyright: (c) 2016, Peter Sagerson # Copyright: (c) 2016, Jiri Tyr -# # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type - ANSIBLE_METADATA = { 'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community' } - -DOCUMENTATION = """ +DOCUMENTATION = r''' --- module: ldap_attr -short_description: Add or remove LDAP attribute values. +short_description: Add or remove LDAP attribute values description: - Add or remove LDAP attribute values. notes: @@ -47,28 +44,33 @@ options: name: description: - The name of the attribute to modify. + type: str required: true state: description: - - The state of the attribute values. If C(present), all given - values will be added if they're missing. If C(absent), all given - values will be removed if present. If C(exact), the set of values - will be forced to exactly those provided and no others. If - I(state=exact) and I(value) is an empty list, all values for this - attribute will be removed. - choices: [present, absent, exact] + - The state of the attribute values. + - If C(present), all given values will be added if they're missing. + - If C(absent), all given values will be removed if present. + - If C(exact), the set of values will be forced to exactly those provided and no others. + - If I(state=exact) and I(value) is an empty list, all values for this attribute will be removed. + choices: [ absent, exact, present ] default: present values: description: - The value(s) to add or remove. This can be a string or a list of strings. The complex argument format is required in order to pass a list of strings (see examples). + type: raw required: true -extends_documentation_fragment: ldap.documentation -""" + params: + description: + - Additional module parameters. + type: dict +extends_documentation_fragment: +- ldap.documentation +''' - -EXAMPLES = """ +EXAMPLES = r''' - name: Configure directory number 1 for example.com ldap_attr: dn: olcDatabase={1}hdb,cn=config @@ -138,16 +140,15 @@ EXAMPLES = """ values: [] state: exact params: "{{ ldap_auth }}" -""" +''' - -RETURN = """ +RETURN = r''' modlist: description: list of modified parameters returned: success type: list sample: '[[2, "olcRootDN", ["cn=root,dc=example,dc=com"]]]' -""" +''' import traceback @@ -237,12 +238,10 @@ class LdapAttr(LdapGeneric): def main(): module = AnsibleModule( argument_spec=gen_specs( - name=dict(required=True), + name=dict(type='str', required=True), params=dict(type='dict'), - state=dict( - default='present', - choices=['present', 'absent', 'exact']), - values=dict(required=True, type='raw'), + state=dict(type='str', default='present', choices=['absent', 'exact', 'present']), + values=dict(type='raw', required=True), ), supports_check_mode=True, ) @@ -279,8 +278,7 @@ def main(): try: ldap.connection.modify_s(ldap.dn, modlist) except Exception as e: - module.fail_json(msg="Attribute action failed.", details=to_native(e), - exception=traceback.format_exc()) + module.fail_json(msg="Attribute action failed.", details=to_native(e)) module.exit_json(changed=changed, modlist=modlist) diff --git a/lib/ansible/modules/net_tools/omapi_host.py b/lib/ansible/modules/net_tools/omapi_host.py index 9e5df7a4c2..fe11fae6d6 100644 --- a/lib/ansible/modules/net_tools/omapi_host.py +++ b/lib/ansible/modules/net_tools/omapi_host.py @@ -1,104 +1,106 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# (c) 2016, Loic Blot +# copyright: (c) 2016, Loic Blot # Sponsored by Infopro Digital. http://www.infopro-digital.com/ # Sponsored by E.T.A.I. http://www.etai.fr/ -# # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type - ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} - -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: omapi_host - short_description: Setup OMAPI hosts. -description: - - Create, update and remove OMAPI hosts into compatible DHCPd servers. +description: Manage OMAPI hosts into compatible DHCPd servers version_added: "2.3" requirements: - pypureomapi -author: "Loic Blot (@nerzhul)" +author: +- Loic Blot (@nerzhul) options: state: description: - Create or remove OMAPI host. + type: str required: true - choices: ['present', 'absent'] - name: + choices: [ absent, present ] + hostname: description: - Sets the host lease hostname (mandatory if state=present). + type: str + aliases: [ name ] host: description: - Sets OMAPI server host to interact with. + type: str default: localhost port: description: - Sets the OMAPI server port to interact with. + type: int default: 7911 key_name: description: - Sets the TSIG key name for authenticating against OMAPI server. + type: str required: true key: description: - Sets the TSIG key content for authenticating against OMAPI server. + type: str required: true macaddr: description: - Sets the lease host MAC address. + type: str required: true ip: description: - Sets the lease host IP address. + type: str statements: description: - Attach a list of OMAPI DHCP statements with host lease (without ending semicolon). + type: list default: [] ddns: description: - Enable dynamic DNS updates for this host. type: bool - default: 'no' + default: no ''' -EXAMPLES = ''' -- name: Remove a host using OMAPI - omapi_host: - key_name: "defomapi" - key: "+bFQtBCta6j2vWkjPkNFtgA==" - host: "10.1.1.1" - macaddr: "00:66:ab:dd:11:44" - state: absent - +EXAMPLES = r''' - name: Add a host using OMAPI omapi_host: - key_name: "defomapi" - key: "+bFQtBCta6j2vWkjPkNFtgA==" - host: "10.98.4.55" - macaddr: "44:dd:ab:dd:11:44" - name: "server01" - ip: "192.168.88.99" + key_name: defomapi + key: +bFQtBCta6j2vWkjPkNFtgA== + host: 10.98.4.55 + macaddr: 44:dd:ab:dd:11:44 + name: server01 + ip: 192.168.88.99 ddns: yes statements: - - 'filename "pxelinux.0"' - - 'next-server 1.1.1.1' + - filename "pxelinux.0" + - next-server 1.1.1.1 state: present + +- name: Remove a host using OMAPI + omapi_host: + key_name: defomapi + key: +bFQtBCta6j2vWkjPkNFtgA== + host: 10.1.1.1 + macaddr: 00:66:ab:dd:11:44 + state: absent ''' -RETURN = ''' -changed: - description: If module has modified a host - returned: success - type: str +RETURN = r''' lease: description: dictionary containing host information returned: success @@ -212,8 +214,7 @@ class OmapiHostManager: stmt_join += "; ".join(self.module.params['statements']) stmt_join += "; " except TypeError as e: - self.module.fail_json(msg="Invalid statements found: %s" % to_native(e), - exception=traceback.format_exc()) + self.module.fail_json(msg="Invalid statements found: %s" % to_native(e)) if len(stmt_join) > 0: msg.obj.append(('statements', stmt_join)) @@ -225,7 +226,7 @@ class OmapiHostManager: "are valid.") self.module.exit_json(changed=True, lease=self.unpack_facts(response.obj)) except OmapiError as e: - self.module.fail_json(msg="OMAPI error: %s" % to_native(e), exception=traceback.format_exc()) + self.module.fail_json(msg="OMAPI error: %s" % to_native(e)) # Forge update message else: response_obj = self.unpack_facts(host_response.obj) @@ -262,7 +263,7 @@ class OmapiHostManager: "are valid.") self.module.exit_json(changed=True) except OmapiError as e: - self.module.fail_json(msg="OMAPI error: %s" % to_native(e), exception=traceback.format_exc()) + self.module.fail_json(msg="OMAPI error: %s" % to_native(e)) def remove_host(self): try: @@ -271,24 +272,24 @@ class OmapiHostManager: except OmapiErrorNotFound: self.module.exit_json() except OmapiError as e: - self.module.fail_json(msg="OMAPI error: %s" % to_native(e), exception=traceback.format_exc()) + self.module.fail_json(msg="OMAPI error: %s" % to_native(e)) def main(): module = AnsibleModule( argument_spec=dict( - state=dict(required=True, type='str', choices=['present', 'absent']), + state=dict(type='str', required=True, choices=['absent', 'present']), host=dict(type='str', default="localhost"), port=dict(type='int', default=7911), - key_name=dict(required=True, type='str', default=None), - key=dict(required=True, type='str', default=None, no_log=True), - macaddr=dict(required=True, type='str', default=None), - hostname=dict(type='str', default=None, aliases=['name']), - ip=dict(type='str', default=None), + key_name=dict(type='str', required=True), + key=dict(type='str', required=True, no_log=True), + macaddr=dict(type='str', required=True), + hostname=dict(type='str', aliases=['name']), + ip=dict(type='str'), ddns=dict(type='bool', default=False), - statements=dict(type='list', default=[]) + statements=dict(type='list', default=[]), ), - supports_check_mode=False + supports_check_mode=False, ) if not pureomapi_found: @@ -307,7 +308,7 @@ def main(): elif module.params['state'] == 'absent': host_manager.remove_host() except ValueError as e: - module.fail_json(msg="OMAPI input value error: %s" % to_native(e), exception=traceback.format_exc()) + module.fail_json(msg="OMAPI input value error: %s" % to_native(e)) if __name__ == '__main__': diff --git a/lib/ansible/modules/net_tools/snmp_facts.py b/lib/ansible/modules/net_tools/snmp_facts.py index 098aaa0ec5..1178fb9b51 100644 --- a/lib/ansible/modules/net_tools/snmp_facts.py +++ b/lib/ansible/modules/net_tools/snmp_facts.py @@ -1,4 +1,5 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- # This file is part of Networklore's snmp library for Ansible # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) @@ -6,18 +7,17 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type - ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} - -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: snmp_facts version_added: "1.9" -author: "Patrick Ogenstad (@ogenstad)" -short_description: Retrieve facts for a device using SNMP. +author: +- Patrick Ogenstad (@ogenstad) +short_description: Retrieve facts for a device using SNMP description: - Retrieve facts for a device using SNMP, the facts will be inserted to the ansible_facts key. @@ -26,56 +26,64 @@ requirements: options: host: description: - - Set to target snmp server (normally {{inventory_hostname}}) + - Set to target snmp server (normally C({{ inventory_hostname }})). + type: str required: true version: description: - - SNMP Version to use, v2/v2c or v3 - choices: [ 'v2', 'v2c', 'v3' ] + - SNMP Version to use, v2/v2c or v3. + type: str required: true + choices: [ v2, v2c, v3 ] community: description: - - The SNMP community string, required if version is v2/v2c - required: false + - The SNMP community string, required if version is v2/v2c. + type: str level: description: - - Authentication level, required if version is v3 - choices: [ 'authPriv', 'authNoPriv' ] - required: false + - Authentication level. + - Required if version is v3. + type: str + choices: [ authNoPriv, authPriv ] username: description: - - Username for SNMPv3, required if version is v3 - required: false + - Username for SNMPv3. + - Required if version is v3. + type: str integrity: description: - - Hashing algorithm, required if version is v3 - choices: [ 'md5', 'sha' ] - required: false + - Hashing algorithm. + - Required if version is v3. + type: str + choices: [ md5, sha ] authkey: description: - - Authentication key, required if version is v3 - required: false + - Authentication key. + - Required if version is v3. + type: str privacy: description: - - Encryption algorithm, required if level is authPriv - choices: [ 'des', 'aes' ] - required: false + - Encryption algorithm. + - Required if level is authPriv. + type: str + choices: [ aes, des ] privkey: description: - - Encryption key, required if version is authPriv - required: false + - Encryption key. + - Required if version is authPriv. + type: str ''' -EXAMPLES = ''' -# Gather facts with SNMP version 2 -- snmp_facts: +EXAMPLES = r''' +- name: Gather facts with SNMP version 2 + snmp_facts: host: '{{ inventory_hostname }}' version: v2c community: public delegate_to: local -# Gather facts using SNMP version 3 -- snmp_facts: +- name: Gather facts using SNMP version 3 + snmp_facts: host: '{{ inventory_hostname }}' version: v3 level: authPriv @@ -87,7 +95,7 @@ EXAMPLES = ''' delegate_to: localhost ''' -RETURN = ''' +RETURN = r''' ansible_sysdescr: description: A textual description of the entity. returned: success @@ -262,18 +270,22 @@ def lookup_operstatus(int_operstatus): def main(): module = AnsibleModule( argument_spec=dict( - host=dict(required=True), - version=dict(required=True, choices=['v2', 'v2c', 'v3']), - community=dict(required=False, default=False), - username=dict(required=False), - level=dict(required=False, choices=['authNoPriv', 'authPriv']), - integrity=dict(required=False, choices=['md5', 'sha']), - privacy=dict(required=False, choices=['des', 'aes']), - authkey=dict(required=False), - privkey=dict(required=False), - removeplaceholder=dict(required=False)), - required_together=(['username', 'level', 'integrity', 'authkey'], ['privacy', 'privkey'],), - supports_check_mode=False) + host=dict(type='str', required=True), + version=dict(type='str', required=True, choices=['v2', 'v2c', 'v3']), + community=dict(type='str'), + username=dict(type='str'), + level=dict(type='str', choices=['authNoPriv', 'authPriv']), + integrity=dict(type='str', choices=['md5', 'sha']), + privacy=dict(type='str', choices=['aes', 'des']), + authkey=dict(type='str'), + privkey=dict(type='str'), + ), + required_together=( + ['username', 'level', 'integrity', 'authkey'], + ['privacy', 'privkey'], + ), + supports_check_mode=False, + ) m_args = module.params @@ -284,7 +296,7 @@ def main(): # Verify that we receive a community when using snmp v2 if m_args['version'] == "v2" or m_args['version'] == "v2c": - if m_args['community'] is False: + if m_args['community'] is None: module.fail_json(msg='Community not set when using snmp version 2') if m_args['version'] == "v3": diff --git a/test/sanity/validate-modules/ignore.txt b/test/sanity/validate-modules/ignore.txt index 4fffd438f9..b79a4baefd 100644 --- a/test/sanity/validate-modules/ignore.txt +++ b/test/sanity/validate-modules/ignore.txt @@ -437,24 +437,8 @@ lib/ansible/modules/monitoring/sensu_check.py E324 lib/ansible/modules/monitoring/sensu_client.py E324 lib/ansible/modules/monitoring/sensu_handler.py E326 lib/ansible/modules/monitoring/zabbix/zabbix_maintenance.py E317 -lib/ansible/modules/net_tools/basics/get_url.py E322 -lib/ansible/modules/net_tools/basics/get_url.py E324 -lib/ansible/modules/net_tools/basics/slurp.py E322 -lib/ansible/modules/net_tools/basics/uri.py E322 lib/ansible/modules/net_tools/basics/uri.py E323 -lib/ansible/modules/net_tools/basics/uri.py E324 lib/ansible/modules/net_tools/basics/uri.py E326 -lib/ansible/modules/net_tools/cloudflare_dns.py E317 -lib/ansible/modules/net_tools/cloudflare_dns.py E327 -lib/ansible/modules/net_tools/haproxy.py E317 -lib/ansible/modules/net_tools/haproxy.py E324 -lib/ansible/modules/net_tools/infinity/infinity.py E326 -lib/ansible/modules/net_tools/ipify_facts.py E324 -lib/ansible/modules/net_tools/ldap/ldap_attr.py E322 -lib/ansible/modules/net_tools/omapi_host.py E317 -lib/ansible/modules/net_tools/omapi_host.py E322 -lib/ansible/modules/net_tools/snmp_facts.py E322 -lib/ansible/modules/net_tools/snmp_facts.py E324 lib/ansible/modules/network/a10/a10_server_axapi3.py E326 lib/ansible/modules/network/a10/a10_virtual_server.py E324 lib/ansible/modules/network/aci/aci_epg_to_domain.py E325