nautobot 2.2.0__py3-none-any.whl → 2.2.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 (362) hide show
  1. nautobot/apps/api.py +2 -1
  2. nautobot/apps/utils.py +0 -4
  3. nautobot/apps/views.py +0 -2
  4. nautobot/circuits/api/urls.py +2 -1
  5. nautobot/circuits/api/views.py +12 -0
  6. nautobot/circuits/tests/test_filters.py +1 -1
  7. nautobot/core/api/routers.py +3 -25
  8. nautobot/core/api/utils.py +0 -4
  9. nautobot/core/api/views.py +15 -21
  10. nautobot/core/filters.py +1 -7
  11. nautobot/core/management/commands/generate_test_data.py +4 -4
  12. nautobot/core/settings.py +0 -1
  13. nautobot/core/tables.py +1 -2
  14. nautobot/core/templates/admin/base.html +94 -23
  15. nautobot/core/templates/graphene/graphiql.html +47 -18
  16. nautobot/core/templates/inc/footer.html +5 -5
  17. nautobot/core/templates/inc/nav_menu.html +7 -0
  18. nautobot/core/templates/rest_framework/api.html +5 -12
  19. nautobot/core/templatetags/helpers.py +2 -2
  20. nautobot/core/testing/views.py +0 -30
  21. nautobot/core/tests/test_api.py +6 -13
  22. nautobot/core/tests/test_csv.py +4 -5
  23. nautobot/core/tests/test_filters.py +1 -2
  24. nautobot/core/tests/test_graphql.py +14 -4
  25. nautobot/core/tests/test_navigations.py +0 -3
  26. nautobot/core/tests/test_views.py +16 -22
  27. nautobot/core/utils/lookup.py +0 -124
  28. nautobot/core/views/__init__.py +7 -3
  29. nautobot/core/views/generic.py +3 -19
  30. nautobot/core/views/mixins.py +0 -7
  31. nautobot/core/views/renderers.py +1 -4
  32. nautobot/dcim/api/serializers.py +4 -4
  33. nautobot/dcim/api/urls.py +3 -2
  34. nautobot/dcim/api/views.py +18 -7
  35. nautobot/dcim/factory.py +7 -7
  36. nautobot/dcim/filters/__init__.py +17 -16
  37. nautobot/dcim/forms.py +45 -61
  38. nautobot/dcim/homepage.py +3 -11
  39. nautobot/dcim/migrations/0057_controller_models.py +70 -11
  40. nautobot/dcim/models/__init__.py +2 -2
  41. nautobot/dcim/models/devices.py +16 -14
  42. nautobot/dcim/models/racks.py +3 -1
  43. nautobot/dcim/navigation.py +31 -23
  44. nautobot/dcim/signals.py +6 -6
  45. nautobot/dcim/tables/__init__.py +2 -2
  46. nautobot/dcim/tables/devices.py +15 -12
  47. nautobot/dcim/tables/template_code.py +1 -1
  48. nautobot/dcim/templates/dcim/controller_retrieve.html +18 -35
  49. nautobot/dcim/templates/dcim/controllerdevicegroup_create.html +43 -0
  50. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +43 -67
  51. nautobot/dcim/templates/dcim/device.html +2 -10
  52. nautobot/dcim/templates/dcim/device_edit.html +1 -1
  53. nautobot/dcim/tests/test_api.py +6 -11
  54. nautobot/dcim/tests/test_filters.py +81 -92
  55. nautobot/dcim/tests/test_graphql.py +1 -11
  56. nautobot/dcim/tests/test_models.py +15 -15
  57. nautobot/dcim/tests/test_signals.py +0 -2
  58. nautobot/dcim/tests/test_views.py +12 -24
  59. nautobot/dcim/urls.py +1 -1
  60. nautobot/dcim/views.py +15 -19
  61. nautobot/extras/api/urls.py +2 -1
  62. nautobot/extras/api/views.py +10 -0
  63. nautobot/extras/filters/__init__.py +2 -53
  64. nautobot/extras/forms/contacts.py +0 -7
  65. nautobot/extras/managers.py +0 -14
  66. nautobot/extras/navigation.py +65 -71
  67. nautobot/extras/plugins/views.py +11 -7
  68. nautobot/extras/tests/test_api.py +0 -2
  69. nautobot/extras/tests/test_dynamicgroups.py +0 -2
  70. nautobot/extras/tests/test_filters.py +4 -89
  71. nautobot/extras/tests/test_models.py +0 -9
  72. nautobot/extras/tests/test_relationships.py +1 -10
  73. nautobot/extras/tests/test_views.py +1 -112
  74. nautobot/extras/views.py +10 -10
  75. nautobot/ipam/api/urls.py +2 -1
  76. nautobot/ipam/api/views.py +11 -0
  77. nautobot/ipam/tables.py +22 -2
  78. nautobot/ipam/tests/test_graphql.py +3 -2
  79. nautobot/ipam/tests/test_views.py +0 -1
  80. nautobot/ipam/views.py +9 -9
  81. nautobot/project-static/css/base.css +0 -1
  82. nautobot/project-static/docs/404.html +3 -24
  83. nautobot/project-static/docs/apps/index.html +3 -24
  84. nautobot/project-static/docs/apps/nautobot-apps.html +3 -24
  85. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +3 -24
  86. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +3 -24
  87. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +5 -26
  88. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +3 -24
  89. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +3 -24
  90. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +3 -24
  91. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +3 -24
  92. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +3 -24
  93. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +3 -24
  94. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +3 -24
  95. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +3 -24
  96. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +3 -24
  97. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +3 -24
  98. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +3 -24
  99. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +3 -24
  100. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +3 -24
  101. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +3 -24
  102. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +3 -24
  103. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +3 -24
  104. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +3 -24
  105. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +3 -24
  106. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +3 -242
  107. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +5 -69
  108. nautobot/project-static/docs/development/apps/api/configuration-view.html +3 -24
  109. nautobot/project-static/docs/development/apps/api/database-backend-config.html +3 -24
  110. nautobot/project-static/docs/development/apps/api/models/django-admin.html +3 -24
  111. nautobot/project-static/docs/development/apps/api/models/global-search.html +3 -24
  112. nautobot/project-static/docs/development/apps/api/models/graphql.html +3 -24
  113. nautobot/project-static/docs/development/apps/api/models/index.html +3 -24
  114. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +3 -24
  115. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +3 -24
  116. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +3 -24
  117. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +3 -24
  118. nautobot/project-static/docs/development/apps/api/platform-features/index.html +3 -24
  119. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +3 -24
  120. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +3 -24
  121. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +3 -24
  122. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +3 -24
  123. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +3 -24
  124. nautobot/project-static/docs/development/apps/api/prometheus.html +3 -24
  125. nautobot/project-static/docs/development/apps/api/setup.html +3 -24
  126. nautobot/project-static/docs/development/apps/api/testing.html +3 -24
  127. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +3 -24
  128. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +3 -24
  129. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +3 -24
  130. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +3 -24
  131. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +3 -24
  132. nautobot/project-static/docs/development/apps/api/views/base-template.html +3 -24
  133. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +12 -38
  134. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +15 -41
  135. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +3 -24
  136. nautobot/project-static/docs/development/apps/api/views/index.html +3 -24
  137. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +3 -24
  138. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +3 -24
  139. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +3 -24
  140. nautobot/project-static/docs/development/apps/api/views/notes.html +3 -24
  141. nautobot/project-static/docs/development/apps/api/views/rest-api.html +3 -24
  142. nautobot/project-static/docs/development/apps/api/views/urls.html +3 -24
  143. nautobot/project-static/docs/development/apps/index.html +3 -24
  144. nautobot/project-static/docs/development/apps/migration/code-updates.html +3 -24
  145. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +3 -24
  146. nautobot/project-static/docs/development/apps/migration/from-v1.html +3 -24
  147. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +3 -24
  148. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +3 -24
  149. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +3 -24
  150. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +3 -24
  151. nautobot/project-static/docs/development/apps/porting-from-netbox.html +3 -24
  152. nautobot/project-static/docs/development/core/application-registry.html +3 -24
  153. nautobot/project-static/docs/development/core/best-practices.html +3 -24
  154. nautobot/project-static/docs/development/core/bootstrap-ui.html +3 -24
  155. nautobot/project-static/docs/development/core/caching.html +3 -24
  156. nautobot/project-static/docs/development/core/controllers.html +204 -35
  157. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +3 -24
  158. nautobot/project-static/docs/development/core/extending-models.html +3 -24
  159. nautobot/project-static/docs/development/core/generic-views.html +3 -24
  160. nautobot/project-static/docs/development/core/getting-started.html +13 -43
  161. nautobot/project-static/docs/development/core/homepage.html +3 -24
  162. nautobot/project-static/docs/development/core/index.html +3 -24
  163. nautobot/project-static/docs/development/core/model-features.html +3 -24
  164. nautobot/project-static/docs/development/core/natural-keys.html +3 -24
  165. nautobot/project-static/docs/development/core/navigation-menu.html +3 -24
  166. nautobot/project-static/docs/development/core/release-checklist.html +3 -24
  167. nautobot/project-static/docs/development/core/role-internals.html +3 -24
  168. nautobot/project-static/docs/development/core/settings.html +3 -24
  169. nautobot/project-static/docs/development/core/style-guide.html +3 -24
  170. nautobot/project-static/docs/development/core/templates.html +3 -24
  171. nautobot/project-static/docs/development/core/testing.html +3 -24
  172. nautobot/project-static/docs/development/core/user-preferences.html +3 -24
  173. nautobot/project-static/docs/development/index.html +3 -24
  174. nautobot/project-static/docs/development/jobs/index.html +3 -24
  175. nautobot/project-static/docs/development/jobs/migration/from-v1.html +3 -24
  176. nautobot/project-static/docs/index.html +3 -24
  177. nautobot/project-static/docs/models/dcim/{controllermanageddevicegroup.html → controllerdevicegroup.html} +3 -3
  178. nautobot/project-static/docs/objects.inv +0 -0
  179. nautobot/project-static/docs/release-notes/index.html +3 -24
  180. nautobot/project-static/docs/release-notes/version-1.0.html +3 -24
  181. nautobot/project-static/docs/release-notes/version-1.1.html +3 -24
  182. nautobot/project-static/docs/release-notes/version-1.2.html +3 -24
  183. nautobot/project-static/docs/release-notes/version-1.3.html +3 -24
  184. nautobot/project-static/docs/release-notes/version-1.4.html +3 -24
  185. nautobot/project-static/docs/release-notes/version-1.5.html +3 -24
  186. nautobot/project-static/docs/release-notes/version-1.6.html +3 -24
  187. nautobot/project-static/docs/release-notes/version-2.0.html +3 -24
  188. nautobot/project-static/docs/release-notes/version-2.1.html +162 -411
  189. nautobot/project-static/docs/release-notes/version-2.2.html +30 -212
  190. nautobot/project-static/docs/search/search_index.json +1 -1
  191. nautobot/project-static/docs/sitemap.xml +255 -260
  192. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  193. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +3 -24
  194. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +3 -24
  195. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +3 -24
  196. nautobot/project-static/docs/user-guide/administration/configuration/index.html +3 -24
  197. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +3 -24
  198. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +3 -24
  199. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +3 -24
  200. nautobot/project-static/docs/user-guide/administration/guides/caching.html +3 -24
  201. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +3 -24
  202. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +3 -24
  203. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +3 -24
  204. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +3 -24
  205. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +3 -24
  206. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +3 -24
  207. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +3 -24
  208. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +3 -24
  209. nautobot/project-static/docs/user-guide/administration/installation/docker.html +6 -31
  210. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +3 -24
  211. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +3 -24
  212. nautobot/project-static/docs/user-guide/administration/installation/index.html +3 -24
  213. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +3 -24
  214. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +3 -24
  215. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +6 -27
  216. nautobot/project-static/docs/user-guide/administration/installation/services.html +3 -24
  217. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +3 -24
  218. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +3 -24
  219. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +3 -24
  220. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +3 -24
  221. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +3 -24
  222. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +3 -24
  223. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +3 -24
  224. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +3 -24
  225. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +3 -24
  226. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +3 -24
  227. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +3 -24
  228. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +3 -24
  229. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +3 -24
  230. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +3 -24
  231. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +3 -24
  232. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +3 -24
  233. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +3 -24
  234. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +3 -24
  235. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +3 -24
  236. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +3 -24
  237. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +3 -24
  238. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +3 -24
  239. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +3 -24
  240. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -259
  241. nautobot/project-static/docs/user-guide/core-data-model/dcim/{controllermanageddevicegroup.html → controllerdevicegroup.html} +17 -107
  242. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +3 -24
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +3 -24
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +3 -24
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +3 -24
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +3 -24
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +3 -24
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +3 -24
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +3 -24
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +3 -24
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +3 -24
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +3 -24
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +3 -24
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +3 -24
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +3 -24
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +3 -24
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +3 -24
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +3 -24
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +3 -24
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +3 -24
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +3 -24
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +3 -24
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +3 -24
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +3 -24
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +3 -24
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +3 -24
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +3 -24
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +3 -24
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +3 -24
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +3 -24
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +3 -24
  272. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +6 -27
  273. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +3 -24
  274. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +3 -24
  275. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +3 -24
  276. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +3 -24
  277. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +3 -24
  278. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +3 -24
  279. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +3 -24
  280. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +3 -24
  281. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +3 -24
  282. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +3 -24
  283. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +3 -24
  284. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +3 -24
  285. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +3 -24
  286. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +3 -24
  287. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +3 -24
  288. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +3 -24
  289. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +3 -24
  290. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +3 -24
  291. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +3 -24
  292. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +3 -24
  293. nautobot/project-static/docs/user-guide/feature-guides/{contacts-and-teams.html → contact-and-team.html} +4 -25
  294. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +5 -26
  295. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +3 -24
  296. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +3 -24
  297. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +3 -24
  298. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +3 -24
  299. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +3 -24
  300. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +3 -24
  301. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +5 -26
  302. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +3 -24
  303. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +3 -24
  304. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +3 -24
  305. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +3 -24
  306. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +3 -24
  307. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +3 -24
  308. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +3 -24
  309. nautobot/project-static/docs/user-guide/index.html +3 -24
  310. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +3 -24
  311. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +3 -24
  312. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +3 -24
  313. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +3 -24
  314. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +3 -24
  315. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +3 -24
  316. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +3 -24
  317. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +3 -24
  318. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +3 -24
  319. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +3 -24
  320. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +3 -24
  321. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +3 -24
  322. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +3 -24
  323. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +3 -24
  324. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +3 -24
  325. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +3 -24
  326. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +3 -24
  327. nautobot/project-static/docs/user-guide/platform-functionality/note.html +3 -24
  328. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +3 -24
  329. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +3 -24
  330. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +3 -24
  331. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +3 -24
  332. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +3 -24
  333. nautobot/project-static/docs/user-guide/platform-functionality/role.html +3 -24
  334. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +3 -24
  335. nautobot/project-static/docs/user-guide/platform-functionality/status.html +3 -24
  336. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +3 -24
  337. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +3 -24
  338. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +3 -24
  339. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +3 -24
  340. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +3 -24
  341. nautobot/tenancy/api/urls.py +2 -1
  342. nautobot/tenancy/api/views.py +12 -0
  343. nautobot/tenancy/tables.py +1 -1
  344. nautobot/tenancy/tests/test_views.py +0 -1
  345. nautobot/users/api/urls.py +2 -1
  346. nautobot/users/api/views.py +65 -2
  347. nautobot/users/views.py +8 -8
  348. nautobot/virtualization/api/urls.py +2 -1
  349. nautobot/virtualization/api/views.py +12 -0
  350. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/METADATA +3 -3
  351. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/RECORD +356 -361
  352. nautobot/core/tests/integration/test_view_authentication.py +0 -67
  353. nautobot/dcim/management/commands/migrate_location_contacts.py +0 -218
  354. nautobot/dcim/templates/dcim/controller_create.html +0 -70
  355. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +0 -88
  356. nautobot/ipam/tests/test_tables.py +0 -42
  357. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +0 -8581
  358. /nautobot/dcim/templates/dcim/{controllermanageddevicegroup_retrieve.html → controllerdevicegroup_retrieve.html} +0 -0
  359. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/LICENSE.txt +0 -0
  360. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/NOTICE +0 -0
  361. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/WHEEL +0 -0
  362. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,43 @@
1
+ {% extends 'generic/object_create.html' %}
2
+ {% load form_helpers %}
3
+ {% load helpers %}
4
+ {% load static %}
5
+
6
+ {% block javascript %}
7
+ <script type="text/javascript">
8
+ const parentInput = $('select#id_parent');
9
+ const controllerInput = $('select#id_controller');
10
+
11
+ const controllerUrl = '{% url 'dcim-api:controllerdevicegroup-list' %}';
12
+
13
+ const updateControllerFromParent = (parentUuid) => {
14
+ $.ajax({
15
+ url: `${controllerUrl}${parentUuid}/`,
16
+ method: "GET",
17
+ success: (data) => {
18
+ if (data.controller) {
19
+ controllerInput.val(data.controller.id);
20
+ }
21
+ },
22
+ error: (error) => console.log("ERROR", error),
23
+ });
24
+ };
25
+
26
+ const onParentInput = (event) => {
27
+ const parentUuid = parentInput.val();
28
+ if (parentUuid) {
29
+ controllerInput.prop("disabled", true);
30
+ if (event) {
31
+ updateControllerFromParent(parentUuid);
32
+ }
33
+ } else {
34
+ controllerInput.prop("disabled", false);
35
+ }
36
+ }
37
+
38
+ parentInput.on('select2:select', onParentInput);
39
+ parentInput.on('select2:unselect', onParentInput);
40
+
41
+ onParentInput();
42
+ </script>
43
+ {% endblock %}
@@ -15,7 +15,6 @@
15
15
  <th>Interface</th>
16
16
  <th>Configured Device</th>
17
17
  <th>Configured Interface</th>
18
- <th>Configured MAC Address</th>
19
18
  <th>LLDP Device</th>
20
19
  <th>LLDP Interface</th>
21
20
  </tr>
@@ -28,21 +27,18 @@
28
27
  <td class="configured_device" data="{{ iface.connected_endpoint.device }}" data-chassis="{{ iface.connected_endpoint.device.virtual_chassis.name }}">
29
28
  {{ iface.connected_endpoint.device|hyperlinked_object }}
30
29
  </td>
31
- <td class="configured_interface" data-interface-name="{{ iface.connected_endpoint }}">
30
+ <td class="configured_interface" data="{{ iface.connected_endpoint }}">
32
31
  <span title="{{ iface.connected_endpoint.get_type_display }}">{{ iface.connected_endpoint }}</span>
33
32
  </td>
34
- <td class="configured_mac" data-mac-address="{{ iface.connected_endpoint.mac_address }}">
35
- <span>{{ iface.connected_endpoint.mac_address }}</span>
36
- </td>
37
33
  {% elif iface.connected_endpoint.circuit %}
38
34
  {% with circuit=iface.connected_endpoint.circuit %}
39
- <td colspan="3">
35
+ <td colspan="2">
40
36
  <i class="mdi mdi-lightning-bolt" title="Circuit"></i>
41
37
  <a href="{{ circuit.get_absolute_url }}">{{ circuit.provider }} {{ circuit }}</a>
42
38
  </td>
43
39
  {% endwith %}
44
40
  {% else %}
45
- <td colspan="3">None</td>
41
+ <td colspan="2">None</td>
46
42
  {% endif %}
47
43
  <td class="device"></td>
48
44
  <td class="interface"></td>
@@ -56,71 +52,51 @@
56
52
  {% block javascript %}
57
53
  {{ block.super }}
58
54
  <script type="text/javascript">
59
- var ready = (callback) => {
60
- if (document.readyState != "loading") {
61
- callback();
62
- } else {
63
- document.addEventListener("DOMContentLoaded", callback);
64
- }
65
- };
66
-
67
- ready(() => {
68
- fetch("{% url 'dcim-api:device-napalm' pk=object.pk %}?method=get_lldp_neighbors_detail")
69
- .then((response) => {
70
- if (!response.ok) {
71
- throw Error(response.statusText);
72
- }
73
- return response.json();
74
- })
75
- .then((data) => {
76
- const interfaces = data["get_lldp_neighbors_detail"];
77
- for (var iface of Object.keys(interfaces)) {
78
- const neighbor = interfaces[iface][0];
79
- const row = document.querySelector('*[data-interface-name="'+ iface.split(".")[0].replace(/([\/:])/g, "\\$1") + '"]');
80
- // var row = $('*[data-interface-name="' + iface.split(".")[0].replace(/([\/:])/g, "\\$1") + '"]');
55
+ $(document).ready(function() {
56
+ $.ajax({
57
+ url: "{% url 'dcim-api:device-napalm' pk=object.pk %}?method=get_lldp_neighbors_detail",
58
+ dataType: 'json',
59
+ success: function(json) {
60
+ $.each(json['get_lldp_neighbors_detail'], function(iface, neighbors) {
61
+ var neighbor = neighbors[0];
62
+ var row = $('*[data-interface-name="' + iface.split(".")[0].replace(/([\/:])/g, "\\$1") + '"]');
81
63
 
82
- // Glean configured hostnames/interfaces from the DOM
83
- const configured_device = row.querySelector('td.configured_device').getAttribute('data');
84
- const configured_chassis = row.querySelector('td.configured_device').getAttribute('data-chassis');
85
- const configured_interface = row.querySelector('td.configured_interface').getAttribute('data-interface-name').toLowerCase();
86
- const configured_mac_address = row.querySelector('td.configured_mac').getAttribute('data-mac-address').toLowerCase();
87
- let configured_interface_short = null;
88
- if (configured_interface) {
89
- // Match long-form IOS names against short ones (e.g. Gi0/1 == GigabitEthernet0/1).
90
- configured_interface_short = configured_interface.replace(/^([A-Z][a-z])[^0-9]*([0-9\/]+)$/, "$1$2");
91
- }
64
+ // Glean configured hostnames/interfaces from the DOM
65
+ var configured_device = row.children('td.configured_device').attr('data');
66
+ var configured_chassis = row.children('td.configured_device').attr('data-chassis');
67
+ var configured_interface = row.children('td.configured_interface').attr('data');
68
+ var configured_interface_short = null;
69
+ if (configured_interface) {
70
+ // Match long-form IOS names against short ones (e.g. Gi0/1 == GigabitEthernet0/1).
71
+ configured_interface_short = configured_interface.replace(/^([A-Z][a-z])[^0-9]*([0-9\/]+)$/, "$1$2");
72
+ }
92
73
 
93
- // Clean up hostnames/interfaces learned via LLDP
94
- const neighbor_host = neighbor['remote_system_name'] || ""; // sanitize hostname if it's null to avoid breaking the split func
95
- const neighbor_port = neighbor['remote_port'] || ""; // sanitize port if it's null to avoid breaking the split func
96
- const lldp_device = neighbor_host.split(".")[0]; // Strip off any trailing domain name
97
- const lldp_interface = neighbor_port.split(".")[0].toLowerCase(); // Strip off any trailing subinterface ID
74
+ // Clean up hostnames/interfaces learned via LLDP
75
+ var neighbor_host = neighbor['remote_system_name'] || ""; // sanitize hostname if it's null to avoid breaking the split func
76
+ var neighbor_port = neighbor['remote_port'] || ""; // sanitize port if it's null to avoid breaking the split func
77
+ var lldp_device = neighbor_host.split(".")[0]; // Strip off any trailing domain name
78
+ var lldp_interface = neighbor_port.split(".")[0]; // Strip off any trailing subinterface ID
98
79
 
99
- // Add LLDP neighbors to table
100
- row.querySelector('td.device').textContent = lldp_device;
101
- row.querySelector('td.interface').textContent = lldp_interface;
80
+ // Add LLDP neighbors to table
81
+ row.children('td.device').html(lldp_device);
82
+ row.children('td.interface').html(lldp_interface);
102
83
 
103
- // Apply colors to rows
104
- if (!configured_device && lldp_device) {
105
- row.classList.add('info');
106
- } else if ((configured_device == lldp_device || configured_chassis == lldp_device) && configured_interface == lldp_interface) {
107
- row.classList.add('success');
108
- } else if ((configured_device == lldp_device || configured_chassis == lldp_device) && configured_interface_short == lldp_interface) {
109
- row.classList.add('success');
110
- } else if ((configured_device == lldp_device || configured_chassis == lldp_device) && configured_mac_address == lldp_interface) {
111
- row.classList.add('success');
112
- } else {
113
- row.classList.add('danger');
114
- }
115
- }
116
- })
117
- .catch((error) => {
118
- if (error.responseText) {
119
- alert(error.responseText);
120
- } else {
121
- throw error;
84
+ // Apply colors to rows
85
+ if (!configured_device && lldp_device) {
86
+ row.addClass('info');
87
+ } else if ((configured_device == lldp_device || configured_chassis == lldp_device) && configured_interface == lldp_interface) {
88
+ row.addClass('success');
89
+ } else if ((configured_device == lldp_device || configured_chassis == lldp_device) && configured_interface_short == lldp_interface) {
90
+ row.addClass('success');
91
+ } else {
92
+ row.addClass('danger');
93
+ }
94
+ });
95
+ },
96
+ error: function(xhr) {
97
+ alert(xhr.responseText);
122
98
  }
123
99
  });
124
100
  });
125
101
  </script>
126
- {% endblock %}
102
+ {% endblock %}
@@ -206,19 +206,11 @@
206
206
  </td>
207
207
  </tr>
208
208
  <tr>
209
- <td>Controller Managed Device Group</td>
209
+ <td>Controller Device Group</td>
210
210
  <td>
211
- {{ object.controller_managed_device_group|hyperlinked_object }}
211
+ {{ object.controller_device_group|hyperlinked_object }}
212
212
  </td>
213
213
  </tr>
214
- {% if object.controller_managed_device_group %}
215
- <tr>
216
- <td>Managed by Controller</td>
217
- <td>
218
- {{ object.controller_managed_device_group.controller|hyperlinked_object }}
219
- </td>
220
- </tr>
221
- {% endif %}
222
214
  {% if object.cluster %}
223
215
  <tr>
224
216
  <td>Cluster</td>
@@ -90,7 +90,7 @@
90
90
  {% render_field form.secrets_group %}
91
91
  {% render_field form.device_redundancy_group %}
92
92
  {% render_field form.device_redundancy_group_priority %}
93
- {% render_field form.controller_managed_device_group %}
93
+ {% render_field form.controller_device_group %}
94
94
  </div>
95
95
  </div>
96
96
  <div class="panel panel-default">
@@ -26,7 +26,7 @@ from nautobot.dcim.models import (
26
26
  ConsoleServerPort,
27
27
  ConsoleServerPortTemplate,
28
28
  Controller,
29
- ControllerManagedDeviceGroup,
29
+ ControllerDeviceGroup,
30
30
  Device,
31
31
  DeviceBay,
32
32
  DeviceBayTemplate,
@@ -771,7 +771,6 @@ class ManufacturerTest(APIViewTestCases.APIViewTestCase):
771
771
  # FIXME: This has to be replaced with# `get_deletable_object` and
772
772
  # `get_deletable_object_pks` but this is a workaround just so all of these objects are
773
773
  # deletable for now.
774
- Controller.objects.filter(controller_device__isnull=False).delete()
775
774
  Device.objects.all().delete()
776
775
  DeviceType.objects.all().delete()
777
776
  Platform.objects.all().delete()
@@ -1167,7 +1166,6 @@ class DeviceTest(APIViewTestCases.APIViewTestCase):
1167
1166
 
1168
1167
  @classmethod
1169
1168
  def setUpTestData(cls):
1170
- Controller.objects.filter(controller_device__isnull=False).delete()
1171
1169
  Device.objects.all().delete()
1172
1170
  locations = Location.objects.filter(location_type=LocationType.objects.get(name="Campus"))[:2]
1173
1171
 
@@ -2170,10 +2168,7 @@ class ConnectedDeviceTest(APITestCase):
2170
2168
  def test_get_connected_device(self):
2171
2169
  url = reverse("dcim-api:connected-device-list")
2172
2170
  response = self.client.get(url + "?peer_device=TestDevice2&peer_interface=eth0", **self.header)
2173
- self.assertHttpStatus(response, status.HTTP_404_NOT_FOUND)
2174
2171
 
2175
- self.add_permissions("dcim.view_interface")
2176
- response = self.client.get(url + "?peer_device=TestDevice2&peer_interface=eth0", **self.header)
2177
2172
  self.assertHttpStatus(response, status.HTTP_200_OK)
2178
2173
  self.assertEqual(response.data["name"], self.device1.name)
2179
2174
 
@@ -2818,8 +2813,8 @@ class ControllerTestCase(APIViewTestCases.APIViewTestCase):
2818
2813
  }
2819
2814
 
2820
2815
 
2821
- class ControllerManagedDeviceGroupTestCase(APIViewTestCases.APIViewTestCase):
2822
- model = ControllerManagedDeviceGroup
2816
+ class ControllerDeviceGroupTestCase(APIViewTestCases.APIViewTestCase):
2817
+ model = ControllerDeviceGroup
2823
2818
 
2824
2819
  @classmethod
2825
2820
  def setUpTestData(cls):
@@ -2827,17 +2822,17 @@ class ControllerManagedDeviceGroupTestCase(APIViewTestCases.APIViewTestCase):
2827
2822
 
2828
2823
  cls.create_data = [
2829
2824
  {
2830
- "name": "ControllerManagedDeviceGroup 1",
2825
+ "name": "ControllerDeviceGroup 1",
2831
2826
  "controller": controllers[0].pk,
2832
2827
  "weight": 100,
2833
2828
  },
2834
2829
  {
2835
- "name": "ControllerManagedDeviceGroup 2",
2830
+ "name": "ControllerDeviceGroup 2",
2836
2831
  "controller": controllers[1].pk,
2837
2832
  "weight": 150,
2838
2833
  },
2839
2834
  {
2840
- "name": "ControllerManagedDeviceGroup 3",
2835
+ "name": "ControllerDeviceGroup 3",
2841
2836
  "controller": controllers[2].pk,
2842
2837
  "weight": 200,
2843
2838
  },
@@ -26,8 +26,8 @@ from nautobot.dcim.filters import (
26
26
  ConsolePortTemplateFilterSet,
27
27
  ConsoleServerPortFilterSet,
28
28
  ConsoleServerPortTemplateFilterSet,
29
+ ControllerDeviceGroupFilterSet,
29
30
  ControllerFilterSet,
30
- ControllerManagedDeviceGroupFilterSet,
31
31
  DeviceBayFilterSet,
32
32
  DeviceBayTemplateFilterSet,
33
33
  DeviceFamilyFilterSet,
@@ -68,7 +68,7 @@ from nautobot.dcim.models import (
68
68
  ConsoleServerPort,
69
69
  ConsoleServerPortTemplate,
70
70
  Controller,
71
- ControllerManagedDeviceGroup,
71
+ ControllerDeviceGroup,
72
72
  Device,
73
73
  DeviceBay,
74
74
  DeviceBayTemplate,
@@ -112,7 +112,6 @@ User = get_user_model()
112
112
 
113
113
 
114
114
  def common_test_data(cls):
115
- Controller.objects.filter(controller_device__isnull=False).delete()
116
115
  Device.objects.all().delete()
117
116
  tenants = Tenant.objects.filter(tenant_group__isnull=False)
118
117
  cls.tenants = tenants
@@ -620,82 +619,6 @@ def common_test_data(cls):
620
619
  cls.devices[0].tags.set(Tag.objects.get_for_model(Device))
621
620
  cls.devices[1].tags.set(Tag.objects.get_for_model(Device)[:3])
622
621
 
623
- controller_statuses = iter(Status.objects.get_for_model(Controller))
624
- external_integrations = iter(ExternalIntegration.objects.all())
625
- device_redundancy_groups = iter(DeviceRedundancyGroup.objects.all())
626
-
627
- cls.controllers = (
628
- Controller.objects.create(
629
- name="Controller 1",
630
- status=next(controller_statuses),
631
- description="First",
632
- location=loc0,
633
- platform=platforms[0],
634
- role=cls.device_roles[0],
635
- tenant=tenants[0],
636
- external_integration=next(external_integrations),
637
- controller_device=cls.devices[0],
638
- ),
639
- Controller.objects.create(
640
- name="Controller 2",
641
- status=next(controller_statuses),
642
- description="Second",
643
- location=loc1,
644
- platform=platforms[1],
645
- role=cls.device_roles[1],
646
- tenant=tenants[1],
647
- external_integration=next(external_integrations),
648
- controller_device=cls.devices[1],
649
- ),
650
- Controller.objects.create(
651
- name="Controller 3",
652
- status=next(controller_statuses),
653
- description="Third",
654
- location=loc2,
655
- platform=platforms[2],
656
- role=cls.device_roles[2],
657
- tenant=tenants[2],
658
- external_integration=next(external_integrations),
659
- controller_device_redundancy_group=next(device_redundancy_groups),
660
- ),
661
- Controller.objects.create(
662
- name="Controller 4",
663
- status=next(controller_statuses),
664
- description="Forth",
665
- location=loc2,
666
- platform=platforms[2],
667
- role=cls.device_roles[2],
668
- tenant=tenants[2],
669
- external_integration=next(external_integrations),
670
- controller_device_redundancy_group=next(device_redundancy_groups),
671
- ),
672
- )
673
- cls.controllers[0].tags.set(Tag.objects.get_for_model(Controller))
674
- cls.controllers[1].tags.set(Tag.objects.get_for_model(Controller)[:3])
675
-
676
- parent_controller_managed_device_group = ControllerManagedDeviceGroup.objects.create(
677
- name="Managed Device Group 11",
678
- weight=1000,
679
- controller=cls.controllers[0],
680
- )
681
- cls.controller_managed_device_groups = (
682
- parent_controller_managed_device_group,
683
- ControllerManagedDeviceGroup.objects.create(
684
- name="Managed Device Group 12",
685
- weight=2000,
686
- controller=cls.controllers[1],
687
- parent=parent_controller_managed_device_group,
688
- ),
689
- ControllerManagedDeviceGroup.objects.create(
690
- name="Managed Device Group 13",
691
- weight=3000,
692
- controller=cls.controllers[2],
693
- parent=parent_controller_managed_device_group,
694
- ),
695
- )
696
- parent_controller_managed_device_group.tags.set(Tag.objects.get_for_model(ControllerManagedDeviceGroup))
697
- cls.controller_managed_device_groups[1].tags.set(Tag.objects.get_for_model(ControllerManagedDeviceGroup)[:3])
698
-
699
622
 
700
623
  class LocationTypeFilterSetTestCase(FilterTestCases.NameOnlyFilterTestCase):
701
624
  queryset = LocationType.objects.all()
@@ -1418,8 +1341,8 @@ class DeviceTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilt
1418
1341
  ("device_redundancy_group", "device_redundancy_group__id"),
1419
1342
  ("device_redundancy_group", "device_redundancy_group__name"),
1420
1343
  ("device_redundancy_group_priority",),
1421
- ("controller_managed_device_group", "controller_managed_device_group__id"),
1422
- ("controller_managed_device_group", "controller_managed_device_group__name"),
1344
+ ("controller_device_group", "controller_device_group__id"),
1345
+ ("controller_device_group", "controller_device_group__name"),
1423
1346
  ("device_type", "device_type__id"),
1424
1347
  ("device_type", "device_type__model"),
1425
1348
  ("front_ports", "front_ports__id"),
@@ -1492,19 +1415,19 @@ class DeviceTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilt
1492
1415
  Service.objects.create(device=devices[0], name="ssh", protocol="tcp", ports=[22])
1493
1416
  Service.objects.create(device=devices[1], name="dns", protocol="udp", ports=[53])
1494
1417
 
1495
- cls.controller_managed_device_groups = list(ControllerManagedDeviceGroup.objects.all()[:2])
1418
+ cls.controller_device_groups = list(ControllerDeviceGroup.objects.all()[:2])
1496
1419
  cls.device_redundancy_groups = list(DeviceRedundancyGroup.objects.all()[:2])
1497
1420
  Device.objects.filter(pk=devices[0].pk).update(
1498
- controller_managed_device_group=cls.controller_managed_device_groups[0],
1421
+ controller_device_group=cls.controller_device_groups[0],
1499
1422
  device_redundancy_group=cls.device_redundancy_groups[0],
1500
1423
  )
1501
1424
  Device.objects.filter(pk=devices[1].pk).update(
1502
- controller_managed_device_group=cls.controller_managed_device_groups[0],
1425
+ controller_device_group=cls.controller_device_groups[0],
1503
1426
  device_redundancy_group=cls.device_redundancy_groups[0],
1504
1427
  device_redundancy_group_priority=1,
1505
1428
  )
1506
1429
  Device.objects.filter(pk=devices[2].pk).update(
1507
- controller_managed_device_group=cls.controller_managed_device_groups[1],
1430
+ controller_device_group=cls.controller_device_groups[1],
1508
1431
  device_redundancy_group=cls.device_redundancy_groups[1],
1509
1432
  device_redundancy_group_priority=100,
1510
1433
  )
@@ -3432,20 +3355,63 @@ class ControllerFilterSetTestCase(FilterTestCases.FilterTestCase):
3432
3355
  ("platform", "platform__name"),
3433
3356
  ("external_integration", "external_integration__id"),
3434
3357
  ("external_integration", "external_integration__name"),
3435
- ("controller_device", "controller_device__id"),
3436
- ("controller_device", "controller_device__name"),
3437
- ("controller_device_redundancy_group", "controller_device_redundancy_group__id"),
3438
- ("controller_device_redundancy_group", "controller_device_redundancy_group__name"),
3358
+ ("deployed_controller_device", "deployed_controller_device__id"),
3359
+ ("deployed_controller_device", "deployed_controller_device__name"),
3360
+ ("deployed_controller_group", "deployed_controller_group__id"),
3361
+ ("deployed_controller_group", "deployed_controller_group__name"),
3439
3362
  )
3440
3363
 
3441
3364
  @classmethod
3442
3365
  def setUpTestData(cls):
3443
3366
  common_test_data(cls)
3444
3367
 
3368
+ external_integrations = iter(ExternalIntegration.objects.all())
3369
+ locations = iter(Location.objects.filter(location_type__name="Campus"))
3370
+ platforms = iter(Platform.objects.all())
3371
+ roles = iter(Role.objects.get_for_model(Controller))
3372
+ statuses = iter(Status.objects.get_for_model(Controller))
3373
+ tenants = iter(Tenant.objects.all())
3374
+
3375
+ cls.controllers = (
3376
+ Controller.objects.create(
3377
+ name="Controller 1",
3378
+ status=next(statuses),
3379
+ description="First",
3380
+ location=next(locations),
3381
+ platform=next(platforms),
3382
+ role=next(roles),
3383
+ tenant=next(tenants),
3384
+ external_integration=next(external_integrations),
3385
+ deployed_controller_device=cls.devices[0],
3386
+ ),
3387
+ Controller.objects.create(
3388
+ name="Controller 2",
3389
+ status=next(statuses),
3390
+ description="Second",
3391
+ location=next(locations),
3392
+ platform=next(platforms),
3393
+ role=next(roles),
3394
+ tenant=next(tenants),
3395
+ external_integration=next(external_integrations),
3396
+ deployed_controller_device=cls.devices[1],
3397
+ ),
3398
+ Controller.objects.create(
3399
+ name="Controller 3",
3400
+ status=next(statuses),
3401
+ description="Third",
3402
+ location=next(locations),
3403
+ platform=next(platforms),
3404
+ role=next(roles),
3405
+ tenant=next(tenants),
3406
+ external_integration=next(external_integrations),
3407
+ deployed_controller_group=DeviceRedundancyGroup.objects.first(),
3408
+ ),
3409
+ )
3410
+
3445
3411
 
3446
- class ControllerManagedDeviceGroupFilterSetTestCase(FilterTestCases.FilterTestCase):
3447
- queryset = ControllerManagedDeviceGroup.objects.all()
3448
- filterset = ControllerManagedDeviceGroupFilterSet
3412
+ class ControllerDeviceGroupFilterSetTestCase(FilterTestCases.FilterTestCase):
3413
+ queryset = ControllerDeviceGroup.objects.all()
3414
+ filterset = ControllerDeviceGroupFilterSet
3449
3415
  generic_filter_tests = (
3450
3416
  ("name",),
3451
3417
  ("weight",),
@@ -3458,3 +3424,26 @@ class ControllerManagedDeviceGroupFilterSetTestCase(FilterTestCases.FilterTestCa
3458
3424
  @classmethod
3459
3425
  def setUpTestData(cls):
3460
3426
  common_test_data(cls)
3427
+
3428
+ cls.controllers = Controller.objects.all()[:3]
3429
+
3430
+ group1 = ControllerDeviceGroup.objects.create(
3431
+ name="Controller Device Group 11",
3432
+ weight=1000,
3433
+ controller=cls.controllers[0],
3434
+ )
3435
+ cls.controller_device_groups = (
3436
+ group1,
3437
+ ControllerDeviceGroup.objects.create(
3438
+ name="Controller Device Group 12",
3439
+ weight=2000,
3440
+ controller=cls.controllers[1],
3441
+ parent=group1,
3442
+ ),
3443
+ ControllerDeviceGroup.objects.create(
3444
+ name="Controller Device Group 13",
3445
+ weight=3000,
3446
+ controller=cls.controllers[2],
3447
+ parent=group1,
3448
+ ),
3449
+ )
@@ -4,22 +4,12 @@ from django.test import override_settings
4
4
  from nautobot.core.graphql import execute_query
5
5
  from nautobot.core.testing import create_test_user, TestCase
6
6
  from nautobot.dcim.choices import InterfaceTypeChoices
7
- from nautobot.dcim.models import (
8
- Controller,
9
- Device,
10
- DeviceType,
11
- Interface,
12
- Location,
13
- LocationType,
14
- Manufacturer,
15
- Platform,
16
- )
7
+ from nautobot.dcim.models import Device, DeviceType, Interface, Location, LocationType, Manufacturer, Platform
17
8
  from nautobot.extras.models import DynamicGroup, Role, Status
18
9
 
19
10
 
20
11
  class GraphQLTestCase(TestCase):
21
12
  def setUp(self):
22
- Controller.objects.filter(controller_device__isnull=False).delete()
23
13
  Device.objects.all().delete()
24
14
  self.user = create_test_user("graphql_testuser")
25
15
  self.location = Location.objects.filter(location_type=LocationType.objects.get(name="Campus")).first()
@@ -24,7 +24,7 @@ from nautobot.dcim.models import (
24
24
  ConsoleServerPort,
25
25
  ConsoleServerPortTemplate,
26
26
  Controller,
27
- ControllerManagedDeviceGroup,
27
+ ControllerDeviceGroup,
28
28
  Device,
29
29
  DeviceBay,
30
30
  DeviceBayTemplate,
@@ -1896,13 +1896,13 @@ class ControllerTestCase(ModelTestCases.BaseModelTestCase):
1896
1896
  status=Status.objects.get_for_model(Controller).first(),
1897
1897
  role=Role.objects.get_for_model(Controller).first(),
1898
1898
  location=Location.objects.first(),
1899
- controller_device=Device.objects.first(),
1900
- controller_device_redundancy_group=DeviceRedundancyGroup.objects.first(),
1899
+ deployed_controller_device=Device.objects.first(),
1900
+ deployed_controller_group=DeviceRedundancyGroup.objects.first(),
1901
1901
  )
1902
1902
  with self.assertRaises(ValidationError) as error:
1903
1903
  controller.validated_save()
1904
1904
  self.assertEqual(
1905
- error.exception.message_dict["controller_device"][0],
1905
+ error.exception.message_dict["deployed_controller_device"][0],
1906
1906
  "Cannot assign both a device and a device redundancy group to a controller.",
1907
1907
  )
1908
1908
 
@@ -1924,19 +1924,19 @@ class ControllerTestCase(ModelTestCases.BaseModelTestCase):
1924
1924
  )
1925
1925
 
1926
1926
 
1927
- class ControllerManagedDeviceGroupTestCase(ModelTestCases.BaseModelTestCase):
1928
- model = ControllerManagedDeviceGroup
1927
+ class ControllerDeviceGroupTestCase(ModelTestCases.BaseModelTestCase):
1928
+ model = ControllerDeviceGroup
1929
1929
 
1930
1930
  def test_controller_matches_parent(self):
1931
1931
  """Ensure a controller device group cannot be linked to a controller that does not match its parent."""
1932
1932
  controllers = iter(Controller.objects.all())
1933
- parent_group = ControllerManagedDeviceGroup(
1933
+ parent_group = ControllerDeviceGroup(
1934
1934
  name="Parent Group testing Controller match",
1935
1935
  controller=next(controllers),
1936
1936
  )
1937
1937
  parent_group.validated_save()
1938
1938
 
1939
- child_group = ControllerManagedDeviceGroup(
1939
+ child_group = ControllerDeviceGroup(
1940
1940
  name="Child Group testing Controller match",
1941
1941
  controller=next(controllers),
1942
1942
  parent=parent_group,
@@ -1955,37 +1955,37 @@ class ControllerManagedDeviceGroupTestCase(ModelTestCases.BaseModelTestCase):
1955
1955
  controller1, controller2 = Controller.objects.all()[:2]
1956
1956
  self.assertNotEqual(controller1, controller2, "Controllers should be different")
1957
1957
 
1958
- parent_group = ControllerManagedDeviceGroup.objects.create(
1958
+ parent_group = ControllerDeviceGroup.objects.create(
1959
1959
  name="Parent Group testing Controller match",
1960
1960
  controller=controller1,
1961
1961
  )
1962
- child_group1 = ControllerManagedDeviceGroup.objects.create(
1962
+ child_group1 = ControllerDeviceGroup.objects.create(
1963
1963
  name="Child Group 1 testing Controller match",
1964
1964
  controller=controller1,
1965
1965
  parent=parent_group,
1966
1966
  )
1967
- child_group2 = ControllerManagedDeviceGroup.objects.create(
1967
+ child_group2 = ControllerDeviceGroup.objects.create(
1968
1968
  name="Child Group 2 testing Controller match",
1969
1969
  controller=controller1,
1970
1970
  parent=child_group1,
1971
1971
  )
1972
1972
 
1973
- parent_group = ControllerManagedDeviceGroup.objects.get(pk=parent_group.pk)
1973
+ parent_group = ControllerDeviceGroup.objects.get(pk=parent_group.pk)
1974
1974
  parent_group.controller = controller2
1975
1975
  parent_group.save()
1976
1976
 
1977
1977
  self.assertEqual(
1978
- ControllerManagedDeviceGroup.objects.get(pk=parent_group.pk).controller,
1978
+ ControllerDeviceGroup.objects.get(pk=parent_group.pk).controller,
1979
1979
  controller2,
1980
1980
  "Parent group controller should have been updated",
1981
1981
  )
1982
1982
  self.assertEqual(
1983
- ControllerManagedDeviceGroup.objects.get(pk=child_group1.pk).controller,
1983
+ ControllerDeviceGroup.objects.get(pk=child_group1.pk).controller,
1984
1984
  controller2,
1985
1985
  "Child group 1 controller should have been updated",
1986
1986
  )
1987
1987
  self.assertEqual(
1988
- ControllerManagedDeviceGroup.objects.get(pk=child_group2.pk).controller,
1988
+ ControllerDeviceGroup.objects.get(pk=child_group2.pk).controller,
1989
1989
  controller2,
1990
1990
  "Child group 2 controller should have been updated",
1991
1991
  )