katello 4.18.1 → 4.19.0.rc2

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 (388) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/locale/bn/katello.js +379 -109
  3. data/app/assets/javascripts/katello/locale/bn_IN/katello.js +379 -109
  4. data/app/assets/javascripts/katello/locale/ca/katello.js +379 -109
  5. data/app/assets/javascripts/katello/locale/cs/katello.js +380 -110
  6. data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +382 -112
  7. data/app/assets/javascripts/katello/locale/de/katello.js +385 -115
  8. data/app/assets/javascripts/katello/locale/de_AT/katello.js +379 -109
  9. data/app/assets/javascripts/katello/locale/de_DE/katello.js +379 -109
  10. data/app/assets/javascripts/katello/locale/el/katello.js +380 -110
  11. data/app/assets/javascripts/katello/locale/en/katello.js +380 -110
  12. data/app/assets/javascripts/katello/locale/en_GB/katello.js +379 -109
  13. data/app/assets/javascripts/katello/locale/en_US/katello.js +379 -109
  14. data/app/assets/javascripts/katello/locale/es/katello.js +383 -113
  15. data/app/assets/javascripts/katello/locale/et_EE/katello.js +379 -109
  16. data/app/assets/javascripts/katello/locale/fr/katello.js +388 -118
  17. data/app/assets/javascripts/katello/locale/gl/katello.js +379 -109
  18. data/app/assets/javascripts/katello/locale/gu/katello.js +379 -109
  19. data/app/assets/javascripts/katello/locale/he_IL/katello.js +379 -109
  20. data/app/assets/javascripts/katello/locale/hi/katello.js +379 -109
  21. data/app/assets/javascripts/katello/locale/id/katello.js +379 -109
  22. data/app/assets/javascripts/katello/locale/it/katello.js +379 -109
  23. data/app/assets/javascripts/katello/locale/ja/katello.js +388 -118
  24. data/app/assets/javascripts/katello/locale/ka/katello.js +385 -115
  25. data/app/assets/javascripts/katello/locale/kn/katello.js +379 -109
  26. data/app/assets/javascripts/katello/locale/ko/katello.js +388 -118
  27. data/app/assets/javascripts/katello/locale/ml_IN/katello.js +379 -109
  28. data/app/assets/javascripts/katello/locale/mr/katello.js +379 -109
  29. data/app/assets/javascripts/katello/locale/nl_NL/katello.js +379 -109
  30. data/app/assets/javascripts/katello/locale/or/katello.js +379 -109
  31. data/app/assets/javascripts/katello/locale/pa/katello.js +379 -109
  32. data/app/assets/javascripts/katello/locale/pl/katello.js +379 -109
  33. data/app/assets/javascripts/katello/locale/pl_PL/katello.js +379 -109
  34. data/app/assets/javascripts/katello/locale/pt/katello.js +379 -109
  35. data/app/assets/javascripts/katello/locale/pt_BR/katello.js +383 -113
  36. data/app/assets/javascripts/katello/locale/ro/katello.js +379 -109
  37. data/app/assets/javascripts/katello/locale/ro_RO/katello.js +379 -109
  38. data/app/assets/javascripts/katello/locale/ru/katello.js +381 -111
  39. data/app/assets/javascripts/katello/locale/sl/katello.js +379 -109
  40. data/app/assets/javascripts/katello/locale/sv_SE/katello.js +379 -109
  41. data/app/assets/javascripts/katello/locale/ta/katello.js +379 -109
  42. data/app/assets/javascripts/katello/locale/ta_IN/katello.js +379 -109
  43. data/app/assets/javascripts/katello/locale/te/katello.js +379 -109
  44. data/app/assets/javascripts/katello/locale/tr/katello.js +379 -109
  45. data/app/assets/javascripts/katello/locale/vi/katello.js +379 -109
  46. data/app/assets/javascripts/katello/locale/vi_VN/katello.js +379 -109
  47. data/app/assets/javascripts/katello/locale/zh/katello.js +379 -109
  48. data/app/assets/javascripts/katello/locale/zh_CN/katello.js +388 -118
  49. data/app/assets/javascripts/katello/locale/zh_TW/katello.js +381 -111
  50. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +41 -12
  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_view_filter_rules_controller.rb +1 -1
  54. data/app/controllers/katello/api/v2/content_views_controller.rb +18 -3
  55. data/app/controllers/katello/api/v2/debs_controller.rb +21 -11
  56. data/app/controllers/katello/api/v2/docker_tags_controller.rb +7 -0
  57. data/app/controllers/katello/api/v2/flatpak_remote_repositories_controller.rb +21 -19
  58. data/app/controllers/katello/api/v2/host_debs_controller.rb +16 -1
  59. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +3 -60
  60. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +10 -53
  61. data/app/controllers/katello/api/v2/repositories_controller.rb +0 -1
  62. data/app/controllers/katello/concerns/api/v2/hosts_controller_extensions.rb +10 -0
  63. data/app/controllers/katello/concerns/organizations_controller_extensions.rb +3 -0
  64. data/app/lib/actions/candlepin/activation_key/create.rb +0 -2
  65. data/app/lib/actions/candlepin/activation_key/update.rb +0 -2
  66. data/app/lib/actions/candlepin/product/content_create.rb +3 -5
  67. data/app/lib/actions/candlepin/product/content_update.rb +2 -3
  68. data/app/lib/actions/helpers/rolling_cv_repos.rb +1 -1
  69. data/app/lib/actions/katello/activation_key/create.rb +0 -1
  70. data/app/lib/actions/katello/activation_key/update.rb +0 -2
  71. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +1 -6
  72. data/app/lib/actions/katello/content_credential/update.rb +1 -1
  73. data/app/lib/actions/katello/content_view/add_rolling_repo_clone.rb +18 -24
  74. data/app/lib/actions/katello/content_view/create.rb +9 -4
  75. data/app/lib/actions/katello/content_view/refresh_rolling_repo.rb +6 -1
  76. data/app/lib/actions/katello/content_view/remove_rolling_repo_clone.rb +16 -11
  77. data/app/lib/actions/katello/content_view/update.rb +34 -7
  78. data/app/lib/actions/katello/product/content_create.rb +2 -2
  79. data/app/lib/actions/katello/product/content_destroy.rb +1 -1
  80. data/app/lib/actions/katello/repository/check_matching_content.rb +1 -1
  81. data/app/lib/actions/katello/repository/clone_contents.rb +1 -1
  82. data/app/lib/actions/katello/repository/create.rb +1 -1
  83. data/app/lib/actions/katello/repository/destroy.rb +4 -4
  84. data/app/lib/actions/katello/repository/finish_upload.rb +1 -1
  85. data/app/lib/actions/katello/repository/sync.rb +1 -1
  86. data/app/lib/actions/pulp3/orchestration/repository/copy_all_units.rb +2 -2
  87. data/app/lib/actions/pulp3/orchestration/repository/generate_metadata.rb +1 -1
  88. data/app/lib/actions/pulp3/orchestration/repository/multi_copy_all_units.rb +1 -1
  89. data/app/lib/actions/pulp3/repository/save_publication.rb +3 -1
  90. data/app/lib/actions/pulp3/repository/save_version.rb +45 -24
  91. data/app/lib/actions/pulp3/repository/save_versions.rb +2 -1
  92. data/app/lib/katello/resources/candlepin/activation_key.rb +3 -4
  93. data/app/lib/katello/resources/candlepin/upstream_job.rb +9 -1
  94. data/app/lib/katello/resources/candlepin.rb +4 -0
  95. data/app/models/katello/authorization/repository.rb +17 -4
  96. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +0 -7
  97. data/app/models/katello/content_view_deb_filter.rb +10 -0
  98. data/app/models/katello/content_view_deb_filter_rule.rb +7 -0
  99. data/app/models/katello/deb.rb +10 -10
  100. data/app/models/katello/erratum.rb +1 -1
  101. data/app/models/katello/glue/provider.rb +14 -3
  102. data/app/models/katello/host/content_facet.rb +1 -1
  103. data/app/models/katello/host/subscription_facet.rb +1 -7
  104. data/app/models/katello/product_content.rb +2 -2
  105. data/app/models/katello/repository.rb +4 -23
  106. data/app/models/katello/root_repository.rb +2 -5
  107. data/app/services/katello/candlepin/event_handler.rb +0 -33
  108. data/app/services/katello/candlepin/message_handler.rb +0 -41
  109. data/app/services/katello/content_unit_indexer.rb +59 -13
  110. data/app/services/katello/product_content_finder.rb +5 -4
  111. data/app/services/katello/pulp3/alternate_content_source.rb +2 -2
  112. data/app/services/katello/pulp3/ansible_collection.rb +1 -0
  113. data/app/services/katello/pulp3/api/content_guard.rb +5 -5
  114. data/app/services/katello/pulp3/api/core.rb +10 -0
  115. data/app/services/katello/pulp3/deb.rb +1 -0
  116. data/app/services/katello/pulp3/docker_manifest.rb +1 -0
  117. data/app/services/katello/pulp3/docker_manifest_list.rb +1 -0
  118. data/app/services/katello/pulp3/docker_tag.rb +1 -0
  119. data/app/services/katello/pulp3/file_unit.rb +1 -0
  120. data/app/services/katello/pulp3/generic_content_unit.rb +1 -0
  121. data/app/services/katello/pulp3/module_stream.rb +1 -0
  122. data/app/services/katello/pulp3/package_group.rb +1 -0
  123. data/app/services/katello/pulp3/repository/apt.rb +41 -16
  124. data/app/services/katello/pulp3/repository.rb +59 -10
  125. data/app/services/katello/pulp3/rpm.rb +3 -2
  126. data/app/services/katello/pulp3/srpm.rb +3 -2
  127. data/app/services/katello/pulp3/task_group.rb +1 -1
  128. data/app/services/katello/registration_manager.rb +19 -17
  129. data/app/services/katello/repository_type_manager.rb +7 -5
  130. data/app/services/katello/smart_proxy_helper.rb +1 -6
  131. data/app/views/foreman/job_templates/upload_profile.erb +5 -0
  132. data/app/views/katello/api/v2/activation_keys/base.json.rabl +1 -1
  133. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -0
  134. data/app/views/katello/api/v2/debs/thindex.json.rabl +6 -0
  135. data/app/views/katello/api/v2/docker_tags/_base.json.rabl +32 -0
  136. data/app/views/katello/api/v2/docker_tags/show.json.rabl +0 -5
  137. data/app/views/katello/api/v2/flatpak_remotes/index.json.rabl +6 -0
  138. data/app/views/katello/api/v2/host_debs/installed_debs.json.rabl +6 -0
  139. data/app/views/katello/api/v2/hosts_bulk_actions/applicable_errata.json.rabl +1 -1
  140. data/app/views/katello/api/v2/hosts_bulk_actions/applicable_erratum.json.rabl +9 -0
  141. data/app/views/katello/api/v2/hosts_bulk_actions/installable_errata.json.rabl +1 -1
  142. data/app/views/katello/api/v2/hosts_bulk_actions/{erratum.json.rabl → installable_erratum.json.rabl} +3 -3
  143. data/app/views/katello/api/v2/subscription_facet/base.json.rabl +1 -1
  144. data/config/initializers/monkeys.rb +1 -0
  145. data/config/routes/api/v2.rb +2 -2
  146. data/config/routes/overrides.rb +2 -7
  147. data/config/routes.rb +2 -0
  148. data/db/migrate/20211019192121_create_cdn_configuration.katello.rb +1 -1
  149. data/db/migrate/20250912000000_add_pulp_prn_fields.rb +73 -0
  150. data/db/migrate/20250912000001_populate_pulp_prn_fields.rb +403 -0
  151. data/db/migrate/20251009142516_remove_auto_attach_from_activation_keys.rb +5 -0
  152. data/db/migrate/20251009142517_remove_autoheal_from_subscription_facets.rb +5 -0
  153. data/db/seeds.d/111-upgrade_tasks.rb +2 -0
  154. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/bn.po +10 -0
  155. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/bn_IN.po +10 -0
  156. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ca.po +10 -0
  157. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/cs_CZ.po +10 -0
  158. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de.po +10 -0
  159. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de_AT.po +10 -0
  160. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de_DE.po +10 -0
  161. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/el.po +12 -2
  162. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/en_GB.po +10 -0
  163. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/en_US.po +10 -0
  164. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/es.po +10 -0
  165. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/et_EE.po +10 -0
  166. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +10 -0
  167. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/gl.po +10 -0
  168. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/gu.po +10 -0
  169. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/he_IL.po +10 -0
  170. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/hi.po +10 -0
  171. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/id.po +10 -0
  172. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/it.po +10 -0
  173. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +10 -0
  174. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ka.po +10 -0
  175. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/kn.po +10 -0
  176. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +10 -0
  177. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ml_IN.po +10 -0
  178. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/mr.po +10 -0
  179. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/nl_NL.po +10 -0
  180. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/or.po +10 -0
  181. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pa.po +10 -0
  182. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pl.po +10 -0
  183. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pl_PL.po +10 -0
  184. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt.po +10 -0
  185. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt_BR.po +10 -0
  186. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ro.po +10 -0
  187. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ro_RO.po +10 -0
  188. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ru.po +10 -0
  189. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/sl.po +10 -0
  190. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/sv_SE.po +10 -0
  191. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ta.po +10 -0
  192. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ta_IN.po +10 -0
  193. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/te.po +10 -0
  194. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/tr.po +10 -0
  195. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/vi.po +10 -0
  196. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/vi_VN.po +10 -0
  197. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh.po +10 -0
  198. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +10 -0
  199. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_TW.po +10 -0
  200. data/lib/katello/permission_creator.rb +2 -2
  201. data/lib/katello/permissions/host_permissions.rb +0 -6
  202. data/lib/katello/plugin.rb +17 -8
  203. data/lib/katello/tasks/jenkins.rake +1 -1
  204. data/lib/katello/tasks/upgrades/4.19/enable_structured_apt_for_deb.rake +87 -0
  205. data/lib/katello/tasks/upgrades/4.19/populate_repository_version_prns.rake +32 -0
  206. data/lib/katello/version.rb +1 -1
  207. data/lib/monkeys/fix_rpm_repository_gpgcheck.rb +38 -0
  208. data/locale/action_names.rb +0 -6
  209. data/locale/bn/LC_MESSAGES/katello.mo +0 -0
  210. data/locale/bn/katello.po +379 -109
  211. data/locale/bn_IN/LC_MESSAGES/katello.mo +0 -0
  212. data/locale/bn_IN/katello.po +379 -109
  213. data/locale/ca/LC_MESSAGES/katello.mo +0 -0
  214. data/locale/ca/katello.po +379 -109
  215. data/locale/cs/LC_MESSAGES/katello.mo +0 -0
  216. data/locale/cs/katello.po +380 -111
  217. data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
  218. data/locale/cs_CZ/katello.po +382 -112
  219. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  220. data/locale/de/katello.po +386 -116
  221. data/locale/de_AT/LC_MESSAGES/katello.mo +0 -0
  222. data/locale/de_AT/katello.po +379 -109
  223. data/locale/de_DE/LC_MESSAGES/katello.mo +0 -0
  224. data/locale/de_DE/katello.po +379 -109
  225. data/locale/el/LC_MESSAGES/katello.mo +0 -0
  226. data/locale/el/katello.po +381 -111
  227. data/locale/en/LC_MESSAGES/katello.mo +0 -0
  228. data/locale/en/katello.po +380 -111
  229. data/locale/en_GB/LC_MESSAGES/katello.mo +0 -0
  230. data/locale/en_GB/katello.po +379 -109
  231. data/locale/en_US/LC_MESSAGES/katello.mo +0 -0
  232. data/locale/en_US/katello.po +379 -109
  233. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  234. data/locale/es/katello.po +383 -113
  235. data/locale/et_EE/LC_MESSAGES/katello.mo +0 -0
  236. data/locale/et_EE/katello.po +379 -109
  237. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  238. data/locale/fr/katello.po +389 -119
  239. data/locale/gl/LC_MESSAGES/katello.mo +0 -0
  240. data/locale/gl/katello.po +379 -109
  241. data/locale/gu/LC_MESSAGES/katello.mo +0 -0
  242. data/locale/gu/katello.po +379 -109
  243. data/locale/he_IL/LC_MESSAGES/katello.mo +0 -0
  244. data/locale/he_IL/katello.po +379 -109
  245. data/locale/hi/LC_MESSAGES/katello.mo +0 -0
  246. data/locale/hi/katello.po +379 -109
  247. data/locale/id/LC_MESSAGES/katello.mo +0 -0
  248. data/locale/id/katello.po +379 -109
  249. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  250. data/locale/it/katello.po +379 -109
  251. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  252. data/locale/ja/katello.po +390 -119
  253. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  254. data/locale/ka/katello.po +385 -115
  255. data/locale/katello.pot +1273 -831
  256. data/locale/kn/LC_MESSAGES/katello.mo +0 -0
  257. data/locale/kn/katello.po +379 -109
  258. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  259. data/locale/ko/katello.po +389 -119
  260. data/locale/ml_IN/LC_MESSAGES/katello.mo +0 -0
  261. data/locale/ml_IN/katello.po +379 -109
  262. data/locale/mr/LC_MESSAGES/katello.mo +0 -0
  263. data/locale/mr/katello.po +379 -109
  264. data/locale/nl_NL/LC_MESSAGES/katello.mo +0 -0
  265. data/locale/nl_NL/katello.po +379 -109
  266. data/locale/or/LC_MESSAGES/katello.mo +0 -0
  267. data/locale/or/katello.po +379 -109
  268. data/locale/pa/LC_MESSAGES/katello.mo +0 -0
  269. data/locale/pa/katello.po +379 -109
  270. data/locale/pl/LC_MESSAGES/katello.mo +0 -0
  271. data/locale/pl/katello.po +379 -109
  272. data/locale/pl_PL/LC_MESSAGES/katello.mo +0 -0
  273. data/locale/pl_PL/katello.po +379 -109
  274. data/locale/pt/LC_MESSAGES/katello.mo +0 -0
  275. data/locale/pt/katello.po +379 -109
  276. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  277. data/locale/pt_BR/katello.po +383 -113
  278. data/locale/ro/LC_MESSAGES/katello.mo +0 -0
  279. data/locale/ro/katello.po +379 -109
  280. data/locale/ro_RO/LC_MESSAGES/katello.mo +0 -0
  281. data/locale/ro_RO/katello.po +379 -109
  282. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  283. data/locale/ru/katello.po +381 -111
  284. data/locale/sl/LC_MESSAGES/katello.mo +0 -0
  285. data/locale/sl/katello.po +379 -109
  286. data/locale/sv_SE/LC_MESSAGES/katello.mo +0 -0
  287. data/locale/sv_SE/katello.po +379 -109
  288. data/locale/ta/LC_MESSAGES/katello.mo +0 -0
  289. data/locale/ta/katello.po +379 -109
  290. data/locale/ta_IN/LC_MESSAGES/katello.mo +0 -0
  291. data/locale/ta_IN/katello.po +379 -109
  292. data/locale/te/LC_MESSAGES/katello.mo +0 -0
  293. data/locale/te/katello.po +379 -109
  294. data/locale/tr/LC_MESSAGES/katello.mo +0 -0
  295. data/locale/tr/katello.po +379 -109
  296. data/locale/vi/LC_MESSAGES/katello.mo +0 -0
  297. data/locale/vi/katello.po +379 -109
  298. data/locale/vi_VN/LC_MESSAGES/katello.mo +0 -0
  299. data/locale/vi_VN/katello.po +379 -109
  300. data/locale/zh/LC_MESSAGES/katello.mo +0 -0
  301. data/locale/zh/katello.po +379 -109
  302. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  303. data/locale/zh_CN/katello.po +389 -119
  304. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  305. data/locale/zh_TW/katello.po +381 -111
  306. data/webpack/ForemanColumnExtensions/index.js +46 -2
  307. data/webpack/components/Content/Details/__tests__/__snapshots__/ContentDetails.test.js.snap +2 -2
  308. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeEditModal.js +0 -2
  309. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/__tests__/SystemPurposeEditModal.test.js +0 -2
  310. data/webpack/components/extensions/Hosts/ActionsBar/index.js +1 -0
  311. data/webpack/components/extensions/Hosts/BulkActions/BulkActionsConstants.js +7 -0
  312. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/BulkChangeHostCollectionsModal.js +388 -0
  313. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/__tests__/BulkChangeHostCollectionsModal.test.js +640 -0
  314. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/actions.js +28 -0
  315. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/index.js +71 -0
  316. data/webpack/components/extensions/Hosts/BulkActions/BulkErrataWizard/02_BulkErrataTable.js +1 -1
  317. data/webpack/components/extensions/Hosts/BulkActions/BulkErrataWizard/BulkErrataWizard.js +1 -1
  318. data/webpack/components/extensions/Hosts/BulkActions/BulkPackagesWizard/02_BulkPackagesTable.js +11 -4
  319. data/webpack/components/extensions/Hosts/BulkActions/BulkPackagesWizard/BulkPackagesWizard.js +51 -24
  320. data/webpack/components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/01_BulkRepositorySetsTable.js +1 -1
  321. data/webpack/components/extensions/Hosts/BulkActions/HostReview.js +8 -1
  322. data/webpack/containers/Application/config.js +11 -1
  323. data/webpack/global_index.js +3 -0
  324. data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/BootedContainerImagesConstants.js +1 -1
  325. data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/BootedContainerImagesPage.js +7 -43
  326. data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/__tests__/bootedContainerImagesPage.test.js +1 -1
  327. data/webpack/scenes/ContainerImages/ContainerImagesPage.js +86 -0
  328. data/webpack/scenes/ContainerImages/LabelsAnnotationsModal.js +105 -0
  329. data/webpack/scenes/ContainerImages/Synced/Details/ManifestDetails.js +218 -0
  330. data/webpack/scenes/ContainerImages/Synced/Details/ManifestDetailsActions.js +15 -0
  331. data/webpack/scenes/ContainerImages/Synced/Details/ManifestDetailsSelectors.js +16 -0
  332. data/webpack/scenes/ContainerImages/Synced/Details/__tests__/ManifestDetails.test.js +395 -0
  333. data/webpack/scenes/ContainerImages/Synced/Details/__tests__/manifestDetails.fixtures.json +43 -0
  334. data/webpack/scenes/ContainerImages/Synced/Details/__tests__/manifestList.fixtures.json +58 -0
  335. data/webpack/scenes/ContainerImages/Synced/Details/index.js +4 -0
  336. data/webpack/scenes/ContainerImages/Synced/SyncedContainerImagesPage.js +359 -0
  337. data/webpack/scenes/ContainerImages/Synced/SyncedContainerImagesPage.scss +21 -0
  338. data/webpack/scenes/ContainerImages/Synced/__tests__/LabelsAnnotationsModal.test.js +69 -0
  339. data/webpack/scenes/ContainerImages/Synced/__tests__/SyncedContainerImagesPage.test.js +335 -0
  340. data/webpack/scenes/ContainerImages/Synced/__tests__/syncedContainerImages.fixtures.json +105 -0
  341. data/webpack/scenes/ContainerImages/TableEmptyState.js +67 -0
  342. data/webpack/scenes/ContainerImages/containerImagesHelpers.js +48 -0
  343. data/webpack/scenes/ContainerImages/index.js +4 -0
  344. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +29 -3
  345. data/webpack/scenes/ContentViews/Create/__tests__/contentViewCreateResult.fixtures.json +1 -0
  346. data/webpack/scenes/ContentViews/Create/__tests__/createContentView.test.js +45 -1
  347. data/webpack/scenes/ContentViews/Delete/__tests__/affectedHosts.fixtures.json +0 -1
  348. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +59 -1
  349. data/webpack/scenes/ContentViews/Details/Filters/CVDebFilterContent.js +1 -0
  350. data/webpack/scenes/ContentViews/Details/Filters/Rules/DebPackage/AddEditDebPackageRuleModal.js +164 -24
  351. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVDebFilterContent.test.js +268 -0
  352. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvDebFilterDetail.fixtures.json +95 -0
  353. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvDebFilterRules.fixtures.json +31 -0
  354. data/webpack/scenes/ContentViews/Details/Filters/__tests__/emptyCVDebFilterRules.fixtures.json +10 -0
  355. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/hosts.fixtures.json +0 -1
  356. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvAffectedHosts.fixture.json +0 -1
  357. data/webpack/scenes/ContentViews/Details/__tests__/contentViewRollingDetail.test.js +15 -0
  358. data/webpack/scenes/ContentViews/Details/__tests__/contentViewRollingDetails.fixtures.json +1 -0
  359. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +9 -0
  360. data/webpack/scenes/FlatpakRemotes/CreateEdit/CreateFlatpakRemoteModal.js +5 -3
  361. data/webpack/scenes/FlatpakRemotes/CreateEdit/EditFlatpakRemotesModal.js +1 -1
  362. data/webpack/scenes/FlatpakRemotes/CreateEdit/FlatpakRemoteform.js +35 -3
  363. data/webpack/scenes/FlatpakRemotes/Details/FlatpakRemoteDetails.js +1 -1
  364. data/webpack/scenes/FlatpakRemotes/Details/RemoteRepositories/RemoteRepositoriesTable.css +3 -0
  365. data/webpack/scenes/FlatpakRemotes/Details/RemoteRepositories/RemoteRepositoriesTable.js +63 -132
  366. data/webpack/scenes/FlatpakRemotes/FlatpakRemotesPage.js +67 -143
  367. data/webpack/scenes/SmartProxy/ExpandableCvDetails.js +10 -2
  368. data/webpack/scenes/SmartProxy/SmartProxyContentActions.js +13 -2
  369. data/webpack/scenes/SmartProxy/SmartProxyContentConstants.js +1 -0
  370. data/webpack/scenes/SmartProxy/SmartProxyExpandableTable.js +8 -2
  371. data/webpack/scenes/SmartProxy/__tests__/SmartProxyContentTest.js +67 -1
  372. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +2 -2
  373. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +0 -2
  374. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +15 -5
  375. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +22 -5
  376. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +141 -0
  377. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +2 -2
  378. metadata +82 -56
  379. data/app/lib/actions/katello/host/attach_subscriptions.rb +0 -59
  380. data/app/lib/actions/katello/host/auto_attach_subscriptions.rb +0 -22
  381. data/app/lib/actions/katello/host/remove_subscriptions.rb +0 -50
  382. data/app/lib/actions/katello/organization/simple_content_access/disable.rb +0 -25
  383. data/app/lib/actions/katello/organization/simple_content_access/enable.rb +0 -25
  384. data/app/lib/actions/katello/organization/simple_content_access/toggle.rb +0 -42
  385. data/lib/katello/tasks/migrate_structure_content_for_deb.rake +0 -105
  386. data/lib/katello/tasks/upgrades/4.2/remove_checksum_values.rake +0 -17
  387. /data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/__tests__/bootedContainerImages.fixtures.js +0 -0
  388. /data/webpack/scenes/{BootedContainerImages → ContainerImages/Booted}/index.js +0 -0
@@ -0,0 +1,268 @@
1
+ import React from 'react';
2
+ import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
3
+ import { screen, within } from '@testing-library/react';
4
+ import { Route } from 'react-router-dom';
5
+
6
+ import ContentViewFilterDetails from '../ContentViewFilterDetails';
7
+ import { cvFilterDetailsKey } from '../../../ContentViewsConstants';
8
+ import { nockInstance, assertNockRequest, mockAutocomplete } from '../../../../../test-utils/nockWrapper';
9
+ import api from '../../../../../services/api';
10
+
11
+ import cvDebFilterDetails from './cvDebFilterDetail.fixtures.json';
12
+ import cvDebFilterRules from './cvDebFilterRules.fixtures.json';
13
+ import cvFilterFixtures from './contentViewFilters.fixtures.json';
14
+ import details from '../../../__tests__/mockDetails.fixtures.json';
15
+ import emptyDebFilterRules from './emptyCVDebFilterRules.fixtures.json';
16
+
17
+ const cvFiltersPath = api.getApiUrl('/content_view_filters');
18
+ const cvFilterDetailsPath = api.getApiUrl('/content_view_filters/42');
19
+ const cvDebFilterRulesPath = api.getApiUrl('/content_view_filters/42/rules');
20
+ // const cvDebFilterRulesNew = api.getApiUrl('/content_view_filters/42/rules');
21
+ const cvDebFilterRulesDel = api.getApiUrl('/content_view_filters/42/rules/99');
22
+ const cvDebFilterRulesEdit = api.getApiUrl('/content_view_filters/42/rules/100');
23
+
24
+ const acRulesUrl = '/content_view_filters/42/rules/auto_complete_search';
25
+ const acNameUrl = '/debs/auto_complete_name';
26
+ const acArchUrl = '/debs/auto_complete_arch';
27
+
28
+ const acRulesQuery = { organization_id: 1, search: '' };
29
+ const acBlankTermQuery = { organization_id: 1, term: '' };
30
+
31
+ const renderOptions = {
32
+ apiNamespace: cvFilterDetailsKey(1, 42),
33
+ routerParams: {
34
+ initialEntries: [{ pathname: '/content_views/1#/filters/42', hash: '#/filters' }],
35
+ initialIndex: 1,
36
+ },
37
+ };
38
+
39
+ const withCVRoute = c => (
40
+ <Route path="/content_views/:id([0-9]+)#/filters/:filterId([0-9]+)">{c}</Route>
41
+ );
42
+
43
+ test('Can show filter details on Deb rules', async () => {
44
+ const { name: filterName } = cvDebFilterDetails;
45
+
46
+ const cvFilterDetailsScope = nockInstance
47
+ .get(cvFilterDetailsPath)
48
+ .query(true)
49
+ .reply(200, cvDebFilterDetails);
50
+ const cvFiltersScope = nockInstance
51
+ .get(cvFiltersPath).query(true).reply(200, cvFilterFixtures)
52
+ .persist();
53
+ const cvDebRulesScope = nockInstance
54
+ .get(cvDebFilterRulesPath).query(true)
55
+ .reply(200, cvDebFilterRules);
56
+
57
+ const acRulesScope = mockAutocomplete(nockInstance, acRulesUrl, acRulesQuery);
58
+
59
+ const { getByText, queryByText } = renderWithRedux(
60
+ withCVRoute(<ContentViewFilterDetails cvId={1} details={details} />),
61
+ renderOptions,
62
+ );
63
+
64
+ expect(queryByText(filterName)).toBeNull();
65
+ await patientlyWaitFor(() => expect(getByText(filterName)).toBeInTheDocument());
66
+
67
+ assertNockRequest(acRulesScope);
68
+ assertNockRequest(cvFilterDetailsScope);
69
+ assertNockRequest(cvFiltersScope);
70
+ assertNockRequest(cvDebRulesScope);
71
+ });
72
+
73
+ test('Can search for Deb rules in filter details', async () => {
74
+ const lastRule = cvDebFilterRules.results[1];
75
+ const rulesSearchQuery = {
76
+ organization_id: 1,
77
+ search: `name = ${lastRule.name}`,
78
+ };
79
+
80
+ const rulesSearchResults = [
81
+ {
82
+ completed: `name = ${lastRule.name}`,
83
+ part: 'and',
84
+ label: `name = ${lastRule.name} and`,
85
+ category: 'Operators',
86
+ },
87
+ {
88
+ completed: `name = ${lastRule.name}`,
89
+ part: 'or',
90
+ label: `name = ${lastRule.name} or`,
91
+ category: 'Operators',
92
+ },
93
+ ];
94
+
95
+ const cvFilterDetailsScope = nockInstance
96
+ .get(cvFilterDetailsPath).query(true)
97
+ .reply(200, cvDebFilterDetails);
98
+
99
+ nockInstance.get(cvFiltersPath).query(true).reply(200, cvFilterFixtures);
100
+
101
+ const cvDebRulesScope = nockInstance
102
+ .get(cvDebFilterRulesPath).query(true)
103
+ .reply(200, cvDebFilterRules);
104
+
105
+ const ruleSearchScope = nockInstance
106
+ .get(cvDebFilterRulesPath).query(rulesSearchQuery)
107
+ .reply(200, { results: [lastRule] });
108
+
109
+ const acRulesScope = mockAutocomplete(nockInstance, acRulesUrl, acRulesQuery);
110
+ const acRulesSearch = mockAutocomplete(
111
+ nockInstance,
112
+ acRulesUrl,
113
+ rulesSearchQuery,
114
+ rulesSearchResults,
115
+ );
116
+
117
+ const { getByText, getByLabelText } = renderWithRedux(
118
+ withCVRoute(<ContentViewFilterDetails cvId={1} details={details} />),
119
+ renderOptions,
120
+ );
121
+
122
+ await patientlyWaitFor(() => expect(getByText(lastRule.name)).toBeInTheDocument());
123
+
124
+ fireEvent.change(getByLabelText('Search input'), {
125
+ target: { value: `name = ${lastRule.name}` },
126
+ });
127
+ fireEvent.keyDown(getByLabelText('Search input'), {
128
+ key: 'Enter',
129
+ code: 'Enter',
130
+ charCode: 13,
131
+ });
132
+
133
+ await patientlyWaitFor(() => {
134
+ expect(getByText(lastRule.name)).toBeInTheDocument();
135
+ });
136
+
137
+ assertNockRequest(acRulesScope);
138
+ assertNockRequest(acRulesSearch);
139
+ assertNockRequest(ruleSearchScope);
140
+ assertNockRequest(cvFilterDetailsScope);
141
+ assertNockRequest(cvDebRulesScope);
142
+ });
143
+
144
+ test('Remove deb filter rule in a self-closing modal', async () => {
145
+ const { name: filterName } = cvDebFilterDetails;
146
+
147
+ const acRulesScope = mockAutocomplete(nockInstance, acRulesUrl, acRulesQuery);
148
+ const acNameScope = mockAutocomplete(nockInstance, acNameUrl, acBlankTermQuery).persist();
149
+ const acArchScope = mockAutocomplete(nockInstance, acArchUrl, acBlankTermQuery).persist();
150
+
151
+ const cvFiltersScope = nockInstance
152
+ .get(cvFiltersPath).query(true).reply(200, cvFilterFixtures);
153
+ const cvDetailsScope = nockInstance
154
+ .get(cvFilterDetailsPath).query(true).reply(200, cvDebFilterDetails);
155
+ const cvDebRulesScope = nockInstance
156
+ .get(cvDebFilterRulesPath).times(2).query(true).reply(200, cvDebFilterRules);
157
+
158
+ const removeScope = nockInstance
159
+ .delete(cvDebFilterRulesDel)
160
+ .reply(201, {});
161
+
162
+ const { getByText, queryByText, getAllByLabelText } =
163
+ renderWithRedux(
164
+ withCVRoute(<ContentViewFilterDetails cvId={1} details={details} />),
165
+ renderOptions,
166
+ );
167
+
168
+ expect(queryByText(filterName)).toBeNull();
169
+ await patientlyWaitFor(() => {
170
+ expect(getByText(filterName)).toBeInTheDocument();
171
+ expect(getAllByLabelText('Kebab toggle')[0]).toBeInTheDocument();
172
+ });
173
+
174
+ getAllByLabelText('Kebab toggle')[0].click();
175
+ await patientlyWaitFor(() => expect(getByText('Remove')).toBeInTheDocument());
176
+ getByText('Remove').click();
177
+
178
+ await patientlyWaitFor(() => {
179
+ expect(getByText(filterName)).toBeInTheDocument();
180
+ expect(getAllByLabelText('Kebab toggle')[1]).toBeInTheDocument();
181
+ });
182
+
183
+ assertNockRequest(acRulesScope);
184
+ assertNockRequest(acNameScope);
185
+ assertNockRequest(acArchScope);
186
+ assertNockRequest(cvFiltersScope);
187
+ assertNockRequest(cvDetailsScope);
188
+ assertNockRequest(cvDebRulesScope);
189
+ assertNockRequest(removeScope);
190
+ });
191
+
192
+ test('Edit deb filter rule in a self-closing modal', async () => {
193
+ const { name: filterName } = cvDebFilterDetails;
194
+
195
+ const acRulesScope = mockAutocomplete(nockInstance, acRulesUrl, true, undefined, 2);
196
+ const acNameScope = mockAutocomplete(nockInstance, acNameUrl, true, undefined, 2).persist();
197
+ const acArchScope = mockAutocomplete(nockInstance, acArchUrl, true, undefined, 2).persist();
198
+
199
+ nockInstance.get(cvFiltersPath).times(2).query(true).reply(200, cvFilterFixtures);
200
+ nockInstance.get(cvFilterDetailsPath).times(2).query(true).reply(200, cvDebFilterDetails);
201
+ nockInstance.persist().get(cvDebFilterRulesPath).query(true).reply(200, cvDebFilterRules);
202
+
203
+ const editScope = nockInstance.put(cvDebFilterRulesEdit).query(true).reply(201, {});
204
+
205
+ const { getByText, getByLabelText, queryByText } =
206
+ renderWithRedux(
207
+ withCVRoute(<ContentViewFilterDetails cvId={1} details={details} />),
208
+ renderOptions,
209
+ );
210
+
211
+ await patientlyWaitFor(() => expect(getByText(filterName)).toBeInTheDocument());
212
+ const table = await screen.findByLabelText('Content View Table');
213
+ const unoRow = within(table).getByText('uno').closest('tr');
214
+ const kebabBtn = within(unoRow).getByLabelText('Kebab toggle');
215
+ fireEvent.click(kebabBtn);
216
+
217
+ await patientlyWaitFor(() => expect(getByText('Edit')).toBeInTheDocument());
218
+ fireEvent.click(getByText('Edit'));
219
+
220
+ await patientlyWaitFor(() => expect(getByText('Edit DEB rule')).toBeInTheDocument());
221
+ fireEvent.submit(getByLabelText('add_deb_package_filter_rule'));
222
+
223
+ await patientlyWaitFor(() => {
224
+ expect(queryByText('Edit DEB rule')).not.toBeInTheDocument();
225
+ expect(getByText(filterName)).toBeInTheDocument();
226
+ });
227
+
228
+ assertNockRequest(acRulesScope);
229
+ assertNockRequest(acNameScope);
230
+ assertNockRequest(acArchScope);
231
+ assertNockRequest(editScope);
232
+ });
233
+
234
+ test('Shows call-to-action when there are no DEB filters', async () => {
235
+ const acRulesScope = mockAutocomplete(nockInstance, acRulesUrl);
236
+ const acNameScope = mockAutocomplete(nockInstance, acNameUrl);
237
+ const acArchScope = mockAutocomplete(nockInstance, acArchUrl);
238
+
239
+ nockInstance.get(cvFiltersPath).query(true).reply(200, cvFilterFixtures);
240
+ const cvFilterDetailsScope = nockInstance
241
+ .get(cvFilterDetailsPath).query(true).reply(200, cvDebFilterDetails);
242
+ const cvDebRulesScope = nockInstance
243
+ .get(cvDebFilterRulesPath).query(true).reply(200, emptyDebFilterRules);
244
+
245
+ const { queryByLabelText, queryByText, getAllByLabelText } =
246
+ renderWithRedux(
247
+ withCVRoute(<ContentViewFilterDetails cvId={1} details={details} />),
248
+ renderOptions,
249
+ );
250
+
251
+ await patientlyWaitFor(() => expect(queryByLabelText('create_deb_rule')).toBeInTheDocument());
252
+ fireEvent.click(queryByLabelText('create_deb_rule'));
253
+
254
+ await patientlyWaitFor(() => {
255
+ expect(getAllByLabelText('Search input')[0]).toBeInTheDocument();
256
+ expect(queryByText('Cancel')).toBeInTheDocument();
257
+ });
258
+
259
+ fireEvent.click(queryByText('Cancel'));
260
+ await patientlyWaitFor(() =>
261
+ expect(queryByLabelText('add-edit-package-modal-cancel')).not.toBeInTheDocument());
262
+
263
+ assertNockRequest(acRulesScope);
264
+ assertNockRequest(acNameScope);
265
+ assertNockRequest(acArchScope);
266
+ assertNockRequest(cvFilterDetailsScope);
267
+ assertNockRequest(cvDebRulesScope);
268
+ });
@@ -0,0 +1,95 @@
1
+ {
2
+ "inclusion": true,
3
+ "original_packages": false,
4
+ "id": 42,
5
+ "name": "test_deb_filter",
6
+ "description": null,
7
+ "created_at": "2025-07-28 12:00:00 -0400",
8
+ "updated_at": "2025-07-28 12:00:00 -0400",
9
+ "content_view": {
10
+ "composite": false,
11
+ "rolling": false,
12
+ "component_ids": [],
13
+ "default": false,
14
+ "version_count": 1,
15
+ "latest_version": "1.0",
16
+ "auto_publish": false,
17
+ "solve_dependencies": false,
18
+ "import_only": false,
19
+ "repository_ids": [ 11 ],
20
+ "id": 7,
21
+ "name": "Debian-CV",
22
+ "label": "Debian_CV",
23
+ "description": "",
24
+ "organization_id": 1,
25
+ "organization": {
26
+ "name": "Default Organization",
27
+ "label": "Default_Organization",
28
+ "id": 1
29
+ },
30
+ "created_at": "2025-07-28 11:50:00 -0400",
31
+ "updated_at": "2025-07-28 11:50:00 -0400",
32
+ "environments": [
33
+ {
34
+ "id": 1,
35
+ "name": "Library",
36
+ "label": "Library",
37
+ "permissions": {
38
+ "readable": true
39
+ }
40
+ }
41
+ ],
42
+ "repositories": [
43
+ {
44
+ "id": 11,
45
+ "name": "debian_10_amd64",
46
+ "label": "debian_10_amd64",
47
+ "content_type": "deb",
48
+ "product": {
49
+ "id": 5,
50
+ "name": "Debian 10"
51
+ },
52
+ "content_counts": {
53
+ "deb": 8,
54
+ "package": 8,
55
+ "package_group": 0,
56
+ "erratum": 0,
57
+ "module_stream": 0
58
+ }
59
+ }
60
+ ],
61
+ "versions": [
62
+ {
63
+ "id": 31,
64
+ "version": "1.0",
65
+ "published": "2025-07-28 11:55:00 -0400",
66
+ "environment_ids": []
67
+ }
68
+ ],
69
+ "components": [],
70
+ "content_view_components": [],
71
+ "activation_keys": [],
72
+ "next_version": "2.0",
73
+ "last_published": "2025-07-28 11:55:00 -0400",
74
+ "permissions": {
75
+ "view_content_views": true,
76
+ "edit_content_views": true,
77
+ "destroy_content_views": true,
78
+ "publish_content_views": true,
79
+ "promote_or_remove_content_views": true
80
+ }
81
+ },
82
+ "repositories": [],
83
+ "type": "deb",
84
+ "rules": [
85
+ {
86
+ "content_view_filter_id": 42,
87
+ "min_version": "1.0",
88
+ "architecture": "amd64",
89
+ "id": 99,
90
+ "name": "tre",
91
+ "created_at": "2025-07-28 12:01:00 -0400",
92
+ "updated_at": "2025-07-28 12:01:00 -0400"
93
+ }
94
+ ]
95
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "total": 2,
3
+ "subtotal": 2,
4
+ "page": "1",
5
+ "per_page": "20",
6
+ "error": null,
7
+ "search": null,
8
+ "sort": {
9
+ "by": "id",
10
+ "order": "asc"
11
+ },
12
+ "results": [
13
+ {
14
+ "content_view_filter_id": 42,
15
+ "min_version": "1.0",
16
+ "architecture": "amd64",
17
+ "id": 99,
18
+ "name": "tre",
19
+ "created_at": "2025-07-28 12:01:00 -0400",
20
+ "updated_at": "2025-07-28 12:01:00 -0400"
21
+ },
22
+ {
23
+ "content_view_filter_id": 42,
24
+ "architecture": "amd64",
25
+ "id": 100,
26
+ "name": "uno",
27
+ "created_at": "2025-07-28 12:02:00 -0400",
28
+ "updated_at": "2025-07-28 12:02:00 -0400"
29
+ }
30
+ ]
31
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "total": 0,
3
+ "subtotal": 0,
4
+ "page": "1",
5
+ "per_page": "20",
6
+ "error": null,
7
+ "search": null,
8
+ "sort": { "by": "id", "order": "asc" },
9
+ "results": []
10
+ }
@@ -132,7 +132,6 @@
132
132
  "last_checkin": "2022-02-15 14:49:39 -0700",
133
133
  "service_level": "",
134
134
  "release_version": null,
135
- "autoheal": true,
136
135
  "registered_at": "2022-01-11 15:17:54 -0700",
137
136
  "registered_through": "steve8.satellite.lab.eng.rdu2.redhat.com",
138
137
  "purpose_role": "",
@@ -126,7 +126,6 @@
126
126
  "last_checkin": "2021-09-16 10:59:32 -0400",
127
127
  "service_level": "",
128
128
  "release_version": null,
129
- "autoheal": true,
130
129
  "registered_at": "2021-09-13 12:53:31 -0400",
131
130
  "registered_through": "centos7-devel4.samir.example.com",
132
131
  "purpose_role": "",
@@ -6,6 +6,7 @@ import api from '../../../../services/api';
6
6
  import ContentViewDetails from '../ContentViewDetails';
7
7
  import CONTENT_VIEWS_KEY from '../../ContentViewsConstants';
8
8
  import cvDetailData from './contentViewRollingDetails.fixtures.json';
9
+ import environmentPathsData from '../../Publish/__tests__/environmentPaths.fixtures.json';
9
10
 
10
11
 
11
12
  const withCVRoute = component => <Route path="/content_views/:id([0-9]+)">{component}</Route>;
@@ -19,6 +20,19 @@ const renderOptions = {
19
20
  };
20
21
 
21
22
  const cvDetailsPath = api.getApiUrl('/content_views/1');
23
+ const environmentPathsPath = api.getApiUrl('/organizations/1/environments/paths');
24
+ let envScope;
25
+
26
+ beforeEach(() => {
27
+ envScope = nockInstance
28
+ .get(environmentPathsPath)
29
+ .query(true)
30
+ .reply(200, environmentPathsData);
31
+ });
32
+
33
+ afterEach(() => {
34
+ assertNockRequest(envScope);
35
+ });
22
36
 
23
37
  test('Can call API and show details on page load', async (done) => {
24
38
  const { label, name, description } = cvDetailData;
@@ -104,6 +118,7 @@ test('Page contains Rolling CV type', async (done) => {
104
118
  await patientlyWaitFor(() => {
105
119
  expect(queryByText('Content view')).not.toBeInTheDocument();
106
120
  expect(queryByText('Rolling content view')).toBeInTheDocument();
121
+ expect(queryByText('Lifecycle Environments')).toBeInTheDocument();
107
122
  expect(queryByText('Composite content view')).not.toBeInTheDocument();
108
123
  expect(queryByText('Versions')).not.toBeInTheDocument();
109
124
  expect(queryByText('Filters')).not.toBeInTheDocument();
@@ -8,6 +8,7 @@
8
8
  "latest_version": "1.0",
9
9
  "auto_publish": false,
10
10
  "solve_dependencies": false,
11
+ "environment_ids": [1],
11
12
  "needs_publish": false,
12
13
  "generated_for": "none",
13
14
  "repository_ids": [
@@ -10,9 +10,11 @@ import {
10
10
  } from '../../../test-utils/nockWrapper';
11
11
  import createBasicCVs from './basicContentViews.fixtures';
12
12
  import cvIndexData from './contentViewList.fixtures.json';
13
+ import environmentPathsData from '../Publish/__tests__/environmentPaths.fixtures.json';
13
14
 
14
15
  const cvIndexPath = api.getApiUrl('/content_views');
15
16
  const autocompleteUrl = '/content_views/auto_complete_search';
17
+ const environmentPathsPath = api.getApiUrl('/organizations/1/environments/paths');
16
18
  const renderOptions = { apiNamespace: CONTENT_VIEWS_KEY };
17
19
  const autocompleteQuery = {
18
20
  organization_id: 1,
@@ -409,6 +411,10 @@ test('Displays Create Content View and opens modal with Form', async () => {
409
411
  .get(cvIndexPath)
410
412
  .query(true)
411
413
  .reply(200, noResults);
414
+ const scope = nockInstance
415
+ .get(environmentPathsPath)
416
+ .query(true)
417
+ .reply(200, environmentPathsData);
412
418
  const {
413
419
  getByText, queryByText, getByLabelText,
414
420
  } = renderWithRedux(<ContentViewsPage />, renderOptions);
@@ -421,6 +427,7 @@ test('Displays Create Content View and opens modal with Form', async () => {
421
427
  expect(queryByText('Content view')).not.toBeInTheDocument();
422
428
  expect(queryByText('Solve dependencies')).not.toBeInTheDocument();
423
429
  expect(queryByText('Auto publish')).not.toBeInTheDocument();
430
+ expect(queryByText('Lifecycle Environments')).not.toBeInTheDocument();
424
431
 
425
432
  getByLabelText('create_content_view').click();
426
433
 
@@ -432,6 +439,8 @@ test('Displays Create Content View and opens modal with Form', async () => {
432
439
  expect(getByText('Content view')).toBeInTheDocument();
433
440
  expect(getByText('Solve dependencies')).toBeInTheDocument();
434
441
  expect(queryByText('Auto publish')).not.toBeInTheDocument();
442
+ expect(queryByText('Lifecycle Environments')).not.toBeInTheDocument();
443
+ assertNockRequest(scope);
435
444
  });
436
445
 
437
446
  /* eslint-enable no-useless-escape */
@@ -4,27 +4,29 @@ import { translate as __ } from 'foremanReact/common/I18n';
4
4
  import { Modal, ModalVariant } from '@patternfly/react-core';
5
5
  import FlatpakRemotesForm from './FlatpakRemoteform';
6
6
 
7
- const CreateFlatpakModal = ({ show, setIsOpen }) => (
7
+ const CreateFlatpakModal = ({ show, setIsOpen, hasRedhatRemote }) => (
8
8
  <Modal
9
9
  ouiaId="create-flatpak-modal"
10
10
  title={__('Create Flatpak Remote')}
11
- variant={ModalVariant.small}
11
+ variant={ModalVariant.medium}
12
12
  isOpen={show}
13
13
  onClose={() => { setIsOpen(false); }}
14
14
  appendTo={document.body}
15
15
  >
16
- <FlatpakRemotesForm setModalOpen={setIsOpen} />
16
+ <FlatpakRemotesForm setModalOpen={setIsOpen} hasRedhatRemote={hasRedhatRemote} />
17
17
  </Modal>
18
18
  );
19
19
 
20
20
  CreateFlatpakModal.propTypes = {
21
21
  show: PropTypes.bool,
22
22
  setIsOpen: PropTypes.func,
23
+ hasRedhatRemote: PropTypes.bool,
23
24
  };
24
25
 
25
26
  CreateFlatpakModal.defaultProps = {
26
27
  show: false,
27
28
  setIsOpen: null,
29
+ hasRedhatRemote: true,
28
30
  };
29
31
 
30
32
  export default CreateFlatpakModal;
@@ -8,7 +8,7 @@ const EditFlatpakModal = ({ show, setIsOpen, remoteData }) => (
8
8
  <Modal
9
9
  ouiaId="edit-flatpak-modal"
10
10
  title={__('Edit Flatpak Remote')}
11
- variant={ModalVariant.small}
11
+ variant={ModalVariant.medium}
12
12
  isOpen={show}
13
13
  onClose={() => { setIsOpen(false); }}
14
14
  appendTo={document.body}
@@ -13,8 +13,12 @@ import {
13
13
  FormHelperText,
14
14
  HelperText,
15
15
  HelperTextItem,
16
-
16
+ Alert,
17
+ AlertActionCloseButton,
18
+ AlertActionLink,
19
+ TextContent,
17
20
  } from '@patternfly/react-core';
21
+ import { ExternalLinkAltIcon } from '@patternfly/react-icons';
18
22
  import { createFlatpakRemote } from '../FlatpakRemotesActions';
19
23
  import {
20
24
  selectCreateFlatpakRemotes,
@@ -24,7 +28,7 @@ import {
24
28
  import { updateFlatpakRemote } from '../Details/FlatpakRemoteDetailActions';
25
29
 
26
30
  // eslint-disable-next-line react/prop-types
27
- const FlatpakRemotesForm = ({ setModalOpen, remoteData }) => {
31
+ const FlatpakRemotesForm = ({ setModalOpen, remoteData, hasRedhatRemote }) => {
28
32
  const {
29
33
  id: editingId,
30
34
  name: editingName,
@@ -42,6 +46,7 @@ const FlatpakRemotesForm = ({ setModalOpen, remoteData }) => {
42
46
  const [redirect, setRedirect] = useState(false);
43
47
  const [saving, setSaving] = useState(false);
44
48
 
49
+ const [alertDismissed, setAlertDismissed] = useState(false);
45
50
  const [urlValidated, setUrlValidated] = useState('default');
46
51
  const handleUrlChange = (newurl, _event) => {
47
52
  setUrl(newurl);
@@ -114,6 +119,29 @@ const FlatpakRemotesForm = ({ setModalOpen, remoteData }) => {
114
119
  }}
115
120
  id="create-flatpak-form"
116
121
  >
122
+ {!alertDismissed && !hasRedhatRemote && (
123
+ <Alert
124
+ ouiaId="flatpak-remote-info-alert"
125
+ isInline
126
+ title={__('Add Red Hat Flatpak remote')}
127
+ actionClose={<AlertActionCloseButton onClose={() => setAlertDismissed(true)} />}
128
+ actionLinks={
129
+ <React.Fragment>
130
+ <AlertActionLink onClick={() => setUrl('https://flatpaks.redhat.io/rhel')}>
131
+ {__('Add Red Hat flatpak remote')}
132
+ </AlertActionLink>
133
+ <AlertActionLink component="a" href="https://access.redhat.com/terms-based-registry/" target="_blank">
134
+ {__('Generate username and password')} <ExternalLinkAltIcon />
135
+ </AlertActionLink>
136
+ </React.Fragment>
137
+ }
138
+ >
139
+ <TextContent>
140
+ {__('To continue with Red Hat Flatpak remote, you need to generate your username and password in')} <a target="_blank" href="https://access.redhat.com/terms-based-registry/" rel="noreferrer">access.redhat.com/terms-based-registry/</a>
141
+ </TextContent>
142
+ </Alert>
143
+ )}
144
+
117
145
  <FormGroup
118
146
  label={__('Name')}
119
147
  isRequired
@@ -168,7 +196,9 @@ const FlatpakRemotesForm = ({ setModalOpen, remoteData }) => {
168
196
  />
169
197
  <FormHelperText>
170
198
  <HelperText>
171
- <HelperTextItem>Authentication for registry</HelperTextItem>
199
+ <HelperTextItem>
200
+ {__('Provide credentials if the registry requires authentication')}
201
+ </HelperTextItem>
172
202
  </HelperText>
173
203
  </FormHelperText>
174
204
  </FormGroup>
@@ -209,10 +239,12 @@ const FlatpakRemotesForm = ({ setModalOpen, remoteData }) => {
209
239
 
210
240
  FlatpakRemotesForm.propTypes = {
211
241
  setModalOpen: PropTypes.func,
242
+ hasRedhatRemote: PropTypes.bool,
212
243
  };
213
244
 
214
245
  FlatpakRemotesForm.defaultProps = {
215
246
  setModalOpen: null,
247
+ hasRedhatRemote: true,
216
248
  };
217
249
 
218
250
  export default FlatpakRemotesForm;
@@ -149,7 +149,7 @@ export default function FlatpakRemoteDetails() {
149
149
  </TextContent>
150
150
  </GridItem>
151
151
 
152
- <GridItem span={12}>
152
+ <GridItem span={12} id="remote-repositories-table">
153
153
  <RemoteRepositoriesTable frId={frId} canMirror={canMirror} />
154
154
  </GridItem>
155
155
  { isEditing &&
@@ -0,0 +1,3 @@
1
+ #remote-repositories-table .pf-v5-c-toolbar__content-section {
2
+ gap: 1rem;
3
+ }