katello 4.12.0.rc3 → 4.13.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 (244) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/app/assets/javascripts/katello/locale/bn/katello.js +3365 -3350
  4. data/app/assets/javascripts/katello/locale/bn_IN/katello.js +3136 -3121
  5. data/app/assets/javascripts/katello/locale/ca/katello.js +3588 -3576
  6. data/app/assets/javascripts/katello/locale/cs/katello.js +3499 -3487
  7. data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +4186 -4186
  8. data/app/assets/javascripts/katello/locale/de/katello.js +5553 -5562
  9. data/app/assets/javascripts/katello/locale/de_AT/katello.js +3008 -2993
  10. data/app/assets/javascripts/katello/locale/de_DE/katello.js +3066 -3051
  11. data/app/assets/javascripts/katello/locale/el/katello.js +3376 -3370
  12. data/app/assets/javascripts/katello/locale/en/katello.js +3008 -2993
  13. data/app/assets/javascripts/katello/locale/en_GB/katello.js +3076 -3073
  14. data/app/assets/javascripts/katello/locale/en_US/katello.js +3008 -2993
  15. data/app/assets/javascripts/katello/locale/es/katello.js +5366 -5372
  16. data/app/assets/javascripts/katello/locale/et_EE/katello.js +3008 -2993
  17. data/app/assets/javascripts/katello/locale/fr/katello.js +5975 -5984
  18. data/app/assets/javascripts/katello/locale/gl/katello.js +3125 -3113
  19. data/app/assets/javascripts/katello/locale/gu/katello.js +3119 -3104
  20. data/app/assets/javascripts/katello/locale/he_IL/katello.js +3020 -3005
  21. data/app/assets/javascripts/katello/locale/hi/katello.js +3137 -3122
  22. data/app/assets/javascripts/katello/locale/id/katello.js +3008 -2993
  23. data/app/assets/javascripts/katello/locale/it/katello.js +4469 -4466
  24. data/app/assets/javascripts/katello/locale/ja/katello.js +5969 -5978
  25. data/app/assets/javascripts/katello/locale/ka/katello.js +5649 -5652
  26. data/app/assets/javascripts/katello/locale/kn/katello.js +3136 -3121
  27. data/app/assets/javascripts/katello/locale/ko/katello.js +4717 -4720
  28. data/app/assets/javascripts/katello/locale/locale/katello.js +1050 -1084
  29. data/app/assets/javascripts/katello/locale/ml_IN/katello.js +3008 -2993
  30. data/app/assets/javascripts/katello/locale/mr/katello.js +3136 -3121
  31. data/app/assets/javascripts/katello/locale/nl_NL/katello.js +3116 -3101
  32. data/app/assets/javascripts/katello/locale/or/katello.js +3137 -3122
  33. data/app/assets/javascripts/katello/locale/pa/katello.js +3136 -3121
  34. data/app/assets/javascripts/katello/locale/pl/katello.js +3210 -3195
  35. data/app/assets/javascripts/katello/locale/pl_PL/katello.js +3008 -2993
  36. data/app/assets/javascripts/katello/locale/pt/katello.js +3009 -2994
  37. data/app/assets/javascripts/katello/locale/pt_BR/katello.js +5362 -5368
  38. data/app/assets/javascripts/katello/locale/ro/katello.js +3008 -2993
  39. data/app/assets/javascripts/katello/locale/ro_RO/katello.js +3008 -2993
  40. data/app/assets/javascripts/katello/locale/ru/katello.js +4638 -4641
  41. data/app/assets/javascripts/katello/locale/sl/katello.js +3051 -3036
  42. data/app/assets/javascripts/katello/locale/sv_SE/katello.js +3156 -3144
  43. data/app/assets/javascripts/katello/locale/ta/katello.js +3365 -3350
  44. data/app/assets/javascripts/katello/locale/ta_IN/katello.js +3121 -3106
  45. data/app/assets/javascripts/katello/locale/te/katello.js +3136 -3121
  46. data/app/assets/javascripts/katello/locale/tr/katello.js +3025 -3010
  47. data/app/assets/javascripts/katello/locale/vi/katello.js +3008 -2993
  48. data/app/assets/javascripts/katello/locale/vi_VN/katello.js +3008 -2993
  49. data/app/assets/javascripts/katello/locale/zh/katello.js +3008 -2993
  50. data/app/assets/javascripts/katello/locale/zh_CN/katello.js +5968 -5977
  51. data/app/assets/javascripts/katello/locale/zh_TW/katello.js +4694 -4697
  52. data/app/assets/javascripts/katello/sync_management/sync_management.js +1 -0
  53. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +51 -124
  54. data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -20
  55. data/app/controllers/katello/api/v2/activation_keys_controller.rb +10 -4
  56. data/app/controllers/katello/api/v2/capsule_content_controller.rb +24 -0
  57. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +9 -2
  58. data/app/controllers/katello/api/v2/debs_controller.rb +1 -1
  59. data/app/controllers/katello/api/v2/errata_controller.rb +1 -1
  60. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +12 -4
  61. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +3 -3
  62. data/app/controllers/katello/api/v2/organizations_controller.rb +0 -11
  63. data/app/controllers/katello/api/v2/packages_controller.rb +1 -1
  64. data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -1
  65. data/app/controllers/katello/api/v2/repositories_controller.rb +18 -12
  66. data/app/controllers/katello/api/v2/repository_sets_controller.rb +2 -1
  67. data/app/controllers/katello/api/v2/simple_content_access_controller.rb +9 -22
  68. data/app/controllers/katello/concerns/api/v2/authorization.rb +1 -1
  69. data/app/helpers/katello/concerns/dashboard_helper_extensions.rb +0 -10
  70. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +14 -2
  71. data/app/helpers/katello/katello_urls_helper.rb +26 -1
  72. data/app/helpers/katello/subscription_mailer_helper.rb +1 -1
  73. data/app/jobs/create_manifest_expire_soon_warning_notifications.rb +11 -0
  74. data/app/lib/actions/candlepin/owner/regenerate_upstream_identity_cert.rb +21 -0
  75. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  76. data/app/lib/actions/katello/capsule_content/verify_checksum.rb +75 -0
  77. data/app/lib/actions/katello/content_view/promote.rb +1 -1
  78. data/app/lib/actions/katello/content_view/publish.rb +1 -1
  79. data/app/lib/actions/katello/content_view_version/verify_checksum.rb +29 -0
  80. data/app/lib/actions/katello/host/hypervisors_update.rb +1 -0
  81. data/app/lib/actions/katello/host/update_content_view.rb +2 -2
  82. data/app/lib/actions/katello/organization/manifest_import.rb +5 -0
  83. data/app/lib/actions/katello/organization/manifest_refresh.rb +3 -0
  84. data/app/lib/actions/katello/repository/metadata_generate.rb +7 -1
  85. data/app/lib/actions/katello/repository/remove_content.rb +1 -0
  86. data/app/lib/actions/katello/repository/sync.rb +2 -1
  87. data/app/lib/actions/katello/repository/upload_files.rb +1 -0
  88. data/app/lib/actions/pulp3/capsule_content/verify_checksum.rb +27 -0
  89. data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +7 -9
  90. data/app/lib/actions/pulp3/orchestration/content_view_version/syncable_export.rb +5 -4
  91. data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -2
  92. data/app/lib/katello/errors.rb +4 -0
  93. data/app/lib/katello/http_resource.rb +6 -1
  94. data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
  95. data/app/lib/katello/resources/candlepin/upstream_consumer.rb +18 -6
  96. data/app/lib/katello/resources/candlepin/upstream_job.rb +1 -1
  97. data/app/lib/katello/resources/cdn.rb +4 -13
  98. data/app/lib/katello/resources/registry.rb +25 -0
  99. data/app/mailers/katello/subscription_mailer.rb +3 -6
  100. data/app/models/katello/candlepin/repository_mapper.rb +1 -1
  101. data/app/models/katello/concerns/organization_extensions.rb +42 -3
  102. data/app/models/katello/content_view.rb +28 -0
  103. data/app/models/katello/content_view_environment_content_facet.rb +4 -2
  104. data/app/models/katello/glue/provider.rb +19 -12
  105. data/app/models/katello/glue/pulp/repos.rb +3 -8
  106. data/app/models/katello/host/content_facet.rb +1 -1
  107. data/app/models/katello/host/subscription_facet.rb +1 -1
  108. data/app/models/katello/host_collection.rb +12 -3
  109. data/app/models/katello/ping.rb +1 -1
  110. data/app/models/katello/repository.rb +33 -0
  111. data/app/models/katello/root_repository.rb +0 -4
  112. data/app/services/katello/content_unit_indexer.rb +9 -0
  113. data/app/services/katello/pulp3/alternate_content_source.rb +6 -8
  114. data/app/services/katello/pulp3/api/core.rb +13 -0
  115. data/app/services/katello/pulp3/api/yum.rb +11 -0
  116. data/app/services/katello/pulp3/docker_manifest.rb +5 -1
  117. data/app/services/katello/pulp3/repository/generic.rb +1 -1
  118. data/app/services/katello/pulp3/repository.rb +26 -6
  119. data/app/services/katello/pulp3/repository_mirror.rb +13 -12
  120. data/app/services/katello/pulp3/service_common.rb +2 -10
  121. data/app/services/katello/pulp3/smart_proxy_repository.rb +0 -2
  122. data/app/services/katello/ui_notifications/subscriptions/manifest_expire_soon_warning.rb +75 -0
  123. data/app/views/foreman/job_templates/update_package_-_katello_ansible_default.erb +5 -1
  124. data/app/views/foreman/job_templates/update_packages_by_search_query_-_katello_ansible_default.erb +2 -2
  125. data/app/views/foreman/job_templates/upload_profile.erb +16 -0
  126. data/app/views/katello/api/v2/content_view_filter_rules/show.json.rabl +9 -0
  127. data/app/views/katello/api/v2/docker_manifests/show.json.rabl +1 -0
  128. data/app/views/katello/api/v2/hosts/host_collections.json.rabl +5 -1
  129. data/app/views/katello/api/v2/organizations/show.json.rabl +9 -1
  130. data/app/views/katello/hosts/_errata_counts.html.erb +1 -1
  131. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +1 -1
  132. data/app/views/overrides/activation_keys/_host_media_type_select.html.erb +15 -5
  133. data/app/views/overrides/activation_keys/_host_tab_pane.html.erb +1 -29
  134. data/config/routes/api/registry.rb +4 -8
  135. data/config/routes/api/v2.rb +2 -0
  136. data/db/migrate/20240423112842_add_fields_to_katello_docker_manifest.rb +8 -0
  137. data/db/migrate/20240502192021_change_katello_repository_rpms_id_seq_to_big_int.rb +9 -0
  138. data/db/seeds.d/109-katello-notification-blueprints.rb +6 -0
  139. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-repository-sets.controller.js +3 -3
  140. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +2 -1
  141. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-repository-sets.controller.js +3 -3
  142. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +0 -15
  143. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +8 -6
  144. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +12 -10
  145. data/lib/katello/permission_creator.rb +3 -3
  146. data/lib/katello/permissions/registry_permissions.rb +4 -7
  147. data/lib/katello/plugin.rb +10 -16
  148. data/lib/katello/repository_types/ostree.rb +7 -0
  149. data/lib/katello/scheduled_jobs.rb +7 -1
  150. data/lib/katello/tasks/clean_backend_objects.rake +1 -1
  151. data/lib/katello/tasks/repository.rake +22 -0
  152. data/lib/katello/version.rb +1 -1
  153. data/locale/action_names.rb +4 -3
  154. data/locale/bn/katello.po +166 -151
  155. data/locale/bn_IN/katello.po +166 -151
  156. data/locale/ca/katello.po +166 -151
  157. data/locale/cs/katello.po +166 -151
  158. data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
  159. data/locale/cs_CZ/katello.po +172 -157
  160. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  161. data/locale/de/katello.po +178 -163
  162. data/locale/de_AT/katello.po +166 -151
  163. data/locale/de_DE/katello.po +166 -151
  164. data/locale/el/katello.po +166 -151
  165. data/locale/en/katello.po +166 -151
  166. data/locale/en_GB/katello.po +166 -151
  167. data/locale/en_US/katello.po +166 -151
  168. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  169. data/locale/es/katello.po +178 -163
  170. data/locale/et_EE/katello.po +166 -151
  171. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  172. data/locale/fr/katello.po +179 -164
  173. data/locale/gl/katello.po +166 -151
  174. data/locale/gu/katello.po +166 -151
  175. data/locale/he_IL/katello.po +166 -151
  176. data/locale/hi/katello.po +166 -151
  177. data/locale/id/katello.po +166 -151
  178. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  179. data/locale/it/katello.po +169 -154
  180. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  181. data/locale/ja/katello.po +179 -164
  182. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  183. data/locale/ka/katello.po +177 -162
  184. data/locale/katello.pot +1119 -1062
  185. data/locale/kn/katello.po +166 -151
  186. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  187. data/locale/ko/katello.po +174 -159
  188. data/locale/ml_IN/katello.po +166 -151
  189. data/locale/mr/katello.po +166 -151
  190. data/locale/nl_NL/katello.po +166 -151
  191. data/locale/or/katello.po +166 -151
  192. data/locale/pa/katello.po +166 -151
  193. data/locale/pl/katello.po +166 -151
  194. data/locale/pl_PL/katello.po +166 -151
  195. data/locale/pt/katello.po +166 -151
  196. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  197. data/locale/pt_BR/katello.po +178 -163
  198. data/locale/ro/katello.po +166 -151
  199. data/locale/ro_RO/katello.po +166 -151
  200. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  201. data/locale/ru/katello.po +171 -156
  202. data/locale/sl/katello.po +166 -151
  203. data/locale/sv_SE/katello.po +166 -151
  204. data/locale/ta/katello.po +166 -151
  205. data/locale/ta_IN/katello.po +166 -151
  206. data/locale/te/katello.po +166 -151
  207. data/locale/tr/katello.po +166 -151
  208. data/locale/vi/katello.po +166 -151
  209. data/locale/vi_VN/katello.po +166 -151
  210. data/locale/zh/katello.po +166 -151
  211. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  212. data/locale/zh_CN/katello.po +179 -164
  213. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  214. data/locale/zh_TW/katello.po +171 -156
  215. data/webpack/ForemanColumnExtensions/index.js +129 -0
  216. data/webpack/components/ActivationKeysSearch/ActivationKeysSearch.test.js +28 -0
  217. data/webpack/components/ActivationKeysSearch/index.js +222 -0
  218. data/webpack/components/Table/TableWrapper.js +14 -0
  219. data/webpack/components/extensions/HostDetails/ActionsBar/index.js +1 -1
  220. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +1 -1
  221. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +1 -0
  222. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +1 -0
  223. data/webpack/components/extensions/Hosts/ActionsBar/index.js +20 -1
  224. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/BulkChangeHostCVModal.js +220 -0
  225. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/actions.js +23 -0
  226. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/index.js +25 -0
  227. data/webpack/components/extensions/Hosts/BulkActions/__tests__/bulkChangeHostCVModal.test.js +133 -0
  228. data/webpack/global_index.js +19 -0
  229. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +6 -3
  230. data/webpack/scenes/ContentViews/Publish/CVPublishForm.js +1 -1
  231. data/webpack/scenes/ContentViews/Publish/__tests__/publishContentView.test.js +30 -0
  232. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +3 -1
  233. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +63 -25
  234. data/webpack/scenes/Hosts/ChangeContentSource/index.js +24 -16
  235. data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +1 -0
  236. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +64 -5
  237. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +16 -13
  238. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +14 -8
  239. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +1 -0
  240. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +1 -1
  241. metadata +59 -40
  242. data/app/assets/javascripts/katello/hosts/activation_key_edit.js +0 -167
  243. data/app/lib/actions/katello/host/upload_package_profile.rb +0 -45
  244. data/app/lib/actions/katello/host/upload_profiles.rb +0 -47
@@ -1,42 +1,29 @@
1
1
  module Katello
2
2
  class Api::V2::SimpleContentAccessController < Api::V2::ApiController
3
- before_action :find_organization
4
-
5
3
  resource_description do
6
4
  description "Red Hat subscriptions management platform."
7
5
  api_version 'v2'
8
6
  end
9
7
 
10
- api :GET, "/organizations/:organization_id/simple_content_access/eligible",
11
- N_("Check if the specified organization is eligible for Simple Content Access. %s") % sca_only_deprecation_text, deprecated: true
8
+ def render_sca_410_error
9
+ render_error 'custom_error', status: :gone,
10
+ locals: { message: N_('Simple Content Access is the only supported content access mode') }
11
+ end
12
+
12
13
  def eligible
13
- ::Foreman::Deprecation.api_deprecation_warning(N_("This endpoint is deprecated and will be removed in Katello 4.12. All organizations are now eligible for Simple Content Access."))
14
- eligible = @organization.simple_content_access_eligible?
15
- render json: { simple_content_access_eligible: eligible }
14
+ render_sca_410_error
16
15
  end
17
16
 
18
- api :GET, "/organizations/:organization_id/simple_content_access/status",
19
- N_("Check if the specified organization has Simple Content Access enabled. %s") % sca_only_deprecation_text, deprecated: true
20
- param :organization_id, :number, :desc => N_("Organization ID"), :required => true
21
17
  def status
22
- status = @organization.simple_content_access?
23
- render json: { simple_content_access: status }
18
+ render_sca_410_error
24
19
  end
25
20
 
26
- api :PUT, "/organizations/:organization_id/simple_content_access/enable",
27
- N_("Enable simple content access for a manifest"), deprecated: true
28
- param :organization_id, :number, :desc => N_("Organization ID"), :required => true
29
21
  def enable
30
- task = async_task(::Actions::Katello::Organization::SimpleContentAccess::Enable, params[:organization_id])
31
- respond_for_async :resource => task
22
+ render_sca_410_error
32
23
  end
33
24
 
34
- api :PUT, "/organizations/:organization_id/simple_content_access/disable",
35
- N_("Disable simple content access for a manifest. %s") % sca_only_deprecation_text, deprecated: true
36
- param :organization_id, :number, :desc => N_("Organization ID"), :required => true
37
25
  def disable
38
- task = async_task(::Actions::Katello::Organization::SimpleContentAccess::Disable, params[:organization_id])
39
- respond_for_async :resource => task
26
+ render_sca_410_error
40
27
  end
41
28
  end
42
29
  end
@@ -49,7 +49,7 @@ module Katello
49
49
 
50
50
  # promote_or_remove_content_views_to_environments has a special relationship to promote_or_remove_content_views
51
51
  if path_to_authenticate["controller"] == "katello/api/v2/content_view_versions" &&
52
- path_to_authenticate["action"].in?(["promote", "remove_from_environment", "remove", "republish_repositories"])
52
+ path_to_authenticate["action"].in?(["promote", "remove_from_environment", "remove", "republish_repositories", "verify_checksum"])
53
53
  missing_perms << ::Permission.find_by(name: "promote_or_remove_content_views_to_environments")
54
54
  end
55
55
  missing_perms
@@ -8,16 +8,6 @@ module Katello
8
8
  def total_host_count
9
9
  host_query.size
10
10
  end
11
-
12
- def removed_widgets
13
- widgets = super
14
-
15
- if Organization.current&.simple_content_access?
16
- widgets.reject! { |widget| ::Widget.singleton_class::SUBSCRIPTION_TEMPLATES.include? widget[:template] }
17
- end
18
-
19
- widgets
20
- end
21
11
  end
22
12
  end
23
13
  end
@@ -72,6 +72,10 @@ module Katello
72
72
  def fetch_lifecycle_environment(host_or_hostgroup, options = {})
73
73
  return host_or_hostgroup.single_lifecycle_environment if host_or_hostgroup.try(:single_lifecycle_environment)
74
74
  return host_or_hostgroup.lifecycle_environment if host_or_hostgroup.try(:lifecycle_environment)
75
+ if host_or_hostgroup.is_a?(::Hostgroup) && host_or_hostgroup.content_facet.present?
76
+ # to handle cloned hostgroups that are new records
77
+ return host_or_hostgroup.content_facet.lifecycle_environment
78
+ end
75
79
  selected_host_group = options.fetch(:selected_host_group, nil)
76
80
  return selected_host_group.lifecycle_environment if selected_host_group.present?
77
81
  end
@@ -79,12 +83,20 @@ module Katello
79
83
  def fetch_content_view(host_or_hostgroup, options = {})
80
84
  return host_or_hostgroup.single_content_view if host_or_hostgroup.try(:single_content_view)
81
85
  return host_or_hostgroup.content_view if host_or_hostgroup.try(:content_view)
86
+ if host_or_hostgroup.is_a?(::Hostgroup) && host_or_hostgroup.content_facet.present?
87
+ # to handle cloned hostgroups that are new records
88
+ return host_or_hostgroup.content_facet.content_view
89
+ end
82
90
  selected_host_group = options.fetch(:selected_host_group, nil)
83
91
  return selected_host_group.content_view if selected_host_group.present?
84
92
  end
85
93
 
86
- def fetch_content_source(host, options = {})
87
- return host.content_source if host.try(:content_source_id)
94
+ def fetch_content_source(host_or_hostgroup, options = {})
95
+ return host_or_hostgroup.content_source if host_or_hostgroup.content_source_id&.present? && host_or_hostgroup.persisted?
96
+ if host_or_hostgroup.is_a?(::Hostgroup) && host_or_hostgroup.content_facet.present?
97
+ # to handle cloned hostgroups that are new records
98
+ return host_or_hostgroup.content_facet.content_source
99
+ end
88
100
  selected_host_group = options.fetch(:selected_host_group, nil)
89
101
  return selected_host_group.content_source if selected_host_group.present?
90
102
  end
@@ -37,11 +37,36 @@ module Katello
37
37
  "#{prefix}/pub/#{config}"
38
38
  end
39
39
 
40
- apipie :method, 'Generates an absolute path to the file' do
40
+ apipie :method, 'Generates an absolute path to the file for liveimg kickstart templates' do
41
41
  required :content_path, String, desc: "Relative path to the file or it's name"
42
42
  optional :schema, String, desc: 'Optional URL schema for the content source', default: 'http'
43
43
  optional :content_type, String, desc: 'Content type', default: 'repos'
44
44
  returns String, desc: 'Absolute path to a file'
45
45
  end
46
+ def repository_url(content_path, _content_type = nil, schema = 'http')
47
+ return content_path if content_path =~ %r|^([\w\-\+]+)://|
48
+ url = if @host.content_source
49
+ "#{schema}://#{@host.content_source.hostname}"
50
+ else
51
+ foreman_settings_url(schema)
52
+ end
53
+ content_path = content_path.sub(%r|^/|, '')
54
+
55
+ lifecycle_environment = nil
56
+ if @host.default_environment?
57
+ # Don't update the content_path if the host is using the default org view / library
58
+ lifecycle_environment = ::Katello::KTEnvironment.library.find_by(organization_id: @host.organization_id)
59
+ elsif !@host.single_content_view_environment?
60
+ fail ::Katello::Errors::MultiEnvironmentNotSupportedError,
61
+ "Host #{@host.name} must be subscribed to only a single content view & environment or subscribe to the default organization content view for liveimg provisioning."
62
+ else
63
+ lifecycle_environment = @host.single_lifecycle_environment
64
+ content_path = [@host.single_content_view.label, content_path].join('/')
65
+ end
66
+
67
+ path = ::Katello::Repository.repo_path_from_content_path(
68
+ lifecycle_environment, content_path)
69
+ "#{url}/pulp/content/#{path}"
70
+ end
46
71
  end
47
72
  end
@@ -13,7 +13,7 @@ module Katello
13
13
  end
14
14
 
15
15
  def start_report_task(days_from_now)
16
- @report_template = ReportTemplate.find_by(name: "Subscription - Entitlement Report")
16
+ @report_template = ReportTemplate.find_by(name: "Subscription - General Report")
17
17
  template_input_id = @report_template.template_inputs.find_by_name("Days from Now").id.to_s
18
18
  params = { format: 'csv', template_id: @report_template.id, input_values: { template_input_id => { value: days_from_now} } }
19
19
  composer = ReportComposer.new(params)
@@ -0,0 +1,11 @@
1
+ class CreateManifestExpireSoonWarningNotifications < ApplicationJob
2
+ def perform
3
+ Katello::UINotifications::Subscriptions::ManifestExpireSoonWarning.deliver!
4
+ ensure
5
+ self.class.set(:wait => 24.hours).perform_later
6
+ end
7
+
8
+ def humanized_name
9
+ _('Subscription Manifest expiration date check')
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module Actions
2
+ module Candlepin
3
+ module Owner
4
+ class RegenerateUpstreamIdentityCert < Candlepin::Abstract
5
+ input_format do
6
+ param :organization_id
7
+ param :upstream
8
+ end
9
+
10
+ def run
11
+ organization = ::Organization.find(input[:organization_id])
12
+ output[:response] = organization.redhat_provider.owner_upstream_regenerate_identity_cert(input[:upstream])
13
+ end
14
+
15
+ def rescue_strategy
16
+ Dynflow::Action::Rescue::Skip
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -52,7 +52,7 @@ module Actions
52
52
  notification = MailNotification[:proxy_sync_failure]
53
53
  proxy = SmartProxy.find(input.fetch(:smart_proxy, {})[:id])
54
54
  subjects = subjects(input[:options]).merge(smart_proxy: proxy)
55
- notification.users.where(disabled: [nil, false], mail_enabled: true).each do |user|
55
+ notification.users.with_enabled_email.each do |user|
56
56
  notification.deliver(subjects.merge(user: user, task: task))
57
57
  end
58
58
  end
@@ -0,0 +1,75 @@
1
+ module Actions
2
+ module Katello
3
+ module CapsuleContent
4
+ class VerifyChecksum < ::Actions::EntryAction
5
+ def humanized_name
6
+ _("Verify checksum for content on smart proxy")
7
+ end
8
+
9
+ def plan(smart_proxy, options = {})
10
+ input[:options] = options
11
+ action_subject(smart_proxy)
12
+ fail _("Action not allowed for the default smart proxy.") if smart_proxy.pulp_primary?
13
+ subjects = subjects(options)
14
+ repair_options = options.merge(subjects)
15
+ environment = repair_options[:environment]
16
+ content_view = repair_options[:content_view]
17
+ check_cv_capsule_environments!(smart_proxy, content_view, environment)
18
+ repository = repair_options[:repository]
19
+ repos = repos_to_repair(smart_proxy, environment, content_view, repository)
20
+ repos.in_groups_of(Setting[:foreman_proxy_content_batch_size], false) do |repo_batch|
21
+ concurrence do
22
+ repo_batch.each do |repo|
23
+ if smart_proxy.pulp3_support?(repo)
24
+ plan_action(Actions::Pulp3::CapsuleContent::VerifyChecksum,
25
+ repo,
26
+ smart_proxy)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def repos_to_repair(smart_proxy, environment, content_view, repository)
34
+ smart_proxy_helper = ::Katello::SmartProxyHelper.new(smart_proxy)
35
+ smart_proxy_helper.lifecycle_environment_check(environment, repository)
36
+ if repository
37
+ [repository]
38
+ else
39
+ repositories = smart_proxy_helper.repositories_available_to_capsule(environment, content_view).by_rpm_count
40
+ repositories
41
+ end
42
+ end
43
+
44
+ def check_cv_capsule_environments!(smart_proxy, content_view, environment)
45
+ cv_environments = content_view&.versions&.collect(&:environments)&.flatten
46
+ if cv_environments.present?
47
+ if environment.present? && !(cv_environments.pluck(:id).include? environment.id)
48
+ fail _("Content view '%{content_view}' is not attached to the environment.") % {content_view: content_view.name}
49
+ end
50
+ if (smart_proxy.lifecycle_environments.pluck(:id) & cv_environments.pluck(:id)).empty?
51
+ fail _("Content view '%{content_view}' is not attached to this capsule.") % {content_view: content_view.name}
52
+ end
53
+ end
54
+ end
55
+
56
+ def subjects(options = {})
57
+ environment_id = options.fetch(:environment_id, nil)
58
+ environment = ::Katello::KTEnvironment.find(environment_id) if environment_id
59
+
60
+ repository_id = options.fetch(:repository_id, nil)
61
+ repository = ::Katello::Repository.find(repository_id) if repository_id
62
+
63
+ content_view_id = options.fetch(:content_view_id, nil)
64
+ content_view = ::Katello::ContentView.find(content_view_id) if content_view_id
65
+
66
+ {content_view: content_view, environment: environment, repository: repository}
67
+ end
68
+
69
+ def rescue_strategy
70
+ Dynflow::Action::Rescue::Skip
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -27,7 +27,7 @@ module Actions
27
27
  def notify_on_failure(_plan)
28
28
  notification = MailNotification[:content_view_promote_failure]
29
29
  view = ::Katello::ContentView.find(input.fetch(:content_view, {})[:id])
30
- notification.users.where(disabled: [nil, false], mail_enabled: true).each do |user|
30
+ notification.users.with_enabled_email.each do |user|
31
31
  notification.deliver(user: user, content_view: view, task: task)
32
32
  end
33
33
  end
@@ -136,7 +136,7 @@ module Actions
136
136
  def notify_on_failure(_plan)
137
137
  notification = MailNotification[:content_view_publish_failure]
138
138
  view = ::Katello::ContentView.find(input.fetch(:content_view, {})[:id])
139
- notification.users.where(disabled: [nil, false], mail_enabled: true).each do |user|
139
+ notification.users.with_enabled_email.each do |user|
140
140
  notification.deliver(user: user, content_view: view, task: task)
141
141
  end
142
142
  end
@@ -0,0 +1,29 @@
1
+ module Actions
2
+ module Katello
3
+ module ContentViewVersion
4
+ class VerifyChecksum < Actions::EntryAction
5
+ def plan(content_view_version)
6
+ action_subject(content_view_version.content_view)
7
+ plan_self(:version_id => content_view_version.id)
8
+ plan_action(::Actions::BulkAction, ::Actions::Katello::Repository::VerifyChecksum, content_view_version.repositories) if content_view_version.repositories.any?
9
+ end
10
+
11
+ def run
12
+ #dummy run phase to save input and support humanized_name
13
+ end
14
+
15
+ def humanized_name
16
+ if input && input[:version_id]
17
+ version = ::Katello::ContentViewVersion.find_by(:id => input[:version_id])
18
+ end
19
+
20
+ if version
21
+ _("Verify checksum of repositories in %{name} %{version}") % {:name => version.content_view.name, :version => version.version}
22
+ else
23
+ _("Verify checksum of version repositories")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -169,6 +169,7 @@ module Actions
169
169
  if @candlepin_attributes.key?(uuid)
170
170
  host.subscription_facet.candlepin_consumer.consumer_attributes = @candlepin_attributes[uuid]
171
171
  host.subscription_facet.import_database_attributes
172
+ host.subscription_facet.last_checkin = Time.now
172
173
  host.subscription_facet.save!
173
174
  end
174
175
  end
@@ -17,9 +17,9 @@ module Actions
17
17
 
18
18
  def humanized_name
19
19
  if input.try(:[], :hostname).nil?
20
- _("Update for host")
20
+ _("Update content view environments for host")
21
21
  else
22
- _("Update for host %s") % input[:hostname]
22
+ _("Update content view environments for host %s") % input[:hostname]
23
23
  end
24
24
  end
25
25
  end
@@ -27,6 +27,11 @@ module Actions
27
27
  end
28
28
  end
29
29
 
30
+ def run
31
+ organization = ::Organization.find_by(name: input[:organization_name])
32
+ organization&.manifest_expiration_date(cached: false) # update the date
33
+ end
34
+
30
35
  def failure_notification(plan)
31
36
  ::Katello::UINotifications::Subscriptions::ManifestImportError.deliver!(
32
37
  :subject => subject_organization,
@@ -21,6 +21,9 @@ module Actions
21
21
  upstream_update = plan_action(Candlepin::Owner::UpstreamUpdate,
22
22
  { :organization_id => organization.id,
23
23
  :upstream => upstream })
24
+ plan_action(Candlepin::Owner::RegenerateUpstreamIdentityCert,
25
+ { :organization_id => organization.id,
26
+ :upstream => upstream })
24
27
  export_action = plan_action(Candlepin::Owner::StartUpstreamExport,
25
28
  { :organization_id => organization.id,
26
29
  :upstream => upstream,
@@ -1,8 +1,10 @@
1
1
  module Actions
2
2
  module Katello
3
3
  module Repository
4
- class MetadataGenerate < Actions::Base
4
+ class MetadataGenerate < Actions::EntryAction
5
5
  def plan(repository, options = {})
6
+ action_subject(repository)
7
+ repository.check_ready_to_act!
6
8
  source_repository = options.fetch(:source_repository, nil)
7
9
  source_repository ||= repository.target_repository if repository.link?
8
10
  smart_proxy = options.fetch(:smart_proxy, SmartProxy.pulp_primary)
@@ -15,6 +17,10 @@ module Actions
15
17
  :source_repository => source_repository,
16
18
  :matching_content => matching_content)
17
19
  end
20
+
21
+ def resource_locks
22
+ :link
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -5,6 +5,7 @@ module Actions
5
5
  include Dynflow::Action::WithSubPlans
6
6
 
7
7
  def plan(repository, content_units, options = {})
8
+ repository.check_ready_to_act!
8
9
  sync_capsule = options.fetch(:sync_capsule, true)
9
10
  if repository.redhat?
10
11
  fail _("Cannot remove content from a non-custom repository")
@@ -20,6 +20,7 @@ module Actions
20
20
  # of Katello and we just need to finish the rest of the orchestration
21
21
  def plan(repo, options = {})
22
22
  action_subject(repo)
23
+ repo.check_ready_to_act!
23
24
 
24
25
  validate_contents = options.fetch(:validate_contents, false)
25
26
  skip_metadata_check = options.fetch(:skip_metadata_check, false) || (validate_contents && (repo.yum? || repo.deb?))
@@ -100,7 +101,7 @@ module Actions
100
101
  def notify_on_failure(_plan)
101
102
  notification = MailNotification[:repository_sync_failure]
102
103
  repo = ::Katello::Repository.find(input.fetch(:repository, {})[:id])
103
- notification.users.where(disabled: [nil, false], mail_enabled: true).each do |user|
104
+ notification.users.with_enabled_email.each do |user|
104
105
  notification.deliver(user: user, repo: repo, task: task)
105
106
  end
106
107
  end
@@ -8,6 +8,7 @@ module Actions
8
8
  class UploadFiles < Actions::EntryAction
9
9
  def plan(repository, files, content_type = nil, options = {})
10
10
  action_subject(repository)
11
+ repository.check_ready_to_act!
11
12
  repository.clear_smart_proxy_sync_histories
12
13
  tmp_files = prepare_tmp_files(files)
13
14
 
@@ -0,0 +1,27 @@
1
+ module Actions
2
+ module Pulp3
3
+ module CapsuleContent
4
+ class VerifyChecksum < Pulp3::AbstractAsyncTask
5
+ def plan(repository, smart_proxy)
6
+ plan_self(:repository_id => repository.id, :smart_proxy_id => smart_proxy.id)
7
+ end
8
+
9
+ def invoke_external_task
10
+ repo = ::Katello::Repository.find(input[:repository_id])
11
+ output[:pulp_tasks] = repo.backend_service(smart_proxy).with_mirror_adapter.repair
12
+ end
13
+
14
+ def repos_to_repair(smart_proxy, environment, content_view, repository)
15
+ smart_proxy_helper = ::Katello::SmartProxyHelper.new(smart_proxy)
16
+ smart_proxy_helper.lifecycle_environment_check(environment, repository)
17
+ if repository
18
+ [repository]
19
+ else
20
+ repositories = smart_proxy_helper.repositories_available_to_capsule(environment, content_view).by_rpm_count
21
+ repositories
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -3,26 +3,24 @@ module Actions
3
3
  module Orchestration
4
4
  module ContentViewVersion
5
5
  class ExportRepository < Actions::EntryAction
6
- def plan(repository,
7
- chunk_size: nil,
8
- from_history: nil,
9
- format: ::Katello::Pulp3::ContentViewVersion::Export::IMPORTABLE)
6
+ def plan(repository, opts = {})
7
+ opts[:format] ||= ::Katello::Pulp3::ContentViewVersion::Export::IMPORTABLE
10
8
  action_subject(repository)
11
9
  validate_repositories_immediate!(repository)
12
- validate_export_types!(repository, format)
10
+ validate_export_types!(repository, opts[:format])
13
11
  content_view = ::Katello::Pulp3::ContentViewVersion::Export.find_repository_export_view(
14
12
  repository: repository,
15
13
  create_by_default: true,
16
- format: format)
14
+ format: opts[:format])
17
15
  content_view.update!(repository_ids: [repository.library_instance_or_self.id])
18
16
 
19
17
  sequence do
20
18
  publish_action = plan_action(::Actions::Katello::ContentView::Publish, content_view, '')
21
19
  export_action = plan_action(Actions::Katello::ContentViewVersion::Export,
22
20
  content_view_version: publish_action.version,
23
- chunk_size: chunk_size,
24
- from_history: from_history,
25
- format: format)
21
+ chunk_size: opts[:chunk_size],
22
+ from_history: opts[:from_history],
23
+ format: opts[:format])
26
24
  plan_self(export_action_output: export_action.output)
27
25
  end
28
26
  end
@@ -16,10 +16,11 @@ module Actions
16
16
  param :export_history_id, Integer
17
17
  end
18
18
 
19
- def plan(content_view_version:,
20
- smart_proxy:,
21
- destination_server:,
22
- from_content_view_version:)
19
+ def plan(opts = {})
20
+ content_view_version = opts[:content_view_version]
21
+ smart_proxy = opts[:smart_proxy]
22
+ destination_server = opts[:destination_server]
23
+ from_content_view_version = opts[:from_content_view_version]
23
24
  format = ::Katello::Pulp3::ContentViewVersion::Export::SYNCABLE
24
25
  sequence do
25
26
  export_service = ::Katello::Pulp3::ContentViewVersion::Export.create(
@@ -216,9 +216,14 @@ module Katello
216
216
  keyword :includes, Array, of: [String, Symbol], desc: 'An array of associations represented by strings or symbols, to be included in the SQL query. The list can be extended
217
217
  from plugins and can not be fully documented here. Most used associations are :subscription, :products, :organization', default: nil
218
218
  returns array_of: 'Pool', desc: 'The collection that can be iterated over using each_record'
219
+ keyword :expiring_in_days, String, desc: "Return subscriptions expiring in the given number of days. Leave blank to return all subscriptions.", default: nil
219
220
  end
220
- def load_pools(search: '', includes: nil)
221
- load_resource(klass: Pool.readable, search: search, permission: nil, includes: includes)
221
+ def load_pools(search: '', includes: nil, expiring_in_days: nil)
222
+ pools = Pool.readable
223
+ if expiring_in_days
224
+ pools = pools.expiring_in_days(expiring_in_days)
225
+ end
226
+ load_resource(klass: pools, search: search, permission: nil, includes: includes)
222
227
  end
223
228
 
224
229
  apipie :method, 'Returns the last time the host checked in via RHSM' do
@@ -10,6 +10,10 @@ module Katello
10
10
 
11
11
  class RegistrationError < StandardError; end
12
12
 
13
+ class InvalidRepositoryTypeError < StandardError; end
14
+
15
+ class MultiEnvironmentNotSupportedError < StandardError; end
16
+
13
17
  # unauthorized access
14
18
  class SecurityViolation < StandardError; end
15
19
 
@@ -38,6 +38,7 @@ module Katello
38
38
  get: Net::HTTP::Get,
39
39
  post: Net::HTTP::Post,
40
40
  put: Net::HTTP::Put,
41
+ patch: Net::HTTP::Patch,
41
42
  delete: Net::HTTP::Delete
42
43
  }.freeze
43
44
 
@@ -84,7 +85,11 @@ module Katello
84
85
  def issue_request(method:, path:, headers: {}, payload: nil)
85
86
  logger.debug("Resource #{method.upcase} request: #{path}")
86
87
  logger.debug "Headers: #{headers.to_json}"
87
- logger.debug "Body: #{filter_sensitive_data(payload.to_json)}"
88
+ begin
89
+ logger.debug "Body: #{filter_sensitive_data(payload.to_json)}"
90
+ rescue JSON::GeneratorError, Encoding::UndefinedConversionError
91
+ logger.debug "Body: Error: could not render payload as json"
92
+ end
88
93
 
89
94
  client = rest_client(REQUEST_MAP[method], method, path)
90
95
  args = [method, payload, headers].compact
@@ -7,7 +7,7 @@ module Katello
7
7
  class << self
8
8
  def all_uuids
9
9
  cp_consumers = Organization.all.map do |org|
10
- ::Katello::Resources::Candlepin::Consumer.get('owner' => org.label, :include_only => [:uuid])
10
+ ::Katello::Resources::Candlepin::Consumer.get('owner' => org.label, :include_only => [:uuid], :sort_by => "uuid")
11
11
  end
12
12
  cp_consumers.flatten!
13
13
  cp_consumers.map { |consumer| consumer["uuid"] }
@@ -40,19 +40,31 @@ module Katello
40
40
  raise ::Katello::Errors::UpstreamEntitlementGone
41
41
  end
42
42
 
43
- def get_export(url, client_cert, client_key, ca_file)
43
+ def start_upstream_export(url, client_cert, client_key, ca_file)
44
44
  logger.debug "Sending GET request to upstream Candlepin: #{url}"
45
- return resource(url: url, client_cert: client_cert, client_key: client_key, ca_file: ca_file).get
45
+ resource(url: url, client_cert: client_cert, client_key: client_key, ca_file: ca_file).get
46
46
  rescue RestClient::Exception => e
47
47
  raise e
48
48
  end
49
49
 
50
+ alias_method :retrieve_upstream_export, :start_upstream_export
51
+
50
52
  def update(url, client_cert, client_key, ca_file, attributes)
51
53
  logger.debug "Sending PUT request to upstream Candlepin: #{url} #{attributes.to_json}"
52
- return resource(url: url, client_cert: client_cert, client_key: client_key, ca_file: ca_file).put(attributes.to_json,
53
- 'accept' => 'application/json',
54
- 'accept-language' => I18n.locale,
55
- 'content-type' => 'application/json')
54
+ resource(
55
+ url: url,
56
+ client_cert: client_cert,
57
+ client_key: client_key,
58
+ ca_file: ca_file).put(
59
+ attributes.to_json,
60
+ 'accept' => 'application/json',
61
+ 'accept-language' => I18n.locale,
62
+ 'content-type' => 'application/json')
63
+ end
64
+
65
+ def regenerate_upstream_identity(url, client_cert, client_key, ca_file)
66
+ logger.debug "Sending POST request to upstream Candlepin: #{url}"
67
+ resource(url: url, client_cert: client_cert, client_key: client_key, ca_file: ca_file).post(nil)
56
68
  end
57
69
 
58
70
  def bind_entitlement(**pool)
@@ -12,7 +12,7 @@ module Katello
12
12
 
13
13
  def get(id, upstream)
14
14
  url = API_URL
15
- response = Resources::Candlepin::UpstreamConsumer.get_export("#{url}#{path(id)}", upstream['idCert']['cert'],
15
+ response = Resources::Candlepin::UpstreamConsumer.start_upstream_export("#{url}#{path(id)}", upstream['idCert']['cert'],
16
16
  upstream['idCert']['key'], nil)
17
17
  job = JSON.parse(response)
18
18
  job.with_indifferent_access