annet 1.0.2__tar.gz → 1.0.3__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 (193) hide show
  1. {annet-1.0.2/annet.egg-info → annet-1.0.3}/PKG-INFO +2 -2
  2. {annet-1.0.2 → annet-1.0.3}/annet/__init__.py +0 -5
  3. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/common/models.py +12 -7
  4. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/common/storage_opts.py +17 -2
  5. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/v37/storage.py +5 -36
  6. {annet-1.0.2 → annet-1.0.3}/annet/bgp_models.py +1 -0
  7. {annet-1.0.2 → annet-1.0.3}/annet/connectors.py +12 -15
  8. {annet-1.0.2 → annet-1.0.3}/annet/mesh/executor.py +9 -8
  9. {annet-1.0.2 → annet-1.0.3}/annet/mesh/peer_models.py +1 -0
  10. {annet-1.0.2 → annet-1.0.3/annet.egg-info}/PKG-INFO +2 -2
  11. {annet-1.0.2 → annet-1.0.3}/annet.egg-info/requires.txt +1 -1
  12. {annet-1.0.2 → annet-1.0.3}/setup.py +1 -1
  13. {annet-1.0.2 → annet-1.0.3}/AUTHORS +0 -0
  14. {annet-1.0.2 → annet-1.0.3}/LICENSE +0 -0
  15. {annet-1.0.2 → annet-1.0.3}/MANIFEST.in +0 -0
  16. {annet-1.0.2 → annet-1.0.3}/README.md +0 -0
  17. {annet-1.0.2 → annet-1.0.3}/annet/adapters/__init__.py +0 -0
  18. {annet-1.0.2 → annet-1.0.3}/annet/adapters/fetchers/__init__.py +0 -0
  19. {annet-1.0.2 → annet-1.0.3}/annet/adapters/fetchers/stub/__init__.py +0 -0
  20. {annet-1.0.2 → annet-1.0.3}/annet/adapters/fetchers/stub/fetcher.py +0 -0
  21. {annet-1.0.2 → annet-1.0.3}/annet/adapters/file/__init__.py +0 -0
  22. {annet-1.0.2 → annet-1.0.3}/annet/adapters/file/provider.py +0 -0
  23. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/__init__.py +0 -0
  24. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/common/__init__.py +0 -0
  25. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/common/client.py +0 -0
  26. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/common/manufacturer.py +0 -0
  27. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/common/query.py +0 -0
  28. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/common/status_client.py +0 -0
  29. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/provider.py +0 -0
  30. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/v24/__init__.py +0 -0
  31. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/v24/storage.py +0 -0
  32. {annet-1.0.2 → annet-1.0.3}/annet/adapters/netbox/v37/__init__.py +0 -0
  33. {annet-1.0.2 → annet-1.0.3}/annet/annet.py +0 -0
  34. {annet-1.0.2 → annet-1.0.3}/annet/annlib/__init__.py +0 -0
  35. {annet-1.0.2 → annet-1.0.3}/annet/annlib/command.py +0 -0
  36. {annet-1.0.2 → annet-1.0.3}/annet/annlib/diff.py +0 -0
  37. {annet-1.0.2 → annet-1.0.3}/annet/annlib/errors.py +0 -0
  38. {annet-1.0.2 → annet-1.0.3}/annet/annlib/filter_acl.py +0 -0
  39. {annet-1.0.2 → annet-1.0.3}/annet/annlib/jsontools.py +0 -0
  40. {annet-1.0.2 → annet-1.0.3}/annet/annlib/lib.py +0 -0
  41. {annet-1.0.2 → annet-1.0.3}/annet/annlib/netdev/__init__.py +0 -0
  42. {annet-1.0.2 → annet-1.0.3}/annet/annlib/netdev/db.py +0 -0
  43. {annet-1.0.2 → annet-1.0.3}/annet/annlib/netdev/devdb/__init__.py +0 -0
  44. {annet-1.0.2 → annet-1.0.3}/annet/annlib/netdev/devdb/data/devdb.json +0 -0
  45. {annet-1.0.2 → annet-1.0.3}/annet/annlib/netdev/views/__init__.py +0 -0
  46. {annet-1.0.2 → annet-1.0.3}/annet/annlib/netdev/views/dump.py +0 -0
  47. {annet-1.0.2 → annet-1.0.3}/annet/annlib/netdev/views/hardware.py +0 -0
  48. {annet-1.0.2 → annet-1.0.3}/annet/annlib/output.py +0 -0
  49. {annet-1.0.2 → annet-1.0.3}/annet/annlib/patching.py +0 -0
  50. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rbparser/__init__.py +0 -0
  51. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rbparser/acl.py +0 -0
  52. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rbparser/deploying.py +0 -0
  53. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rbparser/ordering.py +0 -0
  54. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rbparser/platform.py +0 -0
  55. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rbparser/syntax.py +0 -0
  56. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rulebook/__init__.py +0 -0
  57. {annet-1.0.2 → annet-1.0.3}/annet/annlib/rulebook/common.py +0 -0
  58. {annet-1.0.2 → annet-1.0.3}/annet/annlib/tabparser.py +0 -0
  59. {annet-1.0.2 → annet-1.0.3}/annet/annlib/types.py +0 -0
  60. {annet-1.0.2 → annet-1.0.3}/annet/api/__init__.py +0 -0
  61. {annet-1.0.2 → annet-1.0.3}/annet/argparse.py +0 -0
  62. {annet-1.0.2 → annet-1.0.3}/annet/cli.py +0 -0
  63. {annet-1.0.2 → annet-1.0.3}/annet/cli_args.py +0 -0
  64. {annet-1.0.2 → annet-1.0.3}/annet/configs/context.yml +0 -0
  65. {annet-1.0.2 → annet-1.0.3}/annet/configs/logging.yaml +0 -0
  66. {annet-1.0.2 → annet-1.0.3}/annet/deploy.py +0 -0
  67. {annet-1.0.2 → annet-1.0.3}/annet/deploy_ui.py +0 -0
  68. {annet-1.0.2 → annet-1.0.3}/annet/diff.py +0 -0
  69. {annet-1.0.2 → annet-1.0.3}/annet/executor.py +0 -0
  70. {annet-1.0.2 → annet-1.0.3}/annet/filtering.py +0 -0
  71. {annet-1.0.2 → annet-1.0.3}/annet/gen.py +0 -0
  72. {annet-1.0.2 → annet-1.0.3}/annet/generators/__init__.py +0 -0
  73. {annet-1.0.2 → annet-1.0.3}/annet/generators/base.py +0 -0
  74. {annet-1.0.2 → annet-1.0.3}/annet/generators/common/__init__.py +0 -0
  75. {annet-1.0.2 → annet-1.0.3}/annet/generators/common/initial.py +0 -0
  76. {annet-1.0.2 → annet-1.0.3}/annet/generators/entire.py +0 -0
  77. {annet-1.0.2 → annet-1.0.3}/annet/generators/exceptions.py +0 -0
  78. {annet-1.0.2 → annet-1.0.3}/annet/generators/jsonfragment.py +0 -0
  79. {annet-1.0.2 → annet-1.0.3}/annet/generators/partial.py +0 -0
  80. {annet-1.0.2 → annet-1.0.3}/annet/generators/perf.py +0 -0
  81. {annet-1.0.2 → annet-1.0.3}/annet/generators/ref.py +0 -0
  82. {annet-1.0.2 → annet-1.0.3}/annet/generators/result.py +0 -0
  83. {annet-1.0.2 → annet-1.0.3}/annet/hardware.py +0 -0
  84. {annet-1.0.2 → annet-1.0.3}/annet/implicit.py +0 -0
  85. {annet-1.0.2 → annet-1.0.3}/annet/lib.py +0 -0
  86. {annet-1.0.2 → annet-1.0.3}/annet/mesh/__init__.py +0 -0
  87. {annet-1.0.2 → annet-1.0.3}/annet/mesh/basemodel.py +0 -0
  88. {annet-1.0.2 → annet-1.0.3}/annet/mesh/device_models.py +0 -0
  89. {annet-1.0.2 → annet-1.0.3}/annet/mesh/match_args.py +0 -0
  90. {annet-1.0.2 → annet-1.0.3}/annet/mesh/models_converter.py +0 -0
  91. {annet-1.0.2 → annet-1.0.3}/annet/mesh/port_processor.py +0 -0
  92. {annet-1.0.2 → annet-1.0.3}/annet/mesh/registry.py +0 -0
  93. {annet-1.0.2 → annet-1.0.3}/annet/output.py +0 -0
  94. {annet-1.0.2 → annet-1.0.3}/annet/parallel.py +0 -0
  95. {annet-1.0.2 → annet-1.0.3}/annet/patching.py +0 -0
  96. {annet-1.0.2 → annet-1.0.3}/annet/reference.py +0 -0
  97. {annet-1.0.2 → annet-1.0.3}/annet/rpl/__init__.py +0 -0
  98. {annet-1.0.2 → annet-1.0.3}/annet/rpl/action.py +0 -0
  99. {annet-1.0.2 → annet-1.0.3}/annet/rpl/condition.py +0 -0
  100. {annet-1.0.2 → annet-1.0.3}/annet/rpl/match_builder.py +0 -0
  101. {annet-1.0.2 → annet-1.0.3}/annet/rpl/policy.py +0 -0
  102. {annet-1.0.2 → annet-1.0.3}/annet/rpl/result.py +0 -0
  103. {annet-1.0.2 → annet-1.0.3}/annet/rpl/routemap.py +0 -0
  104. {annet-1.0.2 → annet-1.0.3}/annet/rpl/statement_builder.py +0 -0
  105. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/__init__.py +0 -0
  106. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/aspath.py +0 -0
  107. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/community.py +0 -0
  108. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/cumulus_frr.py +0 -0
  109. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/entities.py +0 -0
  110. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/execute.py +0 -0
  111. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/policy.py +0 -0
  112. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/prefix_lists.py +0 -0
  113. {annet-1.0.2 → annet-1.0.3}/annet/rpl_generators/rd.py +0 -0
  114. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/__init__.py +0 -0
  115. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/arista/__init__.py +0 -0
  116. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/arista/iface.py +0 -0
  117. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/aruba/__init__.py +0 -0
  118. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/aruba/ap_env.py +0 -0
  119. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/aruba/misc.py +0 -0
  120. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/b4com/__init__.py +0 -0
  121. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/b4com/file.py +0 -0
  122. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/b4com/iface.py +0 -0
  123. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/cisco/__init__.py +0 -0
  124. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/cisco/iface.py +0 -0
  125. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/cisco/misc.py +0 -0
  126. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/cisco/vlandb.py +0 -0
  127. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/common.py +0 -0
  128. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/deploying.py +0 -0
  129. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/huawei/__init__.py +0 -0
  130. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/huawei/aaa.py +0 -0
  131. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/huawei/bgp.py +0 -0
  132. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/huawei/iface.py +0 -0
  133. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/huawei/misc.py +0 -0
  134. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/huawei/vlandb.py +0 -0
  135. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/juniper/__init__.py +0 -0
  136. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/nexus/__init__.py +0 -0
  137. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/nexus/iface.py +0 -0
  138. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/patching.py +0 -0
  139. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/ribbon/__init__.py +0 -0
  140. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/routeros/__init__.py +0 -0
  141. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/routeros/file.py +0 -0
  142. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/arista.deploy +0 -0
  143. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/arista.order +0 -0
  144. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/arista.rul +0 -0
  145. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/aruba.deploy +0 -0
  146. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/aruba.order +0 -0
  147. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/aruba.rul +0 -0
  148. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/b4com.deploy +0 -0
  149. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/b4com.order +0 -0
  150. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/b4com.rul +0 -0
  151. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/cisco.deploy +0 -0
  152. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/cisco.order +0 -0
  153. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/cisco.rul +0 -0
  154. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/huawei.deploy +0 -0
  155. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/huawei.order +0 -0
  156. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/huawei.rul +0 -0
  157. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/juniper.rul +0 -0
  158. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/nexus.deploy +0 -0
  159. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/nexus.order +0 -0
  160. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/nexus.rul +0 -0
  161. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/nokia.rul +0 -0
  162. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/optixtrans.deploy +0 -0
  163. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/optixtrans.order +0 -0
  164. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/optixtrans.rul +0 -0
  165. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/pc.deploy +0 -0
  166. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/pc.order +0 -0
  167. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/pc.rul +0 -0
  168. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/ribbon.deploy +0 -0
  169. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/ribbon.rul +0 -0
  170. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/routeros.order +0 -0
  171. {annet-1.0.2 → annet-1.0.3}/annet/rulebook/texts/routeros.rul +0 -0
  172. {annet-1.0.2 → annet-1.0.3}/annet/storage.py +0 -0
  173. {annet-1.0.2 → annet-1.0.3}/annet/tabparser.py +0 -0
  174. {annet-1.0.2 → annet-1.0.3}/annet/text_term_format.py +0 -0
  175. {annet-1.0.2 → annet-1.0.3}/annet/tracing.py +0 -0
  176. {annet-1.0.2 → annet-1.0.3}/annet/types.py +0 -0
  177. {annet-1.0.2 → annet-1.0.3}/annet.egg-info/SOURCES.txt +0 -0
  178. {annet-1.0.2 → annet-1.0.3}/annet.egg-info/dependency_links.txt +0 -0
  179. {annet-1.0.2 → annet-1.0.3}/annet.egg-info/entry_points.txt +0 -0
  180. {annet-1.0.2 → annet-1.0.3}/annet.egg-info/top_level.txt +0 -0
  181. {annet-1.0.2 → annet-1.0.3}/annet_generators/__init__.py +0 -0
  182. {annet-1.0.2 → annet-1.0.3}/annet_generators/example/__init__.py +0 -0
  183. {annet-1.0.2 → annet-1.0.3}/annet_generators/example/lldp.py +0 -0
  184. {annet-1.0.2 → annet-1.0.3}/annet_generators/mesh_example/__init__.py +0 -0
  185. {annet-1.0.2 → annet-1.0.3}/annet_generators/mesh_example/bgp.py +0 -0
  186. {annet-1.0.2 → annet-1.0.3}/annet_generators/mesh_example/mesh_logic.py +0 -0
  187. {annet-1.0.2 → annet-1.0.3}/annet_generators/rpl_example/__init__.py +0 -0
  188. {annet-1.0.2 → annet-1.0.3}/annet_generators/rpl_example/generator.py +0 -0
  189. {annet-1.0.2 → annet-1.0.3}/annet_generators/rpl_example/items.py +0 -0
  190. {annet-1.0.2 → annet-1.0.3}/annet_generators/rpl_example/mesh.py +0 -0
  191. {annet-1.0.2 → annet-1.0.3}/annet_generators/rpl_example/route_policy.py +0 -0
  192. {annet-1.0.2 → annet-1.0.3}/requirements.txt +0 -0
  193. {annet-1.0.2 → annet-1.0.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: annet
3
- Version: 1.0.2
3
+ Version: 1.0.3
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.13; 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
@@ -49,11 +49,6 @@ def init(options: Namespace):
49
49
  colorama.init = lambda *_, **__: None
50
50
  colorama.init()
51
51
 
52
- # Workaround for Python 3.8.0: https://bugs.python.org/issue38529
53
- import asyncio.streams
54
- if hasattr(asyncio.streams.StreamReaderProtocol, "_on_reader_gc"):
55
- asyncio.streams.StreamReaderProtocol._on_reader_gc = lambda *args, **kwargs: None # pylint: disable=protected-access
56
-
57
52
 
58
53
  def assert_python_version():
59
54
  if sys.version_info < (3, 10, 0):
@@ -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
 
@@ -111,33 +111,30 @@ class AdapterWithName(ABC):
111
111
 
112
112
 
113
113
  def get_connector_from_config(config_key: str, connectors: List[Type[Connector]]) -> Tuple[Connector, Dict[str, Any]]:
114
- seen: list[str] = []
115
114
  if not connectors:
116
115
  raise Exception("empty connectors")
117
- connector = connectors[0] # default
118
- connector_params: Dict[str, Any] = {}
116
+
117
+ # handle configuration
118
+ connector_params = dict[str, Any]() # default
119
119
  if context_storage := get_context().get(config_key):
120
- adapter_name = context_storage.get("adapter", None)
121
120
  connector_params = context_storage.get("params", {})
122
- if adapter_name:
121
+ if adapter_name := context_storage.get("adapter", None):
122
+ seen = list[str]()
123
123
  for con in connectors:
124
- con_name = connector.__name__
125
124
  if issubclass(con, AdapterWithName):
126
125
  con_name = con.name()
126
+ else:
127
+ con_name = con.__name__
127
128
  seen.append(con_name)
128
129
  if adapter_name == con_name:
129
- connector = con
130
+ connectors = [con]
130
131
  break
131
132
  else:
132
133
  raise Exception("unknown %s %s: seen %s" % (config_key, adapter_name, seen))
133
- else:
134
- connector = connectors[0]
135
- if len(connectors) > 1:
136
- warnings.warn(f"Please specify adapter for '{config_key}'. Found more than one classes {connectors}", UserWarning)
137
- else:
138
- connector = connectors[0]
139
- if len(connectors) > 1:
140
- warnings.warn(f"Please specify '{config_key}'. Found more than one classes {connectors}", UserWarning)
134
+
135
+ if len(connectors) > 1:
136
+ warnings.warn(f"Please specify adapter for '{config_key}'. Found more than one classes {connectors}", UserWarning)
137
+ connector = connectors[0]
141
138
  if issubclass(connector, AdapterWithConfig):
142
139
  connector_ins = connector.with_config(**connector_params)
143
140
  else:
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: annet
3
- Version: 1.0.2
3
+ Version: 1.0.3
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.13; 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.13
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.13"],
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
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