nautobot 2.4.5__py3-none-any.whl → 2.4.7__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 (410) hide show
  1. nautobot/apps/forms.py +2 -0
  2. nautobot/circuits/templates/circuits/providernetwork.html +1 -1
  3. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +2 -55
  4. nautobot/circuits/views.py +20 -23
  5. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +2 -40
  6. nautobot/cloud/views.py +12 -0
  7. nautobot/core/api/mixins.py +10 -0
  8. nautobot/core/api/urls.py +2 -2
  9. nautobot/core/api/views.py +39 -1
  10. nautobot/core/celery/encoders.py +2 -2
  11. nautobot/core/forms/__init__.py +2 -0
  12. nautobot/core/forms/fields.py +23 -7
  13. nautobot/core/forms/utils.py +1 -0
  14. nautobot/core/forms/widgets.py +18 -0
  15. nautobot/core/jobs/bulk_actions.py +1 -1
  16. nautobot/core/management/commands/generate_test_data.py +1 -1
  17. nautobot/core/models/name_color_content_types.py +9 -0
  18. nautobot/core/models/validators.py +7 -0
  19. nautobot/core/settings.py +0 -14
  20. nautobot/core/settings.yaml +0 -28
  21. nautobot/core/tables.py +6 -1
  22. nautobot/core/templates/generic/object_retrieve.html +1 -1
  23. nautobot/core/templates/widgets/sluginput.html +5 -1
  24. nautobot/core/templatetags/helpers.py +15 -1
  25. nautobot/core/testing/api.py +18 -0
  26. nautobot/core/testing/integration.py +6 -2
  27. nautobot/core/tests/nautobot_config.py +0 -2
  28. nautobot/core/tests/runner.py +17 -140
  29. nautobot/core/tests/test_api.py +4 -4
  30. nautobot/core/tests/test_authentication.py +83 -4
  31. nautobot/core/tests/test_forms.py +11 -8
  32. nautobot/core/tests/test_graphql.py +9 -0
  33. nautobot/core/tests/test_jobs.py +7 -0
  34. nautobot/core/ui/object_detail.py +47 -3
  35. nautobot/core/utils/lookup.py +2 -2
  36. nautobot/dcim/factory.py +2 -0
  37. nautobot/dcim/filters/__init__.py +5 -0
  38. nautobot/dcim/forms.py +27 -1
  39. nautobot/dcim/migrations/0068_alter_softwareimagefile_download_url.py +19 -0
  40. nautobot/dcim/migrations/0069_softwareimagefile_external_integration.py +25 -0
  41. nautobot/dcim/models/devices.py +9 -2
  42. nautobot/dcim/models/locations.py +9 -0
  43. nautobot/dcim/tables/devices.py +1 -0
  44. nautobot/dcim/templates/dcim/device_list.html +1 -1
  45. nautobot/dcim/templates/dcim/devicetype.html +1 -1
  46. nautobot/dcim/templates/dcim/manufacturer.html +1 -63
  47. nautobot/dcim/templates/dcim/module_list.html +1 -1
  48. nautobot/dcim/templates/dcim/moduletype_retrieve.html +1 -1
  49. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +4 -0
  50. nautobot/dcim/tests/integration/test_module_bay_position.py +125 -0
  51. nautobot/dcim/tests/test_api.py +74 -31
  52. nautobot/dcim/tests/test_filters.py +2 -0
  53. nautobot/dcim/tests/test_models.py +78 -0
  54. nautobot/dcim/tests/test_views.py +7 -1
  55. nautobot/dcim/urls.py +1 -45
  56. nautobot/dcim/views.py +35 -66
  57. nautobot/extras/choices.py +4 -0
  58. nautobot/extras/filters/__init__.py +6 -0
  59. nautobot/extras/forms/forms.py +83 -11
  60. nautobot/extras/models/customfields.py +10 -9
  61. nautobot/extras/plugins/marketplace_manifest.yml +18 -0
  62. nautobot/extras/signals.py +43 -4
  63. nautobot/extras/tables.py +4 -5
  64. nautobot/extras/tasks.py +4 -2
  65. nautobot/extras/templates/extras/contact_retrieve.html +1 -58
  66. nautobot/extras/templates/extras/exporttemplate.html +1 -53
  67. nautobot/extras/templates/extras/inc/panel_changelog.html +1 -1
  68. nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
  69. nautobot/extras/templates/extras/status.html +1 -37
  70. nautobot/extras/templates/extras/team_retrieve.html +1 -58
  71. nautobot/extras/tests/integration/test_notes.py +1 -1
  72. nautobot/extras/tests/test_api.py +22 -7
  73. nautobot/extras/tests/test_changelog.py +4 -4
  74. nautobot/extras/tests/test_customfields.py +27 -0
  75. nautobot/extras/tests/test_plugins.py +19 -13
  76. nautobot/extras/tests/test_relationships.py +9 -0
  77. nautobot/extras/tests/test_tags.py +2 -2
  78. nautobot/extras/tests/test_views.py +37 -6
  79. nautobot/extras/urls.py +3 -100
  80. nautobot/extras/views.py +111 -133
  81. nautobot/ipam/tables.py +7 -2
  82. nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -41
  83. nautobot/ipam/templates/ipam/service.html +2 -46
  84. nautobot/ipam/templates/ipam/service_edit.html +1 -17
  85. nautobot/ipam/templates/ipam/service_retrieve.html +7 -0
  86. nautobot/ipam/tests/migration/__init__.py +0 -0
  87. nautobot/ipam/tests/migration/test_migrations.py +510 -0
  88. nautobot/ipam/tests/test_api.py +66 -36
  89. nautobot/ipam/tests/test_filters.py +0 -10
  90. nautobot/ipam/tests/test_views.py +44 -2
  91. nautobot/ipam/urls.py +2 -47
  92. nautobot/ipam/utils/migrations.py +185 -152
  93. nautobot/ipam/utils/testing.py +177 -0
  94. nautobot/ipam/views.py +95 -157
  95. nautobot/project-static/css/base.css +5 -0
  96. nautobot/project-static/docs/404.html +0 -2
  97. nautobot/project-static/docs/apps/index.html +0 -2
  98. nautobot/project-static/docs/apps/nautobot-apps.html +0 -2
  99. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +0 -2
  100. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +0 -2
  101. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +0 -2
  102. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +0 -2
  103. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +0 -2
  104. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +0 -2
  105. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +0 -2
  106. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +0 -2
  107. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +0 -2
  108. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +0 -2
  109. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +0 -2
  110. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +0 -2
  111. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +62 -2
  112. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +0 -2
  113. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +0 -2
  114. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +47 -2
  115. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +0 -2
  116. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +0 -2
  117. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +18 -2
  118. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +0 -2
  119. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +70 -5
  120. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +0 -2
  121. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +0 -2
  122. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +0 -2
  123. nautobot/project-static/docs/development/apps/api/configuration-view.html +0 -2
  124. nautobot/project-static/docs/development/apps/api/database-backend-config.html +0 -2
  125. nautobot/project-static/docs/development/apps/api/models/django-admin.html +0 -2
  126. nautobot/project-static/docs/development/apps/api/models/global-search.html +0 -2
  127. nautobot/project-static/docs/development/apps/api/models/graphql.html +0 -2
  128. nautobot/project-static/docs/development/apps/api/models/index.html +0 -2
  129. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +0 -2
  130. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +0 -2
  131. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +0 -2
  132. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +0 -2
  133. nautobot/project-static/docs/development/apps/api/platform-features/index.html +0 -2
  134. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +0 -2
  135. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +0 -2
  136. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +0 -2
  137. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +0 -2
  138. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +0 -2
  139. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +0 -2
  140. nautobot/project-static/docs/development/apps/api/prometheus.html +0 -2
  141. nautobot/project-static/docs/development/apps/api/setup.html +0 -2
  142. nautobot/project-static/docs/development/apps/api/testing.html +0 -89
  143. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +0 -2
  144. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +0 -2
  145. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +0 -2
  146. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +0 -2
  147. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +0 -2
  148. nautobot/project-static/docs/development/apps/api/views/base-template.html +0 -2
  149. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +0 -2
  150. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +0 -2
  151. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +0 -2
  152. nautobot/project-static/docs/development/apps/api/views/index.html +0 -2
  153. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +0 -2
  154. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +0 -2
  155. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +0 -2
  156. nautobot/project-static/docs/development/apps/api/views/notes.html +0 -2
  157. nautobot/project-static/docs/development/apps/api/views/rest-api.html +0 -2
  158. nautobot/project-static/docs/development/apps/api/views/urls.html +0 -2
  159. nautobot/project-static/docs/development/apps/index.html +0 -2
  160. nautobot/project-static/docs/development/apps/migration/code-updates.html +0 -2
  161. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +1 -3
  162. nautobot/project-static/docs/development/apps/migration/from-v1.html +0 -2
  163. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +0 -2
  164. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +0 -2
  165. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +0 -2
  166. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +0 -2
  167. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +0 -2
  168. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +0 -2
  169. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +0 -2
  170. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +0 -2
  171. nautobot/project-static/docs/development/apps/porting-from-netbox.html +0 -2
  172. nautobot/project-static/docs/development/core/application-registry.html +0 -2
  173. nautobot/project-static/docs/development/core/best-practices.html +3 -5
  174. nautobot/project-static/docs/development/core/bootstrap-ui.html +0 -2
  175. nautobot/project-static/docs/development/core/caching.html +0 -2
  176. nautobot/project-static/docs/development/core/controllers.html +0 -2
  177. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +0 -2
  178. nautobot/project-static/docs/development/core/generic-views.html +0 -2
  179. nautobot/project-static/docs/development/core/getting-started.html +78 -109
  180. nautobot/project-static/docs/development/core/homepage.html +0 -2
  181. nautobot/project-static/docs/development/core/index.html +0 -2
  182. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +0 -2
  183. nautobot/project-static/docs/development/core/model-checklist.html +0 -2
  184. nautobot/project-static/docs/development/core/model-features.html +0 -2
  185. nautobot/project-static/docs/development/core/natural-keys.html +0 -2
  186. nautobot/project-static/docs/development/core/navigation-menu.html +0 -2
  187. nautobot/project-static/docs/development/core/release-checklist.html +1 -3
  188. nautobot/project-static/docs/development/core/role-internals.html +0 -2
  189. nautobot/project-static/docs/development/core/settings.html +0 -2
  190. nautobot/project-static/docs/development/core/style-guide.html +1 -3
  191. nautobot/project-static/docs/development/core/templates.html +0 -2
  192. nautobot/project-static/docs/development/core/testing.html +24 -200
  193. nautobot/project-static/docs/development/core/ui-component-framework.html +0 -2
  194. nautobot/project-static/docs/development/core/user-preferences.html +0 -2
  195. nautobot/project-static/docs/development/index.html +0 -2
  196. nautobot/project-static/docs/development/jobs/index.html +0 -2
  197. nautobot/project-static/docs/development/jobs/migration/from-v1.html +0 -2
  198. nautobot/project-static/docs/index.html +0 -2
  199. nautobot/project-static/docs/media/user-guide/administration/getting-started/nautobot-cloud.png +0 -0
  200. nautobot/project-static/docs/objects.inv +0 -0
  201. nautobot/project-static/docs/overview/application_stack.html +1 -3
  202. nautobot/project-static/docs/overview/design_philosophy.html +0 -2
  203. nautobot/project-static/docs/release-notes/index.html +0 -2
  204. nautobot/project-static/docs/release-notes/version-1.0.html +0 -2
  205. nautobot/project-static/docs/release-notes/version-1.1.html +0 -2
  206. nautobot/project-static/docs/release-notes/version-1.2.html +0 -2
  207. nautobot/project-static/docs/release-notes/version-1.3.html +0 -2
  208. nautobot/project-static/docs/release-notes/version-1.4.html +0 -2
  209. nautobot/project-static/docs/release-notes/version-1.5.html +0 -2
  210. nautobot/project-static/docs/release-notes/version-1.6.html +0 -2
  211. nautobot/project-static/docs/release-notes/version-2.0.html +0 -2
  212. nautobot/project-static/docs/release-notes/version-2.1.html +0 -2
  213. nautobot/project-static/docs/release-notes/version-2.2.html +0 -2
  214. nautobot/project-static/docs/release-notes/version-2.3.html +0 -2
  215. nautobot/project-static/docs/release-notes/version-2.4.html +364 -3
  216. nautobot/project-static/docs/search/search_index.json +1 -1
  217. nautobot/project-static/docs/sitemap.xml +290 -290
  218. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  219. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +0 -2
  220. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +0 -2
  221. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +0 -2
  222. nautobot/project-static/docs/user-guide/administration/configuration/index.html +0 -2
  223. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +0 -2
  224. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +2 -50
  225. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +0 -2
  226. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +0 -2
  227. nautobot/project-static/docs/user-guide/administration/guides/docker.html +0 -2
  228. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +0 -2
  229. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +71 -2
  230. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +0 -2
  231. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +0 -2
  232. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +0 -2
  233. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +0 -2
  234. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +0 -2
  235. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +0 -2
  236. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +0 -2
  237. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +3 -3
  238. nautobot/project-static/docs/user-guide/administration/installation/index.html +257 -18
  239. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +0 -2
  240. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +0 -2
  241. nautobot/project-static/docs/user-guide/administration/installation/services.html +0 -2
  242. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +0 -2
  243. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +0 -2
  244. nautobot/project-static/docs/user-guide/administration/security/index.html +0 -2
  245. nautobot/project-static/docs/user-guide/administration/security/notices.html +0 -2
  246. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +1 -3
  247. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +0 -2
  248. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +0 -2
  249. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +0 -2
  250. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +0 -2
  251. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +0 -2
  252. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +0 -2
  253. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +0 -2
  254. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +0 -2
  255. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +0 -2
  256. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +2 -4
  257. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +0 -2
  258. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +0 -2
  259. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +0 -2
  260. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +0 -2
  261. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +0 -2
  262. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +0 -2
  263. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +0 -2
  264. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +0 -2
  265. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +0 -2
  266. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +0 -2
  267. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +0 -2
  268. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +0 -2
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +0 -2
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +0 -2
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +0 -2
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +0 -2
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +0 -2
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +0 -2
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +0 -2
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +0 -2
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +0 -2
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +0 -2
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +0 -2
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +0 -2
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +0 -2
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +0 -2
  283. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +0 -2
  284. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +0 -2
  285. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +0 -2
  286. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +0 -2
  287. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +0 -2
  288. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +0 -2
  289. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +0 -2
  290. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +0 -2
  291. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +0 -2
  292. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +0 -2
  293. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +0 -2
  294. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +0 -2
  295. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +0 -2
  296. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +0 -2
  297. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +0 -2
  298. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +0 -2
  299. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +0 -2
  300. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +0 -2
  301. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +0 -2
  302. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +0 -2
  303. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +0 -2
  304. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +0 -2
  305. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +0 -2
  306. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +0 -2
  307. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +4 -2
  308. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +0 -2
  309. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +0 -2
  310. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +0 -2
  311. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +0 -2
  312. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +0 -2
  313. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +0 -2
  314. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +0 -2
  315. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +0 -2
  316. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +0 -2
  317. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +0 -2
  318. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +0 -2
  319. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +0 -2
  320. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +0 -2
  321. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +0 -2
  322. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +0 -2
  323. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +0 -2
  324. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +0 -2
  325. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +0 -2
  326. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +0 -2
  327. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +0 -2
  328. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +0 -2
  329. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +0 -2
  330. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +0 -2
  331. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +0 -2
  332. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +0 -2
  333. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +0 -2
  334. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +0 -2
  335. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +0 -2
  336. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +11 -13
  337. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +0 -2
  338. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +8 -10
  339. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +1 -2
  340. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +0 -2
  341. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +40 -27
  342. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +4 -6
  343. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +1 -3
  344. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +77 -7
  345. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +1 -3
  346. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +0 -3
  347. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +1 -3
  348. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +0 -2
  349. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +0 -2
  350. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +0 -2
  351. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +0 -2
  352. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +0 -2
  353. nautobot/project-static/docs/user-guide/index.html +89 -4
  354. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +0 -2
  355. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +0 -2
  356. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +0 -2
  357. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +0 -2
  358. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +0 -2
  359. nautobot/project-static/docs/user-guide/platform-functionality/events.html +0 -2
  360. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +0 -2
  361. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +0 -2
  362. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +0 -2
  363. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +0 -2
  364. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +0 -2
  365. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +0 -2
  366. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +0 -2
  367. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +0 -2
  368. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +0 -2
  369. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +0 -2
  370. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +0 -2
  371. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +0 -2
  372. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +0 -2
  373. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +0 -2
  374. nautobot/project-static/docs/user-guide/platform-functionality/note.html +0 -2
  375. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +0 -2
  376. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +0 -2
  377. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +0 -2
  378. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +0 -2
  379. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +0 -2
  380. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +0 -2
  381. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +0 -2
  382. nautobot/project-static/docs/user-guide/platform-functionality/role.html +0 -2
  383. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +0 -2
  384. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +0 -2
  385. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +0 -2
  386. nautobot/project-static/docs/user-guide/platform-functionality/status.html +0 -2
  387. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +0 -2
  388. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +0 -2
  389. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +0 -2
  390. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +0 -2
  391. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +207 -124
  392. nautobot/project-static/js/forms.js +88 -37
  393. nautobot/project-static/js/homepage_layout.js +12 -3
  394. nautobot/virtualization/forms.py +20 -0
  395. nautobot/virtualization/templates/virtualization/clustergroup.html +1 -39
  396. nautobot/virtualization/templates/virtualization/clustertype.html +1 -0
  397. nautobot/virtualization/tests/test_api.py +14 -3
  398. nautobot/virtualization/tests/test_views.py +10 -2
  399. nautobot/virtualization/urls.py +10 -93
  400. nautobot/virtualization/views.py +33 -72
  401. {nautobot-2.4.5.dist-info → nautobot-2.4.7.dist-info}/METADATA +6 -5
  402. {nautobot-2.4.5.dist-info → nautobot-2.4.7.dist-info}/RECORD +407 -402
  403. {nautobot-2.4.5.dist-info → nautobot-2.4.7.dist-info}/WHEEL +1 -1
  404. nautobot/core/tests/performance_baselines.yml +0 -8900
  405. nautobot/dcim/templates/dcim/modulebay_create.html +0 -39
  406. nautobot/ipam/tests/test_migrations.py +0 -462
  407. /nautobot/ipam/templates/ipam/{namespace_ipaddresses.html → namespace_ip_addresses.html} +0 -0
  408. {nautobot-2.4.5.dist-info → nautobot-2.4.7.dist-info}/LICENSE.txt +0 -0
  409. {nautobot-2.4.5.dist-info → nautobot-2.4.7.dist-info}/NOTICE +0 -0
  410. {nautobot-2.4.5.dist-info → nautobot-2.4.7.dist-info}/entry_points.txt +0 -0
@@ -86,43 +86,93 @@ function initializeCheckboxes(context){
86
86
  });
87
87
  }
88
88
 
89
- function initializeSlugField(context){
90
- this_context = $(context);
91
- var slug_field = this_context.find('#id_slug');
89
+ function repopulateAutoField(context, targetField, sourceFields, maxLength, transformValue = null){
90
+ const newValues = sourceFields.map(function(sourceFieldName){
91
+ const sourceFieldId = `id_${sourceFieldName}`;
92
+ return context.getElementById(sourceFieldId).value;
93
+ })
94
+
95
+ const newValue = newValues.join(" ")
96
+ if(transformValue){
97
+ targetField.value = transformValue(newValue, maxLength)
98
+ } else {
99
+ targetField.value = newValue.slice(0, maxLength)
100
+ }
101
+ }
102
+
103
+ function repopulateIfChanged(targetField, repopulate){
104
+ if(targetField.dataset.manuallyChanged === 'true'){
105
+ return;
106
+ }
107
+ repopulate()
108
+ }
109
+
110
+ function watchManualChanges(field){
111
+ field.dataset.manuallyChanged = Boolean(field.value)
112
+ field.addEventListener('change', function(){
113
+ field.dataset.manuallyChanged = Boolean(field.value)
114
+ })
115
+ }
116
+
117
+ function watchSourceFields(context, targetField, sourceFields, repopulate){
118
+ // Watch for any changes in source fields to regenerate the target field
119
+ sourceFields.forEach(function(sourceFieldName){
120
+ const sourceFieldId = `id_${sourceFieldName}`;
121
+ const sourceField = context.getElementById(sourceFieldId);
122
+ const onFieldUpdate = function(){ repopulateIfChanged(targetField, repopulate)}
123
+ sourceField.addEventListener('keyup', onFieldUpdate)
124
+ sourceField.addEventListener('change', onFieldUpdate)
125
+ })
126
+ }
127
+
128
+ function watchRegenerateButton(context, targetField, repopulate){
129
+ // If user clicks the "regenerate" button, set target field to be auto-populate again
130
+ const regenerateButton = context.querySelector(`[data-regenerate=${targetField.getAttribute('id')}]`)
131
+ regenerateButton.addEventListener('click', repopulate)
132
+ }
133
+
134
+ function getSlugField(context){
135
+ const slugField = context.getElementById("id_slug");
136
+ if(slugField){
137
+ return slugField
138
+ }
92
139
  // If id_slug field is not to be found
93
- // check if it is rename to key field like what we did for CustomField and Relationship
94
- if (slug_field.length == 0) {
95
- slug_field = this_context.find('#id_key');
140
+ // check if it is renamed to key field like what we did for CustomField and Relationship
141
+ return context.getElementById("id_key");
142
+ }
143
+
144
+ function initializeAutoField(context, field, sourceFieldsAttrName, defaultMaxLength = 255, transformValue = null){
145
+ // Get source fields and length values set as html attributes on given field
146
+ const sourceFields = field.getAttribute(sourceFieldsAttrName).split(" ");
147
+ const length = field.getAttribute('maxlength') || defaultMaxLength
148
+
149
+ // Prepare repopulate function with custom source fields and length set on this field
150
+ const repopulateField = function() {
151
+ repopulateAutoField(context, field, sourceFields, length, transformValue)
96
152
  }
97
- if (slug_field.length != 0) {
98
- var slug_source_arr = slug_field.attr('slug-source').split(" ");
99
- var slug_length = slug_field.attr('maxlength');
100
- slug_field.attr('_changed', Boolean(slug_field.val()));
101
- slug_field.change(function() {
102
- $(this).attr('_changed', Boolean($(this).val()));
103
- });
104
- function reslugify() {
105
- let slug_str = "";
106
- for (slug_source_str of slug_source_arr) {
107
- if (slug_str != "") {
108
- slug_str += " ";
109
- }
110
- let slug_source = $('#id_' + slug_source_str);
111
- slug_str += slug_source.val();
112
- }
113
- slug_field.val(slugify(slug_str, (slug_length ? slug_length : 100)));
114
- };
115
-
116
- for (slug_source_str of slug_source_arr) {
117
- let slug_source = $('#id_' + slug_source_str);
118
- slug_source.on('keyup change', function() {
119
- if (slug_field && slug_field.attr('_changed')=="false") {
120
- reslugify();
121
- }
122
- });
123
- }
124
- this_context.find('button.reslugify').click(reslugify);
153
+ watchSourceFields(context, field, sourceFields, repopulateField);
154
+ watchRegenerateButton(context, field, repopulateField);
155
+ watchManualChanges(field);
156
+ }
157
+
158
+ function initializeSlugField(context){
159
+ // Function to support slug fields auto-populate and slugify logic
160
+ const vanilla_context = context[0] // jsify form passes jquery context
161
+ const slugField = getSlugField(vanilla_context)
162
+ if(!slugField){
163
+ return
125
164
  }
165
+ initializeAutoField(vanilla_context, slugField, 'slug-source', 100, slugify);
166
+ }
167
+
168
+ function initializeAutoPopulateField(context){
169
+ // Function to support other auto-populate fields like position for Device Module Bay
170
+ const vanilla_context = context[0] // jsify form passes jquery context
171
+ const fields = vanilla_context.querySelectorAll('[data-autopopulate]');
172
+
173
+ fields.forEach(function(field){
174
+ initializeAutoField(vanilla_context, field, 'source');
175
+ })
126
176
  }
127
177
 
128
178
  function initializeFormActionClick(context){
@@ -887,10 +937,11 @@ function replaceEl(replaced_el, replacing_el) {
887
937
  }
888
938
 
889
939
  function initializeInputs(context) {
890
- this_context = $(context);
940
+ const this_context = $(context);
891
941
  initializeStaticChoiceSelection(this_context)
892
942
  initializeCheckboxes(this_context)
893
943
  initializeSlugField(this_context)
944
+ initializeAutoPopulateField(this_context)
894
945
  initializeFormActionClick(this_context)
895
946
  initializeBulkEditNullification(this_context)
896
947
  initializeColorPicker(this_context)
@@ -905,7 +956,7 @@ function initializeInputs(context) {
905
956
  initializeMultiValueChar(this_context)
906
957
 
907
958
  $(this_context).find(".modal").each(function() {
908
- this_modal = $(this)
959
+ const this_modal = $(this)
909
960
  initializeStaticChoiceSelection(this_modal, this_modal)
910
961
  initializeColorPicker(this_modal, this_modal)
911
962
  initializeDynamicChoiceSelection(this_modal, this_modal)
@@ -915,7 +966,7 @@ function initializeInputs(context) {
915
966
  }
916
967
 
917
968
  function jsify_form(context) {
918
- this_context = $(context);
969
+ const this_context = $(context);
919
970
  // Pagination
920
971
  initializeInputs(this_context)
921
972
  }
@@ -52,9 +52,18 @@ document.addEventListener("DOMContentLoaded", function() {
52
52
 
53
53
  // Function to handle the start of a drag event
54
54
  function handleDragStart(e) {
55
- e.dataTransfer.clearData("text/plain");
56
- e.dataTransfer.setData("text/plain", e.target.id);
57
- e.target.classList.add("dragging");
55
+
56
+ // Get the element the user clicked on
57
+ const clickedElement = document.elementFromPoint(e.clientX, e.clientY);
58
+
59
+ // Only allow drag if the handle is in the panel-heading
60
+ if (!clickedElement || !clickedElement.closest(".panel-heading")) {
61
+ e.preventDefault();
62
+ return;
63
+ }
64
+ e.dataTransfer.clearData("text/plain");
65
+ e.dataTransfer.setData("text/plain", e.target.id);
66
+ e.target.classList.add("dragging");
58
67
  }
59
68
 
60
69
  function handleDragEnd(e) {
@@ -69,6 +69,16 @@ class ClusterTypeFilterForm(NautobotFilterForm):
69
69
  clusters = DynamicModelMultipleChoiceField(queryset=Cluster.objects.all(), to_field_name="name", required=False)
70
70
 
71
71
 
72
+ class ClusterTypeBulkEditForm(NautobotBulkEditForm):
73
+ pk = forms.ModelMultipleChoiceField(queryset=ClusterType.objects.all(), widget=forms.MultipleHiddenInput())
74
+ description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
75
+
76
+ class Meta:
77
+ nullable_fields = [
78
+ "description",
79
+ ]
80
+
81
+
72
82
  #
73
83
  # Cluster groups
74
84
  #
@@ -89,6 +99,16 @@ class ClusterGroupFilterForm(NautobotFilterForm):
89
99
  clusters = DynamicModelMultipleChoiceField(queryset=Cluster.objects.all(), to_field_name="name", required=False)
90
100
 
91
101
 
102
+ class ClusterGroupBulkEditForm(NautobotBulkEditForm):
103
+ pk = forms.ModelMultipleChoiceField(queryset=ClusterGroup.objects.all(), widget=forms.MultipleHiddenInput())
104
+ description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
105
+
106
+ class Meta:
107
+ nullable_fields = [
108
+ "description",
109
+ ]
110
+
111
+
92
112
  #
93
113
  # Clusters
94
114
  #
@@ -1,40 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load helpers %}
3
-
4
- {% block content_left_page %}
5
- <div class="panel panel-default">
6
- <div class="panel-heading">
7
- <strong>Cluster Group</strong>
8
- </div>
9
- <table class="table table-hover panel-body attr-table">
10
- <tr>
11
- <td>Description</td>
12
- <td>{{ object.description|placeholder }}</td>
13
- </tr>
14
- <tr>
15
- <td>Clusters</td>
16
- <td>
17
- <a href="{% url 'virtualization:cluster_list' %}?cluster_group={{ object.name }}">{{ cluster_table.rows|length }}</a>
18
- </td>
19
- </tr>
20
- </table>
21
- </div>
22
- {% endblock content_left_page %}
23
-
24
- {% block content_right_page %}
25
- <div class="panel panel-default">
26
- <div class="panel-heading">
27
- <strong>Clusters</strong>
28
- </div>
29
- {% include 'inc/table.html' with table=cluster_table %}
30
- {% if perms.virtualization.add_cluster %}
31
- <div class="panel-footer text-right noprint">
32
- <a href="{% url 'virtualization:cluster_add' %}?cluster_group={{ object.pk }}" class="btn btn-xs btn-primary">
33
- <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add cluster
34
- </a>
35
- </div>
36
- {% endif %}
37
- </div>
38
- {% include 'inc/paginator.html' with paginator=cluster_table.paginator page=cluster_table.page %}
39
- <div class="row"></div>
40
- {% endblock content_right_page %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -239,7 +239,7 @@ class VirtualMachineTest(APIViewTestCases.APIViewTestCase):
239
239
  schema = ConfigContextSchema.objects.create(
240
240
  name="Schema 1", data_schema={"type": "object", "properties": {"A": {"type": "integer"}}}
241
241
  )
242
- self.add_permissions("virtualization.change_virtualmachine")
242
+ self.add_permissions("virtualization.change_virtualmachine", "extras.view_configcontextschema")
243
243
 
244
244
  patch_data = {"local_config_context_schema": str(schema.pk)}
245
245
 
@@ -346,7 +346,12 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
346
346
 
347
347
  def test_untagged_vlan_requires_mode(self):
348
348
  """Test that when an `untagged_vlan` is specified, `mode` is also required."""
349
- self.add_permissions("virtualization.add_vminterface")
349
+ self.add_permissions(
350
+ "virtualization.add_vminterface",
351
+ "virtualization.view_virtualmachine",
352
+ "extras.view_status",
353
+ "ipam.view_vlan",
354
+ )
350
355
 
351
356
  # This will fail.
352
357
  url = self._get_list_url()
@@ -361,7 +366,13 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
361
366
  )
362
367
 
363
368
  def test_tagged_vlan_raise_error_if_mode_not_set_to_tagged(self):
364
- self.add_permissions("virtualization.add_vminterface", "virtualization.change_vminterface")
369
+ self.add_permissions(
370
+ "virtualization.add_vminterface",
371
+ "virtualization.change_vminterface",
372
+ "virtualization.view_virtualmachine",
373
+ "extras.view_status",
374
+ "ipam.view_vlan",
375
+ )
365
376
  vlan = VLAN.objects.get(name="VLAN 1")
366
377
  virtualmachine = VirtualMachine.objects.first()
367
378
  with self.subTest("On create, assert 400 status."):
@@ -18,7 +18,7 @@ from nautobot.virtualization.models import (
18
18
  )
19
19
 
20
20
 
21
- class ClusterGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
21
+ class ClusterGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase, ViewTestCases.BulkEditObjectsViewTestCase):
22
22
  model = ClusterGroup
23
23
 
24
24
  @classmethod
@@ -30,8 +30,12 @@ class ClusterGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
30
30
  "description": "A new cluster group",
31
31
  }
32
32
 
33
+ cls.bulk_edit_data = {
34
+ "description": "New description",
35
+ }
36
+
33
37
 
34
- class ClusterTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
38
+ class ClusterTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase, ViewTestCases.BulkEditObjectsViewTestCase):
35
39
  model = ClusterType
36
40
 
37
41
  @classmethod
@@ -48,6 +52,10 @@ class ClusterTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
48
52
  "description": "A new cluster type",
49
53
  }
50
54
 
55
+ cls.bulk_edit_data = {
56
+ "description": "New description",
57
+ }
58
+
51
59
 
52
60
  class ClusterTestCase(ViewTestCases.PrimaryObjectViewTestCase):
53
61
  model = Cluster
@@ -1,105 +1,20 @@
1
1
  from django.urls import path
2
2
 
3
+ from nautobot.core.views.routers import NautobotUIViewSetRouter
3
4
  from nautobot.extras.views import ObjectChangeLogView, ObjectDynamicGroupsView, ObjectNotesView
4
5
  from nautobot.ipam.views import ServiceEditView
5
6
 
6
7
  from . import views
7
- from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
8
+ from .models import Cluster, VirtualMachine, VMInterface
8
9
 
9
10
  app_name = "virtualization"
11
+
12
+ router = NautobotUIViewSetRouter()
13
+ router.register("cluster-groups", views.ClusterGroupUIViewSet)
14
+ router.register("cluster-types", views.ClusterTypeUIViewSet)
15
+
16
+
10
17
  urlpatterns = [
11
- # Cluster types
12
- path("cluster-types/", views.ClusterTypeListView.as_view(), name="clustertype_list"),
13
- path(
14
- "cluster-types/add/",
15
- views.ClusterTypeEditView.as_view(),
16
- name="clustertype_add",
17
- ),
18
- path(
19
- "cluster-types/import/",
20
- views.ClusterTypeBulkImportView.as_view(), # 3.0 TODO: remove, unused
21
- name="clustertype_import",
22
- ),
23
- path(
24
- "cluster-types/delete/",
25
- views.ClusterTypeBulkDeleteView.as_view(),
26
- name="clustertype_bulk_delete",
27
- ),
28
- path(
29
- "cluster-types/<uuid:pk>/",
30
- views.ClusterTypeView.as_view(),
31
- name="clustertype",
32
- ),
33
- path(
34
- "cluster-types/<uuid:pk>/edit/",
35
- views.ClusterTypeEditView.as_view(),
36
- name="clustertype_edit",
37
- ),
38
- path(
39
- "cluster-types/<uuid:pk>/delete/",
40
- views.ClusterTypeDeleteView.as_view(),
41
- name="clustertype_delete",
42
- ),
43
- path(
44
- "cluster-types/<uuid:pk>/changelog/",
45
- ObjectChangeLogView.as_view(),
46
- name="clustertype_changelog",
47
- kwargs={"model": ClusterType},
48
- ),
49
- path(
50
- "cluster-types/<uuid:pk>/notes/",
51
- ObjectNotesView.as_view(),
52
- name="clustertype_notes",
53
- kwargs={"model": ClusterType},
54
- ),
55
- # Cluster groups
56
- path(
57
- "cluster-groups/",
58
- views.ClusterGroupListView.as_view(),
59
- name="clustergroup_list",
60
- ),
61
- path(
62
- "cluster-groups/add/",
63
- views.ClusterGroupEditView.as_view(),
64
- name="clustergroup_add",
65
- ),
66
- path(
67
- "cluster-groups/import/",
68
- views.ClusterGroupBulkImportView.as_view(), # 3.0 TODO: remove, unused
69
- name="clustergroup_import",
70
- ),
71
- path(
72
- "cluster-groups/delete/",
73
- views.ClusterGroupBulkDeleteView.as_view(),
74
- name="clustergroup_bulk_delete",
75
- ),
76
- path(
77
- "cluster-groups/<uuid:pk>/",
78
- views.ClusterGroupView.as_view(),
79
- name="clustergroup",
80
- ),
81
- path(
82
- "cluster-groups/<uuid:pk>/edit/",
83
- views.ClusterGroupEditView.as_view(),
84
- name="clustergroup_edit",
85
- ),
86
- path(
87
- "cluster-groups/<uuid:pk>/delete/",
88
- views.ClusterGroupDeleteView.as_view(),
89
- name="clustergroup_delete",
90
- ),
91
- path(
92
- "cluster-groups/<uuid:pk>/changelog/",
93
- ObjectChangeLogView.as_view(),
94
- name="clustergroup_changelog",
95
- kwargs={"model": ClusterGroup},
96
- ),
97
- path(
98
- "cluster-groups/<uuid:pk>/notes/",
99
- ObjectNotesView.as_view(),
100
- name="clustergroup_notes",
101
- kwargs={"model": ClusterGroup},
102
- ),
103
18
  # Clusters
104
19
  path("clusters/", views.ClusterListView.as_view(), name="cluster_list"),
105
20
  path("clusters/add/", views.ClusterEditView.as_view(), name="cluster_add"),
@@ -266,3 +181,5 @@ urlpatterns = [
266
181
  name="virtualmachine_bulk_add_vminterface",
267
182
  ),
268
183
  ]
184
+
185
+ urlpatterns += router.urls
@@ -4,18 +4,18 @@ from django.db.models import Prefetch
4
4
  from django.shortcuts import get_object_or_404, redirect, render
5
5
  from django.urls import reverse
6
6
  from django.utils.functional import cached_property
7
- from django_tables2 import RequestConfig
8
7
 
9
8
  from nautobot.core.ui import object_detail
10
9
  from nautobot.core.ui.choices import SectionChoices
11
10
  from nautobot.core.utils.requests import normalize_querydict
12
11
  from nautobot.core.views import generic
13
- from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
12
+ from nautobot.core.views.viewsets import NautobotUIViewSet
14
13
  from nautobot.dcim.models import Device
15
14
  from nautobot.dcim.tables import DeviceTable
16
15
  from nautobot.extras.views import ObjectConfigContextView
17
16
  from nautobot.ipam.models import IPAddress, Service
18
17
  from nautobot.ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable, VRFDeviceAssignmentTable
18
+ from nautobot.virtualization.api import serializers
19
19
 
20
20
  from . import filters, forms, tables
21
21
  from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
@@ -25,15 +25,15 @@ from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterf
25
25
  #
26
26
 
27
27
 
28
- class ClusterTypeListView(generic.ObjectListView):
28
+ class ClusterTypeUIViewSet(NautobotUIViewSet):
29
+ bulk_update_form_class = forms.ClusterTypeBulkEditForm
30
+ filterset_class = filters.ClusterTypeFilterSet
31
+ filterset_form_class = forms.ClusterTypeFilterForm
32
+ form_class = forms.ClusterTypeForm
33
+ serializer_class = serializers.ClusterTypeSerializer
34
+ table_class = tables.ClusterTypeTable
29
35
  queryset = ClusterType.objects.all()
30
- filterset = filters.ClusterTypeFilterSet
31
- filterset_form = forms.ClusterTypeFilterForm
32
- table = tables.ClusterTypeTable
33
36
 
34
-
35
- class ClusterTypeView(generic.ObjectView):
36
- queryset = ClusterType.objects.all()
37
37
  object_detail_content = object_detail.ObjectDetailContent(
38
38
  panels=(
39
39
  object_detail.ObjectFieldsPanel(
@@ -48,79 +48,40 @@ class ClusterTypeView(generic.ObjectView):
48
48
  table_filter="cluster_type",
49
49
  exclude_columns=["cluster_type"],
50
50
  ),
51
- ),
51
+ )
52
52
  )
53
53
 
54
54
 
55
- class ClusterTypeEditView(generic.ObjectEditView):
56
- queryset = ClusterType.objects.all()
57
- model_form = forms.ClusterTypeForm
58
-
59
-
60
- class ClusterTypeDeleteView(generic.ObjectDeleteView):
61
- queryset = ClusterType.objects.all()
62
-
63
-
64
- class ClusterTypeBulkImportView(generic.BulkImportView): # 3.0 TODO: remove, unused
65
- queryset = ClusterType.objects.all()
66
- table = tables.ClusterTypeTable
67
-
68
-
69
- class ClusterTypeBulkDeleteView(generic.BulkDeleteView):
70
- queryset = ClusterType.objects.all()
71
- table = tables.ClusterTypeTable
72
- filterset = filters.ClusterTypeFilterSet
73
-
74
-
75
55
  #
76
56
  # Cluster groups
77
57
  #
78
58
 
79
59
 
80
- class ClusterGroupListView(generic.ObjectListView):
81
- queryset = ClusterGroup.objects.all()
82
- filterset = filters.ClusterGroupFilterSet
83
- filterset_form = forms.ClusterGroupFilterForm
84
- table = tables.ClusterGroupTable
85
-
86
-
87
- class ClusterGroupView(generic.ObjectView):
60
+ class ClusterGroupUIViewSet(NautobotUIViewSet):
61
+ bulk_update_form_class = forms.ClusterGroupBulkEditForm
62
+ filterset_class = filters.ClusterGroupFilterSet
63
+ filterset_form_class = forms.ClusterGroupFilterForm
64
+ form_class = forms.ClusterGroupForm
65
+ serializer_class = serializers.ClusterGroupSerializer
66
+ table_class = tables.ClusterGroupTable
88
67
  queryset = ClusterGroup.objects.all()
89
68
 
90
- def get_extra_context(self, request, instance):
91
- # Clusters
92
- clusters = Cluster.objects.restrict(request.user, "view").filter(cluster_group=instance)
93
-
94
- cluster_table = tables.ClusterTable(clusters)
95
- cluster_table.columns.hide("cluster_group")
96
-
97
- paginate = {
98
- "paginator_class": EnhancedPaginator,
99
- "per_page": get_paginate_count(request),
100
- }
101
- RequestConfig(request, paginate).configure(cluster_table)
102
-
103
- return {"cluster_table": cluster_table, **super().get_extra_context(request, instance)}
104
-
105
-
106
- class ClusterGroupEditView(generic.ObjectEditView):
107
- queryset = ClusterGroup.objects.all()
108
- model_form = forms.ClusterGroupForm
109
-
110
-
111
- class ClusterGroupDeleteView(generic.ObjectDeleteView):
112
- queryset = ClusterGroup.objects.all()
113
-
114
-
115
- class ClusterGroupBulkImportView(generic.BulkImportView): # 3.0 TODO: remove, unused
116
- queryset = ClusterGroup.objects.all()
117
- table = tables.ClusterGroupTable
118
-
119
-
120
- class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
121
- queryset = ClusterGroup.objects.all()
122
- table = tables.ClusterGroupTable
123
- filterset = filters.ClusterGroupFilterSet
69
+ object_detail_content = object_detail.ObjectDetailContent(
70
+ panels=(
71
+ object_detail.ObjectFieldsPanel(
72
+ weight=100,
73
+ section=SectionChoices.LEFT_HALF,
74
+ fields="__all__",
75
+ ),
76
+ object_detail.ObjectsTablePanel(
77
+ weight=100,
78
+ section=SectionChoices.RIGHT_HALF,
79
+ table_class=tables.ClusterTable,
80
+ table_filter="cluster_group",
81
+ exclude_columns=["cluster_group"],
82
+ ),
83
+ )
84
+ )
124
85
 
125
86
 
126
87
  #
@@ -1,21 +1,21 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nautobot
3
- Version: 2.4.5
3
+ Version: 2.4.7
4
4
  Summary: Source of truth and network automation platform.
5
5
  Home-page: https://nautobot.com
6
6
  License: Apache-2.0
7
7
  Keywords: Nautobot
8
8
  Author: Network to Code
9
9
  Author-email: opensource@networktocode.com
10
- Requires-Python: >=3.9,<3.13
10
+ Requires-Python: >=3.9.2,<3.13
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: License :: OSI Approved :: Apache Software License
14
14
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.9
16
15
  Classifier: Programming Language :: Python :: 3.10
17
16
  Classifier: Programming Language :: Python :: 3.11
18
17
  Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.9
19
19
  Provides-Extra: all
20
20
  Provides-Extra: ldap
21
21
  Provides-Extra: mysql
@@ -29,6 +29,7 @@ Requires-Dist: Markdown (>=3.6,<3.7)
29
29
  Requires-Dist: Pillow (>=11.0.0,<11.1.0)
30
30
  Requires-Dist: PyYAML (>=6.0.2,<6.1.0)
31
31
  Requires-Dist: celery (>=5.3.6,<5.4.0)
32
+ Requires-Dist: cryptography (>=44.0.2,<44.1.0)
32
33
  Requires-Dist: django-ajax-tables (>=1.1.1,<1.2.0)
33
34
  Requires-Dist: django-auth-ldap (>=5.1.0,<5.2.0) ; extra == "all" or extra == "ldap"
34
35
  Requires-Dist: django-celery-beat (>=2.6.0,<2.7.0)
@@ -57,12 +58,12 @@ Requires-Dist: graphene-django (>=2.16.0,<2.17.0)
57
58
  Requires-Dist: graphene-django-optimizer (>=0.8.0,<0.9.0)
58
59
  Requires-Dist: jsonschema (>=4.7.0,<5.0.0)
59
60
  Requires-Dist: kombu (>=5.4.2,<5.5.0)
60
- Requires-Dist: kubernetes (>=32.0.0,<33.0.0)
61
+ Requires-Dist: kubernetes (>=32.0.1,<33.0.0)
61
62
  Requires-Dist: mysqlclient (>=2.2.7,<2.3.0) ; extra == "all" or extra == "mysql"
62
63
  Requires-Dist: napalm (>=4.1.0,<6.0.0) ; extra == "all" or extra == "napalm"
63
64
  Requires-Dist: netaddr (>=1.3.0,<1.4.0)
64
65
  Requires-Dist: netutils (>=1.6.0,<2.0.0)
65
- Requires-Dist: nh3 (>=0.2.20,<0.3.0)
66
+ Requires-Dist: nh3 (>=0.2.21,<0.3.0)
66
67
  Requires-Dist: packaging (>=23.1)
67
68
  Requires-Dist: prometheus-client (>=0.20.0,<0.21.0)
68
69
  Requires-Dist: psycopg2-binary (>=2.9.10,<2.10.0)