nautobot 2.0.0a3__py3-none-any.whl → 2.0.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (780) hide show
  1. nautobot/apps/api.py +6 -8
  2. nautobot/apps/forms.py +0 -2
  3. nautobot/apps/ui.py +0 -8
  4. nautobot/circuits/api/serializers.py +9 -117
  5. nautobot/circuits/api/urls.py +1 -1
  6. nautobot/circuits/api/views.py +0 -1
  7. nautobot/circuits/forms.py +0 -65
  8. nautobot/circuits/migrations/0014_related_name_changes.py +1 -1
  9. nautobot/circuits/migrations/0016_tagsfield.py +34 -0
  10. nautobot/circuits/migrations/0017_fixup_null_statuses.py +22 -0
  11. nautobot/circuits/migrations/0018_status_nonnullable.py +22 -0
  12. nautobot/circuits/models.py +3 -87
  13. nautobot/circuits/navigation.py +14 -69
  14. nautobot/circuits/signals.py +0 -2
  15. nautobot/circuits/tables.py +39 -1
  16. nautobot/circuits/tests/integration/test_relationships.py +9 -9
  17. nautobot/circuits/tests/test_api.py +4 -8
  18. nautobot/circuits/tests/test_filters.py +10 -4
  19. nautobot/circuits/tests/test_models.py +5 -1
  20. nautobot/circuits/tests/test_views.py +27 -5
  21. nautobot/circuits/views.py +18 -10
  22. nautobot/core/api/__init__.py +8 -2
  23. nautobot/core/api/fields.py +15 -6
  24. nautobot/core/api/filter_backends.py +3 -2
  25. nautobot/core/api/metadata.py +237 -30
  26. nautobot/core/api/mixins.py +94 -0
  27. nautobot/core/api/pagination.py +4 -0
  28. nautobot/core/api/parsers.py +154 -0
  29. nautobot/core/api/renderers.py +153 -2
  30. nautobot/core/api/schema.py +46 -2
  31. nautobot/core/api/serializers.py +377 -35
  32. nautobot/core/api/urls.py +11 -3
  33. nautobot/core/api/utils.py +174 -2
  34. nautobot/core/api/versioning.py +32 -10
  35. nautobot/core/api/views.py +266 -72
  36. nautobot/core/apps/__init__.py +138 -220
  37. nautobot/core/celery/__init__.py +112 -41
  38. nautobot/core/celery/backends.py +19 -12
  39. nautobot/core/celery/control.py +46 -0
  40. nautobot/core/celery/encoders.py +53 -0
  41. nautobot/core/celery/log.py +38 -0
  42. nautobot/core/celery/schedulers.py +23 -4
  43. nautobot/core/celery/task.py +1 -16
  44. nautobot/core/checks.py +0 -27
  45. nautobot/core/choices.py +0 -113
  46. nautobot/core/{cli.py → cli/__init__.py} +1 -1
  47. nautobot/core/cli/__main__.py +3 -0
  48. nautobot/core/constants.py +0 -24
  49. nautobot/core/context_processors.py +12 -0
  50. nautobot/core/filters.py +2 -2
  51. nautobot/core/forms/__init__.py +0 -4
  52. nautobot/core/forms/fields.py +38 -65
  53. nautobot/core/forms/forms.py +4 -1
  54. nautobot/core/forms/utils.py +0 -52
  55. nautobot/core/graphql/schema.py +4 -27
  56. nautobot/core/jobs/__init__.py +75 -0
  57. nautobot/core/management/commands/build_ui.py +255 -0
  58. nautobot/core/management/commands/generate_test_data.py +3 -2
  59. nautobot/core/management/commands/post_upgrade.py +24 -24
  60. nautobot/core/models/__init__.py +26 -1
  61. nautobot/core/models/fields.py +24 -5
  62. nautobot/core/models/generics.py +2 -42
  63. nautobot/core/models/managers.py +5 -0
  64. nautobot/core/models/name_color_content_types.py +0 -14
  65. nautobot/core/models/tree_queries.py +14 -4
  66. nautobot/core/models/utils.py +5 -6
  67. nautobot/core/models/validators.py +17 -8
  68. nautobot/core/releases.py +8 -10
  69. nautobot/core/settings.py +80 -42
  70. nautobot/core/tables.py +5 -5
  71. nautobot/core/tasks.py +4 -7
  72. nautobot/core/templates/base.html +1 -49
  73. nautobot/core/templates/base_django.html +49 -0
  74. nautobot/core/templates/base_react.html +55 -0
  75. nautobot/core/templates/buttons/export.html +6 -4
  76. nautobot/core/templates/generic/object_bulk_create.html +10 -21
  77. nautobot/core/templates/generic/object_list.html +3 -1
  78. nautobot/core/templates/generic/object_retrieve_plugin_full_width.html +3 -0
  79. nautobot/core/templates/inc/footer.html +1 -0
  80. nautobot/core/templates/inc/javascript.html +0 -14
  81. nautobot/core/templates/inc/nav_menu.html +28 -33
  82. nautobot/core/templates/inc/object_details_advanced_panel.html +13 -0
  83. nautobot/core/templates/inc/relationships_table_rows.html +2 -2
  84. nautobot/core/templates/nautobot_config.py.j2 +8 -20
  85. nautobot/core/templates/plugin_template/__init__.py-tpl +1 -2
  86. nautobot/core/templates/rest_framework/api.html +8 -0
  87. nautobot/core/templatetags/buttons.py +32 -28
  88. nautobot/core/testing/__init__.py +47 -44
  89. nautobot/core/testing/api.py +362 -47
  90. nautobot/core/testing/filters.py +1 -1
  91. nautobot/core/testing/migrations.py +2 -0
  92. nautobot/core/testing/mixins.py +22 -9
  93. nautobot/core/testing/schema.py +2 -1
  94. nautobot/core/testing/views.py +21 -46
  95. nautobot/core/tests/integration/test_filters.py +17 -8
  96. nautobot/core/tests/integration/test_navbar.py +11 -34
  97. nautobot/core/tests/integration/test_plugin_navbar.py +9 -103
  98. nautobot/core/tests/nautobot_config.py +2 -3
  99. nautobot/core/tests/test_api.py +290 -21
  100. nautobot/core/tests/test_checks.py +0 -7
  101. nautobot/core/tests/test_filters.py +107 -59
  102. nautobot/core/tests/test_forms.py +26 -92
  103. nautobot/core/tests/test_graphql.py +110 -77
  104. nautobot/core/tests/test_logging.py +4 -0
  105. nautobot/core/tests/test_managers.py +3 -1
  106. nautobot/core/tests/test_models.py +2 -0
  107. nautobot/core/tests/test_paginator.py +3 -1
  108. nautobot/core/tests/test_releases.py +12 -12
  109. nautobot/core/tests/test_templatetags_helpers.py +4 -4
  110. nautobot/core/tests/test_utils.py +32 -68
  111. nautobot/core/tests/test_views.py +12 -15
  112. nautobot/core/utils/data.py +17 -0
  113. nautobot/core/utils/deprecation.py +9 -6
  114. nautobot/core/utils/filtering.py +8 -3
  115. nautobot/core/utils/git.py +12 -4
  116. nautobot/core/utils/lookup.py +3 -1
  117. nautobot/core/utils/requests.py +1 -104
  118. nautobot/core/views/__init__.py +1 -0
  119. nautobot/core/views/generic.py +75 -110
  120. nautobot/core/views/mixins.py +52 -61
  121. nautobot/core/views/renderers.py +6 -7
  122. nautobot/core/views/utils.py +80 -0
  123. nautobot/dcim/api/serializers.py +160 -667
  124. nautobot/dcim/api/urls.py +1 -1
  125. nautobot/dcim/api/views.py +7 -44
  126. nautobot/dcim/choices.py +2 -0
  127. nautobot/dcim/filters/__init__.py +21 -0
  128. nautobot/dcim/form_mixins.py +1 -27
  129. nautobot/dcim/forms.py +19 -765
  130. nautobot/dcim/migrations/0024_alter_device_and_rack_role_add_new_role.py +2 -1
  131. nautobot/dcim/migrations/0025_device_and_rack_roles_data_migrations.py +19 -13
  132. nautobot/dcim/migrations/0027_remove_device_role_and_rack_role.py +1 -1
  133. nautobot/dcim/migrations/0028_rename_foreignkey_fields.py +1 -1
  134. nautobot/dcim/migrations/0030_migrate_region_and_site_data_to_locations.py +2 -2
  135. nautobot/dcim/migrations/0035_related_name_changes.py +1 -1
  136. nautobot/dcim/migrations/0036_remove_region_and_site.py +1 -1
  137. nautobot/dcim/migrations/0040_tagsfield.py +109 -0
  138. nautobot/dcim/migrations/{0040_ipam__namespaces.py → 0041_ipam__namespaces.py} +1 -1
  139. nautobot/dcim/migrations/0042_fixup_null_statuses.py +51 -0
  140. nautobot/dcim/migrations/0043_status_nonnullable.py +72 -0
  141. nautobot/dcim/models/cables.py +3 -33
  142. nautobot/dcim/models/device_component_templates.py +6 -0
  143. nautobot/dcim/models/device_components.py +12 -198
  144. nautobot/dcim/models/devices.py +30 -143
  145. nautobot/dcim/models/locations.py +3 -64
  146. nautobot/dcim/models/power.py +3 -50
  147. nautobot/dcim/models/racks.py +7 -84
  148. nautobot/dcim/navigation.py +141 -467
  149. nautobot/dcim/signals.py +0 -2
  150. nautobot/dcim/tables/locations.py +2 -2
  151. nautobot/dcim/tables/power.py +1 -2
  152. nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -0
  153. nautobot/dcim/templates/dcim/devicetype.html +2 -2
  154. nautobot/dcim/templates/dcim/interface_connection_list.html +7 -0
  155. nautobot/dcim/templates/dcim/location.html +16 -1
  156. nautobot/dcim/templates/dcim/locationtype.html +15 -0
  157. nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -0
  158. nautobot/dcim/templates/dcim/rackgroup.html +0 -12
  159. nautobot/dcim/tests/test_api.py +166 -81
  160. nautobot/dcim/tests/test_cablepaths.py +41 -35
  161. nautobot/dcim/tests/test_filters.py +67 -23
  162. nautobot/dcim/tests/test_forms.py +5 -205
  163. nautobot/dcim/tests/test_graphql.py +7 -2
  164. nautobot/dcim/tests/test_migrations.py +6 -11
  165. nautobot/dcim/tests/test_models.py +182 -110
  166. nautobot/dcim/tests/test_natural_ordering.py +11 -8
  167. nautobot/dcim/tests/test_signals.py +6 -3
  168. nautobot/dcim/tests/test_views.py +197 -175
  169. nautobot/dcim/urls.py +11 -16
  170. nautobot/dcim/views.py +7 -134
  171. nautobot/docs/additional-features/caching.md +6 -87
  172. nautobot/docs/additional-features/job-scheduling-and-approvals.md +3 -0
  173. nautobot/docs/additional-features/jobs.md +177 -195
  174. nautobot/docs/administration/nautobot-server.md +6 -21
  175. nautobot/docs/administration/replicating-nautobot.md +0 -10
  176. nautobot/docs/configuration/optional-settings.md +32 -41
  177. nautobot/docs/configuration/required-settings.md +11 -52
  178. nautobot/docs/development/application-registry.md +2 -13
  179. nautobot/docs/development/extending-models.md +15 -17
  180. nautobot/docs/development/generic-views.md +0 -2
  181. nautobot/docs/development/getting-started.md +55 -5
  182. nautobot/docs/development/navigation-menu.md +22 -93
  183. nautobot/docs/development/react-ui.md +105 -0
  184. nautobot/docs/development/role-internals.md +1 -3
  185. nautobot/docs/development/style-guide.md +6 -4
  186. nautobot/docs/index.md +3 -2
  187. nautobot/docs/installation/migrating-from-netbox.md +11 -42
  188. nautobot/docs/installation/nautobot.md +1 -1
  189. nautobot/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
  190. nautobot/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
  191. nautobot/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
  192. nautobot/docs/installation/tables/v2-code-location-changes.yaml +241 -0
  193. nautobot/docs/installation/tables/v2-code-removals.yaml +67 -0
  194. nautobot/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
  195. nautobot/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
  196. nautobot/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
  197. nautobot/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
  198. nautobot/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
  199. nautobot/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
  200. nautobot/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
  201. nautobot/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
  202. nautobot/docs/installation/upgrading-from-nautobot-v1.md +170 -747
  203. nautobot/docs/models/dcim/device.md +3 -0
  204. nautobot/docs/models/dcim/deviceredundancygroup.md +3 -3
  205. nautobot/docs/models/extras/computedfield.md +4 -4
  206. nautobot/docs/models/extras/gitrepository.md +3 -0
  207. nautobot/docs/models/extras/job.md +1 -0
  208. nautobot/docs/models/extras/jobbutton.md +18 -13
  209. nautobot/docs/models/extras/jobhook.md +7 -4
  210. nautobot/docs/models/extras/jobresult.md +6 -2
  211. nautobot/docs/models/extras/relationship.md +2 -2
  212. nautobot/docs/models/extras/status.md +6 -19
  213. nautobot/docs/models/ipam/ipaddress.md +3 -0
  214. nautobot/docs/models/virtualization/virtualmachine.md +3 -0
  215. nautobot/docs/plugins/development.md +83 -21
  216. nautobot/docs/release-notes/version-1.5.md +53 -0
  217. nautobot/docs/release-notes/version-2.0.md +180 -0
  218. nautobot/docs/requirements.txt +1 -0
  219. nautobot/docs/rest-api/overview.md +384 -215
  220. nautobot/docs/rest-api/ui-related-endpoints.md +9 -0
  221. nautobot/extras/admin.py +3 -5
  222. nautobot/extras/api/customfields.py +15 -39
  223. nautobot/extras/api/fields.py +0 -11
  224. nautobot/extras/api/mixins.py +45 -0
  225. nautobot/extras/api/relationships.py +63 -158
  226. nautobot/extras/api/serializers.py +165 -700
  227. nautobot/extras/api/urls.py +1 -1
  228. nautobot/extras/api/views.py +294 -280
  229. nautobot/extras/apps.py +4 -7
  230. nautobot/extras/choices.py +11 -9
  231. nautobot/extras/constants.py +9 -3
  232. nautobot/extras/datasources/__init__.py +2 -0
  233. nautobot/extras/datasources/git.py +135 -186
  234. nautobot/extras/datasources/registry.py +25 -35
  235. nautobot/extras/filters/__init__.py +20 -19
  236. nautobot/extras/filters/mixins.py +4 -4
  237. nautobot/extras/forms/forms.py +63 -127
  238. nautobot/extras/forms/mixins.py +23 -51
  239. nautobot/extras/health_checks.py +0 -33
  240. nautobot/extras/jobs.py +387 -565
  241. nautobot/extras/management/commands/runjob.py +24 -62
  242. nautobot/extras/managers.py +30 -7
  243. nautobot/extras/migrations/0058_jobresult_add_time_status_idxs.py +38 -0
  244. nautobot/extras/migrations/{0058_joblogentry_scheduledjob_webhook_data_migration.py → 0059_joblogentry_scheduledjob_webhook_data_migration.py} +1 -1
  245. nautobot/extras/migrations/{0059_alter_joblogentry_scheduledjob_webhook_fields.py → 0060_alter_joblogentry_scheduledjob_webhook_fields.py} +1 -1
  246. nautobot/extras/migrations/{0060_role_and_alter_status.py → 0061_role_and_alter_status.py} +1 -7
  247. nautobot/extras/migrations/{0061_collect_roles_from_related_apps_roles.py → 0062_collect_roles_from_related_apps_roles.py} +33 -32
  248. nautobot/extras/migrations/{0062_alter_role_options.py → 0063_alter_role_options.py} +1 -1
  249. nautobot/extras/migrations/{0063_alter_configcontext_and_add_new_role.py → 0064_alter_configcontext_and_add_new_role.py} +1 -1
  250. nautobot/extras/migrations/0065_configcontext_data_migrations.py +44 -0
  251. nautobot/extras/migrations/{0065_rename_configcontext_role.py → 0066_rename_configcontext_role.py} +1 -1
  252. nautobot/extras/migrations/{0066_jobresult__add_celery_fields.py → 0067_jobresult__add_celery_fields.py} +36 -2
  253. nautobot/extras/migrations/{0067_created_datetime.py → 0068_created_datetime.py} +1 -1
  254. nautobot/extras/migrations/{0068_remove_site_and_region_attributes_from_config_context.py → 0069_remove_site_and_region_attributes_from_config_context.py} +1 -1
  255. nautobot/extras/migrations/{0069_replace_related_names.py → 0070_replace_related_names.py} +1 -1
  256. nautobot/extras/migrations/{0070_rename_model_fields.py → 0071_rename_model_fields.py} +1 -1
  257. nautobot/extras/migrations/0072_job__unique_name_data_migration.py +86 -0
  258. nautobot/extras/migrations/{0072_job__unique_name.py → 0073_job__unique_name.py} +13 -9
  259. nautobot/extras/migrations/{0073_remove_gitrepository_fields.py → 0074_remove_gitrepository_fields.py} +1 -1
  260. nautobot/extras/migrations/{0074_rename_slug_to_key_for_custom_field.py → 0075_rename_slug_to_key_for_custom_field.py} +1 -1
  261. nautobot/extras/migrations/{0075_migrate_custom_field_data.py → 0076_migrate_custom_field_data.py} +1 -1
  262. nautobot/extras/migrations/{0076_remove_name_field_and_make_label_field_non_nullable.py → 0077_remove_name_field_and_make_label_field_non_nullable.py} +1 -1
  263. nautobot/extras/migrations/{0077_remove_slug.py → 0078_remove_slug.py} +1 -5
  264. nautobot/extras/migrations/0079_tagsfield.py +28 -0
  265. nautobot/extras/migrations/0080_rename_relationship_slug_to_key.py +17 -0
  266. nautobot/extras/migrations/0081_rename_relationship_name_to_label.py +29 -0
  267. nautobot/extras/migrations/0082_ensure_relationship_keys_are_unique.py +43 -0
  268. nautobot/extras/migrations/0083_rename_computed_field_slug_to_key.py +21 -0
  269. nautobot/extras/migrations/0084_taggeditem_cleanup.py +43 -0
  270. nautobot/extras/migrations/0085_taggeditem_uniqueness.py +22 -0
  271. nautobot/extras/migrations/0086_job__celery_task_fields__dryrun_support.py +81 -0
  272. nautobot/extras/migrations/0087_job__commit_default_data_migration.py +26 -0
  273. nautobot/extras/migrations/0088_joblogentry__log_level_default.py +17 -0
  274. nautobot/extras/migrations/0089_joblogentry__log_level_data_migration.py +34 -0
  275. nautobot/extras/migrations/0090_scheduledjob__data_migration.py +57 -0
  276. nautobot/extras/models/__init__.py +2 -3
  277. nautobot/extras/models/change_logging.py +0 -36
  278. nautobot/extras/models/customfields.py +39 -33
  279. nautobot/extras/models/datasources.py +48 -50
  280. nautobot/extras/models/groups.py +5 -6
  281. nautobot/extras/models/jobs.py +189 -321
  282. nautobot/extras/models/mixins.py +0 -71
  283. nautobot/extras/models/models.py +0 -19
  284. nautobot/extras/models/relationships.py +19 -13
  285. nautobot/extras/models/roles.py +0 -34
  286. nautobot/extras/models/secrets.py +2 -26
  287. nautobot/extras/models/statuses.py +6 -5
  288. nautobot/extras/models/tags.py +2 -17
  289. nautobot/extras/navigation.py +89 -307
  290. nautobot/extras/plugins/__init__.py +3 -120
  291. nautobot/extras/plugins/utils.py +0 -3
  292. nautobot/extras/plugins/validators.py +5 -4
  293. nautobot/extras/plugins/views.py +16 -3
  294. nautobot/extras/querysets.py +1 -7
  295. nautobot/extras/registry.py +3 -0
  296. nautobot/extras/signals.py +26 -60
  297. nautobot/extras/tables.py +34 -40
  298. nautobot/extras/tasks.py +0 -12
  299. nautobot/extras/templates/extras/configcontext.html +1 -1
  300. nautobot/extras/templates/extras/configcontextschema.html +16 -1
  301. nautobot/extras/templates/extras/customfield.html +0 -13
  302. nautobot/extras/templates/extras/gitrepository.html +3 -3
  303. nautobot/extras/templates/extras/inc/jobresult.html +10 -0
  304. nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
  305. nautobot/extras/templates/extras/job.html +35 -25
  306. nautobot/extras/templates/extras/job_approval_request.html +15 -30
  307. nautobot/extras/templates/extras/job_detail.html +13 -31
  308. nautobot/extras/templates/extras/job_edit.html +15 -17
  309. nautobot/extras/templates/extras/jobresult.html +24 -6
  310. nautobot/extras/templates/extras/scheduledjob.html +2 -2
  311. nautobot/extras/templates/extras/secret.html +28 -0
  312. nautobot/extras/templatetags/job_buttons.py +1 -0
  313. nautobot/extras/{tests/example_jobs → test_jobs}/api_test_job.py +13 -6
  314. nautobot/extras/test_jobs/atomic_transaction.py +53 -0
  315. nautobot/extras/test_jobs/dry_run.py +29 -0
  316. nautobot/extras/{tests/example_jobs/test_duplicate_name.py → test_jobs/duplicate_name.py} +4 -0
  317. nautobot/extras/test_jobs/duplicate_name2.py +9 -0
  318. nautobot/extras/test_jobs/fail.py +23 -0
  319. nautobot/extras/{tests/example_jobs/test_field_default.py → test_jobs/field_default.py} +4 -0
  320. nautobot/extras/{tests/example_jobs/test_field_order.py → test_jobs/field_order.py} +4 -0
  321. nautobot/extras/{tests/example_jobs/test_file_upload_fail.py → test_jobs/file_upload_fail.py} +11 -6
  322. nautobot/extras/test_jobs/file_upload_pass.py +25 -0
  323. nautobot/extras/test_jobs/has_sensitive_variables.py +25 -0
  324. nautobot/extras/test_jobs/ipaddress_vars.py +66 -0
  325. nautobot/extras/test_jobs/job_button_receiver.py +28 -0
  326. nautobot/extras/test_jobs/job_hook_receiver.py +29 -0
  327. nautobot/extras/test_jobs/job_variables.py +88 -0
  328. nautobot/extras/test_jobs/location_with_custom_field.py +45 -0
  329. nautobot/extras/test_jobs/log_redaction.py +20 -0
  330. nautobot/extras/test_jobs/log_skip_db_logging.py +17 -0
  331. nautobot/extras/test_jobs/modify_db.py +25 -0
  332. nautobot/extras/{tests/example_jobs/test_no_field_order.py → test_jobs/no_field_order.py} +4 -0
  333. nautobot/extras/test_jobs/object_var_optional.py +21 -0
  334. nautobot/extras/test_jobs/object_var_required.py +21 -0
  335. nautobot/extras/test_jobs/object_vars.py +26 -0
  336. nautobot/extras/test_jobs/pass.py +25 -0
  337. nautobot/extras/test_jobs/profiling.py +32 -0
  338. nautobot/extras/test_jobs/read_only_job.py +15 -0
  339. nautobot/extras/{tests/example_jobs/test_required_args.py → test_jobs/required_args.py} +4 -0
  340. nautobot/extras/{tests/example_jobs/test_soft_time_limit_greater_than_time_limit.py → test_jobs/soft_time_limit_greater_than_time_limit.py} +5 -1
  341. nautobot/extras/{tests/example_jobs/test_task_queues.py → test_jobs/task_queues.py} +5 -1
  342. nautobot/extras/tests/integration/test_computedfields.py +1 -1
  343. nautobot/extras/tests/integration/test_configcontextschema.py +5 -3
  344. nautobot/extras/tests/integration/test_customfields.py +4 -2
  345. nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
  346. nautobot/extras/tests/integration/test_jobs.py +25 -27
  347. nautobot/extras/tests/integration/test_notes.py +8 -4
  348. nautobot/extras/tests/integration/test_relationships.py +2 -2
  349. nautobot/extras/tests/test_api.py +649 -642
  350. nautobot/extras/tests/test_changelog.py +3 -3
  351. nautobot/extras/tests/test_context_managers.py +5 -3
  352. nautobot/extras/tests/test_customfields.py +92 -50
  353. nautobot/extras/tests/test_datasources.py +189 -112
  354. nautobot/extras/tests/test_dynamicgroups.py +7 -8
  355. nautobot/extras/tests/test_filters.py +137 -89
  356. nautobot/extras/tests/test_forms.py +73 -75
  357. nautobot/extras/tests/{test_scripts.py → test_job_variables.py} +43 -49
  358. nautobot/extras/tests/test_jobs.py +262 -263
  359. nautobot/extras/tests/test_migrations.py +4 -3
  360. nautobot/extras/tests/test_models.py +116 -161
  361. nautobot/extras/tests/test_plugins.py +38 -60
  362. nautobot/extras/tests/test_relationships.py +167 -120
  363. nautobot/extras/tests/test_tags.py +6 -11
  364. nautobot/extras/tests/test_utils.py +31 -1
  365. nautobot/extras/tests/test_views.py +201 -145
  366. nautobot/extras/tests/test_webhooks.py +6 -2
  367. nautobot/extras/urls.py +42 -42
  368. nautobot/extras/utils.py +137 -163
  369. nautobot/extras/views.py +78 -152
  370. nautobot/ipam/api/fields.py +17 -0
  371. nautobot/ipam/api/serializers.py +58 -164
  372. nautobot/ipam/api/urls.py +1 -1
  373. nautobot/ipam/api/views.py +3 -2
  374. nautobot/ipam/apps.py +1 -2
  375. nautobot/ipam/filters.py +1 -10
  376. nautobot/ipam/forms.py +4 -177
  377. nautobot/ipam/lookups.py +1 -0
  378. nautobot/ipam/management/commands/__init__.py +0 -0
  379. nautobot/ipam/management/commands/fix_prefix_broadcast.py +17 -0
  380. nautobot/ipam/migrations/0010_alter_ipam_role_add_new_role.py +1 -1
  381. nautobot/ipam/migrations/0011_migrate_ipam_role_data.py +32 -38
  382. nautobot/ipam/migrations/0020_related_name_changes.py +1 -1
  383. nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py +2 -2
  384. nautobot/ipam/migrations/0028_tagsfield.py +44 -0
  385. nautobot/ipam/migrations/0029_ip_address_to_interface_uniqueness_constraints.py +18 -0
  386. nautobot/ipam/migrations/{0028_ipam__namespaces.py → 0030_ipam__namespaces.py} +77 -28
  387. nautobot/ipam/migrations/0031_ipam__prefix__add_parent.py +58 -0
  388. nautobot/ipam/migrations/0032_ipam__namespaces_finish.py +63 -0
  389. nautobot/ipam/migrations/0033_fixup_null_statuses.py +26 -0
  390. nautobot/ipam/migrations/0034_status_nonnullable.py +36 -0
  391. nautobot/ipam/models.py +100 -236
  392. nautobot/ipam/navigation.py +36 -181
  393. nautobot/ipam/querysets.py +20 -25
  394. nautobot/ipam/signals.py +49 -6
  395. nautobot/ipam/tables.py +10 -3
  396. nautobot/ipam/templates/ipam/namespace_ipaddresses.html +11 -0
  397. nautobot/ipam/templates/ipam/namespace_prefixes.html +11 -0
  398. nautobot/ipam/templates/ipam/namespace_retrieve.html +17 -4
  399. nautobot/ipam/templates/ipam/namespace_vrfs.html +11 -0
  400. nautobot/ipam/templates/ipam/prefix.html +1 -1
  401. nautobot/ipam/templates/ipam/vlangroup.html +0 -13
  402. nautobot/ipam/templates/ipam/vrf_edit.html +6 -0
  403. nautobot/ipam/tests/integration/test_prefixes.py +3 -26
  404. nautobot/ipam/tests/test_api.py +22 -19
  405. nautobot/ipam/tests/test_filters.py +59 -23
  406. nautobot/ipam/tests/test_migrations.py +6 -10
  407. nautobot/ipam/tests/test_models.py +323 -198
  408. nautobot/ipam/tests/test_ordering.py +2 -2
  409. nautobot/ipam/tests/test_querysets.py +44 -24
  410. nautobot/ipam/tests/test_views.py +73 -26
  411. nautobot/ipam/urls.py +16 -0
  412. nautobot/ipam/{utils.py → utils/__init__.py} +2 -2
  413. nautobot/ipam/utils/migrations.py +713 -0
  414. nautobot/ipam/views.py +137 -20
  415. nautobot/project-static/docs/404.html +1178 -10
  416. nautobot/project-static/docs/additional-features/caching.html +1224 -159
  417. nautobot/project-static/docs/additional-features/change-logging.html +1180 -12
  418. nautobot/project-static/docs/additional-features/config-contexts.html +1180 -12
  419. nautobot/project-static/docs/additional-features/graphql.html +1179 -11
  420. nautobot/project-static/docs/additional-features/healthcheck.html +1180 -12
  421. nautobot/project-static/docs/additional-features/job-scheduling-and-approvals.html +1184 -12
  422. nautobot/project-static/docs/additional-features/jobs.html +1514 -328
  423. nautobot/project-static/docs/additional-features/napalm.html +1180 -12
  424. nautobot/project-static/docs/additional-features/prometheus-metrics.html +1180 -12
  425. nautobot/project-static/docs/additional-features/template-filters.html +1180 -12
  426. nautobot/project-static/docs/administration/celery-queues.html +1178 -10
  427. nautobot/project-static/docs/administration/nautobot-server.html +1451 -304
  428. nautobot/project-static/docs/administration/nautobot-shell.html +1178 -10
  429. nautobot/project-static/docs/administration/permissions.html +1178 -10
  430. nautobot/project-static/docs/administration/replicating-nautobot.html +1262 -113
  431. nautobot/project-static/docs/apps/index.html +1178 -10
  432. nautobot/project-static/docs/apps/nautobot-apps.html +1178 -10
  433. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1580 -426
  434. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1178 -10
  435. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3481 -1838
  436. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1178 -10
  437. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1178 -10
  438. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1185 -11
  439. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1719 -551
  440. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2062 -930
  441. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +1946 -659
  442. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1180 -12
  443. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1189 -21
  444. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +9283 -6218
  445. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2734 -2122
  446. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1178 -10
  447. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2337 -1300
  448. nautobot/project-static/docs/configuration/authentication/ldap.html +1178 -10
  449. nautobot/project-static/docs/configuration/authentication/remote.html +1178 -10
  450. nautobot/project-static/docs/configuration/authentication/sso.html +1178 -10
  451. nautobot/project-static/docs/configuration/index.html +1178 -10
  452. nautobot/project-static/docs/configuration/optional-settings.html +1311 -160
  453. nautobot/project-static/docs/configuration/required-settings.html +1312 -211
  454. nautobot/project-static/docs/core-functionality/circuits.html +1178 -10
  455. nautobot/project-static/docs/core-functionality/device-types.html +1178 -10
  456. nautobot/project-static/docs/core-functionality/devices.html +1182 -10
  457. nautobot/project-static/docs/core-functionality/ipam.html +1182 -10
  458. nautobot/project-static/docs/core-functionality/power.html +1178 -10
  459. nautobot/project-static/docs/core-functionality/secrets.html +1178 -10
  460. nautobot/project-static/docs/core-functionality/services.html +1178 -10
  461. nautobot/project-static/docs/core-functionality/sites-and-racks.html +1178 -10
  462. nautobot/project-static/docs/core-functionality/tenancy.html +1178 -10
  463. nautobot/project-static/docs/core-functionality/virtualization.html +1182 -10
  464. nautobot/project-static/docs/core-functionality/vlans.html +1179 -11
  465. nautobot/project-static/docs/development/application-registry.html +1190 -42
  466. nautobot/project-static/docs/development/best-practices.html +1178 -10
  467. nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1178 -10
  468. nautobot/project-static/docs/development/extending-models.html +1238 -83
  469. nautobot/project-static/docs/development/generic-views.html +1180 -14
  470. nautobot/project-static/docs/development/getting-started.html +1365 -90
  471. nautobot/project-static/docs/development/homepage.html +1178 -10
  472. nautobot/project-static/docs/development/index.html +1178 -10
  473. nautobot/project-static/docs/development/model-features.html +1178 -10
  474. nautobot/project-static/docs/development/natural-keys.html +1178 -10
  475. nautobot/project-static/docs/development/navigation-menu.html +1215 -125
  476. nautobot/project-static/docs/development/react-ui.html +4199 -0
  477. nautobot/project-static/docs/development/release-checklist.html +1178 -10
  478. nautobot/project-static/docs/development/role-internals.html +1179 -12
  479. nautobot/project-static/docs/development/style-guide.html +1188 -19
  480. nautobot/project-static/docs/development/templates.html +1178 -10
  481. nautobot/project-static/docs/development/testing.html +1178 -10
  482. nautobot/project-static/docs/development/user-preferences.html +1178 -10
  483. nautobot/project-static/docs/docker/index.html +1178 -10
  484. nautobot/project-static/docs/index.html +1183 -12
  485. nautobot/project-static/docs/installation/centos.html +1178 -10
  486. nautobot/project-static/docs/installation/external-authentication.html +1178 -10
  487. nautobot/project-static/docs/installation/http-server.html +1178 -10
  488. nautobot/project-static/docs/installation/index.html +1178 -10
  489. nautobot/project-static/docs/installation/migrating-from-netbox.html +1305 -189
  490. nautobot/project-static/docs/installation/migrating-from-postgresql.html +1178 -10
  491. nautobot/project-static/docs/installation/nautobot.html +1179 -11
  492. nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1178 -10
  493. nautobot/project-static/docs/installation/selinux-troubleshooting.html +1178 -10
  494. nautobot/project-static/docs/installation/services.html +1178 -10
  495. nautobot/project-static/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
  496. nautobot/project-static/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
  497. nautobot/project-static/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
  498. nautobot/project-static/docs/installation/tables/v2-code-location-changes.yaml +241 -0
  499. nautobot/project-static/docs/installation/tables/v2-code-removals.yaml +67 -0
  500. nautobot/project-static/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
  501. nautobot/project-static/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
  502. nautobot/project-static/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
  503. nautobot/project-static/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
  504. nautobot/project-static/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
  505. nautobot/project-static/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
  506. nautobot/project-static/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
  507. nautobot/project-static/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
  508. nautobot/project-static/docs/installation/ubuntu.html +1178 -10
  509. nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +3823 -2152
  510. nautobot/project-static/docs/installation/upgrading.html +1178 -10
  511. nautobot/project-static/docs/models/circuits/circuit.html +1293 -103
  512. nautobot/project-static/docs/models/circuits/circuittermination.html +1293 -103
  513. nautobot/project-static/docs/models/circuits/circuittype.html +1293 -103
  514. nautobot/project-static/docs/models/circuits/provider.html +1293 -103
  515. nautobot/project-static/docs/models/circuits/providernetwork.html +1293 -103
  516. nautobot/project-static/docs/models/dcim/cable.html +1324 -103
  517. nautobot/project-static/docs/models/dcim/consoleport.html +1293 -103
  518. nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1293 -103
  519. nautobot/project-static/docs/models/dcim/consoleserverport.html +1293 -103
  520. nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1293 -103
  521. nautobot/project-static/docs/models/dcim/device.html +1326 -132
  522. nautobot/project-static/docs/models/dcim/devicebay.html +1293 -103
  523. nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1293 -103
  524. nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1379 -97
  525. nautobot/project-static/docs/models/dcim/devicetype.html +1293 -103
  526. nautobot/project-static/docs/models/dcim/frontport.html +1293 -103
  527. nautobot/project-static/docs/models/dcim/frontporttemplate.html +1293 -103
  528. nautobot/project-static/docs/models/dcim/interface.html +1293 -103
  529. nautobot/project-static/docs/models/dcim/interfacetemplate.html +1293 -103
  530. nautobot/project-static/docs/models/dcim/inventoryitem.html +1293 -103
  531. nautobot/project-static/docs/models/dcim/location.html +1293 -103
  532. nautobot/project-static/docs/models/dcim/locationtype.html +1293 -103
  533. nautobot/project-static/docs/models/dcim/manufacturer.html +1292 -102
  534. nautobot/project-static/docs/models/dcim/platform.html +1272 -82
  535. nautobot/project-static/docs/models/dcim/powerfeed.html +1270 -80
  536. nautobot/project-static/docs/models/dcim/poweroutlet.html +1272 -82
  537. nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1272 -82
  538. nautobot/project-static/docs/models/dcim/powerpanel.html +1270 -80
  539. nautobot/project-static/docs/models/dcim/powerport.html +1272 -82
  540. nautobot/project-static/docs/models/dcim/powerporttemplate.html +1272 -82
  541. nautobot/project-static/docs/models/dcim/rack.html +1272 -82
  542. nautobot/project-static/docs/models/dcim/rackgroup.html +1272 -82
  543. nautobot/project-static/docs/models/dcim/rackreservation.html +1272 -82
  544. nautobot/project-static/docs/models/dcim/rearport.html +1286 -96
  545. nautobot/project-static/docs/models/dcim/rearporttemplate.html +1286 -96
  546. nautobot/project-static/docs/models/dcim/region.html +1178 -10
  547. nautobot/project-static/docs/models/dcim/site.html +1178 -10
  548. nautobot/project-static/docs/models/dcim/virtualchassis.html +1284 -94
  549. nautobot/project-static/docs/models/extras/computedfield.html +1184 -16
  550. nautobot/project-static/docs/models/extras/configcontext.html +1314 -86
  551. nautobot/project-static/docs/models/extras/configcontextschema.html +1276 -86
  552. nautobot/project-static/docs/models/extras/customfield.html +1180 -12
  553. nautobot/project-static/docs/models/extras/customlink.html +1180 -12
  554. nautobot/project-static/docs/models/extras/dynamicgroup.html +1180 -12
  555. nautobot/project-static/docs/models/extras/exporttemplate.html +1180 -12
  556. nautobot/project-static/docs/models/extras/gitrepository.html +1184 -12
  557. nautobot/project-static/docs/models/extras/graphqlquery.html +1321 -86
  558. nautobot/project-static/docs/models/extras/imageattachment.html +1276 -86
  559. nautobot/project-static/docs/models/extras/job.html +1277 -86
  560. nautobot/project-static/docs/models/extras/jobbutton.html +1201 -29
  561. nautobot/project-static/docs/models/extras/jobhook.html +1188 -16
  562. nautobot/project-static/docs/models/extras/joblogentry.html +1274 -84
  563. nautobot/project-static/docs/models/extras/jobresult.html +1364 -169
  564. nautobot/project-static/docs/models/extras/note.html +1180 -12
  565. nautobot/project-static/docs/models/extras/relationship.html +1182 -14
  566. nautobot/project-static/docs/models/extras/role.html +1320 -86
  567. nautobot/project-static/docs/models/extras/secret.html +1314 -86
  568. nautobot/project-static/docs/models/extras/secretsgroup.html +1276 -86
  569. nautobot/project-static/docs/models/extras/status.html +1188 -59
  570. nautobot/project-static/docs/models/extras/tag.html +1180 -12
  571. nautobot/project-static/docs/models/extras/webhook.html +1180 -12
  572. nautobot/project-static/docs/models/ipam/ipaddress.html +1327 -102
  573. nautobot/project-static/docs/models/ipam/prefix.html +1276 -86
  574. nautobot/project-static/docs/models/ipam/rir.html +1276 -86
  575. nautobot/project-static/docs/models/ipam/routetarget.html +1276 -86
  576. nautobot/project-static/docs/models/ipam/service.html +1276 -86
  577. nautobot/project-static/docs/models/ipam/vlan.html +1276 -86
  578. nautobot/project-static/docs/models/ipam/vlangroup.html +1276 -86
  579. nautobot/project-static/docs/models/ipam/vrf.html +1276 -86
  580. nautobot/project-static/docs/models/tenancy/tenant.html +1276 -86
  581. nautobot/project-static/docs/models/tenancy/tenantgroup.html +1276 -86
  582. nautobot/project-static/docs/models/users/objectpermission.html +1314 -86
  583. nautobot/project-static/docs/models/users/token.html +1276 -86
  584. nautobot/project-static/docs/models/virtualization/cluster.html +1276 -86
  585. nautobot/project-static/docs/models/virtualization/clustergroup.html +1276 -86
  586. nautobot/project-static/docs/models/virtualization/clustertype.html +1276 -86
  587. nautobot/project-static/docs/models/virtualization/virtualmachine.html +1321 -127
  588. nautobot/project-static/docs/models/virtualization/vminterface.html +1276 -86
  589. nautobot/project-static/docs/objects.inv +0 -0
  590. nautobot/project-static/docs/plugins/development.html +1726 -495
  591. nautobot/project-static/docs/plugins/index.html +1178 -10
  592. nautobot/project-static/docs/plugins/porting-from-netbox.html +1178 -10
  593. nautobot/project-static/docs/release-notes/index.html +1178 -10
  594. nautobot/project-static/docs/release-notes/version-1.0.html +1178 -10
  595. nautobot/project-static/docs/release-notes/version-1.1.html +1178 -10
  596. nautobot/project-static/docs/release-notes/version-1.2.html +1178 -10
  597. nautobot/project-static/docs/release-notes/version-1.3.html +1178 -10
  598. nautobot/project-static/docs/release-notes/version-1.4.html +1178 -10
  599. nautobot/project-static/docs/release-notes/version-1.5.html +1608 -225
  600. nautobot/project-static/docs/release-notes/version-2.0.html +1547 -47
  601. nautobot/project-static/docs/requirements.txt +1 -0
  602. nautobot/project-static/docs/rest-api/authentication.html +1179 -11
  603. nautobot/project-static/docs/rest-api/filtering.html +1178 -10
  604. nautobot/project-static/docs/rest-api/overview.html +1841 -446
  605. nautobot/project-static/docs/rest-api/ui-related-endpoints.html +4057 -0
  606. nautobot/project-static/docs/search/search_index.json +1 -1
  607. nautobot/project-static/docs/sitemap.xml +197 -187
  608. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  609. nautobot/project-static/docs/user-guides/custom-fields.html +1178 -10
  610. nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1178 -10
  611. nautobot/project-static/docs/user-guides/getting-started/index.html +1178 -10
  612. nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1178 -10
  613. nautobot/project-static/docs/user-guides/getting-started/ipam.html +1178 -10
  614. nautobot/project-static/docs/user-guides/getting-started/platforms.html +1178 -10
  615. nautobot/project-static/docs/user-guides/getting-started/regions.html +1178 -10
  616. nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1178 -10
  617. nautobot/project-static/docs/user-guides/getting-started/tenants.html +1178 -10
  618. nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1178 -10
  619. nautobot/project-static/docs/user-guides/git-data-source.html +1178 -10
  620. nautobot/project-static/docs/user-guides/graphql.html +1178 -10
  621. nautobot/project-static/docs/user-guides/relationships.html +1178 -10
  622. nautobot/project-static/docs/user-guides/s3-django-storage.html +1178 -10
  623. nautobot/project-static/js/forms.js +16 -9
  624. nautobot/project-static/js/theme.js +5 -0
  625. nautobot/tenancy/api/serializers.py +4 -32
  626. nautobot/tenancy/api/urls.py +1 -1
  627. nautobot/tenancy/forms.py +0 -28
  628. nautobot/tenancy/migrations/0008_tagsfield.py +19 -0
  629. nautobot/tenancy/models.py +0 -25
  630. nautobot/tenancy/navigation.py +6 -39
  631. nautobot/tenancy/templates/tenancy/tenant.html +12 -12
  632. nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
  633. nautobot/tenancy/tests/test_api.py +1 -3
  634. nautobot/tenancy/tests/test_filters.py +10 -5
  635. nautobot/tenancy/views.py +0 -2
  636. nautobot/ui/.eslintignore +6 -0
  637. nautobot/ui/.gitignore +10 -0
  638. nautobot/ui/.prettierignore +9 -0
  639. nautobot/ui/.prettierrc +4 -0
  640. nautobot/ui/README.md +33 -0
  641. nautobot/ui/app_imports.js.j2 +7 -0
  642. nautobot/ui/craco.config.js +46 -0
  643. nautobot/ui/jsconfig-base.json +11 -0
  644. nautobot/ui/jsconfig.json +5 -0
  645. nautobot/ui/lib/nautobot-craco-alias-plugin.js +40 -0
  646. nautobot/ui/package-lock.json +21451 -0
  647. nautobot/ui/package.json +70 -0
  648. nautobot/ui/public/index.html +47 -0
  649. nautobot/ui/public/logo192.png +0 -0
  650. nautobot/ui/public/logo512.png +0 -0
  651. nautobot/ui/public/manifest.json +25 -0
  652. nautobot/ui/public/nautobot_logo.svg +131 -0
  653. nautobot/ui/public/robots.txt +3 -0
  654. nautobot/ui/src/App.js +71 -0
  655. nautobot/ui/src/components/AppFullWidthComponents.js +8 -0
  656. nautobot/ui/src/components/AppTab.js +40 -0
  657. nautobot/ui/src/components/Apps.js +60 -0
  658. nautobot/ui/src/components/HomeChangelogPanel.js +98 -0
  659. nautobot/ui/src/components/HomePanel.js +58 -0
  660. nautobot/ui/src/components/JobHistoryTable.js +78 -0
  661. nautobot/ui/src/components/Layout.js +53 -0
  662. nautobot/ui/src/components/LoadingWidget.js +25 -0
  663. nautobot/ui/src/components/Navbar.js +116 -0
  664. nautobot/ui/src/components/NotificationPopover.js +27 -0
  665. nautobot/ui/src/components/ObjectListTable.js +209 -0
  666. nautobot/ui/src/components/ReferenceDataTag.js +35 -0
  667. nautobot/ui/src/components/RouterButton.js +10 -0
  668. nautobot/ui/src/components/RouterLink.js +10 -0
  669. nautobot/ui/src/components/SidebarNav.js +147 -0
  670. nautobot/ui/src/components/Table.js +48 -0
  671. nautobot/ui/src/components/TableItem.js +71 -0
  672. nautobot/ui/src/components/__tests__/AppFullWidthComponents.test.js +16 -0
  673. nautobot/ui/src/components/__tests__/AppTab.test.js +21 -0
  674. nautobot/ui/src/components/__tests__/Apps.test.js +14 -0
  675. nautobot/ui/src/components/__tests__/Layout.test.js +33 -0
  676. nautobot/ui/src/components/__tests__/Table.test.js +36 -0
  677. nautobot/ui/src/components/__tests__/TableItem.test.js +37 -0
  678. nautobot/ui/src/components/__tests__/paginator.test.js +43 -0
  679. nautobot/ui/src/components/__tests__/paginator_form.test.js +13 -0
  680. nautobot/ui/src/components/pagination.js +93 -0
  681. nautobot/ui/src/components/paginator.js +79 -0
  682. nautobot/ui/src/components/paginator_form.js +43 -0
  683. nautobot/ui/src/components/usePagination.js +57 -0
  684. nautobot/ui/src/constants/apiPath.js +10 -0
  685. nautobot/ui/src/constants/icons.js +15 -0
  686. nautobot/ui/src/constants/size.js +15 -0
  687. nautobot/ui/src/index.js +65 -0
  688. nautobot/ui/src/reportWebVitals.js +15 -0
  689. nautobot/ui/src/router.js +77 -0
  690. nautobot/ui/src/utils/api.js +131 -0
  691. nautobot/ui/src/utils/app-import.js +15 -0
  692. nautobot/ui/src/utils/color.js +15 -0
  693. nautobot/ui/src/utils/date.js +14 -0
  694. nautobot/ui/src/utils/index.js +15 -0
  695. nautobot/ui/src/utils/navigation.js +32 -0
  696. nautobot/ui/src/utils/session.js +64 -0
  697. nautobot/ui/src/utils/store.js +242 -0
  698. nautobot/ui/src/utils/string.js +6 -0
  699. nautobot/ui/src/utils/url.js +4 -0
  700. nautobot/ui/src/views/Home.js +138 -0
  701. nautobot/ui/src/views/InstalledApps.js +80 -0
  702. nautobot/ui/src/views/Login.js +48 -0
  703. nautobot/ui/src/views/Logout.js +20 -0
  704. nautobot/ui/src/views/__tests__/BSCreateViewTemplate.test.js +11 -0
  705. nautobot/ui/src/views/__tests__/BSListViewTemplate.test.js +107 -0
  706. nautobot/ui/src/views/__tests__/Login.test.js +15 -0
  707. nautobot/ui/src/views/generic/GenericView.js +142 -0
  708. nautobot/ui/src/views/generic/ObjectCreate.js +96 -0
  709. nautobot/ui/src/views/generic/ObjectList.js +127 -0
  710. nautobot/ui/src/views/generic/ObjectRetrieve.js +551 -0
  711. nautobot/users/admin.py +1 -1
  712. nautobot/users/api/serializers.py +51 -61
  713. nautobot/users/api/urls.py +1 -1
  714. nautobot/users/api/views.py +53 -2
  715. nautobot/users/tests/test_api.py +110 -25
  716. nautobot/virtualization/api/serializers.py +18 -130
  717. nautobot/virtualization/api/urls.py +1 -1
  718. nautobot/virtualization/api/views.py +1 -22
  719. nautobot/virtualization/forms.py +13 -99
  720. nautobot/virtualization/migrations/0012_alter_virtualmachine_role_add_new_role.py +1 -1
  721. nautobot/virtualization/migrations/0013_migrate_virtualmachine_role_data.py +18 -11
  722. nautobot/virtualization/migrations/0015_rename_foreignkey_fields.py +1 -1
  723. nautobot/virtualization/migrations/0018_related_name_changes.py +1 -1
  724. nautobot/virtualization/migrations/0021_tagsfield_and_vminterface_to_primarymodel.py +39 -0
  725. nautobot/virtualization/migrations/0022_vminterface_timestamps_data_migration.py +17 -0
  726. nautobot/virtualization/migrations/{0021_ipam__namespaces.py → 0023_ipam__namespaces.py} +2 -2
  727. nautobot/virtualization/migrations/0024_fixup_null_statuses.py +25 -0
  728. nautobot/virtualization/migrations/0025_status_nonnullable.py +29 -0
  729. nautobot/virtualization/models.py +31 -123
  730. nautobot/virtualization/navigation.py +18 -99
  731. nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -1
  732. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +6 -0
  733. nautobot/virtualization/tests/test_api.py +25 -26
  734. nautobot/virtualization/tests/test_filters.py +41 -15
  735. nautobot/virtualization/tests/test_models.py +31 -7
  736. nautobot/virtualization/tests/test_views.py +42 -25
  737. nautobot/virtualization/views.py +7 -6
  738. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/METADATA +3 -7
  739. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/RECORD +744 -602
  740. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/WHEEL +1 -1
  741. nautobot/circuits/api/nested_serializers.py +0 -69
  742. nautobot/core/templates/plugin_template/navigation.py-tpl +0 -22
  743. nautobot/dcim/api/nested_serializers.py +0 -356
  744. nautobot/dcim/templates/dcim/device_import.html +0 -5
  745. nautobot/dcim/templates/dcim/device_import_child.html +0 -5
  746. nautobot/dcim/templates/dcim/inc/device_import_header.html +0 -4
  747. nautobot/extras/api/nested_serializers.py +0 -353
  748. nautobot/extras/migrations/0064_configcontext_data_migrations.py +0 -41
  749. nautobot/extras/migrations/0071_job__unique_name_data_migration.py +0 -46
  750. nautobot/extras/reports.py +0 -60
  751. nautobot/extras/scripts.py +0 -72
  752. nautobot/extras/tests/example_jobs/script_variables.py +0 -67
  753. nautobot/extras/tests/example_jobs/test_duplicate_name2.py +0 -5
  754. nautobot/extras/tests/example_jobs/test_fail.py +0 -16
  755. nautobot/extras/tests/example_jobs/test_file_upload_pass.py +0 -20
  756. nautobot/extras/tests/example_jobs/test_ipaddress_vars.py +0 -52
  757. nautobot/extras/tests/example_jobs/test_job_button_receiver.py +0 -21
  758. nautobot/extras/tests/example_jobs/test_job_hook_receiver.py +0 -20
  759. nautobot/extras/tests/example_jobs/test_location_with_custom_field.py +0 -35
  760. nautobot/extras/tests/example_jobs/test_log_redaction.py +0 -14
  761. nautobot/extras/tests/example_jobs/test_modify_db.py +0 -18
  762. nautobot/extras/tests/example_jobs/test_object_var_optional.py +0 -14
  763. nautobot/extras/tests/example_jobs/test_object_var_required.py +0 -14
  764. nautobot/extras/tests/example_jobs/test_object_vars.py +0 -29
  765. nautobot/extras/tests/example_jobs/test_pass.py +0 -19
  766. nautobot/extras/tests/example_jobs/test_read_only_fail.py +0 -24
  767. nautobot/extras/tests/example_jobs/test_read_only_no_commit_field.py +0 -10
  768. nautobot/extras/tests/example_jobs/test_read_only_pass.py +0 -22
  769. nautobot/ipam/api/nested_serializers.py +0 -159
  770. nautobot/ipam/migrations/0029_ipam__prefix__add_parent.py +0 -31
  771. nautobot/ipam/migrations/0030_ipam__prefix__data_migration.py +0 -13
  772. nautobot/ipam/migrations/0031_ipam__ipaddress__add_parent.py +0 -41
  773. nautobot/ipam/migrations/0032_ipam__ipaddress__data_migration.py +0 -11
  774. nautobot/tenancy/api/nested_serializers.py +0 -31
  775. nautobot/users/api/nested_serializers.py +0 -67
  776. nautobot/virtualization/api/nested_serializers.py +0 -65
  777. /nautobot/extras/{tests/example_jobs → test_jobs}/__init__.py +0 -0
  778. /nautobot/{dcim/models/sites.py → ipam/management/__init__.py} +0 -0
  779. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/LICENSE.txt +0 -0
  780. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/entry_points.txt +0 -0
@@ -67,7 +67,7 @@
67
67
  {% if object.roles.all %}
68
68
  <ul>
69
69
  {% for role in object.roles.all %}
70
- <li><a href="{% url 'dcim:device_list' %}?role={{ role.slug }}">{{ role }}</a></li>
70
+ <li><a href="{% url 'dcim:device_list' %}?role={{ role.name }}">{{ role }}</a></li>
71
71
  {% endfor %}
72
72
  </ul>
73
73
  {% else %}
@@ -1,9 +1,24 @@
1
1
  {% extends 'generic/object_detail.html' %}
2
+ {% load buttons %}
3
+ {% load plugins %}
2
4
  {% load helpers %}
3
5
 
6
+ {% block buttons %}
7
+ {% plugin_buttons object %}
8
+ {% if perms.extras.add_configcontextschema %}
9
+ {% clone_button object %}
10
+ {% endif %}
11
+ {% if perms.extras.change_configcontextschema %}
12
+ {% edit_button object key="pk" %}
13
+ {% endif %}
14
+ {% if perms.extras.delete_configcontextschema %}
15
+ {% delete_button object key="pk" %}
16
+ {% endif %}
17
+ {% endblock buttons %}
18
+
4
19
  {% block extra_nav_tabs %}
5
20
  <li role="presentation"{% if active_tab == 'validation' %} class="active"{% endif %}>
6
- <a href="{% url 'extras:configcontextschema_object_validation' slug=object.slug %}">Validation</a>
21
+ <a href="{% url 'extras:configcontextschema_object_validation' pk=object.pk %}">Validation</a>
7
22
  </li>
8
23
  {% endblock extra_nav_tabs %}
9
24
 
@@ -2,19 +2,6 @@
2
2
  {% load buttons %}
3
3
  {% load helpers %}
4
4
 
5
-
6
- {% block buttons %}
7
- {% if object.clone_fields and perms.extras.add_customfield %}
8
- {% clone_button object %}
9
- {% endif %}
10
- {% if perms.extras.change_customfield %}
11
- {% edit_button object key="pk" %}
12
- {% endif %}
13
- {% if perms.extras.delete_customfield %}
14
- {% delete_button object key="pk" %}
15
- {% endif %}
16
- {% endblock buttons %}
17
-
18
5
  {% block content_left_page %}
19
6
  <div class="panel panel-default">
20
7
  <div class="panel-heading">
@@ -4,14 +4,14 @@
4
4
  {% block extra_buttons %}
5
5
  {% if perms.extras.change_gitrepository %}
6
6
  <form class="form-inline" style="display: inline-block"
7
- method="post" action="{% url 'extras:gitrepository_dryrun' slug=object.slug %}">
7
+ method="post" action="{% url 'extras:gitrepository_dryrun' pk=object.pk %}">
8
8
  {% csrf_token %}
9
9
  <button type="submit" class="btn btn-info">
10
10
  <i class="mdi mdi-book-refresh" aria-hidden="true"></i> Dry-Run
11
11
  </button>
12
12
  </form>
13
13
  <form class="form-inline" style="display: inline-block"
14
- method="post" action="{% url 'extras:gitrepository_sync' slug=object.slug %}">
14
+ method="post" action="{% url 'extras:gitrepository_sync' pk=object.pk %}">
15
15
  {% csrf_token %}
16
16
  <button type="submit" class="btn btn-primary">
17
17
  <i class="mdi mdi-source-branch-sync" aria-hidden="true"></i> Sync
@@ -22,7 +22,7 @@
22
22
 
23
23
  {% block extra_nav_tabs %}
24
24
  <li role="presentation"{% if active_tab == 'result' %} class="active"{% endif %}>
25
- <a href="{% url 'extras:gitrepository_result' slug=object.slug %}">Synchronization Status</a>
25
+ <a href="{% url 'extras:gitrepository_result' pk=object.pk %}">Synchronization Status</a>
26
26
  </li>
27
27
  {% endblock extra_nav_tabs %}
28
28
 
@@ -40,6 +40,16 @@
40
40
  {% endif %}
41
41
  </td>
42
42
  </tr>
43
+ <tr>
44
+ <td>Return Value</td>
45
+ <td id="pending-result-loader">
46
+ {% if result.date_done %}
47
+ {{ result.result | placeholder }}
48
+ {% else %}
49
+ <img src="{% static 'img/ajax-loader.gif' %}">
50
+ {% endif %}
51
+ </td>
52
+ </tr>
43
53
  </table>
44
54
  </div>
45
55
 
@@ -2,7 +2,7 @@
2
2
  {% for result in job_results %}
3
3
  <div class="list-group-item">
4
4
  <a href="{% url 'extras:jobresult' pk=result.pk %}">
5
- {{ result.obj_type.name }} - {{ result.related_name }}
5
+ {{ result.job_model.name }}
6
6
  </a>
7
7
  <span class="pull-right" title="{{ result.date_created }}">{% include 'extras/inc/job_label.html' %}</span>
8
8
  <br>
@@ -62,30 +62,22 @@
62
62
  </div>
63
63
  {% endif %}
64
64
  {% csrf_token %}
65
- {% if job_form.requires_input %}
66
- <div class="panel panel-default">
67
- <div class="panel-heading">
68
- <strong>Job Data</strong>
69
- </div>
70
- <div class="panel-body">
71
- {% render_form job_form %}
72
- </div>
73
- {% if job_model.has_sensitive_variables %}
74
- <div class="panel-footer">
75
- <span class="help-block">
76
- <i class="mdi mdi-information-outline"></i>
77
- This job may have sensitive variables and can only be executed immediately. This can be changed in the Job edit view to set `has_sensitive_variables` to `False` if appropriate.
78
- </span>
79
- </div>
80
- {% endif %}
65
+ <div class="panel panel-default">
66
+ <div class="panel-heading">
67
+ <strong>Job Data</strong>
81
68
  </div>
82
- {% else %}
83
- <div class="alert alert-info">
84
- <i class="mdi mdi-information"></i>
85
- This job does not require any input to run.
69
+ <div class="panel-body">
70
+ {% render_form job_form %}
86
71
  </div>
87
- {% render_form job_form %}
88
- {% endif %}
72
+ {% if job_model.has_sensitive_variables %}
73
+ <div class="panel-footer">
74
+ <span class="help-block">
75
+ <i class="mdi mdi-information-outline"></i>
76
+ This job may have sensitive variables and can only be executed immediately. This can be changed in the Job edit view to set `has_sensitive_variables` to `False` if appropriate.
77
+ </span>
78
+ </div>
79
+ {% endif %}
80
+ </div>
89
81
  <div class="panel panel-default job_execution">
90
82
  <div class="panel-heading">
91
83
  <strong>Job Execution</strong>
@@ -124,6 +116,8 @@
124
116
  var requires_approval = {{ job_model.approval_required|yesno:"true,false" }};
125
117
  var run_now_text;
126
118
  var schedule_text;
119
+ var dry_run_text = "Run Job Now (DRYRUN)";
120
+ var schedule_dry_run_text = "Schedule Job (DRYRUN)";
127
121
 
128
122
  if (requires_approval) {
129
123
  run_now_text = "Request to Run Job Now";
@@ -138,10 +132,21 @@
138
132
  * Toggle form elements based on the job execution type.
139
133
  * If the type is `immediately` (the default), don't show
140
134
  * any of the scheduling related elements, else, show them.
135
+ * If dryrun is selected, the job may run without approval.
141
136
  **/
137
+ var dryrun = false;
138
+ if ($("#id_dryrun").prop("type") === "checkbox") {
139
+ dryrun = $("#id_dryrun").prop("checked")
140
+ } else if ($("#id_dryrun").prop("type") === "hidden") {
141
+ dryrun = ($("#id_dryrun").val() === "True")
142
+ }
142
143
  if ($("#id__schedule_type").val() == "immediately") {
143
144
  // Toggle run button
144
- $("#id__run").html('<i class="mdi mdi-play"></i> ' + run_now_text);
145
+ if (dryrun){
146
+ $("#id__run").html('<i class="mdi mdi-play"></i> ' + dry_run_text);
147
+ } else {
148
+ $("#id__run").html('<i class="mdi mdi-play"></i> ' + run_now_text);
149
+ }
145
150
  $("#id__run").addClass("btn-primary");
146
151
  $("#id__run").removeClass("btn-warning");
147
152
 
@@ -151,7 +156,11 @@
151
156
  $("#id__schedule_start_time").parent().parent().hide();
152
157
  } else {
153
158
  // Toggle run button
154
- $("#id__run").html('<i class="mdi mdi-clock"></i> ' + schedule_text);
159
+ if (dryrun){
160
+ $("#id__run").html('<i class="mdi mdi-clock"></i> ' + schedule_dry_run_text);
161
+ } else {
162
+ $("#id__run").html('<i class="mdi mdi-clock"></i> ' + schedule_text);
163
+ }
155
164
  $("#id__run").addClass("btn-warning");
156
165
  $("#id__run").removeClass("btn-primary");
157
166
 
@@ -171,11 +180,12 @@
171
180
  $(document).ready(function() {
172
181
  {% if not job_model.has_sensitive_variables %}
173
182
  $("#id__schedule_type").change(toggleExecutionType);
174
- toggleExecutionType();
175
183
  {% else %}
176
184
  $("#id__schedule_type").val("immediately");
177
185
  $(".job_execution").hide();
178
186
  {% endif %}
187
+ $("#id_dryrun").change(toggleExecutionType);
188
+ toggleExecutionType();
179
189
  });
180
190
  </script>
181
191
  {% endblock %}
@@ -32,9 +32,6 @@
32
32
  <li role="presentation" class="active">
33
33
  <a href="#run" role="tab" data-toggle="tab" class="active">Approval Request</a>
34
34
  </li>
35
- <li role="presentation">
36
- <a href="#source" role="tab" data-toggle="tab">Source</a>
37
- </li>
38
35
  </ul>
39
36
  <div class="tab-content">
40
37
  <div role="tabpanel" class="tab-pane active" id="run">
@@ -66,22 +63,14 @@
66
63
  </div>
67
64
  </div>
68
65
  {% endif %}
69
- {% if job_form.requires_input %}
70
- <div class="panel panel-default">
71
- <div class="panel-heading">
72
- <strong>Job Data</strong>
73
- </div>
74
- <div class="panel-body">
75
- {% render_form job_form %}
76
- </div>
66
+ <div class="panel panel-default">
67
+ <div class="panel-heading">
68
+ <strong>Job Data</strong>
77
69
  </div>
78
- {% else %}
79
- <div class="alert alert-info">
80
- <i class="mdi mdi-information"></i>
81
- This job does not require any input to run.
70
+ <div class="panel-body">
71
+ {% render_form job_form %}
82
72
  </div>
83
- {% render_form job_form %}
84
- {% endif %}
73
+ </div>
85
74
  {% else %}
86
75
  <div class="panel panel-default">
87
76
  <div class="panel-heading"><strong>Job Data</strong></div>
@@ -110,13 +99,15 @@
110
99
  </div>
111
100
  </div>
112
101
  <div class="pull-right">
113
- <button type="submit" name="_dry_run" id="id__dry_run" class="btn btn-primary"
114
- {% if not perms.extras.run_job or object.job_model is None or not object.job_model.runnable %}
115
- disabled="disabled"
116
- {% endif %}
117
- >
118
- <i class="mdi mdi-play"></i> Dry Run
119
- </button>
102
+ {% if "dryrun" in job_form.fields and object.job_model.supports_dryrun %}
103
+ <button type="submit" name="_dry_run" id="id__dry_run" class="btn btn-primary"
104
+ {% if not perms.extras.run_job or object.job_model is None or not object.job_model.runnable %}
105
+ disabled="disabled"
106
+ {% endif %}
107
+ >
108
+ <i class="mdi mdi-play"></i> Dry Run
109
+ </button>
110
+ {% endif %}
120
111
  <button type="submit" name="_approve" id="id__approve" class="btn btn-success"
121
112
  {% if not perms.extras.approve_job or not perms.extras.change_scheduledjob or object.job_model is None or not object.job_model.runnable %}
122
113
  disabled="disabled"
@@ -139,11 +130,5 @@
139
130
  </div>
140
131
  </div>
141
132
  </div>
142
- <div role="tabpanel" class="tab-pane" id="source">
143
- {% if object.job_model.installed and object.job_model.job_class is not None %}
144
- <p><code>{{ object.job_model.job_class.filename }}</code></p>
145
- <pre>{{ object.job_model.job_class.source }}</pre>
146
- {% endif %}
147
- </div>
148
133
  </div>
149
134
  {% endblock %}
@@ -9,7 +9,7 @@
9
9
 
10
10
  {% block extra_buttons %}
11
11
  {% if perms.extras.run_job %}
12
- <a href="{% url 'extras:job_run' slug=object.slug %}" class="btn btn-primary"
12
+ <a href="{% url 'extras:job_run' pk=object.pk %}" class="btn btn-primary"
13
13
  {% if not object.installed or not object.enabled %}disabled="disabled"{% endif %}>
14
14
  <i class="mdi mdi-play" aria-hidden="true"></i> Run/Schedule
15
15
  </a>
@@ -22,16 +22,6 @@
22
22
  <strong>Source Code</strong>
23
23
  </div>
24
24
  <table class="table table-hover panel-body attr-table">
25
- <tr>
26
- <td>Source</td>
27
- <td>{{ object.source | bettertitle }}</td>
28
- </tr>
29
- {% if object.source == "git" %}
30
- <tr>
31
- <td>Repository</td>
32
- <td>{{ object.git_repository|hyperlinked_object }}</td>
33
- </tr>
34
- {% endif %}
35
25
  <tr>
36
26
  <td>Module</td>
37
27
  <td><code>{{ object.module_name }}</code></td>
@@ -152,14 +142,18 @@
152
142
  </td>
153
143
  </tr>
154
144
  <tr>
155
- <td>Default to Committing Changes</td>
156
- <td>{{ object.commit_default | render_boolean }}</td>
145
+ <td>Supports Dryrun</td>
146
+ <td colspan="2">{{ object.supports_dryrun | render_boolean }}</td>
147
+ </tr>
148
+ <tr>
149
+ <td>Default to Dryrun</td>
150
+ <td>{{ object.dryrun_default | render_boolean }}</td>
157
151
  <td>
158
- {% if object.commit_default_override %}
152
+ {% if object.dryrun_default_override %}
159
153
  <span class="text-muted">
160
154
  overridden; default is
161
155
  {% if object.installed %}
162
- {{ object.job_class.commit_default | render_boolean }}
156
+ {{ object.job_class.dryrun_default | render_boolean }}
163
157
  {% else %}
164
158
  unknown (not currently installed)
165
159
  {% endif %}
@@ -167,6 +161,10 @@
167
161
  {% endif %}
168
162
  </td>
169
163
  </tr>
164
+ <tr>
165
+ <td>Read-Only Execution</td>
166
+ <td colspan="2">{{ object.read_only | render_boolean }}</td>
167
+ </tr>
170
168
  <tr>
171
169
  <td>Hide from Default UI</td>
172
170
  <td>{{ object.hidden | render_boolean }}</td>
@@ -183,22 +181,6 @@
183
181
  {% endif %}
184
182
  </td>
185
183
  </tr>
186
- <tr>
187
- <td>Read-Only Execution</td>
188
- <td>{{ object.read_only | render_boolean }}</td>
189
- <td>
190
- {% if object.read_only_override %}
191
- <span class="text-muted">
192
- overridden; default is
193
- {% if object.installed %}
194
- {{ object.job_class.read_only | render_boolean }}
195
- {% else %}
196
- unknown (not currently installed)
197
- {% endif %}
198
- </span>
199
- {% endif %}
200
- </td>
201
- </tr>
202
184
  <tr>
203
185
  <td>Has Sensitive Variables</td>
204
186
  <td>{{ object.has_sensitive_variables | render_boolean }}</td>
@@ -6,21 +6,6 @@
6
6
  <div class="panel panel-default">
7
7
  <div class="panel-heading"><strong>Job Source</strong></div>
8
8
  <div class="panel-body">
9
- <div class="form-group">
10
- <label class="col-md-3 control-label">Source</label>
11
- <div class="col-md-9" style="padding-top: 7px">
12
- {{ obj.source | split:"." | first | bettertitle }}
13
- <span class="help-block">Source of the Python code for this job</span>
14
- </div>
15
- </div>
16
- {% if obj.source == "git" %}
17
- <div class="form-group">
18
- <label class="col-md-3 control-label">Repository</label>
19
- <div class="col-md-9" style="padding-top: 7px">
20
- <td>{{ obj.git_repository | placeholder }}</td>
21
- </div>
22
- </div>
23
- {% endif %}
24
9
  <div class="form-group">
25
10
  <label class="col-md-3 control-label">Module</label>
26
11
  <div class="col-md-9" style="padding-top: 7px">
@@ -48,6 +33,19 @@
48
33
  </div>
49
34
  </div>
50
35
  </div>
36
+ <div class="form-group">
37
+ <div class="col-md-9 col-md-offset-3">
38
+ <div class="checkbox">
39
+ <label>
40
+ <input type="checkbox" disabled="true" {% if obj.supports_dryrun %}checked="checked"{% endif %}>
41
+ Supports dryrun
42
+ </label>
43
+ <span class="help-block">
44
+ Whether this job supports bypassing approval when running with dryrun argument set to true
45
+ </span>
46
+ </div>
47
+ </div>
48
+ </div>
51
49
  <div class="form-group">
52
50
  <div class="col-md-9 col-md-offset-3">
53
51
  <div class="checkbox">
@@ -81,6 +79,7 @@
81
79
  <div class="panel-body">
82
80
  {% render_field form.enabled %}
83
81
  {% include "extras/inc/overridable_field.html" with field=form.name override_field=form.name_override %}
82
+ {% render_field form.slug %}
84
83
  {% include "extras/inc/overridable_field.html" with field=form.grouping override_field=form.grouping_override %}
85
84
  {% include "extras/inc/overridable_field.html" with field=form.description override_field=form.description_override %}
86
85
  </div>
@@ -89,9 +88,8 @@
89
88
  <div class="panel-heading"><strong>Properties</strong></div>
90
89
  <div class="panel-body">
91
90
  {% include "extras/inc/overridable_field.html" with field=form.approval_required override_field=form.approval_required_override %}
92
- {% include "extras/inc/overridable_field.html" with field=form.commit_default override_field=form.commit_default_override %}
91
+ {% include "extras/inc/overridable_field.html" with field=form.dryrun_default override_field=form.dryrun_default_override %}
93
92
  {% include "extras/inc/overridable_field.html" with field=form.hidden override_field=form.hidden_override %}
94
- {% include "extras/inc/overridable_field.html" with field=form.read_only override_field=form.read_only_override %}
95
93
  {% include "extras/inc/overridable_field.html" with field=form.soft_time_limit override_field=form.soft_time_limit_override %}
96
94
  {% include "extras/inc/overridable_field.html" with field=form.time_limit override_field=form.time_limit_override %}
97
95
  {% include "extras/inc/overridable_field.html" with field=form.has_sensitive_variables override_field=form.has_sensitive_variables_override %}
@@ -35,18 +35,20 @@
35
35
  {% block buttons %}
36
36
  {% if perms.extras.run_job %}
37
37
  {% if result.job_model and result.task_kwargs %}
38
- <a href="{% url 'extras:job_run' slug=result.job_model.slug %}?kwargs_from_job_result={{ result.pk }}"
38
+ <a href="{% url 'extras:job_run' pk=result.job_model.pk %}?kwargs_from_job_result={{ result.pk }}"
39
39
  class="btn btn-success">
40
40
  <span class="mdi mdi-repeat" aria-hidden="true"></span> Re-Run
41
41
  </a>
42
42
  {% elif result.job_model is not None %}
43
- <a href="{% url 'extras:job_run' slug=result.job_model.slug %}"
43
+ <a href="{% url 'extras:job_run' pk=result.job_model.pk %}"
44
44
  class="btn btn-primary">
45
45
  <span class="mdi mdi-play" aria-hidden="true"></span> Run
46
46
  </a>
47
47
  {% endif %}
48
48
  {% endif %}
49
- {% export_button %}
49
+ <a href="{% url 'extras-api:joblogentry-list' %}?job_result={{ result.pk }}&format=csv" class="btn btn-success">
50
+ <span class="mdi mdi-database-export" aria-hidden="true"></span> Export
51
+ </a>
50
52
  {{ block.super }}
51
53
  {% endblock buttons %}
52
54
 
@@ -84,20 +86,36 @@
84
86
  <div class="col-md-6">
85
87
  <div class="panel panel-default">
86
88
  <div class="panel-heading">
87
- <strong>Job Inputs</strong>
89
+ <strong>Job Positional Arguments</strong>
90
+ </div>
91
+ <div class="panel-body">
92
+ {% include 'extras/inc/json_data.html' with data=result.task_args format="json" %}
93
+ </div>
94
+ </div>
95
+ <div class="panel panel-default">
96
+ <div class="panel-heading">
97
+ <strong>Job Keyword Arguments</strong>
88
98
  </div>
89
99
  <div class="panel-body">
90
100
  {% include 'extras/inc/json_data.html' with data=result.task_kwargs format="json" %}
91
101
  </div>
92
102
  </div>
103
+ <div class="panel panel-default">
104
+ <div class="panel-heading">
105
+ <strong>Job Celery Keyword Arguments</strong>
106
+ </div>
107
+ <div class="panel-body">
108
+ {% include 'extras/inc/json_data.html' with data=result.celery_kwargs format="json" %}
109
+ </div>
110
+ </div>
93
111
  </div>
94
112
  <div class="col-md-6">
95
113
  <div class="panel panel-default">
96
114
  <div class="panel-heading">
97
- <strong>Output Data</strong>
115
+ <strong>Return Data</strong>
98
116
  </div>
99
117
  <div class="panel-body">
100
- {% include 'extras/inc/json_data.html' with data=result.data format="json" %}
118
+ {% include 'extras/inc/json_data.html' with data=result.result format="json" %}
101
119
  </div>
102
120
  </div>
103
121
  <div class="panel panel-default">
@@ -8,7 +8,7 @@
8
8
  {% block buttons %}
9
9
  {% plugin_buttons object %}
10
10
  {% if user|can_delete:object %}
11
- {% delete_button object key='pk' %}
11
+ {% delete_button object %}
12
12
  {% endif %}
13
13
  {% endblock buttons %}
14
14
 
@@ -119,7 +119,7 @@
119
119
  <strong>User Inputs</strong>
120
120
  </div>
121
121
  <table class="table table-hover panel-body attr-table">
122
- {% for key, value in object.kwargs.data.items %}
122
+ {% for key, value in object.kwargs.items %}
123
123
  <tr>
124
124
  <td>{{ labels|get_item:key }}</td>
125
125
  <td>{% if value is None %}–{% else %}<code>{{ value }}</code>{% endif %}</td>
@@ -1,6 +1,12 @@
1
1
  {% extends 'generic/object_detail.html' %}
2
2
  {% load helpers %}
3
3
 
4
+ {% block extra_buttons %}
5
+ <a onClick="checkSecret()" class="btn btn-default">
6
+ Check Secret
7
+ </a>
8
+ {% endblock extra_buttons %}
9
+
4
10
  {% block content_left_page %}
5
11
  <div class="panel panel-default">
6
12
  <div class="panel-heading">
@@ -35,3 +41,25 @@
35
41
  {% block content_right_page %}
36
42
  {% include 'utilities/obj_table.html' with table=groups_table table_template='panel_table.html' heading='Groups containing this secret' %}
37
43
  {% endblock content_right_page %}
44
+
45
+
46
+ {% block javascript %}
47
+ <script>
48
+ function checkSecret() {
49
+ $.ajax({
50
+ url: "{% url 'extras-api:secret-check' pk=object.pk %}",
51
+ dataType: 'json',
52
+ success: function(json) {
53
+ if(json.result) {
54
+ alert("The secret was successfully retrieved.")
55
+ } else {
56
+ alert("Error retrieving secret: \n\n" + json.message)
57
+ }
58
+ },
59
+ error: function(xhr) {
60
+ alert("Error checking secret: \n\n" + xhr.responseText);
61
+ }
62
+ });
63
+ }
64
+ </script>
65
+ {% endblock javascript %}
@@ -144,6 +144,7 @@ def job_buttons(context, obj):
144
144
  "object": obj,
145
145
  "job": jb.job,
146
146
  "hidden_inputs": hidden_inputs,
147
+ "disabled": "" if context["user"].has_perms(("extras.run_jobbutton", "extras.run_job")) else "disabled",
147
148
  }
148
149
  try:
149
150
  text_rendered = render_jinja2(jb.text, button_context)
@@ -1,9 +1,13 @@
1
1
  from django.conf import settings
2
2
 
3
- from nautobot.extras.jobs import Job, BooleanVar, IntegerVar, StringVar, ObjectVar
3
+ from nautobot.core.celery import register_jobs
4
+ from nautobot.extras.jobs import Job, BooleanVar, IntegerVar, StringVar, ObjectVar, get_task_logger
4
5
  from nautobot.extras.models import Role
5
6
 
6
7
 
8
+ logger = get_task_logger(__name__)
9
+
10
+
7
11
  class APITestJob(Job):
8
12
  class Meta:
9
13
  name = "Job for API Tests"
@@ -15,10 +19,13 @@ class APITestJob(Job):
15
19
  var3 = BooleanVar()
16
20
  var4 = ObjectVar(model=Role)
17
21
 
18
- def run(self, data, commit=True):
19
- self.log_debug(message=data["var1"])
20
- self.log_info(message=data["var2"])
21
- self.log_success(message=data["var3"])
22
- self.log_warning(message=data["var4"])
22
+ def run(self, var1, var2, var3, var4):
23
+ logger.debug(var1)
24
+ logger.info(var2)
25
+ logger.warning(var3)
26
+ logger.error(var4)
23
27
 
24
28
  return "Job complete"
29
+
30
+
31
+ register_jobs(APITestJob)
@@ -0,0 +1,53 @@
1
+ from django.db import transaction
2
+
3
+ from nautobot.core.celery import register_jobs
4
+ from nautobot.extras.jobs import Job, BooleanVar, get_task_logger
5
+ from nautobot.extras.models import Status
6
+
7
+
8
+ logger = get_task_logger(__name__)
9
+
10
+
11
+ class SimulatedError(Exception):
12
+ """I'm just a dummy exception for the purpose of testing."""
13
+
14
+
15
+ class TestAtomicDecorator(Job):
16
+ """
17
+ Job that uses @transaction.atomic decorator to roll back changes.
18
+ """
19
+
20
+ fail = BooleanVar()
21
+
22
+ @transaction.atomic
23
+ def run(self, fail=False):
24
+ try:
25
+ Status.objects.create(name="Test database atomic rollback 1")
26
+ if fail:
27
+ raise SimulatedError("simulated failure")
28
+ except Exception:
29
+ logger.error("Job failed, all database changes have been rolled back.")
30
+ raise
31
+ logger.info("Job succeeded.")
32
+
33
+
34
+ class TestAtomicContextManager(Job):
35
+ """
36
+ Job that uses `with transaction.atomic()` context manager to roll back changes.
37
+ """
38
+
39
+ fail = BooleanVar()
40
+
41
+ def run(self, fail=False):
42
+ try:
43
+ with transaction.atomic():
44
+ Status.objects.create(name="Test database atomic rollback 2")
45
+ if fail:
46
+ raise SimulatedError("simulated failure")
47
+ except Exception as err:
48
+ logger.error("Job failed, all database changes have been rolled back.")
49
+ raise err
50
+ logger.info("Job succeeded.")
51
+
52
+
53
+ register_jobs(TestAtomicContextManager, TestAtomicDecorator)