nautobot 2.2.0b1__py3-none-any.whl → 2.2.1__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 (425) hide show
  1. nautobot/__init__.py +31 -0
  2. nautobot/apps/api.py +1 -2
  3. nautobot/apps/utils.py +4 -0
  4. nautobot/apps/views.py +2 -0
  5. nautobot/circuits/api/urls.py +1 -2
  6. nautobot/circuits/api/views.py +0 -12
  7. nautobot/circuits/apps.py +1 -1
  8. nautobot/circuits/tests/test_filters.py +1 -1
  9. nautobot/core/api/routers.py +50 -3
  10. nautobot/core/api/utils.py +4 -0
  11. nautobot/core/api/views.py +21 -15
  12. nautobot/core/cli/__init__.py +18 -11
  13. nautobot/core/constants.py +85 -0
  14. nautobot/core/filters.py +7 -1
  15. nautobot/core/forms/widgets.py +1 -2
  16. nautobot/core/graphql/schema.py +1 -0
  17. nautobot/core/management/commands/generate_test_data.py +4 -4
  18. nautobot/core/models/__init__.py +1 -0
  19. nautobot/core/settings.py +24 -3
  20. nautobot/core/settings.yaml +20 -0
  21. nautobot/core/signals.py +1 -0
  22. nautobot/core/tables.py +2 -1
  23. nautobot/core/templates/admin/base.html +23 -94
  24. nautobot/core/templates/generic/object_retrieve.html +2 -2
  25. nautobot/core/templates/graphene/graphiql.html +18 -47
  26. nautobot/core/templates/inc/footer.html +5 -5
  27. nautobot/core/templates/inc/javascript.html +4 -4
  28. nautobot/core/templates/inc/media.html +2 -2
  29. nautobot/core/templates/inc/nav_menu.html +0 -7
  30. nautobot/core/templates/nautobot_config.py.j2 +14 -1
  31. nautobot/core/templates/rest_framework/api.html +12 -5
  32. nautobot/core/templatetags/helpers.py +2 -2
  33. nautobot/core/testing/__init__.py +1 -1
  34. nautobot/core/testing/filters.py +1 -1
  35. nautobot/core/testing/views.py +30 -0
  36. nautobot/core/tests/integration/test_view_authentication.py +68 -0
  37. nautobot/core/tests/test_api.py +13 -6
  38. nautobot/core/tests/test_csv.py +5 -4
  39. nautobot/core/tests/test_filters.py +2 -1
  40. nautobot/core/tests/test_graphql.py +4 -14
  41. nautobot/core/tests/test_navigations.py +3 -0
  42. nautobot/core/tests/test_views.py +44 -16
  43. nautobot/core/utils/data.py +1 -2
  44. nautobot/core/utils/lookup.py +126 -0
  45. nautobot/core/views/__init__.py +3 -7
  46. nautobot/core/views/generic.py +20 -6
  47. nautobot/core/views/mixins.py +7 -1
  48. nautobot/core/views/renderers.py +11 -6
  49. nautobot/dcim/api/serializers.py +4 -4
  50. nautobot/dcim/api/urls.py +2 -3
  51. nautobot/dcim/api/views.py +7 -18
  52. nautobot/dcim/apps.py +8 -4
  53. nautobot/dcim/elevations.py +5 -1
  54. nautobot/dcim/factory.py +7 -7
  55. nautobot/dcim/filters/__init__.py +16 -17
  56. nautobot/dcim/forms.py +61 -45
  57. nautobot/dcim/homepage.py +11 -3
  58. nautobot/dcim/management/commands/migrate_location_contacts.py +218 -0
  59. nautobot/dcim/migrations/0057_controller_models.py +11 -70
  60. nautobot/dcim/models/__init__.py +2 -2
  61. nautobot/dcim/models/devices.py +14 -16
  62. nautobot/dcim/models/racks.py +1 -3
  63. nautobot/dcim/navigation.py +23 -31
  64. nautobot/dcim/signals.py +6 -6
  65. nautobot/dcim/tables/__init__.py +2 -2
  66. nautobot/dcim/tables/devices.py +13 -16
  67. nautobot/dcim/tables/template_code.py +1 -1
  68. nautobot/dcim/templates/dcim/controller_create.html +70 -0
  69. nautobot/dcim/templates/dcim/controller_retrieve.html +35 -18
  70. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +88 -0
  71. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +75 -43
  72. nautobot/dcim/templates/dcim/device.html +11 -3
  73. nautobot/dcim/templates/dcim/device_edit.html +1 -1
  74. nautobot/dcim/templates/dcim/devicefamily_retrieve.html +4 -0
  75. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +1 -1
  76. nautobot/dcim/tests/test_api.py +47 -6
  77. nautobot/dcim/tests/test_filters.py +92 -81
  78. nautobot/dcim/tests/test_graphql.py +11 -1
  79. nautobot/dcim/tests/test_models.py +15 -15
  80. nautobot/dcim/tests/test_signals.py +3 -1
  81. nautobot/dcim/tests/test_views.py +24 -12
  82. nautobot/dcim/urls.py +1 -1
  83. nautobot/dcim/views.py +25 -15
  84. nautobot/extras/api/serializers.py +20 -1
  85. nautobot/extras/api/urls.py +1 -2
  86. nautobot/extras/api/views.py +0 -10
  87. nautobot/extras/apps.py +7 -0
  88. nautobot/extras/context_managers.py +15 -4
  89. nautobot/extras/filters/__init__.py +53 -2
  90. nautobot/extras/filters/customfields.py +14 -9
  91. nautobot/extras/filters/mixins.py +6 -1
  92. nautobot/extras/forms/contacts.py +7 -0
  93. nautobot/extras/health_checks.py +1 -0
  94. nautobot/extras/jobs.py +1 -0
  95. nautobot/extras/managers.py +15 -2
  96. nautobot/extras/models/contacts.py +1 -0
  97. nautobot/extras/models/customfields.py +25 -2
  98. nautobot/extras/models/datasources.py +1 -0
  99. nautobot/extras/models/mixins.py +1 -0
  100. nautobot/extras/navigation.py +71 -65
  101. nautobot/extras/plugins/__init__.py +2 -1
  102. nautobot/extras/plugins/views.py +7 -11
  103. nautobot/extras/querysets.py +1 -2
  104. nautobot/extras/secrets/providers.py +1 -0
  105. nautobot/extras/signals.py +15 -5
  106. nautobot/extras/tasks.py +70 -17
  107. nautobot/extras/tests/test_api.py +2 -4
  108. nautobot/extras/tests/test_customfields.py +72 -9
  109. nautobot/extras/tests/test_dynamicgroups.py +2 -0
  110. nautobot/extras/tests/test_filters.py +89 -4
  111. nautobot/extras/tests/test_models.py +9 -0
  112. nautobot/extras/tests/test_relationships.py +10 -1
  113. nautobot/extras/tests/test_views.py +112 -1
  114. nautobot/extras/views.py +18 -17
  115. nautobot/ipam/api/serializers.py +10 -0
  116. nautobot/ipam/api/urls.py +1 -2
  117. nautobot/ipam/api/views.py +0 -11
  118. nautobot/ipam/apps.py +3 -2
  119. nautobot/ipam/tables.py +2 -22
  120. nautobot/ipam/tests/test_graphql.py +2 -3
  121. nautobot/ipam/tests/test_tables.py +42 -0
  122. nautobot/ipam/tests/test_views.py +1 -0
  123. nautobot/ipam/views.py +9 -9
  124. nautobot/project-static/css/base.css +1 -0
  125. nautobot/project-static/docs/404.html +126 -73
  126. nautobot/project-static/docs/apps/index.html +127 -71
  127. nautobot/project-static/docs/apps/nautobot-apps.html +127 -71
  128. nautobot/project-static/docs/assets/javascripts/{bundle.8fd75fb4.min.js → bundle.bd41221c.min.js} +2 -2
  129. nautobot/project-static/docs/assets/javascripts/{bundle.8fd75fb4.min.js.map → bundle.bd41221c.min.js.map} +3 -3
  130. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css +1 -0
  131. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css.map +1 -0
  132. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +127 -71
  133. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +127 -71
  134. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +167 -73
  135. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +165 -72
  136. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +127 -71
  137. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +127 -71
  138. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +127 -71
  139. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +127 -71
  140. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +127 -71
  141. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +127 -71
  142. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +127 -71
  143. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +127 -71
  144. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +127 -71
  145. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +127 -71
  146. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +127 -71
  147. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +127 -71
  148. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +127 -71
  149. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +127 -71
  150. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +128 -72
  151. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +127 -71
  152. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +127 -71
  153. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +345 -71
  154. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +172 -73
  155. nautobot/project-static/docs/development/apps/api/configuration-view.html +127 -71
  156. nautobot/project-static/docs/development/apps/api/database-backend-config.html +127 -71
  157. nautobot/project-static/docs/development/apps/api/models/django-admin.html +127 -71
  158. nautobot/project-static/docs/development/apps/api/models/global-search.html +127 -71
  159. nautobot/project-static/docs/development/apps/api/models/graphql.html +127 -71
  160. nautobot/project-static/docs/development/apps/api/models/index.html +127 -71
  161. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +127 -71
  162. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +127 -71
  163. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +127 -71
  164. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +127 -71
  165. nautobot/project-static/docs/development/apps/api/platform-features/index.html +127 -71
  166. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +127 -71
  167. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +127 -71
  168. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +127 -71
  169. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +127 -71
  170. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +127 -71
  171. nautobot/project-static/docs/development/apps/api/prometheus.html +127 -71
  172. nautobot/project-static/docs/development/apps/api/setup.html +127 -71
  173. nautobot/project-static/docs/development/apps/api/testing.html +127 -71
  174. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +127 -71
  175. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +127 -71
  176. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +127 -71
  177. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +127 -71
  178. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +127 -71
  179. nautobot/project-static/docs/development/apps/api/views/base-template.html +127 -71
  180. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +141 -80
  181. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +144 -83
  182. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +127 -71
  183. nautobot/project-static/docs/development/apps/api/views/index.html +127 -71
  184. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +127 -71
  185. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +127 -71
  186. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +127 -71
  187. nautobot/project-static/docs/development/apps/api/views/notes.html +127 -71
  188. nautobot/project-static/docs/development/apps/api/views/rest-api.html +127 -71
  189. nautobot/project-static/docs/development/apps/api/views/urls.html +127 -71
  190. nautobot/project-static/docs/development/apps/index.html +127 -71
  191. nautobot/project-static/docs/development/apps/migration/code-updates.html +127 -71
  192. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +127 -71
  193. nautobot/project-static/docs/development/apps/migration/from-v1.html +127 -71
  194. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +127 -71
  195. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +127 -71
  196. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +127 -71
  197. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +127 -71
  198. nautobot/project-static/docs/development/apps/porting-from-netbox.html +127 -71
  199. nautobot/project-static/docs/development/core/application-registry.html +127 -71
  200. nautobot/project-static/docs/development/core/best-practices.html +145 -79
  201. nautobot/project-static/docs/development/core/bootstrap-ui.html +127 -71
  202. nautobot/project-static/docs/development/core/caching.html +127 -71
  203. nautobot/project-static/docs/development/core/controllers.html +141 -275
  204. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +127 -71
  205. nautobot/project-static/docs/development/core/extending-models.html +13 -8166
  206. nautobot/project-static/docs/development/core/generic-views.html +142 -86
  207. nautobot/project-static/docs/development/core/getting-started.html +146 -81
  208. nautobot/project-static/docs/development/core/homepage.html +145 -89
  209. nautobot/project-static/docs/development/core/index.html +127 -71
  210. nautobot/project-static/docs/development/core/model-checklist.html +8354 -0
  211. nautobot/project-static/docs/development/core/model-features.html +130 -74
  212. nautobot/project-static/docs/development/core/natural-keys.html +127 -71
  213. nautobot/project-static/docs/development/core/navigation-menu.html +127 -71
  214. nautobot/project-static/docs/development/core/release-checklist.html +127 -71
  215. nautobot/project-static/docs/development/core/role-internals.html +127 -71
  216. nautobot/project-static/docs/development/core/settings.html +127 -71
  217. nautobot/project-static/docs/development/core/style-guide.html +127 -71
  218. nautobot/project-static/docs/development/core/templates.html +127 -71
  219. nautobot/project-static/docs/development/core/testing.html +127 -71
  220. nautobot/project-static/docs/development/core/user-preferences.html +127 -71
  221. nautobot/project-static/docs/development/extending-models.html +3 -3
  222. nautobot/project-static/docs/development/index.html +127 -71
  223. nautobot/project-static/docs/development/jobs/index.html +128 -72
  224. nautobot/project-static/docs/development/jobs/migration/from-v1.html +127 -71
  225. nautobot/project-static/docs/index.html +126 -73
  226. nautobot/project-static/docs/models/dcim/{controllerdevicegroup.html → controllermanageddevicegroup.html} +3 -3
  227. nautobot/project-static/docs/objects.inv +0 -0
  228. nautobot/project-static/docs/release-notes/index.html +127 -71
  229. nautobot/project-static/docs/release-notes/version-1.0.html +127 -71
  230. nautobot/project-static/docs/release-notes/version-1.1.html +127 -71
  231. nautobot/project-static/docs/release-notes/version-1.2.html +127 -71
  232. nautobot/project-static/docs/release-notes/version-1.3.html +127 -71
  233. nautobot/project-static/docs/release-notes/version-1.4.html +127 -71
  234. nautobot/project-static/docs/release-notes/version-1.5.html +127 -71
  235. nautobot/project-static/docs/release-notes/version-1.6.html +127 -71
  236. nautobot/project-static/docs/release-notes/version-2.0.html +127 -71
  237. nautobot/project-static/docs/release-notes/version-2.1.html +538 -254
  238. nautobot/project-static/docs/release-notes/version-2.2.html +520 -101
  239. nautobot/project-static/docs/requirements.txt +3 -3
  240. nautobot/project-static/docs/search/search_index.json +1 -1
  241. nautobot/project-static/docs/sitemap.xml +264 -259
  242. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  243. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +127 -71
  244. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +127 -71
  245. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +127 -71
  246. nautobot/project-static/docs/user-guide/administration/configuration/index.html +127 -71
  247. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +192 -71
  248. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +127 -71
  249. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +127 -71
  250. nautobot/project-static/docs/user-guide/administration/guides/caching.html +127 -71
  251. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +127 -71
  252. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +127 -71
  253. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +127 -71
  254. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +131 -71
  255. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +127 -71
  256. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +127 -71
  257. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +130 -74
  258. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +127 -71
  259. nautobot/project-static/docs/user-guide/administration/installation/docker.html +134 -74
  260. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +127 -71
  261. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +8616 -0
  262. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +127 -71
  263. nautobot/project-static/docs/user-guide/administration/installation/index.html +127 -71
  264. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +127 -71
  265. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +127 -71
  266. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +130 -74
  267. nautobot/project-static/docs/user-guide/administration/installation/services.html +127 -71
  268. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +127 -71
  269. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +127 -71
  270. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +127 -71
  271. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +127 -71
  272. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +127 -71
  273. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +127 -71
  274. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +127 -71
  275. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +127 -71
  276. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +127 -71
  277. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +127 -71
  278. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +127 -71
  279. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +127 -71
  280. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +127 -71
  281. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +127 -71
  282. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +127 -71
  283. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +127 -71
  284. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +127 -71
  285. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +127 -71
  286. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +127 -71
  287. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +127 -71
  288. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +127 -71
  289. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +127 -71
  290. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +127 -71
  291. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +362 -79
  292. nautobot/project-static/docs/user-guide/core-data-model/dcim/{controllerdevicegroup.html → controllermanageddevicegroup.html} +210 -85
  293. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +127 -71
  294. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +127 -71
  295. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +127 -71
  296. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +127 -71
  297. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +127 -71
  298. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +127 -71
  299. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +127 -71
  300. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +127 -71
  301. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +127 -71
  302. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +127 -71
  303. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +127 -71
  304. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +127 -71
  305. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +127 -71
  306. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +127 -71
  307. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +127 -71
  308. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +127 -71
  309. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +127 -71
  310. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +127 -71
  311. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +127 -71
  312. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +127 -71
  313. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +127 -71
  314. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +127 -71
  315. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +127 -71
  316. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +127 -71
  317. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +127 -71
  318. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +127 -71
  319. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +127 -71
  320. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +127 -71
  321. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +127 -71
  322. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +127 -71
  323. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +130 -74
  324. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +127 -71
  325. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +138 -71
  326. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +138 -71
  327. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +127 -71
  328. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +127 -71
  329. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +127 -71
  330. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +127 -71
  331. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +127 -71
  332. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +127 -71
  333. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +127 -71
  334. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +127 -71
  335. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +127 -71
  336. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +127 -71
  337. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +127 -71
  338. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +127 -71
  339. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +127 -71
  340. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +127 -71
  341. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +127 -71
  342. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +127 -71
  343. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +127 -71
  344. nautobot/project-static/docs/user-guide/feature-guides/{contact-and-team.html → contacts-and-teams.html} +128 -72
  345. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +129 -73
  346. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +127 -71
  347. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +127 -71
  348. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +127 -71
  349. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +127 -71
  350. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +127 -71
  351. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +127 -71
  352. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +129 -73
  353. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +127 -71
  354. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +127 -71
  355. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +127 -71
  356. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +127 -71
  357. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +127 -71
  358. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +127 -71
  359. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +127 -71
  360. nautobot/project-static/docs/user-guide/index.html +127 -71
  361. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +127 -71
  362. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +127 -71
  363. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +127 -71
  364. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +127 -71
  365. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +127 -71
  366. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +127 -71
  367. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +127 -71
  368. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +127 -71
  369. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +127 -71
  370. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +127 -71
  371. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +127 -71
  372. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +127 -71
  373. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +127 -71
  374. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +127 -71
  375. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +127 -71
  376. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +127 -71
  377. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +127 -71
  378. nautobot/project-static/docs/user-guide/platform-functionality/note.html +127 -71
  379. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +127 -71
  380. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +127 -71
  381. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +127 -71
  382. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +127 -71
  383. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +127 -71
  384. nautobot/project-static/docs/user-guide/platform-functionality/role.html +127 -71
  385. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +127 -71
  386. nautobot/project-static/docs/user-guide/platform-functionality/status.html +127 -71
  387. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +127 -71
  388. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +127 -71
  389. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +127 -71
  390. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +127 -71
  391. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +127 -71
  392. nautobot/project-static/jquery/jquery-3.7.1.min.js +2 -0
  393. nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_444444_256x240.png +0 -0
  394. nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_555555_256x240.png +0 -0
  395. nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_777620_256x240.png +0 -0
  396. nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_777777_256x240.png +0 -0
  397. nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_cc0000_256x240.png +0 -0
  398. nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/images/ui-icons_ffffff_256x240.png +0 -0
  399. nautobot/project-static/jquery-ui-1.13.2/jquery-ui.min.css +7 -0
  400. nautobot/project-static/jquery-ui-1.13.2/jquery-ui.min.js +6 -0
  401. nautobot/project-static/jquery-ui-1.13.2/jquery-ui.structure.min.css +5 -0
  402. nautobot/project-static/{jquery-ui-1.13.1 → jquery-ui-1.13.2}/jquery-ui.theme.min.css +1 -1
  403. nautobot/tenancy/api/urls.py +1 -2
  404. nautobot/tenancy/api/views.py +0 -12
  405. nautobot/tenancy/tables.py +1 -1
  406. nautobot/tenancy/tests/test_views.py +1 -0
  407. nautobot/users/api/urls.py +1 -2
  408. nautobot/users/api/views.py +2 -65
  409. nautobot/users/views.py +8 -8
  410. nautobot/virtualization/api/urls.py +1 -2
  411. nautobot/virtualization/api/views.py +0 -12
  412. {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/METADATA +24 -24
  413. {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/RECORD +418 -412
  414. nautobot/dcim/templates/dcim/controllerdevicegroup_create.html +0 -43
  415. nautobot/project-static/docs/assets/stylesheets/main.f2e4d321.min.css +0 -1
  416. nautobot/project-static/docs/assets/stylesheets/main.f2e4d321.min.css.map +0 -1
  417. nautobot/project-static/jquery/jquery-3.6.0.min.js +0 -2
  418. nautobot/project-static/jquery-ui-1.13.1/jquery-ui.min.css +0 -7
  419. nautobot/project-static/jquery-ui-1.13.1/jquery-ui.min.js +0 -6
  420. nautobot/project-static/jquery-ui-1.13.1/jquery-ui.structure.min.css +0 -5
  421. /nautobot/dcim/templates/dcim/{controllerdevicegroup_retrieve.html → controllermanageddevicegroup_retrieve.html} +0 -0
  422. {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/LICENSE.txt +0 -0
  423. {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/NOTICE +0 -0
  424. {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/WHEEL +0 -0
  425. {nautobot-2.2.0b1.dist-info → nautobot-2.2.1.dist-info}/entry_points.txt +0 -0
@@ -1171,6 +1171,19 @@ properties:
1171
1171
  "Guide to Nautobot Prometheus metrics": "../guides/prometheus-metrics.md"
1172
1172
  type: "boolean"
1173
1173
  version_added: "2.1.5"
1174
+ METRICS_DISABLED_APPS:
1175
+ default: []
1176
+ description: >-
1177
+ A list of app names for which Prometheus metrics should be disabled.
1178
+ (If provided as an environment variable, it should be a comma-separated string, for example
1179
+ `NAUTOBOT_METRICS_DISABLED_APPS="nautobot_ssot, nautobot_device_lifecycle_mgmt"`.)
1180
+ environment_variable: "NAUTOBOT_METRICS_DISABLED_APPS"
1181
+ items:
1182
+ type: "string"
1183
+ see_also:
1184
+ "Guide to Nautobot Prometheus metrics": "../guides/prometheus-metrics.md"
1185
+ type: "array"
1186
+ version_added: "2.2.1"
1174
1187
  METRICS_ENABLED:
1175
1188
  default: false
1176
1189
  description: "Toggle the availability of Prometheus-compatible metrics at `/metrics`."
@@ -1376,6 +1389,13 @@ properties:
1376
1389
  environment_variable: "NAUTOBOT_RACK_ELEVATION_DEFAULT_UNIT_WIDTH"
1377
1390
  is_constance_config: true
1378
1391
  type: "integer"
1392
+ RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT:
1393
+ default: false
1394
+ description: "Enables two-digit format for the rack unit numbering in a rack elevation diagram."
1395
+ environment_variable: "NAUTOBOT_RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT"
1396
+ is_constance_config: true
1397
+ type: "boolean"
1398
+ version_added: "2.2.1"
1379
1399
  REDIS_LOCK_TIMEOUT:
1380
1400
  default: 600
1381
1401
  description: >-
nautobot/core/signals.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Custom signals and handlers for the core Nautobot application."""
2
+
2
3
  import contextlib
3
4
  from functools import wraps
4
5
  import inspect
nautobot/core/tables.py CHANGED
@@ -34,7 +34,7 @@ class BaseTable(django_tables2.Table):
34
34
  "class": "table table-hover table-headings",
35
35
  }
36
36
 
37
- def __init__(self, *args, user=None, **kwargs):
37
+ def __init__(self, *args, user=None, hide_hierarchy_ui=False, **kwargs):
38
38
  # Add custom field columns
39
39
  model = self._meta.model
40
40
 
@@ -64,6 +64,7 @@ class BaseTable(django_tables2.Table):
64
64
 
65
65
  # Init table
66
66
  super().__init__(*args, **kwargs)
67
+ self.hide_hierarchy_ui = hide_hierarchy_ui
67
68
 
68
69
  # Set default empty_text if none was provided
69
70
  if self.empty_text is None:
@@ -8,55 +8,7 @@
8
8
  <html lang="en"{% if request.COOKIES|get_item:"theme" == 'dark' %} data-theme="dark"{% endif %}>
9
9
  <head>
10
10
  <title>{% block title %}Admin Home{% endblock %} - Nautobot</title>
11
- <link rel="stylesheet"
12
- href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"
13
- onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/css/bootstrap.min.css'">
14
- <link rel="stylesheet"
15
- href="{% static 'materialdesignicons-6.5.95/css/materialdesignicons.min.css' %}"
16
- onerror="window.location='{% url 'media_failure' %}?filename=materialdesignicons-6.5.95/css/materialdesignicons.min.css'">
17
- <link rel="stylesheet"
18
- href="{% static 'jquery-ui-1.13.1/jquery-ui.min.css' %}"
19
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.css'">
20
- <link rel="stylesheet"
21
- href="{% static 'select2-4.0.13/select2.min.css' %}"
22
- onerror="window.location='{% url 'media_failure' %}?filename=select2-4.0.13/select2.min.css'">
23
- <link rel="stylesheet"
24
- href="{% static 'select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css' %}"
25
- onerror="window.location='{% url 'media_failure' %}?filename=select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css'">
26
- <link rel="stylesheet"
27
- href="{% static 'flatpickr-4.6.9/themes/light.min.css' %}"
28
- onerror="window.location='{% url 'media_failure' %}?filename=flatpickr-4.6.9/themes/light.min.css'">
29
- <link rel="stylesheet" id="dark-theme"
30
- href="{% versioned_static 'css/dark.css' %}"
31
- onerror="window.location='{% url 'media_failure' %}?filename=css/dark.css'"{% if request.COOKIES|get_item:"theme" != 'dark' %} disabled="disabled"{% endif %} />
32
- <link rel="stylesheet" id="base-theme"
33
- href="{% versioned_static 'css/base.css' %}"
34
- onerror="window.location='{% url 'media_failure' %}?filename=css/base.css'">
35
- <link rel="apple-touch-icon" sizes="180x180" href="{% custom_branding_or_static 'icon_180' 'img/nautobot_icon_180x180.png' %}">
36
- <link rel="icon" type="image/png" sizes="32x32" href="{% custom_branding_or_static 'icon_32' 'img/nautobot_icon_32x32.png' %}">
37
- <link rel="icon" type="image/png" sizes="16x16" href="{% custom_branding_or_static 'icon_16' 'img/nautobot_icon_16x16.png' %}">
38
- <link rel="icon" type="image/png" href="{% custom_branding_or_static 'icon_192' 'img/nautobot_icon_192x192.png' %}" sizes="192x192">
39
- <link rel="mask-icon" href="{% custom_branding_or_static 'icon_mask' 'img/nautobot_icon_monochrome.svg' %}" color="#0097ff">
40
- <link rel="shortcut icon" href="{% custom_branding_or_static 'favicon' 'img/favicon.ico' %}">
41
-
42
- <script src="{% static 'jquery/jquery-3.6.0.min.js' %}"
43
- onerror="window.location='{% url 'media_failure' %}?filename=jquery/jquery-3.6.0.min.js'"></script>
44
- <script src="{% static 'jquery-ui-1.13.1/jquery-ui.min.js' %}"
45
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.js'"></script>
46
- <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"
47
- onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/js/bootstrap.min.js'"></script>
48
- <script src="{% static 'select2-4.0.13/select2.min.js' %}"
49
- onerror="window.location='{% url 'media_failure' %}?filename=select2-4.0.13/select2.min.js'"></script>
50
- <script src="{% static 'flatpickr-4.6.9/flatpickr.min.js' %}"
51
- onerror="window.location='{% url 'media_failure' %}?filename=flatpickr-4.6.9/flatpickr.min.js'"></script>
52
- <script src="{% static 'js/forms.js' %}"
53
- onerror="window.location='{% url 'media_failure' %}?filename=js/forms.js'"></script>
54
-
55
- <meta name="msapplication-TileColor" content="#2d89ef">
56
- <meta name="theme-color" content="#ffffff">
57
- <meta charset="UTF-8">
58
- <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
59
-
11
+ {% include 'inc/media.html' %}
60
12
  {% block extrahead %}{% endblock %}
61
13
  {% block extrastyle %}{% endblock %}
62
14
 
@@ -94,23 +46,27 @@
94
46
  }
95
47
  </style>
96
48
  </head>
97
- <body {% if is_popup %}style="padding-top: 0px;"{% endif %}>
49
+ <body {% if is_popup %}style="padding-left: 0px;"{% endif %}>
50
+
98
51
  {% if not is_popup %}
99
52
  {% include 'inc/nav_menu.html' %}
100
53
  {% endif %}
101
- <div class="container-fluid wrapper" {% if is_popup %}style="padding-bottom: 0px;"{% endif %}>
102
- {% if "BANNER_TOP"|settings_or_config %}
103
- <div class="alert alert-info text-center" role="alert">
104
- {{ "BANNER_TOP"|settings_or_config|safe }}
105
- </div>
106
- {% endif %}
107
- {% if settings.MAINTENANCE_MODE %}
108
- <div class="alert alert-warning text-center" role="alert">
109
- <h4><i class="mdi mdi-alert"></i> Maintenance Mode</h4>
110
- <p>Nautobot is currently in maintenance mode. Functionality may be limited.</p>
111
- </div>
54
+
55
+ <div class="container-fluid wrapper" id="main-content" {% if is_popup %}style="padding-bottom: 0px;"{% endif %}>
56
+ {% if not is_popup %}
57
+ {% if "BANNER_TOP"|settings_or_config %}
58
+ <div class="alert alert-info text-center" role="alert">
59
+ {{ "BANNER_TOP"|settings_or_config|safe }}
60
+ </div>
61
+ {% endif %}
62
+ {% if settings.MAINTENANCE_MODE %}
63
+ <div class="alert alert-warning text-center" role="alert">
64
+ <h4><i class="mdi mdi-alert"></i> Maintenance Mode</h4>
65
+ <p>Nautobot is currently in maintenance mode. Functionality may be limited.</p>
66
+ </div>
67
+ {% endif %}
68
+ {% plugin_banners %}
112
69
  {% endif %}
113
- {% plugin_banners %}
114
70
  {% for message in messages %}
115
71
  <div class="alert alert-{{ message.tags }} alert-dismissable" role="alert">
116
72
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
@@ -148,8 +104,6 @@
148
104
  {% block content %}{{ content }}{% endblock %}
149
105
  </div>
150
106
  </div>
151
-
152
- {% block footer %}<footer id="footer"></footer>{% endblock %}
153
107
  <div class="push"></div>
154
108
  {% if "BANNER_BOTTOM"|settings_or_config %}
155
109
  <div class="alert alert-info text-center banner-bottom" role="alert">
@@ -158,37 +112,12 @@
158
112
  {% endif %}
159
113
  </div>
160
114
  {% if not is_popup %}
161
- <footer class="footer">
162
- <div class="container-fluid">
163
- <div class="row">
164
- <div class="col-xs-4">
165
- <p class="text-muted">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</p>
166
- </div>
167
- <div class="col-xs-4 text-center">
168
- <p class="text-muted">{% now 'Y-m-d H:i:s T' %}</p>
169
- </div>
170
- <div class="col-xs-4 text-right noprint">
171
- <p class="text-muted">
172
- <a href="#theme_modal" data-toggle="modal" data-target="#theme_modal" id="btn-theme-modal"><i class="mdi mdi-theme-light-dark text-primary"></i>Theme</a> &middot;
173
- <i class="mdi mdi-book-open-page-variant text-primary"></i>
174
- {% if settings.BRANDING_URLS.docs %}
175
- <a href="{{ settings.BRANDING_URLS.docs }}">Docs</a>
176
- {% else %}
177
- <a href="{% static 'docs/index.html' %}">Docs</a>
178
- {% endif %}
179
- &middot;
180
- <i class="mdi mdi-cloud-braces text-primary"></i> <a href="{% url 'api_docs' %}">API</a> &middot;
181
- <i class="mdi mdi-graphql text-primary"></i> <a href="{% url 'graphql' %}">GraphQL</a> &middot;
182
- <i class="mdi mdi-xml text-primary"></i> <a href="{{ settings.BRANDING_URLS.code }}">Code</a> &middot;
183
- <i class="mdi mdi-lifebuoy text-primary"></i> <a href="{{ settings.BRANDING_URLS.help }}">Help</a>
184
- </p>
185
- </div>
186
- </div>
187
- </div>
188
- </footer>
115
+ {% include 'inc/footer.html' %}
189
116
  {% endif %}
190
117
  {% include 'modals/modal_theme.html' with name='theme'%}
191
- <script src="{% versioned_static 'js/theme.js' %}"></script>
192
- {% block javascript %}{% endblock %}
118
+
119
+ {% block javascript %}
120
+ {% include 'inc/javascript.html' %}
121
+ {% endblock %}
193
122
  </body>
194
123
  </html>
@@ -87,7 +87,7 @@
87
87
  Advanced
88
88
  </a>
89
89
  </li>
90
- {% if is_contact_associatable_model %}
90
+ {% if object.is_contact_associable_model %}
91
91
  <li role="presentation"{% if request.GET.tab == 'contacts' %} class="active"{% endif %}>
92
92
  <a href="{{ object.get_absolute_url }}#contacts" onclick="switch_tab(this.href)" aria-controls="contacts" role="tab" data-toggle="tab">
93
93
  Contacts
@@ -159,7 +159,7 @@
159
159
  </div>
160
160
  </div>
161
161
  </div>
162
- {% if is_contact_associatable_model %}
162
+ {% if object.is_contact_associable_model %}
163
163
  <div id="contacts" role="tabpanel" class="tab-pane {% if request.GET.tab == 'contacts' %}active{% else %}fade{% endif %}">
164
164
  <div class="row">
165
165
  <div class="col-md-12">
@@ -10,53 +10,31 @@ add "&raw" to the end of the URL within a browser.
10
10
  <!DOCTYPE html>
11
11
  <html>
12
12
  <head>
13
+ {% include 'inc/media.html' %}
14
+ {% block extra_styles %}{% endblock %}
13
15
  <!-- Nautobot template requirements -->
14
16
  <title>{% block title %}GraphiQL{% endblock %} - {{ settings.BRANDING_TITLE }}</title>
15
- <link rel="stylesheet"
16
- href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"
17
- onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/css/bootstrap.min.css'">
18
- <link rel="stylesheet"
19
- href="{% static 'materialdesignicons-6.5.95/css/materialdesignicons.min.css' %}"
20
- onerror="window.location='{% url 'media_failure' %}?filename=materialdesignicons-6.5.95/css/materialdesignicons.min.css'">
21
- <link rel="stylesheet"
22
- href="{% static 'jquery-ui-1.13.1/jquery-ui.min.css' %}"
23
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.css'">
24
- <link rel="stylesheet"
25
- href="{% static 'select2-4.0.13/select2.min.css' %}"
26
- onerror="window.location='{% url 'media_failure' %}?filename=select2-4.0.13/select2.min.css'">
27
- <link rel="stylesheet"
28
- href="{% static 'select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css' %}"
29
- onerror="window.location='{% url 'media_failure' %}?filename=select2-bootstrap-0.1.0-beta.10/select2-bootstrap.min.css'">
30
- <link rel="stylesheet"
31
- href="{% static 'flatpickr-4.6.9/themes/light.min.css' %}"
32
- onerror="window.location='{% url 'media_failure' %}?filename=flatpickr-4.6.9/themes/light.min.css'">
33
- <link rel="stylesheet" id="dark-theme"
34
- href="{% versioned_static 'css/dark.css' %}"
35
- onerror="window.location='{% url 'media_failure' %}?filename=css/dark.css'" disabled="disabled" />
36
- <link rel="stylesheet"
37
- href="{% versioned_static 'css/base.css' %}"
38
- onerror="window.location='{% url 'media_failure' %}?filename=css/base.css'">
39
- <link rel="apple-touch-icon" sizes="180x180" href="{% custom_branding_or_static 'icon_180' 'img/nautobot_icon_180x180.png' %}">
40
- <link rel="icon" type="image/png" sizes="32x32" href="{% custom_branding_or_static 'icon_32' 'img/nautobot_icon_32x32.png' %}">
41
- <link rel="icon" type="image/png" sizes="16x16" href="{% custom_branding_or_static 'icon_16' 'img/nautobot_icon_16x16.png' %}">
42
- <link rel="icon" type="image/png" sizes="192x192" href="{% custom_branding_or_static 'icon_192' 'img/nautobot_icon_192x192.png' %}">
43
- <link rel="mask-icon" type="image/png" color="#0097ff" href="{% custom_branding_or_static 'icon_mask' 'img/nautobot_icon_monochrome.png' %}">
44
- <link rel="shortcut icon" href="{% custom_branding_or_static 'favicon' 'img/favicon.ico' %}">
45
- <meta name="msapplication-TileColor" content="#2d89ef">
46
- <meta name="theme-color" content="#ffffff">
47
- <meta charset="UTF-8">
48
- <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
17
+
49
18
  <!-- GraphiQL template requirements -->
50
19
  <style>
51
- html, body, #editor {
52
- height: 100%;
20
+ #editor {
53
21
  margin: 0;
54
22
  width: 100%;
23
+ height: calc(100vh - 56px - 3rem);
55
24
  }
56
25
  .toolbar .dropdown-menu > li > a {
57
26
  clear: left;
58
27
  margin-right: 120px; /* leave room for the "Save Changes" button if present */
59
28
  }
29
+ .graphiql-container .doc-explorer-title-bar {
30
+ box-sizing: content-box;
31
+ }
32
+ .graphiql-container .history-title-bar {
33
+ box-sizing: content-box;
34
+ }
35
+ .graphiql-container .docExplorerShow {
36
+ white-space: nowrap;
37
+ }
60
38
  </style>
61
39
  <!-- As Nautobot may be run without internet access, we source these files locally rather than from an online CDN -->
62
40
  <link rel="stylesheet"
@@ -72,23 +50,16 @@ add "&raw" to the end of the URL within a browser.
72
50
  onerror="window.location='{% url 'media_failure' %}?filename=graphiql-1.5.16/graphiql.min.js'"></script>
73
51
  <script src="{% static 'subscriptions-transport-ws-0.9.18/client.min.js' %}"
74
52
  onerror="window.location='{% url 'media_failure' %}?filename=subscriptions-transport-ws-0.9.18/client.min.js'"></script>
75
- <!-- Custom CSS to address some conflicts between the two -->
76
- <style>
77
- body {
78
- padding-top: 54px;
79
- }
80
- .graphiql-container .doc-explorer-title-bar {
81
- box-sizing: content-box;
82
- }
83
- </style>
84
53
  </head>
85
54
  <body>
86
55
  <!-- Nautobot page contents -->
87
56
  {% include 'inc/nav_menu.html' %}
88
57
  {% include 'modals/modal_theme.html' with name='theme'%}
89
58
  {% include 'inc/javascript.html' %}
90
- <!-- GraphiQL page contents -->
91
- <div id="editor"></div>
59
+ <div class="container-fluid wrapper" id="main-content">
60
+ <!-- GraphiQL page contents -->
61
+ <div id="editor"></div>
62
+ </div>
92
63
  {% include 'inc/footer.html' %}
93
64
  {% csrf_token %}
94
65
  <script type="application/javascript">
@@ -3,8 +3,8 @@
3
3
  {% load plugins %}
4
4
 
5
5
  <style>
6
- /* Styles for viewports narrower than 1007px */
7
- @media (max-width: 1007px) {
6
+ /* Styles for viewports narrower than 1232px, i.e. bootstrap 'xs' and 'sm' layouts */
7
+ @media (max-width: 1232px) {
8
8
  .footer-col-1, .footer-col-2, .footer-col-3 {
9
9
  text-align: center !important;
10
10
  }
@@ -19,7 +19,7 @@
19
19
  <footer class="footer" id="footer">
20
20
  <div class="container-fluid">
21
21
  <div class="row">
22
- <div class="col-xl-4 col-lg-4 col-md-4 col-sm-3 col-xs-12 text-left footer-col-1 no-wrap">
22
+ <div class="col-xl-4 col-lg-4 col-md-3 col-sm-12 col-xs-12 text-left footer-col-1 no-wrap">
23
23
  {% if request.user.is_authenticated %}
24
24
  <p class="text-muted">
25
25
  {% if settings.BRANDING_FILEPATHS.logo and settings.BRANDING_POWERED_BY_URL %}<a href="{{ settings.BRANDING_POWERED_BY_URL }}"><img src="{% static 'img/nautobot_logo.svg' %}" height="20" /> Powered</a> &middot;{% endif %}
@@ -27,10 +27,10 @@
27
27
  </p>
28
28
  {% endif %}
29
29
  </div>
30
- <div class="col-xl-4 col-lg-4 col-md-4 col-sm-3 col-xs-12 text-center footer-col-2">
30
+ <div class="col-xl-4 col-lg-3 col-md-3 col-sm-12 col-xs-12 text-center footer-col-2">
31
31
  <p class="text-muted">{% now 'Y-m-d H:i:s T' %}</p>
32
32
  </div>
33
- <div class="col-xl-4 col-lg-4 col-md-4 col-sm-6 col-xs-12 text-right footer-col-3 noprint">
33
+ <div class="col-xl-4 col-lg-5 col-md-6 col-sm-12 col-xs-12 text-right footer-col-3 noprint">
34
34
  {% if request.user.is_authenticated %}
35
35
  <p class="text-muted footer-links">
36
36
  <a href="#theme_modal" data-toggle="modal" data-target="#theme_modal" id="btn-theme-modal"><i class="mdi mdi-theme-light-dark text-primary"></i>Theme</a> &middot;
@@ -2,10 +2,10 @@
2
2
  {% load plugins %}
3
3
  {% load static %}
4
4
 
5
- <script src="{% static 'jquery/jquery-3.6.0.min.js' %}"
6
- onerror="window.location='{% url 'media_failure' %}?filename=jquery/jquery-3.6.0.min.js'"></script>
7
- <script src="{% static 'jquery-ui-1.13.1/jquery-ui.min.js' %}"
8
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.js'"></script>
5
+ <script src="{% static 'jquery/jquery-3.7.1.min.js' %}"
6
+ onerror="window.location='{% url 'media_failure' %}?filename=jquery/jquery-3.7.1.min.js'"></script>
7
+ <script src="{% static 'jquery-ui-1.13.2/jquery-ui.min.js' %}"
8
+ onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.2/jquery-ui.min.js'"></script>
9
9
  <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"
10
10
  onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/js/bootstrap.min.js'"></script>
11
11
  <script src="{% static 'select2-4.0.13/select2.min.js' %}"
@@ -11,8 +11,8 @@
11
11
  href="{% static 'materialdesignicons-6.5.95/css/materialdesignicons.min.css' %}"
12
12
  onerror="window.location='{% url 'media_failure' %}?filename=materialdesignicons-6.5.95/css/materialdesignicons.min.css'">
13
13
  <link rel="stylesheet"
14
- href="{% static 'jquery-ui-1.13.1/jquery-ui.min.css' %}"
15
- onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.1/jquery-ui.min.css'">
14
+ href="{% static 'jquery-ui-1.13.2/jquery-ui.min.css' %}"
15
+ onerror="window.location='{% url 'media_failure' %}?filename=jquery-ui-1.13.2/jquery-ui.min.css'">
16
16
  <link rel="stylesheet"
17
17
  href="{% static 'select2-4.0.13/select2.min.css' %}"
18
18
  onerror="window.location='{% url 'media_failure' %}?filename=select2-4.0.13/select2.min.css'">
@@ -121,9 +121,6 @@
121
121
  document.addEventListener('DOMContentLoaded', function() {
122
122
  const navbar = document.querySelector('.navbar-fixed-left');
123
123
  const navbarHeader = document.querySelector('.navbar-header');
124
- const breadcrumb = document.querySelector('.breadcrumb');
125
- const bannerAlertArea = document.querySelector('.banner-alert-area');
126
- const bannerAlert = document.querySelector('.plugin-banner') !== null;
127
124
  const mainContent = document.querySelector('#main-content');
128
125
  const footer = document.querySelector('#footer');
129
126
  const dropdownToggles = document.querySelectorAll('.navbar-fixed-left .navbar-nav > .dropdown > a[data-toggle="collapse"]');
@@ -180,10 +177,6 @@
180
177
  function adjustElementsForNavbarState(isCollapsed) {
181
178
  const marginLeftValue = isCollapsed ? '-240px' : '0px';
182
179
  mainContent.style.marginLeft = marginLeftValue;
183
- bannerAlertArea.classList.toggle('collapsed', isCollapsed);
184
- if(!bannerAlert && breadcrumb) {
185
- breadcrumb.classList.toggle('collapsed', isCollapsed);
186
- };
187
180
  if(footer) footer.style.marginLeft = marginLeftValue;
188
181
  toggler.style.left = isCollapsed ? '-5px' : '225px';
189
182
  }
@@ -415,6 +415,11 @@ INSTALLATION_METRICS_ENABLED = is_truthy(os.getenv("NAUTOBOT_INSTALLATION_METRIC
415
415
  #
416
416
  # METRICS_AUTHENTICATED = is_truthy(os.getenv("NAUTOBOT_METRICS_AUTHENTICATED", "False"))
417
417
 
418
+ # Disable app metrics for specific apps
419
+ #
420
+ # if "NAUTOBOT_METRICS_DISABLED_APPS" in os.environ and os.environ["NAUTOBOT_METRICS_DISABLED_APPS"] != "":
421
+ # METRICS_DISABLED_APPS = os.getenv("NAUTOBOT_METRICS_DISABLED_APPS", "").split(",")
422
+
418
423
  # Credentials that Nautobot will uses to authenticate to devices when connecting via NAPALM.
419
424
  #
420
425
  # NAPALM_USERNAME = os.getenv("NAUTOBOT_NAPALM_USERNAME", "")
@@ -472,6 +477,14 @@ INSTALLATION_METRICS_ENABLED = is_truthy(os.getenv("NAUTOBOT_INSTALLATION_METRIC
472
477
  # ):
473
478
  # RACK_ELEVATION_DEFAULT_UNIT_WIDTH = int(os.environ["NAUTOBOT_RACK_ELEVATION_DEFAULT_UNIT_WIDTH"])
474
479
 
480
+ # Enable two-digit format for the rack unit numbering in rack elevations.
481
+ #
482
+ # if (
483
+ # "NAUTOBOT_RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT" in os.environ
484
+ # and os.environ["NAUTOBOT_RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT"] != ""
485
+ # ):
486
+ # RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT = is_truthy(os.environ["NAUTOBOT_RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT"])
487
+
475
488
  # Sets an age out timer of redis lock. This is NOT implicitly applied to locks, must be added
476
489
  # to a lock creation as `timeout=settings.REDIS_LOCK_TIMEOUT`
477
490
  #
@@ -509,7 +522,7 @@ INSTALLATION_METRICS_ENABLED = is_truthy(os.getenv("NAUTOBOT_INSTALLATION_METRIC
509
522
  # class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG.
510
523
  # These default to None and {} respectively.
511
524
  #
512
- # STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage'
525
+ # STORAGE_BACKEND = 'storages.backends.s3.S3Storage'
513
526
  # STORAGE_CONFIG = {
514
527
  # 'AWS_ACCESS_KEY_ID': 'Key ID',
515
528
  # 'AWS_SECRET_ACCESS_KEY': 'Secret',
@@ -7,13 +7,20 @@
7
7
  {% include 'inc/media.html' %}
8
8
  {% endblock bootstrap_theme %}
9
9
 
10
- {% block navbar %}
11
- {% include 'inc/nav_menu.html' %}
12
- {% endblock navbar %}
13
-
14
10
  {% block body %}
15
- {{ block.super }}
11
+ {% include 'inc/nav_menu.html' %}
12
+ <div class="container-fluid" id="main-content">
13
+ {{ block.super }}
14
+ </div>
16
15
  {% include 'inc/footer.html' %}
16
+ <style>
17
+ .navbar-static-top {
18
+ display: none;
19
+ }
20
+ #main-content {
21
+ min-height: calc(100vh - 70px);
22
+ }
23
+ </style>
17
24
  {% endblock body %}
18
25
 
19
26
  {% block script %}
@@ -85,7 +85,7 @@ def hyperlinked_object(value, field="display"):
85
85
  @register.filter()
86
86
  def hyperlinked_email(value):
87
87
  """Render an email address as a `mailto:` hyperlink."""
88
- if value is None:
88
+ if not value:
89
89
  return placeholder(value)
90
90
  return format_html('<a href="mailto:{}">{}</a>', value, value)
91
91
 
@@ -94,7 +94,7 @@ def hyperlinked_email(value):
94
94
  @register.filter()
95
95
  def hyperlinked_phone_number(value):
96
96
  """Render a phone number as a `tel:` hyperlink."""
97
- if value is None:
97
+ if not value:
98
98
  return placeholder(value)
99
99
  return format_html('<a href="tel:{}">{}</a>', value, value)
100
100
 
@@ -109,7 +109,7 @@ def get_job_class_and_model(module, name, source="local"):
109
109
 
110
110
 
111
111
  @tag("unit")
112
- class TransactionTestCase(_TransactionTestCase, NautobotTestCaseMixin):
112
+ class TransactionTestCase(NautobotTestCaseMixin, _TransactionTestCase):
113
113
  """
114
114
  Base test case class using the TransactionTestCase for unit testing
115
115
  """
@@ -44,7 +44,7 @@ class FilterTestCases:
44
44
  # randomly break out of loop after 2 values have been selected
45
45
  if len(test_values) > 1 and random.choice([True, False]): # noqa: S311 # suspicious-non-cryptographic-random-usage
46
46
  break
47
- if value[field_name] and value["count"] <= qs_count:
47
+ if value[field_name] and value["count"] < qs_count:
48
48
  qs_count -= value["count"]
49
49
  test_values.append(str(value[field_name]))
50
50
 
@@ -17,6 +17,7 @@ from tree_queries.models import TreeNode
17
17
 
18
18
  from nautobot.core import testing
19
19
  from nautobot.core.models.generics import PrimaryModel
20
+ from nautobot.core.models.tree_queries import TreeModel
20
21
  from nautobot.core.templatetags import helpers
21
22
  from nautobot.core.testing import mixins
22
23
  from nautobot.core.utils import lookup
@@ -24,6 +25,7 @@ from nautobot.extras import choices as extras_choices, models as extras_models,
24
25
  from nautobot.extras.forms import CustomFieldModelFormMixin, RelationshipModelFormMixin
25
26
  from nautobot.extras.models import CustomFieldModel, RelationshipModel
26
27
  from nautobot.extras.models.mixins import NotesMixin
28
+ from nautobot.ipam.models import Prefix
27
29
  from nautobot.users import models as users_models
28
30
 
29
31
  __all__ = (
@@ -722,6 +724,8 @@ class ViewTestCases:
722
724
  """
723
725
 
724
726
  filterset = None
727
+ filter_on_field = "name"
728
+ sort_on_field = "tags"
725
729
 
726
730
  def get_filterset(self):
727
731
  return self.filterset or lookup.get_filterset_for_model(self.model)
@@ -737,6 +741,32 @@ class ViewTestCases:
737
741
  def get_list_view(self):
738
742
  return lookup.get_view_for_model(self.model, view_type="List")
739
743
 
744
+ def test_table_with_indentation_is_removed_on_filter_or_sort(self):
745
+ self.user.is_superuser = True
746
+ self.user.save()
747
+
748
+ if not issubclass(self.model, (TreeModel)) and self.model is not Prefix:
749
+ self.skipTest("Skipping Non TreeModels")
750
+
751
+ with self.subTest("Assert indentation is present"):
752
+ response = self.client.get(f"{self._get_url('list')}")
753
+ response_body = response.content.decode(response.charset)
754
+ self.assertInHTML('<i class="mdi mdi-circle-small"></i>', response_body)
755
+
756
+ with self.subTest("Assert indentation is removed on filter"):
757
+ queryset = (
758
+ self._get_queryset().filter(parent__isnull=False).values_list(self.filter_on_field, flat=True)[:5]
759
+ )
760
+ filter_values = "&".join([f"{self.filter_on_field}={instance_value}" for instance_value in queryset])
761
+ response = self.client.get(f"{self._get_url('list')}?{filter_values}")
762
+ response_body = response.content.decode(response.charset)
763
+ self.assertNotIn('<i class="mdi mdi-circle-small"></i>', response_body)
764
+
765
+ with self.subTest("Assert indentation is removed on sort"):
766
+ response = self.client.get(f"{self._get_url('list')}?sort={self.sort_on_field}")
767
+ response_body = response.content.decode(response.charset)
768
+ self.assertNotIn('<i class="mdi mdi-circle-small"></i>', response_body)
769
+
740
770
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
741
771
  def test_list_objects_anonymous(self):
742
772
  # Make the request as an unauthenticated user
@@ -0,0 +1,68 @@
1
+ from django.test import tag
2
+
3
+ from nautobot.core.testing import TestCase
4
+ from nautobot.core.utils.lookup import get_url_for_url_pattern, get_url_patterns
5
+
6
+
7
+ @tag("integration")
8
+ class AuthenticationEnforcedTestCase(TestCase):
9
+ r"""
10
+ Test that all\* registered views require authentication to access.
11
+
12
+ \* with a very small number of known exceptions such as login and logout views.
13
+ """
14
+
15
+ def test_all_views_require_authentication(self):
16
+ self.client.logout()
17
+ url_patterns = get_url_patterns()
18
+
19
+ for url_pattern in url_patterns:
20
+ with self.subTest(url_pattern=url_pattern):
21
+ url = get_url_for_url_pattern(url_pattern)
22
+ response = self.client.get(url, follow=True)
23
+
24
+ if response.status_code == 405: # Method not allowed
25
+ response = self.client.post(url, follow=True)
26
+
27
+ # Is a view that *should* be open to unauthenticated users?
28
+ if url in [
29
+ "/admin/login/",
30
+ "/api/plugins/example-app/webhook/",
31
+ "/health/",
32
+ "/login/",
33
+ "/media-failure/",
34
+ "/template.css",
35
+ ]:
36
+ self.assertHttpStatus(response, 200, msg=url)
37
+ elif response.status_code == 200:
38
+ # UI views generally should redirect unauthenticated users to the appropriate login page
39
+ if url.startswith("/admin"):
40
+ if "logout" in url:
41
+ # /admin/logout/ sets next=/admin/ because having login redirect to logout would be silly
42
+ redirect_url = "/admin/login/?next=/admin/"
43
+ else:
44
+ redirect_url = f"/admin/login/?next={url}"
45
+ else:
46
+ if "logout" in url:
47
+ # /logout/ sets next=/ because having login redirect back to logout would be silly
48
+ redirect_url = "/login/?next=/"
49
+ else:
50
+ redirect_url = f"/login/?next={url}"
51
+ self.assertRedirects(response, redirect_url)
52
+ elif response.status_code != 403:
53
+ if any(
54
+ url.startswith(path)
55
+ for path in [
56
+ "/complete/", # social auth
57
+ "/health/string/", # health-check
58
+ "/login/", # social auth
59
+ "/media/", # MEDIA_ROOT
60
+ "/plugins/example-app/docs/", # STATIC_ROOT
61
+ ]
62
+ ):
63
+ self.assertEqual(response.status_code, 404)
64
+ else:
65
+ self.fail(
66
+ f"Unexpected {response.status_code} response at {url}: "
67
+ + response.content.decode(response.charset)
68
+ )