katello 4.18.0 → 4.19.0.rc1

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 katello might be problematic. Click here for more details.

Files changed (345) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/locale/bn/katello.js +52 -349
  3. data/app/assets/javascripts/katello/locale/bn_IN/katello.js +52 -349
  4. data/app/assets/javascripts/katello/locale/ca/katello.js +52 -349
  5. data/app/assets/javascripts/katello/locale/cs/katello.js +53 -350
  6. data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +54 -351
  7. data/app/assets/javascripts/katello/locale/de/katello.js +56 -353
  8. data/app/assets/javascripts/katello/locale/de_AT/katello.js +52 -349
  9. data/app/assets/javascripts/katello/locale/de_DE/katello.js +52 -349
  10. data/app/assets/javascripts/katello/locale/el/katello.js +54 -351
  11. data/app/assets/javascripts/katello/locale/en/katello.js +53 -350
  12. data/app/assets/javascripts/katello/locale/en_GB/katello.js +53 -350
  13. data/app/assets/javascripts/katello/locale/en_US/katello.js +52 -349
  14. data/app/assets/javascripts/katello/locale/es/katello.js +56 -353
  15. data/app/assets/javascripts/katello/locale/et_EE/katello.js +52 -349
  16. data/app/assets/javascripts/katello/locale/fr/katello.js +138 -435
  17. data/app/assets/javascripts/katello/locale/gl/katello.js +52 -349
  18. data/app/assets/javascripts/katello/locale/gu/katello.js +52 -349
  19. data/app/assets/javascripts/katello/locale/he_IL/katello.js +52 -349
  20. data/app/assets/javascripts/katello/locale/hi/katello.js +52 -349
  21. data/app/assets/javascripts/katello/locale/id/katello.js +52 -349
  22. data/app/assets/javascripts/katello/locale/it/katello.js +53 -350
  23. data/app/assets/javascripts/katello/locale/ja/katello.js +142 -439
  24. data/app/assets/javascripts/katello/locale/ka/katello.js +56 -353
  25. data/app/assets/javascripts/katello/locale/kn/katello.js +52 -349
  26. data/app/assets/javascripts/katello/locale/ko/katello.js +135 -432
  27. data/app/assets/javascripts/katello/locale/ml_IN/katello.js +52 -349
  28. data/app/assets/javascripts/katello/locale/mr/katello.js +52 -349
  29. data/app/assets/javascripts/katello/locale/nl_NL/katello.js +52 -349
  30. data/app/assets/javascripts/katello/locale/or/katello.js +52 -349
  31. data/app/assets/javascripts/katello/locale/pa/katello.js +52 -349
  32. data/app/assets/javascripts/katello/locale/pl/katello.js +52 -349
  33. data/app/assets/javascripts/katello/locale/pl_PL/katello.js +52 -349
  34. data/app/assets/javascripts/katello/locale/pt/katello.js +52 -349
  35. data/app/assets/javascripts/katello/locale/pt_BR/katello.js +56 -353
  36. data/app/assets/javascripts/katello/locale/ro/katello.js +52 -349
  37. data/app/assets/javascripts/katello/locale/ro_RO/katello.js +52 -349
  38. data/app/assets/javascripts/katello/locale/ru/katello.js +54 -351
  39. data/app/assets/javascripts/katello/locale/sl/katello.js +52 -349
  40. data/app/assets/javascripts/katello/locale/sv_SE/katello.js +52 -349
  41. data/app/assets/javascripts/katello/locale/ta/katello.js +52 -349
  42. data/app/assets/javascripts/katello/locale/ta_IN/katello.js +52 -349
  43. data/app/assets/javascripts/katello/locale/te/katello.js +52 -349
  44. data/app/assets/javascripts/katello/locale/tr/katello.js +52 -349
  45. data/app/assets/javascripts/katello/locale/vi/katello.js +52 -349
  46. data/app/assets/javascripts/katello/locale/vi_VN/katello.js +52 -349
  47. data/app/assets/javascripts/katello/locale/zh/katello.js +52 -349
  48. data/app/assets/javascripts/katello/locale/zh_CN/katello.js +135 -432
  49. data/app/assets/javascripts/katello/locale/zh_TW/katello.js +54 -351
  50. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +46 -13
  51. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +1 -1
  52. data/app/controllers/katello/api/v2/activation_keys_controller.rb +3 -65
  53. data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +56 -34
  54. data/app/controllers/katello/api/v2/content_view_filter_rules_controller.rb +1 -1
  55. data/app/controllers/katello/api/v2/content_views_controller.rb +18 -3
  56. data/app/controllers/katello/api/v2/debs_controller.rb +21 -11
  57. data/app/controllers/katello/api/v2/docker_tags_controller.rb +7 -0
  58. data/app/controllers/katello/api/v2/errata_controller.rb +4 -4
  59. data/app/controllers/katello/api/v2/flatpak_remote_repositories_controller.rb +21 -19
  60. data/app/controllers/katello/api/v2/host_debs_controller.rb +16 -1
  61. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +3 -60
  62. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +10 -53
  63. data/app/controllers/katello/api/v2/repositories_controller.rb +0 -1
  64. data/app/controllers/katello/concerns/organizations_controller_extensions.rb +3 -0
  65. data/app/lib/actions/candlepin/activation_key/create.rb +0 -2
  66. data/app/lib/actions/candlepin/activation_key/update.rb +0 -2
  67. data/app/lib/actions/candlepin/product/content_create.rb +3 -5
  68. data/app/lib/actions/candlepin/product/content_update.rb +2 -3
  69. data/app/lib/actions/helpers/rolling_cv_repos.rb +1 -1
  70. data/app/lib/actions/katello/activation_key/create.rb +0 -1
  71. data/app/lib/actions/katello/activation_key/update.rb +0 -2
  72. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +1 -6
  73. data/app/lib/actions/katello/content_credential/update.rb +1 -1
  74. data/app/lib/actions/katello/content_view/add_rolling_repo_clone.rb +18 -24
  75. data/app/lib/actions/katello/content_view/create.rb +9 -4
  76. data/app/lib/actions/katello/content_view/publish.rb +7 -7
  77. data/app/lib/actions/katello/content_view/refresh_rolling_repo.rb +6 -1
  78. data/app/lib/actions/katello/content_view/remove_rolling_repo_clone.rb +16 -11
  79. data/app/lib/actions/katello/content_view/update.rb +34 -7
  80. data/app/lib/actions/katello/product/content_create.rb +2 -2
  81. data/app/lib/actions/katello/product/content_destroy.rb +1 -1
  82. data/app/lib/actions/katello/repository/check_matching_content.rb +1 -1
  83. data/app/lib/actions/katello/repository/clone_contents.rb +1 -1
  84. data/app/lib/actions/katello/repository/create.rb +1 -1
  85. data/app/lib/actions/katello/repository/destroy.rb +4 -4
  86. data/app/lib/actions/katello/repository/finish_upload.rb +1 -1
  87. data/app/lib/actions/katello/repository/sync.rb +1 -1
  88. data/app/lib/actions/pulp3/orchestration/repository/copy_all_units.rb +2 -2
  89. data/app/lib/actions/pulp3/orchestration/repository/generate_metadata.rb +1 -1
  90. data/app/lib/actions/pulp3/orchestration/repository/multi_copy_all_units.rb +1 -1
  91. data/app/lib/actions/pulp3/repository/save_publication.rb +3 -1
  92. data/app/lib/actions/pulp3/repository/save_version.rb +45 -24
  93. data/app/lib/actions/pulp3/repository/save_versions.rb +2 -1
  94. data/app/lib/katello/resources/candlepin/activation_key.rb +3 -4
  95. data/app/lib/katello/resources/candlepin/upstream_job.rb +9 -1
  96. data/app/lib/katello/resources/candlepin.rb +4 -0
  97. data/app/models/katello/authorization/repository.rb +17 -4
  98. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +0 -7
  99. data/app/models/katello/content_view_deb_filter.rb +10 -0
  100. data/app/models/katello/content_view_deb_filter_rule.rb +7 -0
  101. data/app/models/katello/deb.rb +10 -12
  102. data/app/models/katello/erratum.rb +1 -1
  103. data/app/models/katello/glue/provider.rb +14 -3
  104. data/app/models/katello/host/content_facet.rb +1 -1
  105. data/app/models/katello/host/subscription_facet.rb +1 -7
  106. data/app/models/katello/product_content.rb +2 -2
  107. data/app/models/katello/repository.rb +4 -23
  108. data/app/models/katello/root_repository.rb +2 -5
  109. data/app/services/katello/candlepin/event_handler.rb +0 -33
  110. data/app/services/katello/candlepin/message_handler.rb +0 -41
  111. data/app/services/katello/content_unit_indexer.rb +59 -13
  112. data/app/services/katello/product_content_finder.rb +16 -7
  113. data/app/services/katello/pulp3/alternate_content_source.rb +2 -2
  114. data/app/services/katello/pulp3/ansible_collection.rb +1 -0
  115. data/app/services/katello/pulp3/api/content_guard.rb +5 -5
  116. data/app/services/katello/pulp3/api/core.rb +10 -0
  117. data/app/services/katello/pulp3/content_view_version/export.rb +25 -10
  118. data/app/services/katello/pulp3/deb.rb +1 -0
  119. data/app/services/katello/pulp3/docker_manifest.rb +1 -0
  120. data/app/services/katello/pulp3/docker_manifest_list.rb +1 -0
  121. data/app/services/katello/pulp3/docker_tag.rb +1 -0
  122. data/app/services/katello/pulp3/file_unit.rb +1 -0
  123. data/app/services/katello/pulp3/generic_content_unit.rb +1 -0
  124. data/app/services/katello/pulp3/module_stream.rb +1 -0
  125. data/app/services/katello/pulp3/package_group.rb +1 -0
  126. data/app/services/katello/pulp3/repository/apt.rb +30 -13
  127. data/app/services/katello/pulp3/repository.rb +59 -10
  128. data/app/services/katello/pulp3/rpm.rb +3 -2
  129. data/app/services/katello/pulp3/srpm.rb +3 -2
  130. data/app/services/katello/pulp3/task_group.rb +1 -1
  131. data/app/services/katello/registration_manager.rb +19 -17
  132. data/app/services/katello/repository_type_manager.rb +7 -5
  133. data/app/services/katello/smart_proxy_helper.rb +1 -6
  134. data/app/views/foreman/job_templates/upload_profile.erb +5 -0
  135. data/app/views/katello/api/v2/activation_keys/base.json.rabl +1 -1
  136. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -0
  137. data/app/views/katello/api/v2/debs/thindex.json.rabl +6 -0
  138. data/app/views/katello/api/v2/docker_tags/_base.json.rabl +32 -0
  139. data/app/views/katello/api/v2/docker_tags/show.json.rabl +0 -5
  140. data/app/views/katello/api/v2/flatpak_remotes/index.json.rabl +6 -0
  141. data/app/views/katello/api/v2/host_debs/installed_debs.json.rabl +6 -0
  142. data/app/views/katello/api/v2/hosts_bulk_actions/applicable_errata.json.rabl +1 -1
  143. data/app/views/katello/api/v2/hosts_bulk_actions/applicable_erratum.json.rabl +9 -0
  144. data/app/views/katello/api/v2/hosts_bulk_actions/installable_errata.json.rabl +1 -1
  145. data/app/views/katello/api/v2/hosts_bulk_actions/{erratum.json.rabl → installable_erratum.json.rabl} +3 -3
  146. data/app/views/katello/api/v2/subscription_facet/base.json.rabl +1 -1
  147. data/config/initializers/monkeys.rb +1 -0
  148. data/config/routes/api/v2.rb +2 -2
  149. data/config/routes/overrides.rb +2 -7
  150. data/config/routes.rb +2 -0
  151. data/db/migrate/20211019192121_create_cdn_configuration.katello.rb +1 -1
  152. data/db/migrate/20250912000000_add_pulp_prn_fields.rb +73 -0
  153. data/db/migrate/20250912000001_populate_pulp_prn_fields.rb +403 -0
  154. data/db/migrate/20251009142516_remove_auto_attach_from_activation_keys.rb +5 -0
  155. data/db/migrate/20251009142517_remove_autoheal_from_subscription_facets.rb +5 -0
  156. data/db/seeds.d/111-upgrade_tasks.rb +2 -0
  157. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/el.po +2 -2
  158. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +6 -1
  159. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +5 -2
  160. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +5 -2
  161. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +5 -2
  162. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/translations.js +4 -4
  163. data/lib/katello/permission_creator.rb +2 -2
  164. data/lib/katello/permissions/host_permissions.rb +0 -6
  165. data/lib/katello/plugin.rb +16 -8
  166. data/lib/katello/tasks/jenkins.rake +1 -1
  167. data/lib/katello/tasks/upgrades/4.19/enable_structured_apt_for_deb.rake +87 -0
  168. data/lib/katello/tasks/upgrades/4.19/populate_repository_version_prns.rake +32 -0
  169. data/lib/katello/version.rb +1 -1
  170. data/lib/monkeys/fix_rpm_repository_gpgcheck.rb +38 -0
  171. data/locale/bn/LC_MESSAGES/katello.mo +0 -0
  172. data/locale/bn/katello.po +52 -349
  173. data/locale/bn_IN/LC_MESSAGES/katello.mo +0 -0
  174. data/locale/bn_IN/katello.po +52 -349
  175. data/locale/ca/LC_MESSAGES/katello.mo +0 -0
  176. data/locale/ca/katello.po +52 -349
  177. data/locale/cs/LC_MESSAGES/katello.mo +0 -0
  178. data/locale/cs/katello.po +54 -350
  179. data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
  180. data/locale/cs_CZ/katello.po +54 -351
  181. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  182. data/locale/de/katello.po +56 -353
  183. data/locale/de_AT/LC_MESSAGES/katello.mo +0 -0
  184. data/locale/de_AT/katello.po +52 -349
  185. data/locale/de_DE/LC_MESSAGES/katello.mo +0 -0
  186. data/locale/de_DE/katello.po +52 -349
  187. data/locale/el/LC_MESSAGES/katello.mo +0 -0
  188. data/locale/el/katello.po +55 -352
  189. data/locale/en/LC_MESSAGES/katello.mo +0 -0
  190. data/locale/en/katello.po +54 -350
  191. data/locale/en_GB/LC_MESSAGES/katello.mo +0 -0
  192. data/locale/en_GB/katello.po +53 -350
  193. data/locale/en_US/LC_MESSAGES/katello.mo +0 -0
  194. data/locale/en_US/katello.po +52 -349
  195. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  196. data/locale/es/katello.po +56 -353
  197. data/locale/et_EE/LC_MESSAGES/katello.mo +0 -0
  198. data/locale/et_EE/katello.po +52 -349
  199. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  200. data/locale/fr/katello.po +139 -435
  201. data/locale/gl/LC_MESSAGES/katello.mo +0 -0
  202. data/locale/gl/katello.po +52 -349
  203. data/locale/gu/LC_MESSAGES/katello.mo +0 -0
  204. data/locale/gu/katello.po +52 -349
  205. data/locale/he_IL/LC_MESSAGES/katello.mo +0 -0
  206. data/locale/he_IL/katello.po +52 -349
  207. data/locale/hi/LC_MESSAGES/katello.mo +0 -0
  208. data/locale/hi/katello.po +52 -349
  209. data/locale/id/LC_MESSAGES/katello.mo +0 -0
  210. data/locale/id/katello.po +52 -349
  211. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  212. data/locale/it/katello.po +53 -350
  213. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  214. data/locale/ja/katello.po +143 -439
  215. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  216. data/locale/ka/katello.po +56 -353
  217. data/locale/katello.pot +695 -1152
  218. data/locale/kn/LC_MESSAGES/katello.mo +0 -0
  219. data/locale/kn/katello.po +52 -349
  220. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  221. data/locale/ko/katello.po +136 -432
  222. data/locale/ml_IN/LC_MESSAGES/katello.mo +0 -0
  223. data/locale/ml_IN/katello.po +52 -349
  224. data/locale/mr/LC_MESSAGES/katello.mo +0 -0
  225. data/locale/mr/katello.po +52 -349
  226. data/locale/nl_NL/LC_MESSAGES/katello.mo +0 -0
  227. data/locale/nl_NL/katello.po +52 -349
  228. data/locale/or/LC_MESSAGES/katello.mo +0 -0
  229. data/locale/or/katello.po +52 -349
  230. data/locale/pa/LC_MESSAGES/katello.mo +0 -0
  231. data/locale/pa/katello.po +52 -349
  232. data/locale/pl/LC_MESSAGES/katello.mo +0 -0
  233. data/locale/pl/katello.po +52 -349
  234. data/locale/pl_PL/LC_MESSAGES/katello.mo +0 -0
  235. data/locale/pl_PL/katello.po +52 -349
  236. data/locale/pt/LC_MESSAGES/katello.mo +0 -0
  237. data/locale/pt/katello.po +52 -349
  238. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  239. data/locale/pt_BR/katello.po +56 -353
  240. data/locale/ro/LC_MESSAGES/katello.mo +0 -0
  241. data/locale/ro/katello.po +52 -349
  242. data/locale/ro_RO/LC_MESSAGES/katello.mo +0 -0
  243. data/locale/ro_RO/katello.po +52 -349
  244. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  245. data/locale/ru/katello.po +54 -351
  246. data/locale/sl/LC_MESSAGES/katello.mo +0 -0
  247. data/locale/sl/katello.po +52 -349
  248. data/locale/sv_SE/LC_MESSAGES/katello.mo +0 -0
  249. data/locale/sv_SE/katello.po +52 -349
  250. data/locale/ta/LC_MESSAGES/katello.mo +0 -0
  251. data/locale/ta/katello.po +52 -349
  252. data/locale/ta_IN/LC_MESSAGES/katello.mo +0 -0
  253. data/locale/ta_IN/katello.po +52 -349
  254. data/locale/te/LC_MESSAGES/katello.mo +0 -0
  255. data/locale/te/katello.po +52 -349
  256. data/locale/tr/LC_MESSAGES/katello.mo +0 -0
  257. data/locale/tr/katello.po +52 -349
  258. data/locale/vi/LC_MESSAGES/katello.mo +0 -0
  259. data/locale/vi/katello.po +52 -349
  260. data/locale/vi_VN/LC_MESSAGES/katello.mo +0 -0
  261. data/locale/vi_VN/katello.po +52 -349
  262. data/locale/zh/LC_MESSAGES/katello.mo +0 -0
  263. data/locale/zh/katello.po +52 -349
  264. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  265. data/locale/zh_CN/katello.po +136 -432
  266. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  267. data/locale/zh_TW/katello.po +54 -351
  268. data/webpack/components/Content/Details/__tests__/__snapshots__/ContentDetails.test.js.snap +2 -2
  269. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeEditModal.js +0 -2
  270. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/__tests__/SystemPurposeEditModal.test.js +0 -2
  271. data/webpack/components/extensions/Hosts/ActionsBar/index.js +1 -0
  272. data/webpack/components/extensions/Hosts/BulkActions/BulkActionsConstants.js +7 -0
  273. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/BulkChangeHostCollectionsModal.js +388 -0
  274. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/__tests__/BulkChangeHostCollectionsModal.test.js +640 -0
  275. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/actions.js +28 -0
  276. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/index.js +71 -0
  277. data/webpack/components/extensions/Hosts/BulkActions/BulkErrataWizard/BulkErrataWizard.js +1 -1
  278. data/webpack/components/extensions/Hosts/BulkActions/BulkPackagesWizard/02_BulkPackagesTable.js +10 -3
  279. data/webpack/components/extensions/Hosts/BulkActions/BulkPackagesWizard/BulkPackagesWizard.js +51 -24
  280. data/webpack/components/extensions/Hosts/BulkActions/HostReview.js +7 -0
  281. data/webpack/containers/Application/config.js +11 -1
  282. data/webpack/global_index.js +3 -0
  283. data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/BootedContainerImagesConstants.js +1 -1
  284. data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/BootedContainerImagesPage.js +7 -43
  285. data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/__tests__/bootedContainerImagesPage.test.js +1 -1
  286. data/webpack/scenes/ContainerImages/ContainerImagesPage.js +86 -0
  287. data/webpack/scenes/ContainerImages/LabelsAnnotationsModal.js +105 -0
  288. data/webpack/scenes/ContainerImages/Synced/Details/ManifestDetails.js +218 -0
  289. data/webpack/scenes/ContainerImages/Synced/Details/ManifestDetailsActions.js +15 -0
  290. data/webpack/scenes/ContainerImages/Synced/Details/ManifestDetailsSelectors.js +16 -0
  291. data/webpack/scenes/ContainerImages/Synced/Details/__tests__/ManifestDetails.test.js +395 -0
  292. data/webpack/scenes/ContainerImages/Synced/Details/__tests__/manifestDetails.fixtures.json +43 -0
  293. data/webpack/scenes/ContainerImages/Synced/Details/__tests__/manifestList.fixtures.json +58 -0
  294. data/webpack/scenes/ContainerImages/Synced/Details/index.js +4 -0
  295. data/webpack/scenes/ContainerImages/Synced/SyncedContainerImagesPage.js +359 -0
  296. data/webpack/scenes/ContainerImages/Synced/SyncedContainerImagesPage.scss +21 -0
  297. data/webpack/scenes/ContainerImages/Synced/__tests__/LabelsAnnotationsModal.test.js +69 -0
  298. data/webpack/scenes/ContainerImages/Synced/__tests__/SyncedContainerImagesPage.test.js +335 -0
  299. data/webpack/scenes/ContainerImages/Synced/__tests__/syncedContainerImages.fixtures.json +105 -0
  300. data/webpack/scenes/ContainerImages/TableEmptyState.js +67 -0
  301. data/webpack/scenes/ContainerImages/containerImagesHelpers.js +48 -0
  302. data/webpack/scenes/ContainerImages/index.js +4 -0
  303. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +29 -3
  304. data/webpack/scenes/ContentViews/Create/__tests__/contentViewCreateResult.fixtures.json +1 -0
  305. data/webpack/scenes/ContentViews/Create/__tests__/createContentView.test.js +45 -1
  306. data/webpack/scenes/ContentViews/Delete/__tests__/affectedHosts.fixtures.json +0 -1
  307. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +59 -1
  308. data/webpack/scenes/ContentViews/Details/Filters/CVDebFilterContent.js +1 -0
  309. data/webpack/scenes/ContentViews/Details/Filters/Rules/DebPackage/AddEditDebPackageRuleModal.js +164 -24
  310. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVDebFilterContent.test.js +268 -0
  311. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvDebFilterDetail.fixtures.json +95 -0
  312. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvDebFilterRules.fixtures.json +31 -0
  313. data/webpack/scenes/ContentViews/Details/Filters/__tests__/emptyCVDebFilterRules.fixtures.json +10 -0
  314. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/hosts.fixtures.json +0 -1
  315. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvAffectedHosts.fixture.json +0 -1
  316. data/webpack/scenes/ContentViews/Details/__tests__/contentViewRollingDetail.test.js +15 -0
  317. data/webpack/scenes/ContentViews/Details/__tests__/contentViewRollingDetails.fixtures.json +1 -0
  318. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +9 -0
  319. data/webpack/scenes/FlatpakRemotes/CreateEdit/CreateFlatpakRemoteModal.js +5 -3
  320. data/webpack/scenes/FlatpakRemotes/CreateEdit/EditFlatpakRemotesModal.js +1 -1
  321. data/webpack/scenes/FlatpakRemotes/CreateEdit/FlatpakRemoteform.js +35 -3
  322. data/webpack/scenes/FlatpakRemotes/Details/FlatpakRemoteDetails.js +1 -1
  323. data/webpack/scenes/FlatpakRemotes/Details/RemoteRepositories/RemoteRepositoriesTable.css +3 -0
  324. data/webpack/scenes/FlatpakRemotes/Details/RemoteRepositories/RemoteRepositoriesTable.js +63 -132
  325. data/webpack/scenes/FlatpakRemotes/FlatpakRemotesPage.js +67 -143
  326. data/webpack/scenes/SmartProxy/ExpandableCvDetails.js +10 -2
  327. data/webpack/scenes/SmartProxy/SmartProxyContentActions.js +13 -2
  328. data/webpack/scenes/SmartProxy/SmartProxyContentConstants.js +1 -0
  329. data/webpack/scenes/SmartProxy/SmartProxyExpandableTable.js +8 -2
  330. data/webpack/scenes/SmartProxy/__tests__/SmartProxyContentTest.js +67 -1
  331. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +2 -2
  332. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +0 -2
  333. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +2 -2
  334. metadata +83 -55
  335. data/app/lib/actions/katello/host/attach_subscriptions.rb +0 -59
  336. data/app/lib/actions/katello/host/auto_attach_subscriptions.rb +0 -22
  337. data/app/lib/actions/katello/host/remove_subscriptions.rb +0 -50
  338. data/app/lib/actions/katello/organization/simple_content_access/disable.rb +0 -25
  339. data/app/lib/actions/katello/organization/simple_content_access/enable.rb +0 -25
  340. data/app/lib/actions/katello/organization/simple_content_access/toggle.rb +0 -42
  341. data/lib/katello/tasks/migrate_structure_content_for_deb.rake +0 -105
  342. data/lib/katello/tasks/upgrades/4.2/remove_checksum_values.rake +0 -17
  343. data/locale/action_names.rb +0 -186
  344. /data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/__tests__/bootedContainerImages.fixtures.js +0 -0
  345. /data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/index.js +0 -0
@@ -0,0 +1,58 @@
1
+ {
2
+ "id": 1,
3
+ "name": "latest",
4
+ "repositories": [
5
+ {
6
+ "id": 8,
7
+ "name": "multi-arch-container",
8
+ "full_path": "Default_Organization/Library/multi-arch-container",
9
+ "library_instance": true
10
+ }
11
+ ],
12
+ "product": {
13
+ "id": 3,
14
+ "name": "Container Images"
15
+ },
16
+ "manifest": {
17
+ "id": 101,
18
+ "digest": "sha256:abcd1234567890abcd1234567890abcd1234567890abcd1234567890abcd1234",
19
+ "schema_version": 2,
20
+ "manifest_type": "list",
21
+ "labels": {},
22
+ "annotations": {},
23
+ "is_bootable": false,
24
+ "is_flatpak": false,
25
+ "created_at": "2024-08-20T10:00:00.000Z",
26
+ "updated_at": "2024-08-20T10:00:00.000Z",
27
+ "manifests": [
28
+ {
29
+ "id": 102,
30
+ "digest": "sha256:1111aaaa2222bbbb3333cccc4444dddd5555eeee6666ffff7777gggg8888hhhh",
31
+ "manifest_type": "image",
32
+ "architecture": "amd64",
33
+ "labels": {
34
+ "arch": "amd64"
35
+ },
36
+ "annotations": {},
37
+ "is_bootable": false,
38
+ "is_flatpak": false,
39
+ "created_at": "2024-08-20T09:00:00.000Z",
40
+ "updated_at": "2024-08-20T09:00:00.000Z"
41
+ },
42
+ {
43
+ "id": 103,
44
+ "digest": "sha256:2222bbbb3333cccc4444dddd5555eeee6666ffff7777gggg8888hhhh9999iiii",
45
+ "manifest_type": "image",
46
+ "architecture": "arm64",
47
+ "labels": {
48
+ "arch": "arm64"
49
+ },
50
+ "annotations": {},
51
+ "is_bootable": true,
52
+ "is_flatpak": false,
53
+ "created_at": "2024-08-20T09:30:00.000Z",
54
+ "updated_at": "2024-08-20T09:30:00.000Z"
55
+ }
56
+ ]
57
+ }
58
+ }
@@ -0,0 +1,4 @@
1
+ import { withRouter } from 'react-router-dom';
2
+ import ManifestDetails from './ManifestDetails';
3
+
4
+ export default withRouter(ManifestDetails);
@@ -0,0 +1,359 @@
1
+ import React, { useState } from 'react';
2
+ import { Link } from 'react-router-dom';
3
+ import { Table, Thead, Th, Tbody, Tr, Td } from '@patternfly/react-table';
4
+ import { Button } from '@patternfly/react-core';
5
+ import TableIndexPage from 'foremanReact/components/PF4/TableIndexPage/TableIndexPage';
6
+ import {
7
+ useSetParamsAndApiAndSearch,
8
+ useTableIndexAPIResponse,
9
+ } from 'foremanReact/components/PF4/TableIndexPage/Table/TableIndexHooks';
10
+ import {
11
+ useUrlParams,
12
+ useSet,
13
+ } from 'foremanReact/components/PF4/TableIndexPage/Table/TableHooks';
14
+ import {
15
+ getColumnHelpers,
16
+ } from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
17
+ import {
18
+ useTableSort,
19
+ } from 'foremanReact/components/PF4/Helpers/useTableSort';
20
+ import Pagination from 'foremanReact/components/Pagination';
21
+ import { translate as __ } from 'foremanReact/common/I18n';
22
+ import { orgId } from '../../../services/api';
23
+ import {
24
+ formatManifestType,
25
+ getManifest,
26
+ hasLabelsOrAnnotations,
27
+ anyChildHasLabelsOrAnnotations,
28
+ STATUS,
29
+ } from '../containerImagesHelpers';
30
+ import LabelsAnnotationsModal from '../LabelsAnnotationsModal';
31
+ import TableEmptyState from '../TableEmptyState';
32
+ import './SyncedContainerImagesPage.scss';
33
+
34
+ const SYNCED_CONTAINER_IMAGES_KEY = 'SYNCED_CONTAINER_IMAGES';
35
+ const SYNCED_CONTAINER_IMAGES_API_PATH = '/katello/api/v2/docker_tags';
36
+
37
+ const SyncedContainerImagesPage = () => {
38
+ const [showLabelsModal, setShowLabelsModal] = useState(false);
39
+ const [selectedManifest, setSelectedManifest] = useState(null);
40
+
41
+ const getManifestType = (tag) => {
42
+ const manifest = getManifest(tag);
43
+ return formatManifestType(manifest);
44
+ };
45
+
46
+ const getDigest = (tag) => {
47
+ const manifest = getManifest(tag);
48
+ if (!manifest || !manifest.digest) return 'N/A';
49
+ return (
50
+ <Link to={`/labs/container_images/${tag.id}`}>
51
+ {manifest.digest}
52
+ </Link>
53
+ );
54
+ };
55
+
56
+ const getProductLink = (tag) => {
57
+ if (!tag.product) return 'N/A';
58
+
59
+ const productId = tag.product.id;
60
+ const productName = tag.product.name;
61
+
62
+ return (
63
+ <a href={`/products/${productId}`} target="_blank" rel="noopener noreferrer">
64
+ {productName}
65
+ </a>
66
+ );
67
+ };
68
+
69
+ const openLabelsModal = (manifest) => {
70
+ setSelectedManifest(manifest);
71
+ setShowLabelsModal(true);
72
+ };
73
+
74
+ const expandedTags = useSet([]);
75
+ const tagIsExpanded = tagId => expandedTags.has(tagId);
76
+
77
+ const columns = {
78
+ name: {
79
+ title: __('Tag'),
80
+ isSorted: true,
81
+ },
82
+ digest: {
83
+ title: __('Manifest digest'),
84
+ wrapper: tag => getDigest(tag),
85
+ },
86
+ type: {
87
+ title: __('Type'),
88
+ wrapper: tag => getManifestType(tag),
89
+ },
90
+ product: {
91
+ title: __('Product'),
92
+ wrapper: tag => getProductLink(tag),
93
+ },
94
+ labels: {
95
+ title: __('Labels | Annotations'),
96
+ wrapper: (tag) => {
97
+ const manifest = getManifest(tag);
98
+ if (hasLabelsOrAnnotations(manifest)) {
99
+ return (
100
+ <Button
101
+ variant="link"
102
+ isInline
103
+ onClick={() => openLabelsModal(manifest)}
104
+ ouiaId="view-labels-annotations-button"
105
+ aria-label={__('View labels and annotations')}
106
+ >
107
+ {__('View here')}
108
+ </Button>
109
+ );
110
+ }
111
+ if (anyChildHasLabelsOrAnnotations(manifest)) {
112
+ const isExpanded = tagIsExpanded(tag.id);
113
+ return (
114
+ <Button
115
+ variant="link"
116
+ isInline
117
+ onClick={() => expandedTags.onToggle(!isExpanded, tag.id)}
118
+ ouiaId="see-child-manifests-button"
119
+ >
120
+ {__('See child manifests')}
121
+ </Button>
122
+ );
123
+ }
124
+ return <span>{__('N/A')}</span>;
125
+ },
126
+ width: 15,
127
+ },
128
+ };
129
+
130
+ const {
131
+ searchParam: currentSearchQuery = '',
132
+ page: urlPage,
133
+ per_page: urlPerPage,
134
+ } = useUrlParams();
135
+
136
+ // Persistent params that must always be included
137
+ const persistentParams = {
138
+ grouped: true,
139
+ organization_id: orgId(),
140
+ };
141
+
142
+ const defaultParams = {
143
+ search: currentSearchQuery,
144
+ page: urlPage ? Number(urlPage) : 1,
145
+ per_page: urlPerPage ? Number(urlPerPage) : 20,
146
+ ...persistentParams,
147
+ };
148
+ const apiOptions = {
149
+ key: SYNCED_CONTAINER_IMAGES_KEY,
150
+ };
151
+
152
+ const originalResponse = useTableIndexAPIResponse({
153
+ apiUrl: SYNCED_CONTAINER_IMAGES_API_PATH,
154
+ apiOptions,
155
+ defaultParams,
156
+ });
157
+
158
+ // Wrap setAPIOptions to ensure persistent params are always included
159
+ // This is necessary because TableIndexPage may call setAPIOptions directly
160
+ // for operations like search, and those calls need to preserve persistent params
161
+ const wrappedSetAPIOptions = (options) => {
162
+ const mergedOptions = {
163
+ ...options,
164
+ params: {
165
+ ...persistentParams,
166
+ ...options.params,
167
+ },
168
+ };
169
+ originalResponse.setAPIOptions(mergedOptions);
170
+ };
171
+
172
+ const response = {
173
+ ...originalResponse,
174
+ setAPIOptions: wrappedSetAPIOptions,
175
+ };
176
+
177
+ const columnsToSortParams = {};
178
+ Object.keys(columns).forEach((key) => {
179
+ if (columns[key].isSorted) {
180
+ columnsToSortParams[columns[key].title] = key;
181
+ }
182
+ });
183
+
184
+ const { setParamsAndAPI, params } = useSetParamsAndApiAndSearch({
185
+ defaultParams,
186
+ apiOptions,
187
+ setAPIOptions: wrappedSetAPIOptions,
188
+ });
189
+
190
+ const onSort = (_event, index, direction) => {
191
+ setParamsAndAPI({
192
+ ...params,
193
+ page: urlPage ? Number(urlPage) : params.page,
194
+ per_page: urlPerPage ? Number(urlPerPage) : params.per_page,
195
+ search: currentSearchQuery,
196
+ order: `${Object.keys(columns)[index]} ${direction}`,
197
+ });
198
+ };
199
+
200
+ const { pfSortParams } = useTableSort({
201
+ allColumns: Object.keys(columns).map(k => columns[k].title),
202
+ columnsToSortParams,
203
+ onSort,
204
+ });
205
+
206
+ const {
207
+ response: {
208
+ results = [],
209
+ subtotal,
210
+ message: errorMessage,
211
+ },
212
+ status = STATUS.PENDING,
213
+ } = response;
214
+
215
+ const [columnNamesKeys, keysToColumnNames] = getColumnHelpers(columns);
216
+ const onPagination = (newPagination) => {
217
+ setParamsAndAPI({
218
+ ...params,
219
+ search: currentSearchQuery,
220
+ ...newPagination,
221
+ });
222
+ };
223
+
224
+ return (
225
+ <TableIndexPage
226
+ apiUrl={SYNCED_CONTAINER_IMAGES_API_PATH}
227
+ apiOptions={apiOptions}
228
+ replacementResponse={response}
229
+ creatable={false}
230
+ isDeleteable={false}
231
+ customSearchProps={{
232
+ autocomplete: {
233
+ url: `${SYNCED_CONTAINER_IMAGES_API_PATH}/auto_complete_search`,
234
+ apiParams: { organization_id: orgId() },
235
+ },
236
+ controller: 'katello_docker_tags',
237
+ bookmarks: {
238
+ url: '/api/bookmarks',
239
+ canCreate: true,
240
+ },
241
+ }}
242
+ ouiaId="synced-container-images-table-index"
243
+ >
244
+ <>
245
+ <Table variant="compact" ouiaId="synced-container-images-table">
246
+ <Thead>
247
+ <Tr ouiaId="table-header">
248
+ <Th />
249
+ {columnNamesKeys.map(k => (
250
+ <Th
251
+ key={k}
252
+ width={columns[k].width}
253
+ sort={
254
+ Object.values(columnsToSortParams).includes(k) &&
255
+ pfSortParams(keysToColumnNames[k])
256
+ }
257
+ >
258
+ {keysToColumnNames[k]}
259
+ </Th>
260
+ ))}
261
+ </Tr>
262
+ </Thead>
263
+ <TableEmptyState
264
+ status={status}
265
+ results={results}
266
+ errorMessage={errorMessage}
267
+ />
268
+ {results?.map((tag, rowIndex) => {
269
+ const { id, manifest } = tag;
270
+ const isExpanded = tagIsExpanded(id);
271
+ const hasChildManifests = manifest?.manifest_type === 'list' && manifest?.manifests?.length > 0;
272
+ return (
273
+ <Tbody key={`synced-container-images-body-${id}`} isExpanded={isExpanded}>
274
+ <Tr key={id} ouiaId={`table-row-${rowIndex}`}>
275
+ <Td
276
+ expand={hasChildManifests && {
277
+ rowIndex,
278
+ isExpanded,
279
+ onToggle: (_event, _rInx, isOpen) =>
280
+ expandedTags.onToggle(isOpen, id),
281
+ expandId: `synced-containers-expander-${id}`,
282
+ }}
283
+ />
284
+ {columnNamesKeys.map(k => (
285
+ <Td
286
+ key={`${id}-${keysToColumnNames[k]}`}
287
+ dataLabel={keysToColumnNames[k]}
288
+ >
289
+ {columns[k].wrapper ? columns[k].wrapper(tag) : tag[k]}
290
+ </Td>
291
+ ))}
292
+ </Tr>
293
+ {hasChildManifests && manifest.manifests.map((childManifest, childIndex) => {
294
+ const isLastChild = childIndex === manifest.manifests.length - 1;
295
+ return (
296
+ <Tr
297
+ key={childManifest.id || childIndex}
298
+ isExpanded={isExpanded}
299
+ ouiaId={`table-row-expandable-${rowIndex}-${childIndex}`}
300
+ className={`child-manifest-row ${isLastChild ? 'last-child' : ''}`}
301
+ >
302
+ <Td className="empty-cell" />
303
+ <Td className="empty-cell" />
304
+ <Td dataLabel={__('Manifest digest')}>
305
+ {childManifest.digest ? (
306
+ <Link to={`/labs/container_images/${tag.id}?manifest=${childManifest.id}`}>
307
+ {childManifest.digest}
308
+ </Link>
309
+ ) : 'N/A'}
310
+ </Td>
311
+ <Td dataLabel={__('Type')}>
312
+ {formatManifestType(childManifest)}
313
+ </Td>
314
+ <Td dataLabel={__('Product')} className="empty-cell" />
315
+ <Td dataLabel={__('Labels | Annotations')}>
316
+ {hasLabelsOrAnnotations(childManifest) ? (
317
+ <Button
318
+ variant="link"
319
+ isInline
320
+ onClick={() => openLabelsModal(childManifest)}
321
+ ouiaId="view-child-labels-annotations-button"
322
+ aria-label={__('View labels and annotations')}
323
+ >
324
+ {__('View here')}
325
+ </Button>
326
+ ) : (
327
+ <span>N/A</span>
328
+ )}
329
+ </Td>
330
+ </Tr>
331
+ );
332
+ })}
333
+ </Tbody>
334
+ );
335
+ })}
336
+ </Table>
337
+ {results.length > 0 && !errorMessage &&
338
+ <Pagination
339
+ key="table-bottom-pagination"
340
+ page={params.page}
341
+ perPage={params.per_page}
342
+ itemCount={subtotal}
343
+ onChange={onPagination}
344
+ updateParamsByUrl
345
+ />
346
+ }
347
+ <LabelsAnnotationsModal
348
+ show={showLabelsModal}
349
+ setIsOpen={setShowLabelsModal}
350
+ digest={selectedManifest?.digest || ''}
351
+ labels={selectedManifest?.labels || {}}
352
+ annotations={selectedManifest?.annotations || {}}
353
+ />
354
+ </>
355
+ </TableIndexPage>
356
+ );
357
+ };
358
+
359
+ export default SyncedContainerImagesPage;
@@ -0,0 +1,21 @@
1
+ table.pf-v5-c-table {
2
+ tr.child-manifest-row {
3
+ background-color: inherit;
4
+ border: none;
5
+
6
+ td {
7
+ padding-top: 1rem;
8
+ padding-bottom: 1rem;
9
+ border: none;
10
+ background-color: inherit;
11
+ }
12
+
13
+ &.last-child td {
14
+ border-bottom: 1px solid var(--pf-v5-global--BorderColor--100);
15
+ }
16
+
17
+ td.empty-cell {
18
+ padding: 0;
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,69 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import LabelsAnnotationsModal from '../../LabelsAnnotationsModal';
5
+
6
+ describe('LabelsAnnotationsModal', () => {
7
+ const mockSetIsOpen = jest.fn();
8
+ const defaultProps = {
9
+ show: true,
10
+ setIsOpen: mockSetIsOpen,
11
+ digest: 'sha256:abcd1234',
12
+ labels: {},
13
+ annotations: {},
14
+ };
15
+
16
+ beforeEach(() => {
17
+ jest.clearAllMocks();
18
+ });
19
+
20
+ it('renders and closes modal correctly', () => {
21
+ const { rerender } = render(<LabelsAnnotationsModal {...defaultProps} />);
22
+
23
+ expect(screen.getByText('Labels and annotations')).toBeInTheDocument();
24
+ expect(screen.getByText('sha256:abcd1234')).toBeInTheDocument();
25
+
26
+ // Close modal
27
+ const closeButton = screen.getByText('Close');
28
+ fireEvent.click(closeButton);
29
+ expect(mockSetIsOpen).toHaveBeenCalledWith(false);
30
+
31
+ // Modal hidden when show is false
32
+ rerender(<LabelsAnnotationsModal {...defaultProps} show={false} />);
33
+ expect(screen.queryByText('Labels and annotations')).not.toBeInTheDocument();
34
+ });
35
+
36
+ it('displays labels and annotations with pagination', () => {
37
+ // Test with small number of items
38
+ const labels = { app: 'myapp', env: 'prod' };
39
+ const annotations = { version: '1.0.0' };
40
+ const { rerender } = render(<LabelsAnnotationsModal
41
+ {...defaultProps}
42
+ labels={labels}
43
+ annotations={annotations}
44
+ />);
45
+
46
+ expect(screen.getByText('app=myapp')).toBeInTheDocument();
47
+ expect(screen.getByText('env=prod')).toBeInTheDocument();
48
+ expect(screen.getByText('version=1.0.0')).toBeInTheDocument();
49
+ expect(screen.getByText('3 labels and annotations')).toBeInTheDocument();
50
+
51
+ // Test with more than 10 items to trigger pagination
52
+ const manyLabels = {};
53
+ for (let i = 1; i <= 15; i += 1) {
54
+ manyLabels[`label${i}`] = `value${i}`;
55
+ }
56
+ rerender(<LabelsAnnotationsModal {...defaultProps} labels={manyLabels} />);
57
+
58
+ // Initially shows first 10 items
59
+ expect(screen.getByText('label1=value1')).toBeInTheDocument();
60
+ expect(screen.getByText('label10=value10')).toBeInTheDocument();
61
+ expect(screen.queryByText('label11=value11')).not.toBeInTheDocument();
62
+ expect(screen.getByText('Show 5 more')).toBeInTheDocument();
63
+
64
+ // Click to show all
65
+ fireEvent.click(screen.getByText('Show 5 more'));
66
+ expect(screen.getByText('label15=value15')).toBeInTheDocument();
67
+ expect(screen.queryByText('Show 5 more')).not.toBeInTheDocument();
68
+ });
69
+ });