Add junos_l3_interfaces (#59026)

This commit is contained in:
Daniel Mellado Area 2019-07-31 16:29:32 +02:00 committed by GitHub
parent 47f9f43b0d
commit 58a53fe0eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 932 additions and 9 deletions

View file

@ -9,7 +9,8 @@ The arg spec for the junos facts module.
CHOICES = [
'all',
'interfaces',
'lag_interfaces'
'lag_interfaces',
'l3_interfaces'
]

View file

@ -0,0 +1,38 @@
# -*- 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 arg spec for the junos_l3_interfaces module
"""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
class L3_interfacesArgs(object): # pylint: disable=R0903
"""The arg spec for the junos_l3_interfaces module
"""
def __init__(self, **kwargs):
pass
argument_spec = {'config': {'elements': 'dict', 'options':
{
'ipv4': {'elements': 'dict',
'options':
{'address': {'type': 'str'}},
'type': 'list'},
'ipv6': {'elements': 'dict',
'options':
{'address': {'type': 'str'}},
'type': 'list'},
'name': {'required': True, 'type': 'str'},
'description': {'type': 'str'},
'unit': {'type': 'int', 'default': 0}
},
'type': 'list'},
'state': {'choices':
['merged', 'replaced', 'overridden', 'deleted'],
'default': 'merged',
'type': 'str'}} # pylint: disable=C0301

View file

@ -0,0 +1,234 @@
#
# -*- 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_l3_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.cfg.base import ConfigBase
from ansible.module_utils.network.common.utils import to_list
from ansible.module_utils.network.junos.facts.facts import Facts
from ansible.module_utils.network.junos.junos import (
locked_config, load_config, commit_configuration, discard_changes,
tostring)
from ansible.module_utils.network.common.netconf import (build_root_xml_node,
build_child_xml_node)
class L3_interfaces(ConfigBase):
"""
The junos_l3_interfaces class
"""
gather_subset = [
'!all',
'!min',
]
gather_network_resources = [
'l3_interfaces',
]
def __init__(self, module):
super(L3_interfaces, self).__init__(module)
def get_l3_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)
l3_interfaces_facts = facts['ansible_network_resources'].get(
'l3_interfaces')
if not l3_interfaces_facts:
return []
return l3_interfaces_facts
def execute_module(self):
""" Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
result = {'changed': False}
warnings = list()
existing_interfaces_facts = self.get_l3_interfaces_facts()
config_xmls = self.set_config(existing_interfaces_facts)
with locked_config(self._module):
for config_xml in to_list(config_xmls):
diff = load_config(self._module, config_xml, warnings)
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_interfaces_facts = self.get_l3_interfaces_facts()
result['before'] = existing_interfaces_facts
if result['changed']:
result['after'] = changed_interfaces_facts
result['warnings'] = warnings
return result
def set_config(self, existing_l3_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_l3_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 _get_common_xml_node(self, name):
root_node = build_root_xml_node('interface')
build_child_xml_node(root_node, 'name', name)
intf_unit_node = build_child_xml_node(root_node, 'unit')
return root_node, intf_unit_node
def _state_replaced(self, want, have):
""" The xml generator when state is replaced
:rtype: A list
:returns: the xml necessary to migrate the current configuration
to the desired configuration
"""
intf_xml = []
intf_xml.extend(self._state_deleted(want, have))
intf_xml.extend(self._state_merged(want, have))
return intf_xml
def _state_overridden(self, want, have):
""" The xml generator when state is overridden
:rtype: A list
:returns: the xml necessary to migrate the current configuration
to the desired configuration
"""
intf_xml = []
intf_xml.extend(self._state_deleted(have, have))
intf_xml.extend(self._state_merged(want, have))
return intf_xml
def _state_merged(self, want, have):
""" The xml generator when state is merged
:rtype: A list
:returns: the xml necessary to merge the provided into
the current configuration
"""
intf_xml = []
for config in want:
root_node, unit_node = self._get_common_xml_node(config['name'])
build_child_xml_node(unit_node, 'name',
str(config['unit']))
if config.get('ipv4'):
self.build_ipaddr_et(config, unit_node)
if config.get('ipv6'):
self.build_ipaddr_et(config, unit_node, protocol='ipv6')
intf_xml.append(root_node)
return intf_xml
def build_ipaddr_et(self, config, unit_node, protocol='ipv4',
delete=False):
family = build_child_xml_node(unit_node, 'family')
inet = 'inet'
if protocol == 'ipv6':
inet = 'inet6'
ip_protocol = build_child_xml_node(family, inet)
for ip_addr in config[protocol]:
if ip_addr['address'] == 'dhcp' and protocol == 'ipv4':
build_child_xml_node(ip_protocol, 'dhcp')
else:
ip_addresses = build_child_xml_node(
ip_protocol, 'address')
build_child_xml_node(
ip_addresses, 'name', ip_addr['address'])
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
"""
intf_xml = []
existing_l3_intfs = [l3_intf['name'] for l3_intf in have]
if not want:
want = have
for config in want:
if config['name'] not in existing_l3_intfs:
continue
else:
root_node, unit_node = self._get_common_xml_node(
config['name'])
build_child_xml_node(unit_node, 'name',
str(config['unit']))
family = build_child_xml_node(unit_node, 'family')
ipv4 = build_child_xml_node(family, 'inet')
intf = next(
(intf for intf in have if intf['name'] == config['name']),
None)
if 'ipv4' in intf:
if 'dhcp' in [x['address'] for x in intf.get('ipv4') if intf.get('ipv4') is not None]:
build_child_xml_node(ipv4, 'dhcp', None, {'delete': 'delete'})
else:
build_child_xml_node(
ipv4, 'address', None, {'delete': 'delete'})
ipv6 = build_child_xml_node(family, 'inet6')
build_child_xml_node(ipv6, 'address', None, {'delete': 'delete'})
intf_xml.append(root_node)
return intf_xml

View file

@ -14,6 +14,7 @@ from ansible.module_utils.network.common.facts.facts import FactsBase
from ansible.module_utils.network.junos.facts.legacy.base import Default, Hardware, Config, Interfaces, OFacts, HAS_PYEZ
from ansible.module_utils.network.junos.facts.interfaces.interfaces import InterfacesFacts
from ansible.module_utils.network.junos.facts.lag_interfaces.lag_interfaces import Lag_interfacesFacts
from ansible.module_utils.network.junos.facts.l3_interfaces.l3_interfaces import L3_interfacesFacts
FACT_LEGACY_SUBSETS = dict(
default=Default,
@ -24,6 +25,7 @@ FACT_LEGACY_SUBSETS = dict(
FACT_RESOURCE_SUBSETS = dict(
interfaces=InterfacesFacts,
lag_interfaces=Lag_interfacesFacts,
l3_interfaces=L3_interfacesFacts,
)

View file

@ -0,0 +1,115 @@
#
# -*- 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 l3_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.network.common import utils
from ansible.module_utils.network.junos.argspec.l3_interfaces.l3_interfaces import L3_interfacesArgs
class L3_interfacesFacts(object):
""" The junos l3_interfaces fact class
"""
def __init__(self, module, subspec='config', options='options'):
self._module = module
self.argument_spec = L3_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 l3_interfaces
:param connection: the device connection
:param ansible_facts: Facts dictionary
:param data: previously collected conf
:rtype: dictionary
:returns: facts
"""
if not data:
data = connection.get_configuration()
resources = data.xpath('//configuration/interfaces/node()')
objs = []
if resources:
objs = self.parse_l3_if_resources(resources)
config = []
if objs:
for l3_if_obj in objs:
config.append(self.render_config(
self.generated_spec, l3_if_obj))
facts = {}
facts['l3_interfaces'] = config
ansible_facts['ansible_network_resources'].update(facts)
return ansible_facts
def parse_l3_if_resources(self, l3_if_resources):
l3_ifaces = []
for iface in l3_if_resources:
interface = {}
interface['name'] = iface.find('name').text
if iface.find('description') is not None:
interface['description'] = iface.find('description').text
interface['unit'] = iface.find('unit/name').text
family = iface.find('unit/family/')
if family is not None and family.tag != 'ethernet-switching':
ipv4 = iface.findall('unit/family/inet/address')
dhcp = iface.findall('unit/family/inet/dhcp')
ipv6 = iface.findall('unit/family/inet6/address')
if dhcp:
interface['ipv4'] = [{'address': 'dhcp'}]
if ipv4:
interface['ipv4'] = self.get_ip_addresses(ipv4)
elif not dhcp:
interface['ipv4'] = None
if ipv6:
interface['ipv6'] = self.get_ip_addresses(ipv6)
l3_ifaces.append(interface)
return l3_ifaces
def get_ip_addresses(self, ip_addr):
address_list = []
for ip in ip_addr:
for addr in ip:
address_list.append({'address': addr.text})
return address_list
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 configuration
:rtype: dictionary
:returns: The generated config
"""
config = deepcopy(spec)
config['name'] = conf['name']
config['description'] = conf.get('description')
config['unit'] = conf.get('unit', 0)
config['ipv4'] = conf.get('ipv4')
config['ipv6'] = conf.get('ipv6')
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 L3 interfaces on Juniper JUNOS network devices
description:
- This module provides declarative management of L3 interfaces
on Juniper JUNOS network devices.
deprecated:
removed_in: "2.13"
why: Updated modules released with more functionality
alternative: Use M(junos_l3_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']
choices: ['all', 'interfaces', 'lag_interfaces', 'l3_interfaces']
required: false
version_added: "2.9"
requirements:

View file

@ -0,0 +1,407 @@
#!/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_l3_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_l3_interfaces
version_added: 2.9
short_description: Manage Layer 3 interface on Juniper JUNOS devices
description: This module provides declarative management of a Layer 3 interface on Juniper JUNOS devices
author: Daniel Mellado (@dmellado)
requirements:
- ncclient (>=v0.6.4)
notes:
- This module requires the netconf system service be enabled on the device being managed.
- This module works with connection C(netconf). See L(the Junos OS Platform Options,../network/user_guide/platform_junos.html).
- Tested against JunOS v18.4R1
options:
config:
description: A dictionary of Layer 3 interface options
type: list
elements: dict
suboptions:
name:
description:
- Full name of interface, e.g. ge-0/0/1
type: str
required: True
description:
description:
- Description about the interface, like an alias
type: str
unit:
description:
- Logical interface number. Value of C(unit) should be of type integer
default: 0
type: int
ipv4:
description:
- IPv4 addresses to be set for the Layer 3 logical interface mentioned in I(name) option.
The address format is <ipv4 address>/<mask>. The mask is number in range 0-32
for example, 192.0.2.1/24, or C(dhcp) to query DHCP for an IP address
type: list
elements: dict
suboptions:
address:
description:
- IPv4 address to be set for the specific interface
type: str
ipv6:
description:
- IPv6 addresses to be set for the Layer 3 logical interface mentioned in I(name) option.
The address format is <ipv6 address>/<mask>, the mask is number in range 0-128
for example, 2001:db8:2201:1::1/64 or C(auto-config) to use SLAAC
type: list
elements: dict
suboptions:
address:
description:
- IPv6 address to be set for the specific interface
type: str
state:
description:
- The state the configuration should be left in
type: str
choices:
- merged
- replaced
- overridden
- deleted
default: merged
"""
EXAMPLES = """
# Using deleted
# Before state:
# -------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "L3 interface";
# unit 0 {
# family inet {
# address 10.200.16.10/24;
# }
# }
# }
# ge-0/0/2 {
# description "non L3 interface";
# unit 0 {
# family ethernet-switching {
# interface-mode access;
# vlan {
# members 2;
# }
# }
# }
# }
- name: Delete JUNOS L3 logical interface
junos_l3_interfaces:
config:
- name: ge-0/0/1
- name: ge-0/0/2
state: deleted
# After state:
# ------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "deleted L3 interface";
# }
# ge-0/0/2 {
# description "non L3 interface";
# unit 0 {
# family ethernet-switching {
# interface-mode access;
# vlan {
# members 2;
# }
# }
# }
# }
# Using merged
# Before state
# ------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "L3 interface";
# unit 0 {
# family inet {
# address 10.200.16.10/24;
# }
# }
# }
# ge-0/0/2 {
# description "non configured interface";
# unit 0;
# }
- name: Merge provided configuration with device configuration (default operation is merge)
junos_l3_interfaces:
config:
- name: ge-0/0/1
ipv4:
- address: 192.168.1.10/24
ipv6:
- address: 8d8d:8d01::1/64
- name: ge-0/0/2
ipv4:
- address: dhcp
state: merged
# After state:
# ------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "L3 interface";
# unit 0 {
# family inet {
# address 10.200.16.10/24;
# address 192.168.1.10/24;
# }
# family inet6 {
# address 8d8d:8d01::1/64;
# }
# }
# }
# ge-0/0/2 {
# description "L3 interface with dhcp";
# unit 0 {
# family inet {
# dhcp;
# }
# }
# }
# Using overridden
# Before state
# ------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "L3 interface";
# unit 0 {
# family inet {
# address 10.200.16.10/24;
# }
# }
# }
# ge-0/0/2 {
# description "L3 interface with dhcp";
# unit 0 {
# family inet {
# dhcp;
# }
# }
# }
# ge-0/0/3 {
# description "another L3 interface";
# unit 0 {
# family inet {
# address 192.168.1.10/24;
# }
# }
# }
- name: Override provided configuration with device configuration
junos_l3_interfaces:
config:
- name: ge-0/0/1
ipv4:
- address: 192.168.1.10/24
ipv6:
- address: 8d8d:8d01::1/64
- name: ge-0/0/2
ipv6:
- address: 2001:db8:3000::/64
state: overridden
# After state:
# ------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "L3 interface";
# unit 0 {
# family inet {
# address 192.168.1.10/24;
# }
# family inet6 {
# address 8d8d:8d01::1/64;
# }
# }
# }
# ge-0/0/2 {
# description "L3 interface whith ipv6";
# unit 0 {
# family inet6 {
# address 2001:db8:3000::/64;
# }
# }
# }
# ge-0/0/3 {
# description "overridden L3 interface";
# unit 0;
# }
# Using replaced
# Before state
# ------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "L3 interface";
# unit 0 {
# family inet {
# address 10.200.16.10/24;
# }
# }
# }
# ge-0/0/2 {
# description "non configured interface";
# unit 0;
# }
# ge-0/0/3 {
# description "another L3 interface";
# unit 0 {
# family inet {
# address 192.168.1.10/24;
# }
# }
# }
- name: Replace provided configuration with device configuration
junos_l3_interfaces:
config:
- name: ge-0/0/1
ipv4:
- address: 192.168.1.10/24
ipv6:
- address: 8d8d:8d01::1/64
- name: ge-0/0/2
ipv4:
- address: dhcp
state: replaced
# After state:
# ------------
#
# admin# show interfaces
# ge-0/0/1 {
# description "L3 interface";
# unit 0 {
# family inet {
# address 192.168.1.10/24;
# }
# family inet6 {
# address 8d8d:8d01::1/64;
# }
# }
# }
# ge-0/0/2 {
# description "L3 interface with dhcp";
# unit 0 {
# family inet {
# dhcp;
# }
# }
# }
# ge-0/0/3 {
# description "another L3 interface";
# unit 0 {
# family inet {
# address 192.168.1.10/24;
# }
# }
# }
"""
RETURN = """
before:
description: The configuration prior to the model invocation.
returned: always
sample: >
The configuration returned will always be in the same format
of the parameters above.
type: list
after:
description: The resulting configuration model invocation.
returned: when changed
sample: >
The configuration returned will always be in the same format
of the parameters above.
type: list
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.l3_interfaces.l3_interfaces import L3_interfacesArgs
from ansible.module_utils.network.junos.config.l3_interfaces.l3_interfaces import L3_interfaces
def main():
"""
Main entry point for module execution
:returns: the result form module invocation
"""
module = AnsibleModule(argument_spec=L3_interfacesArgs.argument_spec,
supports_check_mode=True)
result = L3_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,16 @@
---
- name: collect all netconf test cases
find:
paths: "{{ role_path }}/tests/netconf"
patterns: "{{ testcase }}.yaml"
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,99 @@
---
- name: bootstrap interfaces
junos_l3_interfaces:
config:
- name: ge-1/0/0
ipv4:
- address: 192.168.100.1/24
- address: 10.200.16.20/24
- name: ge-2/0/0
ipv4:
- address: 192.168.100.2/24
- address: 10.200.16.21/24
- name: ge-3/0/0
ipv4:
- address: 192.168.100.3/24
- address: 10.200.16.22/24
state: replaced
register: result
- assert:
that:
- result is changed
- "'<nc:address><nc:name>192.168.100.1/24</nc:name></nc:address>' in result.xml[0]"
- "'<nc:address><nc:name>10.200.16.20/24</nc:name></nc:address>' in result.xml[0]"
- "result.after[0].name == 'ge-1/0/0'"
- "result.after[0].ipv4[0]['address'] == '192.168.100.1/24'"
- "result.after[0].ipv4[1]['address'] == '10.200.16.20/24'"
- name: bootstrap interfaces (idempotent)
junos_l3_interfaces:
config:
- name: ge-1/0/0
ipv4:
- address: 192.168.100.1/24
- address: 10.200.16.20/24
- name: ge-2/0/0
ipv4:
- address: 192.168.100.2/24
- address: 10.200.16.21/24
- name: ge-3/0/0
ipv4:
- address: 192.168.100.3/24
- address: 10.200.16.22/24
state: replaced
register: result
- assert:
that:
- result is not changed
- name: Add another interface ip
junos_l3_interfaces:
config:
- name: ge-1/0/0
ipv4:
- address: 100.64.0.1/10
- address: 100.64.0.2/10
state: merged
register: result
- assert:
that:
- result is changed
- "'<nc:address><nc:name>100.64.0.1/10</nc:name></nc:address>' in result.xml[0]"
- "'<nc:address><nc:name>100.64.0.2/10</nc:name></nc:address>' in result.xml[0]"
- "result.after[0].name == 'ge-1/0/0'"
- "result.after[0].ipv4[0]['address'] == '192.168.100.1/24'"
- "result.after[0].ipv4[1]['address'] == '10.200.16.20/24'"
- "result.after[0].ipv4[2]['address'] == '100.64.0.1/10'"
- "result.after[0].ipv4[3]['address'] == '100.64.0.2/10'"
- name: Delete ge-2/0/0 interface config
junos_l3_interfaces:
config:
- name: ge-2/0/0
state: deleted
register: result
- assert:
that:
- result is changed
- "'<nc:name>ge-2/0/0</nc:name><nc:unit><nc:name>0</nc:name><nc:family><nc:inet><nc:address delete=\"delete\"/>' in result.xml[0]"
- name: Override all config
junos_l3_interfaces:
config:
- name: ge-1/0/0
ipv4:
- address: dhcp
- name: fxp0
ipv4:
- address: dhcp
state: overridden
register: result
- assert:
that:
- result is changed
- "'<nc:name>fxp0</nc:name><nc:unit><nc:name>0</nc:name><nc:family><nc:inet><nc:dhcp/></nc:inet>' in result.xml[0]"

View file

@ -4898,12 +4898,12 @@ 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_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_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