diff --git a/lib/ansible/module_utils/junos.py b/lib/ansible/module_utils/junos.py index af93f276ce..e8eeda2e20 100644 --- a/lib/ansible/module_utils/junos.py +++ b/lib/ansible/module_utils/junos.py @@ -303,10 +303,6 @@ def map_obj_to_ele(module, want, top, value_map=None): if state == 'absent' and not (is_key or leaf_only): continue - # for tag only node if value is false continue to next attr - if tag_only and not value: - continue - # convert param value to device specific value if value_map and fxpath in value_map: value = value_map[fxpath].get(value) @@ -335,12 +331,13 @@ def map_obj_to_ele(module, want, top, value_map=None): else: ele = ele_list[0] - tags = fxpath.split('/') - if value is not None: + if value is not None and not isinstance(value, bool): value = to_text(value, errors='surrogate_then_replace') - for item in tags: - ele = SubElement(ele, item) + if fxpath: + tags = fxpath.split('/') + for item in tags: + ele = SubElement(ele, item) if tag_only: if state == 'present': diff --git a/lib/ansible/modules/network/junos/junos_interface.py b/lib/ansible/modules/network/junos/junos_interface.py index 1b6d73f896..9f922ddaf8 100644 --- a/lib/ansible/modules/network/junos/junos_interface.py +++ b/lib/ansible/modules/network/junos/junos_interface.py @@ -216,7 +216,6 @@ def main(): if state in ('present', 'up', 'down'): module.params['state'] = 'present' - else: module.params['disable'] = True diff --git a/lib/ansible/modules/network/junos/junos_linkagg.py b/lib/ansible/modules/network/junos/junos_linkagg.py index dd58fbc187..824208b30f 100644 --- a/lib/ansible/modules/network/junos/junos_linkagg.py +++ b/lib/ansible/modules/network/junos/junos_linkagg.py @@ -314,7 +314,7 @@ def main(): module.params['disable'] = True if module.params.get('mode') == 'off': - module.params['mode'] = False + module.params['mode'] = '' elif module.params.get('mode') == 'on': module.params['mode'] = 'passive' diff --git a/lib/ansible/modules/network/junos/junos_lldp.py b/lib/ansible/modules/network/junos/junos_lldp.py new file mode 100644 index 0000000000..313bbaa0c2 --- /dev/null +++ b/lib/ansible/modules/network/junos/junos_lldp.py @@ -0,0 +1,144 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible by Red Hat +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +ANSIBLE_METADATA = {'metadata_version': '1.0', + 'status': ['preview'], + 'supported_by': 'core'} + + +DOCUMENTATION = """ +--- +module: junos_lldp +version_added: "2.4" +author: "Ganesh Nalawade (@ganeshrn)" +short_description: Manage LLDP configuration on Juniper JUNOS network devices +description: + - This module provides declarative management of LLDP service + on Juniper JUNOS network devices. +options: + state: + description: + - State of the LLDP configuration. + default: present + choices: ['present', 'absent'] + active: + description: + - Specifies whether or not the configuration is active or deactivated + default: True + choices: [True, False] +requirements: + - ncclient (>=v0.5.2) +notes: + - This module requires the netconf system service be enabled on + the remote device being managed +""" + +EXAMPLES = """ +- name: Enable LLDP service + junos_lldp: + state: present + +- name: Disable LLDP service + vyos_lldp: + state: absent +""" + +RETURN = """ +diff.prepared: + description: Configuration difference before and after applying change. + returned: when configuration is changed and diff option is enabled. + type: string + sample: > + [edit] + + protocols { + + lldp { + + disable; + + } + + } +""" +import collections + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.junos import junos_argument_spec, check_args +from ansible.module_utils.junos import load_config, map_params_to_obj, map_obj_to_ele +from ansible.module_utils.junos import commit_configuration, discard_changes, locked_config + +try: + from lxml.etree import tostring +except ImportError: + from xml.etree.ElementTree import tostring + +USE_PERSISTENT_CONNECTION = True + + +def main(): + """ main entry point for module execution + """ + argument_spec = dict( + purge=dict(default=False, type='bool'), + state=dict(default='present', choices=['present', 'absent']), + ) + + argument_spec.update(junos_argument_spec) + + module = AnsibleModule(argument_spec=argument_spec, + supports_check_mode=True) + + warnings = list() + check_args(module, warnings) + + result = {'changed': False} + + if warnings: + result['warnings'] = warnings + + top = 'protocols/lldp' + + param_to_xpath_map = collections.OrderedDict() + param_to_xpath_map.update([ + ('disable', {'xpath': 'disable', 'tag_only': True, 'is_key': True}) + ]) + + state = module.params.get('state') + module.params['disable'] = True if state == 'absent' else False + + want = map_params_to_obj(module, param_to_xpath_map) + ele = map_obj_to_ele(module, want, top) + + with locked_config(module): + diff = load_config(module, tostring(ele), warnings, action='replace') + + commit = not module.check_mode + if diff: + if commit: + commit_configuration(module) + else: + discard_changes(module) + result['changed'] = True + + if module._diff: + result['diff'] = {'prepared': diff} + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/test/integration/junos.yaml b/test/integration/junos.yaml index 2a8bf329cc..eb44bdf0df 100644 --- a/test/integration/junos.yaml +++ b/test/integration/junos.yaml @@ -120,6 +120,13 @@ rescue: - set_fact: test_failed=true + - block: + - include_role: + name: junos_lldp + when: "limit_to in ['*', 'junos_lldp']" + rescue: + - set_fact: test_failed=true + ########### - name: Has any previous test failed? fail: diff --git a/test/integration/targets/junos_interface/tests/netconf/basic.yaml b/test/integration/targets/junos_interface/tests/netconf/basic.yaml index 1a84965d37..b08b6244cd 100644 --- a/test/integration/targets/junos_interface/tests/netconf/basic.yaml +++ b/test/integration/targets/junos_interface/tests/netconf/basic.yaml @@ -145,7 +145,7 @@ - assert: that: - "result.changed == true" - - "'' not in config.xml" + - "'[edit interfaces ge-0/0/1]\n- disable;' in result.diff.prepared" - "'ge-0/0/1' in config.xml" - name: Delete interface diff --git a/test/integration/targets/junos_lldp/defaults/main.yaml b/test/integration/targets/junos_lldp/defaults/main.yaml new file mode 100644 index 0000000000..5f709c5aac --- /dev/null +++ b/test/integration/targets/junos_lldp/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" diff --git a/test/integration/targets/junos_lldp/tasks/main.yaml b/test/integration/targets/junos_lldp/tasks/main.yaml new file mode 100644 index 0000000000..cc27f174fd --- /dev/null +++ b/test/integration/targets/junos_lldp/tasks/main.yaml @@ -0,0 +1,2 @@ +--- +- { include: netconf.yaml, tags: ['netconf'] } diff --git a/test/integration/targets/junos_lldp/tasks/netconf.yaml b/test/integration/targets/junos_lldp/tasks/netconf.yaml new file mode 100644 index 0000000000..1286b35422 --- /dev/null +++ b/test/integration/targets/junos_lldp/tasks/netconf.yaml @@ -0,0 +1,16 @@ +--- +- name: collect all netconf test cases + find: + paths: "{{ role_path }}/tests/netconf" + patterns: "{{ testcase }}.yaml" + register: test_cases + delegate_to: localhost + +- name: set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: run test case + include: "{{ test_case_to_run }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/test/integration/targets/junos_lldp/tests/netconf/basic.yaml b/test/integration/targets/junos_lldp/tests/netconf/basic.yaml new file mode 100644 index 0000000000..5d6dc2ae48 --- /dev/null +++ b/test/integration/targets/junos_lldp/tests/netconf/basic.yaml @@ -0,0 +1,49 @@ +--- +- debug: msg="START junos_lldp netconf/basic.yaml" + +- name: setup - remove lldp + junos_lldp: + state: absent + provider: "{{ netconf }}" + +- name: configure lldp + junos_lldp: + state: present + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == true" + - "'[edit]\n- protocols {\n- lldp {\n- disable;\n- }\n- }' in result.diff.prepared" + +- name: configure lldp (idempotent) + junos_lldp: + state: present + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" + +- name: Disable lldp + junos_lldp: + state: absent + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == true" + - "'[edit]\n+ protocols {\n+ lldp {\n+ disable;\n+ }\n+ }' in result.diff.prepared" + +- name: Disable lldp (idempotent) + junos_lldp: + state: absent + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" diff --git a/test/integration/targets/net_lldp/tests/junos/basic.yaml b/test/integration/targets/net_lldp/tests/junos/basic.yaml new file mode 100644 index 0000000000..037765fb76 --- /dev/null +++ b/test/integration/targets/net_lldp/tests/junos/basic.yaml @@ -0,0 +1,50 @@ +--- +- debug: msg="START net_lldp junos/basic.yaml" + + +- name: setup - remove lldp + net_lldp: + state: absent + provider: "{{ netconf }}" + +- name: configure lldp + net_lldp: + state: present + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == true" + - "'[edit]\n- protocols {\n- lldp {\n- disable;\n- }\n- }' in result.diff.prepared" + +- name: configure lldp (idempotent) + net_lldp: + state: present + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" + +- name: Disable lldp + net_lldp: + state: absent + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == true" + - "'[edit]\n+ protocols {\n+ lldp {\n+ disable;\n+ }\n+ }' in result.diff.prepared" + +- name: Disable lldp (idempotent) + net_lldp: + state: absent + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" diff --git a/test/integration/targets/net_lldp/tests/netconf/basic.yaml b/test/integration/targets/net_lldp/tests/netconf/basic.yaml new file mode 100644 index 0000000000..5ff7cf5af8 --- /dev/null +++ b/test/integration/targets/net_lldp/tests/netconf/basic.yaml @@ -0,0 +1,3 @@ +--- +- include: "{{ role_path }}/tests/junos/basic.yaml" + when: hostvars[inventory_hostname]['ansible_network_os'] == 'junos'