katello 4.10.0.rc2 → 4.11.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of katello might be problematic. Click here for more details.

Files changed (418) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/locale/bn/katello.js +254 -215
  3. data/app/assets/javascripts/katello/locale/bn_IN/katello.js +254 -215
  4. data/app/assets/javascripts/katello/locale/ca/katello.js +254 -215
  5. data/app/assets/javascripts/katello/locale/cs/katello.js +254 -215
  6. data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +254 -215
  7. data/app/assets/javascripts/katello/locale/de/katello.js +260 -245
  8. data/app/assets/javascripts/katello/locale/de_AT/katello.js +254 -215
  9. data/app/assets/javascripts/katello/locale/de_DE/katello.js +254 -215
  10. data/app/assets/javascripts/katello/locale/el/katello.js +254 -215
  11. data/app/assets/javascripts/katello/locale/en/katello.js +254 -215
  12. data/app/assets/javascripts/katello/locale/en_GB/katello.js +254 -215
  13. data/app/assets/javascripts/katello/locale/en_US/katello.js +254 -215
  14. data/app/assets/javascripts/katello/locale/es/katello.js +257 -233
  15. data/app/assets/javascripts/katello/locale/et_EE/katello.js +254 -215
  16. data/app/assets/javascripts/katello/locale/fr/katello.js +268 -268
  17. data/app/assets/javascripts/katello/locale/gl/katello.js +254 -215
  18. data/app/assets/javascripts/katello/locale/gu/katello.js +254 -215
  19. data/app/assets/javascripts/katello/locale/he_IL/katello.js +254 -215
  20. data/app/assets/javascripts/katello/locale/hi/katello.js +254 -215
  21. data/app/assets/javascripts/katello/locale/id/katello.js +254 -215
  22. data/app/assets/javascripts/katello/locale/it/katello.js +254 -221
  23. data/app/assets/javascripts/katello/locale/ja/katello.js +268 -268
  24. data/app/assets/javascripts/katello/locale/ka/katello.js +261 -231
  25. data/app/assets/javascripts/katello/locale/kn/katello.js +254 -215
  26. data/app/assets/javascripts/katello/locale/ko/katello.js +255 -222
  27. data/app/assets/javascripts/katello/locale/locale/katello.js +1049 -1012
  28. data/app/assets/javascripts/katello/locale/ml_IN/katello.js +254 -215
  29. data/app/assets/javascripts/katello/locale/mr/katello.js +254 -215
  30. data/app/assets/javascripts/katello/locale/nl_NL/katello.js +254 -215
  31. data/app/assets/javascripts/katello/locale/or/katello.js +254 -215
  32. data/app/assets/javascripts/katello/locale/pa/katello.js +254 -215
  33. data/app/assets/javascripts/katello/locale/pl/katello.js +254 -215
  34. data/app/assets/javascripts/katello/locale/pl_PL/katello.js +254 -215
  35. data/app/assets/javascripts/katello/locale/pt/katello.js +254 -215
  36. data/app/assets/javascripts/katello/locale/pt_BR/katello.js +257 -233
  37. data/app/assets/javascripts/katello/locale/ro/katello.js +254 -215
  38. data/app/assets/javascripts/katello/locale/ro_RO/katello.js +254 -215
  39. data/app/assets/javascripts/katello/locale/ru/katello.js +255 -222
  40. data/app/assets/javascripts/katello/locale/sl/katello.js +254 -215
  41. data/app/assets/javascripts/katello/locale/sv_SE/katello.js +254 -215
  42. data/app/assets/javascripts/katello/locale/ta/katello.js +254 -215
  43. data/app/assets/javascripts/katello/locale/ta_IN/katello.js +254 -215
  44. data/app/assets/javascripts/katello/locale/te/katello.js +254 -215
  45. data/app/assets/javascripts/katello/locale/tr/katello.js +254 -215
  46. data/app/assets/javascripts/katello/locale/vi/katello.js +254 -215
  47. data/app/assets/javascripts/katello/locale/vi_VN/katello.js +254 -215
  48. data/app/assets/javascripts/katello/locale/zh/katello.js +254 -215
  49. data/app/assets/javascripts/katello/locale/zh_CN/katello.js +268 -268
  50. data/app/assets/javascripts/katello/locale/zh_TW/katello.js +255 -222
  51. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +15 -2
  52. data/app/controllers/katello/api/v2/capsule_content_controller.rb +21 -4
  53. data/app/controllers/katello/api/v2/capsules_controller.rb +11 -1
  54. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +1 -1
  55. data/app/controllers/katello/api/v2/docker_tags_controller.rb +2 -0
  56. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +2 -1
  57. data/app/controllers/katello/api/v2/organizations_controller.rb +2 -2
  58. data/app/controllers/katello/api/v2/repositories_controller.rb +1 -0
  59. data/app/controllers/katello/api/v2/simple_content_access_controller.rb +5 -5
  60. data/app/controllers/katello/api/v2/sync_plans_controller.rb +11 -3
  61. data/app/controllers/katello/concerns/api/api_controller.rb +6 -0
  62. data/app/controllers/katello/concerns/api/v2/hosts_bulk_actions_controller_extensions.rb +23 -0
  63. data/app/controllers/katello/concerns/filtered_auto_complete_search.rb +1 -1
  64. data/app/controllers/katello/concerns/organizations_controller_extensions.rb +2 -0
  65. data/app/controllers/katello/remote_execution_controller.rb +1 -1
  66. data/app/jobs/create_host_lifecycle_expire_soon_notifications.rb +11 -0
  67. data/app/lib/actions/katello/applicability/hosts/bulk_generate.rb +10 -0
  68. data/app/lib/actions/katello/capsule_content/refresh_repos.rb +8 -2
  69. data/app/lib/actions/katello/capsule_content/sync.rb +30 -10
  70. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +13 -0
  71. data/app/lib/actions/katello/capsule_content/update_content_counts.rb +24 -0
  72. data/app/lib/actions/katello/content_view/promote.rb +9 -0
  73. data/app/lib/actions/katello/content_view/publish.rb +9 -0
  74. data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +8 -0
  75. data/app/lib/actions/katello/repository/remove_content.rb +9 -1
  76. data/app/lib/actions/katello/repository/sync.rb +11 -0
  77. data/app/lib/actions/pulp3/capsule_content/reclaim_space.rb +5 -0
  78. data/app/lib/actions/pulp3/content_view_version/create_export_history.rb +6 -1
  79. data/app/lib/actions/pulp3/content_view_version/export.rb +8 -0
  80. data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +1 -1
  81. data/app/lib/katello/concerns/base_template_scope_extensions.rb +14 -1
  82. data/app/lib/katello/errors.rb +1 -0
  83. data/app/lib/katello/repo_discovery.rb +78 -5
  84. data/app/lib/katello/validators/content_view_environment_coherent_default_validator.rb +22 -0
  85. data/app/lib/katello/validators/content_view_environment_validator.rb +1 -0
  86. data/app/mailers/katello/task_mailer.rb +54 -0
  87. data/app/models/katello/concerns/host_managed_extensions.rb +41 -1
  88. data/app/models/katello/concerns/organization_extensions.rb +1 -1
  89. data/app/models/katello/concerns/smart_proxy_extensions.rb +75 -3
  90. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +6 -0
  91. data/app/models/katello/content_view.rb +21 -0
  92. data/app/models/katello/content_view_environment.rb +6 -1
  93. data/app/models/katello/docker_meta_tag.rb +1 -1
  94. data/app/models/katello/docker_tag.rb +1 -1
  95. data/app/models/katello/erratum.rb +1 -1
  96. data/app/models/katello/host/content_facet.rb +10 -7
  97. data/app/models/katello/product.rb +8 -0
  98. data/app/models/katello/repository.rb +31 -6
  99. data/app/models/katello/rhel_lifecycle_status.rb +214 -0
  100. data/app/models/katello/sync_plan.rb +19 -1
  101. data/app/models/katello/yum_metadata_file.rb +1 -1
  102. data/app/services/katello/applicability/applicable_content_helper.rb +1 -1
  103. data/app/services/katello/event_queue.rb +10 -2
  104. data/app/services/katello/host_status_manager.rb +1 -0
  105. data/app/services/katello/product_content_importer.rb +45 -3
  106. data/app/services/katello/pulp3/ansible_collection.rb +1 -0
  107. data/app/services/katello/pulp3/api/core.rb +1 -1
  108. data/app/services/katello/pulp3/deb.rb +1 -0
  109. data/app/services/katello/pulp3/docker_manifest.rb +1 -0
  110. data/app/services/katello/pulp3/docker_manifest_list.rb +9 -4
  111. data/app/services/katello/pulp3/docker_tag.rb +1 -0
  112. data/app/services/katello/pulp3/erratum.rb +1 -0
  113. data/app/services/katello/pulp3/file_unit.rb +1 -0
  114. data/app/services/katello/pulp3/module_stream.rb +1 -0
  115. data/app/services/katello/pulp3/package_group.rb +1 -0
  116. data/app/services/katello/pulp3/pulp_content_unit.rb +39 -0
  117. data/app/services/katello/pulp3/repository_mirror.rb +21 -2
  118. data/app/services/katello/pulp3/rpm.rb +1 -0
  119. data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +1 -1
  120. data/app/services/katello/pulp3/srpm.rb +3 -2
  121. data/app/services/katello/registration_manager.rb +6 -3
  122. data/app/services/katello/repository_type.rb +2 -1
  123. data/app/services/katello/ui_notifications/hosts/lifecycle_expire_soon.rb +58 -0
  124. data/app/views/foreman/job_templates/resolve_traces.erb +1 -1
  125. data/app/views/foreman/smart_proxies/_content_tab.html.erb +1 -3
  126. data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +39 -1
  127. data/app/views/katello/api/v2/content_facet/show.json.rabl +4 -0
  128. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -1
  129. data/app/views/katello/api/v2/docker_tags/_base.json.rabl +28 -6
  130. data/app/views/katello/hosts/_errata_counts.html.erb +2 -2
  131. data/app/views/katello/task_mailer/cv_promote_failure.html.erb +31 -0
  132. data/app/views/katello/task_mailer/cv_promote_failure.text.erb +13 -0
  133. data/app/views/katello/task_mailer/cv_publish_failure.html.erb +31 -0
  134. data/app/views/katello/task_mailer/cv_publish_failure.text.erb +13 -0
  135. data/app/views/katello/task_mailer/proxy_sync_failure.html.erb +45 -0
  136. data/app/views/katello/task_mailer/proxy_sync_failure.text.erb +25 -0
  137. data/app/views/katello/task_mailer/repo_sync_failure.html.erb +35 -0
  138. data/app/views/katello/task_mailer/repo_sync_failure.text.erb +15 -0
  139. data/app/views/overrides/organizations/_edit_override.html.erb +4 -0
  140. data/config/routes/api/v2.rb +2 -0
  141. data/db/migrate/20230825180856_add_content_counts_to_smart_proxy.rb +7 -0
  142. data/db/migrate/20231020153017_create_indexes_for_nvra_and_epoch.rb +6 -0
  143. data/db/seeds.d/106-mail_notifications.rb +32 -0
  144. data/db/seeds.d/109-katello-notification-blueprints.rb +6 -0
  145. data/engines/bastion/app/assets/javascripts/bastion/components/views/bst-alert.html +1 -1
  146. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/activation-keys.controller.js +4 -0
  147. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-add-host-collections.controller.js +3 -0
  148. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-add-subscriptions.controller.js +3 -0
  149. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-associations.controller.js +4 -0
  150. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-copy.controller.js +7 -2
  151. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-host-collections.controller.js +3 -0
  152. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-repository-sets.controller.js +3 -0
  153. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-subscriptions.controller.js +3 -0
  154. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/new/new-activation-key.controller.js +6 -2
  155. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/capsule-content.controller.js +16 -1
  156. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/views/rhel-lifecycle-notice.html +5 -0
  157. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/content-credentials.controller.js +7 -2
  158. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/content-credential-acs.controller.js +7 -2
  159. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/content-credential-products.controller.js +7 -2
  160. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/content-credential-repositories.controller.js +7 -2
  161. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/new-content-credential.controller.js +3 -0
  162. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-errata-modal.controller.js +5 -1
  163. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-actions.controller.js +5 -1
  164. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-applicable.controller.js +3 -0
  165. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-installed.controller.js +3 -0
  166. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-errata.controller.js +4 -0
  167. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +3 -0
  168. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-applicable.controller.js +3 -0
  169. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +3 -0
  170. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages.controller.js +3 -0
  171. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-traces.controller.js +4 -0
  172. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-debs-actions.html +1 -1
  173. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-debs-applicable.html +1 -1
  174. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-debs-installed.html +1 -1
  175. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-errata.html +3 -3
  176. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-module-streams.html +1 -1
  177. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-actions.html +1 -1
  178. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-applicable.html +1 -1
  179. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-installed.html +1 -1
  180. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-traces.html +3 -3
  181. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +5 -0
  182. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.routes.js +1 -1
  183. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-add-host-collections.controller.js +4 -1
  184. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-add-subscriptions.controller.js +3 -0
  185. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-host-collections.controller.js +4 -1
  186. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-repository-sets.controller.js +3 -0
  187. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-subscriptions.controller.js +3 -0
  188. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-add-subscriptions.html +1 -1
  189. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-details.html +4 -3
  190. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-host-collections.html +1 -1
  191. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +3 -3
  192. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-provisioning-info.html +2 -2
  193. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-subscriptions-list.html +1 -1
  194. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-subscriptions.html +1 -1
  195. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +3 -3
  196. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/debs.controller.js +7 -0
  197. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/details/deb-content-views.controller.js +8 -1
  198. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/debs/details/deb-repositories.controller.js +10 -2
  199. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/details/docker-tag-environments.controller.js +5 -2
  200. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/details/docker-tag-repositories.controller.js +6 -2
  201. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/docker-tags.controller.js +6 -3
  202. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/environment-content.controller.js +13 -0
  203. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/environment.controller.js +6 -0
  204. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/new-environment.controller.js +8 -2
  205. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +4 -0
  206. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/erratum-content-hosts.controller.js +7 -2
  207. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/erratum-repositories.controller.js +7 -2
  208. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/erratum.controller.js +6 -2
  209. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum-info.html +2 -2
  210. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/errata.controller.js +5 -0
  211. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/views/errata.html +1 -1
  212. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/files/details/file-content-views.controller.js +10 -2
  213. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/files/details/file-repositories.controller.js +8 -1
  214. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/files/files.controller.js +9 -2
  215. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/host-collection-add-hosts.controller.js +3 -0
  216. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/host-collection-copy.controller.js +7 -2
  217. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/host-collection-hosts.controller.js +3 -0
  218. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/host-collections.controller.js +4 -0
  219. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/new/new-host-collection.controller.js +6 -2
  220. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host.factory.js +4 -0
  221. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +166 -43
  222. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +4 -0
  223. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/translations.js +1 -1
  224. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/packages/packages.controller.js +7 -0
  225. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/product-repositories.controller.js +5 -0
  226. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-advanced-sync.controller.js +6 -2
  227. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-manage-content.controller.js +11 -0
  228. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +3 -0
  229. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/views/product-repositories.html +2 -2
  230. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery-create.controller.js +3 -0
  231. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery.controller.js +3 -0
  232. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/new/product-form.controller.js +6 -2
  233. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.controller.js +4 -0
  234. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +1 -1
  235. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/sync-plan-add-products.controller.js +5 -1
  236. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/sync-plan-products.controller.js +4 -0
  237. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/new/new-sync-plan.controller.js +3 -0
  238. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/sync-plans.controller.js +4 -0
  239. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/tasks/task-details.controller.js +6 -2
  240. data/lib/katello/engine.rb +2 -3
  241. data/lib/katello/permission_creator.rb +2 -2
  242. data/lib/katello/plugin.rb +4 -0
  243. data/lib/katello/repository_types/ostree.rb +1 -0
  244. data/lib/katello/repository_types/python.rb +1 -0
  245. data/lib/katello/scheduled_jobs.rb +1 -1
  246. data/lib/katello/version.rb +1 -1
  247. data/locale/action_names.rb +1 -3
  248. data/locale/bn/katello.po +236 -197
  249. data/locale/bn_IN/katello.po +236 -197
  250. data/locale/ca/LC_MESSAGES/katello.mo +0 -0
  251. data/locale/ca/katello.po +236 -197
  252. data/locale/cs/katello.po +236 -206
  253. data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
  254. data/locale/cs_CZ/katello.po +236 -197
  255. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  256. data/locale/de/katello.po +241 -202
  257. data/locale/de_AT/katello.po +236 -197
  258. data/locale/de_DE/katello.po +236 -197
  259. data/locale/el/katello.po +236 -197
  260. data/locale/en/katello.po +236 -197
  261. data/locale/en_GB/katello.po +236 -197
  262. data/locale/en_US/katello.po +236 -197
  263. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  264. data/locale/es/katello.po +238 -199
  265. data/locale/et_EE/katello.po +236 -197
  266. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  267. data/locale/fr/katello.po +247 -208
  268. data/locale/gl/katello.po +236 -197
  269. data/locale/gu/katello.po +236 -197
  270. data/locale/he_IL/katello.po +236 -197
  271. data/locale/hi/katello.po +236 -197
  272. data/locale/id/katello.po +236 -197
  273. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  274. data/locale/it/katello.po +236 -197
  275. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  276. data/locale/ja/katello.po +247 -208
  277. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  278. data/locale/ka/katello.po +241 -202
  279. data/locale/katello.pot +1427 -1296
  280. data/locale/kn/katello.po +236 -197
  281. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  282. data/locale/ko/katello.po +236 -197
  283. data/locale/ml_IN/katello.po +236 -197
  284. data/locale/mr/katello.po +236 -197
  285. data/locale/nl_NL/katello.po +236 -197
  286. data/locale/or/katello.po +236 -197
  287. data/locale/pa/katello.po +236 -197
  288. data/locale/pl/katello.po +236 -197
  289. data/locale/pl_PL/katello.po +236 -197
  290. data/locale/pt/katello.po +236 -197
  291. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  292. data/locale/pt_BR/katello.po +238 -199
  293. data/locale/ro/katello.po +236 -197
  294. data/locale/ro_RO/katello.po +236 -197
  295. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  296. data/locale/ru/katello.po +236 -197
  297. data/locale/sl/katello.po +236 -197
  298. data/locale/sv_SE/katello.po +236 -197
  299. data/locale/ta/katello.po +236 -197
  300. data/locale/ta_IN/katello.po +236 -197
  301. data/locale/te/katello.po +236 -197
  302. data/locale/tr/katello.po +236 -197
  303. data/locale/vi/katello.po +236 -197
  304. data/locale/vi_VN/katello.po +236 -197
  305. data/locale/zh/katello.po +236 -197
  306. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  307. data/locale/zh_CN/katello.po +247 -208
  308. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  309. data/locale/zh_TW/katello.po +236 -197
  310. data/webpack/components/Table/EmptyStateMessage.js +7 -4
  311. data/webpack/components/Table/MainTable.scss +18 -17
  312. data/webpack/components/Table/TableWrapper.js +4 -1
  313. data/webpack/components/extensions/HostDetails/ActionsBar/index.js +45 -4
  314. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.scss +9 -7
  315. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsCard.js +1 -1
  316. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsModal.js +1 -1
  317. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeActions.js +29 -7
  318. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeCard.js +106 -66
  319. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeCard.scss +6 -0
  320. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeConstants.js +2 -0
  321. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeEditModal.js +53 -29
  322. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeSelectors.js +7 -6
  323. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/__tests__/SystemPurposeCard.test.js +24 -5
  324. data/webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/__tests__/SystemPurposeEditModal.test.js +137 -7
  325. data/webpack/components/extensions/HostDetails/DetailsTabCards/HwPropertiesCard.js +11 -10
  326. data/webpack/components/extensions/HostDetails/DetailsTabCards/RegistrationCard.js +8 -2
  327. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +27 -10
  328. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/HostErrataActions.js +3 -22
  329. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/HostErrataConstants.js +0 -1
  330. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +3 -2
  331. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackageInstallModal.js +2 -2
  332. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +48 -12
  333. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +22 -10
  334. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionHooks.js +1 -1
  335. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +2 -2
  336. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/EnableTracerModal.js +71 -5
  337. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/EnableTracerModal.scss +16 -0
  338. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/TracesEnabler.js +4 -1
  339. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/TracesTab.js +6 -2
  340. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +2 -1
  341. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +25 -0
  342. data/webpack/components/extensions/Hosts/ActionsBar/index.js +36 -0
  343. data/webpack/components/extensions/Hosts/constants.js +2 -0
  344. data/webpack/components/extensions/RegistrationCommands/RegistrationCommandsPageHelpers.js +13 -7
  345. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/ActivationKeys.test.js.snap +9 -1
  346. data/webpack/components/extensions/RegistrationCommands/fields/ActivationKeys.js +87 -22
  347. data/webpack/components/extensions/RegistrationCommands/index.js +17 -41
  348. data/webpack/global_index.js +11 -2
  349. data/webpack/redux/reducers/RedHatRepositories/enabled.fixtures.js +4 -0
  350. data/webpack/redux/reducers/RedHatRepositories/enabled.js +1 -0
  351. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetails.js +10 -1
  352. data/webpack/scenes/ActivationKeys/Details/ActivationKeyDetails.scss +33 -31
  353. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +3 -1
  354. data/webpack/scenes/Content/ContentConfig.js +3 -0
  355. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +6 -4
  356. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.scss +8 -6
  357. data/webpack/scenes/ContentViews/Delete/ContentViewDeleteWizard.js +1 -0
  358. data/webpack/scenes/ContentViews/Delete/Steps/CVEnvironmentSelectionForm.scss +4 -2
  359. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +3 -4
  360. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +2 -2
  361. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +5 -5
  362. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/compositeCVDetails.fixtures.json +393 -0
  363. data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +30 -4
  364. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +3 -1
  365. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/CVRpmMatchContentModal.js +18 -4
  366. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/matchContentModal.scss +3 -0
  367. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +15 -1
  368. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +3 -3
  369. data/webpack/scenes/ContentViews/Details/Repositories/RepoIcon.js +2 -1
  370. data/webpack/scenes/ContentViews/Details/Versions/Compare/CVVersionCompareTable.js +1 -1
  371. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +1 -1
  372. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveCVVersionWizard.js +1 -1
  373. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +1 -1
  374. data/webpack/scenes/ContentViews/Publish/CVPublishForm.js +24 -1
  375. data/webpack/scenes/ContentViews/Publish/PublishContentViewWizard.js +1 -0
  376. data/webpack/scenes/ContentViews/Publish/__tests__/publishContentView.test.js +42 -0
  377. data/webpack/scenes/ContentViews/Publish/cvPublishForm.scss +13 -11
  378. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +2 -1
  379. data/webpack/scenes/ContentViews/__tests__/mockDetails.fixtures.json +2 -1
  380. data/webpack/scenes/Hosts/ChangeContentSource/index.js +4 -3
  381. data/webpack/scenes/ModuleStreams/Details/ModuleStreamDetails.js +1 -2
  382. data/webpack/scenes/ModuleStreams/Details/__tests__/__snapshots__/ModuleStreamDetails.test.js.snap +1 -1
  383. data/webpack/scenes/RedHatRepositories/RedHatRepositoriesPage.js +2 -1
  384. data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +6 -0
  385. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepository.js +4 -1
  386. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepositoryContent.js +13 -4
  387. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/__tests__/EnabledRepositoryContent.test.js +1 -0
  388. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/__tests__/__snapshots__/EnabledRepository.test.js.snap +1 -0
  389. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/__tests__/__snapshots__/EnabledRepositoryContent.test.js.snap +3 -2
  390. data/webpack/scenes/SmartProxy/AdditionalCapsuleContent.js +93 -0
  391. data/webpack/scenes/SmartProxy/Content.js +12 -4
  392. data/webpack/scenes/SmartProxy/ExpandableCvDetails.js +107 -0
  393. data/webpack/scenes/SmartProxy/ExpandedSmartProxyRepositories.js +139 -0
  394. data/webpack/scenes/SmartProxy/SmartProxyContentActions.js +17 -4
  395. data/webpack/scenes/SmartProxy/SmartProxyContentConstants.js +1 -0
  396. data/webpack/scenes/SmartProxy/SmartProxyExpandableTable.js +150 -0
  397. data/webpack/scenes/SmartProxy/__tests__/SmartProxyContentTest.fixtures.json +799 -0
  398. data/webpack/scenes/SmartProxy/__tests__/SmartProxyContentTest.js +29 -17
  399. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +16 -19
  400. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.scss +12 -8
  401. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +21 -18
  402. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnConfigurationForm.scss +4 -2
  403. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.scss +38 -19
  404. data/webpack/scenes/Subscriptions/Manifest/index.js +0 -2
  405. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +38 -12
  406. data/webpack/scenes/Subscriptions/SubscriptionsPage.scss +38 -36
  407. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +16 -13
  408. data/webpack/utils/helpers.js +0 -1
  409. metadata +58 -39
  410. data/app/controllers/katello/concerns/api/v2/bulk_hosts_extensions.rb +0 -47
  411. data/webpack/components/Table/TableHooks.js +0 -315
  412. data/webpack/components/Table/__test__/useBulkSelect.test.js +0 -99
  413. data/webpack/components/extensions/RegistrationCommands/__tests__/LifeCycleEnvironment.test.js +0 -11
  414. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/LifeCycleEnvironment.test.js.snap +0 -29
  415. data/webpack/components/extensions/RegistrationCommands/fields/LifecycleEnvironment.js +0 -57
  416. data/webpack/scenes/SmartProxy/SmartProxyContentTable.js +0 -164
  417. data/webpack/scenes/SmartProxy/__tests__/SmartProxyContentResult.fixtures.json +0 -140
  418. data/webpack/scenes/Subscriptions/Manifest/Manifest.scss +0 -16
@@ -3,6 +3,7 @@ module Actions
3
3
  module CapsuleContent
4
4
  class ReclaimSpace < Pulp3::AbstractAsyncTask
5
5
  def plan(smart_proxy)
6
+ action_subject(smart_proxy)
6
7
  if smart_proxy.pulp_primary?
7
8
  repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs(::Katello::Repository.unscoped.on_demand, ::Organization.all)
8
9
  repository_hrefs.flatten!
@@ -20,6 +21,10 @@ module Actions
20
21
  output[:pulp_tasks] = ::Katello::Pulp3::Api::Core.new(SmartProxy.find(input[:smart_proxy_id])).
21
22
  repositories_reclaim_space_api.reclaim(repo_hrefs: input[:repository_hrefs])
22
23
  end
24
+
25
+ def rescue_strategy
26
+ Dynflow::Action::Rescue::Skip
27
+ end
23
28
  end
24
29
  end
25
30
  end
@@ -16,11 +16,16 @@ module Actions
16
16
  param :exported_file_checksum, String
17
17
  end
18
18
 
19
- def run
19
+ def run # rubocop:disable Metrics/AbcSize
20
20
  smart_proxy = ::SmartProxy.unscoped.find(input[:smart_proxy_id])
21
21
  api = ::Katello::Pulp3::Api::Core.new(smart_proxy)
22
22
  export_data = api.export_api.list(input[:exporter_data][:pulp_href]).results.first
23
23
  output[:exported_file_checksum] = export_data.output_file_info
24
+ if output[:exported_file_checksum].blank?
25
+ output[:export_history_id] = nil
26
+ output[:message] = _("Export failed: One or more repositories needs to be synced (with Immediate download policy.)")
27
+ return
28
+ end
24
29
  file_name = output[:exported_file_checksum].first&.first
25
30
  path = File.dirname(file_name.to_s)
26
31
  output[:path] = path
@@ -24,6 +24,14 @@ module Actions
24
24
  .create_export(input[:exporter_data],
25
25
  chunk_size: input[:chunk_size])
26
26
  end
27
+
28
+ def rescue_external_task(error)
29
+ if error.is_a?(::Katello::Errors::Pulp3Error) && error.message.match?(/Remote artifacts cannot be exported/)
30
+ fail ::Katello::Errors::Pulp3ExportError, "Failed to export: One or more repositories needs to be synced (with Immediate download policy.)"
31
+ else
32
+ super
33
+ end
34
+ end
27
35
  end
28
36
  end
29
37
  end
@@ -28,7 +28,7 @@ module Actions
28
28
  end
29
29
 
30
30
  def run
31
- output[:export_history_id] = input[:export_action_output][:export_history_id]
31
+ output[:export_history_id] = input[:export_action_output]&.[](:export_history_id)
32
32
  end
33
33
 
34
34
  def humanized_name
@@ -88,6 +88,19 @@ module Katello
88
88
  end
89
89
  end
90
90
 
91
+ apipie :method, 'Returns installed product names for the host with CP IDs' do
92
+ required :host, 'Host::Managed', desc: 'Host object to get products for'
93
+ returns array_of: String, desc: 'Array with names and CP IDs of installed products on the host'
94
+ end
95
+ def host_products_names_and_ids(host)
96
+ products = host_products(host)
97
+ if products
98
+ products.collect { |product| "#{product.name} (#{product.cp_product_id})" }
99
+ else
100
+ []
101
+ end
102
+ end
103
+
91
104
  apipie :method, 'Returns the host collections the host belongs to' do
92
105
  required :host, 'Host::Managed', desc: 'Host object to get the host collections for'
93
106
  returns array_of: 'HostCollection', desc: "Array of the host collection objects the host belongs to"
@@ -370,7 +383,7 @@ module Katello
370
383
  (found.chomp.split('=', 2).last || '').split(',')
371
384
  else
372
385
  TemplateInvocationInputValue.joins(:template_input).where("template_invocation_id = ? AND template_inputs.name = ?", task.template_invocation_id, 'errata')
373
- .first.value.split(',')
386
+ .first&.value&.split(',') || []
374
387
  end
375
388
  end
376
389
  end
@@ -110,6 +110,7 @@ module Katello
110
110
 
111
111
  class Pulp3Error < StandardError; end
112
112
  class Pulp3MigrationError < StandardError; end
113
+ class Pulp3ExportError < StandardError; end
113
114
 
114
115
  class PulpError < StandardError
115
116
  def self.from_task(task)
@@ -1,3 +1,5 @@
1
+ require 'uri'
2
+
1
3
  module Katello
2
4
  class RepoDiscovery
3
5
  include Katello::Util::HttpProxy
@@ -42,6 +44,72 @@ module Katello
42
44
 
43
45
  private
44
46
 
47
+ def parse_parameter(field_value)
48
+ field_value.lstrip!
49
+ i = field_value.index(/[ \t=;,]/) || field_value.length
50
+ name = field_value.slice!(0, i).downcase(:ascii)
51
+ field_value.lstrip!
52
+ if field_value.delete_prefix!('=')
53
+ field_value.lstrip!
54
+ if field_value.delete_prefix!('"')
55
+ value = ''
56
+ until field_value.empty?
57
+ break if field_value.delete_prefix!('"')
58
+ field_value.delete_prefix!("\\")
59
+ value += field_value.slice!(0, 1) || ''
60
+ end
61
+ else
62
+ i = field_value.index(/[;,]/) || field_value.length
63
+ value = field_value.slice!(0, i)
64
+ end
65
+ end
66
+ {name: name, value: value || ''}
67
+ end
68
+
69
+ def parse_parameters(field_value)
70
+ seen_rel = false
71
+ has_next_rel = false
72
+ has_anchor = false
73
+ until field_value.empty?
74
+ field_value.lstrip!
75
+ break if field_value.delete_prefix!(';').nil?
76
+ param = parse_parameter(field_value)
77
+ case
78
+ when param[:name] == 'rel' && !seen_rel
79
+ seen_rel = true
80
+ has_next_rel = param[:value].downcase(:ascii).split(/[ \t]/).include?('next')
81
+ when param[:name] == 'anchor'
82
+ has_anchor = true
83
+ end
84
+ end
85
+ {has_next_rel: has_next_rel, has_anchor: has_anchor}
86
+ end
87
+
88
+ def get_next_link(link_header)
89
+ # This code mostly follows Appendix B "Algorithms of Parsing Link Header Fields" of RFC 8288
90
+ # "Web Linking", <https://www.rfc-editor.org/rfc/rfc8288#appendix-B> (that RFC appears to be
91
+ # silent about multiple "next" links, so just use the first one and ignore any additional
92
+ # ones, in the general spirit of being lenient):
93
+ return nil if link_header.nil?
94
+ field_value = link_header.clone
95
+ until field_value.empty?
96
+ # The following ignores any junk preceding the next <...> link URL:
97
+ m = field_value.match(/<(.*)>/)
98
+ break unless m
99
+ target_string = m[1]
100
+ field_value = m.post_match
101
+ params = parse_parameters(field_value)
102
+ if params[:has_next_rel]
103
+ # To keep it simple, ignore a link with an (unlikely) anchor parameter; but the RFC
104
+ # mandates that we "MUST NOT process the link without applying the anchor", so just raise
105
+ # an exception in that (unlikely) case:
106
+ fail "anchor not supported" if params[:has_anchor]
107
+ return target_string
108
+ end
109
+ end
110
+ nil
111
+ end
112
+
45
113
  def docker_search
46
114
  request_params = {
47
115
  method: :get,
@@ -49,8 +117,8 @@ module Katello
49
117
  url: "#{@uri}v1/search?q=#{@search}"
50
118
  }
51
119
 
52
- request_params[:headers][:user] = @upstream_username unless @upstream_username.empty?
53
- request_params[:headers][:password] = @upstream_password unless @upstream_password.empty?
120
+ request_params[:user] = @upstream_username unless @upstream_username.empty?
121
+ request_params[:password] = @upstream_password unless @upstream_password.empty?
54
122
  request_params[:proxy] = proxy_uri if proxy
55
123
 
56
124
  begin
@@ -61,9 +129,14 @@ module Katello
61
129
  rescue
62
130
  # Note: v2 endpoint does not support search
63
131
  request_params[:url] = "#{@uri}v2/_catalog"
64
- results = RestClient::Request.execute(request_params)
65
- JSON.parse(results)['repositories'].each do |result|
66
- @found << result
132
+ loop do
133
+ results = RestClient::Request.execute(request_params)
134
+ JSON.parse(results)['repositories'].each do |result|
135
+ @found << result
136
+ end
137
+ next_uri = get_next_link(results.headers[:link])
138
+ break if next_uri.nil?
139
+ request_params[:url] = URI(request_params[:url]).merge(next_uri).to_s
67
140
  end
68
141
  end
69
142
  @found.sort!
@@ -0,0 +1,22 @@
1
+ module Katello
2
+ module Validators
3
+ # ensures that the Default Organization View content view can only be used with the Library environment
4
+ class ContentViewEnvironmentCoherentDefaultValidator < ActiveModel::Validator
5
+ def validate(record)
6
+ #support lifecycle_environment_id for foreman models
7
+ environment_id = record.respond_to?(:lifecycle_environment_id) ? record.lifecycle_environment_id : record.environment_id
8
+ if record.content_view_id
9
+ view = ContentView.where(:id => record.content_view_id).first
10
+ if environment_id
11
+ env = KTEnvironment.where(:id => environment_id).first
12
+ return if view.blank? || env.blank?
13
+ if view.default? && !env.library?
14
+ record.errors[:base] << _("Lifecycle environment '%{env}' cannot be used with content view '%{view}'") %
15
+ {:view => view.name, :env => env.name}
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,6 @@
1
1
  module Katello
2
2
  module Validators
3
+ # used by activation key and content facet
3
4
  class ContentViewEnvironmentValidator < ActiveModel::Validator
4
5
  def validate(record)
5
6
  #support lifecycle_environment_id for foreman models
@@ -0,0 +1,54 @@
1
+ module Katello
2
+ class TaskMailer < ApplicationMailer
3
+ helper ApplicationHelper
4
+ include Rails.application.routes.url_helpers
5
+
6
+ def repo_sync_failure(options)
7
+ user, @repo, @task = options.values_at(:user, :repo, :task)
8
+
9
+ ::User.as(user.login) do
10
+ subject = _("Repository %{label} failed to synchronize") % { :label => @repo.label }
11
+
12
+ set_locale_for(user) do
13
+ mail(:to => user.mail, :subject => subject)
14
+ end
15
+ end
16
+ end
17
+
18
+ def cv_publish_failure(options)
19
+ user, @content_view, @task = options.values_at(:user, :content_view, :task)
20
+
21
+ ::User.as(user.login) do
22
+ subject = _("%{label} failed") % { :label => @task.action }
23
+
24
+ set_locale_for(user) do
25
+ mail(:to => user.mail, :subject => subject)
26
+ end
27
+ end
28
+ end
29
+
30
+ def cv_promote_failure(options)
31
+ user, @content_view, @task = options.values_at(:user, :content_view, :task)
32
+
33
+ ::User.as(user.login) do
34
+ subject = _("%{label} failed") % { :label => @task.action }
35
+
36
+ set_locale_for(user) do
37
+ mail(:to => user.mail, :subject => subject)
38
+ end
39
+ end
40
+ end
41
+
42
+ def proxy_sync_failure(options)
43
+ user, @environment, @repo, @content_view, @task, @smart_proxy = options.values_at(:user, :environment, :repository, :content_view, :task, :smart_proxy)
44
+
45
+ ::User.as(user.login) do
46
+ subject = _("%{label} failed") % { :label => @task.action }
47
+
48
+ set_locale_for(user) do
49
+ mail(:to => user.mail, :subject => subject)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -108,6 +108,8 @@ module Katello
108
108
  delegate :content_source_id, :single_content_view, :single_lifecycle_environment, :default_environment?, :single_content_view_environment?, :multi_content_view_environment?, :kickstart_repository_id, :bound_repositories,
109
109
  :installable_errata, :installable_rpms, to: :content_facet, allow_nil: true
110
110
 
111
+ delegate :release_version, :purpose_role, :purpose_usage, to: :subscription_facet, allow_nil: true
112
+
111
113
  has_many :content_view_environment_content_facets, through: :content_facet, class_name: 'Katello::ContentViewEnvironmentContentFacet'
112
114
  has_many :content_view_environments, through: :content_view_environment_content_facets
113
115
  has_many :content_views, through: :content_view_environments
@@ -481,6 +483,18 @@ module Katello
481
483
  @purpose_addons_status_label ||= get_status(::Katello::PurposeAddonsStatus).to_label(options)
482
484
  end
483
485
 
486
+ def rhel_lifecycle_global_status
487
+ @rhel_lifecycle_global_status ||= get_status(::Katello::RhelLifecycleStatus).to_global
488
+ end
489
+
490
+ def rhel_lifecycle_status
491
+ @rhel_lifecycle_status ||= get_status(::Katello::RhelLifecycleStatus).status
492
+ end
493
+
494
+ def rhel_lifecycle_status_label
495
+ @rhel_lifecycle_status_label ||= get_status(::Katello::RhelLifecycleStatus).to_label
496
+ end
497
+
484
498
  def traces_status
485
499
  @traces_status ||= get_status(::Katello::TraceStatus).status
486
500
  end
@@ -494,6 +508,31 @@ module Katello
494
508
  ::Katello::HostTracer.helpers_for(traces)
495
509
  end
496
510
 
511
+ def probably_rhel?
512
+ # Get the os name from sub-man facts rather than operatingsystem. This is
513
+ # less likely to have been changed by the user.
514
+ os_name, = facts('distribution::name').values # only query for that one fact, then get its value
515
+ # if this fact isn't there, we can ignore it because the host is not "managed"
516
+ os_name.present? && os_name.start_with?('Red Hat Enterprise Linux')
517
+ end
518
+
519
+ def rhel_eos_schedule_index
520
+ return nil unless probably_rhel?
521
+ major = operatingsystem.major
522
+ return "RHEL#{major}" unless major == "7"
523
+ arch_name = architecture&.name
524
+ case arch_name
525
+ when "ppc64le"
526
+ "RHEL7 (POWER9)"
527
+ when "aarch64"
528
+ "RHEL7 (ARM)"
529
+ when "s390x"
530
+ "RHEL7 (System z (Structure A))"
531
+ else
532
+ "RHEL#{major}"
533
+ end
534
+ end
535
+
497
536
  def package_names_for_job_template(action:, search:, versions: nil)
498
537
  actions = %w(install remove update).freeze
499
538
  case action
@@ -550,7 +589,8 @@ class ::Host::Managed::Jail < Safemode::Jail
550
589
  :host_collections, :pools, :hypervisor_host, :installed_debs,
551
590
  :installed_packages, :traces_helpers, :advisory_ids, :package_names_for_job_template,
552
591
  :filtered_entitlement_quantity_consumed, :bound_repositories,
553
- :single_content_view, :single_lifecycle_environment
592
+ :single_content_view, :single_lifecycle_environment, :purpose_role, :purpose_usage, :release_version,
593
+ :purpose_role_status_label, :purpose_usage_status_label
554
594
  end
555
595
 
556
596
  class ActiveRecord::Associations::CollectionProxy::Jail < Safemode::Jail
@@ -248,5 +248,5 @@ module Katello
248
248
  end
249
249
 
250
250
  class ::Organization::Jail < ::Safemode::Jail
251
- allow :label
251
+ allow :label, :simple_content_access?
252
252
  end
@@ -121,6 +121,43 @@ module Katello
121
121
  SmartProxy.joins(:smart_proxy_alternate_content_sources).where('katello_smart_proxy_alternate_content_sources.smart_proxy_id' => self.id)
122
122
  end
123
123
 
124
+ def update_content_counts!
125
+ # {:content_view_versions=>{87=>{:repositories=>{1=>{:metadata=>{},:counts=>{:rpms=>98, :module_streams=>9898}}}}}
126
+ new_content_counts = { content_view_versions: {} }
127
+ smart_proxy_helper = ::Katello::SmartProxyHelper.new(self)
128
+ repos = smart_proxy_helper.repositories_available_to_capsule
129
+
130
+ repos&.each do |repo|
131
+ repo_mirror_service = repo.backend_service(self).with_mirror_adapter
132
+ repo_content_counts = repo_mirror_service.latest_content_counts
133
+ translated_counts = {metadata: {}, counts: {}}
134
+ translated_counts[:metadata] = {
135
+ env_id: repo.environment_id,
136
+ library_instance_id: repo.library_instance_or_self.id,
137
+ product_id: repo.product_id,
138
+ content_type: repo.content_type
139
+ }
140
+ repo_content_counts&.each do |name, count|
141
+ count = count[:count]
142
+ # Some content units in Pulp have the same model
143
+ if name == 'rpm.package' && repo.content_counts['srpm'] > 0
144
+ translated_counts[:counts]['srpm'] = repo_mirror_service.count_by_pulpcore_type(::Katello::Pulp3::Srpm)
145
+ translated_counts[:counts]['rpm'] = count - translated_counts[:counts]['srpm']
146
+ elsif name == 'container.manifest' && repo.content_counts['docker_manifest_list'] > 0
147
+ translated_counts[:counts]['docker_manifest_list'] = repo_mirror_service.count_by_pulpcore_type(::Katello::Pulp3::DockerManifestList)
148
+ translated_counts[:counts]['docker_manifest'] = count - translated_counts[:counts]['docker_manifest_list']
149
+ else
150
+ translated_counts[:counts][::Katello::Pulp3::PulpContentUnit.katello_name_from_pulpcore_name(name, repo)] = count
151
+ end
152
+ end
153
+ new_content_counts[:content_view_versions][repo.content_view_version_id] ||= { repositories: {}}
154
+ # Store counts on capsule of archived repos which are reused across environment copies
155
+ # of the archived repo corresponding to each environment CV version is promoted to.
156
+ new_content_counts[:content_view_versions][repo.content_view_version_id][:repositories][repo.id] = translated_counts
157
+ end
158
+ update(content_counts: new_content_counts)
159
+ end
160
+
124
161
  def sync_container_gateway
125
162
  if has_feature?(::SmartProxy::CONTAINER_GATEWAY_FEATURE)
126
163
  update_container_repo_list
@@ -376,14 +413,30 @@ module Katello
376
413
  scope
377
414
  end
378
415
 
416
+ def last_complete_sync_task
417
+ ForemanTasks::Task.for_resource(self).where(:label => 'Actions::Katello::CapsuleContent::Sync').order(started_at: :desc).detect do |task|
418
+ task.input.with_indifferent_access[:options][:environment_id].nil? &&
419
+ task.input.with_indifferent_access[:options][:content_view_id].nil? &&
420
+ task.input.with_indifferent_access[:options][:repository_id].nil?
421
+ end
422
+ end
423
+
379
424
  def sync_tasks
380
425
  ForemanTasks::Task.for_resource(self).where(:label => 'Actions::Katello::CapsuleContent::Sync')
381
426
  end
382
427
 
428
+ def reclaim_space_tasks
429
+ ForemanTasks::Task.for_resource(self).where(:label => 'Actions::Pulp3::CapsuleContent::ReclaimSpace')
430
+ end
431
+
383
432
  def active_sync_tasks
384
433
  sync_tasks.where(:result => 'pending')
385
434
  end
386
435
 
436
+ def last_failed_reclaim_tasks
437
+ reclaim_space_tasks.where('started_at > ?', last_sync_time).where.not(:result => 'pending')
438
+ end
439
+
387
440
  def last_failed_sync_tasks
388
441
  sync_tasks.where('started_at > ?', last_sync_time).where.not(:result => 'pending')
389
442
  end
@@ -392,16 +445,35 @@ module Katello
392
445
  Audited::Audit.where(:auditable_id => self, :auditable_type => SmartProxy.name, action: "sync capsule").order(:created_at).last
393
446
  end
394
447
 
395
- def last_sync_time
396
- task = sync_tasks.where.not(:ended_at => nil).where(:result => 'success').order(:ended_at).last
448
+ def last_sync_task
449
+ sync_tasks.where.not(:ended_at => nil).where(:result => 'success').order(:ended_at).last
450
+ end
397
451
 
398
- task&.ended_at || last_sync_audit&.created_at&.to_s
452
+ def last_sync_time
453
+ last_sync_task&.ended_at || last_sync_audit&.created_at&.to_s
399
454
  end
400
455
 
401
456
  def environment_syncable?(env)
402
457
  last_sync_time.nil? || env.content_view_environments.where('updated_at > ?', last_sync_time).any?
403
458
  end
404
459
 
460
+ def last_env_sync_task(env)
461
+ last_env_sync_task = sync_tasks.order(ended_at: :desc).detect { |task| task.input.with_indifferent_access[:options][:environment_id] == env.id || task.input.with_indifferent_access[:options][:environment_ids]&.include?(env.id) }
462
+
463
+ # env_ids_task_exists checks if any full syncs have run since we started tracking env_ids at time of sync.
464
+ # If yes, return last_env_sync_task which checks for env_id specific sync + full syncs which contain env as part of env_ids
465
+ env_ids_task_exists = sync_tasks.order(ended_at: :desc).any? { |task| task.input.with_indifferent_access[:options][:environment_ids] }
466
+ return last_env_sync_task if env_ids_task_exists
467
+
468
+ if (last_complete_sync_task&.ended_at && last_env_sync_task&.ended_at)
469
+ return last_complete_sync_task.ended_at > last_env_sync_task.ended_at ? last_complete_sync_task : last_env_sync_task
470
+ elsif last_env_sync_task
471
+ return last_env_sync_task
472
+ elsif last_complete_sync_task
473
+ return last_complete_sync_task
474
+ end
475
+ end
476
+
405
477
  def cancel_sync
406
478
  active_sync_tasks.map(&:cancel)
407
479
  end
@@ -31,6 +31,7 @@ module Katello
31
31
  has_one :purpose_usage_status_object, :class_name => 'Katello::PurposeUsageStatus', :foreign_key => 'host_id', :dependent => :destroy
32
32
  has_one :purpose_addons_status_object, :class_name => 'Katello::PurposeAddonsStatus', :foreign_key => 'host_id', :dependent => :destroy
33
33
  has_one :purpose_status_object, :class_name => 'Katello::PurposeStatus', :foreign_key => 'host_id', :dependent => :destroy
34
+ has_one :rhel_lifecycle_status_object, :class_name => 'Katello::RhelLifecycleStatus', :foreign_key => 'host_id', :dependent => :destroy
34
35
  has_one :hypervisor_host, :through => :subscription_facet
35
36
 
36
37
  scoped_search :on => :status, :relation => :subscription_status_object, :rename => :subscription_status,
@@ -41,6 +42,7 @@ module Katello
41
42
  scoped_search on: :status, relation: :purpose_usage_status_object, rename: :usage_status, complete_value: purpose_status_map
42
43
  scoped_search on: :status, relation: :purpose_addons_status_object, rename: :addons_status, complete_value: purpose_status_map
43
44
  scoped_search on: :status, relation: :purpose_status_object, rename: :purpose_status, complete_value: purpose_status_map
45
+ scoped_search on: :status, relation: :rhel_lifecycle_status_object, rename: :rhel_lifecycle_status, complete_value: rhel_lifecycle_status_map
44
46
 
45
47
  scoped_search :on => :release_version, :relation => :subscription_facet, :complete_value => true, :only_explicit => true
46
48
  scoped_search :on => :autoheal, :relation => :subscription_facet, :complete_value => true, :only_explicit => true
@@ -100,6 +102,10 @@ module Katello
100
102
  ::Katello::PurposeStatus.status_map
101
103
  end
102
104
 
105
+ def rhel_lifecycle_status_map
106
+ ::Katello::RhelLifecycleStatus.status_map
107
+ end
108
+
103
109
  def find_by_purpose_addon(_key, operator, value)
104
110
  conditions = sanitize_sql_for_conditions(["#{Katello::PurposeAddon.table_name}.name #{operator} ?", value_to_sql(operator, value)])
105
111
  hosts = ::Host::Managed.joins(:purpose_addons).where(conditions)
@@ -111,6 +111,27 @@ module Katello
111
111
  scoped_search :on => :composite, :complete_value => true
112
112
  scoped_search :on => :generated_for, :complete_value => true
113
113
  scoped_search :on => :default # just for ordering
114
+ scoped_search :on => :name, :complete_value => true,
115
+ :rename => :content_views,
116
+ :operators => ['='],
117
+ :ext_method => :find_components_by_cv_name
118
+
119
+ def self.find_components_by_cv_name(_key, operator, value)
120
+ kcv = Katello::ContentView.table_name
121
+ kcvc = Katello::ContentViewComponent.table_name
122
+ { :conditions => "#{kcv}.composite = 't' AND #{kcv}.id IN (SELECT #{kcvc}.composite_content_view_id FROM #{kcvc} WHERE #{kcvc}.content_view_id IN (SELECT #{kcv}.id FROM #{kcv} WHERE #{kcv}.name #{operator} ?))",
123
+ :parameter => [value]
124
+ }
125
+ end
126
+
127
+ def self.completer_scope_options(search)
128
+ if search.include?('content_views')
129
+ # Don't autocomplete CCV names when searching for components
130
+ { :value_filter => { :composite => false } }
131
+ else
132
+ {}
133
+ end
134
+ end
114
135
 
115
136
  enum generated_for: {
116
137
  none: 0,
@@ -19,6 +19,7 @@ module Katello
19
19
  validates :environment_id, uniqueness: {scope: :content_view_id}, presence: true
20
20
  validates :content_view_id, presence: true
21
21
  validates_with Validators::ContentViewEnvironmentOrgValidator
22
+ validates_with Validators::ContentViewEnvironmentCoherentDefaultValidator
22
23
 
23
24
  before_save :generate_info
24
25
 
@@ -42,6 +43,10 @@ module Katello
42
43
  content_view.activation_keys.in_environment(environment)
43
44
  end
44
45
 
46
+ def default_environment?
47
+ content_view.default? && environment.library?
48
+ end
49
+
45
50
  # TODO: uncomment when we need to start showing multiple CVE names in UI
46
51
  # def candlepin_name
47
52
  # "#{environment.label}/#{content_view.label}"
@@ -52,7 +57,7 @@ module Katello
52
57
  def generate_info
53
58
  self.name ||= environment.name
54
59
 
55
- if content_view.default?
60
+ if default_environment?
56
61
  self.label ||= environment.label
57
62
  self.cp_id ||= Katello::Util::Data.hexdigest(environment.organization.label)
58
63
  else
@@ -111,7 +111,7 @@ module Katello
111
111
  if grouped
112
112
  grouped_fields = "#{table_name}.name, katello_repositories.root_id"
113
113
  ids = distinct.select("ON (#{grouped_fields}) #{table_name}.id").joins(:repositories)
114
- self.where(:id => ids)
114
+ self.where(:id => ids).where("#{self.table_name}.schema1_id in (#{sql}) or #{self.table_name}.schema2_id in (#{sql})")
115
115
  else
116
116
  self.where("#{self.table_name}.schema1_id in (#{sql}) or #{self.table_name}.schema2_id in (#{sql})")
117
117
  end
@@ -73,7 +73,7 @@ module Katello
73
73
  self.where(:id => ids)
74
74
  end
75
75
 
76
- def self.completer_scope_options
76
+ def self.completer_scope_options(_search)
77
77
  {"#{Katello::Repository.table_name}" => lambda { |repo_class| repo_class.docker_type } }
78
78
  end
79
79
 
@@ -71,7 +71,7 @@ module Katello
71
71
  # It is not the errata "belonging" to the host. Its rather the errata that is "applicable"
72
72
  # which is calculated elsewhere.
73
73
 
74
- self.joins(:content_facets).
74
+ self.group(:id).distinct.joins(:content_facets).
75
75
  where("#{Katello::Host::ContentFacet.table_name}.host_id" => hosts.select(:id))
76
76
  end
77
77
 
@@ -8,6 +8,9 @@ module Katello
8
8
  HOST_TOOLS_PACKAGE_NAME = 'katello-host-tools'.freeze
9
9
  HOST_TOOLS_TRACER_PACKAGE_NAME = 'katello-host-tools-tracer'.freeze
10
10
  SUBSCRIPTION_MANAGER_PACKAGE_NAME = 'subscription-manager'.freeze
11
+ ALL_TRACER_PACKAGE_NAMES = [ "python-#{HOST_TOOLS_TRACER_PACKAGE_NAME}",
12
+ "python3-#{HOST_TOOLS_TRACER_PACKAGE_NAME}",
13
+ HOST_TOOLS_TRACER_PACKAGE_NAME ].freeze
11
14
 
12
15
  belongs_to :kickstart_repository, :class_name => "::Katello::Repository", :inverse_of => :kickstart_content_facets
13
16
  belongs_to :content_source, :class_name => "::SmartProxy", :inverse_of => :content_facets
@@ -207,7 +210,7 @@ module Katello
207
210
  ::Katello::Applicability::ApplicableContentHelper.new(self, ::Katello::Erratum, bound_repos).calculate_and_import
208
211
  ::Katello::Applicability::ApplicableContentHelper.new(self, ::Katello::ModuleStream, bound_repos).calculate_and_import
209
212
  update_applicability_counts
210
- self.update_errata_status
213
+ self.host&.refresh_statuses([::Katello::ErrataStatus, ::Katello::RhelLifecycleStatus])
211
214
  end
212
215
 
213
216
  def update_applicability_counts
@@ -305,12 +308,12 @@ module Katello
305
308
  end
306
309
 
307
310
  def tracer_installed?
308
- self.host.installed_packages.where("#{Katello::InstalledPackage.table_name}.name" => [ "python-#{HOST_TOOLS_TRACER_PACKAGE_NAME}",
309
- "python3-#{HOST_TOOLS_TRACER_PACKAGE_NAME}",
310
- HOST_TOOLS_TRACER_PACKAGE_NAME ]).any? ||
311
- self.host.installed_debs.where("#{Katello::InstalledDeb.table_name}.name" => [ "python-#{HOST_TOOLS_TRACER_PACKAGE_NAME}",
312
- "python3-#{HOST_TOOLS_TRACER_PACKAGE_NAME}",
313
- HOST_TOOLS_TRACER_PACKAGE_NAME ]).any?
311
+ self.host.installed_packages.where("#{Katello::InstalledPackage.table_name}.name" => ALL_TRACER_PACKAGE_NAMES).any? ||
312
+ self.host.installed_debs.where("#{Katello::InstalledDeb.table_name}.name" => ALL_TRACER_PACKAGE_NAMES).any?
313
+ end
314
+
315
+ def tracer_rpm_available?
316
+ ::Katello::Rpm.yum_installable_for_host(self.host).where(name: ALL_TRACER_PACKAGE_NAMES).any?
314
317
  end
315
318
 
316
319
  def host_tools_installed?
@@ -34,6 +34,7 @@ module Katello
34
34
  validates_lengths_from_database :except => [:label]
35
35
  validates :provider_id, :presence => true
36
36
  validate :ensure_provider_type_matches_id
37
+ validate :ensure_no_sync_plans_on_empty_product
37
38
  validates_with Validators::KatelloNameFormatValidator, :attributes => :name
38
39
  validates_with Validators::KatelloLabelFormatValidator, :attributes => :label
39
40
  validates_with Validators::ProductUniqueAttributeValidator, :attributes => :name
@@ -263,5 +264,12 @@ module Katello
263
264
  errors.add(:base, _("Cannot associate a Red Hat provider with a custom product"))
264
265
  end
265
266
  end
267
+
268
+ def ensure_no_sync_plans_on_empty_product
269
+ return if sync_plan_id.nil?
270
+ if redhat? && !enabled?
271
+ errors.add(:base, _("Cannot add disabled Red Hat product %s to sync plan!") % name)
272
+ end
273
+ end
266
274
  end
267
275
  end