katello 4.12.1 → 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 (222) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/locale/bn/katello.js +3365 -3350
  3. data/app/assets/javascripts/katello/locale/bn_IN/katello.js +3136 -3121
  4. data/app/assets/javascripts/katello/locale/ca/katello.js +3588 -3576
  5. data/app/assets/javascripts/katello/locale/cs/katello.js +3499 -3487
  6. data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +4186 -4186
  7. data/app/assets/javascripts/katello/locale/de/katello.js +5553 -5562
  8. data/app/assets/javascripts/katello/locale/de_AT/katello.js +3008 -2993
  9. data/app/assets/javascripts/katello/locale/de_DE/katello.js +3066 -3051
  10. data/app/assets/javascripts/katello/locale/el/katello.js +3376 -3370
  11. data/app/assets/javascripts/katello/locale/en/katello.js +3008 -2993
  12. data/app/assets/javascripts/katello/locale/en_GB/katello.js +3076 -3073
  13. data/app/assets/javascripts/katello/locale/en_US/katello.js +3008 -2993
  14. data/app/assets/javascripts/katello/locale/es/katello.js +5366 -5372
  15. data/app/assets/javascripts/katello/locale/et_EE/katello.js +3008 -2993
  16. data/app/assets/javascripts/katello/locale/fr/katello.js +5975 -5984
  17. data/app/assets/javascripts/katello/locale/gl/katello.js +3125 -3113
  18. data/app/assets/javascripts/katello/locale/gu/katello.js +3119 -3104
  19. data/app/assets/javascripts/katello/locale/he_IL/katello.js +3020 -3005
  20. data/app/assets/javascripts/katello/locale/hi/katello.js +3137 -3122
  21. data/app/assets/javascripts/katello/locale/id/katello.js +3008 -2993
  22. data/app/assets/javascripts/katello/locale/it/katello.js +4469 -4466
  23. data/app/assets/javascripts/katello/locale/ja/katello.js +5969 -5978
  24. data/app/assets/javascripts/katello/locale/ka/katello.js +5649 -5652
  25. data/app/assets/javascripts/katello/locale/kn/katello.js +3136 -3121
  26. data/app/assets/javascripts/katello/locale/ko/katello.js +4717 -4720
  27. data/app/assets/javascripts/katello/locale/locale/katello.js +1050 -1084
  28. data/app/assets/javascripts/katello/locale/ml_IN/katello.js +3008 -2993
  29. data/app/assets/javascripts/katello/locale/mr/katello.js +3136 -3121
  30. data/app/assets/javascripts/katello/locale/nl_NL/katello.js +3116 -3101
  31. data/app/assets/javascripts/katello/locale/or/katello.js +3137 -3122
  32. data/app/assets/javascripts/katello/locale/pa/katello.js +3136 -3121
  33. data/app/assets/javascripts/katello/locale/pl/katello.js +3210 -3195
  34. data/app/assets/javascripts/katello/locale/pl_PL/katello.js +3008 -2993
  35. data/app/assets/javascripts/katello/locale/pt/katello.js +3009 -2994
  36. data/app/assets/javascripts/katello/locale/pt_BR/katello.js +5362 -5368
  37. data/app/assets/javascripts/katello/locale/ro/katello.js +3008 -2993
  38. data/app/assets/javascripts/katello/locale/ro_RO/katello.js +3008 -2993
  39. data/app/assets/javascripts/katello/locale/ru/katello.js +4638 -4641
  40. data/app/assets/javascripts/katello/locale/sl/katello.js +3051 -3036
  41. data/app/assets/javascripts/katello/locale/sv_SE/katello.js +3156 -3144
  42. data/app/assets/javascripts/katello/locale/ta/katello.js +3365 -3350
  43. data/app/assets/javascripts/katello/locale/ta_IN/katello.js +3121 -3106
  44. data/app/assets/javascripts/katello/locale/te/katello.js +3136 -3121
  45. data/app/assets/javascripts/katello/locale/tr/katello.js +3025 -3010
  46. data/app/assets/javascripts/katello/locale/vi/katello.js +3008 -2993
  47. data/app/assets/javascripts/katello/locale/vi_VN/katello.js +3008 -2993
  48. data/app/assets/javascripts/katello/locale/zh/katello.js +3008 -2993
  49. data/app/assets/javascripts/katello/locale/zh_CN/katello.js +5968 -5977
  50. data/app/assets/javascripts/katello/locale/zh_TW/katello.js +4694 -4697
  51. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +51 -124
  52. data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -20
  53. data/app/controllers/katello/api/v2/activation_keys_controller.rb +10 -4
  54. data/app/controllers/katello/api/v2/capsule_content_controller.rb +24 -0
  55. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +9 -2
  56. data/app/controllers/katello/api/v2/debs_controller.rb +1 -1
  57. data/app/controllers/katello/api/v2/errata_controller.rb +1 -1
  58. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +12 -4
  59. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +3 -3
  60. data/app/controllers/katello/api/v2/organizations_controller.rb +0 -11
  61. data/app/controllers/katello/api/v2/packages_controller.rb +1 -1
  62. data/app/controllers/katello/api/v2/repositories_controller.rb +18 -12
  63. data/app/controllers/katello/api/v2/repository_sets_controller.rb +2 -1
  64. data/app/controllers/katello/api/v2/simple_content_access_controller.rb +9 -22
  65. data/app/controllers/katello/concerns/api/v2/authorization.rb +1 -1
  66. data/app/helpers/katello/subscription_mailer_helper.rb +1 -1
  67. data/app/jobs/create_manifest_expire_soon_warning_notifications.rb +11 -0
  68. data/app/lib/actions/candlepin/owner/regenerate_upstream_identity_cert.rb +21 -0
  69. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  70. data/app/lib/actions/katello/capsule_content/verify_checksum.rb +75 -0
  71. data/app/lib/actions/katello/content_view/promote.rb +1 -1
  72. data/app/lib/actions/katello/content_view/publish.rb +1 -1
  73. data/app/lib/actions/katello/content_view_version/verify_checksum.rb +29 -0
  74. data/app/lib/actions/katello/host/hypervisors_update.rb +1 -0
  75. data/app/lib/actions/katello/host/update_content_view.rb +2 -2
  76. data/app/lib/actions/katello/organization/manifest_import.rb +5 -0
  77. data/app/lib/actions/katello/organization/manifest_refresh.rb +3 -0
  78. data/app/lib/actions/katello/repository/metadata_generate.rb +7 -1
  79. data/app/lib/actions/katello/repository/remove_content.rb +1 -0
  80. data/app/lib/actions/katello/repository/sync.rb +2 -1
  81. data/app/lib/actions/katello/repository/upload_files.rb +1 -0
  82. data/app/lib/actions/pulp3/capsule_content/verify_checksum.rb +27 -0
  83. data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +7 -9
  84. data/app/lib/actions/pulp3/orchestration/content_view_version/syncable_export.rb +5 -4
  85. data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -2
  86. data/app/lib/katello/http_resource.rb +6 -1
  87. data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
  88. data/app/lib/katello/resources/candlepin/upstream_consumer.rb +18 -6
  89. data/app/lib/katello/resources/candlepin/upstream_job.rb +1 -1
  90. data/app/lib/katello/resources/registry.rb +25 -0
  91. data/app/mailers/katello/subscription_mailer.rb +3 -6
  92. data/app/models/katello/concerns/organization_extensions.rb +42 -3
  93. data/app/models/katello/content_view.rb +28 -0
  94. data/app/models/katello/content_view_environment_content_facet.rb +4 -2
  95. data/app/models/katello/glue/provider.rb +19 -12
  96. data/app/models/katello/glue/pulp/repos.rb +3 -2
  97. data/app/models/katello/host/content_facet.rb +1 -1
  98. data/app/models/katello/host/subscription_facet.rb +1 -1
  99. data/app/models/katello/ping.rb +1 -1
  100. data/app/models/katello/repository.rb +27 -0
  101. data/app/models/katello/root_repository.rb +0 -4
  102. data/app/services/katello/content_unit_indexer.rb +9 -0
  103. data/app/services/katello/pulp3/alternate_content_source.rb +4 -6
  104. data/app/services/katello/pulp3/api/core.rb +13 -0
  105. data/app/services/katello/pulp3/api/yum.rb +11 -0
  106. data/app/services/katello/pulp3/docker_manifest.rb +5 -1
  107. data/app/services/katello/pulp3/repository/generic.rb +1 -1
  108. data/app/services/katello/pulp3/repository.rb +26 -6
  109. data/app/services/katello/pulp3/repository_mirror.rb +13 -12
  110. data/app/services/katello/pulp3/service_common.rb +2 -10
  111. data/app/services/katello/pulp3/smart_proxy_repository.rb +0 -2
  112. data/app/services/katello/ui_notifications/subscriptions/manifest_expire_soon_warning.rb +75 -0
  113. data/app/views/foreman/job_templates/update_package_-_katello_ansible_default.erb +5 -1
  114. data/app/views/foreman/job_templates/update_packages_by_search_query_-_katello_ansible_default.erb +2 -2
  115. data/app/views/foreman/job_templates/upload_profile.erb +16 -0
  116. data/app/views/katello/api/v2/content_view_filter_rules/show.json.rabl +9 -0
  117. data/app/views/katello/api/v2/docker_manifests/show.json.rabl +1 -0
  118. data/app/views/katello/api/v2/organizations/show.json.rabl +9 -1
  119. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +1 -1
  120. data/app/views/overrides/activation_keys/_host_media_type_select.html.erb +15 -5
  121. data/config/routes/api/registry.rb +4 -8
  122. data/config/routes/api/v2.rb +2 -0
  123. data/db/migrate/20240423112842_add_fields_to_katello_docker_manifest.rb +8 -0
  124. data/db/migrate/20240502192021_change_katello_repository_rpms_id_seq_to_big_int.rb +9 -0
  125. data/db/seeds.d/109-katello-notification-blueprints.rb +6 -0
  126. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-repository-sets.controller.js +3 -3
  127. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +2 -1
  128. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-repository-sets.controller.js +3 -3
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +0 -15
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +8 -6
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +12 -10
  132. data/lib/katello/permission_creator.rb +3 -3
  133. data/lib/katello/permissions/registry_permissions.rb +4 -7
  134. data/lib/katello/plugin.rb +9 -8
  135. data/lib/katello/repository_types/ostree.rb +7 -0
  136. data/lib/katello/scheduled_jobs.rb +7 -1
  137. data/lib/katello/tasks/clean_backend_objects.rake +1 -1
  138. data/lib/katello/tasks/repository.rake +22 -0
  139. data/lib/katello/version.rb +1 -1
  140. data/locale/action_names.rb +4 -3
  141. data/locale/bn/katello.po +166 -151
  142. data/locale/bn_IN/katello.po +166 -151
  143. data/locale/ca/katello.po +166 -151
  144. data/locale/cs/katello.po +166 -151
  145. data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
  146. data/locale/cs_CZ/katello.po +172 -157
  147. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  148. data/locale/de/katello.po +178 -163
  149. data/locale/de_AT/katello.po +166 -151
  150. data/locale/de_DE/katello.po +166 -151
  151. data/locale/el/katello.po +166 -151
  152. data/locale/en/katello.po +166 -151
  153. data/locale/en_GB/katello.po +166 -151
  154. data/locale/en_US/katello.po +166 -151
  155. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  156. data/locale/es/katello.po +178 -163
  157. data/locale/et_EE/katello.po +166 -151
  158. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  159. data/locale/fr/katello.po +179 -164
  160. data/locale/gl/katello.po +166 -151
  161. data/locale/gu/katello.po +166 -151
  162. data/locale/he_IL/katello.po +166 -151
  163. data/locale/hi/katello.po +166 -151
  164. data/locale/id/katello.po +166 -151
  165. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  166. data/locale/it/katello.po +169 -154
  167. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  168. data/locale/ja/katello.po +179 -164
  169. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  170. data/locale/ka/katello.po +177 -162
  171. data/locale/katello.pot +1119 -1062
  172. data/locale/kn/katello.po +166 -151
  173. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  174. data/locale/ko/katello.po +174 -159
  175. data/locale/ml_IN/katello.po +166 -151
  176. data/locale/mr/katello.po +166 -151
  177. data/locale/nl_NL/katello.po +166 -151
  178. data/locale/or/katello.po +166 -151
  179. data/locale/pa/katello.po +166 -151
  180. data/locale/pl/katello.po +166 -151
  181. data/locale/pl_PL/katello.po +166 -151
  182. data/locale/pt/katello.po +166 -151
  183. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  184. data/locale/pt_BR/katello.po +178 -163
  185. data/locale/ro/katello.po +166 -151
  186. data/locale/ro_RO/katello.po +166 -151
  187. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  188. data/locale/ru/katello.po +171 -156
  189. data/locale/sl/katello.po +166 -151
  190. data/locale/sv_SE/katello.po +166 -151
  191. data/locale/ta/katello.po +166 -151
  192. data/locale/ta_IN/katello.po +166 -151
  193. data/locale/te/katello.po +166 -151
  194. data/locale/tr/katello.po +166 -151
  195. data/locale/vi/katello.po +166 -151
  196. data/locale/vi_VN/katello.po +166 -151
  197. data/locale/zh/katello.po +166 -151
  198. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  199. data/locale/zh_CN/katello.po +179 -164
  200. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  201. data/locale/zh_TW/katello.po +171 -156
  202. data/webpack/ForemanColumnExtensions/index.js +129 -0
  203. data/webpack/components/Table/TableWrapper.js +14 -0
  204. data/webpack/components/extensions/HostDetails/ActionsBar/index.js +1 -1
  205. data/webpack/components/extensions/Hosts/ActionsBar/index.js +20 -1
  206. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/BulkChangeHostCVModal.js +220 -0
  207. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/actions.js +23 -0
  208. data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/index.js +25 -0
  209. data/webpack/components/extensions/Hosts/BulkActions/__tests__/bulkChangeHostCVModal.test.js +133 -0
  210. data/webpack/global_index.js +9 -0
  211. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +3 -1
  212. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +62 -24
  213. data/webpack/scenes/Hosts/ChangeContentSource/index.js +24 -16
  214. data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +1 -0
  215. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +64 -5
  216. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +16 -13
  217. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +14 -8
  218. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +1 -0
  219. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +1 -1
  220. metadata +59 -41
  221. data/app/lib/actions/katello/host/upload_package_profile.rb +0 -45
  222. 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
@@ -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
@@ -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
@@ -18,10 +18,35 @@ module Katello
18
18
  client.options.merge!(options)
19
19
  client.get(headers)
20
20
  end
21
+
22
+ def self.put(path, body, headers)
23
+ logger.debug "Sending PUT request to Registry: #{path}"
24
+ resource = RegistryResource.load_class
25
+ joined_path = resource.prefix.chomp("/") + path
26
+ resource.issue_request(method: :put, path: joined_path, headers: headers, payload: body)
27
+ end
28
+
29
+ def self.patch(path, body, headers)
30
+ logger.debug "Sending PATCH request to Registry: #{path}"
31
+ resource = RegistryResource.load_class
32
+ joined_path = resource.prefix.chomp("/") + path
33
+ resource.issue_request(method: :patch, path: joined_path, headers: headers, payload: body)
34
+ end
35
+
36
+ def self.post(path, body, headers)
37
+ logger.debug "Sending PUT request to Registry: #{path}"
38
+ resource = RegistryResource.load_class
39
+ joined_path = resource.prefix.chomp("/") + path
40
+ resource.issue_request(method: :post, path: joined_path, headers: headers, payload: body)
41
+ end
21
42
  end
22
43
 
23
44
  class RegistryResource < HttpResource
24
45
  class << self
46
+ def logger
47
+ ::Foreman::Logging.logger('katello/registry_proxy')
48
+ end
49
+
25
50
  def load_class
26
51
  pulp_primary = ::SmartProxy.pulp_primary
27
52
  content_app_url = pulp_primary.setting(SmartProxy::PULP3_FEATURE, 'content_app_url')
@@ -10,14 +10,11 @@ module Katello
10
10
 
11
11
  ::User.as(user.login) do
12
12
  @pools = Katello::Pool.readable.expiring_in_days(days_from_now)
13
- @affected_hosts = ::Host::Managed.with_pools_expiring_in_days(days_from_now)
14
13
  end
15
14
 
16
- if @affected_hosts.any?
17
- start_report_task(days_from_now)
18
- @report_url = report_url
19
- @report_link = report_link
20
- end
15
+ start_report_task(days_from_now)
16
+ @report_url = report_url
17
+ @report_link = report_link
21
18
 
22
19
  set_locale_for(user) do
23
20
  mail(:to => user.mail, :subject => _("You have subscriptions expiring within %s days") % days_from_now)
@@ -100,16 +100,55 @@ module Katello
100
100
  end
101
101
  end
102
102
 
103
- def manifest_expired?
104
- manifest_expiry = owner_details.dig(:upstreamConsumer, :idCert, :serial, :expiration)
103
+ def manifest_expiration_date(cached: true)
104
+ Rails.cache.fetch("#{self.label}_manifest_expiration_date", expires_in: 1.minute, force: !cached) do
105
+ unless manifest_imported?(cached: cached)
106
+ Rails.logger.error "Manifest not imported for organization #{self.label}"
107
+ return nil
108
+ end
109
+ manifest_expiry = owner_details.dig(:upstreamConsumer, :idCert, :serial, :expiration)
110
+
111
+ if manifest_expiry.present?
112
+ DateTime.parse(manifest_expiry)
113
+ else
114
+ Rails.logger.error "Unable to parse manifest expiration date from owner details"
115
+ nil
116
+ end
117
+ end
118
+ end
119
+
120
+ def manifest_expired?(cached: true)
121
+ manifest_expiry = manifest_expiration_date(cached: cached)
105
122
 
106
123
  if manifest_expiry
107
- DateTime.parse(manifest_expiry) < DateTime.now
124
+ manifest_expiry < DateTime.now
108
125
  else
109
126
  false
110
127
  end
111
128
  end
112
129
 
130
+ def manifest_expiring_soon?(days = Setting[:expire_soon_days])
131
+ return false if !manifest_imported? || manifest_expired?
132
+ manifest_expiry = manifest_expiration_date
133
+
134
+ if manifest_expiry
135
+ manifest_expiry < DateTime.now + days.days
136
+ else
137
+ false
138
+ end
139
+ end
140
+
141
+ def manifest_expire_days_remaining
142
+ manifest_expiry = manifest_expiration_date
143
+ return 0 if manifest_expired?
144
+
145
+ if manifest_expiry
146
+ (manifest_expiry - DateTime.now).to_i
147
+ else
148
+ 0
149
+ end
150
+ end
151
+
113
152
  def manifest_history
114
153
  imports.map { |i| OpenStruct.new(i) }
115
154
  end