annet 0.13.4__tar.gz → 3.22.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.
Files changed (262) hide show
  1. {annet-0.13.4/annet.egg-info → annet-3.22.0}/PKG-INFO +15 -7
  2. annet-3.22.0/README.md +89 -0
  3. {annet-0.13.4 → annet-3.22.0}/annet/__init__.py +7 -11
  4. annet-3.22.0/annet/adapters/fetchers/stub/fetcher.py +25 -0
  5. annet-3.22.0/annet/adapters/file/provider.py +280 -0
  6. annet-3.22.0/annet/adapters/netbox/common/adapter.py +87 -0
  7. {annet-0.13.4 → annet-3.22.0}/annet/adapters/netbox/common/client.py +3 -1
  8. annet-3.22.0/annet/adapters/netbox/common/manufacturer.py +44 -0
  9. annet-3.22.0/annet/adapters/netbox/common/models.py +352 -0
  10. annet-3.22.0/annet/adapters/netbox/common/query.py +68 -0
  11. {annet-0.13.4 → annet-3.22.0}/annet/adapters/netbox/common/status_client.py +8 -1
  12. annet-3.22.0/annet/adapters/netbox/common/storage_base.py +290 -0
  13. annet-3.22.0/annet/adapters/netbox/common/storage_opts.py +72 -0
  14. annet-3.22.0/annet/adapters/netbox/provider.py +73 -0
  15. annet-3.22.0/annet/adapters/netbox/v24/models.py +296 -0
  16. {annet-0.13.4 → annet-3.22.0}/annet/adapters/netbox/v24/storage.py +14 -5
  17. annet-3.22.0/annet/adapters/netbox/v37/models.py +77 -0
  18. annet-3.22.0/annet/adapters/netbox/v37/storage.py +129 -0
  19. annet-3.22.0/annet/adapters/netbox/v41/models.py +85 -0
  20. annet-3.22.0/annet/adapters/netbox/v41/storage.py +132 -0
  21. annet-3.22.0/annet/adapters/netbox/v42/models.py +72 -0
  22. annet-3.22.0/annet/adapters/netbox/v42/storage.py +157 -0
  23. {annet-0.13.4 → annet-3.22.0}/annet/annet.py +10 -2
  24. {annet-0.13.4 → annet-3.22.0}/annet/annlib/command.py +6 -2
  25. {annet-0.13.4 → annet-3.22.0}/annet/annlib/diff.py +2 -5
  26. {annet-0.13.4 → annet-3.22.0}/annet/annlib/filter_acl.py +8 -3
  27. annet-3.22.0/annet/annlib/jsontools.py +252 -0
  28. {annet-0.13.4 → annet-3.22.0}/annet/annlib/lib.py +1 -15
  29. {annet-0.13.4 → annet-3.22.0}/annet/annlib/netdev/devdb/__init__.py +4 -2
  30. annet-3.22.0/annet/annlib/netdev/devdb/data/devdb.json +201 -0
  31. {annet-0.13.4 → annet-3.22.0}/annet/annlib/netdev/views/dump.py +8 -0
  32. {annet-0.13.4 → annet-3.22.0}/annet/annlib/netdev/views/hardware.py +41 -49
  33. {annet-0.13.4 → annet-3.22.0}/annet/annlib/output.py +8 -6
  34. annet-3.22.0/annet/annlib/patching.py +900 -0
  35. {annet-0.13.4 → annet-3.22.0}/annet/annlib/rbparser/acl.py +3 -2
  36. annet-3.22.0/annet/annlib/rbparser/ordering.py +96 -0
  37. annet-3.22.0/annet/annlib/rbparser/platform.py +1 -0
  38. {annet-0.13.4 → annet-3.22.0}/annet/annlib/rbparser/syntax.py +51 -29
  39. {annet-0.13.4 → annet-3.22.0}/annet/annlib/rulebook/common.py +30 -89
  40. {annet-0.13.4 → annet-3.22.0}/annet/api/__init__.py +276 -212
  41. {annet-0.13.4 → annet-3.22.0}/annet/argparse.py +8 -2
  42. annet-3.22.0/annet/bgp_models.py +449 -0
  43. {annet-0.13.4 → annet-3.22.0}/annet/cli.py +135 -39
  44. {annet-0.13.4 → annet-3.22.0}/annet/cli_args.py +88 -68
  45. annet-3.22.0/annet/configs/context.yml +16 -0
  46. {annet-0.13.4 → annet-3.22.0}/annet/configs/logging.yaml +1 -0
  47. annet-3.22.0/annet/connectors.py +144 -0
  48. annet-3.22.0/annet/deploy.py +233 -0
  49. annet-3.22.0/annet/deploy_ui.py +809 -0
  50. annet-3.22.0/annet/diff.py +246 -0
  51. {annet-0.13.4 → annet-3.22.0}/annet/filtering.py +1 -0
  52. {annet-0.13.4 → annet-3.22.0}/annet/gen.py +36 -98
  53. {annet-0.13.4 → annet-3.22.0}/annet/generators/__init__.py +99 -76
  54. annet-3.22.0/annet/generators/annotate.py +37 -0
  55. {annet-0.13.4 → annet-3.22.0}/annet/generators/base.py +13 -3
  56. {annet-0.13.4 → annet-3.22.0}/annet/generators/entire.py +20 -31
  57. {annet-0.13.4 → annet-3.22.0}/annet/generators/jsonfragment.py +31 -37
  58. {annet-0.13.4 → annet-3.22.0}/annet/generators/partial.py +32 -52
  59. {annet-0.13.4 → annet-3.22.0}/annet/generators/perf.py +9 -18
  60. {annet-0.13.4 → annet-3.22.0}/annet/generators/result.py +33 -30
  61. annet-3.22.0/annet/hardware.py +42 -0
  62. {annet-0.13.4 → annet-3.22.0}/annet/implicit.py +75 -11
  63. {annet-0.13.4 → annet-3.22.0}/annet/lib.py +43 -8
  64. annet-3.22.0/annet/mesh/__init__.py +23 -0
  65. annet-3.22.0/annet/mesh/basemodel.py +249 -0
  66. annet-3.22.0/annet/mesh/device_models.py +114 -0
  67. annet-3.22.0/annet/mesh/executor.py +421 -0
  68. annet-3.22.0/annet/mesh/match_args.py +165 -0
  69. annet-3.22.0/annet/mesh/models_converter.py +104 -0
  70. annet-3.22.0/annet/mesh/peer_models.py +135 -0
  71. annet-3.22.0/annet/mesh/port_processor.py +18 -0
  72. annet-3.22.0/annet/mesh/registry.py +299 -0
  73. {annet-0.13.4 → annet-3.22.0}/annet/output.py +37 -8
  74. {annet-0.13.4 → annet-3.22.0}/annet/parallel.py +28 -15
  75. annet-3.22.0/annet/rpl/__init__.py +28 -0
  76. annet-3.22.0/annet/rpl/action.py +51 -0
  77. annet-3.22.0/annet/rpl/condition.py +94 -0
  78. annet-3.22.0/annet/rpl/match_builder.py +136 -0
  79. annet-3.22.0/annet/rpl/policy.py +22 -0
  80. annet-3.22.0/annet/rpl/result.py +8 -0
  81. annet-3.22.0/annet/rpl/routemap.py +78 -0
  82. annet-3.22.0/annet/rpl/statement_builder.py +306 -0
  83. annet-3.22.0/annet/rpl_generators/__init__.py +26 -0
  84. annet-3.22.0/annet/rpl_generators/aspath.py +95 -0
  85. annet-3.22.0/annet/rpl_generators/community.py +348 -0
  86. annet-3.22.0/annet/rpl_generators/cumulus_frr.py +489 -0
  87. annet-3.22.0/annet/rpl_generators/entities.py +184 -0
  88. annet-3.22.0/annet/rpl_generators/execute.py +12 -0
  89. annet-3.22.0/annet/rpl_generators/policy.py +1486 -0
  90. annet-3.22.0/annet/rpl_generators/prefix_lists.py +238 -0
  91. annet-3.22.0/annet/rpl_generators/rd.py +71 -0
  92. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/__init__.py +6 -4
  93. annet-3.22.0/annet/rulebook/arista/__init__.py +0 -0
  94. annet-3.22.0/annet/rulebook/arista/aaa.py +63 -0
  95. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/aruba/ap_env.py +1 -6
  96. annet-3.22.0/annet/rulebook/b4com/__init__.py +0 -0
  97. annet-3.22.0/annet/rulebook/b4com/bgp.py +60 -0
  98. annet-3.22.0/annet/rulebook/b4com/file.py +5 -0
  99. annet-3.22.0/annet/rulebook/b4com/iface.py +119 -0
  100. annet-3.22.0/annet/rulebook/cisco/__init__.py +0 -0
  101. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/cisco/iface.py +1 -1
  102. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/cisco/misc.py +8 -6
  103. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/deploying.py +3 -2
  104. annet-3.22.0/annet/rulebook/generic/__init__.py +0 -0
  105. annet-3.22.0/annet/rulebook/generic/misc.py +14 -0
  106. annet-3.22.0/annet/rulebook/h3c/__init__.py +0 -0
  107. annet-3.22.0/annet/rulebook/h3c/aaa.py +28 -0
  108. annet-3.22.0/annet/rulebook/h3c/bgp.py +84 -0
  109. annet-3.22.0/annet/rulebook/h3c/iface.py +22 -0
  110. annet-3.22.0/annet/rulebook/h3c/misc.py +306 -0
  111. annet-3.22.0/annet/rulebook/h3c/vlandb.py +118 -0
  112. annet-3.22.0/annet/rulebook/huawei/__init__.py +0 -0
  113. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/huawei/aaa.py +12 -1
  114. annet-3.22.0/annet/rulebook/juniper/__init__.py +156 -0
  115. annet-3.22.0/annet/rulebook/juniper/iface.py +39 -0
  116. annet-3.22.0/annet/rulebook/nexus/__init__.py +0 -0
  117. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/patching.py +8 -5
  118. annet-3.22.0/annet/rulebook/routeros/__init__.py +0 -0
  119. annet-3.22.0/annet/rulebook/routeros/file.py +5 -0
  120. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/arista.order +14 -13
  121. annet-3.22.0/annet/rulebook/texts/arista.rul +82 -0
  122. annet-3.22.0/annet/rulebook/texts/b4com.deploy +18 -0
  123. annet-3.22.0/annet/rulebook/texts/b4com.order +38 -0
  124. annet-3.22.0/annet/rulebook/texts/b4com.rul +47 -0
  125. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/cisco.deploy +1 -1
  126. annet-3.22.0/annet/rulebook/texts/cisco.order +86 -0
  127. annet-3.22.0/annet/rulebook/texts/cisco.rul +115 -0
  128. annet-0.13.4/annet/rulebook/texts/huawei.deploy → annet-3.22.0/annet/rulebook/texts/h3c.deploy +9 -1
  129. annet-3.22.0/annet/rulebook/texts/h3c.order +392 -0
  130. annet-3.22.0/annet/rulebook/texts/h3c.rul +432 -0
  131. annet-3.22.0/annet/rulebook/texts/huawei.deploy +201 -0
  132. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/huawei.order +24 -3
  133. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/huawei.rul +39 -7
  134. annet-3.22.0/annet/rulebook/texts/iosxr.deploy +27 -0
  135. annet-0.13.4/annet/rulebook/texts/cisco.order → annet-3.22.0/annet/rulebook/texts/iosxr.order +22 -2
  136. annet-0.13.4/annet/rulebook/texts/cisco.rul → annet-3.22.0/annet/rulebook/texts/iosxr.rul +11 -6
  137. annet-3.22.0/annet/rulebook/texts/juniper.order +12 -0
  138. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/juniper.rul +13 -2
  139. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/nexus.rul +5 -1
  140. annet-3.22.0/annet/rulebook/texts/optixtrans.deploy +18 -0
  141. annet-3.22.0/annet/rulebook/texts/optixtrans.order +5 -0
  142. annet-3.22.0/annet/rulebook/texts/optixtrans.rul +13 -0
  143. annet-3.22.0/annet/rulebook/texts/pc.deploy +0 -0
  144. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/routeros.order +14 -1
  145. annet-3.22.0/annet/storage.py +178 -0
  146. {annet-0.13.4 → annet-3.22.0}/annet/text_term_format.py +1 -1
  147. {annet-0.13.4 → annet-3.22.0}/annet/tracing.py +56 -8
  148. annet-3.22.0/annet/vendors/__init__.py +33 -0
  149. annet-3.22.0/annet/vendors/base.py +44 -0
  150. annet-3.22.0/annet/vendors/library/__init__.py +0 -0
  151. annet-3.22.0/annet/vendors/library/arista.py +44 -0
  152. annet-3.22.0/annet/vendors/library/aruba.py +43 -0
  153. annet-3.22.0/annet/vendors/library/b4com.py +49 -0
  154. annet-3.22.0/annet/vendors/library/cisco.py +41 -0
  155. annet-3.22.0/annet/vendors/library/h3c.py +40 -0
  156. annet-3.22.0/annet/vendors/library/huawei.py +43 -0
  157. annet-3.22.0/annet/vendors/library/iosxr.py +41 -0
  158. annet-3.22.0/annet/vendors/library/juniper.py +44 -0
  159. annet-3.22.0/annet/vendors/library/nexus.py +38 -0
  160. annet-3.22.0/annet/vendors/library/nokia.py +40 -0
  161. annet-3.22.0/annet/vendors/library/optixtrans.py +23 -0
  162. annet-3.22.0/annet/vendors/library/pc.py +39 -0
  163. annet-3.22.0/annet/vendors/library/ribbon.py +41 -0
  164. annet-3.22.0/annet/vendors/library/routeros.py +40 -0
  165. annet-3.22.0/annet/vendors/registry.py +93 -0
  166. annet-3.22.0/annet/vendors/tabparser.py +991 -0
  167. {annet-0.13.4 → annet-3.22.0/annet.egg-info}/PKG-INFO +15 -7
  168. {annet-0.13.4 → annet-3.22.0}/annet.egg-info/SOURCES.txt +103 -5
  169. {annet-0.13.4 → annet-3.22.0}/annet.egg-info/entry_points.txt +3 -0
  170. {annet-0.13.4 → annet-3.22.0}/annet.egg-info/requires.txt +6 -4
  171. annet-3.22.0/annet_generators/__init__.py +0 -0
  172. annet-3.22.0/annet_generators/example/__init__.py +15 -0
  173. annet-3.22.0/annet_generators/example/hostname.py +113 -0
  174. {annet-0.13.4 → annet-3.22.0}/annet_generators/example/lldp.py +28 -0
  175. {annet-0.13.4/annet_generators/example → annet-3.22.0/annet_generators/mesh_example}/__init__.py +2 -5
  176. annet-3.22.0/annet_generators/mesh_example/bgp.py +44 -0
  177. annet-3.22.0/annet_generators/mesh_example/mesh_logic.py +41 -0
  178. annet-3.22.0/annet_generators/rpl_example/__init__.py +7 -0
  179. annet-3.22.0/annet_generators/rpl_example/generator.py +130 -0
  180. annet-3.22.0/annet_generators/rpl_example/items.py +29 -0
  181. annet-3.22.0/annet_generators/rpl_example/mesh.py +9 -0
  182. annet-3.22.0/annet_generators/rpl_example/route_policy.py +67 -0
  183. {annet-0.13.4 → annet-3.22.0}/requirements.txt +2 -4
  184. {annet-0.13.4 → annet-3.22.0}/setup.py +10 -1
  185. annet-0.13.4/README.md +0 -111
  186. annet-0.13.4/annet/adapters/netbox/common/manufacturer.py +0 -62
  187. annet-0.13.4/annet/adapters/netbox/common/models.py +0 -136
  188. annet-0.13.4/annet/adapters/netbox/common/query.py +0 -23
  189. annet-0.13.4/annet/adapters/netbox/common/storage_opts.py +0 -14
  190. annet-0.13.4/annet/adapters/netbox/provider.py +0 -34
  191. annet-0.13.4/annet/adapters/netbox/v37/storage.py +0 -216
  192. annet-0.13.4/annet/annlib/jsontools.py +0 -116
  193. annet-0.13.4/annet/annlib/netdev/devdb/data/devdb.json +0 -145
  194. annet-0.13.4/annet/annlib/patching.py +0 -533
  195. annet-0.13.4/annet/annlib/rbparser/ordering.py +0 -52
  196. annet-0.13.4/annet/annlib/rbparser/platform.py +0 -51
  197. annet-0.13.4/annet/annlib/tabparser.py +0 -648
  198. annet-0.13.4/annet/configs/context.yml +0 -18
  199. annet-0.13.4/annet/connectors.py +0 -77
  200. annet-0.13.4/annet/deploy.py +0 -536
  201. annet-0.13.4/annet/diff.py +0 -84
  202. annet-0.13.4/annet/executor.py +0 -556
  203. annet-0.13.4/annet/hardware.py +0 -45
  204. annet-0.13.4/annet/rulebook/juniper/__init__.py +0 -107
  205. annet-0.13.4/annet/rulebook/ribbon/__init__.py +0 -12
  206. annet-0.13.4/annet/rulebook/texts/arista.rul +0 -59
  207. annet-0.13.4/annet/storage.py +0 -125
  208. annet-0.13.4/annet/tabparser.py +0 -36
  209. {annet-0.13.4 → annet-3.22.0}/AUTHORS +0 -0
  210. {annet-0.13.4 → annet-3.22.0}/LICENSE +0 -0
  211. {annet-0.13.4 → annet-3.22.0}/MANIFEST.in +0 -0
  212. {annet-0.13.4 → annet-3.22.0}/annet/adapters/__init__.py +0 -0
  213. {annet-0.13.4/annet/adapters/netbox → annet-3.22.0/annet/adapters/fetchers}/__init__.py +0 -0
  214. {annet-0.13.4/annet/adapters/netbox/common → annet-3.22.0/annet/adapters/fetchers/stub}/__init__.py +0 -0
  215. {annet-0.13.4/annet/adapters/netbox/v24 → annet-3.22.0/annet/adapters/file}/__init__.py +0 -0
  216. {annet-0.13.4/annet/adapters/netbox/v37 → annet-3.22.0/annet/adapters/netbox}/__init__.py +0 -0
  217. {annet-0.13.4/annet/annlib/netdev → annet-3.22.0/annet/adapters/netbox/common}/__init__.py +0 -0
  218. {annet-0.13.4/annet/annlib/netdev/views → annet-3.22.0/annet/adapters/netbox/v24}/__init__.py +0 -0
  219. {annet-0.13.4/annet/annlib/rbparser → annet-3.22.0/annet/adapters/netbox/v37}/__init__.py +0 -0
  220. {annet-0.13.4/annet/annlib/rulebook → annet-3.22.0/annet/adapters/netbox/v41}/__init__.py +0 -0
  221. {annet-0.13.4/annet/generators/common → annet-3.22.0/annet/adapters/netbox/v42}/__init__.py +0 -0
  222. {annet-0.13.4 → annet-3.22.0}/annet/annlib/__init__.py +0 -0
  223. {annet-0.13.4 → annet-3.22.0}/annet/annlib/errors.py +0 -0
  224. {annet-0.13.4/annet/rulebook/arista → annet-3.22.0/annet/annlib/netdev}/__init__.py +0 -0
  225. {annet-0.13.4 → annet-3.22.0}/annet/annlib/netdev/db.py +0 -0
  226. {annet-0.13.4/annet/rulebook/cisco → annet-3.22.0/annet/annlib/netdev/views}/__init__.py +0 -0
  227. {annet-0.13.4/annet/rulebook/huawei → annet-3.22.0/annet/annlib/rbparser}/__init__.py +0 -0
  228. {annet-0.13.4 → annet-3.22.0}/annet/annlib/rbparser/deploying.py +0 -0
  229. {annet-0.13.4/annet/rulebook/nexus → annet-3.22.0/annet/annlib/rulebook}/__init__.py +0 -0
  230. {annet-0.13.4 → annet-3.22.0}/annet/annlib/types.py +0 -0
  231. {annet-0.13.4/annet_generators → annet-3.22.0/annet/generators/common}/__init__.py +0 -0
  232. {annet-0.13.4 → annet-3.22.0}/annet/generators/common/initial.py +0 -0
  233. {annet-0.13.4 → annet-3.22.0}/annet/generators/exceptions.py +0 -0
  234. {annet-0.13.4 → annet-3.22.0}/annet/generators/ref.py +0 -0
  235. {annet-0.13.4 → annet-3.22.0}/annet/patching.py +0 -0
  236. {annet-0.13.4 → annet-3.22.0}/annet/reference.py +0 -0
  237. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/arista/iface.py +0 -0
  238. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/aruba/__init__.py +0 -0
  239. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/aruba/misc.py +0 -0
  240. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/cisco/vlandb.py +0 -0
  241. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/common.py +0 -0
  242. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/huawei/bgp.py +0 -0
  243. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/huawei/iface.py +0 -0
  244. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/huawei/misc.py +0 -0
  245. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/huawei/vlandb.py +0 -0
  246. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/nexus/iface.py +0 -0
  247. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/arista.deploy +0 -0
  248. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/aruba.deploy +0 -0
  249. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/aruba.order +0 -0
  250. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/aruba.rul +0 -0
  251. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/nexus.deploy +0 -0
  252. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/nexus.order +0 -0
  253. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/nokia.rul +0 -0
  254. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/pc.order +0 -0
  255. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/pc.rul +0 -0
  256. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/ribbon.deploy +0 -0
  257. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/ribbon.rul +0 -0
  258. {annet-0.13.4 → annet-3.22.0}/annet/rulebook/texts/routeros.rul +0 -0
  259. {annet-0.13.4 → annet-3.22.0}/annet/types.py +0 -0
  260. {annet-0.13.4 → annet-3.22.0}/annet.egg-info/dependency_links.txt +0 -0
  261. {annet-0.13.4 → annet-3.22.0}/annet.egg-info/top_level.txt +0 -0
  262. {annet-0.13.4 → annet-3.22.0}/setup.cfg +0 -0
@@ -1,10 +1,10 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: annet
3
- Version: 0.13.4
3
+ Version: 3.22.0
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
7
- Requires-Python: >=3.8
7
+ Requires-Python: >=3.10
8
8
  License-File: LICENSE
9
9
  License-File: AUTHORS
10
10
  Requires-Dist: colorama>=0.4.6
@@ -14,12 +14,20 @@ Requires-Dist: jsonpointer>=2.4
14
14
  Requires-Dist: PyYAML>=6.0.1
15
15
  Requires-Dist: Pygments>=2.14.0
16
16
  Requires-Dist: Mako>=1.2.4
17
- Requires-Dist: Jinja2>=3.1.2
18
- Requires-Dist: psutil>=5.8.0
19
17
  Requires-Dist: packaging>=23.2
20
18
  Requires-Dist: contextlog>=1.1
21
19
  Requires-Dist: valkit>=0.1.4
22
- Requires-Dist: aiohttp>=3.8.4
23
20
  Requires-Dist: yarl>=1.8.2
24
- Requires-Dist: adaptix==3.0.0b5
21
+ Requires-Dist: adaptix==3.0.0b7
25
22
  Requires-Dist: dataclass-rest==0.4
23
+ Requires-Dist: ordered-set>=4.1.0
24
+ Provides-Extra: netbox
25
+ Requires-Dist: annetbox[sync]>=0.9.0; extra == "netbox"
26
+ Requires-Dist: requests-cache>=1.2.1; extra == "netbox"
27
+ Dynamic: home-page
28
+ Dynamic: license
29
+ Dynamic: license-file
30
+ Dynamic: provides-extra
31
+ Dynamic: requires-dist
32
+ Dynamic: requires-python
33
+ Dynamic: summary
annet-3.22.0/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # Annet - configuration generation and deploying utility for network equipment
2
+
3
+ [![Telegram](https://img.shields.io/badge/💬-Telegram-blue)](https://t.me/annet_sup)
4
+ [![PyPI version](https://badge.fury.io/py/annet.svg)](https://pypi.python.org/pypi/annet)
5
+ [![Downloads](https://img.shields.io/pypi/dm/annet.svg)](https://pypistats.org/packages/annet)
6
+ [![License](https://img.shields.io/github/license/annetutil/annet)](https://github.com/annetutil/annet/blob/master/LICENSE)
7
+ [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/annetutil/annet/setup.yml)](https://github.com/annetutil/annet/actions)
8
+ [![Doc](https://img.shields.io/github/actions/workflow/status/annetutil/annet/docs.yaml?label=docs)](https://annetutil.github.io/annet)
9
+
10
+
11
+ Annet is a configuration generator that can translate differences between old and new configurations into sequence of commands. This feature is vital for CLI-based devices, such as Huawei, Cisco IOS, Cisco NX-OS, Juniper. Devices configured via separate config files, Linux, FreeBSD and Cumulus are also supported.
12
+
13
+ It works this way. Annet `gen`erates configuration for a device by running Python code, which usually goes to the Network Source of Truth, like NetBox. Annet then gets the `diff`erence by getting the configuration from the device and comparing it. Finally, Annet translates the difference into a sequence of commands, called a `patch`. After `deploy`ing these commands, the diff will be empty.
14
+
15
+ Annet has a number of modes (subcommands):
16
+
17
+ - ```annet gen``` - generates the entire config for the specified devices or specified parts of it
18
+ - ```annet diff``` - first does gen and then builds diff with current config version
19
+ - ```annet patch``` - first does diff and then generates a list of commands to apply diff on the device
20
+ - ```annet deploy``` - first does patch and then deploys it to the device
21
+
22
+ Usage help can be obtained by calling ```annet -h``` or for a specific command, such as ```annet gen -h```.
23
+
24
+ <img src="https://github.com/annetutil/annet/blob/main/docs/_static/annet_demo.gif?raw=true" width="800" />
25
+
26
+ ## Configuration
27
+
28
+ The path to the configuration file is searched in following order:
29
+ - `ANN_CONTEXT_CONFIG_PATH` env.
30
+ - `~/.annet/context.yml`.
31
+ - `annet/configs/context.yml`.
32
+
33
+ Config example:
34
+
35
+ ```yaml
36
+ generators:
37
+ default:
38
+ - my_annet_generators.example
39
+
40
+ storage:
41
+ default:
42
+ adapter: annet.adapters.file.provider
43
+ params:
44
+ path: /path/to/file
45
+
46
+ context:
47
+ default:
48
+ generators: default
49
+ storage: default
50
+
51
+ selected_context: default
52
+ ```
53
+
54
+ Environment variable `ANN_SELECTED_CONTEXT` can be used to override `selected_context` parameter.
55
+
56
+ ## Installation
57
+
58
+ Install from PyPI:
59
+ ```shell
60
+ pip install annet
61
+ ```
62
+
63
+ Or install from source:
64
+ ```shell
65
+ git clone https://github.com/annetutil/annet
66
+ cd annet
67
+ pip install -e .
68
+ ```
69
+
70
+ ## Building doc
71
+ 1. Install dependencies:
72
+ ```shell
73
+ pip install -r requirements-doc.txt
74
+ ```
75
+ 2. Build
76
+ ```shell
77
+ sphinx-build -M html docs docs-build
78
+ ```
79
+ 3. Open rendered html in browser
80
+ ```shell
81
+ open docs-build/html/index.html # macOS
82
+ xdg-open docs-build/html/index.html # Linux
83
+ start docs-build/html/index.html # Windows
84
+ ```
85
+
86
+ ## Links
87
+
88
+ * [Online Documentation](https://annetutil.github.io/annet/)
89
+ * [Tutorial](https://annetutil.github.io/annet/main/usage/tutorial.html)
@@ -7,14 +7,15 @@ from argparse import SUPPRESS, Namespace
7
7
 
8
8
  import colorama
9
9
  import yaml
10
- from annet.annlib.errors import ( # pylint: disable=wrong-import-position
11
- DeployCancelled,
12
- ExecError,
13
- )
14
10
  from contextlog import patch_logging, patch_threading
15
11
  from valkit.python import valid_logging_level
16
12
 
17
13
  import annet.argparse
14
+ from annet.vendors import tabparser # pylint: disable=unused-import
15
+ from annet.annlib.errors import ( # pylint: disable=wrong-import-position
16
+ DeployCancelled,
17
+ ExecError,
18
+ )
18
19
 
19
20
 
20
21
  __all__ = ("DeployCancelled", "ExecError")
@@ -49,13 +50,8 @@ def init(options: Namespace):
49
50
  colorama.init = lambda *_, **__: None
50
51
  colorama.init()
51
52
 
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
53
 
58
54
  def assert_python_version():
59
- if sys.version_info < (3, 8, 0):
60
- sys.stderr.write("Error: you need python 3.8.0 or higher\n")
55
+ if sys.version_info < (3, 10, 0):
56
+ sys.stderr.write("Error: you need python 3.10.0 or higher\n")
61
57
  sys.exit(1)
@@ -0,0 +1,25 @@
1
+ from annet.deploy import Fetcher
2
+ from annet.connectors import AdapterWithConfig
3
+ from typing import Dict, List, Any
4
+ from annet.storage import Device
5
+
6
+
7
+ class StubFetcher(Fetcher, AdapterWithConfig):
8
+ @classmethod
9
+ def with_config(cls, **kwargs: Dict[str, Any]) -> Fetcher:
10
+ return cls(**kwargs)
11
+
12
+ async def fetch_packages(self,
13
+ devices: list[Device],
14
+ processes: int = 1,
15
+ max_slots: int = 0,
16
+ ) -> tuple[dict[Device, str], dict[Device, Any]]:
17
+ raise NotImplementedError()
18
+
19
+ async def fetch(self,
20
+ devices: list[Device],
21
+ files_to_download: dict[str, list[str]] | None = None,
22
+ processes: int = 1,
23
+ max_slots: int = 0,
24
+ ):
25
+ raise NotImplementedError()
@@ -0,0 +1,280 @@
1
+ import dataclasses
2
+ from dataclasses import dataclass, fields
3
+ from typing import Any, Iterable, List, Optional, Sequence
4
+
5
+ import yaml
6
+
7
+ from annet.annlib.netdev.views.dump import DumpableView
8
+ from annet.annlib.netdev.views.hardware import HardwareView
9
+ from annet.connectors import AdapterWithName
10
+ from annet.hardware import hardware_connector
11
+ from annet.storage import Device as DeviceProtocol
12
+ from annet.storage import Query, Storage, StorageProvider
13
+ from annet.adapters.netbox.common.manufacturer import get_breed
14
+
15
+
16
+ @dataclass
17
+ class Interface(DumpableView):
18
+ name: str
19
+ description: str
20
+ enabled: bool = True
21
+
22
+ @property
23
+ def _dump__list_key(self):
24
+ return self.name
25
+
26
+
27
+ @dataclass
28
+ class DeviceStorage:
29
+ fqdn: str
30
+
31
+ vendor: Optional[str] = None
32
+ hw_model: Optional[str] = None
33
+ sw_version: Optional[str] = None
34
+ breed: Optional[str] = None
35
+
36
+ hostname: Optional[str] = None
37
+ serial: Optional[str] = None
38
+ id: Optional[str] = None
39
+ interfaces: Optional[list[Interface]] = None
40
+ storage: Optional[Storage] = None
41
+
42
+ hw: HardwareView = dataclasses.field(init=False)
43
+
44
+ def __post_init__(self):
45
+ if not self.id:
46
+ self.id = self.fqdn
47
+ if not self.hostname:
48
+ self.hostname = self.fqdn.split(".")[0]
49
+
50
+ if self.hw_model:
51
+ hw = HardwareView(self.hw_model, self.sw_version)
52
+ if self.vendor and self.vendor != hw.vendor:
53
+ raise Exception(f"Vendor {self.vendor} is not vendor from hw model ({hw.vendor})")
54
+ else:
55
+ self.vendor = hw.vendor
56
+ else:
57
+ hw_provider = hardware_connector.get()
58
+ hw: HardwareView = hw_provider.vendor_to_hw(self.vendor)
59
+ if not hw:
60
+ raise Exception("unknown vendor")
61
+ self.hw_model = hw.model
62
+ self.hw = hw
63
+
64
+ if not self.breed:
65
+ if self.hw.model:
66
+ parts = self.hw.model.split(maxsplit=1)
67
+ if len(parts) >= 2:
68
+ self.breed = get_breed(parts[0], parts[1])
69
+ if not self.breed:
70
+ self.breed = self.hw.vendor
71
+
72
+ if isinstance(self.interfaces, list):
73
+ interfaces = []
74
+ for iface in self.interfaces:
75
+ try:
76
+ interfaces.append(Interface(**iface))
77
+ except Exception as e:
78
+ raise Exception("unable to parse %s as Interface: %s" % (iface, e))
79
+ self.interfaces = interfaces
80
+
81
+ def set_storage(self, storage: Storage):
82
+ self.storage = storage
83
+
84
+
85
+ @dataclass
86
+ class Device(DeviceProtocol, DumpableView):
87
+ dev: DeviceStorage
88
+
89
+ def __hash__(self):
90
+ return hash((self.id, type(self)))
91
+
92
+ def __eq__(self, other):
93
+ return type(self) is type(other) and self.fqdn == other.fqdn and self.vendor == other.vendor
94
+
95
+ def is_pc(self) -> bool:
96
+ return False
97
+
98
+ @property
99
+ def hostname(self) -> str:
100
+ return self.dev.hostname
101
+
102
+ @property
103
+ def fqdn(self) -> str:
104
+ return self.dev.fqdn
105
+
106
+ @property
107
+ def id(self):
108
+ return self.dev.id
109
+
110
+ @property
111
+ def storage(self) -> Storage:
112
+ return self.dev.storage
113
+
114
+ @property
115
+ def hw(self) -> HardwareView:
116
+ return self.dev.hw
117
+
118
+ @property
119
+ def breed(self) -> str:
120
+ return self.dev.breed
121
+
122
+ @property
123
+ def neighbours_ids(self):
124
+ return []
125
+
126
+ @property
127
+ def neighbours_fqdns(self) -> list[str]:
128
+ return []
129
+
130
+ def make_lag(self, lag: int, ports: Sequence[str], lag_min_links: Optional[int]) -> Interface:
131
+ raise NotImplementedError
132
+
133
+ def add_svi(self, svi: int) -> Interface:
134
+ raise NotImplementedError
135
+
136
+ def add_subif(self, interface: str, subif: int) -> Interface:
137
+ raise NotImplementedError
138
+
139
+ def find_interface(self, name: str) -> Optional[Interface]:
140
+ raise NotImplementedError
141
+
142
+ def flush_perf(self):
143
+ pass
144
+
145
+
146
+ @dataclass
147
+ class Devices:
148
+ devices: list[Device]
149
+
150
+ def __post_init__(self):
151
+ if isinstance(self.devices, list):
152
+ devices = []
153
+ for dev in self.devices:
154
+ try:
155
+ devices.append(Device(dev=DeviceStorage(**dev)))
156
+ except Exception as e:
157
+ raise Exception("unable to parse %s as Device: %s" % (dev, e))
158
+ self.devices = devices
159
+
160
+
161
+ class Provider(StorageProvider, AdapterWithName):
162
+ def storage(self):
163
+ return storage_factory
164
+
165
+ def opts(self):
166
+ return StorageOpts
167
+
168
+ def query(self):
169
+ return Query
170
+
171
+ @classmethod
172
+ def name(cls) -> str:
173
+ return "file"
174
+
175
+
176
+ @dataclass
177
+ class Query(Query):
178
+ query: List[str]
179
+
180
+ @classmethod
181
+ def new(cls, query: str | Iterable[str], hosts_range: Optional[slice] = None) -> "Query":
182
+ if hosts_range is not None:
183
+ raise ValueError("host_range is not supported")
184
+ return cls(query=list(query))
185
+
186
+ @property
187
+ def globs(self):
188
+ return self.query
189
+
190
+ def is_empty(self) -> bool:
191
+ return len(self.query) == 0
192
+
193
+
194
+ class StorageOpts:
195
+ def __init__(self, path: str):
196
+ self.path = path
197
+
198
+ @classmethod
199
+ def parse_params(cls, conf_params: Optional[dict[str, str]], cli_opts: Any):
200
+ path = conf_params.get("path")
201
+ if not path:
202
+ raise Exception("empty path")
203
+ return cls(path=path)
204
+
205
+
206
+ def storage_factory(opts: StorageOpts) -> Storage:
207
+ return FS(opts)
208
+
209
+
210
+ class FS(Storage):
211
+ def __init__(self, opts: StorageOpts):
212
+ self.opts = opts
213
+ self.inventory: Devices = read_inventory(opts.path, self)
214
+
215
+ def __enter__(self):
216
+ return self
217
+
218
+ def __exit__(self, _, __, ___):
219
+ pass
220
+
221
+ def resolve_object_ids_by_query(self, query: Query) -> list[str]:
222
+ result = filter_query(self.inventory.devices, query)
223
+ return [dev.fqdn for dev in result]
224
+
225
+ def resolve_fdnds_by_query(self, query: Query) -> list[str]:
226
+ result = filter_query(self.inventory.devices, query)
227
+ return [dev.fqdn for dev in result]
228
+
229
+ def make_devices(
230
+ self,
231
+ query: Query | list,
232
+ preload_neighbors=False,
233
+ use_mesh=None,
234
+ preload_extra_fields=False,
235
+ **kwargs,
236
+ ) -> list[Device]:
237
+ if isinstance(query, list):
238
+ query = Query.new(query)
239
+ result = filter_query(self.inventory.devices, query)
240
+ return result
241
+
242
+ def get_device(self, obj_id: str, preload_neighbors=False, use_mesh=None, **kwargs) -> Device:
243
+ result = filter_query(self.inventory.devices, Query.new(obj_id))
244
+ if not result:
245
+ raise Exception("not found")
246
+ return result[0]
247
+
248
+ def flush_perf(self):
249
+ pass
250
+
251
+ def resolve_all_fdnds(self) -> list[str]:
252
+ return [d.fqdn for d in self.inventory.devices]
253
+
254
+ def search_connections(self, device: "Device", neighbor: "Device") -> list[tuple["Interface", "Interface"]]:
255
+ return []
256
+
257
+
258
+ def filter_query(devices: list[Device], query: Query) -> list[Device]:
259
+ result: list[Device] = []
260
+ for dev in devices:
261
+ if dev.fqdn in query.query:
262
+ result.append(dev)
263
+ return result
264
+
265
+
266
+ def read_inventory(path: str, storage: Storage) -> Devices:
267
+ with open(path, "r") as f:
268
+ file_data = yaml.load(f, Loader=yaml.SafeLoader)
269
+ res = dataclass_from_dict(Devices, file_data)
270
+ for dev in res.devices:
271
+ dev.dev.set_storage(storage)
272
+ return res
273
+
274
+
275
+ def dataclass_from_dict(klass: type, d: dict[str, Any]):
276
+ try:
277
+ fieldtypes = {f.name: f.type for f in fields(klass)}
278
+ except TypeError:
279
+ return d
280
+ return klass(**{f: dataclass_from_dict(fieldtypes[f], d[f]) for f in d})
@@ -0,0 +1,87 @@
1
+ from abc import abstractmethod, ABC
2
+ from typing import Generic, TypeVar
3
+
4
+ from annet.annlib.netdev.views.hardware import HardwareView
5
+ from .manufacturer import get_breed, get_hw
6
+ from .models import NetboxDevice, Interface, IpAddress, Prefix, \
7
+ FHRPGroupAssignment, FHRPGroup
8
+
9
+ NetboxDeviceT = TypeVar("NetboxDeviceT", bound=NetboxDevice)
10
+ InterfaceT = TypeVar("InterfaceT", bound=Interface)
11
+ IpAddressT = TypeVar("IpAddressT", bound=IpAddress)
12
+ PrefixT = TypeVar("PrefixT", bound=Prefix)
13
+ FHRPGroupT = TypeVar("FHRPGroupT", bound=FHRPGroup)
14
+ FHRPGroupAssignmentT = TypeVar(
15
+ "FHRPGroupAssignmentT", bound=FHRPGroupAssignment,
16
+ )
17
+
18
+
19
+ def get_device_breed(device: NetboxDeviceT) -> str:
20
+ if device.device_type and device.device_type.manufacturer:
21
+ return get_breed(
22
+ device.device_type.manufacturer.name,
23
+ device.device_type.model,
24
+ )
25
+ return ""
26
+
27
+
28
+ def get_device_hw(device: NetboxDeviceT) -> HardwareView:
29
+ if device.device_type and device.device_type.manufacturer:
30
+ return get_hw(
31
+ device.device_type.manufacturer.name,
32
+ device.device_type.model,
33
+ device.platform.name if device.platform else "",
34
+ )
35
+ return HardwareView("", "")
36
+
37
+
38
+ class NetboxAdapter(
39
+ ABC,
40
+ Generic[
41
+ NetboxDeviceT,
42
+ InterfaceT,
43
+ IpAddressT,
44
+ PrefixT,
45
+ FHRPGroupT,
46
+ FHRPGroupAssignmentT,
47
+ ],
48
+ ):
49
+ @abstractmethod
50
+ def list_fqdns(self, query: dict[str, list[str]] | None = None) -> list[str]:
51
+ raise NotImplementedError()
52
+
53
+ @abstractmethod
54
+ def list_devices(self, query: dict[str, list[str]]) -> list[NetboxDeviceT]:
55
+ raise NotImplementedError()
56
+
57
+ @abstractmethod
58
+ def get_device(self, device_id: int) -> NetboxDeviceT:
59
+ raise NotImplementedError()
60
+
61
+ @abstractmethod
62
+ def list_interfaces_by_devices(self, device_ids: list[int]) -> list[InterfaceT]:
63
+ raise NotImplementedError()
64
+
65
+ @abstractmethod
66
+ def list_interfaces(self, ids: list[int]) -> list[InterfaceT]:
67
+ raise NotImplementedError()
68
+
69
+ @abstractmethod
70
+ def list_ipaddr_by_ifaces(self, iface_ids: list[int]) -> list[IpAddressT]:
71
+ raise NotImplementedError()
72
+
73
+ @abstractmethod
74
+ def list_ipprefixes(self, prefixes: list[str]) -> list[PrefixT]:
75
+ raise NotImplementedError()
76
+
77
+ @abstractmethod
78
+ def list_fhrp_group_assignments(
79
+ self, iface_ids: list[int],
80
+ ) -> list[FHRPGroupAssignmentT]:
81
+ raise NotImplementedError()
82
+
83
+ @abstractmethod
84
+ def list_fhrp_groups(
85
+ self, ids: list[int],
86
+ ) -> list[FHRPGroupT]:
87
+ raise NotImplementedError()
@@ -79,9 +79,11 @@ def collect(func: Func, field: str = "", batch_size: int = 100) -> Func:
79
79
 
80
80
 
81
81
  class BaseNetboxClient(RequestsClient):
82
- def __init__(self, url: str, token: str):
82
+ def __init__(self, url: str, token: str, insecure: bool = False):
83
83
  url = url.rstrip("/") + "/api/"
84
84
  session = Session()
85
+ if insecure:
86
+ session.verify = False
85
87
  if token:
86
88
  session.headers["Authorization"] = f"Token {token}"
87
89
  super().__init__(url, session)
@@ -0,0 +1,44 @@
1
+ from logging import getLogger
2
+
3
+ from annet.annlib.netdev.views.hardware import HardwareView
4
+
5
+ logger = getLogger(__name__)
6
+
7
+
8
+ def get_hw(manufacturer: str, model: str, platform_name: str):
9
+ # By some reason Netbox calls Mellanox SN as MSN, so we fix them here
10
+ if manufacturer == "Mellanox" and model.startswith("MSN"):
11
+ model = model.replace("MSN", "SN", 1)
12
+
13
+ return HardwareView(manufacturer + " " + model, platform_name)
14
+
15
+
16
+ def get_breed(manufacturer: str, model: str):
17
+ hw = get_hw(manufacturer, model, "")
18
+ if hw.Huawei.CE:
19
+ return "vrp85"
20
+ elif hw.Huawei.NE:
21
+ return "vrp85"
22
+ elif hw.Huawei:
23
+ return "vrp55"
24
+ elif hw.H3C:
25
+ return "h3c"
26
+ elif hw.PC.NVIDIA or hw.PC.Mellanox:
27
+ return "cuml2"
28
+ elif hw.Juniper:
29
+ return "jun10"
30
+ elif hw.Cisco.Nexus:
31
+ return "nxos"
32
+ elif hw.Cisco:
33
+ return "ios12"
34
+ elif hw.Arista:
35
+ return "eos4"
36
+ elif hw.B4com:
37
+ return "bcom-os"
38
+ elif hw.RouterOS:
39
+ return "routeros"
40
+ elif hw.PC.Moxa or hw.PC.Nebius:
41
+ return "moxa"
42
+ elif hw.PC:
43
+ return "pc"
44
+ return ""