
    Vh                        d dl mZmZmZ eZdZdZdZd dl	m
Z
 d dlmZmZ d dlmZ d dlmZmZmZmZ d d	lmZmZmZ d d
lmZmZmZ dZ	 d dl	mZ 	 d dl"m#Z# d Z%d#dZ&d Z'd Z(d Z)d Z*d Z+d Z,d Z-d Z.d Z/d Z0d Z1d Z2d Z3d Z4d Z5d  Z6e7d!k(  r e6        y"y"# e$ r 	 d dl mZ n# e$ r dZe!ZY nw xY wY jw xY w# e$$ r Y nw xY w)$    )absolute_importdivisionprint_functiona+  
module: api_modify
author:
  - "Felix Fontein (@felixfontein)"
short_description: Modify data at paths with API
version_added: 2.2.0
description:
  - Allows to modify information for a path using the API.
  - Use the M(community.routeros.api_find_and_modify) module to modify one or multiple entries in a controlled way depending
    on some search conditions.
  - To make a backup of a path that can be restored with this module, use the M(community.routeros.api_info) module.
  - The module ignores dynamic and builtin entries.
  - B(Note) that this module is still heavily in development, and only supports B(some) paths. If you want to support new
    paths, or think you found problems with existing paths, please first L(create an issue in the community.routeros Issue
    Tracker,https://github.com/ansible-collections/community.routeros/issues/).
notes:
  - If write-only fields are present in the path, the module is B(not idempotent) in a strict sense, since it is not able
    to verify the current value of these fields. The behavior the module should assume can be controlled with the O(handle_write_only)
    option.
requirements:
  - Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6
extends_documentation_fragment:
  - community.routeros.api
  - community.routeros.api.restrict
  - community.routeros.attributes
  - community.routeros.attributes.actiongroup_api
attributes:
  check_mode:
    support: full
  diff_mode:
    support: full
  platform:
    support: full
    platforms: RouterOS
  idempotent:
    support: full
options:
  path:
    description:
      - Path to query.
      - An example value is V(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS
        CLI.
    required: true
    type: str
    choices:
    # BEGIN PATH LIST
      - caps-man aaa
      - caps-man access-list
      - caps-man channel
      - caps-man configuration
      - caps-man datapath
      - caps-man manager
      - caps-man manager interface
      - caps-man provisioning
      - caps-man security
      - certificate settings
      - interface 6to4
      - interface bonding
      - interface bridge
      - interface bridge mlag
      - interface bridge port
      - interface bridge port-controller
      - interface bridge port-extender
      - interface bridge settings
      - interface bridge vlan
      - interface detect-internet
      - interface eoip
      - interface ethernet
      - interface ethernet poe
      - interface ethernet switch
      - interface ethernet switch port
      - interface ethernet switch port-isolation
      - interface gre
      - interface gre6
      - interface l2tp-client
      - interface l2tp-server server
      - interface list
      - interface list member
      - interface ovpn-client
      - interface ovpn-server server
      - interface ppp-client
      - interface pppoe-client
      - interface pppoe-server server
      - interface pptp-server server
      - interface sstp-server server
      - interface vlan
      - interface vrrp
      - interface wifi
      - interface wifi aaa
      - interface wifi access-list
      - interface wifi cap
      - interface wifi capsman
      - interface wifi channel
      - interface wifi configuration
      - interface wifi datapath
      - interface wifi interworking
      - interface wifi provisioning
      - interface wifi security
      - interface wifi steering
      - interface wifiwave2
      - interface wifiwave2 aaa
      - interface wifiwave2 access-list
      - interface wifiwave2 cap
      - interface wifiwave2 capsman
      - interface wifiwave2 channel
      - interface wifiwave2 configuration
      - interface wifiwave2 datapath
      - interface wifiwave2 interworking
      - interface wifiwave2 provisioning
      - interface wifiwave2 security
      - interface wifiwave2 steering
      - interface wireguard
      - interface wireguard peers
      - interface wireless
      - interface wireless access-list
      - interface wireless align
      - interface wireless cap
      - interface wireless connect-list
      - interface wireless security-profiles
      - interface wireless sniffer
      - interface wireless snooper
      - iot modbus
      - ip accounting
      - ip accounting web-access
      - ip address
      - ip arp
      - ip cloud
      - ip cloud advanced
      - ip dhcp-client
      - ip dhcp-client option
      - ip dhcp-relay
      - ip dhcp-server
      - ip dhcp-server config
      - ip dhcp-server lease
      - ip dhcp-server matcher
      - ip dhcp-server network
      - ip dhcp-server option
      - ip dhcp-server option sets
      - ip dns
      - ip dns adlist
      - ip dns forwarders
      - ip dns static
      - ip firewall address-list
      - ip firewall connection tracking
      - ip firewall filter
      - ip firewall layer7-protocol
      - ip firewall mangle
      - ip firewall nat
      - ip firewall raw
      - ip firewall service-port
      - ip hotspot service-port
      - ip ipsec identity
      - ip ipsec mode-config
      - ip ipsec peer
      - ip ipsec policy
      - ip ipsec profile
      - ip ipsec proposal
      - ip ipsec settings
      - ip neighbor discovery-settings
      - ip pool
      - ip proxy
      - ip route
      - ip route rule
      - ip route vrf
      - ip service
      - ip settings
      - ip smb
      - ip socks
      - ip ssh
      - ip tftp settings
      - ip traffic-flow
      - ip traffic-flow ipfix
      - ip traffic-flow target
      - ip upnp
      - ip upnp interfaces
      - ip vrf
      - ipv6 address
      - ipv6 dhcp-client
      - ipv6 dhcp-server
      - ipv6 dhcp-server option
      - ipv6 firewall address-list
      - ipv6 firewall filter
      - ipv6 firewall mangle
      - ipv6 firewall nat
      - ipv6 firewall raw
      - ipv6 nd
      - ipv6 nd prefix
      - ipv6 nd prefix default
      - ipv6 route
      - ipv6 settings
      - mpls
      - mpls interface
      - mpls ldp
      - mpls ldp accept-filter
      - mpls ldp advertise-filter
      - mpls ldp interface
      - port firmware
      - port remote-access
      - ppp aaa
      - ppp profile
      - ppp secret
      - queue interface
      - queue simple
      - queue tree
      - queue type
      - radius
      - radius incoming
      - routing bfd configuration
      - routing bgp aggregate
      - routing bgp connection
      - routing bgp instance
      - routing bgp network
      - routing bgp peer
      - routing bgp template
      - routing filter
      - routing filter community-list
      - routing filter num-list
      - routing filter rule
      - routing filter select-rule
      - routing id
      - routing igmp-proxy
      - routing igmp-proxy interface
      - routing mme
      - routing ospf area
      - routing ospf area range
      - routing ospf instance
      - routing ospf interface-template
      - routing ospf static-neighbor
      - routing pimsm instance
      - routing pimsm interface-template
      - routing rip
      - routing ripng
      - routing rule
      - routing table
      - snmp
      - snmp community
      - system clock
      - system clock manual
      - system health settings
      - system identity
      - system leds settings
      - system logging
      - system logging action
      - system note
      - system ntp client
      - system ntp client servers
      - system ntp server
      - system package update
      - system resource irq rps
      - system routerboard settings
      - system scheduler
      - system script
      - system upgrade mirror
      - system ups
      - system watchdog
      - tool bandwidth-server
      - tool e-mail
      - tool graphing
      - tool graphing interface
      - tool graphing resource
      - tool mac-server
      - tool mac-server mac-winbox
      - tool mac-server ping
      - tool netwatch
      - tool romon
      - tool sms
      - tool sniffer
      - tool traffic-generator
      - user
      - user aaa
      - user group
      - user settings
    # END PATH LIST
  data:
    description:
      - Data to ensure that is present for this path.
      - Fields not provided will not be modified.
      - If C(.id) appears in an entry, it will be ignored.
    required: true
    type: list
    elements: dict
  ensure_order:
    description:
      - Whether to ensure the same order of the config as present in O(data).
      - Requires O(handle_absent_entries=remove).
    type: bool
    default: false
  handle_absent_entries:
    description:
      - How to handle entries that are present in the current config, but not in O(data).
      - V(ignore) ignores them.
      - V(remove) removes them.
    type: str
    choices:
      - ignore
      - remove
    default: ignore
  handle_entries_content:
    description:
      - For a single entry in O(data), this describes how to handle fields that are not mentioned in that entry, but appear
        in the actual config.
      - If V(ignore), they are not modified.
      - If V(remove), they are removed. If at least one cannot be removed, the module will fail.
      - If V(remove_as_much_as_possible), all that can be removed will be removed. The ones that cannot be removed will be
        kept.
      - Note that V(remove) and V(remove_as_much_as_possible) do not apply to write-only fields.
    type: str
    choices:
      - ignore
      - remove
      - remove_as_much_as_possible
    default: ignore
  handle_read_only:
    description:
      - How to handle values passed in for read-only fields.
      - If V(ignore), they are not passed to the API.
      - If V(validate), the values are not passed for creation, and for updating they are compared to the value returned for
        the object. If they differ, the module fails.
      - If V(error), the module will fail if read-only fields are provided.
    type: str
    choices:
      - ignore
      - validate
      - error
    default: error
    version_added: 2.10.0
  handle_write_only:
    description:
      - How to handle values passed in for write-only fields.
      - If V(create_only), they are passed on creation, and ignored for updating.
      - If V(always_update), they are always passed to the API. This means that if such a value is present, the module will
        always result in C(changed) since there is no way to validate whether the value actually changed.
      - If V(error), the module will fail if write-only fields are provided.
    type: str
    choices:
      - create_only
      - always_update
      - error
    default: create_only
    version_added: 2.10.0
  restrict:
    description:
      - Restrict operation to entries matching the following criteria.
      - This can be useful together with O(handle_absent_entries=remove) to operate on a subset of the values.
      - For example, for O(path=ip firewall filter), you can set O(restrict[].field=chain) and O(restrict[].values=input)
        to restrict operation to the input chain, and ignore the forward and output chains.
    version_added: 2.18.0
seealso:
  - module: community.routeros.api
  - module: community.routeros.api_facts
  - module: community.routeros.api_find_and_modify
  - module: community.routeros.api_info
a  
---
- name: Setup DHCP server networks
  # Ensures that we have exactly two DHCP server networks (in the specified order)
  community.routeros.api_modify:
    path: ip dhcp-server network
    handle_absent_entries: remove
    handle_entries_content: remove_as_much_as_possible
    ensure_order: true
    data:
      - address: 192.168.88.0/24
        comment: admin network
        dns-server: 192.168.88.1
        gateway: 192.168.88.1
      - address: 192.168.1.0/24
        comment: customer network 1
        dns-server: 192.168.1.1
        gateway: 192.168.1.1
        netmask: 24

- name: Adjust NAT
  community.routeros.api_modify:
    hostname: "{{ hostname }}"
    password: "{{ password }}"
    username: "{{ username }}"
    path: ip firewall nat
    data:
      - action: masquerade
        chain: srcnat
        comment: NAT to WAN
        out-interface-list: WAN
        # Three ways to unset values:
        #   - nothing after `:`
        #   - "empty" value (null/~/None)
        #   - prepend '!'
        out-interface:
        to-addresses: ~
        '!to-ports':

- name: Block all incoming connections
  community.routeros.api_modify:
    hostname: "{{ hostname }}"
    password: "{{ password }}"
    username: "{{ username }}"
    path: ip firewall filter
    handle_absent_entries: remove
    handle_entries_content: remove_as_much_as_possible
    restrict:
      # Do not touch any chain except the input chain
      - field: chain
        values:
          - input
    data:
      - action: drop
        chain: input
a  
old_data:
  description:
    - A list of all elements for the current path before a change was made.
  sample:
    - '.id': '*1'
      actual-interface: bridge
      address: "192.168.88.1/24"
      comment: defconf
      disabled: false
      dynamic: false
      interface: bridge
      invalid: false
      network: 192.168.88.0
  type: list
  elements: dict
  returned: always
new_data:
  description:
    - A list of all elements for the current path after a change was made.
  sample:
    - '.id': '*1'
      actual-interface: bridge
      address: "192.168.1.1/24"
      comment: awesome
      disabled: false
      dynamic: false
      interface: bridge
      invalid: false
      network: 192.168.1.0
  type: list
  elements: dict
  returned: always
)defaultdict)AnsibleModulemissing_required_lib)	to_native)api_argument_speccheck_has_library
create_apiget_api_version)PATHS	join_path
split_path)restrict_argument_specrestrict_entry_acceptedvalidate_and_prepare_restrictT)OrderedDictF)LibRouterosErrorc                 V    | j                         }|D ]  }|j                  |      } |S N)pathjoin)apir   api_pathps       q/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/routeros/plugins/modules/api_modify.pycompose_api_pathr     s/    xxzH $==#$O    c           	      V   t               }| j                         }|j                         D ]d  \  }}	|dk(  rd }
|j                  d      r|dd  }
n |	|	|j                  |   j
                  k(  r|}
|
F|
| v rA|j                  |
   j
                  |j                  |
   j
                  ||
<   nd|d|
z  <   ||
= || vr6|j                  |   j                  |	k(  r|j                  |   j                  s|j                  |   }|j                  rJ| j                  |      |	k7  r4|j                  dj                  || j                  |      |	|             -|j                  r|j                  d	   d
k(  rM|| vs
| |   |	k7  s[|	||<   |	||<   g |j                  d   }|dk7  r| D ]  }|dk(  s||v sd|z  |v s||j                  vr#|j                  |   }|j                  |j                  | |   k(  rQ|j
                  |j
                  | |   k(  rp|j                  rD|j                  |j                  ||<   n$|j
                  |j
                  ||<   nd|d|z  <   ||= |j                  |j                  ||<   |j                  ||<   |dk(  s|r y|j                  dj                  ||              |j                  D ]S  }|j                  |   }|| vs||vs|j                  s)|j                  6|j                  ||<   |j                  ||<   U ||fS )N.id!    !%szaRead-only key "{key}" has value "{old_value}", but should have new value "{new_value}"{for_text}.)key	old_value	new_valuefor_textmsghandle_write_onlycreate_onlyhandle_entries_contentignoreremove)NNz(Key "{key}" cannot be removed{for_text}.r&   r)   )r   copyitems
startswithfieldsremove_valuedefaultcan_disable	read_onlyget	fail_jsonformat
write_onlyparams)	old_entry	new_entry	path_infomoduler)   return_none_instead_of_failmodificationsupdated_entrykv
disabled_kkey_infor.   
field_infos                 r   find_modificationsrK     s   MMNN$M!  !1:
<<12JY!y//2???J!Y&##J/<<H090@0@0L0Y0YM*-8:M%*"45!*-I)"2"21"5"="="B9K[K[\]K^KjKj##A&}}Q1$  {  C  Cq)9QQY C [ ! \ }}01]BI1!2 M! M!A !B $]]+CD) 	rAEzQ)^	i/G1T]TdTdKd"))!,J!!-*2D2D	RS2T&&2z7N7NR[\]R^7^%%%%1'1'9'9M!$,,8'1'>'>M!$/1M%!),!!$##/#-#5#5a #-#5#5a '83.%  %O%V%V[\go%V%p q-	r. !! 	6A"))!,J	!ay&8Z=S=SXbXjXjXv#-#5#5a #-#5#5a 		6
 -''r   c                    |j                         D ]|  \  }}|dk(  rd }|j                  d      r|dd  }n |||j                  |   j                  k(  r|}||| v r y N|| vr|j                  |   j                  |k(  ro|| vs	| |   |k7  s| y  |j
                  d   }d}| D ][  }|dk(  s||v sd|z  |v s||j                  vr"|j                  |   }	|	j                  |	j                  | |   k(  rP|dk7  r y |dz  }] |S )Nr!   r"   r#   r.   r   r%   r/   )r3   r4   r5   r6   r7   r>   )
r?   r@   rA   rB   rF   rG   rH   r.   weightrJ   s
             r   essentially_same_weightrN   >  sK   ! 1:
<<12JY!y//2???J!Y&I)"2"21"5"="="BI1!2  $]]+CDF 	:iEAI)+CqPYP`P`G`%%a(
)j.@.@IaL.P!X-aKF	 Mr   c                     g }| j                         D ]H  \  }}|}|j                  d      r|dd  }|j                  |   j                  s8|j	                  |       J |D ]  }| j                  |        y Nr"   r#   )r3   r4   r5   r9   appendpop)entryrA   	to_removereal_krG   rF   s         r   remove_read_onlyrV   ^  sz    I[[] %	<<!"AA((V$%  		!r   c                 F    dj                  d t        | |      D              S )N, c              3   H   K   | ]  \  }}d j                  ||        yw)z{pk}="{value}")pkvalueN)r<   ).0rZ   r[   s      r   	<genexpr>zformat_pk.<locals>.<genexpr>k  s%     lYR%,,%,@ls    ")r   zip)primary_keysvaluess     r   	format_pkra   j  s!    99lRUVbdjRklllr   c                    d| v r| j                  d       g }| j                         D ]  \  }}|}d}|j                  d      r.d}|dd  }|| v r#|j                  dj	                  ||             |j
                  j                  |      }	|	#|j                  d	j	                  ||             |rd|	j                  s#|j                  d
j	                  ||             |d d|	j                  fvrU|j                  dj	                  ||             n1|/|	j                  s#|j                  dj	                  ||             |	j                  rX|j                  d   dk(  r#|j                  dj	                  ||             |j                  d   dk(  r|j                  |       |	j                  s|j                  d   dk(  s|j                  dj	                  ||              |D ]  }| j                  |        |j
                  j                         D ]:  \  }}
|
j                  s|| vs|j                  dj	                  ||             < |j                  D ]x  }|D cg c]	  }|| v s| }}t        |      dkD  s&|r)|j                  dj	                  dj!                  |D cg c]  }dj	                  |       c}      |             z |j"                  D ]u  }|D cg c]	  }|| v s| }}t        |      dkD  s&|j                  dj	                  dj!                  |D cg c]  }dj	                  |       c}      |             w y c c}w c c}w c c}w c c}w )Nr!   Fr"   Tr#   z4Not both "{key}" and "!{key}" must appear{for_text}.r1   r*   zUnknown key "{key}"{for_text}.z:Key "!{key}" must not be disabled (leading "!"){for_text}.r$   z6Disabled key "!{key}" must not have a value{for_text}.z?Key "{key}" must not be disabled (value null/~/None){for_text}.handle_read_onlyerrorz?Key "{key}" is read-only{for_text}, and handle_read_only=error.r/   r,   zAKey "{key}" is write-only{for_text}, and handle_write_only=error.z&Key "{key}" must be present{for_text}.r   zrEvery element in data must contain one of {required_keys}. For example, the element{for_text} does not provide it.rX   z"{k}")rF   )required_keysr)   z@Keys {exclusive_keys} cannot be used at the same time{for_text}.)exclusive_keysr)   )rR   r3   r4   r;   r<   r5   r:   r8   r6   r9   r>   rQ   r=   requiredrequired_one_oflenr   mutually_exclusive)rS   rA   rB   r)   rT   r&   r[   real_keydisabled_keyrI   rJ   require_listrkfound_req_keysrF   exclusive_listekfound_ex_keyss                     r   polish_entryrs   n  s   ~		%Ikkm M
U>>#Lab'Ce|  %[%b%bgju}%b%~ ##'',!A!H!HX`h!H!ij''  %a%h%hmp  |D%h  &E   FT2x'<'<==  %]%d%dilw%d  &A   B]''  %f%m%mru  AI%m  &J   K}}/0G;  %f%m%mru  AI%m  &J   K}}/0H<  *}}01W<  %h%o%otw  CK%o  &L   M5M6  		#$++113 nZ3e#3!I!P!PUXck!P!lmn "11 '3CrU{"CC|q  I  P  P"&)),,WQW^^a^-@,W"X% P    $66 &4DeDD}!V]]#'99=-Yagnnqn.A-Y#Z% ^    D -X
 E .Zs$   7	M0M0>M5>	M:M:M?c                 z    t        | j                               D ]  \  }}|dk(  r||j                  vs|| |= ! y Nr!   )listr3   r5   )rS   rA   rF   rG   s       r   remove_irrelevant_datarw     sC    U[[]# 1:I$$$	a	r   c           	      r   | D cg c]  }d  }}t        |      }g }|j                  d   }|dk(  r`t        |       D ]Q  \  }\  }	}
t        |      D ];  \  }\  }	}t        ||
||d      \  }}	||j	                  ||t        |      f       = S nQt        |       D ]C  \  }\  }	}
t        |      D ]-  \  }\  }	}t        ||
||      }||j	                  |||f       / E |j                  d        |D ]  \  }}}||   ||   ||   d c||<   ||<   ! |D cg c]  }||	 }}||fS c c}w c c}w )Nhandle_absent_entriesr0   T)rC   c                     | d   S )N    rS   s    r   <lambda>zmatch_entries.<locals>.<lambda>  s
    58 r   r&   )rv   r>   	enumeraterK   rQ   ri   rN   sort)new_entriesold_entriesrA   rB   rS   matching_old_entriesmatchesry   	new_indexunusedr@   	old_indexr?   rD   rM   ratingindex_entryunmatched_old_entriess                     r   match_entriesr     s   .9:UD::{#KG"MM*AB(.7.D 	O*I*	2;K2H O.	.FI(:9iQZ\b  AE  )F%v ,NNIy#m:L#MNO	O /8.D 	C*I*	2;K2H C.	.FI0IyRXY%NNIy&#ABC	C
 LL+L,(/ _$	9f	*6+i:P:XBMiBXZ^?Y'Y)?_ =Hc[;Kb[cc!666- ;* ds   	D/D4%D4c                     g }| D ]8  }|j                  dd      s|j                  dd      r(|j                  |       : |S )NdynamicFbuiltin)r:   rQ   )entriesresultrS   s      r   remove_dynamicr     sG    F 99Y&%))Iu*Ee Mr   c                     t        |       }|D ]E  }|j                  j                         D ]&  \  }}|j                  ||vs|j                  ||<   ( G |S r   )rv   r5   r3   absent_value)r   rA   r   rS   rF   rJ   s         r   get_api_datar     sd    8nG 3&--335 	3MAz&&2q~%22a	33 Nr   c                     i }| j                         D ][  \  }}|j                  d      r%|dd  }|j                  |   j                  }| |}|}n||j                  |   j                  }|||<   ] |S rP   )r3   r4   r5   r6   )rS   rA   r@   rF   rG   rU   r6   s          r   prepare_for_addr     s    I 
1<<qrUF$++F3@@L' y$$Q'44	!
 r   c                 F    | D cg c]  }t        |||      r| c}S c c}w r   )r   )datarA   restrict_datarS   s       r   remove_rejectedr     s.    "5)]C 	  s   c                    ( | j                   d   }| j                   d   }|dk(  r|dk(  r| j                  d       |j                  xs d}| j                   d   }t        t              }	t        |      D ]  \   t         ||      s%| j                  d	j                  d
z                |D ]-  }
|
 vs| j                  dj                  |
d
z                / t         fd|D              }t         || dj                  d
z                |	|   j                   f        t        |	      }	t        ||      }t        ||      }t        |      }t        |||      }t        t              }t        |      D ]/  \   t         fd|D              }||   j                   f       1 t        |      }g }g }g }g }|	j!                         D ]  \  }}|j#                  |g       }t%        ||||       \  }}t'        ||      D ]  \  \  }}|a|\  }}t)        |||| dj                  d
z               \  }}|r|d   |d<   |j                  |       |j                  ||f       |d   |d<   lt+        ||       |j                  |        |dk(  r|j-                  d |D               |j-                  |        |j!                         D ]4  \  }}|dk(  r|j-                  d |D               $|j-                  |       6 t/        |d       D  cg c]  \  }} | 	 }}} |j-                  |       g }!| j                   d   rt        |      D ]v  \   d v r fd(n fd(t1        (fdt        |d        D              }"|"k7  s<|!j                  ||"   |   f       |j3                  |j#                  |"             x | j4                  s|r	  |j6                  |  |D ]  }	  |j@                  di |  |D ]"   	  |jB                  di tE         |       d<   $ |!D ]  \  }%}}	  |d#|d   |d   $      D ]  }&  |s|s|!r"t        t        ||            }t        |||      }|D ]   tG         |        |D ]   tG         |        i }'| jH                  rd|id|id'|'d(<    | jJ                  dtM        |xs
 |xs |xs |!      ||d)|' y c c} }w # t8        t:        f$ rj}#| j                  dj                  dj=                  |D $cg c]  }$dj                  |$       nc c}$w c}$      t?        |#                   Y d }#~#qd }#~#ww xY w# t8        t:        f$ r:}#| j                  dj                  |d   t?        |#                    Y d }#~#d }#~#ww xY w# t8        t:        f$ r6}#| j                  d!j                  t?        |#      "             Y d }#~#d }#~#ww xY w# t8        t:        f$ r?}#| j                  d%j                  |d   |%|d   t?        |#      &             Y d }#~#d }#~#ww xY w)*Nry   r.   r0   r/   zaFor this path, handle_absent_entries=remove cannot be combined with handle_entries_content=ignorer*   r|   r   7The element at index #{index} does not match `restrict`r#   indexztEvery element in data must contain "{stratify_key}". For example, the element at index #{index} does not provide it.)stratify_keyr   c              3   (   K   | ]	  }|     y wr   r|   r\   r   rS   s     r   r]   zsync_list.<locals>.<genexpr>	       JLE,'J   z at index {index}c              3   (   K   | ]	  }|     y wr   r|   r   s     r   r]   zsync_list.<locals>.<genexpr>  r   r   r!   c              3   ,   K   | ]  \  }}|d      ywr!   Nr|   r\   r   rS   s      r   r]   zsync_list.<locals>.<genexpr>:  s     VuuU|V   c              3   ,   K   | ]  \  }}|d      ywr   r|   r   s      r   r]   zsync_list.<locals>.<genexpr>@  s     HuuU|Hr   c                     | d   S )Nr   r|   r}   s    r   r~   zsync_list.<locals>.<lambda>D  s    USTX r   r   ensure_orderc                     | d   d   k(  S ru   r|   current_entryrS   s    r   matchzsync_list.<locals>.matchK  s    (/5<??r   c                     | u S r   r|   r   s    r   r   zsync_list.<locals>.matchO  s    (E11r   c              3   @   K   | ]  \  }} |      s|z     y wr   r|   )r\   current_indexr   r   r   s      r   r]   zsync_list.<locals>.<genexpr>R  s2       !P;W=-z  AN  {O!6  !Ps   
+Error while removing {remove_list}: {error}rX   zID {id})idremove_listrd   z*Error while modifying for ID {id}: {error})r   rd   z#Error while creating entry: {error}rd   movenumbersdestinationzXError while moving entry ID {element_id} to position #{new_index} ID ({new_id}): {error})
element_idr   new_idrd   beforeafterdiffchangedold_datanew_data)'r>   r;   stratify_keysr   rv   r   r   r<   tuplers   rQ   dictr   r   r   r   r3   rR   r   r^   rK   rV   extendsortednextinsert
check_moder0   r   UnicodeEncodeErrorr   r	   updateaddr   rw   _diff	exit_jsonbool))rB   r   r   rA   r   ry   r.   r   r   stratified_datar   sksr   r   stratified_old_datacreate_listmodify_listr   r   r&   indexed_entriesr   r   r   r@   potential_old_entryr   r?   rD   rE   r   r   rS   reorder_listr   er   r   resmorer   s)                                  ``       @r   	sync_listr     sN   "MM*AB#]]+CD(!X-w   ++1rM== D!$'O!$ 4u&uiG!Z!a!ahmpqhq!a!rs) 	L5(   O  V  V%1#ai V  ! 	 JMJJ9f&&UQY&7	
 	##UEN3!4" ?+OT*HHi0Hh'HxMBH%d+!(+ 8uJMJJC ''78 23KKKH / 5 5 7 3_)--c26 7DOU`bkms6t33 8;?L`7a 	.3UI 3".':$	9/Ay)V'..UQY.?0,}
 !+4U+;M%(&&}5M :;#,U#3	%  I6""9-	." !H,V@UVVOO1273: ,113 %W H,HHHOOG$	% +1?U*VW,%WHWOOK L}}^$%dO 	DLE5~@2 !  !P[demnsnteu[v  !P  PM%##UH],CXe_$UVx||M'BC	D - ) 		M0-0		 ! 	E+x||PoeY.OPe	 0< 	+Iy)#FIe4DR[\aRbc C	 +%l8Y&GHH&xMJH  1ui01 1ui01 D||  	
V F [NKN;N,O 	k X. %&89   ELL$(IIQ\.]2y/?/?2/?/F.].]$^'l M  !   %&89   DKK(/'l L  !   %&89   =DD'l E  !   %&89   ryy#,U#3"+(/'l	 z  !  sr   !S+%S1 :U-V9?X1U* %U%%T?>!U%%U*-V6</V11V69W>+W99W>Y4Y

Yc                   +, |j                   }|j                  rE| j                  d   r| j                  d       | j                  d   dk(  r| j                  d       | j                  d   }t	               }t        |      D ]@  \  }+t        +||      s%| j                  dj                  |d	z   
             |D ]-  }	|	+vs| j                  dj                  |	|d	z                / t        +fd|D              }
|
|v r^| j                  dj                  dj                  |      dj                  |
D cg c]  }dj                  |       c}                   t        +|| dj                  dj                  t        ||
      D 	cg c]  \  }	}dj                  |	|       c}}	                   +||
<   C t        ||      }t        ||      }t        |      }t        |||      }t	               }i }|D ]#  +t        +fd|D              }
+||
<   +d   ||
<   % g }g }g }g }g }| j                  d   }|j!                         D ]  \  }}|j#                  |d       }|=|dk(  r&|j%                  |d          |j%                  |       E|j%                  |       Wt'        |||| dj                  dj                  t        ||      D 	cg c]  \  }	}dj                  |	|       c}}	                  \  }}|j%                  |       |s|d   |d<   |j%                  ||f        |j)                         D ]  }|j                  rS| j                  dj                  dj                  |D 	cg c]  }	dj                  |	||	          c}	                   t+        ||       |j%                  |       |j-                         }t/        |      D ]%  }|j1                  d      s|j#                  |       ' |j%                  |        g }| j                  d   rt3               }t        |      D ]  \  }+||t        +fd|D              <    t        |      D ]  \  },t        ,fd|D              }|j#                  |      }||k(  r1||   +t        +fd|D              }
|j%                  |||
f       |j!                         D ]  \  } }!|!|k\  s|!|k  s|!d	z   || <    |j5                  ||j#                  |              | j6                  s|r	  |j8                  |  |D ]  \  }}	  |jB                  d.i |  |D ]>  +	  |jD                  d.i tG        +|      +d<   t        +fd$|D              }
+d   ||
<   @ |D ]!  \  }$}%}&	 ||$   }'||&   }( |d'|'|((      D ]  }) # |s|s|r"t        t        ||            }t        |||      }|D ]  +tI        +|        |D ]  +tI        +|        i }*| jJ                  rd|id|id+|*d,<    | jL                  d.tO        |xs
 |xs |xs |      ||d-|* y c c}w c c}}	w c c}}	w c c}	w # t:        t<        f$ r}"| j                  dj                  dj                  t        ||      D #cg c]"  \  }#}dj                  t?        ||      |#       $ nc c}}#w c}}#      tA        |"      !             Y d }"~"d }"~"ww xY w# t:        t<        f$ rE}"| j                  d"j                  t?        ||      |d   tA        |"      #             Y d }"~"d }"~"ww xY w# t:        t<        f$ rX}"| j                  d%j                  t?        ||D cg c]  }+|   	 nc c}w c}      tA        |"      &             Y d }"~"ad }"~"ww xY w# t:        t<        f$ r8}"| j                  d)j                  '(tA        |"      *             Y d }"~"hd }"~"ww xY w)/Nr   z/ensure_order=true cannot be used with this pathr*   ry   r0   z:handle_absent_entries=remove cannot be used with this pathr   r   r#   r   zsEvery element in data must contain "{primary_key}". For example, the element at index #{index} does not provide it.)primary_keyr   c              3   (   K   | ]	  }|     y wr   r|   r\   r   rS   s     r   r]   z)sync_with_primary_keys.<locals>.<genexpr>       G;E+&Gr   zoEvery element in data must contain a unique value for {primary_keys}. The value {value} appears at least twice.,z"{0}")r_   r[   z for {values}rX   z{primary_key}="{value}")r   r[   )r`   c              3   (   K   | ]	  }|     y wr   r|   r   s     r   r]   z)sync_with_primary_keys.<locals>.<genexpr>  r   r   r!   z*Cannot add new entry {values} to this pathr"   c              3   (   K   | ]	  }|     y wr   r|   r   s     r   r]   z)sync_with_primary_keys.<locals>.<genexpr>  s     Rku[1Rr   c              3   (   K   | ]	  }|     y wr   r|   )r\   r   source_entrys     r   r]   z)sync_with_primary_keys.<locals>.<genexpr>	  s     Y[|K8Yr   c              3   (   K   | ]	  }|     y wr   r|   r   s     r   r]   z)sync_with_primary_keys.<locals>.<genexpr>  s     K{k*Kr   r   z{identifier} (ID {id}))
identifierr   r   z9Error while modifying for {identifier} (ID {id}): {error})r   r   rd   c              3   (   K   | ]	  }|     y wr   r|   r   s     r   r]   z)sync_with_primary_keys.<locals>.<genexpr>2  s     O;E+.Or   z4Error while creating entry for {identifier}: {error})r   rd   r   r   zLError while moving entry ID {element_id} to position of ID {new_id}: {error})r   r   rd   r   r   r   r|   )(r_   fixed_entriesr>   r;   r   r   r   r<   r   r   rs   r^   r   r   r   r   r3   rR   rQ   rK   r`   rV   r2   rv   r4   r   r   r   r0   r   r   ra   r	   r   r   r   rw   r   r   r   )-rB   r   r   rA   r   r_   r   new_data_by_keyr   r   pksrZ   r[   r   r   old_data_by_key	id_by_keyr   r   r   r   remove_keysry   r&   r?   r@   rD   rE   r   index_by_key
source_pkssource_indexrF   rG   r   r   element_pksr   new_pksr   r   r   r   rS   r   s-                                              @@r   sync_with_primary_keysr     s   ))L==(!RS==01X=!]^== D!mO!$ %u&uiG!Z!a!ahmpqhq!a!rs' 	K%'   N  U  U$/#ai U  ! 	 G,GG/! F  M  M!$,!7((#E2GNN2$6#EF M    	9f""yy.1,.D"*U .44TY4Z"  # 	
  %9%<  T*HHi0Hh'HxMBH!mOI &G,GG$u	#& HKKKK"MM*AB)//1 9Y#''T2	$0""9U#34""3'	*+=9i&&9925lC2H&.K 288[X]8^&  ' ,(M= OOM*'0'7e$""C#78-9. %++- #	""!M!T!Tyy'3"# .44T]^iTj4k"  "U "  	I.9%NN$		? 	#C~~c"c"	# 		"#  L}}^$v%h/ 	\LE5V[LR\RRS	\#,T? 	?E<YLYYJ'++J7L$UOEKlKKCUC 89$**, ,1:!l"2&'!eLO, OOE8<<#=>	? - #. 
	C	0-0
	 ! 	E+x||PoeY.OPeO,OO!&u	#	 0< 	+KG&{3
"7+#FJFS C		  +%l8Y&GHH&xMJH  1ui01 1ui01 D||  	
V F [NKN;N,O 	I $F"L&"F %&89 	  ELL$(II+.{K+H/ 'C 5;;yQ]_bGchj;k/ / % (l M  !  	 %&89   SZZ#,\3#?(/'l [  !   %&89   NUU#,\P\;]"E"I;];]#^'l V  !   %&89   fmm#-%'l n  !  s   <YYY! Y'-Y, \;]&_,\ ;0[;+'[#[;;\ ]:]]_) ^<	^!^<<_`-``c                 Z   | j                   d   | j                  d       | j                   d   }t        |      dk7  r| j                  d       |d   }t        ||| d       t	        ||      }t        ||      }t        |      dk7  r5| j                  d	j                  t        |      t        |      
             |d   }	t        |	||| d      \  }
}|
r>| j                  s2	  |j                  di |
 t        ||      }t        |      dk(  r|d   }t        |	|       t        ||       i }| j                  r|	|d|d<    | j                   dt#        |
      |	g|gd| y # t        t        f$ r5}| j                  dj                  t        |                   Y d }~d }~ww xY w)NrestrictzVThe restrict option cannot be used with this path, since there is precisely one entry.r*   r   r#   z-Data must be a list with exactly one element.r   r$   zTInternal error: retrieving /{path} resulted in {count} elements. Expected exactly 1.)r   countzError while modifying: {error}r   r   r   r   r|   )r>   r;   ri   rs   r   r   r<   r   rK   r   r   r   r   r	   rw   r   r   r   )rB   r   r   rA   r   r   r@   r   r   r?   rD   rE   r   r   r   s                  r   sync_single_valuer   h  s   }}Z ,uv== D
4yA~LMQIIvr2T*HHi0H
8}fmmt_(m n  	 	
 I $6iIW]_a#b M=  b0-0 $Hi8H8}! ( 9i0=)4 D||"
V F ]# 	% %&89 b  %E%L%LS\]^S_%L%` aabs   %E& &F*5+F%%F*c                     | y | j                   sy | j                  rt        S | j                  rt        S | j
                  st        S y r   )fully_understoodr_   r   single_valuer   has_identifierr   )rA   s    r   get_backendr    sG    %%%%  ##r   c                     | j                   sy| j                  t        | j                        d uS | j                  6| j                  D ]'  \  }}}|s
t	        |t
              rt        |      ' y y)NFT)r   unversionedr  	versioned
isinstancestr)versioned_path_infodummyr  s      r   has_backendr
    sx    //&&2.::;4GG$$0)<)F)F 	%E5+:k3#?KP[D\Dh	 r   c                     t        t        j                         D  cg c]  \  } }t        |      st	        |        c}}       }t        t        dd|      t        ddd      t        dddgd	      t        dg d
d	      t        dd      t        ddg d      t        ddg d            }|j                  t                      |j                  t                      t        |d      }|j                  d   r$|j                  d   dk(  r|j                  d       t        s|j                  t        d             t        |       t        |      }t!        |j                  d         } t        j"                  t%        |             }|j&                  rit)        |      }|j+                  |      \  }}|sHdj-                  dj/                  |       |      }	|rdj-                  |	|      }	|j                  |	       |j1                         }
t3        |
      }|
|1|j                  dj-                  dj/                  |                     t5        ||
      } |||| |
|       y c c}} w )!Nr  T)typerg   choicesrv   r   )r  elementsrg   r/   r0   )r  r  r7   )r/   r0   remove_as_much_as_possibler   F)r  r7   rd   )r/   validaterd   )r  r7   r  r-   )r-   always_updaterd   )r   r   ry   r.   r   rc   r,   )argument_specsupports_check_moder   ry   z7ensure_order=true requires handle_absent_entries=remover*   ordereddictr   z;Path /{path} is not supported for API version {api_version}/)r   api_versionz{0}: {1}z!Path /{path} is not yet supported)r   )r   r   r3   r
  r   r   r   r
   r   r   r>   r;   HAS_ORDEREDDICTr   r   r   r   r:   r   needs_versionr   provide_versionr<   r   get_datar  r   )r   r  path_choicesmodule_argsrB   r   r  	supportednot_supported_msgr+   rA   backendr   s                r   mainr     s;   EKKM~/Ht5H]hi|]}9T?~Lut\Bv>"(7KU]^#8jt|}vu55'CbcE=JstK (*+-/0! F }}^$7N)OS[)[VW1-@Af
V
CfmmF+,D))E$K0((%c*':'J'J;'W$	$OVV\_\d\dei\j  yDV  EC  ''->?%#,,.I)$GGO@GGSXXVZ^G\]1&)DMFCy-8[ s
   I0
I0
__main__N)r$   F)8
__future__r   r   r   r  __metaclass__DOCUMENTATIONEXAMPLESRETURNcollectionsr   ansible.module_utils.basicr   r   +ansible.module_utils.common.text.convertersr	   ?ansible_collections.community.routeros.plugins.module_utils.apir
   r   r   r   Eansible_collections.community.routeros.plugins.module_utils._api_datar   r   r   Gansible_collections.community.routeros.plugins.module_utils._api_helperr   r   r   r  r   ImportErrorr  r   librouteros.exceptionsr   	Exceptionr   rK   rN   rV   ra   rs   rw   r   r   r   r   r   r   r   r   r  r
  r   __name__r|   r   r   <module>r1     s+   C B`D7r!
F $ J A    '	7B(J@	m5p74 m`DN4n$.9b zF [  +   		sH   
B B> B;"B)(B;)	B52B;4B55B;:B;>CC