From 11e72d495dc1b35723a2c1878704a39bb9e32411 Mon Sep 17 00:00:00 2001 From: Ganesh Nalawade Date: Mon, 3 Jul 2017 15:31:59 +0530 Subject: [PATCH] Add net_logging platform agnostic module and junos implementation (#26316) * Add net_logging platform agnostic module and junos implemenatation * net_logging platform agnostic module * junos implemenatation of logging module * net_logging integration test * junos_logging integration test --- lib/ansible/module_utils/junos.py | 56 ++-- .../modules/network/junos/junos_logging.py | 250 +++++++++++++++ .../modules/network/system/net_logging.py | 105 ++++++ lib/ansible/plugins/action/net_logging.py | 26 ++ test/integration/junos.yaml | 1 + test/integration/platform_agnostic.yaml | 1 + .../integration/targets/junos_logging/aliases | 0 .../targets/junos_logging/defaults/main.yaml | 2 + .../targets/junos_logging/tasks/main.yaml | 2 + .../targets/junos_logging/tasks/netconf.yaml | 16 + .../junos_logging/tests/netconf/basic.yaml | 298 ++++++++++++++++++ .../targets/net_logging/defaults/main.yaml | 2 + .../targets/net_logging/tasks/cli.yaml | 16 + .../targets/net_logging/tasks/main.yaml | 3 + .../targets/net_logging/tasks/netconf.yaml | 16 + .../targets/net_logging/tests/cli/basic.yaml | 4 + .../targets/net_logging/tests/eos/basic.yaml | 2 + .../net_logging/tests/junos/basic.yaml | 124 ++++++++ .../net_logging/tests/netconf/basic.yaml | 3 + 19 files changed, 908 insertions(+), 19 deletions(-) create mode 100644 lib/ansible/modules/network/junos/junos_logging.py create mode 100644 lib/ansible/modules/network/system/net_logging.py create mode 100644 lib/ansible/plugins/action/net_logging.py create mode 100644 test/integration/targets/junos_logging/aliases create mode 100644 test/integration/targets/junos_logging/defaults/main.yaml create mode 100644 test/integration/targets/junos_logging/tasks/main.yaml create mode 100644 test/integration/targets/junos_logging/tasks/netconf.yaml create mode 100644 test/integration/targets/junos_logging/tests/netconf/basic.yaml create mode 100644 test/integration/targets/net_logging/defaults/main.yaml create mode 100644 test/integration/targets/net_logging/tasks/cli.yaml create mode 100644 test/integration/targets/net_logging/tasks/main.yaml create mode 100644 test/integration/targets/net_logging/tasks/netconf.yaml create mode 100644 test/integration/targets/net_logging/tests/cli/basic.yaml create mode 100644 test/integration/targets/net_logging/tests/eos/basic.yaml create mode 100644 test/integration/targets/net_logging/tests/junos/basic.yaml create mode 100644 test/integration/targets/net_logging/tests/netconf/basic.yaml diff --git a/lib/ansible/module_utils/junos.py b/lib/ansible/module_utils/junos.py index f7cb8fc0012..2d750724b69 100644 --- a/lib/ansible/module_utils/junos.py +++ b/lib/ansible/module_utils/junos.py @@ -54,12 +54,6 @@ ARGS_DEFAULT_VALUE = { 'timeout': 10 } -OPERATION_LOOK_UP = { - 'absent': 'delete', - 'active': 'active', - 'deactivate': 'inactive' -} - def get_argspec(): return junos_argument_spec @@ -280,9 +274,12 @@ def map_params_to_obj(module, param_to_xpath_map): def map_obj_to_ele(module, want, top, value_map=None): + if not HAS_LXML: + module.fail_json(msg='lxml is not installed.') + + root = Element('root') top_ele = top.split('/') - root = Element(top_ele[0]) - ele = root + ele = SubElement(root, top_ele[0]) if len(top_ele) > 1: for item in top_ele[1:-1]: @@ -302,14 +299,14 @@ def map_obj_to_ele(module, want, top, value_map=None): else: node = container - for xpath, attributes in obj.items(): + for fxpath, attributes in obj.items(): for attr in attributes: tag_only = attr.get('tag_only', False) leaf_only = attr.get('leaf_only', False) is_value = attr.get('value_req', False) is_key = attr.get('is_key', False) value = attr.get('value') - + field_top = attr.get('top') # operation 'delete' is added as element attribute # only if it is key or leaf only node if state == 'absent' and not (is_key or leaf_only): @@ -320,12 +317,34 @@ def map_obj_to_ele(module, want, top, value_map=None): continue # convert param value to device specific value - if value_map and xpath in value_map: - value = value_map[xpath].get(value) + if value_map and fxpath in value_map: + value = value_map[fxpath].get(value) if value or tag_only or leaf_only: ele = node - tags = xpath.split('/') + if field_top: + # eg: top = 'system/syslog/file' + # field_top = 'system/syslog/file/contents' + # + # test + # + # + # + ele_list = root.xpath(top + '/' + field_top) + + if not len(ele_list): + fields = field_top.split('/') + ele = node + for item in fields: + inner_ele = root.xpath(top + '/' + item) + if len(inner_ele): + ele = inner_ele[0] + else: + ele = SubElement(ele, item) + else: + ele = ele_list[0] + + tags = fxpath.split('/') if value: value = to_text(value, errors='surrogate_then_replace') @@ -349,13 +368,12 @@ def map_obj_to_ele(module, want, top, value_map=None): # can result in error, hence the check if is_value: ele.text = value + if is_key: + par = ele.getparent() + par.set('delete', 'delete') else: ele.text = value - - if HAS_LXML: - par = ele.getparent() - else: - module.fail_json(msg='lxml is not installed.') + par = ele.getparent() if state == 'present': # set replace attribute at parent node @@ -368,4 +386,4 @@ def map_obj_to_ele(module, want, top, value_map=None): else: par.set('delete', 'delete') - return root + return root.getchildren()[0] diff --git a/lib/ansible/modules/network/junos/junos_logging.py b/lib/ansible/modules/network/junos/junos_logging.py new file mode 100644 index 00000000000..e5f93f7599e --- /dev/null +++ b/lib/ansible/modules/network/junos/junos_logging.py @@ -0,0 +1,250 @@ +#!/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_logging +version_added: "2.4" +author: "Ganesh Nalawade (@ganeshrn)" +short_description: Manage logging on network devices +description: + - This module provides declarative management of logging + on Juniper JUNOS devices. +options: + dest: + description: + - Destination of the logs. + choices: ['console', 'host', 'file', 'user'] + name: + description: + - If value of C(dest) is I(file) it indicates file-name, + for I(user) it indicates username and for I(host) indicates + the host name to be notified. + facility: + description: + - Set logging facility. + level: + description: + - Set logging severity levels. + collection: + description: List of logging definitions. + purge: + description: + - Purge logging not defined in the collections parameter. + default: no + state: + description: + - State of the logging configuration. + default: present + choices: ['present', 'absent'] + active: + description: + - Specifies whether or not the configuration is active or deactivated + default: True + choices: [True, False] + rotate_frequency: + description: + - Rotate log frequency in minutes, this is applicable if value + of I(dest) is C(file). The acceptable value is in range of 1 to 59. + This controls the frequency after which log file is rotated. + required: false + size: + description: + - Size of the file in archive, this is applicable if value + of I(dest) is C(file). The acceptable value is in range from 65536 to + 1073741824 bytes. + required: false + files: + description: + - Number of files to be archived, this is applicable if value + of I(dest) is C(file). The acceptable value is in range from 1 to 1000. + required: false +""" + +EXAMPLES = """ +- name: configure console logging + junos_logging: + dest: console + facility: any + level: critical + +- name: remove console logging configuration + junos_logging: + dest: console + state: absent + +- name: configure file logging + junos_logging: + dest: file + name: test + facility: pfe + level: error + +- name: configure logging parameter + junos_logging: + files: 30 + size: 65536 + rotate_frequency: 10 +""" + +RETURN = """ +rpc: + description: load-configuration RPC send to the device + returned: when configuration is changed on device + type: string + sample: > + + + + pfe + + + +""" +import collections + +from ansible.module_utils.junos import junos_argument_spec, check_args +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.junos import load_config, map_params_to_obj, map_obj_to_ele + +try: + from lxml.etree import tostring +except ImportError: + from xml.etree.ElementTree import tostring + +USE_PERSISTENT_CONNECTION = True + + +def validate_files(value, module): + if value and not 1 <= value <= 1000: + module.fail_json(msg='files must be between 1 and 1000') + + +def validate_size(value, module): + if value and not 65536 <= value <= 1073741824: + module.fail_json(msg='size must be between 65536 and 1073741824') + + +def validate_rotate_frequency(value, module): + if value and not 1 <= value <= 59: + module.fail_json(msg='rotate_frequency must be between 1 and 59') + + +def validate_param_values(module, obj): + for key in obj: + # validate the param value (if validator func exists) + validator = globals().get('validate_%s' % key) + if callable(validator): + validator(module.params.get(key), module) + + +def main(): + """ main entry point for module execution + """ + argument_spec = dict( + dest=dict(choices=['console', 'host', 'file', 'user']), + name=dict(), + facility=dict(), + level=dict(), + rotate_frequency=dict(type='int'), + size=dict(type='int'), + files=dict(type='int'), + src_addr=dict(), + collection=dict(), + purge=dict(default=False, type='bool'), + state=dict(default='present', choices=['present', 'absent']), + active=dict(default=True, type='bool') + ) + + argument_spec.update(junos_argument_spec) + + required_if = [('dest', 'host', ['name', 'facility', 'level']), + ('dest', 'file', ['name', 'facility', 'level']), + ('dest', 'user', ['name', 'facility', 'level']), + ('dest', 'console', ['facility', 'level'])] + + mutually_exclusive = [('console', 'name')] + + module = AnsibleModule(argument_spec=argument_spec, + required_if=required_if, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True) + + warnings = list() + check_args(module, warnings) + + result = {'changed': False} + + if warnings: + result['warnings'] = warnings + + dest = module.params.get('dest') + if dest == 'console' and module.params.get('name'): + module.fail_json(msg="%s and %s are mutually exclusive" % ('console', 'name')) + + top = 'system/syslog' + is_facility_key = False + field_top = None + if dest: + if dest == 'console': + field_top = dest + is_facility_key = True + else: + field_top = dest + '/contents' + is_facility_key = False + + param_to_xpath_map = collections.OrderedDict() + param_to_xpath_map.update([ + ('name', {'xpath': 'name', 'is_key': True, 'top': dest}), + ('facility', {'xpath': 'name', 'is_key': is_facility_key, 'top': field_top}), + ('level', {'xpath': module.params.get('level'), 'tag_only': True, 'top': field_top}), + ('size', {'xpath': 'size', 'leaf_only': True, 'is_key': True, 'top': 'archive'}), + ('files', {'xpath': 'files', 'leaf_only': True, 'is_key': True, 'top': 'archive'}), + ('rotate_frequency', {'xpath': 'log-rotate-frequency', 'leaf_only': True}), + ]) + + validate_param_values(module, param_to_xpath_map) + + want = list() + want.append(map_params_to_obj(module, param_to_xpath_map)) + ele = map_obj_to_ele(module, want, top) + + kwargs = {'commit': not module.check_mode} + kwargs['action'] = 'replace' + + diff = load_config(module, tostring(ele), warnings, **kwargs) + + if diff: + result.update({ + 'changed': True, + 'diff': {'prepared': diff}, + 'rpc': tostring(ele) + }) + + module.exit_json(**result) + +if __name__ == "__main__": + main() diff --git a/lib/ansible/modules/network/system/net_logging.py b/lib/ansible/modules/network/system/net_logging.py new file mode 100644 index 00000000000..101127bb269 --- /dev/null +++ b/lib/ansible/modules/network/system/net_logging.py @@ -0,0 +1,105 @@ +#!/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: net_logging +version_added: "2.4" +author: "Ganesh Nalawade (@ganeshrn)" +short_description: Manage logging on network devices +description: + - This module provides declarative management of logging + on network devices. +options: + dest: + description: + - Destination of the logs. + choices: ['console', 'host'] + name: + description: + - If value of C(dest) is I(host) it indicates file-name + the host name to be notified. + facility: + description: + - Set logging facility. + level: + description: + - Set logging severity levels. + collection: + description: List of logging definitions. + purge: + description: + - Purge logging not defined in the collections parameter. + default: no + state: + description: + - State of the logging configuration. + default: present + choices: ['present', 'absent'] +""" + +EXAMPLES = """ +- name: configure console logging + net_logging: + dest: console + facility: any + level: critical + +- name: remove console logging configuration + net_logging: + dest: console + state: absent + +- name: configure host logging + net_logging: + dest: host + name: 1.1.1.1 + facility: kernel + level: critical +""" + +RETURN = """ +commands: + description: The list of configuration mode commands to send to the device + returned: always + type: list + sample: + - logging console critical + +rpc: + description: load-configuration RPC send to the device + returned: C(rpc) is returned only for junos device + when configuration is changed on device + type: string + sample: > + + + + pfe + + + +""" diff --git a/lib/ansible/plugins/action/net_logging.py b/lib/ansible/plugins/action/net_logging.py new file mode 100644 index 00000000000..a4ee4db0b6e --- /dev/null +++ b/lib/ansible/plugins/action/net_logging.py @@ -0,0 +1,26 @@ +# (c) 2017, Ansible Inc, +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.plugins.action.net_base import ActionModule as _ActionModule + + +class ActionModule(_ActionModule): + def run(self, tmp=None, task_vars=None): + result = super(ActionModule, self).run(tmp, task_vars) + return result diff --git a/test/integration/junos.yaml b/test/integration/junos.yaml index e0a8509e0b5..cd3fd7de6d9 100644 --- a/test/integration/junos.yaml +++ b/test/integration/junos.yaml @@ -18,3 +18,4 @@ - { role: junos_interface, when: "limit_to in ['*', 'junos_interface']" } - { role: junos_banner, when: "limit_to in ['*', 'junos_banner']" } - { role: junos_system, when: "limit_to in ['*', 'junos_system']" } + - { role: junos_logging, when: "limit_to in ['*', 'junos_logging']" } diff --git a/test/integration/platform_agnostic.yaml b/test/integration/platform_agnostic.yaml index 98c2d7edced..c4ec0bdc187 100644 --- a/test/integration/platform_agnostic.yaml +++ b/test/integration/platform_agnostic.yaml @@ -16,3 +16,4 @@ - { role: net_vrf, when: "limit_to in ['*', 'net_vrf']" } - { role: net_interface, when: "limit_to in ['*', 'net_interface']" } - { role: net_static_route, when: "limit_to in ['*', 'net_static_route']" } + - { role: net_logging, when: "limit_to in ['*', 'net_logging']" } diff --git a/test/integration/targets/junos_logging/aliases b/test/integration/targets/junos_logging/aliases new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/integration/targets/junos_logging/defaults/main.yaml b/test/integration/targets/junos_logging/defaults/main.yaml new file mode 100644 index 00000000000..5f709c5aac1 --- /dev/null +++ b/test/integration/targets/junos_logging/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" diff --git a/test/integration/targets/junos_logging/tasks/main.yaml b/test/integration/targets/junos_logging/tasks/main.yaml new file mode 100644 index 00000000000..cc27f174fd8 --- /dev/null +++ b/test/integration/targets/junos_logging/tasks/main.yaml @@ -0,0 +1,2 @@ +--- +- { include: netconf.yaml, tags: ['netconf'] } diff --git a/test/integration/targets/junos_logging/tasks/netconf.yaml b/test/integration/targets/junos_logging/tasks/netconf.yaml new file mode 100644 index 00000000000..1286b354228 --- /dev/null +++ b/test/integration/targets/junos_logging/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_logging/tests/netconf/basic.yaml b/test/integration/targets/junos_logging/tests/netconf/basic.yaml new file mode 100644 index 00000000000..1b015d56da7 --- /dev/null +++ b/test/integration/targets/junos_logging/tests/netconf/basic.yaml @@ -0,0 +1,298 @@ +--- +- debug: msg="START junos_logging netconf/basic.yaml" + +- name: setup - remove file logging + junos_logging: + dest: file + name: test + facility: pfe + level: error + state: absent + provider: "{{ netconf }}" + +- name: Create file logging + junos_logging: + dest: file + name: test_file + facility: pfe + level: error + state: present + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'test_file' in config.xml" + - "'pfe' in config.xml" + - "'' in config.xml" + +- name: Create file logging (idempotent) + junos_logging: + dest: file + name: test_file + facility: pfe + level: error + state: present + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" + +- name: Deactivate logging configuration + junos_logging: + dest: file + name: test_file + facility: pfe + level: error + state: present + active: False + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'' in config.xml" + - "'' in config.xml" + +- name: Activate logging configuration + junos_logging: + dest: file + name: test_file + facility: pfe + level: error + state: present + active: True + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'test_file' in config.xml" + - "'pfe' in config.xml" + - "'' in config.xml" + +- name: Delete logging configuration + junos_logging: + dest: file + name: test_file + facility: pfe + level: error + state: absent + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'test_file' not in config.xml" + +- name: Configure console logging + junos_logging: + dest: console + facility: kernel + level: emergency + state: present + active: True + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'' in config.xml" + - "'kernel' in config.xml" + - "'' in config.xml" + +- name: Configure console logging (idempotent) + junos_logging: + dest: console + facility: kernel + level: emergency + state: present + active: True + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" + +- name: Disable console logging + junos_logging: + dest: console + facility: kernel + level: emergency + state: present + active: False + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'' in config.xml" + +- name: Delete console logging + junos_logging: + dest: console + facility: kernel + level: emergency + state: absent + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'' not in config.xml" + +- name: Configure logging parameters + junos_logging: + size: 65536 + files: 40 + rotate_frequency: 20 + state: present + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'64k' in config.xml" + - "'40' in config.xml" + - "'20' in config.xml" + +- name: Configure logging parameters (idempotent) + junos_logging: + size: 65536 + files: 40 + rotate_frequency: 20 + state: present + active: True + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" + +- name: Disable logging parameters + junos_logging: + size: 65536 + files: 40 + rotate_frequency: 20 + state: present + active: False + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'64k' in config.xml" + - "'40' in config.xml" + - "'20' in config.xml" + +- name: Activate logging parameters + junos_logging: + size: 65536 + files: 40 + rotate_frequency: 20 + state: present + active: True + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'64k' in config.xml" + - "'40' in config.xml" + - "'20' in config.xml" + +- name: Delete logging parameters + junos_logging: + size: 65536 + files: 40 + rotate_frequency: 20 + state: absent + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'64k' not in config.xml" + - "'40' not in config.xml" + - "'20' not in config.xml" diff --git a/test/integration/targets/net_logging/defaults/main.yaml b/test/integration/targets/net_logging/defaults/main.yaml new file mode 100644 index 00000000000..5f709c5aac1 --- /dev/null +++ b/test/integration/targets/net_logging/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" diff --git a/test/integration/targets/net_logging/tasks/cli.yaml b/test/integration/targets/net_logging/tasks/cli.yaml new file mode 100644 index 00000000000..46d86dd6988 --- /dev/null +++ b/test/integration/targets/net_logging/tasks/cli.yaml @@ -0,0 +1,16 @@ +--- +- name: collect all cli test cases + find: + paths: "{{ role_path }}/tests/cli" + 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/net_logging/tasks/main.yaml b/test/integration/targets/net_logging/tasks/main.yaml new file mode 100644 index 00000000000..af08869c922 --- /dev/null +++ b/test/integration/targets/net_logging/tasks/main.yaml @@ -0,0 +1,3 @@ +--- +- { include: cli.yaml, tags: ['cli'] } +- { include: netconf.yaml, tags: ['netconf'] } diff --git a/test/integration/targets/net_logging/tasks/netconf.yaml b/test/integration/targets/net_logging/tasks/netconf.yaml new file mode 100644 index 00000000000..1286b354228 --- /dev/null +++ b/test/integration/targets/net_logging/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/net_logging/tests/cli/basic.yaml b/test/integration/targets/net_logging/tests/cli/basic.yaml new file mode 100644 index 00000000000..b1bec77f7ca --- /dev/null +++ b/test/integration/targets/net_logging/tests/cli/basic.yaml @@ -0,0 +1,4 @@ +--- + +- include: "{{ role_path }}/tests/eos/basic.yaml" + when: hostvars[inventory_hostname]['ansible_network_os'] == 'eos' diff --git a/test/integration/targets/net_logging/tests/eos/basic.yaml b/test/integration/targets/net_logging/tests/eos/basic.yaml new file mode 100644 index 00000000000..4e29b0ed282 --- /dev/null +++ b/test/integration/targets/net_logging/tests/eos/basic.yaml @@ -0,0 +1,2 @@ +--- +- debug: msg="START net_logging eos/basic.yaml" \ No newline at end of file diff --git a/test/integration/targets/net_logging/tests/junos/basic.yaml b/test/integration/targets/net_logging/tests/junos/basic.yaml new file mode 100644 index 00000000000..53f583253bc --- /dev/null +++ b/test/integration/targets/net_logging/tests/junos/basic.yaml @@ -0,0 +1,124 @@ +--- +- debug: msg="START net_logging junos/basic.yaml" + +- name: setup - remove host logging + net_logging: + dest: host + name: 1.1.1.1 + facility: pfe + level: critical + state: absent + provider: "{{ netconf }}" + +- name: Create file logging + net_logging: + dest: host + name: 1.1.1.1 + facility: pfe + level: critical + state: present + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'1.1.1.1' in config.xml" + - "'pfe' in config.xml" + - "'' in config.xml" + +- name: Create file logging (idempotent) + net_logging: + dest: host + name: 1.1.1.1 + facility: pfe + level: critical + state: present + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" + +- name: Delete logging configuration + net_logging: + dest: host + name: 1.1.1.1 + facility: pfe + level: critical + state: absent + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'1.1.1.1' not in config.xml" + +- name: Configure console logging + net_logging: + dest: console + facility: kernel + level: emergency + state: present + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'' in config.xml" + - "'kernel' in config.xml" + - "'' in config.xml" + +- name: Configure console logging (idempotent) + junos_logging: + dest: console + facility: kernel + level: emergency + state: present + provider: "{{ netconf }}" + register: result + +- assert: + that: + - "result.changed == false" + +- name: Delete console logging + net_logging: + dest: console + facility: kernel + level: emergency + state: absent + provider: "{{ netconf }}" + register: result + +- name: Get running configuration + junos_rpc: + rpc: get-configuration + provider: "{{ netconf }}" + register: config + +- assert: + that: + - "result.changed == true" + - "'' not in config.xml" diff --git a/test/integration/targets/net_logging/tests/netconf/basic.yaml b/test/integration/targets/net_logging/tests/netconf/basic.yaml new file mode 100644 index 00000000000..5ff7cf5af8e --- /dev/null +++ b/test/integration/targets/net_logging/tests/netconf/basic.yaml @@ -0,0 +1,3 @@ +--- +- include: "{{ role_path }}/tests/junos/basic.yaml" + when: hostvars[inventory_hostname]['ansible_network_os'] == 'junos'