From 622225c79b71b3efd7c77c4dbb68d4334d0933d1 Mon Sep 17 00:00:00 2001 From: lou lecrivain Date: Tue, 17 Sep 2024 13:32:51 +0200 Subject: [PATCH 1/2] refactoring WIP draft ideas --- cosmo/graphqlclient.py | 3 +++ cosmo/serializer.py | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/cosmo/graphqlclient.py b/cosmo/graphqlclient.py index bdbaea1..73c7f4a 100644 --- a/cosmo/graphqlclient.py +++ b/cosmo/graphqlclient.py @@ -25,6 +25,9 @@ def query(self, query): return r.json() def get_data(self, device_config): + # TODO add typename everywhere so that the custom JSON parser + # can have JSONRPC2.0-style interface and no hazardous + # field-guessing for object types query_template = Template( """ { diff --git a/cosmo/serializer.py b/cosmo/serializer.py index 343b54d..05156bc 100644 --- a/cosmo/serializer.py +++ b/cosmo/serializer.py @@ -1,6 +1,7 @@ import ipaddress import re import json +import abc from collections import defaultdict from cosmo.logger import Logger @@ -653,6 +654,30 @@ def serialize(self): return device_stub +class SwitchElement(abc.ABC): + @abc.abstractmethod + def serialize(): + pass + +class SwitchElementCompound(SwitchElement): + # children is a list + def add(c: SwitchElement): + raise NotImplemented + + def remove(c: SwitchElement): + raise NotImplemented + + def getChildren(c: SwitchElement): + raise NotImplemented + + def serialize(): + raise NotImplemented + +class InterfaceSwitchElement(SwitchElement): + def serialize(): + raise NotImplemented + + class SwitchSerializer: def __init__(self, device): self.device = device From 65c2641338afbb50f5e2d727dcee089fba1159cd Mon Sep 17 00:00:00 2001 From: lou lecrivain Date: Tue, 17 Sep 2024 14:03:57 +0200 Subject: [PATCH 2/2] add typename for reliable object deserialization --- cosmo/graphqlclient.py | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/cosmo/graphqlclient.py b/cosmo/graphqlclient.py index 73c7f4a..ec11b1d 100644 --- a/cosmo/graphqlclient.py +++ b/cosmo/graphqlclient.py @@ -25,15 +25,13 @@ def query(self, query): return r.json() def get_data(self, device_config): - # TODO add typename everywhere so that the custom JSON parser - # can have JSONRPC2.0-style interface and no hazardous - # field-guessing for object types query_template = Template( """ { device_list( name: $device_array, ) { + __typename id name serial @@ -42,15 +40,19 @@ def get_data(self, device_config): slug } platform { + __typename manufacturer { + __typename slug } slug } primary_ip4 { + __typename address } interfaces { + __typename id name enabled @@ -60,40 +62,53 @@ def get_data(self, device_config): mac_address 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 } connected_endpoints { + __typename ... on InterfaceType { + __typename name device { + __typename primary_ip4 { + __typename address } interfaces { + __typename ip_addresses { + __typename address } } @@ -103,37 +118,47 @@ def get_data(self, device_config): custom_fields } staticroute_set { + __typename interface { + __typename name } vrf { + __typename name } prefix { + __typename prefix family { + __typename value } } next_hop { + __typename address } metric } } vrf_list { + __typename id name description rd export_targets { + __typename name } import_targets { + __typename name } } l2vpn_list { + __typename id name type @@ -146,18 +171,24 @@ def get_data(self, device_config): id } ... on InterfaceType { + __typename id device { + __typename name interfaces (type: "virtual") { + __typename ip_addresses { + __typename address } parent { + __typename name type } vrf { + __typename id } }