Add [junos_l2_interfaces] resource module (#59693)

* Add [junos_l2_interfaces] resource module

*  Add new resource module junos_lag_interfaces.
*  Targets model https://github.com/ansible-network/resource_module_models/pull/12
*  Deprecate junos_l2_interface module

* Fix CI failures

* Fix CI issues
This commit is contained in:
Ganesh Nalawade 2019-08-09 13:09:19 +05:30 committed by GitHub
parent df59f06d6a
commit 309a58eafd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 1241 additions and 19 deletions

View file

@ -10,9 +10,10 @@ CHOICES = [
'all',
'interfaces',
'lag_interfaces',
'l2_interfaces',
'l3_interfaces',
'lldp_interfaces',
'vlans'
'vlans',
]

View file

@ -0,0 +1,49 @@
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#############################################
# WARNING #
#############################################
#
# This file is auto generated by the resource
# module builder playbook.
#
# Do not edit this file manually.
#
# Changes to this file will be over written
# by the resource module builder.
#
# Changes should be made in the model used to
# generate this file or in the resource module
# builder template.
#
#############################################
"""
The arg spec for the junos_l2_interfaces module
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
class L2_interfacesArgs(object):
"""The arg spec for the junos_l2_interfaces module
"""
def __init__(self, **kwargs):
pass
argument_spec = {'config': {'elements': 'dict',
'options': {'access': {'type': 'dict', 'options': {'vlan': {'type': 'str'}}},
'name': {'required': True, 'type': 'str'},
'trunk': {'type': 'dict', 'options': {'allowed_vlans': {'type': 'list'},
'native_vlan': {'type': 'str'}}},
'unit': {'type': 'int'},
'enhanced_layer': {'type': 'bool'}},
'type': 'list'},
'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
'default': 'merged',
'type': 'str'}}

View file

@ -0,0 +1,255 @@
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
The junos_l2_interfaces class
It is in this file where the current configuration (as dict)
is compared to the provided configuration (as dict) and the command set
necessary to bring the current configuration to it's desired end-state is
created
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.module_utils.network.common.utils import to_list
from ansible.module_utils.network.common.cfg.base import ConfigBase
from ansible.module_utils.network.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring
from ansible.module_utils.network.junos.facts.facts import Facts
from ansible.module_utils.network.common.netconf import build_root_xml_node, build_child_xml_node, build_subtree
class L2_interfaces(ConfigBase):
"""
The junos_l2_interfaces class
"""
gather_subset = [
'!all',
'!min',
]
gather_network_resources = [
'l2_interfaces',
]
def __init__(self, module):
super(L2_interfaces, self).__init__(module)
def get_l2_interfaces_facts(self):
""" Get the 'facts' (the current configuration)
:rtype: A dictionary
:returns: The current configuration as a dictionary
"""
facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources)
l2_interfaces_facts = facts['ansible_network_resources'].get('l2_interfaces')
if not l2_interfaces_facts:
return []
return l2_interfaces_facts
def execute_module(self):
""" Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
result = {'changed': False}
existing_l2_interfaces_facts = self.get_l2_interfaces_facts()
config_xmls = self.set_config(existing_l2_interfaces_facts)
with locked_config(self._module):
for config_xml in to_list(config_xmls):
diff = load_config(self._module, config_xml, [])
commit = not self._module.check_mode
if diff:
if commit:
commit_configuration(self._module)
else:
discard_changes(self._module)
result['changed'] = True
if self._module._diff:
result['diff'] = {'prepared': diff}
result['xml'] = config_xmls
changed_l2_interfaces_facts = self.get_l2_interfaces_facts()
result['before'] = existing_l2_interfaces_facts
if result['changed']:
result['after'] = changed_l2_interfaces_facts
return result
def set_config(self, existing_l2_interfaces_facts):
""" Collect the configuration from the args passed to the module,
collect the current configuration (as a dict from facts)
:rtype: A list
:returns: the commands necessary to migrate the current configuration
to the desired configuration
"""
want = self._module.params['config']
have = existing_l2_interfaces_facts
resp = self.set_state(want, have)
return to_list(resp)
def set_state(self, want, have):
""" Select the appropriate function based on the state provided
:param want: the desired configuration as a dictionary
:param have: the current configuration as a dictionary
:rtype: A list
:returns: the list xml configuration necessary to migrate the current configuration
to the desired configuration
"""
root = build_root_xml_node('interfaces')
state = self._module.params['state']
if state == 'overridden':
config_xmls = self._state_overridden(want, have)
elif state == 'deleted':
config_xmls = self._state_deleted(want, have)
elif state == 'merged':
config_xmls = self._state_merged(want, have)
elif state == 'replaced':
config_xmls = self._state_replaced(want, have)
for xml in config_xmls:
root.append(xml)
return tostring(root)
def _state_replaced(self, want, have):
""" The xml configuration generator when state is replaced
:rtype: A list
:returns: the xml configuration necessary to migrate the current configuration
to the desired configuration
"""
l2_intf_xml = []
l2_intf_xml.extend(self._state_deleted(want, have))
l2_intf_xml.extend(self._state_merged(want, have))
return l2_intf_xml
def _state_overridden(self, want, have):
""" The xml configuration generator when state is overridden
:rtype: A list
:returns: the xml configuration necessary to migrate the current configuration
to the desired configuration
"""
l2_interface_xmls_obj = []
# replace interface config with data in want
l2_interface_xmls_obj.extend(self._state_replaced(want, have))
# delete interface config if interface in have not present in want
delete_obj = []
for have_obj in have:
for want_obj in want:
if have_obj['name'] == want_obj['name']:
break
else:
delete_obj.append(have_obj)
if delete_obj:
l2_interface_xmls_obj.extend(self._state_deleted(delete_obj, have))
return l2_interface_xmls_obj
def _state_merged(self, want, have):
""" The xml configuration generator when state is merged
:rtype: A list
:returns: the xml configuration necessary to merge the provided into
the current configuration
"""
intf_xml = []
for config in want:
enhanced_layer = True
if config.get('enhanced_layer') is False:
enhanced_layer = False
mode = 'interface-mode' if enhanced_layer else 'port-mode'
intf = build_root_xml_node('interface')
build_child_xml_node(intf, 'name', config['name'])
unit_node = build_child_xml_node(intf, 'unit')
unit = config['unit'] if config['unit'] else '0'
build_child_xml_node(unit_node, 'name', unit)
eth_node = build_subtree(unit_node, 'family/ethernet-switching')
if config.get('access'):
vlan = config['access'].get('vlan')
if vlan:
build_child_xml_node(eth_node, mode, 'access')
vlan_node = build_child_xml_node(eth_node, 'vlan')
build_child_xml_node(vlan_node, 'members', vlan)
intf_xml.append(intf)
elif config.get('trunk'):
allowed_vlans = config['trunk'].get('allowed_vlans')
native_vlan = config['trunk'].get('native_vlan')
if allowed_vlans:
build_child_xml_node(eth_node, mode, 'trunk')
vlan_node = build_child_xml_node(eth_node, 'vlan')
for vlan in allowed_vlans:
build_child_xml_node(vlan_node, 'members', vlan)
if native_vlan:
build_child_xml_node(intf, 'native-vlan-id', native_vlan)
if allowed_vlans or native_vlan:
intf_xml.append(intf)
return intf_xml
def _state_deleted(self, want, have):
""" The xml configuration generator when state is deleted
:rtype: A list
:returns: the xml configuration necessary to remove the current configuration
of the provided objects
"""
l2_intf_xml = []
l2_intf_obj = want
config_filter = """
<configuration>
<interfaces/>
</configuration>
"""
data = self._connection.get_configuration(filter=config_filter)
if not l2_intf_obj:
# delete l2 interfaces attribute from all the existing interface having l2 config
l2_intf_obj = have
for config in l2_intf_obj:
name = config['name']
enhanced_layer = True
l2_mode = data.xpath("configuration/interfaces/interface[name='%s']/unit/family/ethernet-switching/interface-mode" % name)
if not len(l2_mode):
l2_mode = data.xpath("configuration/interfaces/interface[name='%s']/unit/family/ethernet-switching/port-mode" % name)
enhanced_layer = False
if len(l2_mode):
mode = 'interface-mode' if enhanced_layer else 'port-mode'
intf = build_root_xml_node('interface')
build_child_xml_node(intf, 'name', name)
unit_node = build_child_xml_node(intf, 'unit')
unit = config['unit'] if config['unit'] else '0'
build_child_xml_node(unit_node, 'name', unit)
eth_node = build_subtree(unit_node, 'family/ethernet-switching')
build_child_xml_node(eth_node, mode, None, {'delete': 'delete'})
build_child_xml_node(eth_node, 'vlan', None, {'delete': 'delete'})
build_child_xml_node(intf, 'native-vlan-id', None, {'delete': 'delete'})
l2_intf_xml.append(intf)
return l2_intf_xml

View file

@ -17,6 +17,7 @@ from ansible.module_utils.network.junos.facts.lag_interfaces.lag_interfaces impo
from ansible.module_utils.network.junos.facts.l3_interfaces.l3_interfaces import L3_interfacesFacts
from ansible.module_utils.network.junos.facts.lldp_interfaces.lldp_interfaces import Lldp_interfacesFacts
from ansible.module_utils.network.junos.facts.vlans.vlans import VlansFacts
from ansible.module_utils.network.junos.facts.l2_interfaces.l2_interfaces import L2_interfacesFacts
FACT_LEGACY_SUBSETS = dict(
default=Default,
@ -27,6 +28,7 @@ FACT_LEGACY_SUBSETS = dict(
FACT_RESOURCE_SUBSETS = dict(
interfaces=InterfacesFacts,
lag_interfaces=Lag_interfacesFacts,
l2_interfaces=L2_interfacesFacts,
l3_interfaces=L3_interfacesFacts,
lldp_interfaces=Lldp_interfacesFacts,
vlans=VlansFacts,

View file

@ -0,0 +1,123 @@
#
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""
The junos l2_interfaces fact class
It is in this file the configuration is collected from the device
for a given resource, parsed, and the facts tree is populated
based on the configuration.
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from copy import deepcopy
from ansible.module_utils._text import to_bytes
from ansible.module_utils.network.common import utils
from ansible.module_utils.network.junos.argspec.l2_interfaces.l2_interfaces import L2_interfacesArgs
from ansible.module_utils.six import string_types
try:
from lxml import etree
HAS_LXML = True
except ImportError:
HAS_LXML = False
class L2_interfacesFacts(object):
""" The junos l2_interfaces fact class
"""
def __init__(self, module, subspec='config', options='options'):
self._module = module
self.argument_spec = L2_interfacesArgs.argument_spec
spec = deepcopy(self.argument_spec)
if subspec:
if options:
facts_argument_spec = spec[subspec][options]
else:
facts_argument_spec = spec[subspec]
else:
facts_argument_spec = spec
self.generated_spec = utils.generate_dict(facts_argument_spec)
def populate_facts(self, connection, ansible_facts, data=None):
""" Populate the facts for interfaces
:param connection: the device connection
:param data: previously collected configuration as lxml ElementTree root instance
or valid xml sting
:rtype: dictionary
:returns: facts
"""
if not HAS_LXML:
self._module.fail_json(msg='lxml is not installed.')
if not data:
config_filter = """
<configuration>
<interfaces/>
</configuration>
"""
data = connection.get_configuration(filter=config_filter)
if isinstance(data, string_types):
data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace'))
self._resources = data.xpath('configuration/interfaces/interface')
objs = []
for resource in self._resources:
if resource is not None:
obj = self.render_config(self.generated_spec, resource)
if obj:
objs.append(obj)
facts = {}
if objs:
facts['l2_interfaces'] = []
params = utils.validate_config(self.argument_spec, {'config': objs})
for cfg in params['config']:
facts['l2_interfaces'].append(utils.remove_empties(cfg))
ansible_facts['ansible_network_resources'].update(facts)
return ansible_facts
def render_config(self, spec, conf):
"""`
Render config as dictionary structure and delete keys
from spec for null values
:param spec: The facts tree, generated from the argspec
:param conf: The ElementTree instance of configuration object
:rtype: dictionary
:returns: The generated config
"""
config = deepcopy(spec)
enhanced_layer = True
mode = utils.get_xml_conf_arg(conf, 'unit/family/ethernet-switching/interface-mode')
if mode is None:
mode = utils.get_xml_conf_arg(conf, 'unit/family/ethernet-switching/port-mode')
enhanced_layer = False
# Layer 2 is configured on interface
if mode:
config['name'] = utils.get_xml_conf_arg(conf, 'name')
unit = utils.get_xml_conf_arg(conf, 'unit/name')
config['unit'] = unit if unit else 0
config['enhanced_layer'] = enhanced_layer
if mode == 'access':
config['access'] = {}
config['access']['vlan'] = utils.get_xml_conf_arg(conf, "unit/family/ethernet-switching/vlan/members")
elif mode == 'trunk':
config['trunk'] = {}
vlan_members = conf.xpath('unit/family/ethernet-switching/vlan/members')
if vlan_members:
config['trunk']['allowed_vlans'] = []
for vlan_member in vlan_members:
config['trunk']['allowed_vlans'].append(vlan_member.text)
config['trunk']['native_vlan'] = utils.get_xml_conf_arg(conf, "native-vlan-id")
return utils.remove_empties(config)

View file

@ -9,7 +9,7 @@ __metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'status': ['deprecated'],
'supported_by': 'network'}
@ -22,6 +22,10 @@ short_description: Manage Layer-2 interface on Juniper JUNOS network devices
description:
- This module provides declarative management of Layer-2 interface
on Juniper JUNOS network devices.
deprecated:
removed_in: "2.13"
why: Updated modules released with more functionality
alternative: Use M(junos_l2_interfaces) instead.
options:
name:
description:

View file

@ -63,7 +63,7 @@ options:
to a given subset. Possible values for this argument include
all and the resources like interfaces, vlans etc.
Can specify a list of values to include a larger subset.
choices: ['all', 'interfaces', 'lag_interfaces', 'l3_interfaces', 'lldp_interfaces', 'vlans']
choices: ['all', 'interfaces', 'lag_interfaces', 'l2_interfaces', 'l3_interfaces', 'lldp_interfaces', 'vlans']
required: false
version_added: "2.9"
requirements:

View file

@ -0,0 +1,402 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#############################################
# WARNING #
#############################################
#
# This file is auto generated by the resource
# module builder playbook.
#
# Do not edit this file manually.
#
# Changes to this file will be over written
# by the resource module builder.
#
# Changes should be made in the model used to
# generate this file or in the resource module
# builder template.
#
#############################################
"""
The module file for junos_l2_interfaces
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'network'
}
DOCUMENTATION = """
---
module: junos_l2_interfaces
version_added: 2.9
short_description: Manage Layer-2 interface on Juniper JUNOS devices
description: This module provides declarative management of a Layer-2 interface on Juniper JUNOS devices.
author: Ganesh Nalawade (@ganeshrn)
options:
config:
description: A dictionary of Layer-2 interface options
type: list
elements: dict
suboptions:
name:
description:
- Full name of interface, e.g. ge-0/0/1.
type: str
required: True
unit:
description:
- Logical interface number. Value of C(unit) should be of type
integer.
type: int
access:
description:
- Configure the interface as a Layer 2 access mode.
type: dict
suboptions:
vlan:
description:
- Configure the access VLAN ID.
type: str
trunk:
description:
- Configure the interface as a Layer 2 trunk mode.
type: dict
suboptions:
allowed_vlans:
description:
- List of VLANs to be configured in trunk port. It's used as the VLAN range to ADD or
REMOVE from the trunk.
type: list
native_vlan:
description:
- Native VLAN to be configured in trunk port. It is used as the trunk native VLAN ID.
type: str
enhanced_layer:
description:
- True if your device has Enhanced Layer 2 Software (ELS). If the l2 configuration is under
C(interface-mode) the value is True else if the l2 configuration is under C(port-mode) value
is False
type: bool
state:
choices:
- merged
- replaced
- overridden
- deleted
default: merged
description:
- The state the configuration should be left in
type: str
requirements:
- ncclient (>=v0.6.4)
notes:
- This module requires the netconf system service be enabled on
the remote device being managed.
- Tested against vSRX JUNOS version 18.4R1.
- This module works with connection C(netconf). See L(the Junos OS Platform Options,../network/user_guide/platform_junos.html).
"""
EXAMPLES = """
# Using deleted
# Before state:
# -------------
#
# ansible@junos01# show interfaces
# ge-0/0/1 {
# description "L2 interface";
# speed 1g;
# unit 0 {
# family ethernet-switching {
# interface-mode access;
# vlan {
# members vlan30;
# }
# }
# }
#}
#ge-0/0/2 {
# description "non L2 interface";
# unit 0 {
# family inet {
# address 192.168.56.14/24;
# }
# }
- name: "Delete L2 attributes of given interfaces (Note: This won't delete the interface itself)."
junos_l2_interfaces:
config:
- name: ge-0/0/1
- name: ge-0/0/2
state: deleted
# After state:
# ------------
#
# ansible@junos01# show interfaces
# ge-0/0/1 {
# description "L2 interface";
# speed 1g;
# }
#ge-0/0/2 {
# description "non L2 interface";
# unit 0 {
# family inet {
# address 192.168.56.14/24;
# }
# }
# Using merged
# Before state:
# -------------
# ansible@junos01# show interfaces
# ge-0/0/3 {
# description "test interface";
# speed 1g;
#}
# ge-0/0/4 {
# description interface-trunk;
# native-vlan-id 100;
# unit 0 {
# family ethernet-switching {
# interface-mode trunk;
# vlan {
# members [ vlan40 ];
# }
# }
# }
# }
- name: "Merge provided configuration with device configuration (default operation is merge)"
junos_l2_interfaces:
config:
- name: ge-0/0/3
access:
vlan: v101
- name: ge-0/0/4
trunk:
allowed_vlans:
- vlan30
native_vlan: 50
state: merged
# After state:
# ------------
# user@junos01# show interfaces
# ge-0/0/3 {
# description "test interface";
# speed 1g;
# unit 0 {
# family ethernet-switching {
# interface-mode access;
# vlan {
# members v101;
# }
# }
# }
# }
# ge-0/0/4 {
# description interface-trunk;
# native-vlan-id 50;
# unit 0 {
# family ethernet-switching {
# interface-mode trunk;
# vlan {
# members [ vlan40 vlan30 ];
# }
# }
# }
# }
# Using overridden
# Before state:
# -------------
# ansible@junos01# show interfaces
# ge-0/0/3 {
# description "test interface";
# speed 1g;
#}
# ge-0/0/4 {
# description interface-trunk;
# native-vlan-id 100;
# unit 0 {
# family ethernet-switching {
# interface-mode trunk;
# vlan {
# members [ vlan40 ];
# }
# }
# }
# }
# ge-0/0/5 {
# description "Configured by Ansible-11";
# unit 0 {
# family ethernet-switching {
# interface-mode access;
# vlan {
# members v101;
# }
# }
# }
# }
- name: "Override provided configuration with device configuration"
junos_l2_interfaces:
config:
- name: ge-0/0/3
access:
vlan: v101
- name: ge-0/0/4
trunk:
allowed_vlans:
- vlan30
native_vlan: 50
state: overridden
# After state:
# ------------
# user@junos01# show interfaces
# ge-0/0/3 {
# unit 0 {
# family ethernet-switching {
# interface-mode access;
# vlan {
# members v101;
# }
# }
# }
# }
# ge-0/0/4 {
# description interface-trunk;
# native-vlan-id 50;
# unit 0 {
# family ethernet-switching {
# interface-mode trunk;
# vlan {
# members [ vlan30 ];
# }
# }
# }
# }
# Using replaced
# Before state:
# -------------
# ansible@junos01# show interfaces
# ge-0/0/3 {
# description "test interface";
# speed 1g;
#}
# ge-0/0/4 {
# description interface-trunk;
# native-vlan-id 100;
# unit 0 {
# family ethernet-switching {
# interface-mode trunk;
# vlan {
# members [ vlan40 ];
# }
# }
# }
# }
- name: "Replace provided configuration with device configuration"
junos_l2_interfaces:
config:
- name: ge-0/0/3
access:
vlan: v101
- name: ge-0/0/4
trunk:
allowed_vlans:
- vlan30
native_vlan: 50
state: replaced
# After state:
# ------------
# user@junos01# show interfaces
# ge-0/0/3 {
# unit 0 {
# family ethernet-switching {
# interface-mode access;
# vlan {
# members v101;
# }
# }
# }
# }
# ge-0/0/4 {
# description interface-trunk;
# native-vlan-id 50;
# unit 0 {
# family ethernet-switching {
# interface-mode trunk;
# vlan {
# members [ vlan30 ];
# }
# }
# }
# }
"""
RETURN = """
before:
description: The configuration prior to the model invocation.
returned: always
type: list
sample: >
The configuration returned will always be in the same format
of the parameters above.
after:
description: The resulting configuration model invocation.
returned: when changed
type: list
sample: >
The configuration returned will always be in the same format
of the parameters above.
commands:
description: The set of commands pushed to the remote device.
returned: always
type: list
sample: ['command 1', 'command 2', 'command 3']
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.junos.argspec.l2_interfaces.l2_interfaces import L2_interfacesArgs
from ansible.module_utils.network.junos.config.l2_interfaces.l2_interfaces import L2_interfaces
def main():
"""
Main entry point for module execution
:returns: the result form module invocation
"""
module = AnsibleModule(argument_spec=L2_interfacesArgs.argument_spec,
supports_check_mode=True)
result = L2_interfaces(module).execute_module()
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,3 @@
---
testcase: "[^_].*"
test_items: []

View file

@ -0,0 +1,2 @@
dependencies:
- prepare_junos_tests

View file

@ -0,0 +1,2 @@
---
- { include: netconf.yaml, tags: ['netconf'] }

View file

@ -0,0 +1,17 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yml"
use_regex: true
connection: local
register: test_cases
- name: set test_items
set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
- name: run test case (connection=netconf)
include: "{{ test_case_to_run }} ansible_connection=netconf"
with_items: "{{ test_items }}"
loop_control:
loop_var: test_case_to_run

View file

@ -0,0 +1,14 @@
---
- debug:
msg: "Start junos_l2_interfaces base config ansible_connection={{ ansible_connection }}"
- name: Configure vlan
junos_config:
lines:
- set vlans vlan100 vlan-id 100
- set vlans vlan200 vlan-id 200
- set vlans vlan300 vlan-id 300
- set vlans vlan400 vlan-id 400
- debug:
msg: "End junos_l2_interfaces base config ansible_connection={{ ansible_connection }}"

View file

@ -0,0 +1,18 @@
---
- debug:
msg: "Start junos_l2_interfaces deleted remove l2 interface config ansible_connection={{ ansible_connection }}"
- name: "Setup - remove interface config"
junos_config:
lines:
- delete interfaces ge-0/0/1
- delete interfaces ge-0/0/2
- delete interfaces ge-0/0/3
- delete interfaces lo0
- delete vlans vlan100
- delete vlans vlan200
- delete vlans vlan300
- delete vlans vlan400
- debug:
msg: "End junos_l2_interfaces deleted remove l2 interface config ansible_connection={{ ansible_connection }}"

View file

@ -0,0 +1,81 @@
---
- debug:
msg: "START junos_l2_interfaces deleted integration tests on connection={{ ansible_connection }}"
- include_tasks: _remove_config.yaml
- include_tasks: _base_config.yaml
- set_fact:
expected_deleted_output:
- name: ge-0/0/1
unit: 0
enhanced_layer: True
access:
vlan: vlan100
- block:
- name: Configure initial state for l2 interface
junos_l2_interfaces: &initial
config:
- name: ge-0/0/1
access:
vlan: vlan100
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan200
- vlan300
native_vlan: "400"
state: merged
register: result
- name: Delete the provided l2 interface configuration from running configuration
junos_l2_interfaces: &deleted
config:
- name: ge-0/0/2
state: deleted
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "{{ expected_deleted_output | symmetric_difference(result['after']) |length == 0 }}"
- name: Delete the provided l2 interface configuration from running configuration (IDEMPOTENT)
junos_l2_interfaces: *deleted
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
- name: Configure initial state for interface
junos_l2_interfaces: *initial
register: result
- name: Delete the all l2 interface configuration from running configuration
junos_l2_interfaces:
state: deleted
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "{{ result['after'] == [] }}"
- name: Delete the all l2 interface configuration from running configuration (IDEMPOTENT)
junos_l2_interfaces:
state: deleted
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
always:
- include_tasks: _remove_config.yaml
- debug:
msg: "END junos_l2_interfaces deleted integration tests on connection={{ ansible_connection }}"

View file

@ -0,0 +1,58 @@
---
- debug:
msg: "START junos_l2_interfaces merged integration tests on connection={{ ansible_connection }}"
- include_tasks: _remove_config.yaml
- include_tasks: _base_config.yaml
- set_fact:
expected_merged_output:
- name: ge-0/0/1
access:
vlan: vlan100
enhanced_layer: True
unit: 0
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan200
- vlan300
native_vlan: "400"
enhanced_layer: True
unit: 0
- block:
- name: Merge the provided configuration with the exisiting running configuration
junos_l2_interfaces: &merged
config:
- name: ge-0/0/1
access:
vlan: vlan100
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan200
- vlan300
native_vlan: "400"
state: merged
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "{{ expected_merged_output | symmetric_difference(result['after']) |length == 0 }}"
- name: Merge the provided l2 interface configuration from running configuration (IDEMPOTENT)
junos_l2_interfaces: *merged
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
always:
- include_tasks: _remove_config.yaml
- debug:
msg: "END junos_l2_interfaces merged integration tests on connection={{ ansible_connection }}"

View file

@ -0,0 +1,63 @@
---
- debug:
msg: "START junos_l2_interfaces override integration tests on connection={{ ansible_connection }}"
- include_tasks: _remove_config.yaml
- include_tasks: _base_config.yaml
- set_fact:
expected_overridden_output:
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan100
native_vlan: "200"
enhanced_layer: True
unit: 0
- block:
- name: Setup initial l2 configuration
junos_l2_interfaces:
config:
- name: ge-0/0/1
access:
vlan: vlan100
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan200
- vlan300
native_vlan: "400"
state: overridden
register: result
- name: Override the provided configuration with the exisiting running configuration
junos_l2_interfaces: &overridden
config:
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan100
native_vlan: "200"
state: overridden
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "{{ expected_overridden_output | symmetric_difference(result['after']) |length == 0 }}"
- name: Override the provided l2 interface configuration from running configuration (IDEMPOTENT)
junos_l2_interfaces: *overridden
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
always:
- include_tasks: _remove_config.yaml
- debug:
msg: "END junos_l2_interfaces override integration tests on connection={{ ansible_connection }}"

View file

@ -0,0 +1,58 @@
---
- debug:
msg: "START junos_l2_interfaces replaced integration tests on connection={{ ansible_connection }}"
- include_tasks: _remove_config.yaml
- include_tasks: _base_config.yaml
- set_fact:
expected_replaced_output:
- name: ge-0/0/1
trunk:
allowed_vlans:
- vlan100
- vlan300
native_vlan: "400"
enhanced_layer: True
unit: 0
- name: ge-0/0/2
access:
vlan: vlan200
enhanced_layer: True
unit: 0
- block:
- name: Replace the provided configuration with the exisiting running configuration
junos_l2_interfaces: &replaced
config:
- name: ge-0/0/1
trunk:
allowed_vlans:
- vlan100
- vlan300
native_vlan: "400"
- name: ge-0/0/2
access:
vlan: vlan200
state: replaced
register: result
- name: Assert the configuration is reflected on host
assert:
that:
- "{{ expected_replaced_output | symmetric_difference(result['after']) |length == 0 }}"
- name: Replace the provided interface configuration from running configuration (IDEMPOTENT)
junos_l2_interfaces: *replaced
register: result
- name: Assert that the previous task was idempotent
assert:
that:
- "result['changed'] == false"
always:
- include_tasks: _remove_config.yaml
- debug:
msg: "END junos_l2_interfaces replaced integration tests on connection={{ ansible_connection }}"

View file

@ -0,0 +1,70 @@
---
- debug:
msg: "START junos_l2_interfaces round trip integration tests on connection={{ ansible_connection }}"
- include_tasks: _remove_config.yaml
- include_tasks: _base_config.yaml
- set_fact:
expected_revert_output:
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan100
native_vlan: "200"
enhanced_layer: True
unit: 0
- block:
- name: Apply the provided configuration (base config)
junos_l2_interfaces:
config:
- name: ge-0/0/2
trunk:
allowed_vlans:
- vlan100
native_vlan: "200"
state: merged
register: base_config
- name: Gather interfaces facts
junos_facts:
gather_subset:
- default
gather_network_resources:
- l2_interfaces
- name: Apply the provided configuration (config to be reverted)
junos_l2_interfaces:
config:
- name: ge-0/0/1
trunk:
allowed_vlans:
- vlan100
- vlan300
native_vlan: "400"
- name: ge-0/0/2
access:
vlan: vlan200
state: replaced
register: result
- name: Assert that changes were applied
assert:
that: "result['changed'] == true"
- name: Revert back to base config using facts round trip
junos_l2_interfaces:
config: "{{ ansible_facts['network_resources']['l2_interfaces'] }}"
state: overridden
register: revert
- name: Assert that config was reverted
assert:
that: "{{ expected_revert_output | symmetric_difference(revert['after']) |length == 0 }}"
always:
- include_tasks: _remove_config.yaml
- debug:
msg: "END junos_l2_interfaces round trip integration tests on connection={{ ansible_connection }}"

View file

@ -4364,6 +4364,22 @@ lib/ansible/modules/network/junos/_junos_linkagg.py validate-modules:E326
lib/ansible/modules/network/junos/_junos_linkagg.py validate-modules:E337
lib/ansible/modules/network/junos/_junos_linkagg.py validate-modules:E338
lib/ansible/modules/network/junos/_junos_linkagg.py validate-modules:E340
lib/ansible/modules/network/junos/_junos_l2_interface.py validate-modules:E322
lib/ansible/modules/network/junos/_junos_l2_interface.py validate-modules:E324
lib/ansible/modules/network/junos/_junos_l2_interface.py validate-modules:E326
lib/ansible/modules/network/junos/_junos_l2_interface.py validate-modules:E337
lib/ansible/modules/network/junos/_junos_l2_interface.py validate-modules:E338
lib/ansible/modules/network/junos/_junos_l2_interface.py validate-modules:E340
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E322
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E324
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E326
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E337
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E338
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E340
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E322
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E324
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E326
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E338
lib/ansible/modules/network/junos/junos_banner.py validate-modules:E322
lib/ansible/modules/network/junos/junos_banner.py validate-modules:E324
lib/ansible/modules/network/junos/junos_banner.py validate-modules:E326
@ -4384,22 +4400,6 @@ lib/ansible/modules/network/junos/junos_facts.py validate-modules:E326
lib/ansible/modules/network/junos/junos_facts.py validate-modules:E337
lib/ansible/modules/network/junos/junos_facts.py validate-modules:E338
lib/ansible/modules/network/junos/junos_interfaces.py validate-modules:E325
lib/ansible/modules/network/junos/junos_l2_interface.py validate-modules:E322
lib/ansible/modules/network/junos/junos_l2_interface.py validate-modules:E324
lib/ansible/modules/network/junos/junos_l2_interface.py validate-modules:E326
lib/ansible/modules/network/junos/junos_l2_interface.py validate-modules:E337
lib/ansible/modules/network/junos/junos_l2_interface.py validate-modules:E338
lib/ansible/modules/network/junos/junos_l2_interface.py validate-modules:E340
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E322
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E324
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E326
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E337
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E338
lib/ansible/modules/network/junos/_junos_l3_interface.py validate-modules:E340
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E322
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E324
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E326
lib/ansible/modules/network/junos/_junos_lldp_interface.py validate-modules:E338
lib/ansible/modules/network/junos/junos_lag_interfaces.py validate-modules:E338
lib/ansible/modules/network/junos/junos_lldp.py validate-modules:E322
lib/ansible/modules/network/junos/junos_lldp.py validate-modules:E324