annet 2.5.4__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of annet might be problematic. Click here for more details.
- annet/adapters/file/provider.py +49 -26
- annet/adapters/netbox/common/manufacturer.py +3 -21
- annet/adapters/netbox/common/models.py +4 -3
- annet/adapters/netbox/v24/models.py +4 -3
- annet/annet.py +8 -1
- annet/annlib/netdev/devdb/data/devdb.json +1 -0
- annet/annlib/netdev/views/hardware.py +15 -67
- annet/annlib/patching.py +7 -5
- annet/annlib/rbparser/acl.py +3 -2
- annet/annlib/rbparser/ordering.py +3 -2
- annet/annlib/rbparser/platform.py +4 -0
- annet/annlib/rulebook/common.py +1 -1
- annet/api/__init__.py +2 -1
- annet/generators/__init__.py +1 -1
- annet/hardware.py +8 -12
- annet/parallel.py +28 -9
- annet/rulebook/__init__.py +2 -1
- annet/rulebook/deploying.py +3 -2
- annet/rulebook/patching.py +2 -2
- annet/rulebook/texts/arista.rul +25 -3
- annet/rulebook/texts/iosxr.deploy +27 -0
- annet/rulebook/texts/iosxr.order +85 -0
- annet/rulebook/texts/iosxr.rul +110 -0
- annet/tabparser.py +1 -1
- annet/vendors/__init__.py +33 -0
- annet/vendors/base.py +25 -0
- annet/vendors/registry.py +84 -0
- {annet-2.5.4.dist-info → annet-3.0.0.dist-info}/METADATA +1 -1
- {annet-2.5.4.dist-info → annet-3.0.0.dist-info}/RECORD +37 -30
- annet_generators/example/__init__.py +6 -1
- annet_generators/example/hostname.py +113 -0
- annet_generators/rpl_example/generator.py +3 -0
- {annet-2.5.4.dist-info → annet-3.0.0.dist-info}/WHEEL +0 -0
- {annet-2.5.4.dist-info → annet-3.0.0.dist-info}/entry_points.txt +0 -0
- {annet-2.5.4.dist-info → annet-3.0.0.dist-info}/licenses/AUTHORS +0 -0
- {annet-2.5.4.dist-info → annet-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {annet-2.5.4.dist-info → annet-3.0.0.dist-info}/top_level.txt +0 -0
annet/rulebook/deploying.py
CHANGED
|
@@ -2,8 +2,9 @@ import functools
|
|
|
2
2
|
from collections import OrderedDict as odict
|
|
3
3
|
from collections import namedtuple
|
|
4
4
|
|
|
5
|
-
from annet.annlib.rbparser import
|
|
5
|
+
from annet.annlib.rbparser import syntax
|
|
6
6
|
from annet.annlib.rbparser.deploying import compile_messages
|
|
7
|
+
from annet.vendors import registry_connector
|
|
7
8
|
from valkit.common import valid_bool, valid_number, valid_string_list
|
|
8
9
|
from valkit.python import valid_object_path
|
|
9
10
|
|
|
@@ -38,7 +39,7 @@ def compile_deploying_text(text, vendor):
|
|
|
38
39
|
"default": [],
|
|
39
40
|
}
|
|
40
41
|
}),
|
|
41
|
-
reverse_prefix=
|
|
42
|
+
reverse_prefix=registry_connector.get()[vendor].reverse,
|
|
42
43
|
)
|
|
43
44
|
|
|
44
45
|
|
annet/rulebook/patching.py
CHANGED
|
@@ -3,12 +3,12 @@ import re
|
|
|
3
3
|
from collections import OrderedDict as odict
|
|
4
4
|
|
|
5
5
|
from annet.annlib.rbparser import platform, syntax
|
|
6
|
+
from annet.vendors import registry_connector
|
|
6
7
|
from valkit.common import valid_bool, valid_string_list
|
|
7
8
|
from valkit.python import valid_object_path
|
|
8
9
|
|
|
9
10
|
from .common import import_rulebook_function
|
|
10
11
|
|
|
11
|
-
|
|
12
12
|
DEFAULT_PATCH_LOGIC = "common.default"
|
|
13
13
|
ORDERED_PATCH_LOGIC = "common.ordered"
|
|
14
14
|
REWRITE_PATCH_LOGIC = "common.rewrite"
|
|
@@ -62,7 +62,7 @@ def compile_patching_text(text, vendor):
|
|
|
62
62
|
"default": False,
|
|
63
63
|
},
|
|
64
64
|
}),
|
|
65
|
-
reverse_prefix=
|
|
65
|
+
reverse_prefix=registry_connector.get()[vendor].reverse,
|
|
66
66
|
vendor=vendor,
|
|
67
67
|
)
|
|
68
68
|
|
annet/rulebook/texts/arista.rul
CHANGED
|
@@ -29,13 +29,35 @@ interface * %logic=arista.iface.permanent
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
ip access-list standard *
|
|
32
|
-
*
|
|
32
|
+
* %logic=common.undo_redo
|
|
33
33
|
|
|
34
34
|
ipv6 access-list standard *
|
|
35
|
-
*
|
|
35
|
+
* %logic=common.undo_redo
|
|
36
36
|
|
|
37
37
|
ipv6 access-list *
|
|
38
|
-
|
|
38
|
+
* %logic=common.undo_redo
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# ios-like way of configuring prefix lists
|
|
42
|
+
# should be kept above a eos-native one in arista.rul
|
|
43
|
+
# since beginnig of commands are the same
|
|
44
|
+
# if you use it keep all prefix lists in this format
|
|
45
|
+
|
|
46
|
+
ip prefix-list * seq * %logic=common.undo_redo
|
|
47
|
+
ipv6 prefix-list * seq * %logic=common.undo_redo
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# arista eos native way of configuring prefix lists
|
|
51
|
+
# should be below to not collide with ios-like one
|
|
52
|
+
# only one format is supported at the time for one family
|
|
53
|
+
# prefer this one over the ios-like one
|
|
54
|
+
|
|
55
|
+
ip prefix-list *
|
|
56
|
+
seq * %logic=common.undo_redo
|
|
57
|
+
|
|
58
|
+
ipv6 prefix-list *
|
|
59
|
+
seq * %logic=common.undo_redo
|
|
60
|
+
|
|
39
61
|
|
|
40
62
|
route-map * * *
|
|
41
63
|
~ %global
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Рулбук деплоя на устройства
|
|
2
|
+
#
|
|
3
|
+
# Операторы:
|
|
4
|
+
# * Один аргумент
|
|
5
|
+
# ~ Несколько аргументов (минимум один)
|
|
6
|
+
#
|
|
7
|
+
# Параметры:
|
|
8
|
+
# %timeout=... Таймаут выполнения команды (в секундах, по умолчанию 30)
|
|
9
|
+
#
|
|
10
|
+
# Ответы на вопросы
|
|
11
|
+
#
|
|
12
|
+
# <команда>
|
|
13
|
+
# dialog: <вопрос> ::: <ответ> <параметры>
|
|
14
|
+
#
|
|
15
|
+
# Если <вопрос> заключён в слеши (//), то воспринимается как регулярка, иначе - точное совпадение.
|
|
16
|
+
# Параметы:
|
|
17
|
+
# %send_nl=... Посылать ли перевод строки после ответа (bool, по умолчанию true)
|
|
18
|
+
# -----
|
|
19
|
+
|
|
20
|
+
crypto key generate rsa %timeout=60
|
|
21
|
+
dialog: Do you really want to replace them? [yes/no]: ::: no
|
|
22
|
+
dialog: How many bits in the modulus [512]: ::: 2048
|
|
23
|
+
no username * privilege * secret * *
|
|
24
|
+
dialog: This operation will remove all username related configurations with same name.Do you want to continue? [confirm] ::: Y %send_nl=0
|
|
25
|
+
|
|
26
|
+
copy running-config startup-config
|
|
27
|
+
dialog: Destination filename [startup-config]? ::: startup-config
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# В этом файле определяется порядок команд, в котором их следует подавать на устройство.
|
|
2
|
+
# - Если порядок команды не важен - ее можно не писать сюда совсем.
|
|
3
|
+
# - Если команда начинается с undo и прописан параметр %order_reverse - команда считается
|
|
4
|
+
# обратной, но занимает место между прямыми там, где указано.
|
|
5
|
+
|
|
6
|
+
banner login %order_reverse
|
|
7
|
+
|
|
8
|
+
# Фичи должны быть включены прежде всего
|
|
9
|
+
feature
|
|
10
|
+
# За ним сервисы
|
|
11
|
+
service
|
|
12
|
+
|
|
13
|
+
aaa new-model
|
|
14
|
+
aaa ~
|
|
15
|
+
|
|
16
|
+
no password strength-check
|
|
17
|
+
username
|
|
18
|
+
tacacs-server
|
|
19
|
+
|
|
20
|
+
radius
|
|
21
|
+
radius-server
|
|
22
|
+
dot1x
|
|
23
|
+
|
|
24
|
+
privilege
|
|
25
|
+
file
|
|
26
|
+
|
|
27
|
+
ip access-list
|
|
28
|
+
ipv6 access-list
|
|
29
|
+
class-map
|
|
30
|
+
policy-map
|
|
31
|
+
system qos
|
|
32
|
+
control-plane
|
|
33
|
+
|
|
34
|
+
snmp-server source-interface
|
|
35
|
+
snmp-server user
|
|
36
|
+
snmp-server host
|
|
37
|
+
snmp-server enable
|
|
38
|
+
snmp-server context
|
|
39
|
+
snmp-server community
|
|
40
|
+
snmp-server mib
|
|
41
|
+
|
|
42
|
+
ntp distribute
|
|
43
|
+
ntp server
|
|
44
|
+
ntp commit
|
|
45
|
+
|
|
46
|
+
vlan
|
|
47
|
+
vlan group
|
|
48
|
+
|
|
49
|
+
spanning-tree
|
|
50
|
+
|
|
51
|
+
# перед тем, как менять mtu на интерфейсах, надо выставить максимальный
|
|
52
|
+
no system jumbomtu %order_reverse
|
|
53
|
+
system jumbomtu
|
|
54
|
+
|
|
55
|
+
service dhcp
|
|
56
|
+
ip dhcp relay
|
|
57
|
+
ipv6 dhcp relay
|
|
58
|
+
|
|
59
|
+
vrf context
|
|
60
|
+
|
|
61
|
+
interface */Vlan\d+/
|
|
62
|
+
interface *
|
|
63
|
+
no switchport
|
|
64
|
+
encapsulation
|
|
65
|
+
vrf member
|
|
66
|
+
ip
|
|
67
|
+
ipv6
|
|
68
|
+
no ipv6 nd %order_reverse
|
|
69
|
+
ipv6 nd
|
|
70
|
+
~
|
|
71
|
+
channel-group
|
|
72
|
+
|
|
73
|
+
interface */\S+\.\d+/
|
|
74
|
+
|
|
75
|
+
route-map
|
|
76
|
+
|
|
77
|
+
# удалять eth-trunk можно только после того, как вычистим member interfaces
|
|
78
|
+
undo interface */port-channel\d+/ %order_reverse
|
|
79
|
+
|
|
80
|
+
# remote as of neighbors should be assigned before peer-group, the rule is applied to neighbors, not peer-groups
|
|
81
|
+
router bgp
|
|
82
|
+
neighbor */[\da-f\.\:]+/ remote-as
|
|
83
|
+
neighbor */[\da-f\.\:]+/ peer-group
|
|
84
|
+
|
|
85
|
+
line
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Операторы:
|
|
2
|
+
# * Один аргумент в undo
|
|
3
|
+
# ~ Несколько аргументов (минимум один) в undo
|
|
4
|
+
#
|
|
5
|
+
# Параметры:
|
|
6
|
+
# %global Команда действует на любом уровне ниже
|
|
7
|
+
# %logic=... Кастомная функция обработки правила
|
|
8
|
+
# %diff_logic=... Кастомная функция построения диффа.
|
|
9
|
+
# данная функция работает для подблоков (в отличие от %logic)
|
|
10
|
+
# %comment=... Добавить коммент после строки который будет видно с опцией patch --add-comments
|
|
11
|
+
# Сделано в основном для того чтобы генерировать специальные команды для наливки
|
|
12
|
+
# -----
|
|
13
|
+
|
|
14
|
+
ip domain-name *
|
|
15
|
+
hostname *
|
|
16
|
+
|
|
17
|
+
banner login * %logic=cisco.misc.banner_login
|
|
18
|
+
|
|
19
|
+
ip community-list standard ~
|
|
20
|
+
|
|
21
|
+
!vrf context management
|
|
22
|
+
vrf context *
|
|
23
|
+
|
|
24
|
+
vlan group * vlan-list %logic=cisco.vlandb.simple
|
|
25
|
+
vlan */[^\d].*/
|
|
26
|
+
vlan %logic=cisco.vlandb.simple
|
|
27
|
+
name
|
|
28
|
+
|
|
29
|
+
ip ssh version 2 %logic=cisco.misc.ssh_key
|
|
30
|
+
|
|
31
|
+
# ordering of SNMP blocks
|
|
32
|
+
ip access-list ~
|
|
33
|
+
snmp-server view ~
|
|
34
|
+
snmp-server community ~
|
|
35
|
+
snmp-server host ~
|
|
36
|
+
# Deleting a user using either SNMP or the CLI results in the user being deleted for both SNMP and the CLI.
|
|
37
|
+
# User-role mapping changes are synchronized in SNMP and the CLI.
|
|
38
|
+
!snmp-server user admin ~
|
|
39
|
+
!snmp-server user *
|
|
40
|
+
# Disabling this SNMP option throws WARNING which stops mpdaemon set-up process
|
|
41
|
+
no snmp-server sysobjectid type stack-oid
|
|
42
|
+
|
|
43
|
+
!interface */(mgmt|ipmi|Vlan1$)/
|
|
44
|
+
|
|
45
|
+
interface Loopback
|
|
46
|
+
ipv6 address *
|
|
47
|
+
ip address ~
|
|
48
|
+
! no ip address
|
|
49
|
+
|
|
50
|
+
# SVI/Subifs/Lagg
|
|
51
|
+
interface */(Vlan|Ethernet.*\.|port-channel.*\.?)\d+$/ %diff_logic=cisco.iface.diff
|
|
52
|
+
vrf member
|
|
53
|
+
ipv6 link-local
|
|
54
|
+
ipv6 address *
|
|
55
|
+
ipv6 nd ~ %logic=cisco.misc.no_ipv6_nd_suppress_ra
|
|
56
|
+
ip address ~
|
|
57
|
+
! no ip address
|
|
58
|
+
mtu
|
|
59
|
+
|
|
60
|
+
# Physical
|
|
61
|
+
interface */\w*Ethernet[0-9\/]+$/ %logic=common.permanent %diff_logic=cisco.iface.diff
|
|
62
|
+
switchport mode
|
|
63
|
+
switchport trunk native vlan
|
|
64
|
+
switchport access vlan
|
|
65
|
+
switchport trunk allowed vlan %logic=cisco.vlandb.swtrunk
|
|
66
|
+
vrf member
|
|
67
|
+
ipv6 link-local
|
|
68
|
+
ipv6 address *
|
|
69
|
+
ip address ~
|
|
70
|
+
! no ip address
|
|
71
|
+
channel-group
|
|
72
|
+
mtu
|
|
73
|
+
storm-control * level
|
|
74
|
+
spanning-tree portfast
|
|
75
|
+
|
|
76
|
+
router bgp
|
|
77
|
+
router-id
|
|
78
|
+
vrf *
|
|
79
|
+
router-id
|
|
80
|
+
address-family ~
|
|
81
|
+
maximum-paths
|
|
82
|
+
neighbor ~
|
|
83
|
+
update-source
|
|
84
|
+
|
|
85
|
+
policy-map type qos *
|
|
86
|
+
class * %ordered
|
|
87
|
+
~
|
|
88
|
+
|
|
89
|
+
prefix-set *
|
|
90
|
+
~ %rewrite %global
|
|
91
|
+
|
|
92
|
+
as-path-set *
|
|
93
|
+
~ %rewrite %global
|
|
94
|
+
|
|
95
|
+
community-set *
|
|
96
|
+
~ %rewrite %global
|
|
97
|
+
|
|
98
|
+
route-policy *
|
|
99
|
+
~ %rewrite %global
|
|
100
|
+
|
|
101
|
+
line ~
|
|
102
|
+
exec-timeout
|
|
103
|
+
transport input
|
|
104
|
+
|
|
105
|
+
description %global
|
|
106
|
+
|
|
107
|
+
no ~ %global
|
|
108
|
+
~ %global
|
|
109
|
+
|
|
110
|
+
# vim: set syntax=annrulebook:
|
annet/tabparser.py
CHANGED
|
@@ -23,7 +23,7 @@ def make_formatter(hw, **kwargs):
|
|
|
23
23
|
cls = OptixtransFormatter
|
|
24
24
|
elif hw.Huawei:
|
|
25
25
|
cls = HuaweiFormatter
|
|
26
|
-
elif hw.Cisco.ASR or hw.Cisco.XRV:
|
|
26
|
+
elif hw.Cisco.ASR or hw.Cisco.XRV or hw.Cisco.XR:
|
|
27
27
|
cls = AsrFormatter
|
|
28
28
|
elif hw.Nexus:
|
|
29
29
|
cls = NexusFormatter
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
|
|
3
|
+
from annet.connectors import Connector
|
|
4
|
+
from annet.vendors.base import AbstractVendor
|
|
5
|
+
|
|
6
|
+
from .library import (
|
|
7
|
+
arista,
|
|
8
|
+
aruba,
|
|
9
|
+
b4com,
|
|
10
|
+
cisco,
|
|
11
|
+
h3c,
|
|
12
|
+
huawei,
|
|
13
|
+
iosxr,
|
|
14
|
+
juniper,
|
|
15
|
+
nexus,
|
|
16
|
+
nokia,
|
|
17
|
+
optixtrans,
|
|
18
|
+
pc,
|
|
19
|
+
ribbon,
|
|
20
|
+
routeros,
|
|
21
|
+
)
|
|
22
|
+
from .registry import Registry, registry
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class _RegistryConnector(Connector[Registry]):
|
|
26
|
+
name = "Registry"
|
|
27
|
+
ep_name = "vendors"
|
|
28
|
+
|
|
29
|
+
def _get_default(self) -> Callable[[], Registry]:
|
|
30
|
+
return lambda: registry
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
registry_connector = _RegistryConnector()
|
annet/vendors/base.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from typing import ClassVar
|
|
3
|
+
|
|
4
|
+
from annet.annlib.netdev.views.hardware import HardwareView
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AbstractVendor(abc.ABC):
|
|
8
|
+
NAME: ClassVar[str]
|
|
9
|
+
|
|
10
|
+
@abc.abstractmethod
|
|
11
|
+
def match(self) -> list[str]:
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
@abc.abstractmethod
|
|
16
|
+
def reverse(self) -> str:
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
@abc.abstractmethod
|
|
21
|
+
def hardware(self) -> HardwareView:
|
|
22
|
+
raise NotImplementedError
|
|
23
|
+
|
|
24
|
+
def svi_name(self, num: int) -> str:
|
|
25
|
+
return f"vlan{num}"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
from operator import itemgetter
|
|
3
|
+
|
|
4
|
+
from annet.annlib.netdev.views.hardware import HardwareView
|
|
5
|
+
|
|
6
|
+
from .base import AbstractVendor
|
|
7
|
+
|
|
8
|
+
_SENTINEL = enum.Enum("_SENTINEL", "sentinel")
|
|
9
|
+
sentinel = _SENTINEL.sentinel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GenericVendor(AbstractVendor):
|
|
13
|
+
def match(self) -> list[str]:
|
|
14
|
+
return []
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def reverse(self) -> str:
|
|
18
|
+
return "-"
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def hardware(self) -> HardwareView:
|
|
22
|
+
return HardwareView("")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
GENERIC_VENDOR = GenericVendor()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Registry:
|
|
29
|
+
def __init__(self):
|
|
30
|
+
self.vendors: dict[str, AbstractVendor] = {}
|
|
31
|
+
self._matchers = {}
|
|
32
|
+
|
|
33
|
+
def register(self, cls: type[AbstractVendor]) -> type[AbstractVendor]:
|
|
34
|
+
if not cls.NAME:
|
|
35
|
+
raise RuntimeError(f"{cls.__name__} has empty NAME field")
|
|
36
|
+
if cls.NAME in self.vendors:
|
|
37
|
+
raise RuntimeError(f"{cls.__name__} with name {cls.NAME} already registered")
|
|
38
|
+
self.vendors[cls.NAME] = cls()
|
|
39
|
+
|
|
40
|
+
return cls
|
|
41
|
+
|
|
42
|
+
def __add__(self, other: "Registry"):
|
|
43
|
+
self.vendors = dict(**other.vendors, **self.vendors)
|
|
44
|
+
|
|
45
|
+
def __getitem__(self, item) -> AbstractVendor:
|
|
46
|
+
if item in self.vendors:
|
|
47
|
+
return self.vendors[item]
|
|
48
|
+
raise RuntimeError(f"Unknown vendor {item}")
|
|
49
|
+
|
|
50
|
+
def match(
|
|
51
|
+
self,
|
|
52
|
+
hw: HardwareView | str,
|
|
53
|
+
default: _SENTINEL | AbstractVendor | None = sentinel
|
|
54
|
+
) -> AbstractVendor | None:
|
|
55
|
+
if isinstance(hw, str):
|
|
56
|
+
hw = HardwareView(hw, "")
|
|
57
|
+
|
|
58
|
+
matched: list[tuple[AbstractVendor, int]] = []
|
|
59
|
+
for name, vendor in self.vendors.items():
|
|
60
|
+
for item in vendor.match():
|
|
61
|
+
if hw.match(item):
|
|
62
|
+
matched.append((vendor, item.count(".")))
|
|
63
|
+
|
|
64
|
+
if matched:
|
|
65
|
+
return next(iter(sorted(matched, key=itemgetter(1), reverse=True)))[0]
|
|
66
|
+
if default is sentinel:
|
|
67
|
+
return GENERIC_VENDOR
|
|
68
|
+
return default
|
|
69
|
+
|
|
70
|
+
def get(self, item: str, default: _SENTINEL | AbstractVendor | None = sentinel) -> AbstractVendor | None:
|
|
71
|
+
if item in self:
|
|
72
|
+
return self[item]
|
|
73
|
+
if default is sentinel:
|
|
74
|
+
return GENERIC_VENDOR
|
|
75
|
+
return default
|
|
76
|
+
|
|
77
|
+
def __contains__(self, item):
|
|
78
|
+
return item in self.vendors
|
|
79
|
+
|
|
80
|
+
def __iter__(self):
|
|
81
|
+
return iter(self.vendors)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
registry = Registry()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
annet/__init__.py,sha256=0OKkFkqog8As7B6ApdpKQkrEAcEELUREWp82D8WvGA8,1846
|
|
2
|
-
annet/annet.py,sha256=
|
|
2
|
+
annet/annet.py,sha256=vyQ__n5hkjub3aWO8tksHPoUSbTeK97MyMcR_U8_BSU,1016
|
|
3
3
|
annet/argparse.py,sha256=v1MfhjR0B8qahza0WinmXClpR8UiDFhmwDDWtNroJPA,12855
|
|
4
4
|
annet/bgp_models.py,sha256=oibTSdipNkGL4t8Xn94bhyKHMOtwbPBqmYaAy4FmTxQ,12361
|
|
5
5
|
annet/cli.py,sha256=shq3hHzrTxFL3x1_zTOR43QHo0JYs8QSwyOvGtL86Co,12733
|
|
@@ -11,15 +11,15 @@ annet/diff.py,sha256=vz51az7RrXdYXsPbNMi9Y2awbjNRPQSFl6zzvE36Kx4,9441
|
|
|
11
11
|
annet/executor.py,sha256=lcKI-EbYqeCiBNpL729kSltduzxbAzOkQ1L_QK7tNv8,5112
|
|
12
12
|
annet/filtering.py,sha256=ZtqxPsKdV9reZoRxtQyBg22BqyMqd-2SotYcxZ-68AQ,903
|
|
13
13
|
annet/gen.py,sha256=m76bL6rVbusNV_uVHrHnA3D7TUvvLtckXx7hlr5HGA0,31897
|
|
14
|
-
annet/hardware.py,sha256=
|
|
14
|
+
annet/hardware.py,sha256=e7RWc5yPdEDT5hxNqcqWv9g9DRWIgwAieA2iT4FdPqc,1158
|
|
15
15
|
annet/implicit.py,sha256=G6EwZbrtUp089qRAwh96hminp236-1pJbeKAedoEafg,6056
|
|
16
16
|
annet/lib.py,sha256=4N4X6jCCrig5rk7Ua4AofrV9zK9jhzkBq57fLsfBJjw,4812
|
|
17
17
|
annet/output.py,sha256=se8EpyNS9f9kPOlOaAV0ht4DjzDoBr8F2UafiezLPYw,7743
|
|
18
|
-
annet/parallel.py,sha256=
|
|
18
|
+
annet/parallel.py,sha256=onkE3q3Pe1CjOa3fI20vWUA5VO50sPlPxzfyiVdo8pI,17703
|
|
19
19
|
annet/patching.py,sha256=nILbY5oJajN0b1j3f0HEJm05H3HVThnWvB7vDVh7UQw,559
|
|
20
20
|
annet/reference.py,sha256=B8mH8VUMcecPnzULiTVb_kTQ7jQrCL7zp4pfIZQa5fk,4035
|
|
21
21
|
annet/storage.py,sha256=44f2aHNFOsQMSJwFvGxyu26oRcs3QmS24TKivcfPlxU,4064
|
|
22
|
-
annet/tabparser.py,sha256=
|
|
22
|
+
annet/tabparser.py,sha256=oN0pFeO1GEgMD-ti9rHl5SvaYZPZbrYx_BIVedIC5JQ,1257
|
|
23
23
|
annet/text_term_format.py,sha256=y0U6VuFEAEil8Ab3HB8DBbVHisu31EHiRV7AOVruCeA,2816
|
|
24
24
|
annet/tracing.py,sha256=ndpM-au1c88uBBpOuH_z52qWZL773edYozNyys_wA68,4044
|
|
25
25
|
annet/types.py,sha256=f2HwqoKa6AucwFwDMszoouB6m1B8n6VmdjHMktO30Kc,7175
|
|
@@ -28,20 +28,20 @@ annet/adapters/fetchers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
|
28
28
|
annet/adapters/fetchers/stub/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
29
|
annet/adapters/fetchers/stub/fetcher.py,sha256=FzpkIzPJBQVuNNSdXKoGzkALmIGMgo2gmGLXzYWdDYA,891
|
|
30
30
|
annet/adapters/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
-
annet/adapters/file/provider.py,sha256=
|
|
31
|
+
annet/adapters/file/provider.py,sha256=3hNt0QQg46SVymLQ4Bh9G4VNYyhnB7gV5yu5OiIJpZE,7307
|
|
32
32
|
annet/adapters/netbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
33
|
annet/adapters/netbox/provider.py,sha256=SrxW_uBLvMTqtRiYXreL6RrZK4MpxVguF2ITnYOnVHU,2226
|
|
34
34
|
annet/adapters/netbox/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
35
|
annet/adapters/netbox/common/adapter.py,sha256=-YcO3371D8hupNXKf5f4-FdFSjTto-7VKDvz29Gid38,2016
|
|
36
36
|
annet/adapters/netbox/common/client.py,sha256=PaxHG4W9H8_uunIwMBNYkLq4eQJYoO6p6gY-ciQs7Nc,2563
|
|
37
|
-
annet/adapters/netbox/common/manufacturer.py,sha256=
|
|
38
|
-
annet/adapters/netbox/common/models.py,sha256=
|
|
37
|
+
annet/adapters/netbox/common/manufacturer.py,sha256=n1RxJSGqXilKcGSqwIc7d2jD1NCaUXG5kQcOO93WTxw,1319
|
|
38
|
+
annet/adapters/netbox/common/models.py,sha256=IS9q5ZhrDhp74sjl5exSQu6lVOrQCX_I_RRtA9uCcdg,7686
|
|
39
39
|
annet/adapters/netbox/common/query.py,sha256=kbNQSZwkjFeDArHwA8INHUauxCxYElXtNh58pZipWdo,1867
|
|
40
40
|
annet/adapters/netbox/common/status_client.py,sha256=POaqiQJ0jPcqUQH-X_fWHVnKB7TBYveNriaT0eNTlfI,769
|
|
41
41
|
annet/adapters/netbox/common/storage_base.py,sha256=3dn42CWTEZVBig4ABhy5BMQQ3YGb28InncWZoGvrgKk,8768
|
|
42
42
|
annet/adapters/netbox/common/storage_opts.py,sha256=wfv1spElomwgVYMCgGth3SWVF0RsRgtUgq9GpFL9hJs,1520
|
|
43
43
|
annet/adapters/netbox/v24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
|
-
annet/adapters/netbox/v24/models.py,sha256=
|
|
44
|
+
annet/adapters/netbox/v24/models.py,sha256=RH2ooUPHOtHT0q1ZQE7v23FgmcsGenzzSgJyft13o1k,7605
|
|
45
45
|
annet/adapters/netbox/v24/storage.py,sha256=zptzrW4aZUv_exuGw0DqQPm_kXZR3DwL4zRHYL6twTk,6219
|
|
46
46
|
annet/adapters/netbox/v37/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
47
|
annet/adapters/netbox/v37/models.py,sha256=VqI1bT5E5pFIaDJWxWMU6bioNyrXKJuNq-_J8YIJIbw,1613
|
|
@@ -60,28 +60,28 @@ annet/annlib/filter_acl.py,sha256=mxDga-3SXqpPEsdQypTq0ScqUqP625lxX-DmJalEc3s,71
|
|
|
60
60
|
annet/annlib/jsontools.py,sha256=BS7s4rI8R9c_y3zz0zYl1l6con65oQ0MvfsC1dsXZts,5535
|
|
61
61
|
annet/annlib/lib.py,sha256=lxmYrbeablFMhFtvFmADVpVShSFi9TN4gNWaBs_Ygm0,14952
|
|
62
62
|
annet/annlib/output.py,sha256=_SjJ6G6bejvnTKqNHw6xeio0FT9oO3OIkLaOC3cEga4,7569
|
|
63
|
-
annet/annlib/patching.py,sha256=
|
|
63
|
+
annet/annlib/patching.py,sha256=1Ku5dNCQS9nlsMEr7tt7o1uGBsBeqfVFw4NY8aWYvnc,21483
|
|
64
64
|
annet/annlib/tabparser.py,sha256=aXwY0glVQ4__Sg1FFXiSPghyoNQRrMUQ7XCjMq__3lM,32016
|
|
65
65
|
annet/annlib/types.py,sha256=VHU0CBADfYmO0xzB_c5f-mcuU3dUumuJczQnqGlib9M,852
|
|
66
66
|
annet/annlib/netdev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
annet/annlib/netdev/db.py,sha256=fI_u5aya4l61mbYSjj4JwlVfi3s7obt2jqERSuXGRUI,1634
|
|
68
68
|
annet/annlib/netdev/devdb/__init__.py,sha256=aKYjjLbJebdKBjnGDpVLQdSqrV2JL24spGm58tmMWVU,892
|
|
69
|
-
annet/annlib/netdev/devdb/data/devdb.json,sha256=
|
|
69
|
+
annet/annlib/netdev/devdb/data/devdb.json,sha256=t-j7SjEqSWNPhYV3cPQCSpODc3VGcRKJze9fgj4L9Uw,6710
|
|
70
70
|
annet/annlib/netdev/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
71
|
annet/annlib/netdev/views/dump.py,sha256=rIlyvnA3uM8bB_7oq1nS2KDxTp6dQh2hz-FbNhYIpOU,4630
|
|
72
|
-
annet/annlib/netdev/views/hardware.py,sha256=
|
|
72
|
+
annet/annlib/netdev/views/hardware.py,sha256=XvHtRn29SROKtxqMyr86oc1ItUKy36N98ppfuJQL8PY,3235
|
|
73
73
|
annet/annlib/rbparser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
|
-
annet/annlib/rbparser/acl.py,sha256=
|
|
74
|
+
annet/annlib/rbparser/acl.py,sha256=I_1VUZQgF-s4dYTxyEDxQ-GkAP2MeXonzzsc2xROpTM,3974
|
|
75
75
|
annet/annlib/rbparser/deploying.py,sha256=ACT8QNhDAhJx3ZKuGh2nYBOrpdka2qEKuLDxvQAGKLk,1649
|
|
76
|
-
annet/annlib/rbparser/ordering.py,sha256=
|
|
77
|
-
annet/annlib/rbparser/platform.py,sha256=
|
|
76
|
+
annet/annlib/rbparser/ordering.py,sha256=XknggB92N4IbhHBZZHL0StwCCITt8mkho4D4Nu5Kb4k,2185
|
|
77
|
+
annet/annlib/rbparser/platform.py,sha256=vNoK25ACNQuDRv5I9uDfmNi8Y8yi10XWSbWIeKEVUgs,1672
|
|
78
78
|
annet/annlib/rbparser/syntax.py,sha256=iZ7Y-4QQBw4L3UtjEh54qisiRDhobl7HZxFNdP8mi54,3577
|
|
79
79
|
annet/annlib/rulebook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
|
-
annet/annlib/rulebook/common.py,sha256
|
|
81
|
-
annet/api/__init__.py,sha256=
|
|
80
|
+
annet/annlib/rulebook/common.py,sha256=-E6ATuFkSjNhyK0hiGd-iap5Ch5up2MNuVCbobWfmeU,16649
|
|
81
|
+
annet/api/__init__.py,sha256=KYtCj2Kgj2Qt1eqhk8kpSz4QgXToDdK2Okvtac3UD-w,33152
|
|
82
82
|
annet/configs/context.yml,sha256=RVLrKLIHpCty7AGwOnmqf7Uu0iZQCn-AjYhophDJer8,259
|
|
83
83
|
annet/configs/logging.yaml,sha256=EUagfir99QqA73Scc3k7sfQccbU3E1SvEQdyhLFtCl4,997
|
|
84
|
-
annet/generators/__init__.py,sha256=
|
|
84
|
+
annet/generators/__init__.py,sha256=9MmstB59DlHGnY7GP36nyTiAdKtHdsJTyOYc0cxwm5U,16398
|
|
85
85
|
annet/generators/base.py,sha256=rgQLcQBPZm4ecbKmRhVOpBR-GFJAiVfdb_y5f2-LUR8,3670
|
|
86
86
|
annet/generators/entire.py,sha256=Oe7d0VuIn2sLcOKuRVQW9uR8Vuirg0edekFMSZCMnI4,2786
|
|
87
87
|
annet/generators/exceptions.py,sha256=GPXTBgn2xZ3Ev_bdOPlfCLGRC1kQHe_dEq88S-uyi5s,151
|
|
@@ -118,10 +118,10 @@ annet/rpl_generators/execute.py,sha256=wS6e6fwcPWywsHB0gBMqZ17eF0s4YOBgDgwPB_cr5
|
|
|
118
118
|
annet/rpl_generators/policy.py,sha256=j_2EtAsaxldhZZT4kRXKZacuAsGnHr3JSc2BMxr_Pow,37174
|
|
119
119
|
annet/rpl_generators/prefix_lists.py,sha256=5jM5Xj0dtx5xF9ap-TgExs0ofRAzm0LN2j3aL5Ub_yc,4778
|
|
120
120
|
annet/rpl_generators/rd.py,sha256=YGXgx1D2D0-pixgspXJzA6NvW8lx3AmHMxIY2l5rraI,1457
|
|
121
|
-
annet/rulebook/__init__.py,sha256=
|
|
121
|
+
annet/rulebook/__init__.py,sha256=WtDrO9BrbrF1o06zOTVrEMGuTgDtv7MfF8B29pRW77U,3996
|
|
122
122
|
annet/rulebook/common.py,sha256=zK1s2c5lc5HQbIlMUQ4HARQudXSgOYiZ_Sxc2I_tHqg,721
|
|
123
|
-
annet/rulebook/deploying.py,sha256=
|
|
124
|
-
annet/rulebook/patching.py,sha256=
|
|
123
|
+
annet/rulebook/deploying.py,sha256=9CMeOUw5L1OWdrccSRfpJyH9H_jH7xWNU1JldviBNrk,3015
|
|
124
|
+
annet/rulebook/patching.py,sha256=4JQE_qmdHb0Eggj9ytp99P1Z59uW5ZeUrPJIOdfgi_0,5022
|
|
125
125
|
annet/rulebook/arista/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
126
126
|
annet/rulebook/arista/aaa.py,sha256=7fBTwBnz9SOqYbwG8GBeEQTJG0e4uC4HkuZJeMG-kAY,2250
|
|
127
127
|
annet/rulebook/arista/iface.py,sha256=bgj6a3r__-OE6VyYbSfnD6ps2QJKyX028W7IFJww-UY,720
|
|
@@ -148,7 +148,7 @@ annet/rulebook/routeros/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
|
148
148
|
annet/rulebook/routeros/file.py,sha256=zK7RwBk1YaVoDSFSg1u7Pt8u0Fk3nhhu27aJRngemwc,137
|
|
149
149
|
annet/rulebook/texts/arista.deploy,sha256=OS9eFyJpEPztcOHkBwajw_RTJfTT7ivaMHfx4_HXaUg,792
|
|
150
150
|
annet/rulebook/texts/arista.order,sha256=1jbKfF0USYi2b8V5qFlp4LjBAr3QGL9OkmoQqEK3PW8,1385
|
|
151
|
-
annet/rulebook/texts/arista.rul,sha256=
|
|
151
|
+
annet/rulebook/texts/arista.rul,sha256=S48RSfJAGwMyS7psl5ABZTzr1HZsvbrkLXRG3FyE13w,1537
|
|
152
152
|
annet/rulebook/texts/aruba.deploy,sha256=hI432Bq-of_LMXuUflCu7eNSEFpx6qmj0KItEw6sgHI,841
|
|
153
153
|
annet/rulebook/texts/aruba.order,sha256=ZMakkn0EJ9zomgY6VssoptJImrHrUmYnCqivzLBFTRo,1158
|
|
154
154
|
annet/rulebook/texts/aruba.rul,sha256=zvGVpoYyJvMoL0fb1NQ8we_GCLZXno8nwWpZIOScLQQ,2584
|
|
@@ -161,6 +161,9 @@ annet/rulebook/texts/cisco.rul,sha256=jgL5_xnSwd_H4E8cx4gcneSvJC5W1zz6_BWSb64iux
|
|
|
161
161
|
annet/rulebook/texts/huawei.deploy,sha256=uUsZCHUrC5Zyb_MePrR5svnE1QyGQlg7UxcKf00sJyg,10451
|
|
162
162
|
annet/rulebook/texts/huawei.order,sha256=_X2LmxD9FGcIcb8ziwc13Imy1tBtQJgafrQGmvHPZLM,10649
|
|
163
163
|
annet/rulebook/texts/huawei.rul,sha256=02Fi1RG4YYea2clHCluBuJDKNbT0hS9jtsk6_h6GK8k,12958
|
|
164
|
+
annet/rulebook/texts/iosxr.deploy,sha256=Hu0NkcGv3f1CWUrnbzI3eQOPXJxtH4NNOPRV68IrW4U,1226
|
|
165
|
+
annet/rulebook/texts/iosxr.order,sha256=OvNHMNqkCc-DN2dEjLCTKv_7ZhiaHt4q2X4Y4Z8dvR4,1901
|
|
166
|
+
annet/rulebook/texts/iosxr.rul,sha256=MhIoIbOrfqisbyprZLy86DvO4rl6LtPESFnDU9nQUY0,2974
|
|
164
167
|
annet/rulebook/texts/juniper.order,sha256=PpxmcCgeaeP3TyYe3BWvtb24MKYV_BujjCH3HD4lsc8,256
|
|
165
168
|
annet/rulebook/texts/juniper.rul,sha256=EmtrEJZesnmc2nXjURRD2G0WOq4zLluI_PNupKhSOJs,2654
|
|
166
169
|
annet/rulebook/texts/nexus.deploy,sha256=9YNAQEw7aQxtYZJbE-dMD6qJrTzs_G92Ifrx3Ft4Wn4,1120
|
|
@@ -177,21 +180,25 @@ annet/rulebook/texts/ribbon.deploy,sha256=hCq2XeAcwaYanyQ8lTdnez6Pgq-gRqpNuR8dAl
|
|
|
177
180
|
annet/rulebook/texts/ribbon.rul,sha256=609LyLTDCtXPVQNAzqS-VEyCpW3byHP8TCMJLFMn5cc,2108
|
|
178
181
|
annet/rulebook/texts/routeros.order,sha256=M71uy_hf0KAjLNS3zZY3uih4m2xLUcu26FEoVVjC6k0,905
|
|
179
182
|
annet/rulebook/texts/routeros.rul,sha256=ipfxjj0mjFef6IsUlupqx4BY_Je_OUb8u_U1019O1DE,1203
|
|
180
|
-
annet
|
|
181
|
-
annet
|
|
183
|
+
annet/vendors/__init__.py,sha256=gQcDFlKeWDZB6vxJ_MdPWEoE-C5dg-YgXvgGkuV9YLw,569
|
|
184
|
+
annet/vendors/base.py,sha256=ll7WKL9KtHiNl9Cs6pQs4bJH6c6JRhyHIM7wdgkysdU,536
|
|
185
|
+
annet/vendors/registry.py,sha256=hav8ONavMAM7FCHgF-0_NKC_ntNAtcTicjxqXNtbovw,2326
|
|
186
|
+
annet-3.0.0.dist-info/licenses/AUTHORS,sha256=rh3w5P6gEgqmuC-bw-HB68vBCr-yIBFhVL0PG4hguLs,878
|
|
187
|
+
annet-3.0.0.dist-info/licenses/LICENSE,sha256=yPxl7dno02Pw7gAcFPIFONzx_gapwDoPXsIsh6Y7lC0,1079
|
|
182
188
|
annet_generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
183
|
-
annet_generators/example/__init__.py,sha256=
|
|
189
|
+
annet_generators/example/__init__.py,sha256=OJ77uj8axc-FIyIu_Xdcnzmde3oQW5mk5qbODkhuVc8,355
|
|
190
|
+
annet_generators/example/hostname.py,sha256=RloLzNVetEoWPLITzfJ13Nk3CC0yi-cZB1RTd6dnuhI,2541
|
|
184
191
|
annet_generators/example/lldp.py,sha256=24bGvShxbio-JxUdaehyPRu31LhH9YwSwFDrWVRn6yo,2100
|
|
185
192
|
annet_generators/mesh_example/__init__.py,sha256=NfNWgXn1TNiWI6A5tmU6Y-4QV2i33td0Qs3re0MNNMo,218
|
|
186
193
|
annet_generators/mesh_example/bgp.py,sha256=jzyDndSSGYyYBquDnLlR-7P5lzmUKcSyYCml3VsoMC0,1385
|
|
187
194
|
annet_generators/mesh_example/mesh_logic.py,sha256=DJS5JMCTs0rs0LN__0LulNgo2ekUcWiOMe02BlOeFas,1454
|
|
188
195
|
annet_generators/rpl_example/__init__.py,sha256=A7DTn-SVSlUpeO7mKT_obqimp29p9zWfVRPBSxmENQY,209
|
|
189
|
-
annet_generators/rpl_example/generator.py,sha256=
|
|
196
|
+
annet_generators/rpl_example/generator.py,sha256=EWah19gOH8G-QyNyWqxCqdRi0BK7GbM-l7g6GIg2xDI,3967
|
|
190
197
|
annet_generators/rpl_example/items.py,sha256=d99HSXDHFjZq511EvGhIqRTWK3F4ZsCWfdUqFYQcyhE,772
|
|
191
198
|
annet_generators/rpl_example/mesh.py,sha256=z_WgfDZZ4xnyh3cSf75igyH09hGvtexEVwy1gCD_DzA,288
|
|
192
199
|
annet_generators/rpl_example/route_policy.py,sha256=z6nPb0VDeQtKD1NIg9sFvmUxBD5tVs2frfNIuKdM-5c,2318
|
|
193
|
-
annet-
|
|
194
|
-
annet-
|
|
195
|
-
annet-
|
|
196
|
-
annet-
|
|
197
|
-
annet-
|
|
200
|
+
annet-3.0.0.dist-info/METADATA,sha256=x8H3f6rBvrh1jfXlkoWpqA5LiH7ZB6mnoc04Yhb6o6I,815
|
|
201
|
+
annet-3.0.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
202
|
+
annet-3.0.0.dist-info/entry_points.txt,sha256=5lIaDGlGi3l6QQ2ry2jZaqViP5Lvt8AmsegdD0Uznck,192
|
|
203
|
+
annet-3.0.0.dist-info/top_level.txt,sha256=QsoTZBsUtwp_FEcmRwuN8QITBmLOZFqjssRfKilGbP8,23
|
|
204
|
+
annet-3.0.0.dist-info/RECORD,,
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import itertools
|
|
1
2
|
from typing import List
|
|
2
3
|
|
|
3
4
|
from annet.generators import BaseGenerator
|
|
4
5
|
from annet.storage import Storage
|
|
5
6
|
|
|
6
7
|
from . import lldp
|
|
8
|
+
from . import hostname
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
def get_generators(store: Storage) -> List[BaseGenerator]:
|
|
10
|
-
return
|
|
12
|
+
return list(itertools.chain.from_iterable([
|
|
13
|
+
hostname.get_generators(store),
|
|
14
|
+
lldp.get_generators(store),
|
|
15
|
+
]))
|