diff --git a/plugins/module_utils/network/vyos/config/nat/nat.py b/plugins/module_utils/network/vyos/config/nat/nat.py index 0836259b..c5d3c0b2 100644 --- a/plugins/module_utils/network/vyos/config/nat/nat.py +++ b/plugins/module_utils/network/vyos/config/nat/nat.py @@ -1,151 +1,131 @@ # # -*- coding: utf-8 -*- # Copyright 2021 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # from __future__ import absolute_import, division, print_function __metaclass__ = type """ The vyos_nat config file. 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 its desired end-state is created. """ from copy import deepcopy from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.nat import ( NatTemplate, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import combine # from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( # dict_merge, # ) class Nat(ResourceModule): """ The vyos_nat config class """ def __init__(self, module): super(Nat, self).__init__( empty_fact_val={}, facts_module=Facts(module), module=module, resource="nat", tmplt=NatTemplate(), ) self.parsers = [ "nat.cgnat.log_allocation", "nat.cgnat.pool.external", # "nat.cgnat.pool.external.range", # "nat.cgnat.pool.external.external_port_range", # "nat.cgnat.pool.external.external_per_user", - "nat.cgnat.pool.internal.range", + "nat.cgnat.pool.internal", "nat.cgnat.rule.source.pool", - "nat.cgnat.rule.translation.pool", + # "nat.cgnat.rule.translation", "nat_type_description", "nat_type_protocol", "nat_type_disable", "nat_type_exclude", "nat_type_log", "nat_type_address", "nat_type_prefix", "nat_type_fqdn", "nat_type_port", "nat_type_translation_address", "nat_type_translation_port", "nat_inbound_interface_name", "nat_inbound_interface_group", "nat_static_inbound_interface", "nat6x_inbound_interface", "nat_type_outbound_interface", "nat_type_outbound_interface_group", "nat_type_address_group", "nat_type_packet_type", "nat_type_lb_backend", "nat_type_lb_hash", "nat_type_translation_options", "nat_type_translation_redirect", "nat64_match_mark", "nat64_translation_pool_address", "nat64_translation_pool_description", "nat64_translation_pool_disable", "nat64_translation_pool_port", "nat64_translation_pool_protocol", ] def execute_module(self): """Execute the module :rtype: A dictionary :returns: The result from module execution """ if self.state not in ["parsed", "gathered"]: self.generate_commands() self.run_commands() return self.result def generate_commands(self): """Generate configuration commands to send based on want, have and desired state. """ wantd = {} haved = {} wantd = deepcopy(self.want) haved = deepcopy(self.have) # if state is merged, merge want onto have and then compare if self.state == "merged": # wantd = dict_merge(haved, wantd) wantd = combine(haved, wantd, recursive=True, list_merge="append_rp") self._normalize_pool_list_to_dict(wantd) # self._module.fail_json(msg={"want": wantd, " ******** have": haved},) # self._module.fail_json(msg={"merged": wantd, " ******** have": haved, "******** original want": self.want},) - # wantd = { - # "nat": { - # "cgnat": { - # "pool": { - # "external": { - # "ext-pool-1": { - # "name": "ext-pool-1", - # "range": [ - # { - # "address": "192.168.1.0/24", - # "seq": 1, - # }, - # ], - # }, - # }, - # }, - # }, - # }, - # } - # wantd = {"nat": {"cgnat": {"pool": {"external": {}}}}} - # haved = {} + self.compare(parsers=self.parsers, want=wantd, have=haved) self._module.fail_json(msg={"commands": self.commands}) def _normalize_pool_list_to_dict(self, config): """Convert pool.external and pool.internal from list to name-keyed dict.""" cgnat = config.get("nat", {}).get("cgnat", {}) pool = cgnat.get("pool", {}) for pool_type in ("external", "internal"): entries = pool.get(pool_type) if isinstance(entries, list): pool[pool_type] = {item["name"]: item for item in entries} diff --git a/plugins/module_utils/network/vyos/rm_templates/nat.py b/plugins/module_utils/network/vyos/rm_templates/nat.py index 8befccad..fb5449a1 100644 --- a/plugins/module_utils/network/vyos/rm_templates/nat.py +++ b/plugins/module_utils/network/vyos/rm_templates/nat.py @@ -1,1204 +1,1146 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function __metaclass__ = type import re from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( NetworkTemplate, ) def _tmplt_cgnat_pool_ext(config_data): config_data = config_data["nat"]["cgnat"]["pool"]["external"] + command = [] - # cmd = "nat cgnat pool external {name}".format(**config_data) - cmd = "nat cgnat pool external {name}".format(**config_data) - # for key, value in config_data.items(): - # if ( - # key == "name" - # or isinstance(value, dict) - # or isinstance(value, list) - # or isinstance(value, bool) - # or value is None - # ): - # continue - # else: - # if key == "description": - # value = f"'{value}'" - # command.append(f"{cmd} {key.replace('_', '-')} {value}") - return str(cmd) + for m, pool in config_data.items(): + name = pool["name"] + base_cmd = f"nat cgnat pool external {name}" + + if pool.get("external_port_range") is not None: + command.append( + f"{base_cmd} external-port-range " f"{pool['external_port_range']}", + ) + + per_user = pool.get("per_user_limit") + if per_user and per_user.get("port") is not None: + command.append( + f"{base_cmd} per-user-limit port " f"{per_user['port']}", + ) + + for rng in pool.get("range", []): + if isinstance(rng, dict): + cmd = f"{base_cmd} range {rng['address']}" + + if rng.get("seq") is not None: + cmd += f" seq {rng['seq']}" + + command.append(cmd) + + else: + command.append(f"{base_cmd} range {rng}") + + return command + + +def _tmplt_cgnat_pool_int(config_data): + config_data = config_data["nat"]["cgnat"]["pool"]["internal"] + + command = [] + + for _, pool in config_data.items(): + name = pool["name"] + base_cmd = f"nat cgnat pool internal {name}" + + for rng in pool.get("range", []): + command.append(f"{base_cmd} range {rng['address']}") + + return command + + +def _render_cgnat_rule_pool(config_data, section): + rules = config_data["nat"]["cgnat"]["rule"] + + command = [] + + for rule in rules: + rid = rule["id"] + + data = rule.get(section) + if data and data.get("pool") is not None: + command.append( + f"nat cgnat rule {rid} {section} pool {data['pool']}", + ) + + return command + + +def _tmplt_cgnat_rule_source_pool(config_data): + return _render_cgnat_rule_pool(config_data, "source") + + +def _tmplt_cgnat_rule_translation_pool(config_data): + return _render_cgnat_rule_pool(config_data, "translation") class NatTemplate(NetworkTemplate): def __init__(self, lines=None, module=None): prefix = {"set": "set", "remove": "delete"} super(NatTemplate, self).__init__(lines=lines, tmplt=self, prefix=prefix, module=module) # fmt: off PARSERS = [ - - # - # ------------------------- - # CGNAT (keep explicit) - # ------------------------- - # { "name": "nat.cgnat.log_allocation", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+log-allocation $""", re.VERBOSE, ), "setval": "nat cgnat log-allocation", "result": { "nat": { "cgnat": { "log_allocation": True, }, }, }, }, { "name": "nat.cgnat.pool.external", "getval": re.compile( r""" ^set\s+nat\s+cgnat\s+pool\s+external\s+(?P\S+) (?: \s+external-port-range\s+(?P\S+) | \s+range\s+(?P\S+)(?:\s+seq\s+(?P\d+))? | \s+per-user-limit\s+port\s+(?P\d+) )? $ """, re.VERBOSE, ), "setval": _tmplt_cgnat_pool_ext, "result": { "nat": { "cgnat": { "pool": { "external": { "{{ name }}": { "name": "{{ name }}", "external_port_range": "{{ port_range }}", "per_user_limit": { "port": "{{ limit }}", }, "range": [ { "address": "{{ range }}", "seq": "{{ seq }}", }, ], }, }, }, }, }, }, }, - # { - # "name": "nat.cgnat.pool.external.range", - # "getval": re.compile( - # r""" - # ^set - # \s+nat - # \s+cgnat - # \s+pool - # \s+external - # \s+(?P\S+) - # \s+range - # \s+(?P\S+)(?:\s+seq\s+(?P\d+))? - # $""", - # re.VERBOSE, - # ), - # "setval": "nat cgnat pool external {{ name }} range {{ range }}{% if seq is defined %} seq {{ seq }}{% endif %}", - # "result": { - # "nat": { - # "cgnat": { - # "pool": { - # "external": { - # "{{ name }}": { - # "name": "{{ name }}", - # "range": [ - # { - # "address": "{{ range }}", - # "seq": "{{ seq }}", - # }, - # ], - # }, - # }, - # }, - # }, - # }, - # }, - # }, - # { - # "name": "nat.cgnat.pool.external.external_port_range", - # "getval": re.compile( - # r""" - # ^set - # \s+nat - # \s+cgnat - # \s+pool - # \s+external - # \s+(?P\S+) - # \s+external-port-range - # \s+(?P\S+) - # $""", - # re.VERBOSE, - # ), - # # "setval": "nat cgnat pool external {{ name }} external-port-range {{ port_range }}", - # "setval": "test", - # "result": { - # "nat": { - # "cgnat": { - # "pool": { - # "external": { - # "{{ name }}": { - # "name": "{{ name }}", - # "external_port_range": "{{ port_range }}", - # }, - # }, - # }, - # }, - # }, - # }, - # }, - # { - # "name": "nat.cgnat.pool.external.external_per_user", - # "getval": re.compile( - # r""" - # ^set - # \s+nat - # \s+cgnat - # \s+pool - # \s+external - # \s+(?P\S+) - # \s+per-user-limit - # \s+port - # \s+(?P\d+) - # $""", - # re.VERBOSE, - # ), - # "setval": "nat cgnat pool external {{ name }} per-user-limit port {{ limit }}", - # "result": { - # "nat": { - # "cgnat": { - # "pool": { - # "external": { - # "{{ name }}": { - # "name": "{{ name }}", - # "per_user_limit": {"port": "{{ limit }}"}, - # }, - # }, - # }, - # }, - # }, - # }, - # }, { - "name": "nat.cgnat.pool.internal.range", + "name": "nat.cgnat.pool.internal", "getval": re.compile( r""" - ^set - \s+nat - \s+cgnat - \s+pool - \s+internal - \s+(?P\S+) - \s+range - \s+(?P\S+) - $""", + ^set\s+nat\s+cgnat\s+pool\s+internal\s+(?P\S+) + (?: + \s+range\s+(?P\S+) + )? + $ + """, re.VERBOSE, ), - "setval": "nat cgnat pool internal {{ name }} range {{ range }}", + "setval": _tmplt_cgnat_pool_int, "result": { "nat": { "cgnat": { "pool": { "internal": { "{{ name }}": { "name": "{{ name }}", - "range": ["{{ range }}"], + "range": [ + { + "address": "{{ range }}", + }, + ], }, }, }, }, }, }, }, { "name": "nat.cgnat.rule.source.pool", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+rule \s+(?P\d+) \s+source \s+pool \s+(?P\S+) $""", re.VERBOSE, ), - "setval": "nat cgnat rule {{ id }} source pool {{ pool }}", + "setval": _tmplt_cgnat_rule_source_pool, "result": { "nat": { "cgnat": { "rule": { "{{ id }}": { "id": "{{ id }}", "source": {"pool": "{{ pool }}"}, }, }, }, }, }, }, { "name": "nat.cgnat.rule.translation.pool", "getval": re.compile( r""" ^set \s+nat \s+cgnat \s+rule \s+(?P\d+) \s+translation \s+pool \s+(?P\S+) $""", re.VERBOSE, ), - "setval": "nat cgnat rule {{ id }} translation pool {{ pool }}", + "setval": _tmplt_cgnat_rule_translation_pool, "result": { "nat": { "cgnat": { "rule": { "{{ id }}": { "id": "{{ id }}", "translation": {"pool": "{{ pool }}"}, }, }, }, }, }, }, - # - # ------------------------- - # GENERIC NAT (destination/source/static) - # ------------------------- - # - # description { "name": "nat_type_description", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+description \s+(?P.+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} description {{ description }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "description": "{{ description }}", }, ], }, }, }, }, # protocol { "name": "nat_type_protocol", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+protocol \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} protocol {{ protocol }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "protocol": "{{ protocol }}", }, ], }, }, }, }, # flags { "name": "nat_type_disable", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+disable $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} disable", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "disable": True, }, ], }, }, }, }, { "name": "nat_type_exclude", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+exclude $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} exclude", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "exclude": True, }, ], }, }, }, }, { "name": "nat_type_log", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+log $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} log", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "log": True, }, ], }, }, }, }, # address (destination/source) { "name": "nat_type_address", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+address \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} address {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"address": "{{ value }}"}, }, ], }, }, }, }, # prefix (destination/source) { "name": "nat_type_prefix", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+prefix \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} prefix {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"prefix": "{{ value }}"}, }, ], }, }, }, }, # fqdn { "name": "nat_type_fqdn", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+fqdn \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} fqdn {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"fqdn": "{{ value }}"}, }, ], }, }, }, }, # port { "name": "nat_type_port", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} port {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": {"port": "{{ value }}"}, }, ], }, }, }, }, # translation address { "name": "nat_type_translation_address", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+translation \s+address \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation address {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": {"address": "{{ value }}"}, }, ], }, }, }, }, # translation port { "name": "nat_type_translation_port", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+translation \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation port {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": {"port": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_inbound_interface_name", "getval": re.compile( r""" ^set \s+nat \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+inbound-interface \s+name \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat {{ type }} rule {{ id }} inbound-interface name {{ value }}", "result": { "nat": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "inbound_interface": {"name": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_inbound_interface_group", "getval": re.compile( r""" ^set \s+nat \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+inbound-interface \s+group \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat {{ type }} rule {{ id }} inbound-interface group {{ value }}", "result": { "nat": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "inbound_interface": {"group": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_static_inbound_interface", "getval": re.compile( r""" ^set \s+nat \s+static \s+rule \s+(?P\S+) \s+inbound-interface \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat static rule {{ id }} inbound-interface {{ value }}", "result": { "nat": { "static": { "rule": [ { "id": "{{ id }}", "inbound_interface": "{{ value }}", }, ], }, }, }, }, # NAT6X inbound interface { "name": "nat6x_inbound_interface", "getval": re.compile( r""" ^set \s+(?Pnat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+inbound-interface \s+name \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} inbound-interface name {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "inbound_interface": {"name": "{{ value }}"}, }, ], }, }, }, }, # outbound interface { "name": "nat_type_outbound_interface", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+outbound-interface \s+name \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} outbound-interface name {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "outbound_interface": {"name": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_type_outbound_interface_group", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source|static) \s+rule \s+(?P\S+) \s+outbound-interface \s+group \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} outbound-interface group {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "outbound_interface": {"group": "{{ value }}"}, }, ], }, }, }, }, { "name": "nat_type_address_group", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+(?Pdestination|source) \s+group \s+(?Paddress-group|domain-group|mac-group|network-group|port-group) \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} {{ atype }} group {{ gtype }} {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "{{ atype }}": { "{{ gtype | replace('-', '_') }}": "{{ value }}", }, }, ], }, }, }, }, # packet type { "name": "nat_type_packet_type", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+packet-type \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} packet-type {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "packet_type": "{{ value }}", }, ], }, }, }, }, # load balance backend { "name": "nat_type_lb_backend", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+load-balance \s+backend \s+(?P\S+) \s+weight \s+(?P\d+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} load-balance backend {{ ip }} weight {{ weight }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "load_balance": { "backend": { "ip": "{{ ip }}", "weight": "{{ weight }}", }, }, }, ], }, }, }, }, # load balance hash { "name": "nat_type_lb_hash", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+load-balance \s+hash \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} load-balance hash {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "load_balance": {"hash": "{{ value }}"}, }, ], }, }, }, }, # translation options { "name": "nat_type_translation_options", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+translation \s+options \s+(?Paddress-mapping|port-mapping) \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation options {{ opt }} {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": { "{{ opt | replace(\"-\", \"_\") }}": "{{ value }}", }, }, ], }, }, }, }, # redirect port { "name": "nat_type_translation_redirect", "getval": re.compile( r""" ^set \s+(?Pnat|nat64|nat66) \s+(?Pdestination|source) \s+rule \s+(?P\S+) \s+translation \s+redirect \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "{{ nat }} {{ type }} rule {{ id }} translation redirect port {{ value }}", "result": { "{{ nat }}": { "{{ type }}": { "rule": [ { "id": "{{ id }}", "translation": { "redirect_port": "{{ value }}", }, }, ], }, }, }, }, { "name": "nat64_match_mark", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+match \s+mark \s+(?P\d+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} match mark {{ mark }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "match": {"mark": "{{ mark }}"}, }, ], }, }, }, }, { "name": "nat64_translation_pool_address", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+address \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} address {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "address": "{{ value }}"}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_description", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+description \s+(?P.+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} description {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "description": "{{ value }}"}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_disable", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+disable $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} disable", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "disable": True}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_port", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+port \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} port {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "port": "{{ value }}"}], }, }, ], }, }, }, }, { "name": "nat64_translation_pool_protocol", "getval": re.compile( r""" ^set \s+nat64 \s+source \s+rule \s+(?P\S+) \s+translation \s+pool \s+(?P\d+) \s+protocol \s+(?P\S+) $""", re.VERBOSE, ), "setval": "nat64 source rule {{ id }} translation pool {{ pool_id }} protocol {{ value }}", "result": { "nat64": { "source": { "rule": [ { "id": "{{ id }}", "translation": { "pool": [{"id": "{{ pool_id }}", "protocol": "{{ value }}"}], }, }, ], }, }, }, }, ] # fmt: on