nautobot 2.0.5__py3-none-any.whl → 2.1.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nautobot might be problematic. Click here for more details.

Files changed (376) hide show
  1. nautobot/circuits/navigation.py +0 -25
  2. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -9
  3. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
  4. nautobot/circuits/tests/test_filters.py +1 -0
  5. nautobot/core/api/serializers.py +15 -5
  6. nautobot/core/api/views.py +18 -19
  7. nautobot/core/choices.py +1 -1
  8. nautobot/core/filters.py +12 -4
  9. nautobot/core/jobs/__init__.py +125 -3
  10. nautobot/core/management/commands/generate_test_data.py +4 -1
  11. nautobot/core/models/fields.py +12 -2
  12. nautobot/core/settings.py +8 -7
  13. nautobot/core/templates/base_django.html +2 -2
  14. nautobot/core/templates/buttons/export.html +57 -30
  15. nautobot/core/templates/generic/object_list.html +2 -2
  16. nautobot/core/templates/generic/object_retrieve.html +8 -1
  17. nautobot/core/templates/home.html +5 -5
  18. nautobot/core/templates/inc/created_updated.html +2 -2
  19. nautobot/core/templates/inc/footer.html +2 -2
  20. nautobot/core/templates/inc/javascript.html +0 -10
  21. nautobot/core/templates/inc/media.html +2 -0
  22. nautobot/core/templates/inc/nav_menu.html +66 -68
  23. nautobot/core/templates/inc/object_details_advanced_panel.html +19 -0
  24. nautobot/core/templates/nautobot_config.py.j2 +10 -4
  25. nautobot/core/templates/panel_table.html +1 -1
  26. nautobot/core/templates/template.css +89 -0
  27. nautobot/core/templates/utilities/templatetags/table_config_form.html +1 -0
  28. nautobot/core/templatetags/buttons.py +7 -2
  29. nautobot/core/testing/views.py +34 -4
  30. nautobot/core/tests/integration/test_home.py +1 -43
  31. nautobot/core/tests/integration/test_navbar.py +10 -64
  32. nautobot/core/tests/integration/test_plugin_home.py +4 -5
  33. nautobot/core/tests/integration/test_plugin_navbar.py +20 -16
  34. nautobot/core/tests/integration/test_theme.py +4 -0
  35. nautobot/core/tests/test_api.py +14 -66
  36. nautobot/core/tests/test_filters.py +127 -0
  37. nautobot/core/tests/test_forms.py +1 -1
  38. nautobot/core/tests/test_graphql.py +165 -2
  39. nautobot/core/tests/test_jobs.py +112 -0
  40. nautobot/core/tests/test_openapi.py +6 -0
  41. nautobot/core/tests/test_views.py +11 -85
  42. nautobot/core/urls.py +6 -1
  43. nautobot/core/utils/lookup.py +28 -0
  44. nautobot/core/utils/requests.py +2 -3
  45. nautobot/core/views/__init__.py +3 -4
  46. nautobot/core/views/generic.py +9 -4
  47. nautobot/core/views/mixins.py +4 -2
  48. nautobot/core/views/renderers.py +5 -0
  49. nautobot/dcim/models/device_components.py +1 -0
  50. nautobot/dcim/navigation.py +10 -165
  51. nautobot/dcim/templates/dcim/location.html +1 -1
  52. nautobot/dcim/tests/features/locations.feature +143 -0
  53. nautobot/dcim/tests/test_api.py +1 -1
  54. nautobot/dcim/tests/test_filters.py +11 -3
  55. nautobot/extras/admin.py +1 -1
  56. nautobot/extras/api/serializers.py +33 -0
  57. nautobot/extras/api/urls.py +6 -0
  58. nautobot/extras/api/views.py +45 -6
  59. nautobot/extras/factory.py +28 -2
  60. nautobot/extras/filters/__init__.py +52 -0
  61. nautobot/extras/filters/mixins.py +4 -29
  62. nautobot/extras/forms/forms.py +43 -0
  63. nautobot/extras/jobs.py +31 -9
  64. nautobot/extras/migrations/0100_fileproxy_job_result.py +32 -0
  65. nautobot/extras/migrations/0101_externalintegration.py +61 -0
  66. nautobot/extras/migrations/0102_set_null_objectchange_contenttype.py +32 -0
  67. nautobot/extras/models/__init__.py +2 -0
  68. nautobot/extras/models/change_logging.py +2 -2
  69. nautobot/extras/models/models.py +96 -16
  70. nautobot/extras/navigation.py +17 -29
  71. nautobot/extras/signals.py +15 -0
  72. nautobot/extras/tables.py +27 -0
  73. nautobot/extras/templates/extras/externalintegration_retrieve.html +37 -0
  74. nautobot/extras/templates/extras/inc/jobresult.html +24 -0
  75. nautobot/extras/templates/extras/jobresult.html +24 -0
  76. nautobot/extras/test_jobs/file_output.py +16 -0
  77. nautobot/extras/tests/test_api.py +92 -0
  78. nautobot/extras/tests/test_filters.py +64 -2
  79. nautobot/extras/tests/test_jobs.py +39 -0
  80. nautobot/extras/tests/test_models.py +34 -0
  81. nautobot/extras/tests/test_views.py +22 -2
  82. nautobot/extras/urls.py +1 -0
  83. nautobot/extras/views.py +15 -0
  84. nautobot/ipam/forms.py +16 -0
  85. nautobot/ipam/models.py +3 -0
  86. nautobot/ipam/navigation.py +2 -59
  87. nautobot/ipam/templates/ipam/ipaddress.html +0 -9
  88. nautobot/ipam/templates/ipam/prefix.html +0 -9
  89. nautobot/ipam/tests/features/prefixes.feature +134 -0
  90. nautobot/ipam/tests/test_filters.py +5 -10
  91. nautobot/ipam/tests/test_views.py +8 -1
  92. nautobot/ipam/views.py +3 -0
  93. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css +191 -191
  94. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
  95. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css +1 -1
  96. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
  97. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +874 -881
  98. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
  99. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
  100. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
  101. nautobot/project-static/css/base.css +135 -99
  102. nautobot/project-static/css/dark.css +65 -6
  103. nautobot/project-static/docs/404.html +44 -16
  104. nautobot/project-static/docs/apps/index.html +44 -16
  105. nautobot/project-static/docs/apps/nautobot-apps.html +44 -16
  106. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +44 -16
  107. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +44 -16
  108. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1597 -1457
  109. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +44 -16
  110. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +45 -17
  111. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +44 -16
  112. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +44 -16
  113. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +44 -16
  114. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +44 -16
  115. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +353 -432
  116. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +66 -38
  117. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +44 -16
  118. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2154 -2307
  119. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +807 -691
  120. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +44 -16
  121. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +44 -16
  122. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +58 -30
  123. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +3600 -3456
  124. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +44 -16
  125. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +44 -16
  126. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +101 -75
  127. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +3083 -3019
  128. nautobot/project-static/docs/development/apps/api/configuration-view.html +44 -16
  129. nautobot/project-static/docs/development/apps/api/database-backend-config.html +44 -16
  130. nautobot/project-static/docs/development/apps/api/models/django-admin.html +44 -16
  131. nautobot/project-static/docs/development/apps/api/models/global-search.html +44 -16
  132. nautobot/project-static/docs/development/apps/api/models/graphql.html +44 -16
  133. nautobot/project-static/docs/development/apps/api/models/index.html +44 -16
  134. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +44 -16
  135. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +44 -16
  136. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +44 -16
  137. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +44 -16
  138. nautobot/project-static/docs/development/apps/api/platform-features/index.html +44 -16
  139. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +44 -16
  140. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +44 -16
  141. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +44 -16
  142. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +44 -16
  143. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +44 -16
  144. nautobot/project-static/docs/development/apps/api/prometheus.html +44 -16
  145. nautobot/project-static/docs/development/apps/api/setup.html +44 -16
  146. nautobot/project-static/docs/development/apps/api/testing.html +44 -16
  147. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +44 -16
  148. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +44 -16
  149. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +44 -16
  150. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +44 -16
  151. nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +44 -16
  152. nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +44 -16
  153. nautobot/project-static/docs/development/apps/api/views/base-template.html +44 -16
  154. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +44 -16
  155. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +44 -16
  156. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +44 -16
  157. nautobot/project-static/docs/development/apps/api/views/index.html +44 -16
  158. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +44 -16
  159. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +44 -16
  160. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +44 -16
  161. nautobot/project-static/docs/development/apps/api/views/notes.html +44 -16
  162. nautobot/project-static/docs/development/apps/api/views/rest-api.html +44 -16
  163. nautobot/project-static/docs/development/apps/api/views/urls.html +44 -16
  164. nautobot/project-static/docs/development/apps/api/views/view-overrides.html +44 -16
  165. nautobot/project-static/docs/development/apps/index.html +44 -16
  166. nautobot/project-static/docs/development/apps/migration/code-updates.html +44 -16
  167. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +44 -16
  168. nautobot/project-static/docs/development/apps/migration/from-v1.html +44 -16
  169. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +44 -16
  170. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +44 -16
  171. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +44 -16
  172. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +44 -16
  173. nautobot/project-static/docs/development/apps/porting-from-netbox.html +44 -16
  174. nautobot/project-static/docs/development/core/application-registry.html +44 -16
  175. nautobot/project-static/docs/development/core/best-practices.html +44 -16
  176. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +44 -16
  177. nautobot/project-static/docs/development/core/extending-models.html +44 -16
  178. nautobot/project-static/docs/development/core/generic-views.html +44 -16
  179. nautobot/project-static/docs/development/core/getting-started.html +44 -16
  180. nautobot/project-static/docs/development/core/homepage.html +44 -16
  181. nautobot/project-static/docs/development/core/index.html +44 -16
  182. nautobot/project-static/docs/development/core/model-features.html +44 -16
  183. nautobot/project-static/docs/development/core/natural-keys.html +44 -16
  184. nautobot/project-static/docs/development/core/navigation-menu.html +44 -21
  185. nautobot/project-static/docs/development/core/react-ui.html +44 -16
  186. nautobot/project-static/docs/development/core/release-checklist.html +44 -16
  187. nautobot/project-static/docs/development/core/role-internals.html +44 -16
  188. nautobot/project-static/docs/development/core/style-guide.html +44 -16
  189. nautobot/project-static/docs/development/core/templates.html +44 -16
  190. nautobot/project-static/docs/development/core/testing.html +44 -16
  191. nautobot/project-static/docs/development/core/user-preferences.html +44 -16
  192. nautobot/project-static/docs/development/index.html +44 -16
  193. nautobot/project-static/docs/development/jobs/index.html +280 -234
  194. nautobot/project-static/docs/development/jobs/migration/from-v1.html +44 -16
  195. nautobot/project-static/docs/index.html +44 -16
  196. nautobot/project-static/docs/objects.inv +0 -0
  197. nautobot/project-static/docs/release-notes/index.html +47 -19
  198. nautobot/project-static/docs/release-notes/version-1.0.html +44 -16
  199. nautobot/project-static/docs/release-notes/version-1.1.html +44 -16
  200. nautobot/project-static/docs/release-notes/version-1.2.html +44 -16
  201. nautobot/project-static/docs/release-notes/version-1.3.html +44 -16
  202. nautobot/project-static/docs/release-notes/version-1.4.html +44 -16
  203. nautobot/project-static/docs/release-notes/version-1.5.html +44 -16
  204. nautobot/project-static/docs/release-notes/version-1.6.html +44 -16
  205. nautobot/project-static/docs/release-notes/version-2.0.html +47 -19
  206. nautobot/project-static/docs/release-notes/version-2.1.html +5724 -0
  207. nautobot/project-static/docs/search/search_index.json +1 -1
  208. nautobot/project-static/docs/sitemap.xml +247 -237
  209. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  210. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +44 -16
  211. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +44 -16
  212. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +44 -16
  213. nautobot/project-static/docs/user-guide/administration/configuration/index.html +44 -16
  214. nautobot/project-static/docs/user-guide/administration/configuration/node-configuration.html +44 -16
  215. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +109 -43
  216. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +44 -16
  217. nautobot/project-static/docs/user-guide/administration/guides/caching.html +44 -16
  218. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +44 -16
  219. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +44 -16
  220. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +44 -16
  221. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +44 -16
  222. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +44 -16
  223. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +48 -19
  224. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +44 -16
  225. nautobot/project-static/docs/user-guide/administration/installation/docker.html +44 -16
  226. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +44 -16
  227. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +44 -16
  228. nautobot/project-static/docs/user-guide/administration/installation/index.html +44 -16
  229. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +44 -16
  230. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +44 -16
  231. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +44 -16
  232. nautobot/project-static/docs/user-guide/administration/installation/services.html +44 -16
  233. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +44 -16
  234. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +44 -16
  235. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +44 -16
  236. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +44 -16
  237. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +44 -16
  238. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +44 -16
  239. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +44 -16
  240. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +44 -16
  241. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +44 -16
  242. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +44 -16
  243. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +44 -16
  244. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +44 -16
  245. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +44 -16
  246. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +44 -16
  247. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +44 -16
  248. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +44 -16
  249. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +44 -16
  250. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +44 -16
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +44 -16
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +44 -16
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +44 -16
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +44 -16
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +44 -16
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +44 -16
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +44 -16
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +44 -16
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +44 -16
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +44 -16
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +44 -16
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +44 -16
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +44 -16
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +44 -16
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +44 -16
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +44 -16
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +44 -16
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +44 -16
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +44 -16
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +44 -16
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +44 -16
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +44 -16
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +44 -16
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +44 -16
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +44 -16
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +44 -16
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +44 -16
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +44 -16
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +44 -16
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +44 -16
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +44 -16
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +44 -16
  283. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +44 -16
  284. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +44 -16
  285. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +44 -16
  286. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +44 -16
  287. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +44 -16
  288. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +44 -16
  289. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +44 -16
  290. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +44 -16
  291. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +44 -16
  292. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +44 -16
  293. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +44 -16
  294. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +44 -16
  295. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +44 -16
  296. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +44 -16
  297. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +44 -16
  298. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +44 -16
  299. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +44 -16
  300. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +44 -16
  301. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +44 -16
  302. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +44 -16
  303. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +44 -16
  304. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +44 -16
  305. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +44 -16
  306. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +44 -16
  307. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +44 -16
  308. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +44 -16
  309. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +44 -16
  310. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +44 -16
  311. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +44 -16
  312. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +44 -16
  313. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +44 -16
  314. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +44 -16
  315. nautobot/project-static/docs/user-guide/index.html +44 -16
  316. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +110 -16
  317. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +44 -16
  318. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +44 -16
  319. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +44 -16
  320. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +44 -16
  321. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +47 -19
  322. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +5359 -0
  323. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +47 -19
  324. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +44 -16
  325. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +44 -16
  326. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +44 -16
  327. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +44 -16
  328. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +44 -16
  329. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +44 -16
  330. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +44 -16
  331. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +44 -16
  332. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +44 -16
  333. nautobot/project-static/docs/user-guide/platform-functionality/note.html +44 -16
  334. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +44 -16
  335. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +44 -16
  336. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +113 -44
  337. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +44 -16
  338. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +44 -16
  339. nautobot/project-static/docs/user-guide/platform-functionality/role.html +44 -16
  340. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +44 -16
  341. nautobot/project-static/docs/user-guide/platform-functionality/status.html +44 -16
  342. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +44 -16
  343. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +44 -16
  344. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +44 -16
  345. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +44 -16
  346. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +44 -16
  347. nautobot/project-static/fonts/UFL.txt +96 -0
  348. nautobot/project-static/fonts/Ubuntu-Bold.woff2 +0 -0
  349. nautobot/project-static/fonts/Ubuntu-BoldItalic.woff2 +0 -0
  350. nautobot/project-static/fonts/Ubuntu-Italic.woff2 +0 -0
  351. nautobot/project-static/fonts/Ubuntu-Medium.woff2 +0 -0
  352. nautobot/project-static/fonts/Ubuntu-MediumItalic.woff2 +0 -0
  353. nautobot/project-static/fonts/Ubuntu-Regular.woff2 +0 -0
  354. nautobot/project-static/fonts/UbuntuMono-Bold.woff2 +0 -0
  355. nautobot/project-static/fonts/UbuntuMono-BoldItalic.woff2 +0 -0
  356. nautobot/project-static/fonts/UbuntuMono-Italic.woff2 +0 -0
  357. nautobot/project-static/fonts/UbuntuMono-Regular.woff2 +0 -0
  358. nautobot/project-static/img/dark-theme.png +0 -0
  359. nautobot/project-static/img/light-theme.png +0 -0
  360. nautobot/project-static/img/nautobot_chevron.svg +5 -0
  361. nautobot/project-static/img/nautobot_chevron_header.svg +5 -0
  362. nautobot/project-static/img/system-theme.png +0 -0
  363. nautobot/tenancy/navigation.py +0 -13
  364. nautobot/ui/package-lock.json +2 -2
  365. nautobot/ui/package.json +1 -1
  366. nautobot/users/admin.py +44 -0
  367. nautobot/users/migrations/0007_alter_objectpermission_object_types.py +33 -0
  368. nautobot/users/models.py +3 -2
  369. nautobot/virtualization/navigation.py +1 -33
  370. nautobot/virtualization/tests/test_api.py +1 -1
  371. nautobot/virtualization/tests/test_filters.py +1 -1
  372. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/METADATA +1 -1
  373. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/RECORD +376 -351
  374. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/LICENSE.txt +0 -0
  375. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/WHEEL +0 -0
  376. {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/entry_points.txt +0 -0
@@ -7,6 +7,7 @@ from unittest import mock
7
7
  import uuid
8
8
  import tempfile
9
9
 
10
+ from django.conf import settings
10
11
  from django.contrib.contenttypes.models import ContentType
11
12
  from django.core.files.uploadedfile import SimpleUploadedFile
12
13
  from django.core.management import call_command
@@ -582,6 +583,44 @@ class JobFileUploadTest(TransactionTestCase):
582
583
  self.assertEqual(models.FileProxy.objects.count(), 0)
583
584
 
584
585
 
586
+ class JobFileOutputTest(TransactionTestCase):
587
+ """Test a job that outputs files."""
588
+
589
+ databases = ("default", "job_logs")
590
+
591
+ @override_settings(
592
+ MEDIA_ROOT=tempfile.gettempdir(),
593
+ )
594
+ def test_output_file_to_database(self):
595
+ module = "file_output"
596
+ name = "FileOutputJob"
597
+ data = {"lines": 3}
598
+ job_result = create_job_result_and_run_job(module, name, **data)
599
+
600
+ self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_SUCCESS, job_result.traceback)
601
+ # JobResult should have one attached file
602
+ self.assertEqual(1, job_result.files.count())
603
+ self.assertEqual(job_result.files.first().name, "output.txt")
604
+ self.assertEqual(job_result.files.first().file.read().decode("utf-8"), "Hello World!\n" * 3)
605
+ # File shouldn't exist on filesystem
606
+ self.assertFalse(Path(settings.MEDIA_ROOT, "files", "output.txt").exists())
607
+ self.assertFalse(Path(settings.MEDIA_ROOT, "files", f"{job_result.files.first().pk}-output.txt").exists())
608
+ # File should exist in DB
609
+ # `filename` value is weird, see https://github.com/victor-o-silva/db_file_storage/issues/22
610
+ models.FileAttachment.objects.get(filename="extras.FileAttachment/bytes/filename/mimetype/output.txt")
611
+
612
+ # Make sure cleanup is successful
613
+ job_result.delete()
614
+ with self.assertRaises(models.FileProxy.DoesNotExist):
615
+ models.FileProxy.objects.get(name="output.txt")
616
+ with self.assertRaises(models.FileAttachment.DoesNotExist):
617
+ models.FileAttachment.objects.get(filename="extras.FileAttachment/bytes/filename/mimetype/output.txt")
618
+
619
+ # It would be great to also test the output-to-filesystem case when using JOB_FILE_IO_STORAGE=FileSystemStorage;
620
+ # unfortunately with FileField(storage=callable), the callable gets evaluated only at declaration time, not at
621
+ # usage/runtime, so override_settings(JOB_FILE_IO_STORAGE) doesn't work the way you'd hope it would.
622
+
623
+
585
624
  class RunJobManagementCommandTest(TransactionTestCase):
586
625
  """Test cases for the `nautobot-server runjob` management command."""
587
626
 
@@ -48,6 +48,7 @@ from nautobot.extras.models import (
48
48
  ConfigContextSchema,
49
49
  DynamicGroup,
50
50
  ExportTemplate,
51
+ ExternalIntegration,
51
52
  FileAttachment,
52
53
  FileProxy,
53
54
  GitRepository,
@@ -776,6 +777,39 @@ class ExportTemplateTest(ModelTestCases.BaseModelTestCase):
776
777
  nonduplicate_template.validated_save()
777
778
 
778
779
 
780
+ class ExternalIntegrationTest(ModelTestCases.BaseModelTestCase):
781
+ """
782
+ Tests for the ExternalIntegration model class.
783
+ """
784
+
785
+ model = ExternalIntegration
786
+
787
+ def test_remote_url_validation(self):
788
+ with self.assertRaises(ValidationError):
789
+ ei = ExternalIntegration(
790
+ name="Test Integration",
791
+ remote_url="foo://localhost",
792
+ )
793
+ ei.validated_save()
794
+
795
+ ei.remote_url = "http://localhost"
796
+ ei.validated_save()
797
+
798
+ def test_timeout_validation(self):
799
+ with self.assertRaises(ValidationError):
800
+ ei = ExternalIntegration(
801
+ name="Test Integration",
802
+ remote_url="http://localhost",
803
+ timeout=-1,
804
+ )
805
+ ei.validated_save()
806
+
807
+ ei.timeout = 0
808
+ ei.validated_save()
809
+ ei.timeout = 65536
810
+ ei.validated_save()
811
+
812
+
779
813
  class FileProxyTest(ModelTestCases.BaseModelTestCase):
780
814
  model = FileProxy
781
815
 
@@ -33,6 +33,7 @@ from nautobot.extras.models import (
33
33
  CustomLink,
34
34
  DynamicGroup,
35
35
  ExportTemplate,
36
+ ExternalIntegration,
36
37
  GitRepository,
37
38
  GraphQLQuery,
38
39
  Job,
@@ -693,6 +694,25 @@ class ExportTemplateTestCase(
693
694
  }
694
695
 
695
696
 
697
+ class ExternalIntegrationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
698
+ model = ExternalIntegration
699
+ bulk_edit_data = {"timeout": 10, "verify_ssl": True, "extra_config": r"{}"}
700
+ csv_data = (
701
+ "name,remote_url,verify_ssl,timeout",
702
+ "Test External Integration 1,https://example.com/test1/,False,10",
703
+ "Test External Integration 2,https://example.com/test2/,True,20",
704
+ "Test External Integration 3,https://example.com/test3/,False,30",
705
+ )
706
+ form_data = {
707
+ "name": "Test External Integration",
708
+ "remote_url": "https://example.com/test1/",
709
+ "verify_ssl": False,
710
+ "secrets_group": None,
711
+ "timeout": 10,
712
+ "extra_config": '{"foo": "bar"}',
713
+ }
714
+
715
+
696
716
  class GitRepositoryTestCase(
697
717
  ViewTestCases.BulkDeleteObjectsViewTestCase,
698
718
  ViewTestCases.BulkImportObjectsViewTestCase,
@@ -1936,7 +1956,7 @@ class JobTestCase(
1936
1956
  content = extract_page_body(response.content.decode(response.charset))
1937
1957
 
1938
1958
  self.assertHttpStatus(response, 200)
1939
- self.assertIn(f"<h1>{instance.name} - Change Log</h1>", content)
1959
+ self.assertIn(f"{instance.name} - Change Log", content)
1940
1960
 
1941
1961
 
1942
1962
  class JobButtonTestCase(
@@ -2281,7 +2301,7 @@ class RelationshipAssociationTestCase(
2281
2301
  ),
2282
2302
  )
2283
2303
  vlan_status = Status.objects.get_for_model(VLAN).first()
2284
- vlan_group = VLANGroup.objects.first()
2304
+ vlan_group = VLANGroup.objects.create(name="Test VLANGroup 1")
2285
2305
  vlans = (
2286
2306
  VLAN.objects.create(vid=1, name="VLAN 1", status=vlan_status, vlan_group=vlan_group),
2287
2307
  VLAN.objects.create(vid=2, name="VLAN 2", status=vlan_status, vlan_group=vlan_group),
nautobot/extras/urls.py CHANGED
@@ -26,6 +26,7 @@ from nautobot.extras.models import (
26
26
  app_name = "extras"
27
27
 
28
28
  router = NautobotUIViewSetRouter()
29
+ router.register("external-integrations", views.ExternalIntegrationUIViewSet)
29
30
  router.register("job-buttons", views.JobButtonUIViewSet)
30
31
  router.register("roles", views.RoleUIViewSet)
31
32
 
nautobot/extras/views.py CHANGED
@@ -58,6 +58,7 @@ from .models import (
58
58
  CustomLink,
59
59
  DynamicGroup,
60
60
  ExportTemplate,
61
+ ExternalIntegration,
61
62
  GitRepository,
62
63
  GraphQLQuery,
63
64
  ImageAttachment,
@@ -792,6 +793,20 @@ class ExportTemplateBulkDeleteView(generic.BulkDeleteView):
792
793
  table = tables.ExportTemplateTable
793
794
 
794
795
 
796
+ #
797
+ # External integrations
798
+ #
799
+
800
+
801
+ class ExternalIntegrationUIViewSet(NautobotUIViewSet):
802
+ bulk_update_form_class = forms.ExternalIntegrationBulkEditForm
803
+ filterset_class = filters.ExternalIntegrationFilterSet
804
+ form_class = forms.ExternalIntegrationForm
805
+ queryset = ExternalIntegration.objects.select_related("secrets_group")
806
+ serializer_class = serializers.ExternalIntegrationSerializer
807
+ table_class = tables.ExternalIntegrationTable
808
+
809
+
795
810
  #
796
811
  # Git repositories
797
812
  #
nautobot/ipam/forms.py CHANGED
@@ -75,6 +75,22 @@ class NamespaceForm(LocatableModelFormMixin, NautobotModelForm):
75
75
  fields = ["name", "description", "location"]
76
76
 
77
77
 
78
+ class NamespaceBulkEditForm(
79
+ TagsBulkEditFormMixin,
80
+ LocatableModelBulkEditFormMixin,
81
+ NautobotBulkEditForm,
82
+ ):
83
+ pk = forms.ModelMultipleChoiceField(queryset=Namespace.objects.all(), widget=forms.MultipleHiddenInput())
84
+ description = forms.CharField(max_length=200, required=False)
85
+
86
+ class Meta:
87
+ model = Namespace
88
+ nullable_fields = [
89
+ "description",
90
+ "location",
91
+ ]
92
+
93
+
78
94
  #
79
95
  # VRFs
80
96
  #
nautobot/ipam/models.py CHANGED
@@ -257,6 +257,7 @@ class VRF(PrimaryModel):
257
257
  return instance.delete()
258
258
 
259
259
 
260
+ @extras_features("graphql")
260
261
  class VRFDeviceAssignment(BaseModel):
261
262
  vrf = models.ForeignKey("ipam.VRF", on_delete=models.CASCADE, related_name="device_assignments")
262
263
  device = models.ForeignKey(
@@ -306,6 +307,7 @@ class VRFDeviceAssignment(BaseModel):
306
307
  raise ValidationError("A VRF must be associated with either a device or a virtual machine.")
307
308
 
308
309
 
310
+ @extras_features("graphql")
309
311
  class VRFPrefixAssignment(BaseModel):
310
312
  vrf = models.ForeignKey("ipam.VRF", on_delete=models.CASCADE, related_name="+")
311
313
  prefix = models.ForeignKey("ipam.Prefix", on_delete=models.CASCADE, related_name="vrf_assignments")
@@ -1189,6 +1191,7 @@ class IPAddress(PrimaryModel):
1189
1191
  return f"Multiple IPAddress objects specify this object (pk: {self.obj.pk}) as nat_inside. Please refer to nat_outside_list."
1190
1192
 
1191
1193
 
1194
+ @extras_features("graphql")
1192
1195
  class IPAddressToInterface(BaseModel):
1193
1196
  ip_address = models.ForeignKey("ipam.IPAddress", on_delete=models.CASCADE, related_name="+")
1194
1197
  interface = models.ForeignKey(
@@ -5,7 +5,6 @@ from nautobot.core.apps import (
5
5
  NavMenuAddButton,
6
6
  NavMenuGroup,
7
7
  NavMenuItem,
8
- NavMenuImportButton,
9
8
  NavMenuTab,
10
9
  )
11
10
 
@@ -33,12 +32,6 @@ menu_items = (
33
32
  "ipam.add_ipaddress",
34
33
  ],
35
34
  ),
36
- NavMenuImportButton(
37
- link="ipam:ipaddress_import",
38
- permissions=[
39
- "ipam.add_ipaddress",
40
- ],
41
- ),
42
35
  ),
43
36
  ),
44
37
  NavMenuItem(
@@ -48,14 +41,7 @@ menu_items = (
48
41
  permissions=[
49
42
  "ipam.add_ipaddresstointerface",
50
43
  ],
51
- buttons=(
52
- NavMenuImportButton(
53
- link="ipam:ipaddresstointerface_import",
54
- permissions=[
55
- "ipam.add_ipaddresstointerface",
56
- ],
57
- ),
58
- ),
44
+ buttons=(),
59
45
  ),
60
46
  ),
61
47
  ),
@@ -77,12 +63,6 @@ menu_items = (
77
63
  "ipam.add_prefix",
78
64
  ],
79
65
  ),
80
- NavMenuImportButton(
81
- link="ipam:prefix_import",
82
- permissions=[
83
- "ipam.add_prefix",
84
- ],
85
- ),
86
66
  ),
87
67
  ),
88
68
  ),
@@ -105,12 +85,6 @@ menu_items = (
105
85
  "ipam.add_rir",
106
86
  ],
107
87
  ),
108
- NavMenuImportButton(
109
- link="ipam:rir_import",
110
- permissions=[
111
- "ipam.add_rir",
112
- ],
113
- ),
114
88
  ),
115
89
  ),
116
90
  ),
@@ -149,12 +123,6 @@ menu_items = (
149
123
  "ipam.add_vrf",
150
124
  ],
151
125
  ),
152
- NavMenuImportButton(
153
- link="ipam:vrf_import",
154
- permissions=[
155
- "ipam.add_vrf",
156
- ],
157
- ),
158
126
  ),
159
127
  ),
160
128
  NavMenuItem(
@@ -171,12 +139,6 @@ menu_items = (
171
139
  "ipam.add_routetarget",
172
140
  ],
173
141
  ),
174
- NavMenuImportButton(
175
- link="ipam:routetarget_import",
176
- permissions=[
177
- "ipam.add_routetarget",
178
- ],
179
- ),
180
142
  ),
181
143
  ),
182
144
  ),
@@ -199,12 +161,6 @@ menu_items = (
199
161
  "ipam.add_vlan",
200
162
  ],
201
163
  ),
202
- NavMenuImportButton(
203
- link="ipam:vlan_import",
204
- permissions=[
205
- "ipam.add_vlan",
206
- ],
207
- ),
208
164
  ),
209
165
  ),
210
166
  NavMenuItem(
@@ -221,12 +177,6 @@ menu_items = (
221
177
  "ipam.add_vlangroup",
222
178
  ],
223
179
  ),
224
- NavMenuImportButton(
225
- link="ipam:vlangroup_import",
226
- permissions=[
227
- "ipam.add_vlangroup",
228
- ],
229
- ),
230
180
  ),
231
181
  ),
232
182
  ),
@@ -242,14 +192,7 @@ menu_items = (
242
192
  permissions=[
243
193
  "ipam.view_service",
244
194
  ],
245
- buttons=(
246
- NavMenuImportButton(
247
- link="ipam:service_import",
248
- permissions=[
249
- "ipam.add_service",
250
- ],
251
- ),
252
- ),
195
+ buttons=(),
253
196
  ),
254
197
  ),
255
198
  ),
@@ -6,15 +6,6 @@
6
6
  <li>{{ object.parent.namespace|hyperlinked_object }}</li>
7
7
  {% endblock extra_breadcrumbs %}
8
8
 
9
- {% block masthead %}
10
- <h1>
11
- <span class="hover_copy"><span id="copy_title">{{ object }}</span><button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-target="#copy_title">
12
- <span class="mdi mdi-content-copy"></span>
13
- </button>
14
- </span>
15
- </h1>
16
- {% endblock masthead %}
17
-
18
9
  {% block extra_nav_tabs %}
19
10
  {% with interface_count=object.interfaces.count %}
20
11
  {% if interface_count %}
@@ -9,15 +9,6 @@
9
9
  <li>{{ object|hyperlinked_object }}</li>
10
10
  {% endblock breadcrumbs %}
11
11
 
12
- {% block masthead %}
13
- <h1>
14
- <span class="hover_copy"><span id="copy_title">{{ object }}</span><button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-target="#copy_title">
15
- <span class="mdi mdi-content-copy"></span>
16
- </button>
17
- </span>
18
- </h1>
19
- {% endblock masthead %}
20
-
21
12
  {% block extra_buttons %}
22
13
  {% if perms.ipam.add_prefix and active_tab == 'prefixes' and first_available_prefix %}
23
14
  <a href="{% url 'ipam:prefix_add' %}?prefix={{ first_available_prefix }}&namespace={{ object.namespace.pk }}&location={{ object.location.pk }}&tenant_group={{ object.tenant.tenant_group.pk }}&tenant={{ object.tenant.pk }}" class="btn btn-success">
@@ -0,0 +1,134 @@
1
+ Feature: Prefixes
2
+ In order to manage my network IPAM data,
3
+ As a Network Engineer
4
+ I want to record in Nautobot an appropriate set of Prefixes and related data.
5
+
6
+ Background:
7
+ Given I have appropriate Nautobot permissions:
8
+ | model | permissions |
9
+ | ipam.namespace | add,change,delete,view |
10
+ | ipam.prefix | add,change,delete,view |
11
+ And I am logged in to Nautobot
12
+
13
+ Scenario: Creating a set of Prefixes in a custom Namespace
14
+ When I navigate to the "Add Namespace" view
15
+ And I make the following form entries:
16
+ | name | description |
17
+ | CORP | Corporate network |
18
+ And I submit the form
19
+ Then a Namespace exists in Nautobot with the following properties:
20
+ | name | description |
21
+ | CORP | Corporate network |
22
+ And Nautobot shows the "Namespace Detail" view for the Namespace with name "CORP"
23
+ # TODO: it would be nice to have the ability to create a Prefix directly from the Namespace detail view?
24
+
25
+ When I navigate to the "Add Prefix" view
26
+ And I make the following form entries:
27
+ | prefix | namespace | type | status |
28
+ | 10.0.0.0/8 | CORP | Container | Active |
29
+ And I submit the form
30
+ Then a Prefix exists in Nautobot with the following properties:
31
+ | prefix | namespace | type | status | parent |
32
+ | 10.0.0.0/8 | CORP | Container | Active | None |
33
+ And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.0.0/8" and namespace "CORP"
34
+ And the view shows a "Utilization" of "0%"
35
+
36
+ When I click the "Clone" button
37
+ Then Nautobot shows the "Add Prefix" view with the following presets:
38
+ | namespace | type | status |
39
+ | CORP | Container | Active |
40
+ When I make the following form entries:
41
+ | prefix | type |
42
+ | 10.0.100.0/24 | Network |
43
+ And I submit the form
44
+ Then a Prefix exists in Nautobot with the following properties:
45
+ | prefix | namespace | type | status | parent |
46
+ | 10.0.100.0/24 | CORP | Network | Active | 10.0.0.0/8 |
47
+ And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.100.0/24" and namespace "CORP"
48
+ And the view shows a "Utilization" of "0%"
49
+ And the table "Parent Prefixes" includes rows with the following properties:
50
+ | prefix | type |
51
+ | 10.0.0.0/8 | Container |
52
+
53
+ When I click the "Clone" button
54
+ Then Nautobot shows the "Add Prefix" view with the following presets:
55
+ | namespace | type | status |
56
+ | CORP | Network | Active |
57
+ When I make the following form entries:
58
+ | prefix | type |
59
+ | 10.0.0.0/16 | Container |
60
+ And I submit the form
61
+ Then a Prefix exists in Nautobot with the following properties:
62
+ | prefix | namespace | type | status | parent |
63
+ | 10.0.0.0/16 | CORP | Container | Active | 10.0.0.0/8 |
64
+ And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.0.0/16" and namespace "CORP"
65
+ And the table "Parent Prefixes" includes rows with the following properties:
66
+ | prefix | type |
67
+ | 10.0.0.0/8 | Container |
68
+ And the tab "Child Prefixes" includes a badge with the number "1"
69
+
70
+ When I click the "Child Prefixes" tab
71
+ Then Nautobot shows the "Child Prefixes" tab
72
+ And the table "Child Prefixes" includes rows with the following properties:
73
+ | prefix | type | status |
74
+ | 10.0.0.0/18 | — | — |
75
+ | 10.0.64.0/19 | — | — |
76
+ | 10.0.96.0/22 | — | — |
77
+ | 10.0.100.0/24 | Network | Active |
78
+
79
+ When I click the "10.0.96.0/22" link
80
+ Then Nautobot shows the "Add Prefix" view with the following presets:
81
+ | prefix | namespace |
82
+ | 10.0.96.0/22 | CORP |
83
+ When I make the following form entries:
84
+ | prefix | type | status |
85
+ | 10.0.96.0/20 | Container | Active |
86
+ And I submit the form
87
+ Then a Prefix exists in Nautobot with the following properties:
88
+ | prefix | namespace | type | status | parent |
89
+ | 10.0.96.0/20 | CORP | Container | Active | 10.0.0.0/16 |
90
+ And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.96.0/20" and namespace "CORP"
91
+ And the view shows a "Utilization" of "6%"
92
+ And the table "Parent Prefixes" includes rows with the following properties:
93
+ | prefix | type | status |
94
+ | 10.0.0.0/8 | Container | Active |
95
+ | 10.0.0.0/16 | Container | Active |
96
+ And the tab "Child Prefixes" includes a badge with the number "1"
97
+
98
+ When I navigate to the "Prefix List" view
99
+ And specify a filter of "?namespace=CORP"
100
+ Then the table "Prefixes" includes rows with the following properties:
101
+ | prefix | namespace | type | status | children | utilization |
102
+ | 10.0.0.0/8 | CORP | Container | Active | 3 | 0% |
103
+ | 10.0.0.0/16 | CORP | Container | Active | 2 | 6% |
104
+ | 10.0.96.0/20 | CORP | Container | Active | 1 | 6% |
105
+ | 10.0.100.0/24 | CORP | Network | Active | 0 | 0% |
106
+
107
+ When I click the "Import" button
108
+ Then Nautobot shows the "Prefix Bulk Import" view
109
+ When I enter the following into the "csv_data" field:
110
+ """
111
+ prefix,status__name,type,namespace__name
112
+ 10.0.101.0/24,Reserved,network,CORP
113
+ 10.0.102.0/24,Reserved,network,CORP
114
+ 10.1.0.0/16,Reserved,container,CORP
115
+ """
116
+ And I submit the form
117
+ Then several Prefixes exist in Nautobot with the following properties:
118
+ | prefix | namespace | type | status | parent |
119
+ | 10.0.101.0/24 | CORP | Network | Reserved | 10.0.96.0/20 |
120
+ | 10.0.102.0/24 | CORP | Network | Reserved | 10.0.96.0/20 |
121
+ | 10.1.0.0/16 | CORP | Container | Reserved | 10.0.0.0/8 |
122
+ And Nautobot shows the "Prefix Import Completed" view with 3 rows
123
+ When I click the "View All" button
124
+ Then Nautobot shows the "Prefix List" view
125
+ When I specify a filter of "?namespace=CORP"
126
+ Then the table "Prefixes" includes rows with the following properties:
127
+ | prefix | namespace | type | status | children | utilization |
128
+ | 10.0.0.0/8 | CORP | Container | Active | 6 | 0% |
129
+ | 10.0.0.0/16 | CORP | Container | Active | 4 | 6% |
130
+ | 10.0.96.0/20 | CORP | Container | Active | 3 | 18% |
131
+ | 10.0.100.0/24 | CORP | Network | Active | 0 | 0% |
132
+ | 10.0.101.0/24 | CORP | Network | Reserved | 0 | 0% |
133
+ | 10.0.102.0/24 | CORP | Network | Reserved | 0 | 0% |
134
+ | 10.1.0.0/16 | CORP | Container | Reserved | 0 | 0% |
@@ -165,6 +165,7 @@ class PrefixTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilt
165
165
  ["rir", "rir__name"],
166
166
  ["role", "role__id"],
167
167
  ["role", "role__name"],
168
+ ["status", "status__id"],
168
169
  ["status", "status__name"],
169
170
  ["type"],
170
171
  )
@@ -796,8 +797,8 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
796
797
 
797
798
  def test_present_in_vrf(self):
798
799
  # clear out all the randomly generated route targets and vrfs before running this custom test
799
- test_ip_addresses_pk_list = list(self.queryset.values_list("pk", flat=True)[:10])
800
- test_ip_addresses = self.queryset[:10]
800
+ test_ip_addresses = self.queryset.filter(parent__namespace=self.namespace)
801
+ test_ip_addresses_pk_list = list(test_ip_addresses.values_list("pk", flat=True))
801
802
  # With advent of `IPAddress.parent`, IPAddresses can't just be bulk deleted without clearing their
802
803
  # `parent` first in an `update()` query which doesn't call `save()` or `fire `(pre|post)_save` signals.
803
804
  unwanted_ips = self.queryset.exclude(pk__in=test_ip_addresses_pk_list)
@@ -815,12 +816,6 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
815
816
  VRF.objects.create(name="VRF 2", rd="65000:200", namespace=self.namespace),
816
817
  VRF.objects.create(name="VRF 3", rd="65000:300", namespace=self.namespace),
817
818
  )
818
- test_ip_addresses[0].parent.namespace = self.namespace
819
- test_ip_addresses[0].validated_save()
820
- test_ip_addresses[1].parent.namespace = self.namespace
821
- test_ip_addresses[1].validated_save()
822
- test_ip_addresses[2].parent.namespace = self.namespace
823
- test_ip_addresses[2].validated_save()
824
819
  vrfs[0].import_targets.add(route_targets[0], route_targets[1], route_targets[2])
825
820
  vrfs[1].export_targets.add(route_targets[1])
826
821
  vrfs[2].export_targets.add(route_targets[2])
@@ -855,7 +850,7 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
855
850
 
856
851
  def test_status(self):
857
852
  statuses = list(Status.objects.get_for_model(IPAddress).filter(ip_addresses__isnull=False)[:2])
858
- params = {"status": [statuses[0].name, statuses[1].name]}
853
+ params = {"status": [statuses[0].name, statuses[1].id]}
859
854
  self.assertQuerysetEqualAndNotEmpty(
860
855
  self.filterset(params, self.queryset).qs, self.queryset.filter(status__in=statuses)
861
856
  )
@@ -1114,7 +1109,7 @@ class VLANTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilter
1114
1109
 
1115
1110
  def test_status(self):
1116
1111
  statuses = list(Status.objects.get_for_model(VLAN).filter(vlans__isnull=False).distinct())[:2]
1117
- params = {"status": [statuses[0].name, statuses[1].name]}
1112
+ params = {"status": [statuses[0].name, statuses[1].id]}
1118
1113
  self.assertQuerysetEqual(self.filterset(params, self.queryset).qs, self.queryset.filter(status__in=statuses))
1119
1114
 
1120
1115
  def test_search(self):
@@ -50,12 +50,14 @@ class NamespaceTestCase(
50
50
  ViewTestCases.DeleteObjectViewTestCase,
51
51
  ViewTestCases.ListObjectsViewTestCase,
52
52
  ViewTestCases.BulkImportObjectsViewTestCase,
53
+ ViewTestCases.BulkEditObjectsViewTestCase,
54
+ ViewTestCases.BulkDeleteObjectsViewTestCase,
53
55
  ):
54
56
  model = Namespace
55
57
 
56
58
  @classmethod
57
59
  def setUpTestData(cls):
58
- locations = Location.objects.all()[:4]
60
+ locations = Location.objects.get_for_model(Namespace)
59
61
 
60
62
  cls.form_data = {"name": "Namespace X", "location": locations[0].pk, "description": "A new Namespace"}
61
63
 
@@ -66,6 +68,11 @@ class NamespaceTestCase(
66
68
  "Namespace 6,",
67
69
  )
68
70
 
71
+ cls.bulk_edit_data = {
72
+ "description": "New description",
73
+ "location": locations[1].pk,
74
+ }
75
+
69
76
 
70
77
  class VRFTestCase(ViewTestCases.PrimaryObjectViewTestCase):
71
78
  model = VRF
nautobot/ipam/views.py CHANGED
@@ -72,10 +72,13 @@ class NamespaceUIViewSet(
72
72
  view_mixins.ObjectDestroyViewMixin,
73
73
  view_mixins.ObjectChangeLogViewMixin,
74
74
  view_mixins.ObjectBulkCreateViewMixin,
75
+ view_mixins.ObjectBulkDestroyViewMixin,
76
+ view_mixins.ObjectBulkUpdateViewMixin,
75
77
  view_mixins.ObjectNotesViewMixin,
76
78
  ):
77
79
  lookup_field = "pk"
78
80
  form_class = forms.NamespaceForm
81
+ bulk_update_form_class = forms.NamespaceBulkEditForm
79
82
  filterset_class = filters.NamespaceFilterSet
80
83
  queryset = Namespace.objects.all()
81
84
  serializer_class = serializers.NamespaceSerializer