diff --git a/ntc_rosetta/__init__.py b/ntc_rosetta/__init__.py index 4b31832..e75d80e 100644 --- a/ntc_rosetta/__init__.py +++ b/ntc_rosetta/__init__.py @@ -1,6 +1,6 @@ from typing import Dict, Type -from ntc_rosetta.drivers import ios, junos +from ntc_rosetta.drivers import ios, junos, vyos from ntc_rosetta.drivers.base import Driver @@ -15,7 +15,12 @@ def get_driver(driver: str, model: str = "openconfig") -> Type[Driver]: "openconfig": { "ios": ios.IOSDriverOpenconfig, "junos": junos.JunosDriverOpenconfig, + "vyos": vyos.VyOSDriverOpenconfig, + }, + "ntc": { + "ios": ios.IOSDriverNTC, + "junos": junos.JunosDriverNTC, + "vyos": vyos.VyOSDriverNTC, }, - "ntc": {"ios": ios.IOSDriverNTC, "junos": junos.JunosDriverNTC}, } return mapping[model][driver] diff --git a/ntc_rosetta/drivers/vyos.py b/ntc_rosetta/drivers/vyos.py new file mode 100644 index 0000000..919d47e --- /dev/null +++ b/ntc_rosetta/drivers/vyos.py @@ -0,0 +1,17 @@ +from ntc_rosetta.drivers.base import Driver +from ntc_rosetta.parsers.ntc.vyos import VyOSParser as NTCVyOSParser +from ntc_rosetta.parsers.openconfig.vyos import VyOSParser as OCVyOSParser +from ntc_rosetta.translators.ntc.vyos import VyOSTranslator as NTCVyOSTranslator +from ntc_rosetta.translators.openconfig.vyos import VyOSTranslator as OCVyOSTranslator + + +class VyOSDriverOpenconfig(Driver): + parser = OCVyOSParser + translator = OCVyOSTranslator + datamodel_name = "openconfig" + + +class VyOSDriverNTC(Driver): + parser = NTCVyOSParser + translator = NTCVyOSTranslator + datamodel_name = "ntc" diff --git a/ntc_rosetta/helpers/request_list.py b/ntc_rosetta/helpers/request_list.py new file mode 100644 index 0000000..ded0757 --- /dev/null +++ b/ntc_rosetta/helpers/request_list.py @@ -0,0 +1,30 @@ +import json +from typing import List, Dict, Any + + +class RequestList: + def __init__(self) -> None: + self.requests: List[Dict[str, Any]] = [] + self.pre_path: List[str] = [] + + def set(self, path: List[str], value: str, use_pre_path: bool = False) -> None: + if use_pre_path: + path = self.pre_path + path + self.requests.append({"op": "set", "path": path, "value": value}) + + def delete(self, path: List[str], value: str, use_pre_path: bool = False) -> None: + if use_pre_path: + path = self.pre_path + path + self.requests.append({"op": "delete", "path": path, "value": value}) + + # This is in preparation for possible move to using HTTP/API instead SSH for commands + def to_json(self) -> str: + return json.dumps(self.requests, indent=2) + + def to_set(self) -> str: + result = "" + for request in self.requests: + result += ( + f'{request["op"]} {" ".join(request["path"])} \'{request["value"]}\'\n' + ) + return result diff --git a/ntc_rosetta/helpers/vyos.py b/ntc_rosetta/helpers/vyos.py new file mode 100644 index 0000000..bec45fb --- /dev/null +++ b/ntc_rosetta/helpers/vyos.py @@ -0,0 +1,77 @@ +"""VyOS helper consts and methods""" +from typing import Dict, Any, List + +SYSLOG_FACILITY = { + "all": "ALL", + "auth": "AUTH", + "authpriv": "AUTHPRIV", + "cron": None, + "daemon": "SYSTEM_DAEMON", + "kern": "KERNEL", + "lpr": None, + "mail": "MAIL", + "mark": None, + "news": None, + "protocols": "LOCAL7", + "security": "AUTH", + "syslog": "SYSLOG", + "user": "USER", + "uucp": None, + "local0": "LOCAL0", + "local1": "LOCAL1", + "local2": "LOCAL2", + "local3": "LOCAL3", + "local4": "LOCAL4", + "local5": "LOCAL5", + "local6": "LOCAL6", + "local7": "LOCAL7", +} +SYSLOG_SEVERITY = { + "emerg": "EMERGENCY", + "alert": "ALERT", + "crit": "CRITICAL", + "err": "ERROR", + "warning": "WARNING", + "notice": "NOTICE", + "info": "INFORMATIONAL", + "debug": "DEBUG", + "all": "DEBUG", +} + + +def parse_config_tree(config: List[str]) -> Dict[str, Any]: + parsed: Dict[str, Any] = {} + while True: + if not config: + break + line = config.pop(0).rstrip() + if line.lstrip().startswith("/*"): + continue + nodes = line.lstrip().split() + if nodes[-1] == "{": + if len(nodes) > 2: + parsed.setdefault(nodes[0], {}).update( + {nodes[1]: parse_config_tree(config)} + ) + else: + parsed[nodes[0]] = parse_config_tree(config) + elif nodes[-1] == "}": + break + else: + if len(nodes) == 1: + parsed[nodes[0]] = "" + else: + if nodes[1].startswith('"'): + nodes[1] = nodes[1].lstrip('"') + nodes[-1] = nodes[-1].rstrip('"') + value = " ".join(nodes[1:]) + else: + value = str(nodes[1]) + if nodes[0] in parsed: + if isinstance(parsed[nodes[0]], list): + parsed[nodes[0]].append(value) + else: + parsed[nodes[0]] = [parsed[nodes[0]], value] + else: + parsed[nodes[0]] = value + return parsed diff --git a/ntc_rosetta/parsers/__init__.py b/ntc_rosetta/parsers/__init__.py index d046fe7..8efc488 100644 --- a/ntc_rosetta/parsers/__init__.py +++ b/ntc_rosetta/parsers/__init__.py @@ -1,4 +1,5 @@ from ntc_rosetta.parsers.openconfig.ios import IOSParser from ntc_rosetta.parsers.openconfig.junos import JunosParser +from ntc_rosetta.parsers.openconfig.vyos import VyOSParser -__all__ = ("IOSParser", "JunosParser") +__all__ = ("IOSParser", "JunosParser", "VyOSParser") diff --git a/ntc_rosetta/parsers/ntc/vyos/__init__.py b/ntc_rosetta/parsers/ntc/vyos/__init__.py new file mode 100644 index 0000000..557572f --- /dev/null +++ b/ntc_rosetta/parsers/ntc/vyos/__init__.py @@ -0,0 +1,5 @@ +from yangify import parser + + +class VyOSParser(parser.RootParser): + pass diff --git a/ntc_rosetta/parsers/openconfig/vyos/__init__.py b/ntc_rosetta/parsers/openconfig/vyos/__init__.py new file mode 100644 index 0000000..c3039c5 --- /dev/null +++ b/ntc_rosetta/parsers/openconfig/vyos/__init__.py @@ -0,0 +1,29 @@ +from yangify import parser + +from ntc_rosetta.helpers.vyos import parse_config_tree +from ntc_rosetta.parsers.openconfig.vyos.openconfig_interfaces.interfaces import ( + Interfaces, +) +from ntc_rosetta.parsers.openconfig.vyos.openconfig_network_instance.network_instances import ( + NetworkInstances, +) +from ntc_rosetta.parsers.openconfig.vyos.openconfig_system.system import System + + +class VyOSParser(parser.RootParser): + """ + VyOSParser expects as native data a dictionary where the `dev_conf` + key is reserved for the device configuration. + """ + + class Yangify(parser.ParserData): + def init(self) -> None: + self.root_native["dev_conf"] = parse_config_tree( + self.root_native["dev_conf"].splitlines() + ) + # self.root_native["dev_conf"] = json.loads(self.root_native["dev_conf"]) + self.native["dev_conf"] = self.root_native["dev_conf"] + + interfaces = Interfaces + network_instances = NetworkInstances + system = System diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_if_ethernet/__init__.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_if_ethernet/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_if_ethernet/ethernet.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_if_ethernet/ethernet.py new file mode 100644 index 0000000..662ef17 --- /dev/null +++ b/ntc_rosetta/parsers/openconfig/vyos/openconfig_if_ethernet/ethernet.py @@ -0,0 +1,8 @@ +from yangify.parser import Parser, ParserData + + +class Ethernet(Parser): + class Yangify(ParserData): + path = ( + "openconfig-interfaces:interfaces/interface/openconfig-if-ethernet:ethernet" + ) diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_interfaces/__init__.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_interfaces/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_interfaces/interfaces.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_interfaces/interfaces.py new file mode 100644 index 0000000..e352a03 --- /dev/null +++ b/ntc_rosetta/parsers/openconfig/vyos/openconfig_interfaces/interfaces.py @@ -0,0 +1,121 @@ +from typing import Any, Dict, Iterator, Optional, Tuple, cast + +from ntc_rosetta.parsers.openconfig.vyos.openconfig_if_ethernet import ethernet +from ntc_rosetta.parsers.openconfig.vyos.openconfig_vlan import vlan + +from yangify.parser import Parser, ParserData + + +class SubinterfaceConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/config" + + def description(self) -> Optional[str]: + return self.yy.native.get("description") + + def enabled(self) -> bool: + return "disable" not in self.yy.native + + def index(self) -> int: + if isinstance(self.yy.key, str): + return int(self.yy.key) + vlan_s = self.yy.key[0] + vlan_c = self.yy.key[1] + prepends = 4 - len(vlan_c) + vlan_c = ("0" * prepends) + vlan_c + return int(vlan_s + vlan_c) + + +class Subinterface(Parser): + class Yangify(ParserData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface" + + def extract_elements(self) -> Iterator[Tuple[str, Any]]: + for k, v in self.native.get("vif", {}).items(): + yield k, v + for k_s, v_s in self.native.get("vif-s", {}).items(): + # yield k_s, v_s + for k_c, v_c in v_s.get("vif-c", {}).items(): + yield (k_s, k_c), v_c + + config = SubinterfaceConfig + vlan = vlan.Vlan + + def index(self) -> int: + if isinstance(self.yy.key, str): + return int(self.yy.key) + vlan_s = self.yy.key[0] + vlan_c = self.yy.key[1] + prepends = 4 - len(vlan_c) + vlan_c = ("0" * prepends) + vlan_c + return int(vlan_s + vlan_c) + + +class Subinterfaces(Parser): + class Yangify(ParserData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces" + + subinterface = Subinterface + + +class InterfaceConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-interfaces:interfaces/interface/config" + + def description(self) -> Optional[str]: + return self.yy.native.get("description") + + def enabled(self) -> bool: + return "disable" not in self.yy.native + + def name(self) -> str: + return cast(str, self.yy.key) + + def type(self) -> Optional[str]: + if self.yy.key.startswith("eth"): + return "iana-if-type:ethernetCsmacd" + elif self.yy.key.startswith("lo"): + return "iana-if-type:softwareLoopback" + elif self.yy.key.startswith("bond"): + return "iana-if-type:ieee8023adLag" + elif self.yy.key.startswith("br"): + return "iana-if-type:bridge" + elif self.yy.key.startswith("macsec"): + return "iana-if-type:macSecControlledIF" + elif self.yy.key.startswith("tunnel"): + return "iana-if-type:tunnel" + else: + raise Exception(f"don't know the type for {self.yy.key}") + + def mtu(self) -> Optional[int]: + mtu = self.yy.native.get("mtu") + return int(mtu) if mtu else None + + +class Interface(Parser): + class Yangify(ParserData): + path = "/openconfig-interfaces:interfaces/interface" + + def extract_elements(self) -> Iterator[Tuple[str, Any]]: + if "interfaces" in self.native: + for interfaces in self.native["interfaces"].values(): + for k, v in interfaces.items(): + yield k, v + + config = InterfaceConfig + subinterfaces = Subinterfaces + ethernet = ethernet.Ethernet + + def name(self) -> str: + return cast(str, self.yy.key) + + +class Interfaces(Parser): + interface = Interface + + class Yangify(ParserData): + path = "/openconfig-interfaces:interfaces" + metadata = {"key": "dev_conf", "rpc": "showConfig"} + + def pre_process(self) -> None: + self.native: Dict[str, Any] = self.root_native["dev_conf"] diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_network_instance/__init__.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_network_instance/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_network_instance/network_instances.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_network_instance/network_instances.py new file mode 100644 index 0000000..10e7edf --- /dev/null +++ b/ntc_rosetta/parsers/openconfig/vyos/openconfig_network_instance/network_instances.py @@ -0,0 +1,41 @@ +from typing import Any, Dict, Iterator, Tuple, cast + +from yangify.parser import Parser, ParserData + + +class NetworkInstanceConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-network-instance:network-instances/network-instance/config" + + def name(self) -> str: + return cast(str, self.yy.key) + + def description(self) -> str: + return self.yy.native.get("description") + + +class NetworkInstance(Parser): + class Yangify(ParserData): + path = "/openconfig-network-instance:network-instances/network-instance" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + yield "default", self.root_native["dev_conf"] + if "vrf" in self.native: + for k, v in self.native["vrf"]["name"].items(): + yield k, v + + config = NetworkInstanceConfig + + def name(self) -> str: + return cast(str, self.yy.key) + + +class NetworkInstances(Parser): + class Yangify(ParserData): + path = "/openconfig-network-instance:network-instances" + metadata = {"key": "dev_conf", "rpc": "showConfig"} + + def pre_process(self) -> None: + self.native: Dict[str, Any] = self.root_native["dev_conf"] + + network_instance = NetworkInstance diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_system/__init__.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_system/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_system/system.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_system/system.py new file mode 100644 index 0000000..e268a36 --- /dev/null +++ b/ntc_rosetta/parsers/openconfig/vyos/openconfig_system/system.py @@ -0,0 +1,574 @@ +from ipaddress import ip_address, IPv4Address, IPv6Address +from typing import Dict, Any, Optional, List, Iterator, Tuple + +from yangify.parser import Parser, ParserData + +from ntc_rosetta.helpers.vyos import SYSLOG_FACILITY, SYSLOG_SEVERITY + + +class AaaAuthenticationUserConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/authentication/users/user/config" + + def username(self) -> str: + return str(self.yy.key) + + def role(self) -> Optional[str]: + return "openconfig-aaa:SYSTEM_ROLE_ADMIN" + + def password(self) -> Optional[str]: + authentication = self.yy.native.get("authentication") + if authentication: + return authentication.get("plaintext-password") + + def password_hashed(self) -> Optional[str]: + authentication = self.yy.native.get("authentication") + if authentication: + return authentication.get("encrypted-password") + + def ssh_key(self) -> Optional[str]: + authentication = self.yy.native.get("authentication") + if authentication and "public-keys" in authentication: + for v in authentication.get("public-keys").values(): + # only return the first key + return v["key"] + + +class AaaAuthenticationUser(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/authentication/users/user" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + for k, v in self.native.get("user").items(): + yield k, v + + def username(self) -> str: + return str(self.yy.key) + + config = AaaAuthenticationUserConfig + + +class AaaAuthenticationUsers(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/authentication/users" + + user = AaaAuthenticationUser + + +class AaaAuthenticationConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/authentication/config" + + def authentication_method(self) -> List[str]: + return ["openconfig-aaa:RADIUS_ALL", "openconfig-aaa:LOCAL"] + + +class AaaAuthentication(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/authentication" + + config = AaaAuthenticationConfig + users = AaaAuthenticationUsers + + +class AaaRadiusConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers/server/radius/config" + + def auth_port(self) -> Optional[int]: + port = self.yy.native.get("port") + if port: + return int(port) + + def secret_key(self) -> Optional[str]: + return self.yy.native.get("key") + + def source_address(self) -> Optional[str]: + return ( + self.yy.root_native["dev_conf"] + .get("system") + .get("login") + .get("radius") + .get("source-address") + ) + + +class AaaRadius(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers/server/radius" + + config = AaaRadiusConfig + + +class AaaServerGroupServersServerConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers/server/config" + + def address(self) -> str: + return self.yy.key + + +class AaaServerGroupServersServer(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers/server" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + if self.native and "server" in self.native: + for k, v in self.native["server"].items(): + yield k, v + + def address(self) -> str: + return self.yy.key + + radius = AaaRadius + config = AaaServerGroupServersServerConfig + + +class AaaServerGroupServers(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers" + + server = AaaServerGroupServersServer + + +class AaaServerGroupConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups/server-group/config" + + def pre_process(self) -> None: + self.native = ( + self.root_native["dev_conf"].get("system").get("login").get("radius") + ) + + def name(self) -> str: + return self.yy.key + + def type(self): + return "openconfig-aaa:RADIUS" + + +class AaaServerGroup(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups/server-group" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + if self.native and "server" in self.native: + yield "radius", self.native.get("radius") + + def name(self) -> str: + # Reference to configured name of the server group + return self.yy.key + + servers = AaaServerGroupServers + config = AaaServerGroupConfig + + +class AaaServerGroups(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/server-groups" + + server_group = AaaServerGroup + + +class AaaAuthorizationConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/authorization/config" + + def authorization_method(self) -> List[str]: + return ["openconfig-aaa:RADIUS_ALL", "openconfig-aaa:LOCAL"] + + +class AaaAuthorization(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa/authorization" + + config = AaaAuthorizationConfig + + +class Aaa(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/aaa" + + def pre_process(self) -> None: + self.native = self.root_native["dev_conf"].get("system").get("login") + + authentication = AaaAuthentication + authorization = AaaAuthorization + server_groups = AaaServerGroups + + +class SshServerConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/ssh-server/config" + + def enable(self) -> bool: + return "ssh" in self.yy.native + + def timeout(self) -> Optional[int]: + return None + + def rate_limit(self) -> Optional[int]: + return None + + def session_limit(self) -> Optional[int]: + return None + + +class SshServer(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/ssh-server" + + def pre_process(self) -> None: + self.native = self.root_native["dev_conf"].get("service") + + config = SshServerConfig + + +class NtpConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/ntp/config" + + def enabled(self) -> bool: + return "ntp" in self.yy.native + + +class NtpServerConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/ntp/servers/server/config" + + def address(self) -> str: + return str(self.yy.key) + + def prefer(self) -> Optional[bool]: + return "prefer" in self.yy.native + + +class NtpServer(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/ntp/servers/server" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + ntp = self.native.get("ntp") + if ntp: + for k, v in ntp.get("server").items(): + yield k, v + + def address(self) -> str: + return str(self.yy.key) + + config = NtpServerConfig + + +class NtpServers(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/ntp/servers" + + server = NtpServer + + +class Ntp(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/ntp" + + def pre_process(self) -> None: + self.native = self.root_native["dev_conf"].get("system") + + config = NtpConfig + servers = NtpServers + + +class DnsServerConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns/servers/server/config" + + def address(self) -> str: + return str(self.yy.key) + + def port(self) -> int: + return 53 + + +class DnsServer(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns/servers/server" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + if self.native.get("name-server"): + for i in self.native["name-server"]: + yield i, i + + def address(self) -> str: + return str(self.yy.key) + + config = DnsServerConfig + + +class DnsServers(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns/servers" + + server = DnsServer + + +class DnsConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns/config" + + def search(self) -> Optional[List[str]]: + domain_search = self.yy.native.get("domain-search") + if domain_search: + return domain_search.get("domain") + + +class HostEntryConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns/host-entries/host-entry/config" + + def hostname(self) -> str: + return self.yy.key + + def alias(self) -> Optional[List[str]]: + return [self.yy.native.get("alias")] + + def ipv4_address(self) -> Optional[List[str]]: + inet = self.yy.native["inet"] + try: + if type(ip_address(inet)) is IPv4Address: + return [inet] + except ValueError: + raise Exception(f"address is not valid IPv4 for host entry {self.yy.key}") + + def ipv6_address(self) -> Optional[List[str]]: + inet = self.yy.native["inet"] + try: + if type(ip_address(inet)) is IPv6Address: + return [inet] + except ValueError: + raise Exception(f"address is not valid IPv6 for host entry {self.yy.key}") + + +class HostEntry(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns/host-entries/host-entry" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + static_host_mapping = self.native.get("static-host-mapping") + if static_host_mapping: + for k, v in static_host_mapping.get("host-name").items(): + yield k, v + + def hostname(self) -> str: + return str(self.yy.key) + + config = HostEntryConfig + + +class HostEntries(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns/host-entries" + + host_entry = HostEntry + + +class Dns(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/dns" + + def pre_process(self) -> None: + self.native = self.root_native["dev_conf"].get("system") + + config = DnsConfig + servers = DnsServers + host_entries = HostEntries + + +class ClockConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/clock/config" + + def pre_process(self) -> None: + self.native = self.root_native["dev_conf"].get("system") + + def timezone_name(self) -> str: + return self.yy.native.get("time-zone") + + +class Clock(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/clock" + + config = ClockConfig + + +class SystemConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/config" + + def pre_process(self) -> None: + self.native = self.root_native["dev_conf"].get("system") + + def hostname(self) -> Optional[str]: + return self.yy.native.get("host-name") + + def domain_name(self) -> Optional[str]: + return self.yy.native.get("domain-name") + + def login_banner(self) -> Optional[str]: + banner = self.yy.native.get("login").get("banner") + if banner: + return banner.get("pre-login") + + def motd_banner(self) -> Optional[str]: + banner = self.yy.native.get("login").get("banner") + if banner: + return banner.get("post-login") + + +class ConsoleSelectorConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/console/selectors/selector/config" + + def facility(self) -> str: + return SYSLOG_FACILITY[self.yy.key] + + def severity(self) -> str: + return SYSLOG_SEVERITY[self.yy.native["level"]] + + +class ConsoleSelector(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/console/selectors/selector" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + if self.native and "facility" in self.native: + for k, v in self.native["facility"].items(): + if SYSLOG_FACILITY[k]: + yield k, v + + def facility(self) -> str: + return SYSLOG_FACILITY[self.yy.key] + + def severity(self) -> str: + return SYSLOG_SEVERITY[self.yy.native["level"]] + + config = ConsoleSelectorConfig + + +class ConsoleSelectors(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/console/selectors" + + selector = ConsoleSelector + + +class Console(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/console" + + def pre_process(self) -> None: + self.native = ( + self.root_native["dev_conf"].get("system").get("syslog").get("console") + ) + + selectors = ConsoleSelectors + + +class RemoteServerConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/remote-servers/remote-server/config" + + def host(self) -> str: + return self.yy.key + + def remote_port(self) -> Optional[int]: + return int(self.yy.native.get("port", 514)) + + +class RemoteServerSelectorConfig(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/remote-servers/remote-server/selectors/selector/config" + + def facility(self) -> str: + return SYSLOG_FACILITY[self.yy.key] + + def severity(self) -> str: + return SYSLOG_SEVERITY[self.yy.native["level"]] + + +class RemoteServerSelector(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/remote-servers/remote-server/selectors/selector" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + if self.native and "facility" in self.native: + for k, v in self.native["facility"].items(): + if SYSLOG_FACILITY[k]: + yield k, v + + def facility(self) -> str: + return SYSLOG_FACILITY[self.yy.key] + + def severity(self) -> str: + return SYSLOG_SEVERITY[self.yy.native["level"]] + + config = RemoteServerSelectorConfig + + +class RemoteServerSelectors(Parser): + class Yangify(ParserData): + path = ( + "/openconfig-system:system/logging/remote-servers/remote-server/selectors" + ) + + selector = RemoteServerSelector + + +class RemoteServer(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/remote-servers/remote-server" + + def extract_elements(self) -> Iterator[Tuple[str, Dict[str, Any]]]: + hosts = self.native.get("syslog").get("host") + if hosts: + for k, v in hosts.items(): + yield k, v + + def host(self) -> str: + return self.yy.key + + config = RemoteServerConfig + selectors = RemoteServerSelectors + + +class RemoteServers(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging/remote-servers" + + remote_server = RemoteServer + + +class Logging(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system/logging" + + def pre_process(self) -> None: + self.native = self.root_native["dev_conf"].get("system") + + console = Console + remote_servers = RemoteServers + + +class System(Parser): + class Yangify(ParserData): + path = "/openconfig-system:system" + + def pre_process(self) -> None: + self.native: Dict[str, Any] = self.root_native["dev_conf"] + + config = SystemConfig + clock = Clock + dns = Dns + ntp = Ntp + ssh_server = SshServer + logging = Logging + aaa = Aaa diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_vlan/__init__.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_vlan/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/parsers/openconfig/vyos/openconfig_vlan/vlan.py b/ntc_rosetta/parsers/openconfig/vyos/openconfig_vlan/vlan.py new file mode 100644 index 0000000..995f45a --- /dev/null +++ b/ntc_rosetta/parsers/openconfig/vyos/openconfig_vlan/vlan.py @@ -0,0 +1,70 @@ +from yangify.parser import ParserData, Parser + + +class SingleTaggedConfig(Parser): + class Yangify(ParserData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/single-tagged/config" + ) + + def vlan_id(self): + if isinstance(self.yy.key, str): + return int(self.yy.key) + return None + + +class DoubleTaggedConfig(Parser): + class Yangify(ParserData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/double-tagged/config" + ) + + def inner_vlan_id(self): + if isinstance(self.yy.key, tuple): + return int(self.yy.key[1]) + return None + + def outer_vlan_id(self): + if isinstance(self.yy.key, tuple): + return int(self.yy.key[0]) + return None + + +class SingleTagged(Parser): + class Yangify(ParserData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/single-tagged" + ) + + config = SingleTaggedConfig + + +class DoubleTagged(Parser): + class Yangify(ParserData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/double-tagged" + ) + + config = DoubleTaggedConfig + + +class Match(Parser): + class Yangify(ParserData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match" + ) + + single_tagged = SingleTagged + double_tagged = DoubleTagged + + +class Vlan(Parser): + class Yangify(ParserData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-vlan:vlan" + + match = Match diff --git a/ntc_rosetta/translators/__init__.py b/ntc_rosetta/translators/__init__.py index e69de29..f2a37fc 100644 --- a/ntc_rosetta/translators/__init__.py +++ b/ntc_rosetta/translators/__init__.py @@ -0,0 +1,5 @@ +from ntc_rosetta.translators.openconfig.ios import IOSTranslator +from ntc_rosetta.translators.openconfig.junos import JunosTranslator +from ntc_rosetta.translators.openconfig.vyos import VyOSTranslator + +__all__ = ("IOSTranslator", "JunosTranslator", "VyOSTranslator") diff --git a/ntc_rosetta/translators/ntc/vyos/__init__.py b/ntc_rosetta/translators/ntc/vyos/__init__.py new file mode 100644 index 0000000..b18b2f1 --- /dev/null +++ b/ntc_rosetta/translators/ntc/vyos/__init__.py @@ -0,0 +1,5 @@ +from yangify import translator + + +class VyOSTranslator(translator.RootTranslator): + pass diff --git a/ntc_rosetta/translators/openconfig/vyos/__init__.py b/ntc_rosetta/translators/openconfig/vyos/__init__.py new file mode 100644 index 0000000..a3c8214 --- /dev/null +++ b/ntc_rosetta/translators/openconfig/vyos/__init__.py @@ -0,0 +1,23 @@ +from ntc_rosetta.helpers.request_list import RequestList +from ntc_rosetta.translators.openconfig.vyos.openconfig_interfaces import interfaces +from ntc_rosetta.translators.openconfig.vyos.openconfig_network_instance.network_instances import ( + NetworkInstances, +) +from ntc_rosetta.translators.openconfig.vyos.openconfig_system.system import System + +from yangify import translator + + +class VyOSTranslator(translator.RootTranslator): + class Yangify(translator.TranslatorData): + def init(self) -> None: + self.root_result = RequestList() + self.result = self.root_result + + def post(self) -> None: + # self.root_result = self.root_result.to_json() + self.root_result = self.root_result.to_set() + + interfaces = interfaces.Interfaces + network_instances = NetworkInstances + system = System diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_if_ethernet/__init__.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_if_ethernet/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_if_ethernet/ethernet.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_if_ethernet/ethernet.py new file mode 100644 index 0000000..fbd0608 --- /dev/null +++ b/ntc_rosetta/translators/openconfig/vyos/openconfig_if_ethernet/ethernet.py @@ -0,0 +1,8 @@ +from yangify.translator import Translator, TranslatorData + + +class Ethernet(Translator): + class Yangify(TranslatorData): + path = ( + "openconfig-interfaces:interfaces/interface/openconfig-if-ethernet:ethernet" + ) diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_interfaces/__init__.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_interfaces/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_interfaces/interfaces.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_interfaces/interfaces.py new file mode 100644 index 0000000..5b5338d --- /dev/null +++ b/ntc_rosetta/translators/openconfig/vyos/openconfig_interfaces/interfaces.py @@ -0,0 +1,202 @@ +from typing import Optional +from ntc_rosetta.translators.openconfig.vyos.openconfig_if_ethernet import ethernet +from ntc_rosetta.translators.openconfig.vyos.openconfig_vlan import vlan +from yangify.translator import Translator, TranslatorData, unneeded + +TYPES = { + "eth": "ethernet", + "lo": "loopback", + "bond": "bonding", + "br": "bridge", + "macsec": "macsec", + "tunnel": "tunnel", +} + + +def get_if_type(name: str) -> str: + types = [v for k, v in TYPES.items() if name.startswith(k)] + if len(types) > 0: + return types[0] + else: + raise Exception(f"don't know the type for {name}") + + +class SubinterfaceConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/config" + + index = unneeded + + def description(self, value: Optional[str]) -> None: + if value: + self.yy.result.set(["description"], value, use_pre_path=True) + else: + self.yy.result.delete(["description"], "", use_pre_path=True) + + def enabled(self, value: Optional[bool]) -> None: + if value: + self.yy.result.delete(["disable"], "", use_pre_path=True) + else: + self.yy.result.set(["disable"], "", use_pre_path=True) + + +class Subinterface(Translator): + class Yangify(TranslatorData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface" + + def pre_process_list(self) -> None: + if self.to_remove and not self.replace: + for element in self.to_remove: + data = element.value + parent_key = self.keys[ + "/openconfig-interfaces:interfaces/interface" + ] + if_type = get_if_type(parent_key) + vlan_found = False + try: + vlan_id = str( + data["openconfig-vlan:vlan"]["match"]["single-tagged"][ + "config" + ]["vlan-id"] + ) + self.result.delete( + ["interfaces", if_type, parent_key, "vif"], vlan_id + ) + vlan_found = True + except KeyError: + pass + try: + inner_vlan_id = str( + data["openconfig-vlan:vlan"]["match"]["double-tagged"][ + "config" + ]["inner-vlan-id"] + ) + outer_vlan_id = str( + data["openconfig-vlan:vlan"]["match"]["double-tagged"][ + "config" + ]["outer-vlan-id"] + ) + self.result.delete( + [ + "interfaces", + if_type, + parent_key, + "vif-s", + outer_vlan_id, + "vif-c", + ], + inner_vlan_id, + ) + vlan_found = True + except KeyError: + pass + if not vlan_found: + raise Exception( + f"don't know the vlan tag(s) for subinterface {self.key}" + ) + # TODO: check if this is the last inner vlan for outer vlan and delete outer if true + + def pre_process(self) -> None: + data = self.candidate.goto(self.path).value + parent_key = self.keys["/openconfig-interfaces:interfaces/interface"] + if_type = get_if_type(parent_key) + self.result.pre_path = ["interfaces", if_type, parent_key] + vlan_found = False + try: + vlan_id = str( + data["openconfig-vlan:vlan"]["match"]["single-tagged"]["config"][ + "vlan-id" + ] + ) + self.result.pre_path.extend(["vif", vlan_id]) + vlan_found = True + except KeyError: + pass + try: + inner_vlan_id = str( + data["openconfig-vlan:vlan"]["match"]["double-tagged"]["config"][ + "inner-vlan-id" + ] + ) + outer_vlan_id = str( + data["openconfig-vlan:vlan"]["match"]["double-tagged"]["config"][ + "outer-vlan-id" + ] + ) + self.result.pre_path.extend( + ["vif-s", outer_vlan_id, "vif-c", inner_vlan_id] + ) + vlan_found = True + except KeyError: + pass + if not vlan_found: + raise Exception( + f"don't know the vlan tag(s) for subinterface {self.key}" + ) + + index = unneeded + config = SubinterfaceConfig + vlan = vlan.Vlan + + +class Subinterfaces(Translator): + class Yangify(TranslatorData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces" + + subinterface = Subinterface + + +class InterfaceConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-interfaces:interfaces/interface/config" + + name = unneeded + type = unneeded + + def description(self, value: Optional[str]) -> None: + if value: + self.yy.result.set(["description"], value, use_pre_path=True) + else: + self.yy.result.delete(["description"], "", use_pre_path=True) + + def enabled(self, value: Optional[bool]) -> None: + if value: + self.yy.result.delete(["disable"], "", use_pre_path=True) + else: + self.yy.result.set(["disable"], "", use_pre_path=True) + + def mtu(self, value: Optional[int]) -> None: + if value: + self.yy.result.set(["mtu"], str(value), use_pre_path=True) + else: + self.yy.result.delete(["mtu"], "", use_pre_path=True) + + +class Interface(Translator): + class Yangify(TranslatorData): + path = "/openconfig-interfaces:interfaces/interface" + + def pre_process_list(self) -> None: + if self.to_remove: + for element in self.to_remove: + if_type = get_if_type(element.value["name"]) + self.result.delete(["interfaces", if_type], element.value["name"]) + + def pre_process(self) -> None: + if_type = get_if_type(self.key) + if self.replace: + self.result.delete(["interfaces", if_type], self.key) + self.result.pre_path = ["interfaces", if_type, self.key] + + name = unneeded + + subinterfaces = Subinterfaces + config = InterfaceConfig + ethernet = ethernet.Ethernet + + +class Interfaces(Translator): + class Yangify(TranslatorData): + path = "/openconfig-interfaces:interfaces" + + interface = Interface diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_network_instance/__init__.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_network_instance/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_network_instance/network_instances.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_network_instance/network_instances.py new file mode 100644 index 0000000..fd94d8c --- /dev/null +++ b/ntc_rosetta/translators/openconfig/vyos/openconfig_network_instance/network_instances.py @@ -0,0 +1,41 @@ +from typing import Optional + +from yangify.translator import Translator, TranslatorData, unneeded + + +class NetworkInstanceConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-network-instance:network-instances/network-instance/config" + + name = unneeded + + def description(self, value: Optional[str]) -> None: + self.yy.result.set(["description"], value, use_pre_path=True) + + +class NetworkInstance(Translator): + class Yangify(TranslatorData): + path = "/openconfig-network-instance:network-instances/network-instance" + + def pre_process_list(self) -> None: + for element in self.to_remove: + self.result.delete(["vrf", "name"], element.value) + + def pre_process(self) -> None: + if self.key == "default": + return + if self.replace: + self.result.delete(["vrf", "name"], self.key) + self.result.set(["vrf", "name"], self.key) + self.result.pre_path = ["vrf", "name", self.key] + + config = NetworkInstanceConfig + vlans = unneeded + name = unneeded + + +class NetworkInstances(Translator): + class Yangify(TranslatorData): + path = "/openconfig-network-instance:network-instances" + + network_instance = NetworkInstance diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_system/__init__.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_system/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_system/system.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_system/system.py new file mode 100644 index 0000000..451f6a5 --- /dev/null +++ b/ntc_rosetta/translators/openconfig/vyos/openconfig_system/system.py @@ -0,0 +1,449 @@ +from typing import List + +from yangify.translator import Translator, TranslatorData, unneeded + + +class AaaRadiusConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers/server/radius/config" + + def secret_key(self, value: str) -> None: + self.yy.result.set(["key"], value, use_pre_path=True) + + def source_address(self, value: str) -> None: + self.yy.result.set(["system", "login", "radius", "source-address"], value) + + def auth_port(self, value: int) -> None: + self.yy.result.set(["port"], str(value), use_pre_path=True) + + +class AaaRadius(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers/server/radius" + + config = AaaRadiusConfig + + +class AaaServerGroupServersServer(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers/server" + + def pre_process_list(self) -> None: + if self.to_remove and not self.replace: + for element in self.to_remove: + self.result.delete( + ["system", "login", "radius", "server"], + element.value["address"], + ) + + def pre_process(self): + if self.replace: + self.result.delete(["system", "login", "radius", "server"], self.key) + self.result.pre_path = ["system", "login", "radius", "server", self.key] + + address = unneeded + radius = AaaRadius + + +class AaaServerGroupServers(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/server-groups/server-group/servers" + + server = AaaServerGroupServersServer + + +class AaaServerGroup(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/server-groups/server-group" + + servers = AaaServerGroupServers + name = unneeded + + +class AaaServerGroups(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/server-groups" + + server_group = AaaServerGroup + + +class AaaAuthenticationUserConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/authentication/users/user/config" + + username = unneeded + role = unneeded + + def password(self, value: str) -> None: + if value: + self.yy.result.set(["plaintext-password"], value, use_pre_path=True) + + def password_hashed(self, value: str) -> None: + if value: + self.yy.result.set(["encrypted-password"], value, use_pre_path=True) + + def ssh_key(self, value: str) -> None: + if value: + self.yy.result.set( + ["public-keys", self.yy.key, "key"], value, use_pre_path=True + ) + self.yy.result.set( + ["public-keys", self.yy.key, "type"], "ssh-rsa", use_pre_path=True + ) + + +class AaaAuthenticationUser(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/authentication/users/user" + + def pre_process_list(self) -> None: + if self.to_remove and not self.replace: + for element in self.to_remove: + self.result.delete( + ["system", "login", "user"], element.value["username"] + ) + + def pre_process(self) -> None: + if self.replace: + self.result.delete(["system", "login", "user"], self.key) + self.result.pre_path = [ + "system", + "login", + "user", + self.key, + "authentication", + ] + + username = unneeded + config = AaaAuthenticationUserConfig + + +class AaaAuthenticationUsers(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/authentication/users" + + user = AaaAuthenticationUser + + +class AaaAuthentication(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/authentication" + + users = AaaAuthenticationUsers + + +class AaaAuthorizationConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/authorization/config" + + authorization_method = unneeded + + +class AaaAuthorization(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa/authorization" + + config = AaaAuthorizationConfig + + +class Aaa(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/aaa" + + authentication = AaaAuthentication + authorization = AaaAuthorization + server_groups = AaaServerGroups + + +class ConsoleSelectorConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/logging/console/selectors/selector/config" + + facility = unneeded + severity = unneeded + + +class ConsoleSelector(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/logging/console/selectors/selector" + + def pre_process_list(self) -> None: + if self.to_remove and not self.replace: + for element in self.to_remove: + self.result.delete(["facility"], element["facility"]) + + _facility_val = None + _severity_val = None + + def facility(self, value: str) -> None: + if self._severity_val: + self.yy.result.set( + ["facility", value, "level"], self._severity_val, use_pre_path=True + ) + else: + self._facility_val = value + + def severity(self, value: str) -> None: + if self._facility_val: + self.yy.result.set( + ["facility", self._facility_val, "level"], value, use_pre_path=True + ) + else: + self._severity_val = value + + config = ConsoleSelectorConfig + + +class ConsoleSelectors(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/logging/console/selectors" + + # TODO: Can't be implemented, due to possible bug in Yangson, when using identityref as list key + # selector = ConsoleSelector + + +class Console(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/logging/console" + + def pre_process(self) -> None: + self.result.pre_path = ["system", "syslog", "console"] + + selectors = ConsoleSelectors + + +class Logging(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/logging" + + console = Console + # remote_servers = unneeded # RemoteServers + + +class SshServerConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/ssh-server/config" + + def enable(self, value: bool) -> None: + if value: + self.yy.result.set(["service", "ssh"], "") + + protocol_version = unneeded + timeout = unneeded + rate_limit = unneeded + session_limit = unneeded + + +class SshServer(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/ssh-server" + + config = SshServerConfig + + +class NtpServerConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/ntp/servers/server/config" + + address = unneeded + + def prefer(self, value: bool) -> None: + if value: + self.yy.result.set(["prefer"], "", use_pre_path=True) + + +class NtpServer(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/ntp/servers/server" + + def pre_process_list(self) -> None: + if self.to_remove and not self.replace: + for element in self.to_remove: + self.result.delete( + ["system", "ntp", "server"], element.value["address"] + ) + + def pre_process(self) -> None: + if self.replace: + self.result.delete(["system", "ntp", "server"], self.key) + + def address(self, value: str) -> None: + self.yy.result.set(["system", "ntp", "server"], value) + self.yy.result.pre_path = ["system", "ntp", "server", value] + + config = NtpServerConfig + + +class NtpServers(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/ntp/servers" + + server = NtpServer + + +class NtpConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/ntp/config" + + enabled = unneeded + + +class Ntp(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/ntp" + + config = NtpConfig + servers = NtpServers + + +class HostEntryConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns/host-entries/host-entry/config" + + hostname = unneeded + + def alias(self, value: List[str]) -> None: + # VyOS only supports one alias, so we return the first + self.yy.result.set(["alias"], value[0], use_pre_path=True) + + def ipv4_address(self, value: List[str]) -> None: + # VyOS only supports one address, so we return the first + self.yy.result.set(["inet"], value[0], use_pre_path=True) + + def ipv6_address(self, value: List[str]) -> None: + # VyOS only supports one address, so we return the first + self.yy.result.set(["inet"], value[0], use_pre_path=True) + + +class HostEntry(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns/host-entries/host-entry" + + def pre_process_list(self) -> None: + if self.to_remove and not self.replace: + for element in self.to_remove: + self.result.delete( + ["system", "static-host-mapping", "host-name"], + str(element.value["hostname"]), + ) + + def pre_process(self) -> None: + if self.replace: + self.result.delete( + ["system", "static-host-mapping", "host-name"], self.key + ) + + def hostname(self, value: str) -> None: + self.yy.result.pre_path = ["system", "static-host-mapping", "host-name", value] + + config = HostEntryConfig + + +class HostEntries(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns/host-entries" + + host_entry = HostEntry + + +class DnsServerConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns/servers/server/config" + + address = unneeded + port = unneeded + + +class DnsServer(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns/servers/server" + + def pre_process_list(self) -> None: + if self.to_remove and not self.replace: + for element in self.to_remove: + self.result.delete( + ["system", "name-server"], str(element.value["address"]) + ) + + def pre_process(self) -> None: + if self.replace: + self.result.delete(["system", "name-server"], self.key) + + def address(self, value: str) -> None: + return self.yy.result.set(["system", "name-server"], value) + + config = DnsServerConfig + + +class DnsServers(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns/servers" + + server = DnsServer + + +class DnsConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns/config" + + def pre_process(self) -> None: + if self.replace: + self.result.delete(["system", "domain-search"], "") + + def search(self, value: List[str]) -> None: + for domain in value: + self.yy.result.set(["system", "domain-search", "domain"], domain) + + +class Dns(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/dns" + + config = DnsConfig + servers = DnsServers + host_entries = HostEntries + + +class ClockConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/clock/config" + + def timezone_name(self, value: str) -> None: + self.yy.result.set(["system", "time-zone"], value) + + +class Clock(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/clock" + + config = ClockConfig + + +class SystemConfig(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system/config" + + def hostname(self, value: str) -> None: + self.yy.result.set(["system", "host-name"], value) + + def domain_name(self, value: str) -> None: + self.yy.result.set(["system", "domain-name"], value) + + def login_banner(self, value: str) -> None: + self.yy.result.set(["system", "login", "banner", "pre-login"], value) + + def motd_banner(self, value: str) -> None: + self.yy.result.set(["system", "login", "banner", "post-login"], value) + + +class System(Translator): + class Yangify(TranslatorData): + path = "/openconfig-system:system" + + config = SystemConfig + clock = Clock + dns = Dns + ntp = Ntp + ssh_server = SshServer + logging = Logging + aaa = Aaa diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_vlan/__init__.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_vlan/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ntc_rosetta/translators/openconfig/vyos/openconfig_vlan/vlan.py b/ntc_rosetta/translators/openconfig/vyos/openconfig_vlan/vlan.py new file mode 100644 index 0000000..d52131b --- /dev/null +++ b/ntc_rosetta/translators/openconfig/vyos/openconfig_vlan/vlan.py @@ -0,0 +1,60 @@ +from yangify.translator import Translator, TranslatorData, unneeded + + +class SingleTaggedConfig(Translator): + class Yangify(TranslatorData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/single-tagged/config" + ) + + vlan_id = unneeded + + +class SingleTagged(Translator): + class Yangify(TranslatorData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/single-tagged" + ) + + config = SingleTaggedConfig + + +class DoubleTaggedConfig(Translator): + class Yangify(TranslatorData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/double-tagged/config" + ) + + inner_vlan_id = unneeded + outer_vlan_id = unneeded + + +class DoubleTagged(Translator): + class Yangify(TranslatorData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match/double-tagged" + ) + + config = DoubleTaggedConfig + + +class Match(Translator): + class Yangify(TranslatorData): + path = ( + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/" + + "openconfig-vlan:vlan/match" + ) + + single_tagged = SingleTagged + double_tagged = DoubleTagged + + +class Vlan(Translator): + class Yangify(TranslatorData): + path = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-vlan:vlan" + + match = Match diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/data_candidate.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/data_candidate.json new file mode 100644 index 0000000..084b0f3 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/data_candidate.json @@ -0,0 +1,14 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1", + "description": "this is interface eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/data_running.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/data_running.json new file mode 100644 index 0000000..43ce37f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/data_running.json @@ -0,0 +1,13 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/res_merge b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/res_merge new file mode 100644 index 0000000..c0e7a06 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/res_merge @@ -0,0 +1 @@ +set interfaces ethernet eth1 description 'this is interface eth1' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/res_replace b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/res_replace new file mode 100644 index 0000000..d56c340 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/res_replace @@ -0,0 +1,2 @@ +delete interfaces ethernet 'eth1' +set interfaces ethernet eth1 description 'this is interface eth1' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/test_case.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_add/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/data_candidate.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/data_candidate.json new file mode 100644 index 0000000..43ce37f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/data_candidate.json @@ -0,0 +1,13 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/data_running.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/data_running.json new file mode 100644 index 0000000..084b0f3 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/data_running.json @@ -0,0 +1,14 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1", + "description": "this is interface eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/res_merge b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/res_merge new file mode 100644 index 0000000..32f2424 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/res_merge @@ -0,0 +1 @@ +delete interfaces ethernet eth1 description '' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/res_replace b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/res_replace new file mode 100644 index 0000000..27d95c1 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/res_replace @@ -0,0 +1 @@ +delete interfaces ethernet 'eth1' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/test_case.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/description_remove/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/data_candidate.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/data_candidate.json new file mode 100644 index 0000000..8249e3f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/data_candidate.json @@ -0,0 +1,14 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1", + "mtu": 9000 + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/data_running.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/data_running.json new file mode 100644 index 0000000..43ce37f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/data_running.json @@ -0,0 +1,13 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/res_merge b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/res_merge new file mode 100644 index 0000000..f816af7 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/res_merge @@ -0,0 +1 @@ +set interfaces ethernet eth1 mtu '9000' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/res_replace b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/res_replace new file mode 100644 index 0000000..615e71f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/res_replace @@ -0,0 +1,2 @@ +delete interfaces ethernet 'eth1' +set interfaces ethernet eth1 mtu '9000' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/test_case.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_add/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/data_candidate.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/data_candidate.json new file mode 100644 index 0000000..43ce37f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/data_candidate.json @@ -0,0 +1,13 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/data_running.json b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/data_running.json new file mode 100644 index 0000000..8249e3f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/data_running.json @@ -0,0 +1,14 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1", + "mtu": 9000 + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/res_merge b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/res_merge new file mode 100644 index 0000000..c0fd684 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/res_merge @@ -0,0 +1 @@ +delete interfaces ethernet eth1 mtu '' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/res_replace b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/res_replace new file mode 100644 index 0000000..7228074 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/res_replace @@ -0,0 +1 @@ +delete interfaces ethernet 'eth1' diff --git a/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/test_case.py b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/merge/vyos/mtu_remove/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/dev_conf b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/dev_conf new file mode 100644 index 0000000..4147320 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/dev_conf @@ -0,0 +1,39 @@ +interfaces { + ethernet eth0 { + description "this is interface eth0" + disable + } + ethernet eth1 { + vif 10 { + description "this is interface eth1.10" + } + vif 20 { + description "this is interface eth1.20" + } + } + ethernet eth2 { + vif-s 10 { + vif-c 20 { + description "this is interface eth2.10.20" + } + vif-c 30 { + description "this is interface eth2.10.30" + disable + } + } + vif-s 100 { + vif-c 200 { + description "this is interface eth2.100.200" + } + } + } + loopback lo { + } + bonding bond1 { + description "this is interface bond1" + mtu 9100 + } + bridge br1 { + description "this is interface br1" + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/result.json b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/result.json new file mode 100644 index 0000000..2291c51 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/result.json @@ -0,0 +1,106 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth0", + "config": { + "name": "eth0", + "type": "iana-if-type:ethernetCsmacd", + "description": "this is interface eth0", + "enabled": false + } + }, + { + "name": "eth1", + "config": { + "name": "eth1", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + }, + "subinterfaces": { + "subinterface": [ + { + "index": 10, + "config": { + "enabled": true, + "index": 10, + "description": "this is interface eth1.10" + } + }, + { + "index": 20, + "config": { + "index": 20, + "enabled": true, + "description": "this is interface eth1.20" + } + } + ] + } + }, + { + "name": "eth2", + "config": { + "name": "eth2", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + }, + "subinterfaces": { + "subinterface": [ + { + "index": 100020, + "config": { + "index": 100020, + "enabled": true, + "description": "this is interface eth2.10.20" + } + }, + { + "index": 100030, + "config": { + "index": 100030, + "description": "this is interface eth2.10.30", + "enabled": false + } + }, + { + "index": 1000200, + "config": { + "index": 1000200, + "enabled": true, + "description": "this is interface eth2.100.200" + } + } + ] + } + }, + { + "name": "lo", + "config": { + "name": "lo", + "type": "iana-if-type:softwareLoopback", + "enabled": true + } + }, + { + "name": "bond1", + "config": { + "name": "bond1", + "type": "iana-if-type:ieee8023adLag", + "description": "this is interface bond1", + "mtu": 9100, + "enabled": true + } + }, + { + "name": "br1", + "config": { + "name": "br1", + "type": "iana-if-type:bridge", + "description": "this is interface br1", + "enabled": true + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/test_case.py b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/test_case.py new file mode 100644 index 0000000..33cb979 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/parse/vyos/config/test_case.py @@ -0,0 +1,7 @@ +from tests.models.test_models import parse_path, parser + + +def test_parser() -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + parser(test_data.org, test_data.model, test_data.driver, test_data.path) diff --git a/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/__init__.py b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/data.json b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/data.json new file mode 100644 index 0000000..f20010c --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/data.json @@ -0,0 +1,58 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth0", + "config": { + "name": "eth0", + "type": "iana-if-type:ethernetCsmacd", + "description": "this is interface eth0", + "enabled": false + } + }, + { + "name": "eth1", + "config": { + "name": "eth1", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + } + }, + { + "name": "eth2", + "config": { + "name": "eth2", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + } + }, + { + "name": "lo", + "config": { + "name": "lo", + "type": "iana-if-type:softwareLoopback", + "enabled": true + } + }, + { + "name": "bond1", + "config": { + "name": "bond1", + "type": "iana-if-type:ieee8023adLag", + "description": "this is interface bond1", + "mtu": 9100, + "enabled": true + } + }, + { + "name": "br1", + "config": { + "name": "br1", + "type": "iana-if-type:bridge", + "description": "this is interface br1", + "enabled": true + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/res_merge b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/res_merge new file mode 100644 index 0000000..34c3125 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/res_merge @@ -0,0 +1,10 @@ +set interfaces ethernet eth0 description 'this is interface eth0' +set interfaces ethernet eth0 disable '' +delete interfaces ethernet eth1 disable '' +delete interfaces ethernet eth2 disable '' +delete interfaces loopback lo disable '' +set interfaces bonding bond1 mtu '9100' +set interfaces bonding bond1 description 'this is interface bond1' +delete interfaces bonding bond1 disable '' +set interfaces bridge br1 description 'this is interface br1' +delete interfaces bridge br1 disable '' diff --git a/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/res_replace b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/res_replace new file mode 100644 index 0000000..b4ad44a --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/res_replace @@ -0,0 +1,16 @@ +delete interfaces ethernet 'eth0' +set interfaces ethernet eth0 description 'this is interface eth0' +set interfaces ethernet eth0 disable '' +delete interfaces ethernet 'eth1' +delete interfaces ethernet eth1 disable '' +delete interfaces ethernet 'eth2' +delete interfaces ethernet eth2 disable '' +delete interfaces loopback 'lo' +delete interfaces loopback lo disable '' +delete interfaces bonding 'bond1' +set interfaces bonding bond1 mtu '9100' +set interfaces bonding bond1 description 'this is interface bond1' +delete interfaces bonding bond1 disable '' +delete interfaces bridge 'br1' +set interfaces bridge br1 description 'this is interface br1' +delete interfaces bridge br1 disable '' diff --git a/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/test_case.py b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/test_case.py new file mode 100644 index 0000000..331e9a8 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_interfaces/translate/vyos/test_case_1/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, translate + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_translate(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + translate(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/data_candidate.json new file mode 100644 index 0000000..74f3b3a --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/data_candidate.json @@ -0,0 +1,24 @@ +{ + "openconfig-system:system": { + "dns": { + "servers": { + "server": [ + { + "address": "8.8.8.8", + "config": { + "address": "8.8.8.8", + "port": 53 + } + }, + { + "address": "8.8.4.4", + "config": { + "address": "8.8.4.4", + "port": 53 + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/data_running.json new file mode 100644 index 0000000..fab71ea --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/data_running.json @@ -0,0 +1,17 @@ +{ + "openconfig-system:system": { + "dns": { + "servers": { + "server": [ + { + "address": "8.8.8.8", + "config": { + "address": "8.8.8.8", + "port": 53 + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/res_merge new file mode 100644 index 0000000..7301181 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/res_merge @@ -0,0 +1 @@ +set system name-server '8.8.4.4' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/res_replace new file mode 100644 index 0000000..5e8ef1b --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/res_replace @@ -0,0 +1,4 @@ +delete system name-server '8.8.8.8' +set system name-server '8.8.8.8' +delete system name-server '8.8.4.4' +set system name-server '8.8.4.4' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_dns_server/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/data_candidate.json new file mode 100644 index 0000000..a826dcf --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/data_candidate.json @@ -0,0 +1,26 @@ +{ + "openconfig-system:system": { + "ntp": { + "config": { + "enabled": true, + "enable-ntp-auth": false + }, + "servers": { + "server": [ + { + "address": "2610:20:6F96:96::6", + "config": { + "address": "2610:20:6F96:96::6" + } + }, + { + "address": "129.6.15.29", + "config": { + "address": "129.6.15.29" + } + } + ] + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/data_running.json new file mode 100644 index 0000000..f82e715 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/data_running.json @@ -0,0 +1,20 @@ +{ + "openconfig-system:system": { + "ntp": { + "config": { + "enabled": true, + "enable-ntp-auth": false + }, + "servers": { + "server": [ + { + "address": "2610:20:6F96:96::6", + "config": { + "address": "2610:20:6F96:96::6" + } + } + ] + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/res_merge new file mode 100644 index 0000000..7643f02 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/res_merge @@ -0,0 +1 @@ +set system ntp server '129.6.15.29' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/res_replace new file mode 100644 index 0000000..880ed07 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/res_replace @@ -0,0 +1,4 @@ +delete system ntp server '2610:20:6F96:96::6' +set system ntp server '2610:20:6F96:96::6' +delete system ntp server '129.6.15.29' +set system ntp server '129.6.15.29' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ntp_server/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/data_candidate.json new file mode 100644 index 0000000..f1d63c1 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/data_candidate.json @@ -0,0 +1,43 @@ +{ + "openconfig-system:system": { + "aaa": { + "server-groups": { + "server-group": [ + { + "name": "radius", + "config": { + "name": "radius", + "type": "openconfig-aaa:RADIUS" + }, + "servers": { + "server": [ + { + "address": "192.168.0.42", + "config": { + "address": "192.168.0.42" + }, + "radius": { + "config": { + "secret-key": "PLAINTEXTPASS" + } + } + }, + { + "address": "192.168.0.43", + "config": { + "address": "192.168.0.43" + }, + "radius": { + "config": { + "secret-key": "PLAINTEXTPASS" + } + } + } + ] + } + } + ] + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/data_running.json new file mode 100644 index 0000000..3bdcc53 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/data_running.json @@ -0,0 +1,32 @@ +{ + "openconfig-system:system": { + "aaa": { + "server-groups": { + "server-group": [ + { + "name": "radius", + "config": { + "name": "radius", + "type": "openconfig-aaa:RADIUS" + }, + "servers": { + "server": [ + { + "address": "192.168.0.42", + "config": { + "address": "192.168.0.42" + }, + "radius": { + "config": { + "secret-key": "PLAINTEXTPASS" + } + } + } + ] + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/res_merge new file mode 100644 index 0000000..733dbbf --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/res_merge @@ -0,0 +1 @@ +set system login radius server 192.168.0.43 key 'PLAINTEXTPASS' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/res_replace new file mode 100644 index 0000000..7753969 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/res_replace @@ -0,0 +1,4 @@ +delete system login radius server '192.168.0.42' +set system login radius server 192.168.0.42 key 'PLAINTEXTPASS' +delete system login radius server '192.168.0.43' +set system login radius server 192.168.0.43 key 'PLAINTEXTPASS' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_radius_server/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/data_candidate.json new file mode 100644 index 0000000..35e6e04 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/data_candidate.json @@ -0,0 +1,28 @@ +{ + "openconfig-system:system": { + "aaa": { + "authentication": { + "users": { + "user": [ + { + "username": "other", + "config": { + "username": "other", + "password-hashed": "$6$Ds.gV3Ce$V10YZ/FFypUTCcUtJ8C9WIgnD6wEwsXFivPH2RrVCBs/JzcS7WYgPL.EgVlsFwSVtK1F.HBENK2UbMMj8Dfc4/", + "role": "super-user" + } + }, + { + "username": "user", + "config": { + "username": "user", + "ssh-key": "ssh-rsa some-ssh-key user@example.com", + "role": "super-user" + } + } + ] + } + } + } + } + } diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/data_running.json new file mode 100644 index 0000000..5a578bf --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/data_running.json @@ -0,0 +1,20 @@ +{ + "openconfig-system:system": { + "aaa": { + "authentication": { + "users": { + "user": [ + { + "username": "user", + "config": { + "username": "user", + "ssh-key": "ssh-rsa some-ssh-key user@example.com", + "role": "super-user" + } + } + ] + } + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/res_merge new file mode 100644 index 0000000..2933a57 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/res_merge @@ -0,0 +1 @@ +set system login user other authentication encrypted-password '$6$Ds.gV3Ce$V10YZ/FFypUTCcUtJ8C9WIgnD6wEwsXFivPH2RrVCBs/JzcS7WYgPL.EgVlsFwSVtK1F.HBENK2UbMMj8Dfc4/' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/res_replace new file mode 100644 index 0000000..a79e803 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/res_replace @@ -0,0 +1,5 @@ +delete system login user 'other' +set system login user other authentication encrypted-password '$6$Ds.gV3Ce$V10YZ/FFypUTCcUtJ8C9WIgnD6wEwsXFivPH2RrVCBs/JzcS7WYgPL.EgVlsFwSVtK1F.HBENK2UbMMj8Dfc4/' +delete system login user 'user' +set system login user user authentication public-keys user key 'ssh-rsa some-ssh-key user@example.com' +set system login user user authentication public-keys user type 'ssh-rsa' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/add_ssh_user/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/data_candidate.json new file mode 100644 index 0000000..fab71ea --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/data_candidate.json @@ -0,0 +1,17 @@ +{ + "openconfig-system:system": { + "dns": { + "servers": { + "server": [ + { + "address": "8.8.8.8", + "config": { + "address": "8.8.8.8", + "port": 53 + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/data_running.json new file mode 100644 index 0000000..0230940 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/data_running.json @@ -0,0 +1,24 @@ +{ + "openconfig-system:system": { + "dns": { + "servers": { + "server": [ + { + "address": "8.8.8.8", + "config": { + "address": "8.8.8.8", + "port": 53 + } + }, + { + "address": "8.8.4.4", + "config": { + "address": "8.8.4.4", + "port": 53 + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/res_merge new file mode 100644 index 0000000..eac7865 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/res_merge @@ -0,0 +1 @@ +delete system name-server '8.8.4.4' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/res_replace new file mode 100644 index 0000000..be63835 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/res_replace @@ -0,0 +1,2 @@ +delete system name-server '8.8.8.8' +set system name-server '8.8.8.8' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_dns_server/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/data_candidate.json new file mode 100644 index 0000000..1537c93 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/data_candidate.json @@ -0,0 +1,21 @@ +{ + "openconfig-system:system": { + "ntp": { + "config": { + "enabled": true, + "enable-ntp-auth": false + }, + "servers": { + "server": [ + { + "address": "2610:20:6F96:96::6", + "config": { + "address": "2610:20:6F96:96::6" + } + } + ] + } + } + } +} + diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/data_running.json new file mode 100644 index 0000000..a826dcf --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/data_running.json @@ -0,0 +1,26 @@ +{ + "openconfig-system:system": { + "ntp": { + "config": { + "enabled": true, + "enable-ntp-auth": false + }, + "servers": { + "server": [ + { + "address": "2610:20:6F96:96::6", + "config": { + "address": "2610:20:6F96:96::6" + } + }, + { + "address": "129.6.15.29", + "config": { + "address": "129.6.15.29" + } + } + ] + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/res_merge new file mode 100644 index 0000000..1d732b3 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/res_merge @@ -0,0 +1 @@ +delete system ntp server '129.6.15.29' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/res_replace new file mode 100644 index 0000000..224cec3 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/res_replace @@ -0,0 +1,2 @@ +delete system ntp server '2610:20:6F96:96::6' +set system ntp server '2610:20:6F96:96::6' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ntp_server/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/data_candidate.json new file mode 100644 index 0000000..3bdcc53 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/data_candidate.json @@ -0,0 +1,32 @@ +{ + "openconfig-system:system": { + "aaa": { + "server-groups": { + "server-group": [ + { + "name": "radius", + "config": { + "name": "radius", + "type": "openconfig-aaa:RADIUS" + }, + "servers": { + "server": [ + { + "address": "192.168.0.42", + "config": { + "address": "192.168.0.42" + }, + "radius": { + "config": { + "secret-key": "PLAINTEXTPASS" + } + } + } + ] + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/data_running.json new file mode 100644 index 0000000..f1d63c1 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/data_running.json @@ -0,0 +1,43 @@ +{ + "openconfig-system:system": { + "aaa": { + "server-groups": { + "server-group": [ + { + "name": "radius", + "config": { + "name": "radius", + "type": "openconfig-aaa:RADIUS" + }, + "servers": { + "server": [ + { + "address": "192.168.0.42", + "config": { + "address": "192.168.0.42" + }, + "radius": { + "config": { + "secret-key": "PLAINTEXTPASS" + } + } + }, + { + "address": "192.168.0.43", + "config": { + "address": "192.168.0.43" + }, + "radius": { + "config": { + "secret-key": "PLAINTEXTPASS" + } + } + } + ] + } + } + ] + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/res_merge new file mode 100644 index 0000000..8448f71 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/res_merge @@ -0,0 +1 @@ +delete system login radius server '192.168.0.43' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/res_replace new file mode 100644 index 0000000..e747026 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/res_replace @@ -0,0 +1,2 @@ +delete system login radius server '192.168.0.42' +set system login radius server 192.168.0.42 key 'PLAINTEXTPASS' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_radius_server/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/__init__.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/data_candidate.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/data_candidate.json new file mode 100644 index 0000000..5a578bf --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/data_candidate.json @@ -0,0 +1,20 @@ +{ + "openconfig-system:system": { + "aaa": { + "authentication": { + "users": { + "user": [ + { + "username": "user", + "config": { + "username": "user", + "ssh-key": "ssh-rsa some-ssh-key user@example.com", + "role": "super-user" + } + } + ] + } + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/data_running.json b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/data_running.json new file mode 100644 index 0000000..4018e3f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/data_running.json @@ -0,0 +1,28 @@ +{ + "openconfig-system:system": { + "aaa": { + "authentication": { + "users": { + "user": [ + { + "username": "other", + "config": { + "username": "other", + "password-hashed": "$6$Ds.gV3Ce$V10YZ/FFypUTCcUtJ8C9WIgnD6wEwsXFivPH2RrVCBs/JzcS7WYgPL.EgVlsFwSVtK1F.HBENK2UbMMj8Dfc4/", + "role": "super-user" + } + }, + { + "username": "user", + "config": { + "username": "user", + "ssh-key": "ssh-rsa some-ssh-key user@example.com", + "role": "super-user" + } + } + ] + } + } + } + } +} diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/res_merge b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/res_merge new file mode 100644 index 0000000..c9055ae --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/res_merge @@ -0,0 +1 @@ +delete system login user 'other' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/res_replace b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/res_replace new file mode 100644 index 0000000..aa3bc6b --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/res_replace @@ -0,0 +1,3 @@ +delete system login user 'user' +set system login user user authentication public-keys user key 'ssh-rsa some-ssh-key user@example.com' +set system login user user authentication public-keys user type 'ssh-rsa' diff --git a/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/test_case.py b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/merge/vyos/remove_ssh_user/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_system/parse/vyos/__init__.py b/tests/models/openconfig/data/openconfig_system/parse/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/parse/vyos/config/__init__.py b/tests/models/openconfig/data/openconfig_system/parse/vyos/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/parse/vyos/config/dev_conf b/tests/models/openconfig/data/openconfig_system/parse/vyos/config/dev_conf new file mode 100644 index 0000000..9662955 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/parse/vyos/config/dev_conf @@ -0,0 +1,75 @@ +service { + ssh +} +system { + domain-name vyos.io + domain-search { + domain vyos.io + domain domain.com + ] + } + host-name vyos + login { + banner { + post-login "This is the post-login banner" + pre-login "This is the pre-login banner" + } + radius { + server 192.168.0.1 { + key "shared-key" + port 2012 + } + source-address 192.168.0.100 + } + user vyos { + authentication { + encrypted-password "$6$UfxCExXB$lyKzl4SD0TM2Ygu9bIfG.BTmwQ9S1fCahnAW8DJSizcuDuDnfL0XGMlxRtrtiIt0pxaoPaJCPpEI1MegscoZ3/" + plaintext-password "" + public-keys user1 { + key "AAAAB3NzaC1yc2EAAAADAQABAAABgQDPlV5uLCkrBdNNrPcoWh2RcQYuUMk8HaC4hw7SaF7h/34WBEFF4YL4C3tn5PAvVtYeBjELWxC/2Vb+OPAQQWtNH38vwjg2BBZOV8UtYrLZZIPuz1olzGNdhBCgwZbQgjNLxoOuhZLKR5TqKQ0uGdIIL57cWnVXuQrq7mHAvhqn4lwGiHY3VhJkdBupbSBQWMoGlDm/aQNfKlEVR/ArPZpd7Tyt8PqWcj4WtXHPO4QEqbCa1GxFn8NwMBiPYyeeX0WUMW3no/h43HsM9Lx2PI0dYFBYLHX1GhnIB2BINAMUWcPlM3r6SLFgR1+1NL6e/4V22fxt5uIHm/zcjCixwPYASgyzyG7YDSv891pwNCJXdti2mGekSaGarv0E9DxSyoHoiG//XP9CZfGVzqWlwcvo9/5TD0n632qjBeBSoQrH9YgKOwoiUgyDwUaLa8SxmHmfO+r5BJth6p+kyTOBOfBnSIWjpHk7Fkbl6pmAuVvzNQj6SHpcxdYdo56rjcuhEe0=" + type ssh-rsa + } + } + } + } + name-server 9.9.9.9 + name-server 9.9.9.11 + name-server 2620:fe::fe + name-server 2620:fe::11 + ntp { + server 0.pool.ntp.org { + prefer + } + server 1.pool.ntp.org { + } + server 2.pool.ntp.org { + } + } + static-host-mapping { + host-name domain-v6.com { + alias alias6-domain + inet 1234:ab:cd:ef::1 + } + host-name domain-v4.com { + alias alias4-domain + inet 1.2.3.4 + } + } + syslog { + console { + facility auth { + level alert + } + facility user { + level info + } + } + host syslog.org { + facility all { + level emerg + } + port 614 + } + } + time-zone Europe/Copenhagen +} diff --git a/tests/models/openconfig/data/openconfig_system/parse/vyos/config/result.json b/tests/models/openconfig/data/openconfig_system/parse/vyos/config/result.json new file mode 100644 index 0000000..195cd77 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/parse/vyos/config/result.json @@ -0,0 +1,225 @@ +{ + "openconfig-system:system": { + "config": { + "hostname": "vyos", + "domain-name": "vyos.io", + "login-banner": "This is the pre-login banner", + "motd-banner":"This is the post-login banner" + }, + "clock": { + "config": { + "timezone-name": "Europe/Copenhagen" + } + }, + "dns": { + "config": { + "search": [ + "vyos.io", + "domain.com" + ] + }, + "servers": { + "server": [ + { + "address": "9.9.9.9", + "config": { + "address": "9.9.9.9", + "port": 53 + } + }, + { + "address": "9.9.9.11", + "config": { + "address": "9.9.9.11", + "port": 53 + } + }, + { + "address": "2620:fe::fe", + "config": { + "address": "2620:fe::fe", + "port": 53 + } + }, + { + "address": "2620:fe::11", + "config": { + "address": "2620:fe::11", + "port": 53 + } + } + ] + }, + "host-entries": { + "host-entry": [ + { + "hostname": "domain-v6.com", + "config": { + "hostname": "domain-v6.com", + "alias": [ + "alias6-domain" + ], + "ipv6-address": [ + "1234:ab:cd:ef::1" + ] + } + }, + { + "hostname": "domain-v4.com", + "config": { + "hostname": "domain-v4.com", + "alias": [ + "alias4-domain" + ], + "ipv4-address": [ + "1.2.3.4" + ] + } + } + ] + } + }, + "ntp": { + "config": { + "enabled": true + }, + "servers": { + "server": [ + { + "address": "0.pool.ntp.org", + "config": { + "address": "0.pool.ntp.org", + "prefer": true + } + }, + { + "address": "1.pool.ntp.org", + "config": { + "address": "1.pool.ntp.org", + "prefer": false + } + }, + { + "address": "2.pool.ntp.org", + "config": { + "address": "2.pool.ntp.org", + "prefer": false + } + } + ] + } + }, + "ssh-server": { + "config": { + "enable": true + } + }, + "logging": { + "console": { + "selectors": { + "selector": [ + { + "facility": "openconfig-system:AUTH", + "severity": "ALERT", + "config": { + "facility": "openconfig-system:AUTH", + "severity": "ALERT" + } + }, + { + "facility": "openconfig-system:USER", + "severity": "INFORMATIONAL", + "config": { + "facility": "openconfig-system:USER", + "severity": "INFORMATIONAL" + } + } + ] + } + }, + "remote-servers": { + "remote-server": [ + { + "host": "syslog.org", + "config": { + "host": "syslog.org", + "remote-port": 614 + }, + "selectors": { + "selector": [ + { + "facility": "openconfig-system:ALL", + "severity": "EMERGENCY", + "config": { + "facility": "openconfig-system:ALL", + "severity": "EMERGENCY" + } + } + ] + } + } + ] + } + }, + "aaa": { + "authentication": { + "config": { + "authentication-method": [ + "openconfig-aaa:RADIUS_ALL", + "openconfig-aaa:LOCAL" + ] + }, + "users": { + "user": [ + { + "username": "vyos", + "config": { + "username": "vyos", + "password": "", + "password-hashed": "$6$UfxCExXB$lyKzl4SD0TM2Ygu9bIfG.BTmwQ9S1fCahnAW8DJSizcuDuDnfL0XGMlxRtrtiIt0pxaoPaJCPpEI1MegscoZ3/", + "ssh-key": "AAAAB3NzaC1yc2EAAAADAQABAAABgQDPlV5uLCkrBdNNrPcoWh2RcQYuUMk8HaC4hw7SaF7h/34WBEFF4YL4C3tn5PAvVtYeBjELWxC/2Vb+OPAQQWtNH38vwjg2BBZOV8UtYrLZZIPuz1olzGNdhBCgwZbQgjNLxoOuhZLKR5TqKQ0uGdIIL57cWnVXuQrq7mHAvhqn4lwGiHY3VhJkdBupbSBQWMoGlDm/aQNfKlEVR/ArPZpd7Tyt8PqWcj4WtXHPO4QEqbCa1GxFn8NwMBiPYyeeX0WUMW3no/h43HsM9Lx2PI0dYFBYLHX1GhnIB2BINAMUWcPlM3r6SLFgR1+1NL6e/4V22fxt5uIHm/zcjCixwPYASgyzyG7YDSv891pwNCJXdti2mGekSaGarv0E9DxSyoHoiG//XP9CZfGVzqWlwcvo9/5TD0n632qjBeBSoQrH9YgKOwoiUgyDwUaLa8SxmHmfO+r5BJth6p+kyTOBOfBnSIWjpHk7Fkbl6pmAuVvzNQj6SHpcxdYdo56rjcuhEe0=", + "role": "openconfig-aaa:SYSTEM_ROLE_ADMIN" + } + } + ] + } + }, + "authorization": { + "config": { + "authorization-method": [ + "openconfig-aaa:RADIUS_ALL", + "openconfig-aaa:LOCAL" + ] + } + }, + "server-groups": { + "server-group": [ + { + "name": "radius", + "config": { + "name": "radius", + "type": "openconfig-aaa:RADIUS" + }, + "servers": { + "server": [ + { + "address": "192.168.0.1", + "config": { + "address": "192.168.0.1" + }, + "radius": { + "config": { + "auth-port": 2012, + "secret-key": "shared-key", + "source-address": "192.168.0.100" + } + } + } + ] + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/parse/vyos/config/test_case.py b/tests/models/openconfig/data/openconfig_system/parse/vyos/config/test_case.py new file mode 100644 index 0000000..33cb979 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/parse/vyos/config/test_case.py @@ -0,0 +1,7 @@ +from tests.models.test_models import parse_path, parser + + +def test_parser() -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + parser(test_data.org, test_data.model, test_data.driver, test_data.path) diff --git a/tests/models/openconfig/data/openconfig_system/translate/vyos/__init__.py b/tests/models/openconfig/data/openconfig_system/translate/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/__init__.py b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/data.json b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/data.json new file mode 100644 index 0000000..b1f9417 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/data.json @@ -0,0 +1,225 @@ +{ + "openconfig-system:system": { + "config": { + "hostname": "vyos", + "domain-name": "vyos.io", + "login-banner": "This is the pre-login banner", + "motd-banner":"This is the post-login banner" + }, + "clock": { + "config": { + "timezone-name": "Europe/Copenhagen" + } + }, + "dns": { + "config": { + "search": [ + "vyos.io", + "domain.com" + ] + }, + "servers": { + "server": [ + { + "address": "9.9.9.9", + "config": { + "address": "9.9.9.9", + "port": 53 + } + }, + { + "address": "9.9.9.11", + "config": { + "address": "9.9.9.11", + "port": 53 + } + }, + { + "address": "2620:fe::fe", + "config": { + "address": "2620:fe::fe", + "port": 53 + } + }, + { + "address": "2620:fe::11", + "config": { + "address": "2620:fe::11", + "port": 53 + } + } + ] + }, + "host-entries": { + "host-entry": [ + { + "hostname": "domain-v6.com", + "config": { + "hostname": "domain-v6.com", + "alias": [ + "alias6-domain" + ], + "ipv6-address": [ + "1234:ab:cd:ef::1" + ] + } + }, + { + "hostname": "domain-v4.com", + "config": { + "hostname": "domain-v4.com", + "alias": [ + "alias4-domain" + ], + "ipv4-address": [ + "1.2.3.4" + ] + } + } + ] + } + }, + "ntp": { + "config": { + "enabled": true + }, + "servers": { + "server": [ + { + "address": "0.pool.ntp.org", + "config": { + "address": "0.pool.ntp.org", + "prefer": true + } + }, + { + "address": "1.pool.ntp.org", + "config": { + "address": "1.pool.ntp.org", + "prefer": false + } + }, + { + "address": "2.pool.ntp.org", + "config": { + "address": "2.pool.ntp.org", + "prefer": false + } + } + ] + } + }, + "ssh-server": { + "config": { + "enable": true + } + }, + "logging": { + "console": { + "selectors": { + "selector": [ + { + "facility": "AUTH", + "severity": "ALERT", + "config": { + "facility": "AUTH", + "severity": "ALERT" + } + }, + { + "facility": "USER", + "severity": "INFORMATIONAL", + "config": { + "facility": "USER", + "severity": "INFORMATIONAL" + } + } + ] + } + }, + "remote-servers": { + "remote-server": [ + { + "host": "syslog.org", + "config": { + "host": "syslog.org", + "remote-port": 614 + }, + "selectors": { + "selector": [ + { + "facility": "ALL", + "severity": "EMERGENCY", + "config": { + "facility": "ALL", + "severity": "EMERGENCY" + } + } + ] + } + } + ] + } + }, + "aaa": { + "authentication": { + "config": { + "authentication-method": [ + "openconfig-aaa:RADIUS_ALL", + "openconfig-aaa:LOCAL" + ] + }, + "users": { + "user": [ + { + "username": "vyos", + "config": { + "username": "vyos", + "password": "", + "password-hashed": "$6$UfxCExXB$lyKzl4SD0TM2Ygu9bIfG.BTmwQ9S1fCahnAW8DJSizcuDuDnfL0XGMlxRtrtiIt0pxaoPaJCPpEI1MegscoZ3/", + "ssh-key": "AAAAB3NzaC1yc2EAAAADAQABAAABgQDPlV5uLCkrBdNNrPcoWh2RcQYuUMk8HaC4hw7SaF7h/34WBEFF4YL4C3tn5PAvVtYeBjELWxC/2Vb+OPAQQWtNH38vwjg2BBZOV8UtYrLZZIPuz1olzGNdhBCgwZbQgjNLxoOuhZLKR5TqKQ0uGdIIL57cWnVXuQrq7mHAvhqn4lwGiHY3VhJkdBupbSBQWMoGlDm/aQNfKlEVR/ArPZpd7Tyt8PqWcj4WtXHPO4QEqbCa1GxFn8NwMBiPYyeeX0WUMW3no/h43HsM9Lx2PI0dYFBYLHX1GhnIB2BINAMUWcPlM3r6SLFgR1+1NL6e/4V22fxt5uIHm/zcjCixwPYASgyzyG7YDSv891pwNCJXdti2mGekSaGarv0E9DxSyoHoiG//XP9CZfGVzqWlwcvo9/5TD0n632qjBeBSoQrH9YgKOwoiUgyDwUaLa8SxmHmfO+r5BJth6p+kyTOBOfBnSIWjpHk7Fkbl6pmAuVvzNQj6SHpcxdYdo56rjcuhEe0=", + "role": "openconfig-aaa:SYSTEM_ROLE_ADMIN" + } + } + ] + } + }, + "authorization": { + "config": { + "authorization-method": [ + "openconfig-aaa:RADIUS_ALL", + "openconfig-aaa:LOCAL" + ] + } + }, + "server-groups": { + "server-group": [ + { + "name": "radius", + "config": { + "name": "radius", + "type": "openconfig-aaa:RADIUS" + }, + "servers": { + "server": [ + { + "address": "192.168.0.1", + "config": { + "address": "192.168.0.1" + }, + "radius": { + "config": { + "auth-port": 2012, + "secret-key": "shared-key", + "source-address": "192.168.0.100" + } + } + } + ] + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/res_merge b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/res_merge new file mode 100644 index 0000000..c3e8dd3 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/res_merge @@ -0,0 +1,26 @@ +set system host-name 'vyos' +set system domain-name 'vyos.io' +set system login banner pre-login 'This is the pre-login banner' +set system login banner post-login 'This is the post-login banner' +set system time-zone 'Europe/Copenhagen' +set system domain-search domain 'vyos.io' +set system domain-search domain 'domain.com' +set system name-server '9.9.9.9' +set system name-server '9.9.9.11' +set system name-server '2620:fe::fe' +set system name-server '2620:fe::11' +set system static-host-mapping host-name domain-v6.com alias 'alias6-domain' +set system static-host-mapping host-name domain-v6.com inet '1234:ab:cd:ef::1' +set system static-host-mapping host-name domain-v4.com alias 'alias4-domain' +set system static-host-mapping host-name domain-v4.com inet '1.2.3.4' +set system ntp server '0.pool.ntp.org' +set system ntp server 0.pool.ntp.org prefer '' +set system ntp server '1.pool.ntp.org' +set system ntp server '2.pool.ntp.org' +set service ssh '' +set system login user vyos authentication encrypted-password '$6$UfxCExXB$lyKzl4SD0TM2Ygu9bIfG.BTmwQ9S1fCahnAW8DJSizcuDuDnfL0XGMlxRtrtiIt0pxaoPaJCPpEI1MegscoZ3/' +set system login user vyos authentication public-keys vyos key 'AAAAB3NzaC1yc2EAAAADAQABAAABgQDPlV5uLCkrBdNNrPcoWh2RcQYuUMk8HaC4hw7SaF7h/34WBEFF4YL4C3tn5PAvVtYeBjELWxC/2Vb+OPAQQWtNH38vwjg2BBZOV8UtYrLZZIPuz1olzGNdhBCgwZbQgjNLxoOuhZLKR5TqKQ0uGdIIL57cWnVXuQrq7mHAvhqn4lwGiHY3VhJkdBupbSBQWMoGlDm/aQNfKlEVR/ArPZpd7Tyt8PqWcj4WtXHPO4QEqbCa1GxFn8NwMBiPYyeeX0WUMW3no/h43HsM9Lx2PI0dYFBYLHX1GhnIB2BINAMUWcPlM3r6SLFgR1+1NL6e/4V22fxt5uIHm/zcjCixwPYASgyzyG7YDSv891pwNCJXdti2mGekSaGarv0E9DxSyoHoiG//XP9CZfGVzqWlwcvo9/5TD0n632qjBeBSoQrH9YgKOwoiUgyDwUaLa8SxmHmfO+r5BJth6p+kyTOBOfBnSIWjpHk7Fkbl6pmAuVvzNQj6SHpcxdYdo56rjcuhEe0=' +set system login user vyos authentication public-keys vyos type 'ssh-rsa' +set system login radius server 192.168.0.1 port '2012' +set system login radius server 192.168.0.1 key 'shared-key' +set system login radius source-address '192.168.0.100' diff --git a/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/res_replace b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/res_replace new file mode 100644 index 0000000..2e97440 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/res_replace @@ -0,0 +1,38 @@ +set system host-name 'vyos' +set system domain-name 'vyos.io' +set system login banner pre-login 'This is the pre-login banner' +set system login banner post-login 'This is the post-login banner' +set system time-zone 'Europe/Copenhagen' +delete system domain-search '' +set system domain-search domain 'vyos.io' +set system domain-search domain 'domain.com' +delete system name-server '9.9.9.9' +set system name-server '9.9.9.9' +delete system name-server '9.9.9.11' +set system name-server '9.9.9.11' +delete system name-server '2620:fe::fe' +set system name-server '2620:fe::fe' +delete system name-server '2620:fe::11' +set system name-server '2620:fe::11' +delete system static-host-mapping host-name 'domain-v6.com' +set system static-host-mapping host-name domain-v6.com alias 'alias6-domain' +set system static-host-mapping host-name domain-v6.com inet '1234:ab:cd:ef::1' +delete system static-host-mapping host-name 'domain-v4.com' +set system static-host-mapping host-name domain-v4.com alias 'alias4-domain' +set system static-host-mapping host-name domain-v4.com inet '1.2.3.4' +delete system ntp server '0.pool.ntp.org' +set system ntp server '0.pool.ntp.org' +set system ntp server 0.pool.ntp.org prefer '' +delete system ntp server '1.pool.ntp.org' +set system ntp server '1.pool.ntp.org' +delete system ntp server '2.pool.ntp.org' +set system ntp server '2.pool.ntp.org' +set service ssh '' +delete system login user 'vyos' +set system login user vyos authentication encrypted-password '$6$UfxCExXB$lyKzl4SD0TM2Ygu9bIfG.BTmwQ9S1fCahnAW8DJSizcuDuDnfL0XGMlxRtrtiIt0pxaoPaJCPpEI1MegscoZ3/' +set system login user vyos authentication public-keys vyos key 'AAAAB3NzaC1yc2EAAAADAQABAAABgQDPlV5uLCkrBdNNrPcoWh2RcQYuUMk8HaC4hw7SaF7h/34WBEFF4YL4C3tn5PAvVtYeBjELWxC/2Vb+OPAQQWtNH38vwjg2BBZOV8UtYrLZZIPuz1olzGNdhBCgwZbQgjNLxoOuhZLKR5TqKQ0uGdIIL57cWnVXuQrq7mHAvhqn4lwGiHY3VhJkdBupbSBQWMoGlDm/aQNfKlEVR/ArPZpd7Tyt8PqWcj4WtXHPO4QEqbCa1GxFn8NwMBiPYyeeX0WUMW3no/h43HsM9Lx2PI0dYFBYLHX1GhnIB2BINAMUWcPlM3r6SLFgR1+1NL6e/4V22fxt5uIHm/zcjCixwPYASgyzyG7YDSv891pwNCJXdti2mGekSaGarv0E9DxSyoHoiG//XP9CZfGVzqWlwcvo9/5TD0n632qjBeBSoQrH9YgKOwoiUgyDwUaLa8SxmHmfO+r5BJth6p+kyTOBOfBnSIWjpHk7Fkbl6pmAuVvzNQj6SHpcxdYdo56rjcuhEe0=' +set system login user vyos authentication public-keys vyos type 'ssh-rsa' +delete system login radius server '192.168.0.1' +set system login radius server 192.168.0.1 port '2012' +set system login radius server 192.168.0.1 key 'shared-key' +set system login radius source-address '192.168.0.100' diff --git a/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/test_case.py b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/test_case.py new file mode 100644 index 0000000..331e9a8 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_system/translate/vyos/test_case_1/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, translate + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_translate(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + translate(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/__init__.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/__init__.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/data_candidate.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/data_candidate.json new file mode 100644 index 0000000..ef89053 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/data_candidate.json @@ -0,0 +1,50 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 1, + "config": { + "index": 1, + "description": "This is eth1.1" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 1 + } + } + } + } + }, + { + "index": 20001, + "config": { + "index": 20001, + "description": "This is eth1.2.1" + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 2, + "inner-vlan-id": 1 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/data_running.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/data_running.json new file mode 100644 index 0000000..43ce37f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/data_running.json @@ -0,0 +1,13 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/res_merge b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/res_merge new file mode 100644 index 0000000..8461c88 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/res_merge @@ -0,0 +1,2 @@ +set interfaces ethernet eth1 vif 1 description 'This is eth1.1' +set interfaces ethernet eth1 vif-s 2 vif-c 1 description 'This is eth1.2.1' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/res_replace b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/res_replace new file mode 100644 index 0000000..2571eda --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/res_replace @@ -0,0 +1,3 @@ +delete interfaces ethernet 'eth1' +set interfaces ethernet eth1 vif 1 description 'This is eth1.1' +set interfaces ethernet eth1 vif-s 2 vif-c 1 description 'This is eth1.2.1' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/test_case.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_add/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/__init__.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/data_candidate.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/data_candidate.json new file mode 100644 index 0000000..43ce37f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/data_candidate.json @@ -0,0 +1,13 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/data_running.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/data_running.json new file mode 100644 index 0000000..ef89053 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/data_running.json @@ -0,0 +1,50 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 1, + "config": { + "index": 1, + "description": "This is eth1.1" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 1 + } + } + } + } + }, + { + "index": 20001, + "config": { + "index": 20001, + "description": "This is eth1.2.1" + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 2, + "inner-vlan-id": 1 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/res_merge b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/res_merge new file mode 100644 index 0000000..42a19a6 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/res_merge @@ -0,0 +1,2 @@ +delete interfaces ethernet eth1 vif '1' +delete interfaces ethernet eth1 vif-s 2 vif-c '1' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/res_replace b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/res_replace new file mode 100644 index 0000000..27d95c1 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/res_replace @@ -0,0 +1 @@ +delete interfaces ethernet 'eth1' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/test_case.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_list_remove/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/__init__.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/data_candidate.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/data_candidate.json new file mode 100644 index 0000000..b48884f --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/data_candidate.json @@ -0,0 +1,65 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 1, + "config": { + "index": 1, + "description": "This is eth1.1" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 1 + } + } + } + } + }, + { + "index": 2, + "config": { + "index": 2, + "description": "This is eth1.2" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 2 + } + } + } + } + }, + { + "index": 3, + "config": { + "index": 3, + "description": "This is eth1.3" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 3 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/data_running.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/data_running.json new file mode 100644 index 0000000..907277b --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/data_running.json @@ -0,0 +1,49 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 1, + "config": { + "index": 1, + "description": "This is eth1.1" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 1 + } + } + } + } + }, + { + "index": 2, + "config": { + "index": 2, + "description": "This is eth1.2" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 2 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/res_merge b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/res_merge new file mode 100644 index 0000000..0c0d77c --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/res_merge @@ -0,0 +1 @@ +set interfaces ethernet eth1 vif 3 description 'This is eth1.3' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/res_replace b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/res_replace new file mode 100644 index 0000000..d9b20e3 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/res_replace @@ -0,0 +1,4 @@ +delete interfaces ethernet 'eth1' +set interfaces ethernet eth1 vif 1 description 'This is eth1.1' +set interfaces ethernet eth1 vif 2 description 'This is eth1.2' +set interfaces ethernet eth1 vif 3 description 'This is eth1.3' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/test_case.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_add/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/__init__.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/data_candidate.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/data_candidate.json new file mode 100644 index 0000000..5d83ee8 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/data_candidate.json @@ -0,0 +1,49 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 1, + "config": { + "index": 1, + "description": "This is a new description for eth1.1" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 1 + } + } + } + } + }, + { + "index": 2, + "config": { + "index": 2, + "description": "This is eth1.2" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 2 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/data_running.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/data_running.json new file mode 100644 index 0000000..907277b --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/data_running.json @@ -0,0 +1,49 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 1, + "config": { + "index": 1, + "description": "This is eth1.1" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 1 + } + } + } + } + }, + { + "index": 2, + "config": { + "index": 2, + "description": "This is eth1.2" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 2 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/res_merge b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/res_merge new file mode 100644 index 0000000..5cd266e --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/res_merge @@ -0,0 +1 @@ +set interfaces ethernet eth1 vif 1 description 'This is a new description for eth1.1' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/res_replace b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/res_replace new file mode 100644 index 0000000..c461cb0 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/res_replace @@ -0,0 +1,3 @@ +delete interfaces ethernet 'eth1' +set interfaces ethernet eth1 vif 1 description 'This is a new description for eth1.1' +set interfaces ethernet eth1 vif 2 description 'This is eth1.2' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/test_case.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_change/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/__init__.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/data_candidate.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/data_candidate.json new file mode 100644 index 0000000..91db0da --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/data_candidate.json @@ -0,0 +1,33 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 2, + "config": { + "index": 2, + "description": "This is eth1.2" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 2 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/data_running.json b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/data_running.json new file mode 100644 index 0000000..907277b --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/data_running.json @@ -0,0 +1,49 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth1", + "config": { + "type": "iana-if-type:ethernetCsmacd", + "name": "eth1" + }, + "subinterfaces": { + "subinterface": [ + { + "index": 1, + "config": { + "index": 1, + "description": "This is eth1.1" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 1 + } + } + } + } + }, + { + "index": 2, + "config": { + "index": 2, + "description": "This is eth1.2" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 2 + } + } + } + } + } + ] + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/res_merge b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/res_merge new file mode 100644 index 0000000..92bf66a --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/res_merge @@ -0,0 +1 @@ +delete interfaces ethernet eth1 vif '1' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/res_replace b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/res_replace new file mode 100644 index 0000000..0761dcb --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/res_replace @@ -0,0 +1,2 @@ +delete interfaces ethernet 'eth1' +set interfaces ethernet eth1 vif 2 description 'This is eth1.2' diff --git a/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/test_case.py b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/test_case.py new file mode 100644 index 0000000..e759188 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/merge/vyos/subinterfaces_member_remove/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, merge + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_merge(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + merge(test_data.org, test_data.driver, test_data.path, action) diff --git a/tests/models/openconfig/data/openconfig_vlan/parse/vyos/__init__.py b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/__init__.py b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/dev_conf b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/dev_conf new file mode 100644 index 0000000..6e8b572 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/dev_conf @@ -0,0 +1,48 @@ +interfaces { + ethernet eth0 { + description "this is interface eth0" + disable + } + ethernet eth1 { + vif 10 { + description "this is interface eth1.10" + } + vif 20 { + description "this is interface eth1.20" + } + } + ethernet eth2 { + vif-s 10 { + vif-c 20 { + description "this is interface eth2.10.20" + } + vif-c 30 { + description "this is interface eth2.10.30" + disable + } + } + vif-s 100 { + vif-c 200 { + description "this is interface eth2.100.200" + } + } + } + loopback lo { + } + bonding bond1 { + description "this is interface bond1" + mtu 9100 + } + bridge br1 { + description "this is interface br1" + } +} +vrf { + name vrf-1 { + table 100 + } + name vrf-2 { + description "this is vrf-2" + table 200 + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/result.json b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/result.json new file mode 100644 index 0000000..6c3fd4d --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/result.json @@ -0,0 +1,177 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth0", + "config": { + "name": "eth0", + "type": "iana-if-type:ethernetCsmacd", + "description": "this is interface eth0", + "enabled": false + } + }, + { + "name": "eth1", + "config": { + "name": "eth1", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + }, + "subinterfaces": { + "subinterface": [ + { + "index": 10, + "config": { + "enabled": true, + "index": 10, + "description": "this is interface eth1.10" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 10 + } + } + } + } + }, + { + "index": 20, + "config": { + "index": 20, + "enabled": true, + "description": "this is interface eth1.20" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 20 + } + } + } + } + } + ] + } + }, + { + "name": "eth2", + "config": { + "name": "eth2", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + }, + "subinterfaces": { + "subinterface": [ + { + "index": 100020, + "config": { + "index": 100020, + "enabled": true, + "description": "this is interface eth2.10.20" + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 10, + "inner-vlan-id": 20 + } + } + } + } + }, + { + "index": 100030, + "config": { + "index": 100030, + "description": "this is interface eth2.10.30", + "enabled": false + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 10, + "inner-vlan-id": 30 + } + } + } + } + }, + { + "index": 1000200, + "config": { + "index": 1000200, + "enabled": true, + "description": "this is interface eth2.100.200" + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 100, + "inner-vlan-id": 200 + } + } + } + } + } + ] + } + }, + { + "name": "lo", + "config": { + "name": "lo", + "type": "iana-if-type:softwareLoopback", + "enabled": true + } + }, + { + "name": "bond1", + "config": { + "name": "bond1", + "type": "iana-if-type:ieee8023adLag", + "description": "this is interface bond1", + "mtu": 9100, + "enabled": true + } + }, + { + "name": "br1", + "config": { + "name": "br1", + "type": "iana-if-type:bridge", + "description": "this is interface br1", + "enabled": true + } + } + ] + }, + "openconfig-network-instance:network-instances": { + "network-instance": [ + { + "name": "default", + "config": { + "name": "default" + } + }, + { + "name": "vrf-1", + "config": { + "name": "vrf-1" + } + }, + { + "name": "vrf-2", + "config": { + "name": "vrf-2", + "description": "this is vrf-2" + } + } + ] + } +} diff --git a/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/test_case.py b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/test_case.py new file mode 100644 index 0000000..33cb979 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/parse/vyos/config/test_case.py @@ -0,0 +1,7 @@ +from tests.models.test_models import parse_path, parser + + +def test_parser() -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + parser(test_data.org, test_data.model, test_data.driver, test_data.path) diff --git a/tests/models/openconfig/data/openconfig_vlan/translate/vyos/__init__.py b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/__init__.py b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/data.json b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/data.json new file mode 100644 index 0000000..fe1169d --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/data.json @@ -0,0 +1,150 @@ +{ + "openconfig-interfaces:interfaces": { + "interface": [ + { + "name": "eth0", + "config": { + "name": "eth0", + "type": "iana-if-type:ethernetCsmacd", + "description": "this is interface eth0", + "enabled": false + } + }, + { + "name": "eth1", + "config": { + "name": "eth1", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + }, + "subinterfaces": { + "subinterface": [ + { + "index": 10, + "config": { + "enabled": true, + "index": 10, + "description": "this is interface eth1.10" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 10 + } + } + } + } + }, + { + "index": 20, + "config": { + "index": 20, + "enabled": true, + "description": "this is interface eth1.20" + }, + "openconfig-vlan:vlan": { + "match": { + "single-tagged": { + "config": { + "vlan-id": 20 + } + } + } + } + } + ] + } + }, + { + "name": "eth2", + "config": { + "name": "eth2", + "type": "iana-if-type:ethernetCsmacd", + "enabled": true + }, + "subinterfaces": { + "subinterface": [ + { + "index": 100020, + "config": { + "index": 100020, + "enabled": true, + "description": "this is interface eth2.10.20" + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 10, + "inner-vlan-id": 20 + } + } + } + } + }, + { + "index": 100030, + "config": { + "index": 100030, + "description": "this is interface eth2.10.30", + "enabled": false + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 10, + "inner-vlan-id": 30 + } + } + } + } + }, + { + "index": 1000200, + "config": { + "index": 1000200, + "enabled": true, + "description": "this is interface eth2.100.200" + }, + "openconfig-vlan:vlan": { + "match": { + "double-tagged": { + "config": { + "outer-vlan-id": 100, + "inner-vlan-id": 200 + } + } + } + } + } + ] + } + } + ] + }, + "openconfig-network-instance:network-instances": { + "network-instance": [ + { + "name": "default", + "config": { + "name": "default" + } + }, + { + "name": "vrf-1", + "config": { + "name": "vrf-1" + } + }, + { + "name": "vrf-2", + "config": { + "name": "vrf-2", + "description": "this is vrf-2" + } + } + ] + } +} \ No newline at end of file diff --git a/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/res_merge b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/res_merge new file mode 100644 index 0000000..aa7e307 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/res_merge @@ -0,0 +1,17 @@ +set interfaces ethernet eth0 description 'this is interface eth0' +set interfaces ethernet eth0 disable '' +delete interfaces ethernet eth1 disable '' +set interfaces ethernet eth1 vif 10 description 'this is interface eth1.10' +delete interfaces ethernet eth1 vif 10 disable '' +set interfaces ethernet eth1 vif 20 description 'this is interface eth1.20' +delete interfaces ethernet eth1 vif 20 disable '' +delete interfaces ethernet eth2 disable '' +set interfaces ethernet eth2 vif-s 10 vif-c 20 description 'this is interface eth2.10.20' +delete interfaces ethernet eth2 vif-s 10 vif-c 20 disable '' +set interfaces ethernet eth2 vif-s 10 vif-c 30 description 'this is interface eth2.10.30' +set interfaces ethernet eth2 vif-s 10 vif-c 30 disable '' +set interfaces ethernet eth2 vif-s 100 vif-c 200 description 'this is interface eth2.100.200' +delete interfaces ethernet eth2 vif-s 100 vif-c 200 disable '' +set vrf name 'vrf-1' +set vrf name 'vrf-2' +set vrf name vrf-2 description 'this is vrf-2' diff --git a/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/res_replace b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/res_replace new file mode 100644 index 0000000..eb388b6 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/res_replace @@ -0,0 +1,22 @@ +delete interfaces ethernet 'eth0' +set interfaces ethernet eth0 description 'this is interface eth0' +set interfaces ethernet eth0 disable '' +delete interfaces ethernet 'eth1' +delete interfaces ethernet eth1 disable '' +set interfaces ethernet eth1 vif 10 description 'this is interface eth1.10' +delete interfaces ethernet eth1 vif 10 disable '' +set interfaces ethernet eth1 vif 20 description 'this is interface eth1.20' +delete interfaces ethernet eth1 vif 20 disable '' +delete interfaces ethernet 'eth2' +delete interfaces ethernet eth2 disable '' +set interfaces ethernet eth2 vif-s 10 vif-c 20 description 'this is interface eth2.10.20' +delete interfaces ethernet eth2 vif-s 10 vif-c 20 disable '' +set interfaces ethernet eth2 vif-s 10 vif-c 30 description 'this is interface eth2.10.30' +set interfaces ethernet eth2 vif-s 10 vif-c 30 disable '' +set interfaces ethernet eth2 vif-s 100 vif-c 200 description 'this is interface eth2.100.200' +delete interfaces ethernet eth2 vif-s 100 vif-c 200 disable '' +delete vrf name 'vrf-1' +set vrf name 'vrf-1' +delete vrf name 'vrf-2' +set vrf name 'vrf-2' +set vrf name vrf-2 description 'this is vrf-2' diff --git a/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/test_case.py b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/test_case.py new file mode 100644 index 0000000..331e9a8 --- /dev/null +++ b/tests/models/openconfig/data/openconfig_vlan/translate/vyos/test_case_1/test_case.py @@ -0,0 +1,10 @@ +from tests.models.test_models import parse_path, translate + +import pytest + + +@pytest.mark.parametrize("action", ["merge", "replace"]) # type: ignore +def test_translate(action: str) -> None: + """Run a merge test with the provided action.""" + test_data = parse_path(__file__) + translate(test_data.org, test_data.driver, test_data.path, action)