annet 0.16.36__tar.gz → 0.16.37__tar.gz

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.

Files changed (192) hide show
  1. {annet-0.16.36/annet.egg-info → annet-0.16.37}/PKG-INFO +2 -2
  2. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/common/models.py +12 -7
  3. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/common/storage_opts.py +17 -2
  4. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/v37/storage.py +5 -36
  5. {annet-0.16.36 → annet-0.16.37}/annet/bgp_models.py +1 -0
  6. {annet-0.16.36 → annet-0.16.37}/annet/mesh/executor.py +9 -8
  7. {annet-0.16.36 → annet-0.16.37}/annet/mesh/peer_models.py +1 -0
  8. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/prefix_lists.py +14 -14
  9. {annet-0.16.36 → annet-0.16.37/annet.egg-info}/PKG-INFO +2 -2
  10. {annet-0.16.36 → annet-0.16.37}/annet.egg-info/requires.txt +1 -1
  11. {annet-0.16.36 → annet-0.16.37}/setup.py +1 -1
  12. {annet-0.16.36 → annet-0.16.37}/AUTHORS +0 -0
  13. {annet-0.16.36 → annet-0.16.37}/LICENSE +0 -0
  14. {annet-0.16.36 → annet-0.16.37}/MANIFEST.in +0 -0
  15. {annet-0.16.36 → annet-0.16.37}/README.md +0 -0
  16. {annet-0.16.36 → annet-0.16.37}/annet/__init__.py +0 -0
  17. {annet-0.16.36 → annet-0.16.37}/annet/adapters/__init__.py +0 -0
  18. {annet-0.16.36 → annet-0.16.37}/annet/adapters/fetchers/__init__.py +0 -0
  19. {annet-0.16.36 → annet-0.16.37}/annet/adapters/fetchers/stub/__init__.py +0 -0
  20. {annet-0.16.36 → annet-0.16.37}/annet/adapters/fetchers/stub/fetcher.py +0 -0
  21. {annet-0.16.36 → annet-0.16.37}/annet/adapters/file/__init__.py +0 -0
  22. {annet-0.16.36 → annet-0.16.37}/annet/adapters/file/provider.py +0 -0
  23. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/__init__.py +0 -0
  24. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/common/__init__.py +0 -0
  25. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/common/client.py +0 -0
  26. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/common/manufacturer.py +0 -0
  27. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/common/query.py +0 -0
  28. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/common/status_client.py +0 -0
  29. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/provider.py +0 -0
  30. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/v24/__init__.py +0 -0
  31. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/v24/storage.py +0 -0
  32. {annet-0.16.36 → annet-0.16.37}/annet/adapters/netbox/v37/__init__.py +0 -0
  33. {annet-0.16.36 → annet-0.16.37}/annet/annet.py +0 -0
  34. {annet-0.16.36 → annet-0.16.37}/annet/annlib/__init__.py +0 -0
  35. {annet-0.16.36 → annet-0.16.37}/annet/annlib/command.py +0 -0
  36. {annet-0.16.36 → annet-0.16.37}/annet/annlib/diff.py +0 -0
  37. {annet-0.16.36 → annet-0.16.37}/annet/annlib/errors.py +0 -0
  38. {annet-0.16.36 → annet-0.16.37}/annet/annlib/filter_acl.py +0 -0
  39. {annet-0.16.36 → annet-0.16.37}/annet/annlib/jsontools.py +0 -0
  40. {annet-0.16.36 → annet-0.16.37}/annet/annlib/lib.py +0 -0
  41. {annet-0.16.36 → annet-0.16.37}/annet/annlib/netdev/__init__.py +0 -0
  42. {annet-0.16.36 → annet-0.16.37}/annet/annlib/netdev/db.py +0 -0
  43. {annet-0.16.36 → annet-0.16.37}/annet/annlib/netdev/devdb/__init__.py +0 -0
  44. {annet-0.16.36 → annet-0.16.37}/annet/annlib/netdev/devdb/data/devdb.json +0 -0
  45. {annet-0.16.36 → annet-0.16.37}/annet/annlib/netdev/views/__init__.py +0 -0
  46. {annet-0.16.36 → annet-0.16.37}/annet/annlib/netdev/views/dump.py +0 -0
  47. {annet-0.16.36 → annet-0.16.37}/annet/annlib/netdev/views/hardware.py +0 -0
  48. {annet-0.16.36 → annet-0.16.37}/annet/annlib/output.py +0 -0
  49. {annet-0.16.36 → annet-0.16.37}/annet/annlib/patching.py +0 -0
  50. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rbparser/__init__.py +0 -0
  51. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rbparser/acl.py +0 -0
  52. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rbparser/deploying.py +0 -0
  53. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rbparser/ordering.py +0 -0
  54. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rbparser/platform.py +0 -0
  55. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rbparser/syntax.py +0 -0
  56. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rulebook/__init__.py +0 -0
  57. {annet-0.16.36 → annet-0.16.37}/annet/annlib/rulebook/common.py +0 -0
  58. {annet-0.16.36 → annet-0.16.37}/annet/annlib/tabparser.py +0 -0
  59. {annet-0.16.36 → annet-0.16.37}/annet/annlib/types.py +0 -0
  60. {annet-0.16.36 → annet-0.16.37}/annet/api/__init__.py +0 -0
  61. {annet-0.16.36 → annet-0.16.37}/annet/argparse.py +0 -0
  62. {annet-0.16.36 → annet-0.16.37}/annet/cli.py +0 -0
  63. {annet-0.16.36 → annet-0.16.37}/annet/cli_args.py +0 -0
  64. {annet-0.16.36 → annet-0.16.37}/annet/configs/context.yml +0 -0
  65. {annet-0.16.36 → annet-0.16.37}/annet/configs/logging.yaml +0 -0
  66. {annet-0.16.36 → annet-0.16.37}/annet/connectors.py +0 -0
  67. {annet-0.16.36 → annet-0.16.37}/annet/deploy.py +0 -0
  68. {annet-0.16.36 → annet-0.16.37}/annet/diff.py +0 -0
  69. {annet-0.16.36 → annet-0.16.37}/annet/executor.py +0 -0
  70. {annet-0.16.36 → annet-0.16.37}/annet/filtering.py +0 -0
  71. {annet-0.16.36 → annet-0.16.37}/annet/gen.py +0 -0
  72. {annet-0.16.36 → annet-0.16.37}/annet/generators/__init__.py +0 -0
  73. {annet-0.16.36 → annet-0.16.37}/annet/generators/base.py +0 -0
  74. {annet-0.16.36 → annet-0.16.37}/annet/generators/common/__init__.py +0 -0
  75. {annet-0.16.36 → annet-0.16.37}/annet/generators/common/initial.py +0 -0
  76. {annet-0.16.36 → annet-0.16.37}/annet/generators/entire.py +0 -0
  77. {annet-0.16.36 → annet-0.16.37}/annet/generators/exceptions.py +0 -0
  78. {annet-0.16.36 → annet-0.16.37}/annet/generators/jsonfragment.py +0 -0
  79. {annet-0.16.36 → annet-0.16.37}/annet/generators/partial.py +0 -0
  80. {annet-0.16.36 → annet-0.16.37}/annet/generators/perf.py +0 -0
  81. {annet-0.16.36 → annet-0.16.37}/annet/generators/ref.py +0 -0
  82. {annet-0.16.36 → annet-0.16.37}/annet/generators/result.py +0 -0
  83. {annet-0.16.36 → annet-0.16.37}/annet/hardware.py +0 -0
  84. {annet-0.16.36 → annet-0.16.37}/annet/implicit.py +0 -0
  85. {annet-0.16.36 → annet-0.16.37}/annet/lib.py +0 -0
  86. {annet-0.16.36 → annet-0.16.37}/annet/mesh/__init__.py +0 -0
  87. {annet-0.16.36 → annet-0.16.37}/annet/mesh/basemodel.py +0 -0
  88. {annet-0.16.36 → annet-0.16.37}/annet/mesh/device_models.py +0 -0
  89. {annet-0.16.36 → annet-0.16.37}/annet/mesh/match_args.py +0 -0
  90. {annet-0.16.36 → annet-0.16.37}/annet/mesh/models_converter.py +0 -0
  91. {annet-0.16.36 → annet-0.16.37}/annet/mesh/port_processor.py +0 -0
  92. {annet-0.16.36 → annet-0.16.37}/annet/mesh/registry.py +0 -0
  93. {annet-0.16.36 → annet-0.16.37}/annet/output.py +0 -0
  94. {annet-0.16.36 → annet-0.16.37}/annet/parallel.py +0 -0
  95. {annet-0.16.36 → annet-0.16.37}/annet/patching.py +0 -0
  96. {annet-0.16.36 → annet-0.16.37}/annet/reference.py +0 -0
  97. {annet-0.16.36 → annet-0.16.37}/annet/rpl/__init__.py +0 -0
  98. {annet-0.16.36 → annet-0.16.37}/annet/rpl/action.py +0 -0
  99. {annet-0.16.36 → annet-0.16.37}/annet/rpl/condition.py +0 -0
  100. {annet-0.16.36 → annet-0.16.37}/annet/rpl/match_builder.py +0 -0
  101. {annet-0.16.36 → annet-0.16.37}/annet/rpl/policy.py +0 -0
  102. {annet-0.16.36 → annet-0.16.37}/annet/rpl/result.py +0 -0
  103. {annet-0.16.36 → annet-0.16.37}/annet/rpl/routemap.py +0 -0
  104. {annet-0.16.36 → annet-0.16.37}/annet/rpl/statement_builder.py +0 -0
  105. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/__init__.py +0 -0
  106. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/aspath.py +0 -0
  107. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/community.py +0 -0
  108. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/cumulus_frr.py +0 -0
  109. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/entities.py +0 -0
  110. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/execute.py +0 -0
  111. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/policy.py +0 -0
  112. {annet-0.16.36 → annet-0.16.37}/annet/rpl_generators/rd.py +0 -0
  113. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/__init__.py +0 -0
  114. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/arista/__init__.py +0 -0
  115. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/arista/iface.py +0 -0
  116. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/aruba/__init__.py +0 -0
  117. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/aruba/ap_env.py +0 -0
  118. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/aruba/misc.py +0 -0
  119. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/b4com/__init__.py +0 -0
  120. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/b4com/file.py +0 -0
  121. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/b4com/iface.py +0 -0
  122. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/cisco/__init__.py +0 -0
  123. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/cisco/iface.py +0 -0
  124. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/cisco/misc.py +0 -0
  125. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/cisco/vlandb.py +0 -0
  126. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/common.py +0 -0
  127. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/deploying.py +0 -0
  128. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/huawei/__init__.py +0 -0
  129. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/huawei/aaa.py +0 -0
  130. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/huawei/bgp.py +0 -0
  131. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/huawei/iface.py +0 -0
  132. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/huawei/misc.py +0 -0
  133. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/huawei/vlandb.py +0 -0
  134. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/juniper/__init__.py +0 -0
  135. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/nexus/__init__.py +0 -0
  136. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/nexus/iface.py +0 -0
  137. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/patching.py +0 -0
  138. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/ribbon/__init__.py +0 -0
  139. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/routeros/__init__.py +0 -0
  140. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/routeros/file.py +0 -0
  141. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/arista.deploy +0 -0
  142. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/arista.order +0 -0
  143. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/arista.rul +0 -0
  144. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/aruba.deploy +0 -0
  145. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/aruba.order +0 -0
  146. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/aruba.rul +0 -0
  147. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/b4com.deploy +0 -0
  148. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/b4com.order +0 -0
  149. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/b4com.rul +0 -0
  150. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/cisco.deploy +0 -0
  151. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/cisco.order +0 -0
  152. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/cisco.rul +0 -0
  153. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/huawei.deploy +0 -0
  154. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/huawei.order +0 -0
  155. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/huawei.rul +0 -0
  156. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/juniper.rul +0 -0
  157. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/nexus.deploy +0 -0
  158. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/nexus.order +0 -0
  159. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/nexus.rul +0 -0
  160. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/nokia.rul +0 -0
  161. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/optixtrans.deploy +0 -0
  162. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/optixtrans.order +0 -0
  163. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/optixtrans.rul +0 -0
  164. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/pc.deploy +0 -0
  165. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/pc.order +0 -0
  166. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/pc.rul +0 -0
  167. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/ribbon.deploy +0 -0
  168. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/ribbon.rul +0 -0
  169. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/routeros.order +0 -0
  170. {annet-0.16.36 → annet-0.16.37}/annet/rulebook/texts/routeros.rul +0 -0
  171. {annet-0.16.36 → annet-0.16.37}/annet/storage.py +0 -0
  172. {annet-0.16.36 → annet-0.16.37}/annet/tabparser.py +0 -0
  173. {annet-0.16.36 → annet-0.16.37}/annet/text_term_format.py +0 -0
  174. {annet-0.16.36 → annet-0.16.37}/annet/tracing.py +0 -0
  175. {annet-0.16.36 → annet-0.16.37}/annet/types.py +0 -0
  176. {annet-0.16.36 → annet-0.16.37}/annet.egg-info/SOURCES.txt +0 -0
  177. {annet-0.16.36 → annet-0.16.37}/annet.egg-info/dependency_links.txt +0 -0
  178. {annet-0.16.36 → annet-0.16.37}/annet.egg-info/entry_points.txt +0 -0
  179. {annet-0.16.36 → annet-0.16.37}/annet.egg-info/top_level.txt +0 -0
  180. {annet-0.16.36 → annet-0.16.37}/annet_generators/__init__.py +0 -0
  181. {annet-0.16.36 → annet-0.16.37}/annet_generators/example/__init__.py +0 -0
  182. {annet-0.16.36 → annet-0.16.37}/annet_generators/example/lldp.py +0 -0
  183. {annet-0.16.36 → annet-0.16.37}/annet_generators/mesh_example/__init__.py +0 -0
  184. {annet-0.16.36 → annet-0.16.37}/annet_generators/mesh_example/bgp.py +0 -0
  185. {annet-0.16.36 → annet-0.16.37}/annet_generators/mesh_example/mesh_logic.py +0 -0
  186. {annet-0.16.36 → annet-0.16.37}/annet_generators/rpl_example/__init__.py +0 -0
  187. {annet-0.16.36 → annet-0.16.37}/annet_generators/rpl_example/generator.py +0 -0
  188. {annet-0.16.36 → annet-0.16.37}/annet_generators/rpl_example/items.py +0 -0
  189. {annet-0.16.36 → annet-0.16.37}/annet_generators/rpl_example/mesh.py +0 -0
  190. {annet-0.16.36 → annet-0.16.37}/annet_generators/rpl_example/route_policy.py +0 -0
  191. {annet-0.16.36 → annet-0.16.37}/requirements.txt +0 -0
  192. {annet-0.16.36 → annet-0.16.37}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: annet
3
- Version: 0.16.36
3
+ Version: 0.16.37
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -23,7 +23,7 @@ Requires-Dist: yarl>=1.8.2
23
23
  Requires-Dist: adaptix==3.0.0b7
24
24
  Requires-Dist: dataclass-rest==0.4
25
25
  Provides-Extra: netbox
26
- Requires-Dist: annetbox[sync]>=0.1.12; extra == "netbox"
26
+ Requires-Dist: annetbox[sync]>=0.2.0; extra == "netbox"
27
27
  Dynamic: home-page
28
28
  Dynamic: license
29
29
  Dynamic: provides-extra
@@ -192,20 +192,25 @@ class NetboxDevice(Entity):
192
192
  breed: str
193
193
 
194
194
  interfaces: List[Interface]
195
- neighbours: Optional[List["NetboxDevice"]]
195
+
196
+ @property
197
+ def neighbors(self) -> List["Entity"]:
198
+ return [
199
+ endpoint.device
200
+ for iface in self.interfaces
201
+ if iface.connected_endpoints
202
+ for endpoint in iface.connected_endpoints
203
+ if endpoint.device
204
+ ]
196
205
 
197
206
  # compat
198
207
  @property
199
208
  def neighbours_fqdns(self) -> list[str]:
200
- if not self.neighbours:
201
- return []
202
- return [dev.fqdn for dev in self.neighbours]
209
+ return [dev.name for dev in self.neighbors]
203
210
 
204
211
  @property
205
212
  def neighbours_ids(self):
206
- if not self.neighbours:
207
- return []
208
- return [dev.id for dev in self.neighbours]
213
+ return [dev.id for dev in self.neighbors]
209
214
 
210
215
  def __hash__(self):
211
216
  return hash((self.id, type(self)))
@@ -5,16 +5,25 @@ DEFAULT_URL = "http://localhost"
5
5
 
6
6
 
7
7
  class NetboxStorageOpts:
8
- def __init__(self, url: str, token: str, insecure: bool = False, exact_host_filter: bool = False):
8
+ def __init__(
9
+ self,
10
+ url: str,
11
+ token: str,
12
+ insecure: bool = False,
13
+ exact_host_filter: bool = False,
14
+ threads: int = 1,
15
+ ):
9
16
  self.url = url
10
17
  self.token = token
11
18
  self.insecure = insecure
12
19
  self.exact_host_filter = exact_host_filter
20
+ self.threads = threads
13
21
 
14
22
  @classmethod
15
23
  def parse_params(cls, conf_params: Optional[dict[str, str]], cli_opts: Any):
16
24
  url = os.getenv("NETBOX_URL") or conf_params.get("url") or DEFAULT_URL
17
25
  token = os.getenv("NETBOX_TOKEN", "").strip() or conf_params.get("token") or ""
26
+ threads = os.getenv("NETBOX_CLIENT_THREADS", "").strip() or conf_params.get("threads") or "1"
18
27
  insecure = False
19
28
  if insecure_env := os.getenv("NETBOX_INSECURE", "").lower():
20
29
  insecure = insecure_env in ("true", "1", "t")
@@ -24,4 +33,10 @@ class NetboxStorageOpts:
24
33
  exact_host_filter = exact_host_filter_env in ("true", "1", "t")
25
34
  else:
26
35
  exact_host_filter = bool(conf_params.get("exact_host_filter") or False)
27
- return cls(url=url, token=token, insecure=insecure, exact_host_filter=exact_host_filter)
36
+ return cls(
37
+ url=url,
38
+ token=token,
39
+ insecure=insecure,
40
+ exact_host_filter=exact_host_filter,
41
+ threads=int(threads),
42
+ )
@@ -24,7 +24,6 @@ logger = getLogger(__name__)
24
24
  @impl_converter(recipe=[
25
25
  link(P[api_models.Device].name, P[models.NetboxDevice].hostname),
26
26
  link(P[api_models.Device].name, P[models.NetboxDevice].fqdn),
27
- link_constant(P[models.NetboxDevice].neighbours, value=None),
28
27
  ])
29
28
  def extend_device_base(
30
29
  device: api_models.Device,
@@ -39,7 +38,6 @@ def extend_device_base(
39
38
  def extend_device(
40
39
  device: api_models.Device,
41
40
  interfaces: List[models.Interface],
42
- neighbours: Optional[List[models.NetboxDevice]],
43
41
  storage: Storage,
44
42
  ) -> models.NetboxDevice:
45
43
  platform_name: str = ""
@@ -64,7 +62,6 @@ def extend_device(
64
62
  hw=hw,
65
63
  storage=storage,
66
64
  )
67
- res.neighbours = neighbours
68
65
  return res
69
66
 
70
67
 
@@ -91,6 +88,7 @@ class NetboxStorageV37(Storage):
91
88
  url = ""
92
89
  token = ""
93
90
  self.exact_host_filter = False
91
+ threads = 1
94
92
  if opts:
95
93
  if opts.insecure:
96
94
  ctx = ssl.create_default_context()
@@ -98,8 +96,10 @@ class NetboxStorageV37(Storage):
98
96
  ctx.verify_mode = ssl.CERT_NONE
99
97
  url = opts.url
100
98
  token = opts.token
99
+ threads = opts.threads
101
100
  self.exact_host_filter = opts.exact_host_filter
102
- self.netbox = NetboxV37(url=url, token=token, ssl_context=ctx)
101
+
102
+ self.netbox = NetboxV37(url=url, token=token, ssl_context=ctx, threads=threads)
103
103
  self._all_fqdns: Optional[list[str]] = None
104
104
  self._id_devices: dict[int, models.NetboxDevice] = {}
105
105
  self._name_devices: dict[str, models.NetboxDevice] = {}
@@ -174,7 +174,6 @@ class NetboxStorageV37(Storage):
174
174
  device.id: extend_device(
175
175
  device=device,
176
176
  interfaces=[],
177
- neighbours=[],
178
177
  storage=self,
179
178
  )
180
179
  for device in self._load_devices(query)
@@ -186,16 +185,8 @@ class NetboxStorageV37(Storage):
186
185
  self._record_device(device)
187
186
 
188
187
  interfaces = self._load_interfaces(list(device_ids))
189
- neighbours = {x.id: x for x in self._load_neighbours(interfaces)}
190
- neighbours_seen: dict[str, set] = defaultdict(set)
191
-
192
188
  for interface in interfaces:
193
189
  device_ids[interface.device.id].interfaces.append(interface)
194
- for e in interface.connected_endpoints or []:
195
- neighbour = neighbours[e.device.id]
196
- if neighbour.id not in neighbours_seen[interface.device.id]:
197
- neighbours_seen[interface.device.id].add(neighbour.id)
198
- device_ids[interface.device.id].neighbours.append(neighbour)
199
190
 
200
191
  return list(device_ids.values())
201
192
 
@@ -233,8 +224,7 @@ class NetboxStorageV37(Storage):
233
224
  extended_ifaces[ip.assigned_object_id].ip_addresses.append(ip)
234
225
  return list(extended_ifaces.values())
235
226
 
236
- def _load_interfaces(self, device_ids: List[int]) -> List[
237
- models.Interface]:
227
+ def _load_interfaces(self, device_ids: List[int]) -> List[models.Interface]:
238
228
  interfaces = self.netbox.dcim_all_interfaces(device_id=device_ids)
239
229
  return self._extend_interfaces(interfaces.results)
240
230
 
@@ -242,25 +232,6 @@ class NetboxStorageV37(Storage):
242
232
  interfaces = self.netbox.dcim_all_interfaces_by_id(id=ids)
243
233
  return self._extend_interfaces(interfaces.results)
244
234
 
245
- def _load_neighbours(self, interfaces: List[models.Interface]) -> List[models.NetboxDevice]:
246
- endpoints = [e for i in interfaces for e in i.connected_endpoints or []]
247
- remote_interfaces_ids = [e.id for e in endpoints]
248
- neighbours_ids = [e.device.id for e in endpoints]
249
- neighbours_ifaces_dics = defaultdict(list)
250
- # load only the connected interface to speed things up
251
- for iface in self._load_interfaces_by_id(remote_interfaces_ids):
252
- neighbours_ifaces_dics[iface.device.id].append(iface)
253
- neighbours = []
254
- for neighbour in self.netbox.dcim_all_devices_by_id(id=neighbours_ids).results:
255
- extended_neighbour = extend_device(
256
- device=neighbour,
257
- storage=self,
258
- interfaces=neighbours_ifaces_dics[neighbour.id],
259
- neighbours=None, # do not load recursively
260
- )
261
- neighbours.append(extended_neighbour)
262
- return neighbours
263
-
264
235
  def get_device(
265
236
  self, obj_id, preload_neighbors=False, use_mesh=None,
266
237
  **kwargs,
@@ -270,13 +241,11 @@ class NetboxStorageV37(Storage):
270
241
 
271
242
  device = self.netbox.dcim_device(obj_id)
272
243
  interfaces = self._load_interfaces([device.id])
273
- neighbours = self._load_neighbours(interfaces)
274
244
 
275
245
  res = extend_device(
276
246
  device=device,
277
247
  storage=self,
278
248
  interfaces=interfaces,
279
- neighbours=neighbours,
280
249
  )
281
250
  self._record_device(res)
282
251
  return res
@@ -182,6 +182,7 @@ class PeerGroup:
182
182
  internal_name: str = ""
183
183
  description: str = ""
184
184
  update_source: str = ""
185
+ peer_filter: str = ""
185
186
  import_policy: str = ""
186
187
  export_policy: str = ""
187
188
 
@@ -132,30 +132,30 @@ class MeshExecutor:
132
132
  # we can have multiple rules for the same pair
133
133
  # we merge them according to remote fqdn
134
134
  neighbor_peers: dict[PeerKey, Pair] = {}
135
- # TODO batch resolve
136
135
  rules = self._registry.lookup_direct(device.fqdn, device.neighbours_fqdns)
137
136
  fqdns = {
138
137
  rule.name_right if rule.direct_order else rule.name_left
139
138
  for rule in rules
140
139
  }
141
- neigbors = {
140
+ logger.debug("Loading neighbor devices: %s", fqdns)
141
+ neighbors = {
142
142
  d.fqdn: d for d in self._storage.make_devices(list(fqdns))
143
143
  }
144
144
  for rule in rules:
145
145
  handler_name = self._handler_name(rule.handler)
146
146
  if rule.direct_order:
147
- if rule.name_right not in neigbors:
148
- print(list(neigbors), flush=True)
147
+ if rule.name_right not in neighbors:
149
148
  raise ValueError(
150
- f"Device `{device.fqdn}` has no neighbor `{rule.name_right}` required for `{handler_name}`. {list(neigbors)}",
149
+ f"Device `{device.fqdn}` has no neighbor `{rule.name_right}` "
150
+ f"required for `{handler_name}`. {list(neighbors)}",
151
151
  )
152
- neighbor_device = neigbors[rule.name_right]
152
+ neighbor_device = neighbors[rule.name_right]
153
153
  else:
154
- if rule.name_left not in neigbors:
154
+ if rule.name_left not in neighbors:
155
155
  raise ValueError(
156
156
  f"Device `{device.fqdn}` has no neighbor `{rule.name_left}` required for `{handler_name}`",
157
157
  )
158
- neighbor_device = neigbors[rule.name_left]
158
+ neighbor_device = neighbors[rule.name_left]
159
159
  all_connected_ports = [
160
160
  (p1.name, p2.name)
161
161
  for p1, p2 in self._storage.search_connections(device, neighbor_device)
@@ -238,6 +238,7 @@ class MeshExecutor:
238
238
  rule.name_right if rule.direct_order else rule.name_left
239
239
  for rule in rules
240
240
  }
241
+ logger.debug("Loading indirect connected devices: %s", fqdns)
241
242
  connected_devices = {
242
243
  d.fqdn: d for d in self._storage.make_devices(list(fqdns))
243
244
  }
@@ -126,6 +126,7 @@ class MeshPeerGroup(_OptionsDTO):
126
126
  internal_name: str
127
127
  update_source: str
128
128
  description: str
129
+ peer_filter: str
129
130
 
130
131
  import_policy: str
131
132
  export_policy: str
@@ -110,7 +110,9 @@ class PrefixListFilterGenerator(PartialGenerator, ABC):
110
110
  def acl_arista(self, _):
111
111
  return r"""
112
112
  ip prefix-list
113
+ seq
113
114
  ipv6 prefix-list
115
+ seq
114
116
  """
115
117
 
116
118
  def _arista_prefix_list(
@@ -120,20 +122,18 @@ class PrefixListFilterGenerator(PartialGenerator, ABC):
120
122
  match: PrefixMatchValue,
121
123
  plist: IpPrefixList,
122
124
  ) -> Iterable[Sequence[str]]:
123
- for i, prefix in enumerate(plist.members):
124
- addr_mask = ip_interface(prefix)
125
- yield (
126
- prefix_type,
127
- "prefix-list",
128
- name,
129
- f"seq {i * 5 + 5}",
130
- "permit",
131
- addr_mask.with_prefixlen,
132
- ) + (
133
- ("ge", str(match.greater_equal)) if match.greater_equal is not None else ()
134
- ) + (
135
- ("le", str(match.less_equal)) if match.less_equal is not None else ()
136
- )
125
+ with self.block(prefix_type, "prefix-list", name):
126
+ for i, prefix in enumerate(plist.members):
127
+ addr_mask = ip_interface(prefix)
128
+ yield (
129
+ f"seq {i * 10 + 10}",
130
+ "permit",
131
+ addr_mask.with_prefixlen,
132
+ ) + (
133
+ ("ge", str(match.greater_equal)) if match.greater_equal is not None else ()
134
+ ) + (
135
+ ("le", str(match.less_equal)) if match.less_equal is not None else ()
136
+ )
137
137
 
138
138
  def run_arista(self, device: Any):
139
139
  policies = self.get_policies(device)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: annet
3
- Version: 0.16.36
3
+ Version: 0.16.37
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -23,7 +23,7 @@ Requires-Dist: yarl>=1.8.2
23
23
  Requires-Dist: adaptix==3.0.0b7
24
24
  Requires-Dist: dataclass-rest==0.4
25
25
  Provides-Extra: netbox
26
- Requires-Dist: annetbox[sync]>=0.1.12; extra == "netbox"
26
+ Requires-Dist: annetbox[sync]>=0.2.0; extra == "netbox"
27
27
  Dynamic: home-page
28
28
  Dynamic: license
29
29
  Dynamic: provides-extra
@@ -15,4 +15,4 @@ adaptix==3.0.0b7
15
15
  dataclass-rest==0.4
16
16
 
17
17
  [netbox]
18
- annetbox[sync]>=0.1.12
18
+ annetbox[sync]>=0.2.0
@@ -44,7 +44,7 @@ if __name__ == "__main__":
44
44
  ],
45
45
  },
46
46
  extras_require={
47
- "netbox": ["annetbox[sync]>=0.1.12"],
47
+ "netbox": ["annetbox[sync]>=0.2.0"],
48
48
  },
49
49
  python_requires=">=3.10",
50
50
  install_requires=requirements(),
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes