Skip to content

Commit

Permalink
Make read_polldevs return default values from pollfile
Browse files Browse the repository at this point in the history
  • Loading branch information
johannaengland committed Aug 8, 2024
1 parent e73a755 commit c7b7cb1
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 20 deletions.
6 changes: 3 additions & 3 deletions src/zino/config/polldevs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from zino.config.models import PollDevice


def read_polldevs(filename: str) -> dict[str, PollDevice]:
def read_polldevs(filename: str) -> Tuple[dict[str, PollDevice], dict[str, str]]:
"""
Reads and parses the legacy `polldevs.cf` format, returning a dictionary of device names and the associated
PollDevice object.
PollDevice object and a dictionary of default settings
This parser is slightly more lax than the original Tcl-based parser, in that it allows multiple empty lines or
multiple spaces in value assignments.
Expand Down Expand Up @@ -41,7 +41,7 @@ def read_polldevs(filename: str) -> dict[str, PollDevice]:
error.filename = filename
raise

return devices
return devices, defaults


def _read_conf_sections(filehandle: TextIO) -> Iterator[Tuple[int, dict]]:
Expand Down
4 changes: 2 additions & 2 deletions src/zino/getuptime.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def main():


async def run(args: argparse.Namespace):
devices = read_polldevs(config.polling.file)
devices, _ = read_polldevs(config.polling.file)
device = devices[args.router]

snmp = SNMP(device)
Expand All @@ -29,7 +29,7 @@ async def run(args: argparse.Namespace):


def parse_args():
devices = read_polldevs(config.polling.file)
devices, _ = read_polldevs(config.polling.file)
parser = argparse.ArgumentParser(description="Fetch sysUptime from a device in the pollfile")
parser.add_argument("router", type=str, help="Zino router name", choices=devices.keys())
return parser.parse_args()
Expand Down
10 changes: 5 additions & 5 deletions src/zino/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ def get_scheduler() -> AsyncIOScheduler:


@log_time_spent()
def load_polldevs(polldevs_conf: str) -> Tuple[Set, Set, Set]:
def load_polldevs(polldevs_conf: str) -> Tuple[Set, Set, Set, dict[str, str]]:
"""Loads pollfile into process state.
:returns: A tuple of (new_devices, deleted_devices, changed_devices)
"""
try:
devices = read_polldevs(polldevs_conf)
devices, defaults = read_polldevs(polldevs_conf)
except InvalidConfiguration as error:
_log.error(error)
return set(), set(), set()
return set(), set(), set(), dict()

new_devices = set(devices) - set(state.polldevs)
deleted_devices = set(state.polldevs) - set(devices)
Expand All @@ -68,7 +68,7 @@ def load_polldevs(polldevs_conf: str) -> Tuple[Set, Set, Set]:
for device in deleted_devices:
del state.polldevs[device]

return new_devices, deleted_devices, changed_devices
return new_devices, deleted_devices, changed_devices, defaults


def init_state_for_devices(devices: Sequence[PollDevice]):
Expand All @@ -79,7 +79,7 @@ def init_state_for_devices(devices: Sequence[PollDevice]):


async def load_and_schedule_polldevs(polldevs_conf: str):
new_devices, deleted_devices, changed_devices = load_polldevs(polldevs_conf)
new_devices, deleted_devices, changed_devices, defaults = load_polldevs(polldevs_conf)
deschedule_devices(deleted_devices | changed_devices)
schedule_devices(new_devices | changed_devices)

Expand Down
15 changes: 11 additions & 4 deletions tests/config/polldevs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,21 @@

class TestReadPolldevs:
def test_should_generate_two_polldevices_from_test_config(self, polldevs_conf):
result = read_polldevs(polldevs_conf)
result, _ = read_polldevs(polldevs_conf)
assert len(result) == 2
assert all(isinstance(device, PollDevice) for device in result.values())

def test_should_return_default_values_from_test_config(self, polldevs_conf):
_, defaults = read_polldevs(polldevs_conf)
assert "community" in defaults
assert defaults["community"] == "foobar"
assert "domain" in defaults
assert defaults["domain"] == "uninett.no"

def test_should_use_default_values_in_polldevices_generated_from_test_config(self, polldevs_conf):
result = read_polldevs(polldevs_conf).values()
assert all(device.community == "foobar" for device in result)
assert all(device.domain == "uninett.no" for device in result)
result, _ = read_polldevs(polldevs_conf)
assert all(device.community == "foobar" for device in result.values())
assert all(device.domain == "uninett.no" for device in result.values())


class TestReadInvalidPolldevs:
Expand Down
43 changes: 37 additions & 6 deletions tests/scheduler_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,31 @@ class TestLoadPolldevs:
@patch("zino.state.polldevs", dict())
@patch("zino.state.state", ZinoState())
def test_should_return_all_new_devices_on_first_run(self, polldevs_conf):
new_devices, deleted_devices, changed_devices = scheduler.load_polldevs(polldevs_conf)
new_devices, deleted_devices, changed_devices, _ = scheduler.load_polldevs(polldevs_conf)
assert len(new_devices) > 0
assert not deleted_devices
assert not changed_devices

@patch("zino.state.polldevs", dict())
@patch("zino.state.state", ZinoState())
def test_should_return_defaults_on_first_run(self, polldevs_conf):
_, _, _, defaults = scheduler.load_polldevs(polldevs_conf)
assert len(defaults) > 0
assert "interval" in defaults

@patch("zino.state.polldevs", dict())
@patch("zino.state.state", ZinoState())
def test_should_return_deleted_devices_on_second_run(self, polldevs_conf, polldevs_conf_with_single_router):
scheduler.load_polldevs(polldevs_conf)
new_devices, deleted_devices, changed_devices = scheduler.load_polldevs(polldevs_conf_with_single_router)
new_devices, deleted_devices, changed_devices, _ = scheduler.load_polldevs(polldevs_conf_with_single_router)
assert not new_devices
assert len(deleted_devices) > 0
assert not changed_devices

@patch("zino.state.polldevs", dict())
@patch("zino.state.state", ZinoState())
def test_should_return_no_new_or_deleted_devices_on_invalid_configuration(self, invalid_polldevs_conf):
new_devices, deleted_devices, changed_devices = scheduler.load_polldevs(invalid_polldevs_conf)
new_devices, deleted_devices, changed_devices, _ = scheduler.load_polldevs(invalid_polldevs_conf)
assert not new_devices
assert not deleted_devices
assert not changed_devices
Expand All @@ -41,6 +48,30 @@ def test_should_log_error_on_invalid_configuration(self, caplog, invalid_polldev
scheduler.load_polldevs(invalid_polldevs_conf)
assert "'lalala' is not a valid configuration line" in caplog.text

@patch("zino.state.polldevs", dict())
@patch("zino.state.state", ZinoState())
def test_should_return_changed_defaults(self, polldevs_conf, tmp_path):
polldevs_with_changed_defaults = tmp_path.joinpath("changed-defaults-polldevs.cf")
with open(polldevs_with_changed_defaults, "w") as conf:
conf.write(
"""# polldevs test config
default interval: 10
default community: barfoo
default domain: uninett.no
default statistics: yes
default hcounters: yes
name: example-gw
address: 10.0.42.1
name: example-gw2
address: 10.0.43.1""" # Lack of a new-line here is intentional to test the parser
)

_, _, _, defaults = scheduler.load_polldevs(polldevs_conf)
_, _, _, changed_defaults = scheduler.load_polldevs(polldevs_with_changed_defaults)
assert defaults != changed_defaults

@patch("zino.state.polldevs", dict())
@patch("zino.state.state", ZinoState())
def test_should_return_changed_devices_on_changed_defaults(self, polldevs_conf, tmp_path):
Expand All @@ -62,7 +93,7 @@ def test_should_return_changed_devices_on_changed_defaults(self, polldevs_conf,
)

scheduler.load_polldevs(polldevs_conf)
new_devices, deleted_devices, changed_devices = scheduler.load_polldevs(polldevs_with_changed_defaults)
new_devices, deleted_devices, changed_devices, _ = scheduler.load_polldevs(polldevs_with_changed_defaults)
assert not new_devices
assert not deleted_devices
assert changed_devices
Expand All @@ -89,7 +120,7 @@ def test_should_return_changed_devices_on_changed_interval(self, polldevs_conf,
)

scheduler.load_polldevs(polldevs_conf)
new_devices, deleted_devices, changed_devices = scheduler.load_polldevs(polldevs_with_changed_defaults)
new_devices, deleted_devices, changed_devices, _ = scheduler.load_polldevs(polldevs_with_changed_defaults)
assert not new_devices
assert not deleted_devices
assert changed_devices
Expand All @@ -99,7 +130,7 @@ class TestScheduleNewDevices:
@patch("zino.state.polldevs", dict())
@patch("zino.state.state", ZinoState())
def test_should_schedule_jobs_for_new_devices(self, polldevs_conf, mocked_scheduler):
new_devices, _, _ = scheduler.load_polldevs(polldevs_conf)
new_devices, _, _, _ = scheduler.load_polldevs(polldevs_conf)
assert len(new_devices) > 0

scheduler.schedule_devices(new_devices)
Expand Down

0 comments on commit c7b7cb1

Please sign in to comment.