nautobot 2.4.0__py3-none-any.whl → 2.4.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 (592) hide show
  1. nautobot/apps/__init__.py +1 -1
  2. nautobot/apps/api.py +8 -8
  3. nautobot/apps/change_logging.py +2 -2
  4. nautobot/apps/choices.py +4 -4
  5. nautobot/apps/events.py +3 -3
  6. nautobot/apps/factory.py +2 -2
  7. nautobot/apps/filters.py +1 -1
  8. nautobot/apps/forms.py +20 -20
  9. nautobot/apps/graphql.py +2 -2
  10. nautobot/apps/jobs.py +8 -8
  11. nautobot/apps/models.py +19 -19
  12. nautobot/apps/tables.py +1 -1
  13. nautobot/apps/testing.py +10 -10
  14. nautobot/apps/ui.py +2 -2
  15. nautobot/apps/utils.py +7 -7
  16. nautobot/apps/views.py +7 -7
  17. nautobot/circuits/api/serializers.py +0 -1
  18. nautobot/circuits/api/views.py +8 -4
  19. nautobot/circuits/tables.py +1 -2
  20. nautobot/circuits/templates/circuits/circuit_create.html +7 -1
  21. nautobot/circuits/views.py +3 -3
  22. nautobot/cloud/api/views.py +10 -6
  23. nautobot/cloud/models.py +1 -1
  24. nautobot/cloud/views.py +16 -0
  25. nautobot/core/api/fields.py +5 -5
  26. nautobot/core/api/filter_backends.py +9 -3
  27. nautobot/core/api/schema.py +2 -13
  28. nautobot/core/api/serializers.py +34 -40
  29. nautobot/core/api/views.py +4 -56
  30. nautobot/core/celery/log.py +4 -4
  31. nautobot/core/celery/schedulers.py +1 -1
  32. nautobot/core/choices.py +2 -2
  33. nautobot/core/events/__init__.py +3 -3
  34. nautobot/core/filters.py +16 -21
  35. nautobot/core/fixtures/user-data.json +59 -0
  36. nautobot/core/forms/__init__.py +19 -19
  37. nautobot/core/forms/fields.py +11 -14
  38. nautobot/core/forms/forms.py +2 -33
  39. nautobot/core/graphql/types.py +1 -1
  40. nautobot/core/jobs/__init__.py +7 -28
  41. nautobot/core/jobs/cleanup.py +12 -48
  42. nautobot/core/jobs/groups.py +1 -1
  43. nautobot/core/management/commands/validate_models.py +1 -1
  44. nautobot/core/models/__init__.py +1 -1
  45. nautobot/core/models/query_functions.py +2 -2
  46. nautobot/core/models/tree_queries.py +3 -6
  47. nautobot/core/settings.py +2 -29
  48. nautobot/core/settings.yaml +0 -21
  49. nautobot/core/tables.py +60 -74
  50. nautobot/core/templates/inc/media.html +0 -3
  51. nautobot/core/templates/inc/nav_menu.html +0 -1
  52. nautobot/core/templates/nautobot_config.py.j2 +0 -13
  53. nautobot/core/templates/search.html +0 -7
  54. nautobot/core/templates/utilities/render_jinja2.html +1 -1
  55. nautobot/core/templates/utilities/templatetags/tag.html +1 -1
  56. nautobot/core/templates/utilities/theme_preview.html +0 -7
  57. nautobot/core/templatetags/helpers.py +2 -11
  58. nautobot/core/testing/__init__.py +8 -8
  59. nautobot/core/testing/api.py +15 -170
  60. nautobot/core/testing/filters.py +2 -25
  61. nautobot/core/testing/forms.py +0 -2
  62. nautobot/core/testing/mixins.py +2 -7
  63. nautobot/core/testing/views.py +29 -44
  64. nautobot/core/tests/integration/test_app_home.py +1 -0
  65. nautobot/core/tests/integration/test_app_navbar.py +1 -0
  66. nautobot/core/tests/integration/test_filters.py +2 -0
  67. nautobot/core/tests/integration/test_home.py +1 -0
  68. nautobot/core/tests/integration/test_navbar.py +1 -0
  69. nautobot/core/tests/integration/test_view_authentication.py +0 -1
  70. nautobot/core/tests/runner.py +1 -1
  71. nautobot/core/tests/test_api.py +1 -98
  72. nautobot/core/tests/test_csv.py +3 -25
  73. nautobot/core/tests/test_forms.py +0 -1
  74. nautobot/core/tests/test_jobs.py +1 -303
  75. nautobot/core/tests/test_settings_schema.py +0 -7
  76. nautobot/core/tests/test_tables.py +0 -100
  77. nautobot/core/tests/test_utils.py +1 -63
  78. nautobot/core/tests/test_views.py +3 -30
  79. nautobot/core/ui/nav.py +0 -1
  80. nautobot/core/ui/object_detail.py +1 -15
  81. nautobot/core/urls.py +0 -11
  82. nautobot/core/utils/lookup.py +8 -11
  83. nautobot/core/utils/requests.py +9 -24
  84. nautobot/core/views/__init__.py +0 -42
  85. nautobot/core/views/generic.py +176 -78
  86. nautobot/core/views/mixins.py +34 -94
  87. nautobot/core/views/renderers.py +6 -6
  88. nautobot/dcim/api/serializers.py +62 -54
  89. nautobot/dcim/api/views.py +113 -47
  90. nautobot/dcim/filters/__init__.py +2 -31
  91. nautobot/dcim/forms.py +17 -36
  92. nautobot/dcim/graphql/types.py +2 -2
  93. nautobot/dcim/models/__init__.py +1 -1
  94. nautobot/dcim/models/device_component_templates.py +2 -2
  95. nautobot/dcim/models/device_components.py +20 -22
  96. nautobot/dcim/models/devices.py +1 -10
  97. nautobot/dcim/models/locations.py +3 -3
  98. nautobot/dcim/models/power.py +5 -6
  99. nautobot/dcim/models/racks.py +4 -4
  100. nautobot/dcim/tables/__init__.py +3 -3
  101. nautobot/dcim/tables/devices.py +5 -7
  102. nautobot/dcim/tables/devicetypes.py +2 -2
  103. nautobot/dcim/tables/racks.py +1 -1
  104. nautobot/dcim/templates/dcim/controller_create.html +7 -1
  105. nautobot/dcim/templates/dcim/controller_retrieve.html +9 -1
  106. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +0 -2
  107. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -5
  108. nautobot/dcim/templates/dcim/device.html +9 -1
  109. nautobot/dcim/templates/dcim/device_edit.html +37 -36
  110. nautobot/dcim/templates/dcim/location.html +9 -1
  111. nautobot/dcim/templates/dcim/location_edit.html +7 -1
  112. nautobot/dcim/templates/dcim/rack.html +9 -1
  113. nautobot/dcim/templates/dcim/rack_edit.html +7 -1
  114. nautobot/dcim/templates/dcim/rackreservation.html +9 -1
  115. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +9 -1
  116. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +7 -1
  117. nautobot/dcim/tests/test_api.py +3 -16
  118. nautobot/dcim/tests/test_filters.py +0 -33
  119. nautobot/dcim/tests/test_forms.py +2 -51
  120. nautobot/dcim/tests/test_graphql.py +0 -52
  121. nautobot/dcim/tests/test_models.py +5 -34
  122. nautobot/dcim/tests/test_views.py +83 -21
  123. nautobot/dcim/views.py +13 -1
  124. nautobot/extras/api/customfields.py +2 -2
  125. nautobot/extras/api/serializers.py +85 -90
  126. nautobot/extras/api/views.py +27 -22
  127. nautobot/extras/constants.py +0 -2
  128. nautobot/extras/filters/__init__.py +6 -8
  129. nautobot/extras/forms/base.py +2 -2
  130. nautobot/extras/forms/forms.py +31 -139
  131. nautobot/extras/forms/mixins.py +5 -13
  132. nautobot/extras/group_sync.py +3 -3
  133. nautobot/extras/health_checks.py +2 -1
  134. nautobot/extras/jobs.py +12 -70
  135. nautobot/extras/managers.py +1 -3
  136. nautobot/extras/migrations/0018_joblog_data_migration.py +9 -7
  137. nautobot/extras/models/__init__.py +1 -1
  138. nautobot/extras/models/contacts.py +1 -1
  139. nautobot/extras/models/customfields.py +11 -12
  140. nautobot/extras/models/groups.py +9 -11
  141. nautobot/extras/models/jobs.py +4 -23
  142. nautobot/extras/models/models.py +2 -2
  143. nautobot/extras/plugins/__init__.py +2 -13
  144. nautobot/extras/plugins/marketplace_manifest.yml +79 -84
  145. nautobot/extras/plugins/tables.py +14 -16
  146. nautobot/extras/plugins/views.py +69 -65
  147. nautobot/extras/registry.py +1 -1
  148. nautobot/extras/secrets/__init__.py +2 -2
  149. nautobot/extras/tables.py +5 -7
  150. nautobot/extras/templates/extras/dynamicgroup.html +9 -1
  151. nautobot/extras/templates/extras/job_detail.html +0 -16
  152. nautobot/extras/templates/extras/job_edit.html +0 -1
  153. nautobot/extras/templates/extras/jobqueue_retrieve.html +9 -1
  154. nautobot/extras/templates/extras/marketplace.html +11 -29
  155. nautobot/extras/templates/extras/plugin_detail.html +15 -32
  156. nautobot/extras/templates/extras/plugins_tiles.html +10 -21
  157. nautobot/extras/test_jobs/api_test_job.py +1 -1
  158. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  159. nautobot/extras/test_jobs/dry_run.py +1 -1
  160. nautobot/extras/test_jobs/fail.py +5 -5
  161. nautobot/extras/test_jobs/file_output.py +1 -1
  162. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  163. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  164. nautobot/extras/test_jobs/ipaddress_vars.py +1 -3
  165. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  166. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  167. nautobot/extras/test_jobs/log_redaction.py +1 -1
  168. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  169. nautobot/extras/test_jobs/modify_db.py +1 -1
  170. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  171. nautobot/extras/test_jobs/object_var_required.py +1 -1
  172. nautobot/extras/test_jobs/object_vars.py +1 -1
  173. nautobot/extras/test_jobs/pass.py +3 -3
  174. nautobot/extras/test_jobs/profiling.py +1 -1
  175. nautobot/extras/test_jobs/relative_import.py +3 -3
  176. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  177. nautobot/extras/test_jobs/task_queues.py +1 -1
  178. nautobot/extras/tests/integration/test_plugin_banner.py +2 -0
  179. nautobot/extras/tests/test_api.py +13 -13
  180. nautobot/extras/tests/test_customfields.py +1 -1
  181. nautobot/extras/tests/test_datasources.py +1 -2
  182. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  183. nautobot/extras/tests/test_filters.py +6 -6
  184. nautobot/extras/tests/test_forms.py +1 -20
  185. nautobot/extras/tests/test_jobs.py +19 -160
  186. nautobot/extras/tests/test_models.py +10 -10
  187. nautobot/extras/tests/test_plugins.py +9 -62
  188. nautobot/extras/tests/test_relationships.py +9 -120
  189. nautobot/extras/tests/test_views.py +191 -52
  190. nautobot/extras/utils.py +2 -3
  191. nautobot/extras/views.py +98 -30
  192. nautobot/ipam/api/fields.py +3 -3
  193. nautobot/ipam/api/serializers.py +33 -41
  194. nautobot/ipam/api/views.py +117 -68
  195. nautobot/ipam/factory.py +1 -1
  196. nautobot/ipam/filters.py +2 -3
  197. nautobot/ipam/lookups.py +62 -101
  198. nautobot/ipam/models.py +16 -66
  199. nautobot/ipam/querysets.py +2 -2
  200. nautobot/ipam/tables.py +7 -23
  201. nautobot/ipam/templates/ipam/ipaddress.html +9 -1
  202. nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +7 -1
  203. nautobot/ipam/templates/ipam/ipaddress_edit.html +7 -1
  204. nautobot/ipam/templates/ipam/prefix.html +9 -1
  205. nautobot/ipam/templates/ipam/prefix_edit.html +7 -1
  206. nautobot/ipam/templates/ipam/vlan.html +9 -1
  207. nautobot/ipam/templates/ipam/vlan_edit.html +7 -1
  208. nautobot/ipam/templates/ipam/vrf_edit.html +7 -1
  209. nautobot/ipam/tests/test_api.py +3 -416
  210. nautobot/ipam/tests/test_forms.py +47 -49
  211. nautobot/ipam/tests/test_migrations.py +30 -30
  212. nautobot/ipam/tests/test_models.py +34 -95
  213. nautobot/ipam/tests/test_querysets.py +1 -63
  214. nautobot/ipam/tests/test_views.py +0 -3
  215. nautobot/ipam/utils/__init__.py +6 -36
  216. nautobot/ipam/views.py +87 -61
  217. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
  218. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
  219. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +2 -40
  220. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
  221. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
  222. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
  223. nautobot/project-static/docs/404.html +4 -46
  224. nautobot/project-static/docs/apps/index.html +4 -46
  225. nautobot/project-static/docs/apps/nautobot-apps.html +6 -47
  226. nautobot/project-static/docs/assets/_mkdocstrings.css +1 -25
  227. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.83f73b43.min.js} +2 -2
  228. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.83f73b43.min.js.map} +2 -2
  229. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +10 -62
  230. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +7 -59
  231. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +122 -374
  232. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +18 -90
  233. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +21 -95
  234. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +6 -53
  235. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +5 -52
  236. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +17 -79
  237. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +28 -102
  238. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +21 -108
  239. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +38 -131
  240. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +65 -239
  241. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +165 -581
  242. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +36 -109
  243. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +167 -453
  244. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +211 -493
  245. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +8 -60
  246. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +15 -71
  247. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +55 -407
  248. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +205 -585
  249. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +412 -858
  250. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +7 -59
  251. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +186 -448
  252. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +147 -365
  253. nautobot/project-static/docs/development/apps/api/configuration-view.html +4 -46
  254. nautobot/project-static/docs/development/apps/api/database-backend-config.html +4 -46
  255. nautobot/project-static/docs/development/apps/api/models/django-admin.html +4 -46
  256. nautobot/project-static/docs/development/apps/api/models/global-search.html +4 -46
  257. nautobot/project-static/docs/development/apps/api/models/graphql.html +4 -46
  258. nautobot/project-static/docs/development/apps/api/models/index.html +4 -46
  259. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +4 -46
  260. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +4 -46
  261. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +4 -46
  262. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +4 -46
  263. nautobot/project-static/docs/development/apps/api/platform-features/index.html +4 -46
  264. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +4 -46
  265. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +4 -46
  266. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +4 -46
  267. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +4 -46
  268. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +7 -68
  269. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +4 -46
  270. nautobot/project-static/docs/development/apps/api/prometheus.html +4 -46
  271. nautobot/project-static/docs/development/apps/api/setup.html +4 -46
  272. nautobot/project-static/docs/development/apps/api/testing.html +4 -46
  273. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +4 -46
  274. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +4 -46
  275. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +4 -46
  276. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +4 -46
  277. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +4 -46
  278. nautobot/project-static/docs/development/apps/api/views/base-template.html +4 -46
  279. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +4 -46
  280. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +4 -46
  281. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +4 -46
  282. nautobot/project-static/docs/development/apps/api/views/index.html +4 -46
  283. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +4 -46
  284. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +4 -46
  285. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +4 -46
  286. nautobot/project-static/docs/development/apps/api/views/notes.html +4 -46
  287. nautobot/project-static/docs/development/apps/api/views/rest-api.html +6 -52
  288. nautobot/project-static/docs/development/apps/api/views/urls.html +4 -46
  289. nautobot/project-static/docs/development/apps/index.html +4 -46
  290. nautobot/project-static/docs/development/apps/migration/code-updates.html +4 -46
  291. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +4 -46
  292. nautobot/project-static/docs/development/apps/migration/from-v1.html +4 -46
  293. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +4 -46
  294. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +4 -46
  295. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +4 -46
  296. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +4 -46
  297. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +8 -50
  298. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +4 -46
  299. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +14 -211
  300. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +4 -46
  301. nautobot/project-static/docs/development/apps/porting-from-netbox.html +4 -46
  302. nautobot/project-static/docs/development/core/application-registry.html +4 -46
  303. nautobot/project-static/docs/development/core/best-practices.html +4 -46
  304. nautobot/project-static/docs/development/core/bootstrap-ui.html +4 -46
  305. nautobot/project-static/docs/development/core/caching.html +4 -46
  306. nautobot/project-static/docs/development/core/controllers.html +4 -46
  307. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +74 -73
  308. nautobot/project-static/docs/development/core/generic-views.html +4 -46
  309. nautobot/project-static/docs/development/core/getting-started.html +224 -249
  310. nautobot/project-static/docs/development/core/homepage.html +7 -49
  311. nautobot/project-static/docs/development/core/index.html +4 -46
  312. nautobot/project-static/docs/development/core/{minikube-dev-environment-for-k8s-jobs.html → local-k8s.html} +168 -469
  313. nautobot/project-static/docs/development/core/model-checklist.html +12 -56
  314. nautobot/project-static/docs/development/core/model-features.html +4 -46
  315. nautobot/project-static/docs/development/core/natural-keys.html +4 -46
  316. nautobot/project-static/docs/development/core/navigation-menu.html +4 -46
  317. nautobot/project-static/docs/development/core/release-checklist.html +7 -49
  318. nautobot/project-static/docs/development/core/role-internals.html +4 -46
  319. nautobot/project-static/docs/development/core/settings.html +4 -46
  320. nautobot/project-static/docs/development/core/style-guide.html +7 -49
  321. nautobot/project-static/docs/development/core/templates.html +4 -46
  322. nautobot/project-static/docs/development/core/testing.html +4 -46
  323. nautobot/project-static/docs/development/core/ui-component-framework.html +273 -369
  324. nautobot/project-static/docs/development/core/user-preferences.html +4 -46
  325. nautobot/project-static/docs/development/index.html +4 -46
  326. nautobot/project-static/docs/development/jobs/index.html +122 -216
  327. nautobot/project-static/docs/development/jobs/migration/from-v1.html +4 -46
  328. nautobot/project-static/docs/index.html +23 -54
  329. nautobot/project-static/docs/objects.inv +0 -0
  330. nautobot/project-static/docs/overview/application_stack.html +7 -47
  331. nautobot/project-static/docs/overview/design_philosophy.html +4 -46
  332. nautobot/project-static/docs/release-notes/index.html +12 -52
  333. nautobot/project-static/docs/release-notes/version-1.0.html +193 -234
  334. nautobot/project-static/docs/release-notes/version-1.1.html +190 -231
  335. nautobot/project-static/docs/release-notes/version-1.2.html +265 -306
  336. nautobot/project-static/docs/release-notes/version-1.3.html +291 -332
  337. nautobot/project-static/docs/release-notes/version-1.4.html +377 -417
  338. nautobot/project-static/docs/release-notes/version-1.5.html +566 -605
  339. nautobot/project-static/docs/release-notes/version-1.6.html +447 -904
  340. nautobot/project-static/docs/release-notes/version-2.0.html +489 -528
  341. nautobot/project-static/docs/release-notes/version-2.1.html +324 -363
  342. nautobot/project-static/docs/release-notes/version-2.2.html +317 -356
  343. nautobot/project-static/docs/release-notes/version-2.3.html +352 -997
  344. nautobot/project-static/docs/release-notes/version-2.4.html +101 -417
  345. nautobot/project-static/docs/requirements.txt +2 -2
  346. nautobot/project-static/docs/search/search_index.json +1 -1
  347. nautobot/project-static/docs/sitemap.xml +287 -295
  348. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  349. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +4 -46
  350. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +4 -46
  351. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +6 -48
  352. nautobot/project-static/docs/user-guide/administration/configuration/index.html +4 -46
  353. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +4 -46
  354. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +8 -110
  355. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +4 -46
  356. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +4 -46
  357. nautobot/project-static/docs/user-guide/administration/guides/docker.html +4 -46
  358. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +4 -46
  359. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +4 -46
  360. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +4 -46
  361. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +4 -46
  362. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +4 -46
  363. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +6 -48
  364. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +4 -46
  365. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +4 -46
  366. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +4 -46
  367. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +8 -66
  368. nautobot/project-static/docs/user-guide/administration/installation/index.html +4 -46
  369. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +5 -47
  370. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +4 -46
  371. nautobot/project-static/docs/user-guide/administration/installation/services.html +4 -46
  372. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +4 -46
  373. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +4 -46
  374. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +4 -46
  375. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +4 -46
  376. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +4 -46
  377. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +4 -46
  378. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +4 -46
  379. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +4 -46
  380. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +4 -46
  381. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +8 -49
  382. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +4 -46
  383. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +4 -46
  384. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +4 -46
  385. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +4 -46
  386. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +4 -46
  387. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +4 -46
  388. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +4 -46
  389. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +4 -46
  390. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +4 -46
  391. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +4 -46
  392. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +4 -46
  393. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +4 -46
  394. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +4 -46
  395. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +4 -46
  396. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +4 -46
  397. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +4 -46
  398. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +4 -46
  399. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +4 -46
  400. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +4 -46
  401. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +4 -46
  402. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +4 -46
  403. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +4 -46
  404. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +4 -46
  405. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +4 -46
  406. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +4 -46
  407. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +4 -46
  408. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +4 -46
  409. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +4 -46
  410. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +4 -46
  411. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +4 -46
  412. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +4 -46
  413. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +4 -46
  414. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +4 -46
  415. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +4 -46
  416. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +4 -46
  417. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +4 -46
  418. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +4 -46
  419. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +4 -46
  420. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +4 -46
  421. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +4 -46
  422. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +4 -46
  423. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +4 -46
  424. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +4 -46
  425. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +4 -46
  426. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +4 -46
  427. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +4 -46
  428. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +4 -46
  429. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +4 -46
  430. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +4 -46
  431. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +4 -46
  432. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +4 -46
  433. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +4 -46
  434. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +4 -46
  435. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +4 -46
  436. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +4 -46
  437. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +4 -46
  438. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +4 -46
  439. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +12 -50
  440. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +4 -46
  441. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +4 -46
  442. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +4 -46
  443. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +4 -46
  444. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +4 -46
  445. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +4 -46
  446. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +4 -46
  447. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +4 -46
  448. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +4 -46
  449. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +4 -46
  450. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +4 -46
  451. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +4 -46
  452. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +7 -49
  453. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +4 -46
  454. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +4 -46
  455. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +4 -46
  456. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +4 -46
  457. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +4 -46
  458. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +4 -46
  459. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +4 -46
  460. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +4 -46
  461. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +4 -46
  462. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +4 -46
  463. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +4 -46
  464. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +4 -46
  465. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +4 -46
  466. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +4 -46
  467. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +4 -46
  468. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +4 -46
  469. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +4 -46
  470. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +4 -46
  471. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +4 -46
  472. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +4 -46
  473. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +4 -46
  474. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +4 -46
  475. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +7 -51
  476. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +4 -46
  477. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +4 -46
  478. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +4 -46
  479. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +7 -49
  480. nautobot/project-static/docs/user-guide/index.html +4 -46
  481. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +4 -46
  482. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +8 -50
  483. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +4 -46
  484. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +4 -46
  485. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +4 -46
  486. nautobot/project-static/docs/user-guide/platform-functionality/events.html +4 -46
  487. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +4 -46
  488. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +4 -46
  489. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +4 -46
  490. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +4 -46
  491. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +4 -46
  492. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +4 -46
  493. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +7 -50
  494. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +4 -46
  495. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +7 -49
  496. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +4 -46
  497. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +4 -46
  498. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +4 -46
  499. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +4 -46
  500. nautobot/project-static/docs/user-guide/platform-functionality/note.html +4 -46
  501. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +4 -46
  502. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +5 -47
  503. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +4 -46
  504. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +4 -46
  505. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +25 -94
  506. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +5 -74
  507. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +4 -46
  508. nautobot/project-static/docs/user-guide/platform-functionality/role.html +4 -46
  509. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +4 -46
  510. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +4 -46
  511. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +4 -46
  512. nautobot/project-static/docs/user-guide/platform-functionality/status.html +4 -46
  513. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +4 -46
  514. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +4 -46
  515. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +4 -46
  516. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +4 -46
  517. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +4 -46
  518. nautobot/project-static/js/forms.js +1 -1
  519. nautobot/tenancy/api/views.py +13 -9
  520. nautobot/tenancy/views.py +2 -4
  521. nautobot/users/admin.py +1 -1
  522. nautobot/users/api/serializers.py +4 -5
  523. nautobot/users/api/views.py +3 -3
  524. nautobot/virtualization/api/serializers.py +4 -4
  525. nautobot/virtualization/api/views.py +24 -5
  526. nautobot/virtualization/filters.py +3 -20
  527. nautobot/virtualization/models.py +1 -1
  528. nautobot/virtualization/tables.py +2 -2
  529. nautobot/virtualization/templates/virtualization/cluster_edit.html +7 -1
  530. nautobot/virtualization/templates/virtualization/virtualmachine.html +9 -1
  531. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +8 -2
  532. nautobot/virtualization/tests/test_filters.py +0 -17
  533. nautobot/wireless/filters.py +2 -2
  534. nautobot/wireless/forms.py +1 -1
  535. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +9 -1
  536. nautobot/wireless/tests/test_filters.py +1 -29
  537. nautobot/wireless/views.py +10 -0
  538. {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/METADATA +6 -6
  539. {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/RECORD +543 -591
  540. {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/WHEEL +1 -1
  541. nautobot/core/api/constants.py +0 -11
  542. nautobot/core/jobs/bulk_actions.py +0 -248
  543. nautobot/core/templates/about.html +0 -67
  544. nautobot/core/templates/inc/tenancy_form_panel.html +0 -9
  545. nautobot/core/templates/inc/tenant_table_row.html +0 -11
  546. nautobot/core/utils/querysets.py +0 -64
  547. nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +0 -25
  548. nautobot/dcim/tests/integration/test_controller.py +0 -62
  549. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +0 -71
  550. nautobot/dcim/tests/test_jobs.py +0 -118
  551. nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +0 -22
  552. nautobot/extras/migrations/0121_alter_team_contacts.py +0 -17
  553. nautobot/extras/test_jobs/singleton.py +0 -16
  554. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
  555. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
  556. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
  557. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
  558. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
  559. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
  560. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
  561. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
  562. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
  563. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
  564. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
  565. nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
  566. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
  567. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
  568. nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
  569. nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
  570. nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
  571. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
  572. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
  573. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/central-mode.png +0 -0
  574. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-add.png +0 -0
  575. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-1.png +0 -0
  576. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-2.png +0 -0
  577. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-add.png +0 -0
  578. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-create.png +0 -0
  579. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-add.png +0 -0
  580. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-create.png +0 -0
  581. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-add.png +0 -0
  582. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-1.png +0 -0
  583. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-2.png +0 -0
  584. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-add.png +0 -0
  585. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-create.png +0 -0
  586. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +0 -9444
  587. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +0 -9722
  588. nautobot/wireless/tests/integration/__init__.py +0 -0
  589. nautobot/wireless/tests/integration/test_radio_profile.py +0 -42
  590. {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/LICENSE.txt +0 -0
  591. {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/NOTICE +0 -0
  592. {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/entry_points.txt +0 -0
@@ -2,7 +2,6 @@ from concurrent.futures.thread import ThreadPoolExecutor
2
2
  import json
3
3
  from random import shuffle
4
4
  from unittest import skip
5
- import uuid
6
5
 
7
6
  from django.contrib.contenttypes.models import ContentType
8
7
  from django.db import connection
@@ -349,8 +348,6 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
349
348
  cls.create_data = [
350
349
  {
351
350
  "prefix": "192.168.4.0/24",
352
- "network": "192.168.4.0", # not required, but possible to specify
353
- "broadcast": "192.168.4.255", # not required, but possible to specify
354
351
  "status": cls.status.pk,
355
352
  "rir": rir.pk,
356
353
  "type": choices.PrefixTypeChoices.TYPE_POOL,
@@ -509,8 +506,7 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
509
506
  url, {"prefix_length": "hello", "status": self.status.pk}, format="json", **self.header
510
507
  )
511
508
  self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
512
- self.assertIn("prefix_length", response.data)
513
- self.assertEqual(response.data["prefix_length"], "This field must be an integer.")
509
+ self.assertIn("prefix_length", response.data[0])
514
510
 
515
511
  def test_create_multiple_available_prefixes(self):
516
512
  """
@@ -575,126 +571,6 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
575
571
  self.assertIn("prefixcf", response.data[0]["custom_fields"])
576
572
  self.assertEqual("value 1", response.data[0]["custom_fields"]["prefixcf"])
577
573
 
578
- def test_create_available_prefixes_with_permissions_constraint(self):
579
- # Prepare prefix and permissions
580
- prefix = Prefix.objects.create(
581
- prefix="10.2.3.0/24",
582
- type=choices.PrefixTypeChoices.TYPE_POOL,
583
- namespace=self.namespace,
584
- status=self.status,
585
- description="This is the Prefix created for whole network.",
586
- )
587
- url = reverse("ipam-api:prefix-available-prefixes", kwargs={"pk": prefix.pk})
588
- self.add_permissions("ipam.view_prefix")
589
- self.add_permissions(
590
- "ipam.add_prefix", constraints={"description__startswith": "This is the Prefix created for"}
591
- )
592
-
593
- # Test invalid request
594
- data = {
595
- "prefix_length": 26,
596
- "status": self.status.pk,
597
- }
598
- invalid_data_list = [
599
- data,
600
- {**data, "description": ""},
601
- {**data, "description": "Some description"},
602
- {**data, "description": "Some description. This is the IP created for"},
603
- ]
604
-
605
- for invalid_data in invalid_data_list:
606
- with self.subTest(case=invalid_data):
607
- response = self.client.post(url, invalid_data, format="json", **self.header)
608
- self.assertHttpStatus(response, status.HTTP_403_FORBIDDEN)
609
- self.assertIn("detail", response.data)
610
- self.assertEqual(response.data["detail"], "You do not have permission to perform this action.")
611
-
612
- # Verify that no prefixes were created (the entire prefix is still available)
613
- response = self.client.get(url, **self.header)
614
- self.assertHttpStatus(response, status.HTTP_200_OK)
615
- self.assertEqual(len(response.data), 1)
616
- self.assertEqual(response.data[0]["prefix"], prefix.cidr_str)
617
-
618
- # Test valid request
619
- valid_data = {
620
- "prefix_length": 26,
621
- "status": self.status.pk,
622
- "description": "This is the Prefix created for my local network",
623
- }
624
- response = self.client.post(url, valid_data, format="json", **self.header)
625
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
626
- self.assertEqual(response.data["prefix"], "10.2.3.0/26")
627
-
628
- # Verify that prefix is created
629
- response = self.client.get(url, **self.header)
630
- self.assertHttpStatus(response, status.HTTP_200_OK)
631
- self.assertEqual(len(response.data), 2)
632
- self.assertEqual(response.data[0]["prefix"], "10.2.3.64/26")
633
- self.assertEqual(response.data[1]["prefix"], "10.2.3.128/25")
634
-
635
- def test_create_multiple_available_prefixes_with_permissions_constraint(self):
636
- # Prepare prefix and permissions
637
- prefix = Prefix.objects.create(
638
- prefix="10.2.3.0/24",
639
- type=choices.PrefixTypeChoices.TYPE_POOL,
640
- namespace=self.namespace,
641
- status=self.status,
642
- description="This is the Prefix created for whole network.",
643
- )
644
- url = reverse("ipam-api:prefix-available-prefixes", kwargs={"pk": prefix.pk})
645
- self.add_permissions("ipam.view_prefix")
646
- self.add_permissions(
647
- "ipam.add_prefix", constraints={"description__startswith": "This is the Prefix created for"}
648
- )
649
-
650
- # Test invalid request
651
- data = [
652
- {
653
- "prefix_length": 26,
654
- "status": self.status.pk,
655
- "description": "This is the Prefix created for my local network",
656
- },
657
- {
658
- "prefix_length": 26,
659
- "status": self.status.pk,
660
- },
661
- ]
662
- response = self.client.post(url, data, format="json", **self.header)
663
- self.assertHttpStatus(response, status.HTTP_403_FORBIDDEN)
664
- self.assertIn("detail", response.data)
665
- self.assertEqual(response.data["detail"], "You do not have permission to perform this action.")
666
-
667
- # Verify that no prefixes were created (the entire prefix is still available)
668
- response = self.client.get(url, **self.header)
669
- self.assertHttpStatus(response, status.HTTP_200_OK)
670
- self.assertEqual(len(response.data), 1)
671
- self.assertEqual(response.data[0]["prefix"], prefix.cidr_str)
672
-
673
- # Test valid request
674
- data = [
675
- {
676
- "prefix_length": 26,
677
- "status": self.status.pk,
678
- "description": "This is the Prefix created for my local network",
679
- },
680
- {
681
- "prefix_length": 26,
682
- "status": self.status.pk,
683
- "description": "This is the Prefix created for my guest house network",
684
- },
685
- ]
686
- response = self.client.post(url, data, format="json", **self.header)
687
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
688
- self.assertEqual(len(response.data), 2)
689
- self.assertEqual(response.data[0]["prefix"], "10.2.3.0/26")
690
- self.assertEqual(response.data[1]["prefix"], "10.2.3.64/26")
691
-
692
- # Verify that prefixes were created
693
- response = self.client.get(url, **self.header)
694
- self.assertHttpStatus(response, status.HTTP_200_OK)
695
- self.assertEqual(len(response.data), 1)
696
- self.assertEqual(response.data[0]["prefix"], "10.2.3.128/25")
697
-
698
574
  def test_list_available_ips(self):
699
575
  """
700
576
  Test retrieval of all available IP addresses within a parent prefix.
@@ -718,76 +594,9 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
718
594
  response = self.client.get(url, **self.header)
719
595
  self.assertEqual(len(response.data), 6) # 8 - 2 because prefix.type = network
720
596
 
721
- def test_list_available_ips_calculate_child_ips(self):
722
- """
723
- Test retrieval of all available IP addresses when child IP's exists.
724
- """
725
- ip_status = Status.objects.get_for_model(IPAddress).first()
726
- prefix = Prefix.objects.create(
727
- prefix="192.0.3.0/29",
728
- type=choices.PrefixTypeChoices.TYPE_POOL,
729
- namespace=self.namespace,
730
- status=self.status,
731
- )
732
- Prefix.objects.create(
733
- prefix="192.0.3.0/30",
734
- type=choices.PrefixTypeChoices.TYPE_POOL,
735
- namespace=self.namespace,
736
- status=self.status,
737
- )
738
- IPAddress.objects.create(
739
- address="192.0.3.1/30",
740
- status=ip_status,
741
- namespace=self.namespace,
742
- )
743
-
744
- url = reverse("ipam-api:prefix-available-ips", kwargs={"pk": prefix.pk})
745
- self.add_permissions("ipam.view_prefix", "ipam.view_ipaddress")
746
-
747
- # Retrieve all available IPs
748
- response = self.client.get(url, **self.header)
749
- self.assertEqual(len(response.data), 7) # 7 because prefix.type = pool got 8 IP's minus one children IP
750
-
751
- def test_create_single_available_ip_calculate_child_ips(self):
752
- """
753
- Test creating a single IP when child IP's exists.
754
- """
755
- ip_status = Status.objects.get_for_model(IPAddress).first()
756
- prefix = Prefix.objects.create(
757
- prefix="192.0.4.0/31",
758
- namespace=self.namespace,
759
- type=choices.PrefixTypeChoices.TYPE_NETWORK,
760
- status=self.status,
761
- )
762
- Prefix.objects.create(
763
- prefix="192.0.4.0/32",
764
- type=choices.PrefixTypeChoices.TYPE_POOL,
765
- namespace=self.namespace,
766
- status=self.status,
767
- )
768
- IPAddress.objects.create(
769
- address="192.0.4.0/32",
770
- status=ip_status,
771
- namespace=self.namespace,
772
- )
773
- url = reverse("ipam-api:prefix-available-ips", kwargs={"pk": prefix.pk})
774
- self.add_permissions("ipam.view_prefix", "ipam.add_ipaddress", "extras.view_status")
775
-
776
- data = {
777
- "status": self.status.pk,
778
- }
779
-
780
- response = self.client.post(url, data, format="json", **self.header)
781
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
782
- self.assertEqual(str(response.data["parent"]["url"]), self.absolute_api_url(prefix))
783
-
784
- response = self.client.post(url, data, format="json", **self.header)
785
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
786
- self.assertIn("detail", response.data)
787
-
788
597
  def test_create_single_available_ip(self):
789
598
  """
790
- Test creating single IP will return 204 No content when pool is fully filled.
599
+ Test retrieval of the first available IP address within a parent prefix.
791
600
  """
792
601
  prefix = Prefix.objects.create(
793
602
  prefix="192.0.2.0/29",
@@ -855,116 +664,6 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
855
664
  self.assertIn("ipcf", response.data[0]["custom_fields"])
856
665
  self.assertEqual("1", response.data[0]["custom_fields"]["ipcf"])
857
666
 
858
- def test_create_available_ips_with_permissions_constraint(self):
859
- # Prepare prefix and permissions
860
- prefix = Prefix.objects.create(
861
- prefix="192.168.0.0/30",
862
- type=choices.PrefixTypeChoices.TYPE_NETWORK,
863
- namespace=self.namespace,
864
- status=self.status,
865
- description="This is the Prefix created for whole network.",
866
- )
867
- url = reverse("ipam-api:prefix-available-ips", kwargs={"pk": prefix.pk})
868
- self.add_permissions("ipam.view_prefix", "ipam.view_ipaddress")
869
- self.add_permissions(
870
- "ipam.add_ipaddress", constraints={"description__startswith": "This is the IP created for"}
871
- )
872
-
873
- # Test invalid request
874
- data = {
875
- "status": self.status.pk,
876
- }
877
- invalid_data_list = [
878
- data,
879
- {**data, "description": ""},
880
- {**data, "description": "Some description"},
881
- {**data, "description": "Some description. This is the IP created for"},
882
- ]
883
-
884
- for invalid_data in invalid_data_list:
885
- with self.subTest(case=invalid_data):
886
- response = self.client.post(url, invalid_data, format="json", **self.header)
887
- self.assertHttpStatus(response, status.HTTP_403_FORBIDDEN)
888
- self.assertIn("detail", response.data)
889
- self.assertEqual(response.data["detail"], "You do not have permission to perform this action.")
890
-
891
- # Verify that no IPs were created (the entire prefix pool is still available)
892
- response = self.client.get(url, **self.header)
893
- self.assertHttpStatus(response, status.HTTP_200_OK)
894
- self.assertEqual(len(response.data), 2)
895
-
896
- # Test valid request
897
- valid_data = {
898
- "status": self.status.pk,
899
- "description": "This is the IP created for my private laptop",
900
- }
901
- response = self.client.post(url, valid_data, format="json", **self.header)
902
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
903
- self.assertEqual(response.data["address"], "192.168.0.1/30")
904
-
905
- # Verify that IP is created
906
- response = self.client.get(url, **self.header)
907
- self.assertHttpStatus(response, status.HTTP_200_OK)
908
- self.assertEqual(len(response.data), 1)
909
- self.assertEqual(response.data[0]["address"], "192.168.0.2/30")
910
-
911
- def test_create_multiple_available_ips_with_permissions_constraint(self):
912
- # Prepare prefix and permissions
913
- prefix = Prefix.objects.create(
914
- prefix="192.168.0.0/30",
915
- type=choices.PrefixTypeChoices.TYPE_NETWORK,
916
- namespace=self.namespace,
917
- status=self.status,
918
- description="This is a Prefix created for whole network.",
919
- )
920
- url = reverse("ipam-api:prefix-available-ips", kwargs={"pk": prefix.pk})
921
- self.add_permissions("ipam.view_prefix", "ipam.view_ipaddress")
922
- self.add_permissions(
923
- "ipam.add_ipaddress", constraints={"description__startswith": "This is the IP created for"}
924
- )
925
-
926
- # Test invalid request
927
- data = [
928
- {
929
- "status": self.status.pk,
930
- },
931
- {
932
- "status": self.status.pk,
933
- "description": "This is an IP created for my private laptop",
934
- },
935
- ]
936
- response = self.client.post(url, data, format="json", **self.header)
937
- self.assertHttpStatus(response, status.HTTP_403_FORBIDDEN)
938
- self.assertIn("detail", response.data)
939
- self.assertEqual(response.data["detail"], "You do not have permission to perform this action.")
940
-
941
- # Verify that no IPs were created (the entire prefix pool is still available)
942
- response = self.client.get(url, **self.header)
943
- self.assertHttpStatus(response, status.HTTP_200_OK)
944
- self.assertEqual(len(response.data), 2)
945
-
946
- # Test valid request
947
- valid_data = [
948
- {
949
- "status": self.status.pk,
950
- "description": "This is the IP created for my private laptop",
951
- },
952
- {
953
- "status": self.status.pk,
954
- "description": "This is the IP created for my gaming laptop",
955
- },
956
- ]
957
- response = self.client.post(url, valid_data, format="json", **self.header)
958
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
959
- self.assertEqual(len(response.data), 2)
960
- self.assertEqual(response.data[0]["address"], "192.168.0.1/30")
961
- self.assertEqual(response.data[1]["address"], "192.168.0.2/30")
962
-
963
- # Verify that IPs are created
964
- response = self.client.get(url, **self.header)
965
- self.assertHttpStatus(response, status.HTTP_200_OK)
966
- self.assertEqual(len(response.data), 0)
967
-
968
667
 
969
668
  class PrefixLocationAssignmentTest(APIViewTestCases.APIViewTestCase):
970
669
  model = PrefixLocationAssignment
@@ -1323,7 +1022,7 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
1323
1022
  Test retrieval of all available VLAN IDs within a VLANGroup.
1324
1023
  """
1325
1024
  url = reverse("ipam-api:vlangroup-available-vlans", kwargs={"pk": self.vlan_group.pk})
1326
- self.add_permissions("ipam.view_vlangroup", "ipam.view_vlan")
1025
+ self.add_permissions("ipam.view_vlangroup")
1327
1026
 
1328
1027
  # Retrieve all available VLAN IDs
1329
1028
  response = self.client.get(url, **self.header)
@@ -1340,7 +1039,6 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
1340
1039
  url = reverse("ipam-api:vlangroup-available-vlans", kwargs={"pk": self.vlan_group.pk})
1341
1040
  self.add_permissions(
1342
1041
  "ipam.view_vlangroup",
1343
- "ipam.view_vlan",
1344
1042
  "ipam.add_vlan",
1345
1043
  )
1346
1044
 
@@ -1382,7 +1080,6 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
1382
1080
  url = reverse("ipam-api:vlangroup-available-vlans", kwargs={"pk": self.vlan_group.pk})
1383
1081
  self.add_permissions(
1384
1082
  "ipam.view_vlangroup",
1385
- "ipam.view_vlan",
1386
1083
  "ipam.add_vlan",
1387
1084
  )
1388
1085
 
@@ -1429,7 +1126,6 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
1429
1126
  url = reverse("ipam-api:vlangroup-available-vlans", kwargs={"pk": self.vlan_group.pk})
1430
1127
  self.add_permissions(
1431
1128
  "ipam.view_vlangroup",
1432
- "ipam.view_vlan",
1433
1129
  "ipam.add_vlan",
1434
1130
  )
1435
1131
 
@@ -1459,7 +1155,6 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
1459
1155
  url = reverse("ipam-api:vlangroup-available-vlans", kwargs={"pk": self.vlan_group.pk})
1460
1156
  self.add_permissions(
1461
1157
  "ipam.view_vlangroup",
1462
- "ipam.view_vlan",
1463
1158
  "ipam.add_vlan",
1464
1159
  )
1465
1160
 
@@ -1486,114 +1181,6 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
1486
1181
  f"Invalid VLAN Group requested: {some_other_vlan_group}. Only VLAN Group {self.vlan_group} is permitted.",
1487
1182
  response.data["detail"],
1488
1183
  )
1489
- invalid_id = uuid.uuid4()
1490
- data[0]["vlan_group"] = invalid_id # Invalid UUID
1491
- response = self.client.post(url, data, format="json", **self.header)
1492
- self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
1493
- self.assertIn("detail", response.data)
1494
- self.assertEqual(
1495
- f"VLAN Group with pk {invalid_id} does not exist.",
1496
- response.data["detail"],
1497
- )
1498
-
1499
- def test_create_available_vlans_with_permissions_constraint(self):
1500
- url = reverse("ipam-api:vlangroup-available-vlans", kwargs={"pk": self.vlan_group.pk})
1501
- self.add_permissions(
1502
- "ipam.view_vlangroup",
1503
- "ipam.view_vlan",
1504
- )
1505
- self.add_permissions("ipam.add_vlan", constraints={"description__startswith": "This is the VLAN created for"})
1506
-
1507
- data = {"name": "VLAN_6", "status": self.default_status.pk, "vid": 6}
1508
- invalid_data_list = [
1509
- data,
1510
- {**data, "description": ""},
1511
- {**data, "description": "Some description"},
1512
- {**data, "description": "Some description. This is the VLAN created for"},
1513
- ]
1514
-
1515
- # Test invalid request
1516
- for invalid_data in invalid_data_list:
1517
- with self.subTest(case=invalid_data):
1518
- response = self.client.post(url, data, format="json", **self.header)
1519
- self.assertHttpStatus(response, status.HTTP_403_FORBIDDEN)
1520
- self.assertIn("detail", response.data)
1521
- self.assertEqual(response.data["detail"], "You do not have permission to perform this action.")
1522
-
1523
- # Verify that no VLANs were created (number of VLANs is the same as on the beginning of the test)
1524
- response = self.client.get(url, **self.header)
1525
- self.assertHttpStatus(response, status.HTTP_200_OK)
1526
- self.assertEqual(len(response.data["results"]), len(self.unused_vids))
1527
-
1528
- # Test valid request
1529
- valid_data = {
1530
- "name": "VLAN_6",
1531
- "status": self.default_status.pk,
1532
- "vid": 6,
1533
- "description": "This is the VLAN created for home automation.",
1534
- }
1535
- response = self.client.post(url, valid_data, format="json", **self.header)
1536
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
1537
- self.assertEqual(response.data["results"]["name"], valid_data["name"])
1538
-
1539
- # Verify that VLAN is created
1540
- response = self.client.get(url, **self.header)
1541
- self.assertHttpStatus(response, status.HTTP_200_OK)
1542
- self.assertEqual(
1543
- len(response.data["results"]), len(self.unused_vids) - 1
1544
- ) # initial unsued vids minus one created
1545
-
1546
- def test_create_multiple_available_vlans_with_permissions_constraint(self):
1547
- url = reverse("ipam-api:vlangroup-available-vlans", kwargs={"pk": self.vlan_group.pk})
1548
- self.add_permissions(
1549
- "ipam.view_vlangroup",
1550
- "ipam.view_vlan",
1551
- )
1552
- self.add_permissions("ipam.add_vlan", constraints={"description__startswith": "This is the VLAN created for"})
1553
-
1554
- # Test invalid request
1555
- data = [
1556
- {"name": "VLAN_6", "status": self.default_status.pk},
1557
- {"name": "VLAN_7", "status": self.default_status.pk},
1558
- {"name": "VLAN_8", "status": self.default_status.pk},
1559
- ]
1560
- response = self.client.post(url, data, format="json", **self.header)
1561
- self.assertHttpStatus(response, status.HTTP_403_FORBIDDEN)
1562
- self.assertIn("detail", response.data)
1563
- self.assertEqual(response.data["detail"], "You do not have permission to perform this action.")
1564
-
1565
- # Verify that no VLANs were created (number of VLANs is the same as on the beginning of the test)
1566
- response = self.client.get(url, **self.header)
1567
- self.assertHttpStatus(response, status.HTTP_200_OK)
1568
- self.assertEqual(len(response.data["results"]), len(self.unused_vids))
1569
-
1570
- # Test valid request
1571
- valid_data = [
1572
- {
1573
- "name": "VLAN_6",
1574
- "status": self.default_status.pk,
1575
- "description": "This is the VLAN created for home automation.",
1576
- },
1577
- {
1578
- "name": "VLAN_7",
1579
- "status": self.default_status.pk,
1580
- "description": "This is the VLAN created for IP cameras.",
1581
- },
1582
- {"name": "VLAN_8", "status": self.default_status.pk, "description": "This is the VLAN created for guests."},
1583
- ]
1584
- response = self.client.post(url, valid_data, format="json", **self.header)
1585
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
1586
- self.assertHttpStatus(response, status.HTTP_201_CREATED)
1587
- self.assertEqual(len(response.data["results"]), 3)
1588
- for i, vlan_data in enumerate(data):
1589
- self.assertEqual(response.data["results"][i]["name"], vlan_data["name"])
1590
-
1591
- # Verify that VLANs are created
1592
- response = self.client.get(url, **self.header)
1593
- self.assertHttpStatus(response, status.HTTP_200_OK)
1594
- self.assertEqual(
1595
- len(response.data["results"]), len(self.unused_vids) - 3
1596
- ) # initial unsued vids minus three created
1597
1184
 
1598
1185
 
1599
1186
  class VLANTest(APIViewTestCases.APIViewTestCase):
@@ -1,6 +1,5 @@
1
1
  """Test IPAM forms."""
2
2
 
3
- from django.forms import Form
4
3
  from django.test import TestCase
5
4
 
6
5
  from nautobot.core.testing.forms import FormTestCases
@@ -10,63 +9,62 @@ from nautobot.ipam.choices import IPAddressTypeChoices
10
9
  from nautobot.ipam.models import IPAddress, Namespace, Prefix
11
10
 
12
11
 
13
- class NetworkFormTestCases:
14
- class BaseNetworkFormTest(TestCase):
15
- form_class: type[Form]
16
- field_name: str
17
- object_name: str
18
- extra_data = {}
19
-
20
- def setUp(self):
21
- super().setUp()
22
- self.namespace = Namespace.objects.create(name="IPAM Form Test")
23
- self.status = Status.objects.get(name="Active")
24
- self.prefix_status = Status.objects.get_for_model(Prefix).first()
25
- self.ip_status = Status.objects.get_for_model(IPAddress).first()
26
- self.parent = Prefix.objects.create(
27
- prefix="192.168.1.0/24", namespace=self.namespace, status=self.prefix_status
28
- )
29
- self.parent2 = Prefix.objects.create(
30
- prefix="192.168.0.0/16", namespace=self.namespace, status=self.prefix_status
31
- )
32
- self.parent6 = Prefix.objects.create(
33
- prefix="2001:0db8::/40", namespace=self.namespace, status=self.prefix_status
34
- )
12
+ class BaseNetworkFormTest:
13
+ form_class = None
14
+ field_name = None
15
+ object_name = None
16
+ extra_data = {}
35
17
 
36
- def test_valid_ip_address(self):
37
- data = {self.field_name: "192.168.2.0/24", "namespace": self.namespace, "status": self.status}
38
- data.update(self.extra_data)
39
- form = self.form_class(data)
18
+ def setUp(self):
19
+ super().setUp()
20
+ self.namespace = Namespace.objects.create(name="IPAM Form Test")
21
+ self.status = Status.objects.get(name="Active")
22
+ self.prefix_status = Status.objects.get_for_model(Prefix).first()
23
+ self.ip_status = Status.objects.get_for_model(IPAddress).first()
24
+ self.parent = Prefix.objects.create(
25
+ prefix="192.168.1.0/24", namespace=self.namespace, status=self.prefix_status
26
+ )
27
+ self.parent2 = Prefix.objects.create(
28
+ prefix="192.168.0.0/16", namespace=self.namespace, status=self.prefix_status
29
+ )
30
+ self.parent6 = Prefix.objects.create(
31
+ prefix="2001:0db8::/40", namespace=self.namespace, status=self.prefix_status
32
+ )
40
33
 
41
- self.assertTrue(form.is_valid())
42
- self.assertTrue(form.save())
34
+ def test_valid_ip_address(self):
35
+ data = {self.field_name: "192.168.2.0/24", "namespace": self.namespace, "status": self.status}
36
+ data.update(self.extra_data)
37
+ form = self.form_class(data)
43
38
 
44
- def test_address_invalid_ipv4(self):
45
- data = {self.field_name: "192.168.0.1/64", "namespace": self.namespace, "status": self.status}
46
- data.update(self.extra_data)
47
- form = self.form_class(data)
39
+ self.assertTrue(form.is_valid())
40
+ self.assertTrue(form.save())
48
41
 
49
- self.assertFalse(form.is_valid())
50
- self.assertEqual("Please specify a valid IPv4 or IPv6 address.", form.errors[self.field_name][0])
42
+ def test_address_invalid_ipv4(self):
43
+ data = {self.field_name: "192.168.0.1/64", "namespace": self.namespace, "status": self.status}
44
+ data.update(self.extra_data)
45
+ form = self.form_class(data)
51
46
 
52
- def test_address_zero_mask(self):
53
- data = {self.field_name: "192.168.0.1/0", "namespace": self.namespace, "status": self.status}
54
- data.update(self.extra_data)
55
- form = self.form_class(data)
47
+ self.assertFalse(form.is_valid())
48
+ self.assertEqual("Please specify a valid IPv4 or IPv6 address.", form.errors[self.field_name][0])
56
49
 
57
- # With the advent of `Prefix.parent`, it's now possible to create a /0 .
58
- self.assertTrue(form.is_valid())
50
+ def test_address_zero_mask(self):
51
+ data = {self.field_name: "192.168.0.1/0", "namespace": self.namespace, "status": self.status}
52
+ data.update(self.extra_data)
53
+ form = self.form_class(data)
59
54
 
60
- def test_address_missing_mask(self):
61
- data = {self.field_name: "192.168.0.1", "namespace": self.namespace, "status": self.status}
62
- data.update(self.extra_data)
63
- form = self.form_class(data)
55
+ # With the advent of `Prefix.parent`, it's now possible to create a /0 .
56
+ self.assertTrue(form.is_valid())
64
57
 
65
- self.assertFalse(form.is_valid())
66
- self.assertEqual("CIDR mask (e.g. /24) is required.", form.errors[self.field_name][0])
58
+ def test_address_missing_mask(self):
59
+ data = {self.field_name: "192.168.0.1", "namespace": self.namespace, "status": self.status}
60
+ data.update(self.extra_data)
61
+ form = self.form_class(data)
62
+
63
+ self.assertFalse(form.is_valid())
64
+ self.assertEqual("CIDR mask (e.g. /24) is required.", form.errors[self.field_name][0])
67
65
 
68
66
 
69
- class PrefixFormTest(NetworkFormTestCases.BaseNetworkFormTest, FormTestCases.BaseFormTestCase):
67
+ class PrefixFormTest(BaseNetworkFormTest, FormTestCases.BaseFormTestCase):
70
68
  form_class = forms.PrefixForm
71
69
  field_name = "prefix"
72
70
  object_name = "prefix"
@@ -81,7 +79,7 @@ class PrefixFormTest(NetworkFormTestCases.BaseNetworkFormTest, FormTestCases.Bas
81
79
  }
82
80
 
83
81
 
84
- class IPAddressFormTest(NetworkFormTestCases.BaseNetworkFormTest):
82
+ class IPAddressFormTest(BaseNetworkFormTest, TestCase):
85
83
  form_class = forms.IPAddressForm
86
84
  field_name = "address"
87
85
  object_name = "IP address"