annet 3.12.1__tar.gz → 3.14.0__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 (227) hide show
  1. {annet-3.12.1/annet.egg-info → annet-3.14.0}/PKG-INFO +1 -1
  2. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/models.py +2 -0
  3. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/provider.py +2 -1
  4. {annet-3.12.1 → annet-3.14.0}/annet/annlib/netdev/devdb/data/devdb.json +2 -2
  5. {annet-3.12.1 → annet-3.14.0}/annet/bgp_models.py +12 -3
  6. {annet-3.12.1 → annet-3.14.0}/annet/mesh/device_models.py +2 -0
  7. {annet-3.12.1 → annet-3.14.0}/annet/rpl/match_builder.py +10 -2
  8. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/aspath.py +22 -0
  9. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/community.py +73 -1
  10. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/entities.py +50 -3
  11. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/policy.py +367 -2
  12. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/prefix_lists.py +67 -1
  13. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/rd.py +15 -0
  14. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/huawei.rul +5 -0
  15. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/juniper.rul +6 -2
  16. {annet-3.12.1 → annet-3.14.0}/annet/vendors/tabparser.py +13 -31
  17. {annet-3.12.1 → annet-3.14.0/annet.egg-info}/PKG-INFO +1 -1
  18. {annet-3.12.1 → annet-3.14.0}/AUTHORS +0 -0
  19. {annet-3.12.1 → annet-3.14.0}/LICENSE +0 -0
  20. {annet-3.12.1 → annet-3.14.0}/MANIFEST.in +0 -0
  21. {annet-3.12.1 → annet-3.14.0}/README.md +0 -0
  22. {annet-3.12.1 → annet-3.14.0}/annet/__init__.py +0 -0
  23. {annet-3.12.1 → annet-3.14.0}/annet/adapters/__init__.py +0 -0
  24. {annet-3.12.1 → annet-3.14.0}/annet/adapters/fetchers/__init__.py +0 -0
  25. {annet-3.12.1 → annet-3.14.0}/annet/adapters/fetchers/stub/__init__.py +0 -0
  26. {annet-3.12.1 → annet-3.14.0}/annet/adapters/fetchers/stub/fetcher.py +0 -0
  27. {annet-3.12.1 → annet-3.14.0}/annet/adapters/file/__init__.py +0 -0
  28. {annet-3.12.1 → annet-3.14.0}/annet/adapters/file/provider.py +0 -0
  29. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/__init__.py +0 -0
  30. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/__init__.py +0 -0
  31. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/adapter.py +0 -0
  32. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/client.py +0 -0
  33. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/manufacturer.py +0 -0
  34. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/query.py +0 -0
  35. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/status_client.py +0 -0
  36. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/storage_base.py +0 -0
  37. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/common/storage_opts.py +0 -0
  38. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v24/__init__.py +0 -0
  39. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v24/models.py +0 -0
  40. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v24/storage.py +0 -0
  41. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v37/__init__.py +0 -0
  42. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v37/models.py +0 -0
  43. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v37/storage.py +0 -0
  44. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v41/__init__.py +0 -0
  45. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v41/models.py +0 -0
  46. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v41/storage.py +0 -0
  47. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v42/__init__.py +0 -0
  48. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v42/models.py +0 -0
  49. {annet-3.12.1 → annet-3.14.0}/annet/adapters/netbox/v42/storage.py +0 -0
  50. {annet-3.12.1 → annet-3.14.0}/annet/annet.py +0 -0
  51. {annet-3.12.1 → annet-3.14.0}/annet/annlib/__init__.py +0 -0
  52. {annet-3.12.1 → annet-3.14.0}/annet/annlib/command.py +0 -0
  53. {annet-3.12.1 → annet-3.14.0}/annet/annlib/diff.py +0 -0
  54. {annet-3.12.1 → annet-3.14.0}/annet/annlib/errors.py +0 -0
  55. {annet-3.12.1 → annet-3.14.0}/annet/annlib/filter_acl.py +0 -0
  56. {annet-3.12.1 → annet-3.14.0}/annet/annlib/jsontools.py +0 -0
  57. {annet-3.12.1 → annet-3.14.0}/annet/annlib/lib.py +0 -0
  58. {annet-3.12.1 → annet-3.14.0}/annet/annlib/netdev/__init__.py +0 -0
  59. {annet-3.12.1 → annet-3.14.0}/annet/annlib/netdev/db.py +0 -0
  60. {annet-3.12.1 → annet-3.14.0}/annet/annlib/netdev/devdb/__init__.py +0 -0
  61. {annet-3.12.1 → annet-3.14.0}/annet/annlib/netdev/views/__init__.py +0 -0
  62. {annet-3.12.1 → annet-3.14.0}/annet/annlib/netdev/views/dump.py +0 -0
  63. {annet-3.12.1 → annet-3.14.0}/annet/annlib/netdev/views/hardware.py +0 -0
  64. {annet-3.12.1 → annet-3.14.0}/annet/annlib/output.py +0 -0
  65. {annet-3.12.1 → annet-3.14.0}/annet/annlib/patching.py +0 -0
  66. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rbparser/__init__.py +0 -0
  67. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rbparser/acl.py +0 -0
  68. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rbparser/deploying.py +0 -0
  69. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rbparser/ordering.py +0 -0
  70. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rbparser/platform.py +0 -0
  71. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rbparser/syntax.py +0 -0
  72. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rulebook/__init__.py +0 -0
  73. {annet-3.12.1 → annet-3.14.0}/annet/annlib/rulebook/common.py +0 -0
  74. {annet-3.12.1 → annet-3.14.0}/annet/annlib/types.py +0 -0
  75. {annet-3.12.1 → annet-3.14.0}/annet/api/__init__.py +0 -0
  76. {annet-3.12.1 → annet-3.14.0}/annet/argparse.py +0 -0
  77. {annet-3.12.1 → annet-3.14.0}/annet/cli.py +0 -0
  78. {annet-3.12.1 → annet-3.14.0}/annet/cli_args.py +0 -0
  79. {annet-3.12.1 → annet-3.14.0}/annet/configs/context.yml +0 -0
  80. {annet-3.12.1 → annet-3.14.0}/annet/configs/logging.yaml +0 -0
  81. {annet-3.12.1 → annet-3.14.0}/annet/connectors.py +0 -0
  82. {annet-3.12.1 → annet-3.14.0}/annet/deploy.py +0 -0
  83. {annet-3.12.1 → annet-3.14.0}/annet/deploy_ui.py +0 -0
  84. {annet-3.12.1 → annet-3.14.0}/annet/diff.py +0 -0
  85. {annet-3.12.1 → annet-3.14.0}/annet/filtering.py +0 -0
  86. {annet-3.12.1 → annet-3.14.0}/annet/gen.py +0 -0
  87. {annet-3.12.1 → annet-3.14.0}/annet/generators/__init__.py +0 -0
  88. {annet-3.12.1 → annet-3.14.0}/annet/generators/base.py +0 -0
  89. {annet-3.12.1 → annet-3.14.0}/annet/generators/common/__init__.py +0 -0
  90. {annet-3.12.1 → annet-3.14.0}/annet/generators/common/initial.py +0 -0
  91. {annet-3.12.1 → annet-3.14.0}/annet/generators/entire.py +0 -0
  92. {annet-3.12.1 → annet-3.14.0}/annet/generators/exceptions.py +0 -0
  93. {annet-3.12.1 → annet-3.14.0}/annet/generators/jsonfragment.py +0 -0
  94. {annet-3.12.1 → annet-3.14.0}/annet/generators/partial.py +0 -0
  95. {annet-3.12.1 → annet-3.14.0}/annet/generators/perf.py +0 -0
  96. {annet-3.12.1 → annet-3.14.0}/annet/generators/ref.py +0 -0
  97. {annet-3.12.1 → annet-3.14.0}/annet/generators/result.py +0 -0
  98. {annet-3.12.1 → annet-3.14.0}/annet/hardware.py +0 -0
  99. {annet-3.12.1 → annet-3.14.0}/annet/implicit.py +0 -0
  100. {annet-3.12.1 → annet-3.14.0}/annet/lib.py +0 -0
  101. {annet-3.12.1 → annet-3.14.0}/annet/mesh/__init__.py +0 -0
  102. {annet-3.12.1 → annet-3.14.0}/annet/mesh/basemodel.py +0 -0
  103. {annet-3.12.1 → annet-3.14.0}/annet/mesh/executor.py +0 -0
  104. {annet-3.12.1 → annet-3.14.0}/annet/mesh/match_args.py +0 -0
  105. {annet-3.12.1 → annet-3.14.0}/annet/mesh/models_converter.py +0 -0
  106. {annet-3.12.1 → annet-3.14.0}/annet/mesh/peer_models.py +0 -0
  107. {annet-3.12.1 → annet-3.14.0}/annet/mesh/port_processor.py +0 -0
  108. {annet-3.12.1 → annet-3.14.0}/annet/mesh/registry.py +0 -0
  109. {annet-3.12.1 → annet-3.14.0}/annet/output.py +0 -0
  110. {annet-3.12.1 → annet-3.14.0}/annet/parallel.py +0 -0
  111. {annet-3.12.1 → annet-3.14.0}/annet/patching.py +0 -0
  112. {annet-3.12.1 → annet-3.14.0}/annet/reference.py +0 -0
  113. {annet-3.12.1 → annet-3.14.0}/annet/rpl/__init__.py +0 -0
  114. {annet-3.12.1 → annet-3.14.0}/annet/rpl/action.py +0 -0
  115. {annet-3.12.1 → annet-3.14.0}/annet/rpl/condition.py +0 -0
  116. {annet-3.12.1 → annet-3.14.0}/annet/rpl/policy.py +0 -0
  117. {annet-3.12.1 → annet-3.14.0}/annet/rpl/result.py +0 -0
  118. {annet-3.12.1 → annet-3.14.0}/annet/rpl/routemap.py +0 -0
  119. {annet-3.12.1 → annet-3.14.0}/annet/rpl/statement_builder.py +0 -0
  120. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/__init__.py +0 -0
  121. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/cumulus_frr.py +0 -0
  122. {annet-3.12.1 → annet-3.14.0}/annet/rpl_generators/execute.py +0 -0
  123. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/__init__.py +0 -0
  124. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/arista/__init__.py +0 -0
  125. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/arista/aaa.py +0 -0
  126. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/arista/iface.py +0 -0
  127. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/aruba/__init__.py +0 -0
  128. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/aruba/ap_env.py +0 -0
  129. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/aruba/misc.py +0 -0
  130. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/b4com/__init__.py +0 -0
  131. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/b4com/file.py +0 -0
  132. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/b4com/iface.py +0 -0
  133. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/cisco/__init__.py +0 -0
  134. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/cisco/iface.py +0 -0
  135. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/cisco/misc.py +0 -0
  136. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/cisco/vlandb.py +0 -0
  137. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/common.py +0 -0
  138. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/deploying.py +0 -0
  139. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/generic/__init__.py +0 -0
  140. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/generic/misc.py +0 -0
  141. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/huawei/__init__.py +0 -0
  142. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/huawei/aaa.py +0 -0
  143. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/huawei/bgp.py +0 -0
  144. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/huawei/iface.py +0 -0
  145. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/huawei/misc.py +0 -0
  146. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/huawei/vlandb.py +0 -0
  147. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/juniper/__init__.py +0 -0
  148. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/juniper/iface.py +0 -0
  149. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/nexus/__init__.py +0 -0
  150. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/nexus/iface.py +0 -0
  151. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/patching.py +0 -0
  152. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/routeros/__init__.py +0 -0
  153. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/routeros/file.py +0 -0
  154. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/arista.deploy +0 -0
  155. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/arista.order +0 -0
  156. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/arista.rul +0 -0
  157. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/aruba.deploy +0 -0
  158. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/aruba.order +0 -0
  159. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/aruba.rul +0 -0
  160. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/b4com.deploy +0 -0
  161. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/b4com.order +0 -0
  162. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/b4com.rul +0 -0
  163. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/cisco.deploy +0 -0
  164. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/cisco.order +0 -0
  165. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/cisco.rul +0 -0
  166. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/huawei.deploy +0 -0
  167. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/huawei.order +0 -0
  168. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/iosxr.deploy +0 -0
  169. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/iosxr.order +0 -0
  170. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/iosxr.rul +0 -0
  171. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/juniper.order +0 -0
  172. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/nexus.deploy +0 -0
  173. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/nexus.order +0 -0
  174. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/nexus.rul +0 -0
  175. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/nokia.rul +0 -0
  176. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/optixtrans.deploy +0 -0
  177. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/optixtrans.order +0 -0
  178. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/optixtrans.rul +0 -0
  179. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/pc.deploy +0 -0
  180. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/pc.order +0 -0
  181. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/pc.rul +0 -0
  182. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/ribbon.deploy +0 -0
  183. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/ribbon.rul +0 -0
  184. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/routeros.order +0 -0
  185. {annet-3.12.1 → annet-3.14.0}/annet/rulebook/texts/routeros.rul +0 -0
  186. {annet-3.12.1 → annet-3.14.0}/annet/storage.py +0 -0
  187. {annet-3.12.1 → annet-3.14.0}/annet/text_term_format.py +0 -0
  188. {annet-3.12.1 → annet-3.14.0}/annet/tracing.py +0 -0
  189. {annet-3.12.1 → annet-3.14.0}/annet/types.py +0 -0
  190. {annet-3.12.1 → annet-3.14.0}/annet/vendors/__init__.py +0 -0
  191. {annet-3.12.1 → annet-3.14.0}/annet/vendors/base.py +0 -0
  192. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/__init__.py +0 -0
  193. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/arista.py +0 -0
  194. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/aruba.py +0 -0
  195. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/b4com.py +0 -0
  196. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/cisco.py +0 -0
  197. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/h3c.py +0 -0
  198. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/huawei.py +0 -0
  199. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/iosxr.py +0 -0
  200. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/juniper.py +0 -0
  201. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/nexus.py +0 -0
  202. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/nokia.py +0 -0
  203. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/optixtrans.py +0 -0
  204. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/pc.py +0 -0
  205. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/ribbon.py +0 -0
  206. {annet-3.12.1 → annet-3.14.0}/annet/vendors/library/routeros.py +0 -0
  207. {annet-3.12.1 → annet-3.14.0}/annet/vendors/registry.py +0 -0
  208. {annet-3.12.1 → annet-3.14.0}/annet.egg-info/SOURCES.txt +0 -0
  209. {annet-3.12.1 → annet-3.14.0}/annet.egg-info/dependency_links.txt +0 -0
  210. {annet-3.12.1 → annet-3.14.0}/annet.egg-info/entry_points.txt +0 -0
  211. {annet-3.12.1 → annet-3.14.0}/annet.egg-info/requires.txt +0 -0
  212. {annet-3.12.1 → annet-3.14.0}/annet.egg-info/top_level.txt +0 -0
  213. {annet-3.12.1 → annet-3.14.0}/annet_generators/__init__.py +0 -0
  214. {annet-3.12.1 → annet-3.14.0}/annet_generators/example/__init__.py +0 -0
  215. {annet-3.12.1 → annet-3.14.0}/annet_generators/example/hostname.py +0 -0
  216. {annet-3.12.1 → annet-3.14.0}/annet_generators/example/lldp.py +0 -0
  217. {annet-3.12.1 → annet-3.14.0}/annet_generators/mesh_example/__init__.py +0 -0
  218. {annet-3.12.1 → annet-3.14.0}/annet_generators/mesh_example/bgp.py +0 -0
  219. {annet-3.12.1 → annet-3.14.0}/annet_generators/mesh_example/mesh_logic.py +0 -0
  220. {annet-3.12.1 → annet-3.14.0}/annet_generators/rpl_example/__init__.py +0 -0
  221. {annet-3.12.1 → annet-3.14.0}/annet_generators/rpl_example/generator.py +0 -0
  222. {annet-3.12.1 → annet-3.14.0}/annet_generators/rpl_example/items.py +0 -0
  223. {annet-3.12.1 → annet-3.14.0}/annet_generators/rpl_example/mesh.py +0 -0
  224. {annet-3.12.1 → annet-3.14.0}/annet_generators/rpl_example/route_policy.py +0 -0
  225. {annet-3.12.1 → annet-3.14.0}/requirements.txt +0 -0
  226. {annet-3.12.1 → annet-3.14.0}/setup.cfg +0 -0
  227. {annet-3.12.1 → annet-3.14.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: annet
3
- Version: 3.12.1
3
+ Version: 3.14.0
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -189,6 +189,8 @@ class Interface(Entity, Generic[_IpAddressT, _FHRPGroupAssignmentT]):
189
189
  lag_min_links: int | None = None
190
190
  speed: int | None = None
191
191
 
192
+ custom_fields: Dict[str, Any] = field(default_factory=dict)
193
+
192
194
  ip_addresses: List[_IpAddressT] = field(default_factory=list)
193
195
  count_ipaddresses: int = 0
194
196
  fhrp_groups: List[_FHRPGroupAssignmentT] = field(default_factory=list)
@@ -45,12 +45,13 @@ def storage_factory(opts: NetboxStorageOpts) -> Storage:
45
45
 
46
46
  class NetboxProvider(StorageProvider, AdapterWithName, AdapterWithConfig):
47
47
  def __init__(self, url: Optional[str] = None, token: Optional[str] = None, insecure: bool = False,
48
- exact_host_filter: bool = False, threads: int = 1):
48
+ exact_host_filter: bool = False, threads: int = 1, all_hosts_filter: dict[str, list[str]] | None = None):
49
49
  self.url = url
50
50
  self.token = token
51
51
  self.insecure = insecure
52
52
  self.exact_host_filter = exact_host_filter
53
53
  self.threads = threads
54
+ self.all_hosts_filter = all_hosts_filter
54
55
 
55
56
  @classmethod
56
57
  def with_config(cls, **kwargs: Dict[str, Any]) -> T:
@@ -144,7 +144,7 @@
144
144
  "PC.Whitebox.Ufispace.S.S9300.S9301_32DB": " S9301-32DB",
145
145
  "PC.Whitebox.Ufispace.S.S9300.S9321_64EO": " S9321-64EO",
146
146
  "PC.Nebius": "^Nebius",
147
- "PC.Nebius.NB-E-BR-DCU-AST2600": "^Nebius NB-E-BR-DCU-AST2600",
147
+ "PC.Nebius.Octoport": " NB-D-M-CSM-R",
148
148
  "PC.Avocent": " [Aa]vocent",
149
149
  "PC.Avocent.ACS8000": " (ACS|acs)8000",
150
150
 
@@ -189,4 +189,4 @@
189
189
  "B4com.CS4132U": "^[Bb]4com B4T-CS4132U.*",
190
190
  "B4com.CS4148Q": "^[Bb]4com B4T-CS4148Q.*",
191
191
  "B4com.CS4164U": "^[Bb]4com B4T-CS4164U.*"
192
- }
192
+ }
@@ -255,6 +255,8 @@ class FamilyOptions:
255
255
  rib_group: bool = False
256
256
  loops: int = 0
257
257
  advertise_bgp_static: bool = False
258
+ import_policy: Optional[str] = None
259
+ export_policy: Optional[str] = None
258
260
 
259
261
 
260
262
  @dataclass(frozen=True)
@@ -387,7 +389,7 @@ def _used_policies(peer: Union[Peer, PeerGroup, VrfOptions]) -> Iterable[str]:
387
389
  yield peer.export_policy
388
390
 
389
391
 
390
- def _used_redistribute_policies(opts: Union[GlobalOptions, VrfOptions]) -> Iterable[str]:
392
+ def _used_families_policies(opts: Union[GlobalOptions, VrfOptions]) -> Iterable[str]:
391
393
  for family_opts in (
392
394
  opts.ipv4_unicast,
393
395
  opts.ipv6_unicast,
@@ -400,6 +402,13 @@ def _used_redistribute_policies(opts: Union[GlobalOptions, VrfOptions]) -> Itera
400
402
  yield red.policy
401
403
  if family_opts.aggregate and family_opts.aggregate.policy:
402
404
  yield family_opts.aggregate.policy
405
+ for aggregate in family_opts.aggregates:
406
+ if aggregate.policy:
407
+ yield aggregate.policy
408
+ if family_opts.export_policy:
409
+ yield family_opts.export_policy
410
+ if family_opts.import_policy:
411
+ yield family_opts.import_policy
403
412
 
404
413
 
405
414
  def extract_policies(config: BgpConfig) -> Sequence[str]:
@@ -407,11 +416,11 @@ def extract_policies(config: BgpConfig) -> Sequence[str]:
407
416
  for vrf in config.global_options.vrf.values():
408
417
  for group in vrf.groups:
409
418
  result.extend(_used_policies(group))
410
- result.extend(_used_redistribute_policies(vrf))
419
+ result.extend(_used_families_policies(vrf))
411
420
  result.extend(_used_policies(vrf))
412
421
  for group in config.global_options.groups:
413
422
  result.extend(_used_policies(group))
414
423
  for peer in config.peers:
415
424
  result.extend(_used_policies(peer))
416
- result.extend(_used_redistribute_policies(config.global_options))
425
+ result.extend(_used_families_policies(config.global_options))
417
426
  return result
@@ -36,6 +36,8 @@ class FamilyOptions(BaseMeshModel):
36
36
  rib_group: bool
37
37
  loops: int
38
38
  advertise_bgp_static: bool
39
+ import_policy: Optional[str]
40
+ export_policy: Optional[str]
39
41
 
40
42
 
41
43
  class _FamiliesMixin:
@@ -95,8 +95,12 @@ class Checkable:
95
95
  def match_v6(
96
96
  self,
97
97
  *names: str,
98
- or_longer: OrLonger = (None, None),
98
+ or_longer: bool | OrLonger = (None, None),
99
99
  ) -> SingleCondition[PrefixMatchValue]:
100
+ if or_longer is True:
101
+ or_longer = (None, 128)
102
+ if or_longer is False:
103
+ or_longer = (None, None)
100
104
  return SingleCondition(
101
105
  MatchField.ipv6_prefix,
102
106
  ConditionOperator.CUSTOM,
@@ -106,8 +110,12 @@ class Checkable:
106
110
  def match_v4(
107
111
  self,
108
112
  *names: str,
109
- or_longer: OrLonger = (None, None),
113
+ or_longer: bool | OrLonger = (None, None),
110
114
  ) -> SingleCondition[PrefixMatchValue]:
115
+ if or_longer is True:
116
+ or_longer = (None, 32)
117
+ if or_longer is False:
118
+ or_longer = (None, None)
111
119
  return SingleCondition(
112
120
  MatchField.ip_prefix,
113
121
  ConditionOperator.CUSTOM,
@@ -71,3 +71,25 @@ class AsPathFilterGenerator(PartialGenerator, ABC):
71
71
  else:
72
72
  comma = ""
73
73
  yield "ios-regex", f"'{filter_item}'{comma}"
74
+
75
+ def acl_juniper(self, _):
76
+ return r"""
77
+ policy-options %cant_delete
78
+ as-path ~
79
+ """
80
+
81
+ def _juniper_as_path(self, name: str, as_path_member: str):
82
+ if not as_path_member.isnumeric():
83
+ as_path_member = f'"{as_path_member}"'
84
+ yield "as-path", name, as_path_member
85
+
86
+ def run_juniper(self, device: Any):
87
+ for as_path_filter in self.get_used_as_path_filters(device):
88
+ # TODO could be implemented via as-path-groups
89
+ # But we need to provide as_path_filters to policy generator
90
+ # To select between regular as-path and as-path-groups
91
+ if len(as_path_filter.filters) > 1:
92
+ raise NotImplementedError(f"Multiple elements in as_path_filter {as_path_filter.name} is not supported for Juniper")
93
+
94
+ with self.block("policy-options"):
95
+ yield from self._juniper_as_path(as_path_filter.name, as_path_filter.filters[0])
@@ -1,5 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
- from collections.abc import Sequence, Collection, Iterator
2
+ from collections import defaultdict
3
+ from collections.abc import Sequence, Collection, Iterator, Mapping
3
4
  from typing import Any
4
5
 
5
6
  from annet.generators import PartialGenerator
@@ -12,6 +13,7 @@ from .entities import (
12
13
  def get_used_community_lists(
13
14
  communities: Collection[CommunityList], policies: Collection[RoutingPolicy],
14
15
  ) -> list[CommunityList]:
16
+ assert_unique_names(communities)
15
17
  communities_dict = {c.name: c for c in communities}
16
18
  used_communities: set[str] = set()
17
19
  for policy in policies:
@@ -44,6 +46,7 @@ def get_used_united_community_lists(
44
46
  """
45
47
  Return communities united into groups according to HAS_ANY policy
46
48
  """
49
+ assert_unique_names(communities)
47
50
  communities_dict = {c.name: c for c in communities}
48
51
  used_communities: dict[str, list[CommunityList]] = {}
49
52
  for policy in policies:
@@ -93,6 +96,17 @@ def get_used_united_community_lists(
93
96
  ]
94
97
 
95
98
 
99
+ def assert_unique_names(communities: Collection[CommunityList]) -> None:
100
+ duplicated: list[str] = []
101
+ seen_names: set[str] = set()
102
+ for c in communities:
103
+ if c.name in seen_names:
104
+ duplicated.append(c.name)
105
+ seen_names.add(c.name)
106
+ if duplicated:
107
+ raise NotImplementedError(f"Non-unique community-list names are not supported: {duplicated}")
108
+
109
+
96
110
  class CommunityListGenerator(PartialGenerator, ABC):
97
111
  TAGS = ["policy", "rpl", "routing"]
98
112
 
@@ -274,3 +288,61 @@ class CommunityListGenerator(PartialGenerator, ABC):
274
288
  def run_iosxr(self, device):
275
289
  for community_list in self.get_used_community_lists(device):
276
290
  yield from self._iosxr_community_list(community_list)
291
+
292
+ def acl_juniper(self, _) -> str:
293
+ return r"""
294
+ policy-options %cant_delete
295
+ community ~
296
+ """
297
+
298
+ def _juniper_community_list(self, name: str, community_lists: list[CommunityList]) -> Iterator[Sequence[str]]:
299
+ members: list[str] = []
300
+ logic: set[CommunityLogic] = set()
301
+ for community_list in community_lists:
302
+ prefix: str
303
+ if community_list.type is CommunityType.BASIC:
304
+ prefix = ""
305
+ elif community_list.type is CommunityType.RT:
306
+ prefix = "target:"
307
+ elif community_list.type is CommunityType.SOO:
308
+ prefix = "origin:"
309
+ elif community_list.type is CommunityType.LARGE:
310
+ prefix = "large:"
311
+ else:
312
+ raise NotImplementedError(f"CommunityList {name}: type {community_list.type} not implemented for Juniper")
313
+
314
+ logic.add(community_list.logic)
315
+ for community in community_list.members:
316
+ members.append(prefix + community)
317
+
318
+ if len(members) > 1 and logic != {CommunityLogic.AND}:
319
+ raise NotImplementedError(f"CommunityList {name}: only AND logic between members is implemeted for Juniper")
320
+
321
+ definition = ["community", name, "members"]
322
+ with self.block("policy-options"):
323
+ if len(members) == 1:
324
+ yield *definition, *members
325
+ if len(members) > 1:
326
+ yield *definition, "[", *members, "]"
327
+
328
+ def run_juniper(self, device):
329
+ # Juniper allows different community types
330
+ # so we write generator in a generic way to reflect that.
331
+ #
332
+ # But get_used_community_lists DOES NOT allow multiple names
333
+ # This is in part because juniper does not have a type-aware match
334
+ # It would mean that there is no way to describe a following config via rpl.py:
335
+ #
336
+ # CommunityList("COMM_LIST", ["65000:4000"], CommunityType.BASIC),
337
+ # CommunityList("COMM_LIST", ["65000:4000"], CommunityType.RT),
338
+ #
339
+ # # match only route-target but not basic one
340
+ # with route(R.extcommunity_rt.has("COMM_LIST")) as rule:
341
+ # ...
342
+ used = self.get_used_community_lists(device)
343
+ by_name: Mapping[str, list[CommunityList]] = defaultdict(list)
344
+ for community_list in used:
345
+ by_name[community_list.name].append(community_list)
346
+
347
+ for name, community_lists in by_name.items():
348
+ yield from self._juniper_community_list(name, community_lists)
@@ -3,7 +3,7 @@ from collections import defaultdict
3
3
  from collections.abc import Sequence
4
4
  from dataclasses import dataclass
5
5
  from enum import Enum
6
- from typing import Optional, List
6
+ from typing import Optional, List, Literal
7
7
 
8
8
  from annet.rpl import RoutingPolicy, PrefixMatchValue, OrLonger
9
9
 
@@ -103,12 +103,12 @@ class PrefixListNameGenerator:
103
103
  self._prefix_lists = {x.name: x for x in prefix_lists}
104
104
  self._policies = {x.name: x for x in policies} # this is here for a later use ~azryve@
105
105
 
106
- def get_prefix(self, name: str, match: PrefixMatchValue) -> IpPrefixList:
106
+ def get_prefix(self, name: str, match: PrefixMatchValue | None) -> IpPrefixList:
107
107
  orig_prefix = self._prefix_lists[name]
108
108
  override_name: Optional[str] = None
109
109
  override_orlonger: Optional[OrLonger] = None
110
110
 
111
- if any(match.or_longer):
111
+ if match and match.or_longer != (None, None):
112
112
  ge, le = match.or_longer
113
113
  ge_str = "unset" if ge is None else str(ge)
114
114
  le_str = "unset" if le is None else str(le)
@@ -135,3 +135,50 @@ def group_community_members(
135
135
  community = all_communities[community_name]
136
136
  members[community.type].extend(community.members)
137
137
  return members
138
+
139
+
140
+ class JuniperPrefixListNameGenerator(PrefixListNameGenerator):
141
+ def get_prefix(self, name: str, match: PrefixMatchValue | None) -> IpPrefixList:
142
+ plist = super().get_prefix(name, match)
143
+ flavour = self.get_plist_flavour(plist)
144
+ # keep the orginal name for an orlonger match
145
+ if flavour != "custom":
146
+ plist.name = name
147
+ return plist
148
+
149
+ def get_type(self, name: str, match: PrefixMatchValue | None) -> Literal["prefix-list", "route-filter"]:
150
+ orig_plist = self.get_prefix(name, None)
151
+ plist = self.get_prefix(name, match)
152
+ orig_flavour = self.get_plist_flavour(orig_plist)
153
+ flavour = self.get_plist_flavour(plist)
154
+ if orig_flavour == "custom" or flavour == "custom":
155
+ return "route-filter"
156
+ else:
157
+ return "prefix-list"
158
+
159
+ def get_plist_flavour(self, plist: IpPrefixList) -> Literal["simple", "orlonger", "custom"]:
160
+ is_orlonger: bool = False
161
+ is_custom: bool = False
162
+ for m in plist.members:
163
+ ge, le = m.or_longer
164
+
165
+ # or_longer != (None, None)
166
+ if ge is not None or le is not None:
167
+ is_orlonger = True
168
+
169
+ # orlonger != (n, None), where n is .../n
170
+ if ge is not None and ge != m.prefix.prefixlen:
171
+ is_custom = True
172
+ break
173
+
174
+ # orlonger != (None, n), where n is 32 or 128 (ipv4/ipv6)
175
+ if le is not None and le != m.prefix.max_prefixlen:
176
+ is_custom = True
177
+ break
178
+
179
+ if is_custom:
180
+ return "custom"
181
+ elif is_orlonger:
182
+ return "orlonger"
183
+ else:
184
+ return "simple"