Skip to content

Commit

Permalink
Merge pull request #13361 from LabNConsulting/chopps/munet-cfgopt-and…
Browse files Browse the repository at this point in the history
…-native

cfgopt in munet and native config support and example
  • Loading branch information
ton31337 authored Apr 24, 2023
2 parents 3eefea9 + a929d94 commit 766fcb6
Show file tree
Hide file tree
Showing 20 changed files with 215 additions and 36 deletions.
16 changes: 15 additions & 1 deletion tests/topotests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# pylint: disable=consider-using-f-string

import glob
import logging
import os
import re
import resource
Expand All @@ -16,7 +17,7 @@
import pytest
from lib.micronet_compat import ConfigOptionsProxy, Mininet
from lib.topogen import diagnose_env, get_topogen
from lib.topolog import logger
from lib.topolog import get_test_logdir, logger
from lib.topotest import json_cmp_result
from munet import cli
from munet.base import Commander, proc_error
Expand All @@ -25,6 +26,19 @@

from lib import topolog, topotest

try:
# Used by munet native tests
from munet.testing.fixtures import event_loop, unet # pylint: disable=all # noqa

@pytest.fixture(scope="module")
def rundir_module(pytestconfig):
d = os.path.join(pytestconfig.option.rundir, get_test_logdir())
logging.debug("rundir_module: test module rundir %s", d)
return d

except (AttributeError, ImportError):
pass


def pytest_addoption(parser):
"""
Expand Down
17 changes: 17 additions & 0 deletions tests/topotests/example_munet/munet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 1
topology:
ipv6-enable: true
networks-autonumber: true
networks:
- name: net1
- name: net2
nodes:
- name: r1
kind: frr
connections: ["net1"]
- name: r2
kind: frr
connections: ["net1", "net2"]
- name: r3
kind: frr
connections: ["net2"]
6 changes: 6 additions & 0 deletions tests/topotests/example_munet/r1/daemons
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
zebra=1
staticd=1
vtysh_enable=1
watchfrr_enable=1
zebra_options="-d -F traditional --log=file:/var/log/frr/zebra.log"
staticd_options="-d -F traditional --log=file:/var/log/frr/staticd.log"
7 changes: 7 additions & 0 deletions tests/topotests/example_munet/r1/frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
log file /var/log/frr/frr.log
service integrated-vtysh-config

interface eth0
ip address 10.0.1.1/24

ip route 10.0.0.0/8 blackhole
1 change: 1 addition & 0 deletions tests/topotests/example_munet/r1/vtysh.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
service integrated-vtysh-config
6 changes: 6 additions & 0 deletions tests/topotests/example_munet/r2/daemons
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
zebra=1
staticd=1
vtysh_enable=1
watchfrr_enable=1
zebra_options="-d -F traditional --log=file:/var/log/frr/zebra.log"
staticd_options="-d -F traditional --log=file:/var/log/frr/staticd.log"
10 changes: 10 additions & 0 deletions tests/topotests/example_munet/r2/frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
log file /var/log/frr/frr.log
service integrated-vtysh-config

interface eth0
ip address 10.0.1.2/24

interface eth1
ip address 10.0.2.2/24

ip route 10.0.0.0/8 blackhole
1 change: 1 addition & 0 deletions tests/topotests/example_munet/r2/vtysh.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
service integrated-vtysh-config
6 changes: 6 additions & 0 deletions tests/topotests/example_munet/r3/daemons
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
zebra=1
staticd=1
vtysh_enable=1
watchfrr_enable=1
zebra_options="-d -F traditional --log=file:/var/log/frr/zebra.log"
staticd_options="-d -F traditional --log=file:/var/log/frr/staticd.log"
7 changes: 7 additions & 0 deletions tests/topotests/example_munet/r3/frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
log file /var/log/frr/frr.log
service integrated-vtysh-config

interface eth0
ip address 10.0.2.3/24

ip route 10.0.0.0/8 blackhole
1 change: 1 addition & 0 deletions tests/topotests/example_munet/r3/vtysh.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
service integrated-vtysh-config
10 changes: 10 additions & 0 deletions tests/topotests/example_munet/test_munet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- coding: utf-8 eval: (blacken-mode 1) -*-
# SPDX-License-Identifier: GPL-2.0-or-later
#
# April 23 2023, Christian Hopps <chopps@labn.net>
#
# Copyright (c) 2023, LabN Consulting, L.L.C.
#
async def test_native_test(unet):
o = unet.hosts["r1"].cmd_nostatus("ip addr")
print(o)
30 changes: 30 additions & 0 deletions tests/topotests/kinds.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: 1
kinds:
- name: frr
cmd: |
chown frr:frr -R /var/run/frr
chown frr:frr -R /var/log/frr
/usr/lib/frr/frrinit.sh start
tail -F /var/log/frr/frr.log
cleanup-cmd: |
/usr/lib/frr/frrinit.sh stop
volumes:
- "./%NAME%:/etc/frr"
- "%RUNDIR%/var.log.frr:/var/log/frr"
- "%RUNDIR%/var.run.frr:/var/run/frr"
cap-add:
- SYS_ADMIN
- AUDIT_WRITE
merge: ["volumes"]
cli:
commands:
- name: ""
exec: "vtysh -c '{}'"
format: "[ROUTER ...] COMMAND"
help: "execute vtysh COMMAND on the router[s]"
kinds: ["frr"]
- name: "vtysh"
exec: "/usr/bin/vtysh"
format: "vtysh ROUTER [ROUTER ...]"
new-window: true
kinds: ["frr"]
3 changes: 0 additions & 3 deletions tests/topotests/lib/micronet_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ class Node(LinuxNamespace):
"""Node (mininet compat)."""

def __init__(self, name, rundir=None, **kwargs):

nkwargs = {}

if "unet" in kwargs:
Expand Down Expand Up @@ -177,8 +176,6 @@ def __init__(self, rundir=None, pytestconfig=None):
self.host_params = {}
self.prefix_len = 8

self.cfgopt = ConfigOptionsProxy(pytestconfig)

# SNMPd used to require this, which was set int he mininet shell
# that all commands executed from. This is goofy default so let's not
# do it if we don't have to. The snmpd.conf files have been updated
Expand Down
13 changes: 12 additions & 1 deletion tests/topotests/munet/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from pathlib import Path
from typing import Union

from . import config as munet_config
from . import linux


Expand Down Expand Up @@ -2493,7 +2494,15 @@ async def _async_delete(self):
class BaseMunet(LinuxNamespace):
"""Munet."""

def __init__(self, name="munet", isolated=True, pid=True, rundir=None, **kwargs):
def __init__(
self,
name="munet",
isolated=True,
pid=True,
rundir=None,
pytestconfig=None,
**kwargs,
):
"""Create a Munet."""
# logging.warning("BaseMunet: %s", name)

Expand Down Expand Up @@ -2562,6 +2571,8 @@ def __init__(self, name="munet", isolated=True, pid=True, rundir=None, **kwargs)

roothost = self.rootcmd

self.cfgopt = munet_config.ConfigOptionsProxy(pytestconfig)

super().__init__(
name, mount=True, net=isolated, uts=isolated, pid=pid, unet=None, **kwargs
)
Expand Down
10 changes: 10 additions & 0 deletions tests/topotests/munet/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,18 @@
class PytestConfig:
"""Pytest config duck-type-compatible object using argprase args."""

class Namespace:
"""A namespace defined by a dictionary of values."""

def __init__(self, args):
self.args = args

def __getattr__(self, attr):
return self.args[attr] if attr in self.args else None

def __init__(self, args):
self.args = vars(args)
self.option = PytestConfig.Namespace(self.args)

def getoption(self, name, default=None, skip=False):
assert not skip
Expand Down
54 changes: 54 additions & 0 deletions tests/topotests/munet/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,57 @@ def merge_kind_config(kconf, config):
if k not in new:
new[k] = config[k]
return new


def cli_opt_list(option_list):
if not option_list:
return []
if isinstance(option_list, str):
return [x for x in option_list.split(",") if x]
return [x for x in option_list if x]


def name_in_cli_opt_str(name, option_list):
ol = cli_opt_list(option_list)
return name in ol or "all" in ol


class ConfigOptionsProxy:
"""Proxy options object to fill in for any missing pytest config."""

class DefNoneObject:
"""An object that returns None for any attribute access."""

def __getattr__(self, attr):
return None

def __init__(self, pytestconfig=None):
if isinstance(pytestconfig, ConfigOptionsProxy):
self.config = pytestconfig.config
self.option = self.config.option
else:
self.config = pytestconfig
if self.config:
self.option = self.config.option
else:
self.option = ConfigOptionsProxy.DefNoneObject()

def getoption(self, opt, defval=None):
if not self.config:
return defval

try:
return self.config.getoption(opt, default=defval)
except ValueError:
return defval

def get_option(self, opt, defval=None):
return self.getoption(opt, defval)

def get_option_list(self, opt):
value = self.get_option(opt, "")
return cli_opt_list(value)

def name_in_option_list(self, name, opt):
optlist = self.get_option_list(opt)
return "all" in optlist or name in optlist
Loading

0 comments on commit 766fcb6

Please sign in to comment.