Skip to content

Commit

Permalink
add object-transformation of netbox data
Browse files Browse the repository at this point in the history
+ base visitor
  • Loading branch information
loulecrivain committed Feb 6, 2025
1 parent b602646 commit 4a168a2
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
13 changes: 13 additions & 0 deletions cosmo/clients/netbox_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,24 +251,30 @@ def _fetch_data(self, kwargs):
device_list(filters: {
name: { i_exact: $device },
}) {
__typename
id
name
serial
device_type {
__typename
slug
}
platform {
__typename
manufacturer {
__typename
slug
}
slug
}
primary_ip4 {
__typename
address
}
interfaces {
__typename
id
name
enabled
Expand All @@ -277,29 +283,36 @@ def _fetch_data(self, kwargs):
mtu
description
vrf {
__typename
id
}
lag {
__typename
id
}
ip_addresses {
__typename
address
}
untagged_vlan {
__typename
id
name
vid
}
tagged_vlans {
__typename
id
name
vid
}
tags {
__typename
name
slug
}
parent {
__typename
id
mtu
}
Expand Down
75 changes: 75 additions & 0 deletions cosmo/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import abc


class AbstractNetboxType(abc.ABC, dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__mappings = {}
for c in AbstractNetboxType.__subclasses__():
self.__mappings.update(c.register())
for k, v in self.items():
self[k] = self.convert(v)

def convert(self, item):
if isinstance(item, dict):
if "__typename" in item.keys():
c = self.__mappings[item["__typename"]]
return c({k: self.convert(v) for k,v in item.items()})
else:
return item
elif isinstance(item, list):
replacement = []
for i in item:
replacement.append(self.convert(i))
return replacement
else:
return item

@classmethod
def _getNetboxType(cls):
# classes should have the same name as the type name
# if not, you can override in parent class
return cls.__name__

@classmethod
def register(cls) -> dict:
return {cls._getNetboxType(): cls}

def __repr__(self):
return self._getNetboxType()


class DeviceType(AbstractNetboxType):
pass


class DeviceTypeType(AbstractNetboxType):
pass


class PlatformType(AbstractNetboxType):
pass


class ManufacturerType(AbstractNetboxType):
pass


class IPAddressType(AbstractNetboxType):
pass


class InterfaceType(AbstractNetboxType):
pass


class VRFType(AbstractNetboxType):
pass


class TagType(AbstractNetboxType):
pass


class VLANType(AbstractNetboxType):
pass
50 changes: 50 additions & 0 deletions cosmo/visitors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import abc
from copy import deepcopy
from functools import singledispatchmethod


class AbstractNoopNetboxTypesVisitor(abc.ABC):
def __init__(self, *args, **kwargs):
for c in AbstractNoopNetboxTypesVisitor.__subclasses__():
self.accept.register(
c,
lambda self, o: self._dictLikeTemplateMethod(o)
)

@singledispatchmethod
def accept(self, o):
raise NotImplementedError(f"unsupported type {o}")

@accept.register
def _(self, o: int):
return o

@accept.register
def _(self, o: None):
return o

@accept.register
def _(self, o: str):
return o

def _dictLikeTemplateMethod(self, o):
breakpoint()
o = deepcopy(o)
keys = list(o.keys())
for key in keys:
self._mutateDictKVTemplateMethod(o, key)
return o

def _mutateDictKVTemplateMethod(self, o, key):
o[key] = self.accept(o[key])

@accept.register
def _(self, o: dict) -> dict:
return self._dictLikeTemplateMethod(o)

@accept.register
def _(self, o: list) -> list:
o = deepcopy(o)
for i, v in enumerate(o):
o[i] = self.accept(v)
return o

0 comments on commit 4a168a2

Please sign in to comment.