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,71 @@
1
+ import React, { useContext } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { MenuItem } from '@patternfly/react-core';
4
+ import { BanIcon } from '@patternfly/react-icons';
5
+ import { translate as __ } from 'foremanReact/common/I18n';
6
+ import { useForemanOrganization } from 'foremanReact/Root/Context/ForemanContext';
7
+ import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
8
+ import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
9
+ import BulkChangeHostCollectionsModal from './BulkChangeHostCollectionsModal';
10
+
11
+ const DisabledMenuItemDescription = ({ disabledReason }) => (
12
+ <span className="disabled-menu-item-span">
13
+ <span className="disabled-menu-item-icon">
14
+ <BanIcon />
15
+ </span>
16
+ <p className="disabled-menu-item-p">
17
+ {disabledReason}
18
+ </p>
19
+ </span>
20
+ );
21
+
22
+ DisabledMenuItemDescription.propTypes = {
23
+ disabledReason: PropTypes.string.isRequired,
24
+ };
25
+
26
+ // This component renders only the MenuItem trigger (for the slot in the menu)
27
+ export const BulkChangeHostCollectionsMenuItem = ({ selectedCount }) => {
28
+ const orgId = useForemanOrganization()?.id;
29
+ const { setModalOpen } = useForemanModal({ id: 'bulk-change-host-collections-modal' });
30
+
31
+ return (
32
+ <MenuItem
33
+ itemId="change-host-collections-dropdown-item"
34
+ key="change-host-collections-dropdown-item"
35
+ onClick={setModalOpen}
36
+ isDisabled={selectedCount === 0 || !orgId}
37
+ description={!orgId && <DisabledMenuItemDescription disabledReason={__('To manage host collections, a specific organization must be selected from the organization context.')} />}
38
+ >
39
+ {__('Host collections')}
40
+ </MenuItem>
41
+ );
42
+ };
43
+
44
+ BulkChangeHostCollectionsMenuItem.propTypes = {
45
+ selectedCount: PropTypes.number,
46
+ };
47
+
48
+ BulkChangeHostCollectionsMenuItem.defaultProps = {
49
+ selectedCount: 0,
50
+ };
51
+
52
+ // This component renders only the modal (for the _all-hosts-modals slot)
53
+ const BulkChangeHostCollectionsModalScene = () => {
54
+ const orgId = useForemanOrganization()?.id;
55
+ const { selectedCount, fetchBulkParams } = useContext(ForemanActionsBarContext);
56
+ const { modalOpen, setModalClosed } = useForemanModal({ id: 'bulk-change-host-collections-modal' });
57
+
58
+ if (!orgId) return null;
59
+
60
+ return (
61
+ <BulkChangeHostCollectionsModal
62
+ key="bulk-change-host-collections-modal"
63
+ fetchBulkParams={fetchBulkParams}
64
+ selectedCount={selectedCount}
65
+ isOpen={modalOpen}
66
+ closeModal={setModalClosed}
67
+ />
68
+ );
69
+ };
70
+
71
+ export default BulkChangeHostCollectionsModalScene;
@@ -11,7 +11,7 @@ import TableIndexPage from 'foremanReact/components/PF4/TableIndexPage/TableInde
11
11
  import { translate as __ } from 'foremanReact/common/I18n';
12
12
  import SelectAllCheckbox from 'foremanReact/components/PF4/TableIndexPage/Table/SelectAllCheckbox';
13
13
  import { STATUS, getControllerSearchProps } from 'foremanReact/constants';
14
- import { RowSelectTd } from 'foremanReact/components/HostsIndex/RowSelectTd';
14
+ import { RowSelectTd } from 'foremanReact/components/PF4/TableIndexPage/RowSelectTd';
15
15
  import { getPageStats } from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
16
16
  import { BulkErrataWizardContext, ERRATA_URL } from './BulkErrataWizard';
17
17
  import { ErrataType, ErrataSeverity } from '../../../../../components/Errata';
@@ -51,7 +51,7 @@ export const useErrataHostsBulkSelect = ({ initialSelectedHosts, modalIsOpen })
51
51
  };
52
52
  };
53
53
 
54
- export const ERRATA_URL = `${katelloApi.getApiUrl('/errata')}?per_page=7&include_permissions=true`;
54
+ export const ERRATA_URL = `${katelloApi.getApiUrl('/errata')}?per_page=7&include_permissions=true&errata_restrict_installable=true`;
55
55
 
56
56
  const BulkErrataWizard = () => {
57
57
  const { modalOpen, setModalClosed: closeModal } = useForemanModal({ id: 'bulk-errata-wizard' });
@@ -12,10 +12,11 @@ import { translate as __ } from 'foremanReact/common/I18n';
12
12
  import SelectAllCheckbox from 'foremanReact/components/PF4/TableIndexPage/Table/SelectAllCheckbox';
13
13
  import { getControllerSearchProps } from 'foremanReact/constants';
14
14
  import { noop } from 'foremanReact/common/helpers';
15
- import { RowSelectTd } from 'foremanReact/components/HostsIndex/RowSelectTd';
15
+ import { RowSelectTd } from 'foremanReact/components/PF4/TableIndexPage/RowSelectTd';
16
16
  import { getPageStats } from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
17
17
  import { BulkPackagesWizardContext, getPackagesUrl } from './BulkPackagesWizard';
18
18
  import katelloApi from '../../../../../services/api';
19
+ import PACKAGE_CONTENT_TYPE_NAMES from '../BulkActionsConstants';
19
20
 
20
21
  export const BulkPackagesUpgradeTable = props => <BulkPackagesTable {...props} tableType="upgrade" />;
21
22
  export const BulkPackagesInstallTable = props => <BulkPackagesTable {...props} tableType="install" />;
@@ -23,6 +24,7 @@ export const BulkPackagesRemoveTable = props => <BulkPackagesTable {...props} ta
23
24
 
24
25
  const BulkPackagesTable = ({
25
26
  tableType,
27
+ contentTypeName,
26
28
  }) => {
27
29
  const {
28
30
  setShouldValidateStep2,
@@ -42,12 +44,12 @@ const BulkPackagesTable = ({
42
44
  upgrade: __('Select packages to upgrade to the latest version. Packages may have different versions on different hosts.'),
43
45
  };
44
46
 
45
- const origSearchProps = getControllerSearchProps('packages', 'searchBar-packages');
47
+ const origSearchProps = getControllerSearchProps(contentTypeName, 'searchBar-packages');
46
48
  const customSearchProps = {
47
49
  ...origSearchProps,
48
50
  autocomplete: {
49
51
  ...origSearchProps.autocomplete,
50
- url: katelloApi.getApiUrl('/packages/auto_complete_search'),
52
+ url: katelloApi.getApiUrl(`/${contentTypeName}/auto_complete_search`),
51
53
  },
52
54
  };
53
55
 
@@ -93,7 +95,7 @@ const BulkPackagesTable = ({
93
95
  name: {
94
96
  title: __('Package'),
95
97
  wrapper: ({ name, id }) => (
96
- <a target="_blank" href={tableType === 'remove' ? `/packages?search=${name}` : `/packages/${id}`} rel="noreferrer">{name}</a>
98
+ <a target="_blank" href={tableType === 'remove' ? `/${contentTypeName}?search=${name}` : `/${contentTypeName}/${id}`} rel="noreferrer">{name}</a>
97
99
  ),
98
100
  isSorted: true,
99
101
  weight: 50,
@@ -152,4 +154,9 @@ const BulkPackagesTable = ({
152
154
 
153
155
  BulkPackagesTable.propTypes = {
154
156
  tableType: PropTypes.string.isRequired,
157
+ contentTypeName: PropTypes.string,
158
+ };
159
+
160
+ BulkPackagesTable.defaultProps = {
161
+ contentTypeName: PACKAGE_CONTENT_TYPE_NAMES.REDHAT,
155
162
  };
@@ -22,6 +22,7 @@ import { BulkPackagesReview, dropdownOptions } from './04_Review';
22
22
  import { BulkPackagesUpgradeTable, BulkPackagesInstallTable, BulkPackagesRemoveTable } from './02_BulkPackagesTable';
23
23
  import { BulkPackagesReviewFooter } from './04_ReviewFooter';
24
24
  import katelloApi, { foremanApi } from '../../../../../services/api';
25
+ import PACKAGE_CONTENT_TYPE_NAMES from '../BulkActionsConstants';
25
26
 
26
27
  export const UPGRADE_ALL = 'upgradeAll';
27
28
  export const UPGRADE = 'upgrade';
@@ -62,18 +63,18 @@ export const useHostsBulkSelect = ({ initialSelectedHosts, modalIsOpen }) => {
62
63
  };
63
64
  };
64
65
 
65
- export const getPackagesUrl = (selectedAction) => {
66
+ export const getPackagesUrl = (selectedAction, contentTypeName) => {
67
+ if (contentTypeName === PACKAGE_CONTENT_TYPE_NAMES.INVALID) return '';
66
68
  if (selectedAction === REMOVE) {
67
- return `${foremanApi.getApiUrl('/hosts/host_packages/installed_packages')}?per_page=7&include_permissions=true`;
69
+ return `${foremanApi.getApiUrl(`/hosts/host_${contentTypeName}/installed_${contentTypeName}`)}?per_page=7&include_permissions=true`;
68
70
  }
69
71
 
70
- return `${katelloApi.getApiUrl('/packages/thindex')}?per_page=7&include_permissions=true&packages_restrict_upgradable=${selectedAction === 'upgrade'}`;
72
+ return `${katelloApi.getApiUrl(`/${contentTypeName}/thindex`)}?per_page=7&include_permissions=true&packages_restrict_upgradable=${selectedAction === 'upgrade'}`;
71
73
  };
72
74
 
73
75
  const BulkPackagesWizard = () => {
74
76
  const { modalOpen, setModalClosed: closeModal } = useForemanModal({ id: 'bulk-packages-wizard' });
75
77
 
76
-
77
78
  const [selectedAction, setSelectedAction] = useState(UPGRADE_ALL);
78
79
 
79
80
  const { selectedCount: initialSelectedHostCount, fetchBulkParams }
@@ -86,28 +87,32 @@ const BulkPackagesWizard = () => {
86
87
  const packageActionsNames = {
87
88
  install: __('Install packages'), remove: __('Remove packages'), upgrade: __('Upgrade packages'), upgradeAll: __('Upgrade packages'),
88
89
  };
89
- const packageActions = () => {
90
- switch (selectedAction) {
91
- case INSTALL:
92
- return (
93
- <BulkPackagesInstallTable modalIsOpen={modalOpen} />
94
- );
95
- case REMOVE:
96
- return (
97
- <BulkPackagesRemoveTable modalIsOpen={modalOpen} />
98
- );
99
- default:
100
- return (
101
- <BulkPackagesUpgradeTable modalIsOpen={modalOpen} />
102
- );
90
+
91
+
92
+ const initialSelectedHosts = fetchBulkParams();
93
+
94
+ const hostsBulkSelect =
95
+ useHostsBulkSelect({ initialSelectedHosts, modalIsOpen: modalOpen });
96
+
97
+ const currentlySelectedHosts =
98
+ hostsBulkSelect?.hostsResponse?.response?.results?.filter(host =>
99
+ !hostsBulkSelect.hostsBulkSelect.exclusionSet.has(host.id));
100
+
101
+ const getContentTypeName = () => {
102
+ if (currentlySelectedHosts === undefined) {
103
+ return PACKAGE_CONTENT_TYPE_NAMES.INVALID;
104
+ } else if (currentlySelectedHosts[0]?.operatingsystem_family === 'Debian') {
105
+ return PACKAGE_CONTENT_TYPE_NAMES.DEBIAN;
103
106
  }
107
+
108
+ return PACKAGE_CONTENT_TYPE_NAMES.REDHAT;
104
109
  };
105
110
 
106
111
  const finishButtonTextValues = {
107
112
  install: __('Install'), remove: __('Remove'), upgrade: __('Upgrade'), upgradeAll: __('Upgrade'),
108
113
  };
109
114
  const finishButtonText = finishButtonTextValues[selectedAction];
110
- const PACKAGES_URL = getPackagesUrl(selectedAction);
115
+ const PACKAGES_URL = getPackagesUrl(selectedAction, getContentTypeName());
111
116
  const apiOptions = { key: 'BULK_HOST_PACKAGES' };
112
117
  const replacementResponse = !modalOpen ? { response: {} } : false;
113
118
  const packagesResponse = useTableIndexAPIResponse({
@@ -132,11 +137,6 @@ const BulkPackagesWizard = () => {
132
137
  idColumn: 'name',
133
138
  });
134
139
 
135
- const initialSelectedHosts = fetchBulkParams();
136
-
137
- const hostsBulkSelect =
138
- useHostsBulkSelect({ initialSelectedHosts, modalIsOpen: modalOpen });
139
-
140
140
  // eslint-disable-next-line no-restricted-globals
141
141
  const selectionIsValid = count => count > 0 || isNaN(count);
142
142
  const packagesResultsPresent = packagesResults?.length > 0;
@@ -164,6 +164,33 @@ const BulkPackagesWizard = () => {
164
164
  packagesResponse,
165
165
  hostsBulkSelect: hostsBulkSelect.hostsBulkSelect,
166
166
  };
167
+
168
+ const packageActions = () => {
169
+ switch (selectedAction) {
170
+ case INSTALL:
171
+ return (
172
+ <BulkPackagesInstallTable
173
+ contentTypeName={getContentTypeName()}
174
+ modalIsOpen={modalOpen}
175
+ />
176
+ );
177
+ case REMOVE:
178
+ return (
179
+ <BulkPackagesRemoveTable
180
+ contentTypeName={getContentTypeName()}
181
+ modalIsOpen={modalOpen}
182
+ />
183
+ );
184
+ default:
185
+ return (
186
+ <BulkPackagesUpgradeTable
187
+ contentTypeName={getContentTypeName()}
188
+ modalIsOpen={modalOpen}
189
+ />
190
+ );
191
+ }
192
+ };
193
+
167
194
  return (
168
195
  <BulkPackagesWizardContext.Provider value={bulkPackagesWizardContextData}>
169
196
  <Wizard
@@ -14,7 +14,7 @@ import { useSet } from 'foremanReact/components/PF4/TableIndexPage/Table/TableHo
14
14
  import TableIndexPage from 'foremanReact/components/PF4/TableIndexPage/TableIndexPage';
15
15
  import { Table } from 'foremanReact/components/PF4/TableIndexPage/Table/Table';
16
16
  import { translate as __ } from 'foremanReact/common/I18n';
17
- import { RowSelectTd } from 'foremanReact/components/HostsIndex/RowSelectTd';
17
+ import { RowSelectTd } from 'foremanReact/components/PF4/TableIndexPage/RowSelectTd';
18
18
  import SelectAllCheckbox from 'foremanReact/components/PF4/TableIndexPage/Table/SelectAllCheckbox';
19
19
  import { noop } from 'foremanReact/common/helpers';
20
20
 
@@ -11,7 +11,7 @@ import TableIndexPage from 'foremanReact/components/PF4/TableIndexPage/TableInde
11
11
  import { HOSTS_API_PATH } from 'foremanReact/routes/Hosts/constants';
12
12
  import { translate as __ } from 'foremanReact/common/I18n';
13
13
  import SelectAllCheckbox from 'foremanReact/components/PF4/TableIndexPage/Table/SelectAllCheckbox';
14
- import { RowSelectTd } from 'foremanReact/components/HostsIndex/RowSelectTd';
14
+ import { RowSelectTd } from 'foremanReact/components/PF4/TableIndexPage/RowSelectTd';
15
15
  import { getPageStats } from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
16
16
 
17
17
  const HostReview = ({
@@ -86,6 +86,13 @@ const HostReview = ({
86
86
  isSorted: true,
87
87
  weight: 100,
88
88
  },
89
+ cv_environments: {
90
+ title: __('Content view environments'),
91
+ wrapper: hostDetails =>
92
+ hostDetails?.content_facet_attributes?.content_view_environment_labels,
93
+ isSorted: false,
94
+ weight: 100,
95
+ },
89
96
  };
90
97
 
91
98
  // restrict search query to only selected hosts
@@ -15,7 +15,9 @@ import ContentDetails from '../../scenes/Content/Details';
15
15
  import withHeader from './withHeaders';
16
16
  import ChangeContentSource from '../../scenes/Hosts/ChangeContentSource';
17
17
  import AlternateContentSource from '../../scenes/AlternateContentSources';
18
- import BootedContainerImages from '../../scenes/BootedContainerImages';
18
+ import BootedContainerImages from '../../scenes/ContainerImages/Booted';
19
+ import ContainerImages from '../../scenes/ContainerImages';
20
+ import ManifestDetails from '../../scenes/ContainerImages/Synced/Details';
19
21
  import FlatpakRemotes from '../../scenes/FlatpakRemotes';
20
22
  import FlatpakRemoteDetails from '../../scenes/FlatpakRemotes/Details';
21
23
 
@@ -92,6 +94,14 @@ export const links = [
92
94
  path: 'booted_container_images',
93
95
  component: WithOrganization(withHeader(BootedContainerImages, { title: __('Booted container images') })),
94
96
  },
97
+ {
98
+ path: 'labs/container_images',
99
+ component: WithOrganization(withHeader(ContainerImages, { title: __('Container Images') })),
100
+ },
101
+ {
102
+ path: 'labs/container_images/:id([0-9]+)',
103
+ component: WithOrganization(withHeader(ManifestDetails, { title: __('Manifest Details') })),
104
+ },
95
105
  {
96
106
  path: 'flatpak_remotes',
97
107
  component: WithOrganization(withHeader(FlatpakRemotes, { title: __('Flatpak Remotes') })),
@@ -34,6 +34,7 @@ import HostsIndexActionsBar from './components/extensions/Hosts/ActionsBar';
34
34
  import RecentCommunicationCardExtensions from './components/extensions/HostDetails/DetailsTabCards/RecentCommunicationCardExtensions';
35
35
  import SystemPurposeCard from './components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeCard';
36
36
  import BulkChangeHostCVModal from './components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/index.js';
37
+ import BulkChangeHostCollectionsModal, { BulkChangeHostCollectionsMenuItem } from './components/extensions/Hosts/BulkActions/BulkChangeHostCollectionsModal/index.js';
37
38
  import BulkPackagesWizardModal from './components/extensions/Hosts/BulkActions/BulkPackagesWizard/index.js';
38
39
  import BulkErrataWizardModal from './components/extensions/Hosts/BulkActions/BulkErrataWizard/index.js';
39
40
  import BulkRepositorySetsWizardModal from './components/extensions/Hosts/BulkActions/BulkRepositorySetsWizard/index.js';
@@ -95,6 +96,8 @@ addGlobalFill('_all-hosts-modals', 'BulkChangeHostCVModal', <BulkChangeHostCVMod
95
96
  addGlobalFill('_all-hosts-modals', 'BulkPackagesWizardModal', <BulkPackagesWizardModal key="bulk-packages-wizard-modal" />, 200);
96
97
  addGlobalFill('_all-hosts-modals', 'BulkErrataWizardModal', <BulkErrataWizardModal key="bulk-errata-wizard-modal" />, 300);
97
98
  addGlobalFill('_all-hosts-modals', 'BulkRepositorySetsWizardModal', <BulkRepositorySetsWizardModal key="bulk-repo-sets-wizard-modal" />, 400);
99
+ addGlobalFill('_all-hosts-modals', 'BulkChangeHostCollectionsModal', <BulkChangeHostCollectionsModal key="bulk-change-host-collections-modal" />, 500);
100
+ addGlobalFill('_host-associations', 'BulkChangeHostCollectionsMenuItem', <BulkChangeHostCollectionsMenuItem key="bulk-change-host-collections-menu-item" />, 100);
98
101
 
99
102
  registerColumns(hostsIndexColumnExtensions);
100
103
  registerGetActions({
@@ -1,4 +1,4 @@
1
- import { foremanApi } from '../../services/api';
1
+ import { foremanApi } from '../../../services/api';
2
2
 
3
3
  const BOOTED_CONTAINER_IMAGES_KEY = 'BOOTED_CONTAINER_IMAGES';
4
4
  export const BOOTED_CONTAINER_IMAGES_API_PATH = foremanApi.getApiUrl('/hosts/bootc_images');
@@ -16,9 +16,10 @@ import {
16
16
  useTableSort,
17
17
  } from 'foremanReact/components/PF4/Helpers/useTableSort';
18
18
  import Pagination from 'foremanReact/components/Pagination';
19
- import EmptyPage from 'foremanReact/routes/common/EmptyPage';
20
19
  import { translate as __ } from 'foremanReact/common/I18n';
21
20
  import { useForemanHostsPageUrl } from 'foremanReact/Root/Context/ForemanContext';
21
+ import { STATUS } from '../containerImagesHelpers';
22
+ import TableEmptyState from '../TableEmptyState';
22
23
  import BOOTED_CONTAINER_IMAGES_KEY, { BOOTED_CONTAINER_IMAGES_API_PATH } from './BootedContainerImagesConstants';
23
24
 
24
25
  const BootedContainerImagesPage = () => {
@@ -79,11 +80,6 @@ const BootedContainerImagesPage = () => {
79
80
  });
80
81
  const expandedImages = useSet([]);
81
82
  const imageIsExpanded = bootcBootedImage => expandedImages.has(bootcBootedImage);
82
- const STATUS = {
83
- PENDING: 'PENDING',
84
- RESOLVED: 'RESOLVED',
85
- ERROR: 'ERROR',
86
- };
87
83
 
88
84
  const {
89
85
  response: {
@@ -108,7 +104,6 @@ const BootedContainerImagesPage = () => {
108
104
  <TableIndexPage
109
105
  apiUrl={BOOTED_CONTAINER_IMAGES_API_PATH}
110
106
  apiOptions={apiOptions}
111
- header={__('Booted container images')}
112
107
  createable={false}
113
108
  isDeleteable={false}
114
109
  controller="/katello/api/v2/host_bootc_images"
@@ -134,42 +129,11 @@ const BootedContainerImagesPage = () => {
134
129
  </>
135
130
  </Tr>
136
131
  </Thead>
137
- {(results.length === 0 || errorMessage) && (
138
- <Tbody>
139
- {status === STATUS.PENDING && results.length === 0 && (
140
- <Tr ouiaId="table-loading">
141
- <Td colSpan={100}>
142
- <EmptyPage
143
- message={{
144
- type: 'loading',
145
- text: __('Loading...'),
146
- }}
147
- />
148
- </Td>
149
- </Tr>
150
- )}
151
- {!(status === STATUS.PENDING) &&
152
- results.length === 0 &&
153
- !errorMessage && (
154
- <Tr ouiaId="table-empty">
155
- <Td colSpan={100}>
156
- <EmptyPage
157
- message={{
158
- type: 'empty',
159
- }}
160
- />
161
- </Td>
162
- </Tr>
163
- )}
164
- {errorMessage && (
165
- <Tr ouiaId="table-error">
166
- <Td colSpan={100}>
167
- <EmptyPage message={{ type: 'error', text: errorMessage }} />
168
- </Td>
169
- </Tr>
170
- )}
171
- </Tbody>
172
- )}
132
+ <TableEmptyState
133
+ status={status}
134
+ results={results}
135
+ errorMessage={errorMessage}
136
+ />
173
137
  {results?.map((result, rowIndex) => {
174
138
  const { bootc_booted_image: bootcBootedImage, digests } = result;
175
139
  const isExpanded = imageIsExpanded(bootcBootedImage);
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { renderWithRedux, patientlyWaitFor, act } from 'react-testing-lib-wrapper';
3
- import { nockInstance, assertNockRequest, mockAutocomplete } from '../../../test-utils/nockWrapper';
3
+ import { nockInstance, assertNockRequest, mockAutocomplete } from '../../../../test-utils/nockWrapper';
4
4
  import BootedContainerImagesPage from '../BootedContainerImagesPage';
5
5
  import bootcImagesData from './bootedContainerImages.fixtures';
6
6
 
@@ -0,0 +1,86 @@
1
+ import React, { useState } from 'react';
2
+ import { useHistory, useLocation } from 'react-router-dom';
3
+ import {
4
+ Title,
5
+ PageSection,
6
+ Stack,
7
+ StackItem,
8
+ Tabs,
9
+ Tab,
10
+ TabTitleText,
11
+ TabTitleIcon,
12
+ Popover,
13
+ Button,
14
+ } from '@patternfly/react-core';
15
+ import { SyncAltIcon, OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
16
+ import { translate as __ } from 'foremanReact/common/I18n';
17
+ import FontAwesomeImageModeIcon from '../../components/extensions/Hosts/FontAwesomeImageModeIcon';
18
+ import BootedContainerImagesPage from './Booted/BootedContainerImagesPage';
19
+ import SyncedContainerImagesPage from './Synced/SyncedContainerImagesPage';
20
+
21
+ const ContainerImagesPage = () => {
22
+ const [activeTabKey, setActiveTabKey] = useState(0);
23
+ const history = useHistory();
24
+ const location = useLocation();
25
+
26
+ const handleTabClick = (event, tabIndex) => {
27
+ setActiveTabKey(tabIndex);
28
+ history.replace(location.pathname);
29
+ };
30
+
31
+ return (
32
+ <PageSection variant="light">
33
+ <Stack hasGutter>
34
+ <StackItem>
35
+ <Title headingLevel="h1" size="2xl" ouiaId="container-images-title">
36
+ {__('Container images')}
37
+ <Popover
38
+ headerContent={<div>{__('Container images')}</div>}
39
+ bodyContent={
40
+ <div>
41
+ {__('View container images in the local registry using the Synced tab. View container images booted by image mode hosts using the Booted tab. The Booted tab also shows images outside of the local container registry.')}
42
+ </div>
43
+ }
44
+ >
45
+ <Button variant="plain" aria-label="Help" isInline icon={<OutlinedQuestionCircleIcon size="sm" />} ouiaId="container-images-help-button" />
46
+ </Popover>
47
+ </Title>
48
+ </StackItem>
49
+ <StackItem>
50
+ <Tabs
51
+ activeKey={activeTabKey}
52
+ onSelect={handleTabClick}
53
+ ouiaId="container-images-tabs"
54
+ >
55
+ <Tab
56
+ eventKey={0}
57
+ title={
58
+ <>
59
+ <TabTitleIcon><SyncAltIcon /></TabTitleIcon>
60
+ <TabTitleText>{__('Synced')}</TabTitleText>
61
+ </>
62
+ }
63
+ ouiaId="container-images-synced-tab"
64
+ />
65
+ <Tab
66
+ eventKey={1}
67
+ title={
68
+ <>
69
+ <TabTitleIcon><FontAwesomeImageModeIcon /></TabTitleIcon>
70
+ <TabTitleText>{__('Booted')}</TabTitleText>
71
+ </>
72
+ }
73
+ ouiaId="container-images-booted-tab"
74
+ />
75
+ </Tabs>
76
+ </StackItem>
77
+ <StackItem>
78
+ {activeTabKey === 0 && <SyncedContainerImagesPage />}
79
+ {activeTabKey === 1 && <BootedContainerImagesPage />}
80
+ </StackItem>
81
+ </Stack>
82
+ </PageSection>
83
+ );
84
+ };
85
+
86
+ export default ContainerImagesPage;
@@ -0,0 +1,105 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+ import {
5
+ Modal,
6
+ ModalVariant,
7
+ Button,
8
+ Label,
9
+ Flex,
10
+ FlexItem,
11
+ } from '@patternfly/react-core';
12
+
13
+ const LabelsAnnotationsModal = ({
14
+ show, setIsOpen, digest, labels, annotations,
15
+ }) => {
16
+ const INITIAL_DISPLAY_COUNT = 10;
17
+ const [showAll, setShowAll] = useState(false);
18
+
19
+ const handleClose = () => {
20
+ setShowAll(false);
21
+ setIsOpen(false);
22
+ };
23
+
24
+ // Combine labels and annotations into a single array of key-value pairs
25
+ const allItems = [
26
+ ...Object.entries(labels || {}).map(([key, value]) => ({
27
+ key: `label-${key}`,
28
+ value: `${key}=${value}`,
29
+ })),
30
+ ...Object.entries(annotations || {}).map(([key, value]) => ({
31
+ key: `annotation-${key}`,
32
+ value: `${key}=${value}`,
33
+ })),
34
+ ];
35
+
36
+ const totalCount = allItems.length;
37
+ const displayedItems = showAll ? allItems : allItems.slice(0, INITIAL_DISPLAY_COUNT);
38
+ const remainingCount = totalCount - INITIAL_DISPLAY_COUNT;
39
+
40
+ return (
41
+ <Modal
42
+ ouiaId="labels-annotations-modal"
43
+ title={__('Labels and annotations')}
44
+ variant={ModalVariant.medium}
45
+ isOpen={show}
46
+ onClose={handleClose}
47
+ appendTo={document.body}
48
+ actions={[
49
+ <Button key="close" variant="link" onClick={handleClose} ouiaId="labels-annotations-close-button">
50
+ {__('Close')}
51
+ </Button>,
52
+ ]}
53
+ >
54
+ <div>
55
+ <p>
56
+ {__('View labels and annotations for image ')}
57
+ <strong>{digest}</strong>.
58
+ </p>
59
+ <p style={{ marginTop: '16px', fontWeight: 'bold' }}>
60
+ {__(`${totalCount} labels and annotations`)}
61
+ </p>
62
+ <Flex
63
+ spaceItems={{ default: 'spaceItemsSm' }}
64
+ style={{ marginTop: '16px' }}
65
+ direction={{ default: 'row' }}
66
+ flexWrap={{ default: 'wrap' }}
67
+ >
68
+ {displayedItems.map(item => (
69
+ <FlexItem key={item.key}>
70
+ <Label>{item.value}</Label>
71
+ </FlexItem>
72
+ ))}
73
+ </Flex>
74
+ {!showAll && remainingCount > 0 && (
75
+ <Button
76
+ variant="link"
77
+ isInline
78
+ onClick={() => setShowAll(true)}
79
+ style={{ marginTop: '16px', padding: 0 }}
80
+ ouiaId="show-more-labels-annotations-button"
81
+ >
82
+ {__(`Show ${remainingCount} more`)}
83
+ </Button>
84
+ )}
85
+ </div>
86
+ </Modal>
87
+ );
88
+ };
89
+
90
+ LabelsAnnotationsModal.propTypes = {
91
+ show: PropTypes.bool,
92
+ setIsOpen: PropTypes.func.isRequired,
93
+ digest: PropTypes.string,
94
+ labels: PropTypes.objectOf(PropTypes.string),
95
+ annotations: PropTypes.objectOf(PropTypes.string),
96
+ };
97
+
98
+ LabelsAnnotationsModal.defaultProps = {
99
+ show: false,
100
+ digest: '',
101
+ labels: {},
102
+ annotations: {},
103
+ };
104
+
105
+ export default LabelsAnnotationsModal;