nautobot 2.4.10__py3-none-any.whl → 2.4.11__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 (416) hide show
  1. nautobot/cloud/tests/test_views.py +13 -1
  2. nautobot/cloud/views.py +39 -9
  3. nautobot/core/celery/__init__.py +21 -0
  4. nautobot/core/celery/encoders.py +3 -0
  5. nautobot/core/forms/forms.py +4 -1
  6. nautobot/core/jobs/bulk_actions.py +8 -8
  7. nautobot/core/jobs/cleanup.py +11 -0
  8. nautobot/core/management/commands/generate_test_data.py +2 -1
  9. nautobot/core/templates/generic/object_retrieve.html +1 -1
  10. nautobot/core/testing/mixins.py +19 -1
  11. nautobot/core/testing/views.py +104 -8
  12. nautobot/core/tests/test_jobs.py +20 -4
  13. nautobot/core/tests/test_utils.py +193 -0
  14. nautobot/core/tests/test_views_utils.py +53 -2
  15. nautobot/core/ui/object_detail.py +4 -0
  16. nautobot/core/utils/lookup.py +4 -2
  17. nautobot/core/utils/module_loading.py +86 -58
  18. nautobot/core/views/generic.py +2 -12
  19. nautobot/core/views/mixins.py +19 -1
  20. nautobot/core/views/renderers.py +4 -13
  21. nautobot/core/views/utils.py +16 -0
  22. nautobot/dcim/api/serializers.py +13 -0
  23. nautobot/dcim/api/urls.py +1 -0
  24. nautobot/dcim/api/views.py +20 -0
  25. nautobot/dcim/apps.py +1 -0
  26. nautobot/dcim/factory.py +11 -0
  27. nautobot/dcim/filters/__init__.py +110 -0
  28. nautobot/dcim/forms.py +205 -19
  29. nautobot/dcim/migrations/0070_modulefamily_models.py +92 -0
  30. nautobot/dcim/models/__init__.py +2 -0
  31. nautobot/dcim/models/device_component_templates.py +14 -0
  32. nautobot/dcim/models/device_components.py +13 -1
  33. nautobot/dcim/models/devices.py +62 -0
  34. nautobot/dcim/navigation.py +16 -0
  35. nautobot/dcim/tables/__init__.py +2 -0
  36. nautobot/dcim/tables/devices.py +48 -0
  37. nautobot/dcim/tables/devicetypes.py +35 -1
  38. nautobot/dcim/tables/template_code.py +2 -0
  39. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +1 -90
  40. nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
  41. nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +1 -63
  42. nautobot/dcim/templates/dcim/location.html +2 -249
  43. nautobot/dcim/templates/dcim/location_edit.html +2 -38
  44. nautobot/dcim/templates/dcim/location_retrieve.html +249 -0
  45. nautobot/dcim/templates/dcim/location_update.html +38 -0
  46. nautobot/dcim/templates/dcim/module_update.html +1 -0
  47. nautobot/dcim/templates/dcim/modulebay_retrieve.html +93 -1
  48. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +31 -0
  49. nautobot/dcim/templates/dcim/moduletype_retrieve.html +6 -0
  50. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -160
  51. nautobot/dcim/tests/test_api.py +35 -0
  52. nautobot/dcim/tests/test_filters.py +102 -3
  53. nautobot/dcim/tests/test_models.py +146 -0
  54. nautobot/dcim/tests/test_views.py +70 -97
  55. nautobot/dcim/urls.py +4 -22
  56. nautobot/dcim/views.py +439 -153
  57. nautobot/extras/api/views.py +9 -2
  58. nautobot/extras/datasources/git.py +11 -3
  59. nautobot/extras/forms/forms.py +9 -5
  60. nautobot/extras/jobs.py +4 -2
  61. nautobot/extras/models/datasources.py +5 -8
  62. nautobot/extras/models/jobs.py +5 -0
  63. nautobot/extras/plugins/__init__.py +3 -0
  64. nautobot/extras/tables.py +40 -3
  65. nautobot/extras/templates/extras/configcontext.html +2 -220
  66. nautobot/extras/templates/extras/configcontext_edit.html +2 -50
  67. nautobot/extras/templates/extras/configcontext_retrieve.html +2 -0
  68. nautobot/extras/templates/extras/configcontext_update.html +50 -0
  69. nautobot/extras/templates/extras/configcontextschema.html +2 -48
  70. nautobot/extras/templates/extras/configcontextschema_edit.html +2 -19
  71. nautobot/extras/templates/extras/configcontextschema_retrieve.html +48 -0
  72. nautobot/extras/templates/extras/configcontextschema_update.html +19 -0
  73. nautobot/extras/templates/extras/inc/configcontext_data.html +1 -0
  74. nautobot/extras/templates/extras/inc/json_data.html +1 -1
  75. nautobot/extras/templates/extras/inc/json_format.html +2 -2
  76. nautobot/extras/templates/extras/job_edit.html +12 -6
  77. nautobot/extras/templates/extras/tag.html +2 -52
  78. nautobot/extras/templates/extras/tag_edit.html +2 -15
  79. nautobot/extras/templates/extras/tag_retrieve.html +52 -0
  80. nautobot/extras/templates/extras/tag_update.html +15 -0
  81. nautobot/extras/templates/extras/team_retrieve.html +2 -2
  82. nautobot/extras/tests/test_api.py +15 -15
  83. nautobot/extras/tests/test_filters.py +4 -4
  84. nautobot/extras/tests/test_jobs.py +23 -10
  85. nautobot/extras/tests/test_models.py +19 -8
  86. nautobot/extras/tests/test_plugins.py +6 -3
  87. nautobot/extras/tests/test_views.py +66 -11
  88. nautobot/extras/urls.py +4 -134
  89. nautobot/extras/views.py +113 -158
  90. nautobot/ipam/models.py +19 -4
  91. nautobot/ipam/tables.py +19 -0
  92. nautobot/ipam/templates/ipam/vlan.html +2 -84
  93. nautobot/ipam/templates/ipam/vlan_edit.html +2 -24
  94. nautobot/ipam/templates/ipam/vlan_retrieve.html +84 -0
  95. nautobot/ipam/templates/ipam/vlan_update.html +24 -0
  96. nautobot/ipam/tests/test_views.py +5 -0
  97. nautobot/ipam/urls.py +1 -21
  98. nautobot/ipam/views.py +45 -70
  99. nautobot/project-static/docs/404.html +31 -8
  100. nautobot/project-static/docs/apps/index.html +31 -8
  101. nautobot/project-static/docs/apps/nautobot-apps.html +31 -8
  102. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +31 -8
  103. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +31 -8
  104. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +31 -8
  105. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +31 -8
  106. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +31 -8
  107. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +31 -8
  108. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +31 -8
  109. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +31 -8
  110. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +31 -8
  111. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +31 -8
  112. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +31 -8
  113. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +31 -8
  114. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +31 -8
  115. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +31 -8
  116. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +31 -8
  117. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +31 -8
  118. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +31 -8
  119. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +31 -8
  120. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +31 -8
  121. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +120 -8
  122. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +31 -8
  123. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +31 -8
  124. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +31 -8
  125. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +31 -8
  126. nautobot/project-static/docs/development/apps/api/configuration-view.html +31 -8
  127. nautobot/project-static/docs/development/apps/api/database-backend-config.html +31 -8
  128. nautobot/project-static/docs/development/apps/api/models/django-admin.html +31 -8
  129. nautobot/project-static/docs/development/apps/api/models/global-search.html +31 -8
  130. nautobot/project-static/docs/development/apps/api/models/graphql.html +31 -8
  131. nautobot/project-static/docs/development/apps/api/models/index.html +31 -8
  132. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +40 -8
  133. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +31 -8
  134. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +31 -8
  135. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +31 -8
  136. nautobot/project-static/docs/development/apps/api/platform-features/index.html +31 -8
  137. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +31 -8
  138. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +31 -8
  139. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +31 -8
  140. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +32 -9
  141. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +31 -8
  142. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +31 -8
  143. nautobot/project-static/docs/development/apps/api/prometheus.html +31 -8
  144. nautobot/project-static/docs/development/apps/api/setup.html +31 -8
  145. nautobot/project-static/docs/development/apps/api/testing.html +31 -8
  146. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +31 -8
  147. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +31 -8
  148. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +31 -8
  149. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +31 -8
  150. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +31 -8
  151. nautobot/project-static/docs/development/apps/api/views/base-template.html +31 -8
  152. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +31 -8
  153. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +31 -8
  154. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +31 -8
  155. nautobot/project-static/docs/development/apps/api/views/index.html +31 -8
  156. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +31 -8
  157. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +31 -8
  158. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +31 -8
  159. nautobot/project-static/docs/development/apps/api/views/notes.html +31 -8
  160. nautobot/project-static/docs/development/apps/api/views/rest-api.html +31 -8
  161. nautobot/project-static/docs/development/apps/api/views/urls.html +31 -8
  162. nautobot/project-static/docs/development/apps/index.html +31 -8
  163. nautobot/project-static/docs/development/apps/migration/code-updates.html +31 -8
  164. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +31 -8
  165. nautobot/project-static/docs/development/apps/migration/from-v1.html +31 -8
  166. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +31 -8
  167. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +31 -8
  168. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +31 -8
  169. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +31 -8
  170. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +31 -8
  171. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +31 -8
  172. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +31 -8
  173. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +31 -8
  174. nautobot/project-static/docs/development/apps/porting-from-netbox.html +31 -8
  175. nautobot/project-static/docs/development/core/application-registry.html +31 -8
  176. nautobot/project-static/docs/development/core/best-practices.html +31 -8
  177. nautobot/project-static/docs/development/core/bootstrap-ui.html +31 -8
  178. nautobot/project-static/docs/development/core/caching.html +31 -8
  179. nautobot/project-static/docs/development/core/controllers.html +31 -8
  180. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +31 -8
  181. nautobot/project-static/docs/development/core/generic-views.html +31 -8
  182. nautobot/project-static/docs/development/core/getting-started.html +31 -8
  183. nautobot/project-static/docs/development/core/homepage.html +31 -8
  184. nautobot/project-static/docs/development/core/index.html +31 -8
  185. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +31 -8
  186. nautobot/project-static/docs/development/core/model-checklist.html +31 -8
  187. nautobot/project-static/docs/development/core/model-features.html +31 -8
  188. nautobot/project-static/docs/development/core/natural-keys.html +31 -8
  189. nautobot/project-static/docs/development/core/navigation-menu.html +31 -8
  190. nautobot/project-static/docs/development/core/release-checklist.html +31 -8
  191. nautobot/project-static/docs/development/core/role-internals.html +31 -8
  192. nautobot/project-static/docs/development/core/settings.html +31 -8
  193. nautobot/project-static/docs/development/core/style-guide.html +31 -8
  194. nautobot/project-static/docs/development/core/templates.html +31 -8
  195. nautobot/project-static/docs/development/core/testing.html +31 -8
  196. nautobot/project-static/docs/development/core/ui-component-framework.html +31 -8
  197. nautobot/project-static/docs/development/core/user-preferences.html +31 -8
  198. nautobot/project-static/docs/development/index.html +31 -8
  199. nautobot/project-static/docs/development/jobs/getting-started.html +35 -8
  200. nautobot/project-static/docs/development/jobs/index.html +31 -8
  201. nautobot/project-static/docs/development/jobs/installation.html +31 -8
  202. nautobot/project-static/docs/development/jobs/job-extensions.html +31 -8
  203. nautobot/project-static/docs/development/jobs/job-logging.html +31 -8
  204. nautobot/project-static/docs/development/jobs/job-patterns.html +31 -8
  205. nautobot/project-static/docs/development/jobs/job-structure.html +31 -8
  206. nautobot/project-static/docs/development/jobs/migration/from-v1.html +31 -8
  207. nautobot/project-static/docs/development/jobs/testing.html +31 -8
  208. nautobot/project-static/docs/index.html +31 -8
  209. nautobot/project-static/docs/insert-analytics.sh +36 -0
  210. nautobot/project-static/docs/objects.inv +0 -0
  211. nautobot/project-static/docs/overview/application_stack.html +31 -8
  212. nautobot/project-static/docs/overview/design_philosophy.html +31 -8
  213. nautobot/project-static/docs/release-notes/index.html +31 -8
  214. nautobot/project-static/docs/release-notes/version-1.0.html +31 -8
  215. nautobot/project-static/docs/release-notes/version-1.1.html +31 -8
  216. nautobot/project-static/docs/release-notes/version-1.2.html +31 -8
  217. nautobot/project-static/docs/release-notes/version-1.3.html +31 -8
  218. nautobot/project-static/docs/release-notes/version-1.4.html +31 -8
  219. nautobot/project-static/docs/release-notes/version-1.5.html +31 -8
  220. nautobot/project-static/docs/release-notes/version-1.6.html +31 -8
  221. nautobot/project-static/docs/release-notes/version-2.0.html +31 -8
  222. nautobot/project-static/docs/release-notes/version-2.1.html +31 -8
  223. nautobot/project-static/docs/release-notes/version-2.2.html +31 -8
  224. nautobot/project-static/docs/release-notes/version-2.3.html +31 -8
  225. nautobot/project-static/docs/release-notes/version-2.4.html +252 -8
  226. nautobot/project-static/docs/search/search_index.json +1 -1
  227. nautobot/project-static/docs/sitemap.xml +302 -298
  228. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  229. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +31 -8
  230. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +31 -8
  231. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +31 -8
  232. nautobot/project-static/docs/user-guide/administration/configuration/index.html +31 -8
  233. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +31 -8
  234. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +31 -8
  235. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +31 -8
  236. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +31 -8
  237. nautobot/project-static/docs/user-guide/administration/guides/docker.html +31 -8
  238. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +31 -8
  239. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +31 -8
  240. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +31 -8
  241. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +31 -8
  242. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +31 -8
  243. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +31 -8
  244. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +31 -8
  245. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +31 -8
  246. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +31 -8
  247. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +31 -8
  248. nautobot/project-static/docs/user-guide/administration/installation/index.html +31 -8
  249. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +31 -8
  250. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +31 -8
  251. nautobot/project-static/docs/user-guide/administration/installation/services.html +31 -8
  252. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +31 -8
  253. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +31 -8
  254. nautobot/project-static/docs/user-guide/administration/security/index.html +31 -8
  255. nautobot/project-static/docs/user-guide/administration/security/notices.html +31 -8
  256. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +31 -8
  257. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +31 -8
  258. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +31 -8
  259. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +31 -8
  260. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +31 -8
  261. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +31 -8
  262. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +31 -8
  263. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +31 -8
  264. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +31 -8
  265. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +31 -8
  266. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +31 -8
  267. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +31 -8
  268. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +31 -8
  269. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +31 -8
  270. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +31 -8
  271. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +31 -8
  272. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +31 -8
  273. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +31 -8
  274. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +31 -8
  275. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +31 -8
  276. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +31 -8
  277. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +31 -8
  278. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +31 -8
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +31 -8
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +31 -8
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +31 -8
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +31 -8
  283. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +31 -8
  284. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +31 -8
  285. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +31 -8
  286. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +31 -8
  287. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +31 -8
  288. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +31 -8
  289. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +31 -8
  290. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +43 -20
  291. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +31 -8
  292. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +31 -8
  293. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +31 -8
  294. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +31 -8
  295. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +31 -8
  296. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +31 -8
  297. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +31 -8
  298. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +31 -8
  299. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +31 -8
  300. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +31 -8
  301. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +35 -8
  302. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +35 -8
  303. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +35 -8
  304. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +10261 -0
  305. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +34 -11
  306. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +31 -8
  307. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +31 -8
  308. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +31 -8
  309. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +31 -8
  310. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +31 -8
  311. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +31 -8
  312. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +31 -8
  313. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +31 -8
  314. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +31 -8
  315. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +31 -8
  316. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +31 -8
  317. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +31 -8
  318. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +31 -8
  319. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +31 -8
  320. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +31 -8
  321. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +31 -8
  322. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +31 -8
  323. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +31 -8
  324. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +31 -8
  325. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +31 -8
  326. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +31 -8
  327. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +31 -8
  328. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +31 -8
  329. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +31 -8
  330. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +31 -8
  331. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +31 -8
  332. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +31 -8
  333. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +31 -8
  334. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +31 -8
  335. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +31 -8
  336. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +31 -8
  337. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +31 -8
  338. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +31 -8
  339. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +31 -8
  340. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +31 -8
  341. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +31 -8
  342. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +31 -8
  343. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +31 -8
  344. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +31 -8
  345. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +31 -8
  346. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +31 -8
  347. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +31 -8
  348. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +31 -8
  349. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +31 -8
  350. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +31 -8
  351. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +31 -8
  352. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +31 -8
  353. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +31 -8
  354. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +31 -8
  355. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +31 -8
  356. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +31 -8
  357. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +31 -8
  358. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +41 -15
  359. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +31 -8
  360. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +31 -8
  361. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +31 -8
  362. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +31 -8
  363. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +31 -8
  364. nautobot/project-static/docs/user-guide/index.html +31 -8
  365. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +31 -8
  366. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +31 -8
  367. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +31 -8
  368. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +31 -8
  369. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +31 -8
  370. nautobot/project-static/docs/user-guide/platform-functionality/events.html +31 -8
  371. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +31 -8
  372. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +31 -8
  373. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +37 -9
  374. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +31 -8
  375. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +31 -8
  376. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +31 -8
  377. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +31 -8
  378. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +31 -8
  379. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +31 -8
  380. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +31 -8
  381. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +31 -8
  382. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +31 -8
  383. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +31 -8
  384. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +31 -8
  385. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +31 -8
  386. nautobot/project-static/docs/user-guide/platform-functionality/note.html +31 -8
  387. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +31 -8
  388. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +31 -8
  389. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +31 -8
  390. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +31 -8
  391. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +31 -8
  392. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +31 -8
  393. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +31 -8
  394. nautobot/project-static/docs/user-guide/platform-functionality/role.html +31 -8
  395. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +31 -8
  396. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +31 -8
  397. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +31 -8
  398. nautobot/project-static/docs/user-guide/platform-functionality/status.html +31 -8
  399. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +31 -8
  400. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +31 -8
  401. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +31 -8
  402. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +31 -8
  403. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +31 -8
  404. nautobot/tenancy/tables.py +2 -0
  405. nautobot/virtualization/tests/test_views.py +1 -1
  406. nautobot/wireless/forms.py +0 -1
  407. nautobot/wireless/models.py +1 -1
  408. nautobot/wireless/tables.py +7 -0
  409. {nautobot-2.4.10.dist-info → nautobot-2.4.11.dist-info}/METADATA +4 -4
  410. {nautobot-2.4.10.dist-info → nautobot-2.4.11.dist-info}/RECORD +416 -401
  411. /nautobot/dcim/templates/dcim/{platform_edit.html → platform_create.html} +0 -0
  412. /nautobot/extras/test_jobs/{pass.py → pass_job.py} +0 -0
  413. {nautobot-2.4.10.dist-info → nautobot-2.4.11.dist-info}/LICENSE.txt +0 -0
  414. {nautobot-2.4.10.dist-info → nautobot-2.4.11.dist-info}/NOTICE +0 -0
  415. {nautobot-2.4.10.dist-info → nautobot-2.4.11.dist-info}/WHEEL +0 -0
  416. {nautobot-2.4.10.dist-info → nautobot-2.4.11.dist-info}/entry_points.txt +0 -0
@@ -15,4 +15,96 @@
15
15
  {% endif %}
16
16
  {% endif %}
17
17
  <li><a href="{{ object.get_absolute_url }}">{{ object.name }}</a></li>
18
- {% endblock breadcrumbs %}
18
+ {% endblock breadcrumbs %}
19
+ {% block content_left_page %}
20
+ <div class="panel panel-default">
21
+ <div class="panel-heading">
22
+ <strong>Module Bay</strong>
23
+ </div>
24
+ <table class="table table-hover panel-body attr-table">
25
+ <tr>
26
+ {% if object.parent_device %}
27
+ <td>Parent Device</td>
28
+ <td>
29
+ {{ object.parent_device|hyperlinked_object }}
30
+ </td>
31
+ {% else %}
32
+ <td>Parent Module</td>
33
+ <td>
34
+ {{ object.parent_module|hyperlinked_object }}
35
+ </td>
36
+ {% endif %}
37
+ </tr>
38
+ <tr>
39
+ <td>Family</td>
40
+ <td>
41
+ {{ object.module_family|hyperlinked_object }}
42
+ </td>
43
+ </tr>
44
+ <tr>
45
+ <td>Name</td>
46
+ <td>{{ object.name }}</td>
47
+ </tr>
48
+ <tr>
49
+ <td>Position</td>
50
+ <td>{{ object.position }}</td>
51
+ </tr>
52
+ <tr>
53
+ <td>Label</td>
54
+ <td>{{ object.label|placeholder }}</td>
55
+ </tr>
56
+ <tr>
57
+ <td>Description</td>
58
+ <td>{{ object.description|placeholder }}</td>
59
+ </tr>
60
+ <tr>
61
+ <td>Requires first-party modules</td>
62
+ <td>{{ object.requires_first_party_modules|render_boolean }}</td>
63
+ </tr>
64
+ </table>
65
+ </div>
66
+ {% endblock content_left_page %}
67
+
68
+ {% block content_right_page %}
69
+ {% if object.installed_module %}
70
+ <div class="panel panel-default">
71
+ <div class="panel-heading">
72
+ <strong>Installed Module</strong>
73
+ </div>
74
+ <table class="table table-hover panel-body attr-table">
75
+ <tr>
76
+ <td>Module</td>
77
+ <td>
78
+ {{ object.installed_module|hyperlinked_object }}
79
+ </td>
80
+ </tr>
81
+ <tr>
82
+ <td>Module Type</td>
83
+ <td>
84
+ {{ object.installed_module.module_type|hyperlinked_object }}
85
+ </td>
86
+ </tr>
87
+ <tr>
88
+ <td>Status</td>
89
+ <td>{{ object.installed_module.status|hyperlinked_object_with_color }}</td>
90
+ </tr>
91
+ <tr>
92
+ <td>Role</td>
93
+ <td>{{ object.installed_module.role|hyperlinked_object_with_color }}</td>
94
+ </tr>
95
+ <tr>
96
+ <td>Serial</td>
97
+ <td>{{ object.installed_module.serial|placeholder }}</td>
98
+ </tr>
99
+ <tr>
100
+ <td>Asset Tag</td>
101
+ <td>{{ object.installed_module.asset_tag|placeholder }}</td>
102
+ </tr>
103
+ <tr>
104
+ <td>Tenant</td>
105
+ <td>{{ object.installed_module.tenant|hyperlinked_object }}</td>
106
+ </tr>
107
+ </table>
108
+ </div>
109
+ {% endif %}
110
+ {% endblock content_right_page %}
@@ -0,0 +1,31 @@
1
+ {% extends 'generic/object_detail.html' %}
2
+ {% load helpers %}
3
+
4
+ {% block content_left_page %}
5
+ <div class="panel panel-default">
6
+ <div class="panel-heading">
7
+ <strong>Module Family</strong>
8
+ </div>
9
+ <table class="table table-hover panel-body attr-table">
10
+ <tr>
11
+ <td>Description</td>
12
+ <td>{{ object.description|placeholder }}</td>
13
+ </tr>
14
+ </table>
15
+ </div>
16
+ {% endblock content_left_page %}
17
+
18
+ {% block content_right_page %}
19
+ <div class="panel panel-default">
20
+ <div class="panel-heading">
21
+ <strong>Module Types</strong>
22
+ </div>
23
+ {% include 'inc/table.html' with table=module_type_table %}
24
+ </div>
25
+ <div class="panel panel-default">
26
+ <div class="panel-heading">
27
+ <strong>Module Bays</strong>
28
+ </div>
29
+ {% include 'inc/table.html' with table=module_bay_table %}
30
+ </div>
31
+ {% endblock content_right_page %}
@@ -101,6 +101,12 @@
101
101
  {{ object.model }}<br/>
102
102
  </td>
103
103
  </tr>
104
+ <tr>
105
+ <td>Family</td>
106
+ <td>
107
+ {{ object.module_family|hyperlinked_object }}<br/>
108
+ </td>
109
+ </tr>
104
110
  <tr>
105
111
  <td>Part Number</td>
106
112
  <td>{{ object.part_number|placeholder }}</td>
@@ -1,168 +1,9 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
2
  {% load helpers %}
3
-
4
3
  {% block extra_breadcrumbs %}
5
4
  <li>{{ object.power_panel.location|hyperlinked_object }}</li>
6
5
  <li>{{ object.power_panel|hyperlinked_object }}</li>
7
6
  {% if object.rack %}
8
7
  <li>{{ object.rack|hyperlinked_object }}</li>
9
8
  {% endif %}
10
- {% endblock extra_breadcrumbs %}
11
-
12
- {% block content_left_page %}
13
- <div class="panel panel-default">
14
- <div class="panel-heading">
15
- <strong>Power Feed</strong>
16
- </div>
17
- <table class="table table-hover panel-body attr-table">
18
- <tr>
19
- <td>Power Panel</td>
20
- <td>{{ object.power_panel|hyperlinked_object }}</td>
21
- </tr>
22
- <tr>
23
- <td>Rack</td>
24
- <td>{{ object.rack|hyperlinked_object }}</td>
25
- </tr>
26
- <tr>
27
- <td>Type</td>
28
- <td>
29
- <span class="label label-{{ object.get_type_class }}">{{ object.get_type_display }}</span>
30
- </td>
31
- </tr>
32
- <tr>
33
- <td>Status</td>
34
- <td>
35
- {{ object.status| hyperlinked_object_with_color }}
36
- </td>
37
- </tr>
38
- <tr>
39
- <td>Connected Device</td>
40
- <td>
41
- {% if object.connected_endpoint %}
42
- {{ object.connected_endpoint.parent|hyperlinked_object }}
43
- ({{ object.connected_endpoint }})
44
- {% else %}
45
- <span class="text-muted">None</span>
46
- {% endif %}
47
- </td>
48
- </tr>
49
- <tr>
50
- <td>Utilization (Allocated)</td>
51
- {% with utilization=object.connected_endpoint.get_power_draw %}
52
- {% if utilization %}
53
- <td>
54
- {{ utilization.allocated }}VA / {{ object.available_power }}VA
55
- {% if object.available_power > 0 %}
56
- {% utilization_graph_raw_data utilization.allocated object.available_power %}
57
- {% endif %}
58
- </td>
59
- {% else %}
60
- <td class="text-muted">N/A</td>
61
- {% endif %}
62
- {% endwith %}
63
- </tr>
64
- </table>
65
- </div>
66
- <div class="panel panel-default">
67
- <div class="panel-heading">
68
- <strong>Electrical Characteristics</strong>
69
- </div>
70
- <table class="table table-hover panel-body attr-table">
71
- <tr>
72
- <td>Supply</td>
73
- <td>{{ object.get_supply_display }}</td>
74
- </tr>
75
- <tr>
76
- <td>Voltage</td>
77
- <td>{{ object.voltage }}V</td>
78
- </tr>
79
- <tr>
80
- <td>Amperage</td>
81
- <td>{{ object.amperage }}A</td>
82
- </tr>
83
- <tr>
84
- <td>Phase</td>
85
- <td>{{ object.get_phase_display }}</td>
86
- </tr>
87
- <tr>
88
- <td>Max Utilization</td>
89
- <td>{{ object.max_utilization }}%</td>
90
- </tr>
91
- </table>
92
- </div>
93
- {% endblock content_left_page %}
94
-
95
- {% block content_right_page %}
96
- <div class="panel panel-default">
97
- <div class="panel-heading">
98
- <strong>Connection</strong>
99
- </div>
100
- {% if object.cable %}
101
- <table class="table table-hover panel-body attr-table">
102
- <tr>
103
- <td>Cable</td>
104
- <td>
105
- {{ object.cable|hyperlinked_object }}
106
- <a href="{% url 'dcim:powerfeed_trace' pk=object.pk %}" class="btn btn-primary btn-xs" title="Trace">
107
- <i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i>
108
- </a>
109
- </td>
110
- </tr>
111
- {% if object.connected_endpoint %}
112
- <tr>
113
- {% if object.connected_endpoint.device %}
114
- <td>Device</td>
115
- <td>{{ object.connected_endpoint.device|hyperlinked_object }}</td>
116
- {% else %}
117
- <td>Module</td>
118
- <td>{{ object.connected_endpoint.module|hyperlinked_object }}</td>
119
- {% endif %}
120
- </tr>
121
- <tr>
122
- <td>Power Port</td>
123
- <td>{{ object.connected_endpoint|hyperlinked_object }}</td>
124
- </tr>
125
- <tr>
126
- <td>Type</td>
127
- <td>{{ object.connected_endpoint.get_type_display|placeholder }}</td>
128
- </tr>
129
- <tr>
130
- <td>Description</td>
131
- <td>{{ object.connected_endpoint.description|placeholder }}</td>
132
- </tr>
133
- <tr>
134
- <td>Path Status</td>
135
- <td>
136
- {% if object.path.is_active %}
137
- <span class="label label-success">Reachable</span>
138
- {% else %}
139
- <span class="label label-danger">Not Reachable</span>
140
- {% endif %}
141
- </td>
142
- </tr>
143
- {% endif %}
144
- </table>
145
- {% else %}
146
- <div class="panel-body text-muted">
147
- {% if perms.dcim.add_cable %}
148
- <a href="{% url 'dcim:powerfeed_connect' termination_a_id=object.pk termination_b_type='power-port' %}?return_url={{ object.get_absolute_url }}" class="btn btn-primary btn-sm pull-right">
149
- <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
150
- </a>
151
- {% endif %}
152
- Not connected
153
- </div>
154
- {% endif %}
155
- </div>
156
- <div class="panel panel-default">
157
- <div class="panel-heading">
158
- <strong>Comments</strong>
159
- </div>
160
- <div class="panel-body rendered-markdown">
161
- {% if object.comments %}
162
- {{ object.comments|render_markdown }}
163
- {% else %}
164
- <span class="text-muted">None</span>
165
- {% endif %}
166
- </div>
167
- </div>
168
- {% endblock content_right_page %}
9
+ {% endblock extra_breadcrumbs %}
@@ -50,6 +50,7 @@ from nautobot.dcim.models import (
50
50
  Module,
51
51
  ModuleBay,
52
52
  ModuleBayTemplate,
53
+ ModuleFamily,
53
54
  ModuleType,
54
55
  Platform,
55
56
  PowerFeed,
@@ -1388,15 +1389,18 @@ class ModuleBayTemplateTest(Mixins.ModularDeviceComponentTemplateMixin, Mixins.B
1388
1389
  @classmethod
1389
1390
  def setUpTestData(cls):
1390
1391
  super().setUpTestData()
1392
+ cls.module_family = ModuleFamily.objects.create(name="Test Module Family")
1391
1393
 
1392
1394
  cls.create_data = [
1393
1395
  {
1394
1396
  "device_type": cls.device_type.pk,
1395
1397
  "name": "Test1",
1398
+ "module_family": cls.module_family.pk,
1396
1399
  },
1397
1400
  {
1398
1401
  "module_type": cls.module_type.pk,
1399
1402
  "name": "Test2",
1403
+ "module_family": cls.module_family.pk,
1400
1404
  },
1401
1405
  {
1402
1406
  "device_type": cls.device_type.pk,
@@ -3792,3 +3796,34 @@ class InterfaceVDCAssignmentTestCase(APIViewTestCases.APIViewTestCase):
3792
3796
  def test_docs(self):
3793
3797
  """Skip: InterfaceVDCAssignment has no docs yet"""
3794
3798
  # TODO(timizuo): Add docs for Interface VDC Assignment
3799
+
3800
+
3801
+ class ModuleFamilyTest(APIViewTestCases.APIViewTestCase):
3802
+ """Test the ModuleFamily API."""
3803
+
3804
+ model = ModuleFamily
3805
+ brief_fields = ["display", "id", "name", "url"]
3806
+ create_data = [
3807
+ {
3808
+ "name": "Module Family 4",
3809
+ "description": "Fourth family",
3810
+ },
3811
+ {
3812
+ "name": "Module Family 5",
3813
+ "description": "Fifth family",
3814
+ },
3815
+ {
3816
+ "name": "Module Family 6",
3817
+ "description": "Sixth family",
3818
+ },
3819
+ ]
3820
+ bulk_update_data = {
3821
+ "description": "New description",
3822
+ }
3823
+
3824
+ @classmethod
3825
+ def setUpTestData(cls):
3826
+ """Create test data for API tests."""
3827
+ ModuleFamily.objects.create(name="Module Family 1", description="First family")
3828
+ ModuleFamily.objects.create(name="Module Family 2", description="Second family")
3829
+ ModuleFamily.objects.create(name="Module Family 3", description="Third family")
@@ -52,6 +52,7 @@ from nautobot.dcim.filters import (
52
52
  ManufacturerFilterSet,
53
53
  ModuleBayFilterSet,
54
54
  ModuleBayTemplateFilterSet,
55
+ ModuleFamilyFilterSet,
55
56
  ModuleFilterSet,
56
57
  ModuleTypeFilterSet,
57
58
  PlatformFilterSet,
@@ -100,6 +101,7 @@ from nautobot.dcim.models import (
100
101
  Module,
101
102
  ModuleBay,
102
103
  ModuleBayTemplate,
104
+ ModuleFamily,
103
105
  ModuleType,
104
106
  Platform,
105
107
  PowerFeed,
@@ -573,12 +575,20 @@ def common_test_data(cls):
573
575
  label="devicebay3",
574
576
  description="Device Bay Description 3",
575
577
  )
578
+
579
+ cls.module_families = (
580
+ ModuleFamily.objects.create(name="Module Family 1"),
581
+ ModuleFamily.objects.create(name="Module Family 2"),
582
+ ModuleFamily.objects.create(name="Module Family 3"),
583
+ )
576
584
  ModuleBayTemplate.objects.create(
577
585
  device_type=device_types[0],
578
586
  name="device test module bay 1",
579
587
  position=1,
580
588
  label="devicemodulebay1",
581
589
  description="device test module bay 1 description",
590
+ module_family=cls.module_families[0],
591
+ requires_first_party_modules=True,
582
592
  )
583
593
  ModuleBayTemplate.objects.create(
584
594
  device_type=device_types[1],
@@ -586,13 +596,16 @@ def common_test_data(cls):
586
596
  position=2,
587
597
  label="devicemodulebay2",
588
598
  description="device test module bay 2 description",
599
+ module_family=cls.module_families[1],
600
+ requires_first_party_modules=False,
589
601
  )
590
602
  ModuleBayTemplate.objects.create(
591
603
  device_type=device_types[2],
592
604
  name="device test module bay 3",
593
605
  position=3,
594
606
  label="devicemodulebay3",
595
- description="device test module bay 3 description",
607
+ description="device test module bay 3 without a module family",
608
+ requires_first_party_modules=True,
596
609
  )
597
610
  secrets_groups = (
598
611
  SecretsGroup.objects.create(name="Secrets group 1"),
@@ -667,10 +680,16 @@ def common_test_data(cls):
667
680
  manufacturer=cls.manufacturers[0], model="Filter Test Module Type 1", comments="Module Type 1"
668
681
  ),
669
682
  ModuleType.objects.create(
670
- manufacturer=cls.manufacturers[1], model="Filter Test Module Type 2", comments="Module Type 2"
683
+ manufacturer=cls.manufacturers[1],
684
+ model="Filter Test Module Type 2",
685
+ comments="Module Type 2",
686
+ module_family=cls.module_families[0],
671
687
  ),
672
688
  ModuleType.objects.create(
673
- manufacturer=cls.manufacturers[2], model="Filter Test Module Type 3", comments="Module Type 3"
689
+ manufacturer=cls.manufacturers[2],
690
+ model="Filter Test Module Type 3",
691
+ comments="Module Type 3",
692
+ module_family=cls.module_families[1],
674
693
  ),
675
694
  )
676
695
 
@@ -715,6 +734,7 @@ def common_test_data(cls):
715
734
  name=f"Test Filters Module Module Bay {i+1}",
716
735
  position=i + 1,
717
736
  module_type=module_types[i % 2],
737
+ requires_first_party_modules=(i % 2 == 0), # True for even indices, False for odd
718
738
  )
719
739
 
720
740
  module_roles = Role.objects.get_for_model(Module)
@@ -4055,6 +4075,18 @@ class ModuleTestCase(
4055
4075
  Interface.objects.filter(pk=interfaces[0].pk).update(mac_address="00-00-00-00-00-01")
4056
4076
  Interface.objects.filter(pk=interfaces[1].pk).update(mac_address="00-00-00-00-00-02")
4057
4077
 
4078
+ def test_compatible_with_module_bay(self):
4079
+ """Test filtering modules that are compatible with a specific module bay based on module family."""
4080
+ module_bay = ModuleBay.objects.filter(module_family__isnull=False).first()
4081
+ compatible_modules = Module.objects.filter(module_type__module_family=module_bay.module_family)
4082
+ params = {"compatible_with_module_bay": module_bay.pk}
4083
+ self.assertQuerysetEqualAndNotEmpty(self.filterset(params).qs, compatible_modules)
4084
+
4085
+ # Test with module bay that has no module family - should return ALL modules
4086
+ module_bay_no_family = ModuleBay.objects.filter(module_family__isnull=True).first()
4087
+ params = {"compatible_with_module_bay": module_bay_no_family.pk}
4088
+ self.assertQuerysetEqual(self.filterset(params).qs, self.queryset, ordered=False)
4089
+
4058
4090
 
4059
4091
  class ModuleTypeTestCase(FilterTestCases.FilterTestCase):
4060
4092
  queryset = ModuleType.objects.all()
@@ -4080,12 +4112,26 @@ class ModuleTypeTestCase(FilterTestCases.FilterTestCase):
4080
4112
  ("rear_port_templates", "rear_port_templates__id"),
4081
4113
  ("rear_port_templates", "rear_port_templates__name"),
4082
4114
  ("module_bay_templates", "module_bay_templates__id"),
4115
+ ("module_family", "module_family__id"),
4116
+ ("module_family", "module_family__name"),
4083
4117
  ]
4084
4118
 
4085
4119
  @classmethod
4086
4120
  def setUpTestData(cls):
4087
4121
  common_test_data(cls)
4088
4122
 
4123
+ def test_compatible_with_module_bay(self):
4124
+ """Test filtering module types that are compatible with a specific module bay based on module family."""
4125
+ module_bay = ModuleBay.objects.filter(module_family__isnull=False).first()
4126
+ compatible_module_types = ModuleType.objects.filter(module_family=module_bay.module_family)
4127
+ params = {"compatible_with_module_bay": module_bay.pk}
4128
+ self.assertQuerysetEqualAndNotEmpty(self.filterset(params).qs, compatible_module_types)
4129
+
4130
+ # Test with module bay that has no module family - should return ALL module types
4131
+ module_bay_no_family = ModuleBay.objects.filter(module_family__isnull=True).first()
4132
+ params = {"compatible_with_module_bay": module_bay_no_family.pk}
4133
+ self.assertQuerysetEqual(self.filterset(params).qs, self.queryset, ordered=False)
4134
+
4089
4135
 
4090
4136
  class ModuleBayTemplateTestCase(FilterTestCases.FilterTestCase):
4091
4137
  queryset = ModuleBayTemplate.objects.all()
@@ -4097,6 +4143,8 @@ class ModuleBayTemplateTestCase(FilterTestCases.FilterTestCase):
4097
4143
  ("label",),
4098
4144
  ("module_type", "module_type__id"),
4099
4145
  ("module_type", "module_type__model"),
4146
+ ("module_family", "module_family__id"),
4147
+ ("module_family", "module_family__name"),
4100
4148
  ("name",),
4101
4149
  ("position",),
4102
4150
  ]
@@ -4105,6 +4153,21 @@ class ModuleBayTemplateTestCase(FilterTestCases.FilterTestCase):
4105
4153
  def setUpTestData(cls):
4106
4154
  common_test_data(cls)
4107
4155
 
4156
+ def test_requires_first_party_modules(self):
4157
+ # TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
4158
+ with self.subTest():
4159
+ params = {"requires_first_party_modules": True}
4160
+ self.assertQuerysetEqual(
4161
+ self.filterset(params, self.queryset).qs,
4162
+ self.queryset.filter(requires_first_party_modules=True),
4163
+ )
4164
+ with self.subTest():
4165
+ params = {"requires_first_party_modules": False}
4166
+ self.assertQuerysetEqual(
4167
+ self.filterset(params, self.queryset).qs,
4168
+ self.queryset.filter(requires_first_party_modules=False),
4169
+ )
4170
+
4108
4171
 
4109
4172
  class ModuleBayTestCase(FilterTestCases.FilterTestCase):
4110
4173
  queryset = ModuleBay.objects.all()
@@ -4268,3 +4331,39 @@ class InterfaceVDCAssignmentTestCase(FilterTestCases.FilterTestCase):
4268
4331
  status=interface_status,
4269
4332
  ),
4270
4333
  )
4334
+
4335
+
4336
+ class ModuleFamilyTestCase(FilterTestCases.FilterTestCase):
4337
+ """Test cases for the ModuleFamilyFilterSet."""
4338
+
4339
+ queryset = ModuleFamily.objects.all()
4340
+ filterset = ModuleFamilyFilterSet
4341
+ generic_filter_tests = [
4342
+ ("name",),
4343
+ ("description",),
4344
+ ("module_types", "module_types__id"),
4345
+ ("module_types", "module_types__model"),
4346
+ ]
4347
+
4348
+ @classmethod
4349
+ def setUpTestData(cls):
4350
+ """Create test data for filter tests."""
4351
+ manufacturers = (
4352
+ Manufacturer.objects.create(name="Manufacturer 1"),
4353
+ Manufacturer.objects.create(name="Manufacturer 2"),
4354
+ )
4355
+
4356
+ cls.module_families = (
4357
+ ModuleFamily.objects.create(name="Module Family 1", description="First family"),
4358
+ ModuleFamily.objects.create(name="Module Family 2", description="Second family"),
4359
+ ModuleFamily.objects.create(name="Module Family 3", description="Third family"),
4360
+ )
4361
+
4362
+ cls.module_types = (
4363
+ ModuleType.objects.create(
4364
+ manufacturer=manufacturers[0], model="Model 1", module_family=cls.module_families[0]
4365
+ ),
4366
+ ModuleType.objects.create(
4367
+ manufacturer=manufacturers[1], model="Model 2", module_family=cls.module_families[1]
4368
+ ),
4369
+ )