diff --git a/lib/ansible/module_utils/junos.py b/lib/ansible/module_utils/junos.py
index f7cb8fc001..2d750724b6 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 0000000000..e5f93f7599
--- /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 0000000000..101127bb26
--- /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 0000000000..a4ee4db0b6
--- /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 e0a8509e0b..cd3fd7de6d 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 98c2d7edce..c4ec0bdc18 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 0000000000..e69de29bb2
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 0000000000..5f709c5aac
--- /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 0000000000..cc27f174fd
--- /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 0000000000..1286b35422
--- /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 0000000000..1b015d56da
--- /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 0000000000..5f709c5aac
--- /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 0000000000..46d86dd698
--- /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 0000000000..af08869c92
--- /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 0000000000..1286b35422
--- /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 0000000000..b1bec77f7c
--- /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 0000000000..4e29b0ed28
--- /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 0000000000..53f583253b
--- /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 0000000000..5ff7cf5af8
--- /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'