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,8 +1,6 @@
1
1
  module Katello
2
2
  module Resources
3
3
  module CDN
4
- SUPPORTED_SSL_VERSIONS = ['SSLv23', 'TLSv1'].freeze
5
-
6
4
  class Utils
7
5
  # takes releasever from contentUrl (e.g. 6Server, 6.0, 6.1)
8
6
  # returns hash e.g. {:major => 6, :minor => "6.1"}
@@ -24,11 +22,6 @@ module Katello
24
22
  end
25
23
 
26
24
  def initialize(url, options = {})
27
- @ssl_version = Setting[:cdn_ssl_version]
28
- if @ssl_version && !SUPPORTED_SSL_VERSIONS.include?(@ssl_version)
29
- fail("Invalid SSL version specified. Check the 'CDN SSL Version' setting")
30
- end
31
-
32
25
  options.reverse_merge!(:verify_ssl => 9)
33
26
  options.assert_valid_keys(:ssl_client_key,
34
27
  :ssl_client_cert,
@@ -106,12 +99,10 @@ module Katello
106
99
  net.cert_store = @cert_store
107
100
  end
108
101
 
109
- # NOTE: This was added because some proxies dont support SSLv23 and do not handle TLS 1.2
110
- # Valid values in ruby 1.9.3 are 'SSLv23' or 'TLSV1'
111
- # Run the following command in rails console to figure out other
112
- # valid constants in other ruby versions
113
- # "OpenSSL::SSL::SSLContext::METHODS"
114
- net.ssl_version = @ssl_version
102
+ # NOTE: This is only here due to https://github.com/ruby/openssl/issues/709, otherwise the
103
+ # system-wide crypto policy could be used. Enforcing TLS version >= 1.2 will prevent using
104
+ # very old infrastructure for now, but that was considered better than having an insecure default.
105
+ net.min_version = OpenSSL::SSL::TLS1_2_VERSION
115
106
 
116
107
  if (@options[:verify_ssl] == false) || (@options[:verify_ssl] == OpenSSL::SSL::VERIFY_NONE)
117
108
  net.verify_mode = OpenSSL::SSL::VERIFY_NONE
@@ -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)
@@ -74,7 +74,7 @@ module Katello
74
74
  end
75
75
 
76
76
  def relative_path
77
- ::Katello::Glue::Pulp::Repos.repo_path_from_content_path(product.organization.library, path)
77
+ ::Katello::Repository.repo_path_from_content_path(product.organization.library, path)
78
78
  end
79
79
 
80
80
  def prune_substitutions(subs, url)
@@ -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
@@ -634,6 +634,7 @@ module Katello
634
634
  check_ready_to_import!
635
635
  else
636
636
  fail _("Import-only content views can not be published directly") if import_only? && !syncable
637
+ check_repositories_blocking_publish!
637
638
  check_composite_action_allowed!(organization.library)
638
639
  check_docker_repository_names!([organization.library])
639
640
  check_orphaned_content_facets!(environments: self.environments)
@@ -642,6 +643,16 @@ module Katello
642
643
  true
643
644
  end
644
645
 
646
+ def check_repositories_blocking_publish!
647
+ blocking_tasks = repositories&.map { |repo| repo.blocking_task }&.compact
648
+
649
+ if blocking_tasks&.any?
650
+ errored_tasks = blocking_tasks.uniq.map { |task| "- #{Setting['foreman_url']}/foreman_tasks/tasks/#{task&.id}" }.join("\n")
651
+ fail _("Pending tasks detected in repositories of this content view. Please wait for the tasks: " +
652
+ errored_tasks + " before publishing.")
653
+ end
654
+ end
655
+
645
656
  def check_docker_repository_names!(environments)
646
657
  environments.each do |environment|
647
658
  repositories = []
@@ -789,6 +800,10 @@ module Katello
789
800
  repositories.any? { |repo| repo.last_indexed && repo.last_indexed > latest_version_object.created_at }
790
801
  end
791
802
 
803
+ def unpublishable?
804
+ default? || import_only? || generated?
805
+ end
806
+
792
807
  def needs_publish?
793
808
  #Returns
794
809
  # True:
@@ -808,7 +823,9 @@ module Katello
808
823
  # a) No changes were detected via audits *and*
809
824
  # Audit for CV publish exists (Audits haven't been cleaned up)
810
825
  # *and* applied_filters field is set(Published after upgrade)
826
+ # b) Default, import only and generated CVs can not be published, hence these will always return false.
811
827
  #
828
+ return false if unpublishable?
812
829
  return true unless latest_version_object
813
830
  return nil unless last_publish_task_success?
814
831
  return composite_cv_components_changed? if composite?
@@ -868,6 +885,17 @@ module Katello
868
885
  filters.present?
869
886
  end
870
887
 
888
+ def blocking_task
889
+ blocking_task_labels = [
890
+ ::Actions::Katello::ContentView::Publish.name
891
+ ]
892
+ ForemanTasks::Task::DynflowTask.where(:label => blocking_task_labels)
893
+ .where.not(state: 'stopped')
894
+ .for_resource(self)
895
+ .order(:started_at)
896
+ .last
897
+ end
898
+
871
899
  protected
872
900
 
873
901
  def remove_repository(repository)
@@ -5,7 +5,7 @@ module Katello
5
5
 
6
6
  validates :content_view_environment_id, presence: true
7
7
  validates :content_facet_id, presence: true, unless: :new_record?
8
- validate :ensure_valid_content_source
8
+ validate :ensure_valid_content_source, if: proc { Setting['validate_host_lce_content_source_coherence'] }
9
9
 
10
10
  def ensure_valid_content_source
11
11
  source = self.content_facet&.content_source
@@ -14,7 +14,9 @@ module Katello
14
14
  hostname = self.content_facet&.host&.name
15
15
  return unless [source, env].all? { |x| x.present? }
16
16
  unless source.lifecycle_environments.include?(env)
17
- errors.add(:base, _("Host %{hostname}: Cannot add content view environment to content facet. The host's content source '%{content_source}' does not sync lifecycle environment '%{lce}'.") % { hostname: hostname, content_source: source.name, lce: env.name })
17
+ error_msg = _("Host %{hostname}: Cannot add content view environment to content facet. The host's content source '%{content_source}' does not sync lifecycle environment '%{lce}'.") % { hostname: hostname, content_source: source.name, lce: env.name }
18
+ Rails.logger.warn error_msg
19
+ errors.add(:base, error_msg)
18
20
  end
19
21
  end
20
22
  end
@@ -32,6 +32,10 @@ module Katello
32
32
 
33
33
  module InstanceMethods
34
34
  API_URL = 'https://subscription.rhsm.redhat.com/subscription/consumers/'.freeze
35
+ def api_url(upstream = {})
36
+ # Default to Red Hat
37
+ upstream['apiUrl'] || API_URL
38
+ end
35
39
 
36
40
  def sync
37
41
  Rails.logger.debug "Syncing provider #{name}"
@@ -62,34 +66,37 @@ module Katello
62
66
  fail _("Upstream identity certificate not available")
63
67
  end
64
68
 
65
- # Default to Red Hat
66
- url = upstream['apiUrl'] || API_URL
67
-
68
69
  params = {}
69
70
  params[:capabilities] = Resources::Candlepin::CandlepinPing.ping['managerCapabilities'].inject([]) do |result, element|
70
71
  result << {'name' => element}
71
72
  end
72
73
  params[:facts] = {:distributor_version => DISTRIBUTOR_VERSION }
73
- Resources::Candlepin::UpstreamConsumer.update("#{url}#{upstream['uuid']}", upstream['idCert']['cert'],
74
+ Resources::Candlepin::UpstreamConsumer.update("#{api_url(upstream)}#{upstream['uuid']}", upstream['idCert']['cert'],
74
75
  upstream['idCert']['key'], ca_file, params)
75
76
  end
76
77
 
77
- def start_owner_upstream_export(upstream)
78
+ def owner_upstream_regenerate_identity_cert(upstream)
78
79
  validate_upstream_identity_cert!(upstream)
79
- url = upstream['apiUrl'] || API_URL
80
+ Rails.logger.debug "Sending request to regenerate identity certificate for upstream consumer: #{upstream['uuid']}"
81
+ response = Resources::Candlepin::UpstreamConsumer.regenerate_upstream_identity("#{api_url(upstream)}#{upstream['uuid']}", upstream['idCert']['cert'],
82
+ upstream['idCert']['key'], ca_file)
83
+ JSON.parse(response)
84
+ end
80
85
 
81
- response = Resources::Candlepin::UpstreamConsumer.get_export("#{url}#{upstream['uuid']}/export/async", upstream['idCert']['cert'],
86
+ def start_owner_upstream_export(upstream)
87
+ validate_upstream_identity_cert!(upstream)
88
+ response = Resources::Candlepin::UpstreamConsumer.start_upstream_export("#{api_url(upstream)}#{upstream['uuid']}/export/async", upstream['idCert']['cert'],
82
89
  upstream['idCert']['key'], ca_file)
83
90
  JSON.parse(response)
84
91
  end
85
92
 
86
93
  def retrieve_owner_upstream_export(upstream, zip_file_path, export_id)
87
94
  validate_upstream_identity_cert!(upstream)
88
- url = upstream['apiUrl'] || API_URL
89
-
90
- data = Resources::Candlepin::UpstreamConsumer.get_export("#{url}#{upstream['uuid']}/export/#{export_id}", upstream['idCert']['cert'],
91
- upstream['idCert']['key'], ca_file)
92
-
95
+ data = Resources::Candlepin::UpstreamConsumer.retrieve_upstream_export(
96
+ "#{api_url(upstream)}#{upstream['uuid']}/export/#{export_id}",
97
+ upstream['idCert']['cert'],
98
+ upstream['idCert']['key'], ca_file
99
+ )
93
100
  File.write(zip_file_path, data, mode: 'wb')
94
101
 
95
102
  true
@@ -6,12 +6,6 @@ module Katello
6
6
  base.send :include, InstanceMethods
7
7
  end
8
8
 
9
- def self.repo_path_from_content_path(environment, content_path)
10
- path = content_path.sub(%r|^/|, '')
11
- path_prefix = [environment.organization.label, environment.label].join('/')
12
- "#{path_prefix}/#{path}"
13
- end
14
-
15
9
  module InstanceMethods
16
10
  def distributions(env)
17
11
  to_ret = []
@@ -56,7 +50,7 @@ module Katello
56
50
  end
57
51
 
58
52
  def last_sync_audit
59
- Audited::Audit.where(:auditable_id => self.repositories, :auditable_type => Katello::Repository.name).order(:created_at).last
53
+ Audited::Audit.where(:auditable_id => self.repositories, :auditable_type => Katello::Repository.name, :action => "sync").order(:created_at).last
60
54
  end
61
55
 
62
56
  def last_sync
@@ -64,13 +58,14 @@ module Katello
64
58
  end
65
59
 
66
60
  def last_repo_sync_task
67
- @last_sync_task ||= last_repo_sync_tasks.first
61
+ @last_sync_task ||= last_repo_sync_tasks&.first
68
62
  end
69
63
 
70
64
  def last_repo_sync_tasks
71
65
  ids = repos(self.library, nil, false).pluck(:id).join(',')
72
66
  label = ::Actions::Katello::Repository::Sync.name
73
67
  type = ::Katello::Repository.name
68
+ return nil if ids.empty?
74
69
  ForemanTasks::Task.search_for("label = #{label} and resource_type = #{type} and resource_id ^ (#{ids})")
75
70
  .order("started_at desc")
76
71
  end
@@ -44,7 +44,7 @@ module Katello
44
44
 
45
45
  validates_with ::AssociationExistsValidator, attributes: [:content_source]
46
46
  validates_with Katello::Validators::GeneratedContentViewValidator
47
- validates_associated :content_view_environment_content_facets
47
+ validates_associated :content_view_environment_content_facets, :message => _("invalid: The content source must sync the lifecycle environment assigned to the host. See the logs for more information.")
48
48
  validates :host, :presence => true, :allow_blank => false
49
49
 
50
50
  attr_accessor :cves_changed
@@ -67,7 +67,7 @@ module Katello
67
67
  self.purpose_addon_ids = consumer_params['addOns'].map { |addon_name| ::Katello::PurposeAddon.find_or_create_by(name: addon_name).id }
68
68
  end
69
69
 
70
- unless consumer_params['releaseVer'].blank?
70
+ unless consumer_params['releaseVer'].nil?
71
71
  release = consumer_params['releaseVer']
72
72
  release = release['releaseVer'] if release.is_a?(Hash)
73
73
  self.release_version = release
@@ -29,7 +29,10 @@ module Katello
29
29
  scoped_search :relation => :hosts, :on => :name, :rename => :host, :complete_value => true
30
30
 
31
31
  def max_hosts_check
32
- if !unlimited_hosts && (hosts.length > 0 && (hosts.length.to_i > max_hosts.to_i)) && max_hosts_changed?
32
+ # NOTE: max_hosts_check and max_hosts_no_exceeded use size() instead of count() because
33
+ # the host list exists as an array rather than a DB query when run as a validation.
34
+ host_count = hosts.size
35
+ if !unlimited_hosts && (host_count > 0 && (host_count.to_i > max_hosts.to_i)) && max_hosts_changed?
33
36
  errors.add :max_host, N_("may not be less than the number of hosts associated with the host collection.")
34
37
  end
35
38
  end
@@ -60,8 +63,14 @@ module Katello
60
63
  type ? query.of_type(type) : query
61
64
  end
62
65
 
63
- def total_hosts
64
- hosts.length
66
+ def cache_key
67
+ "#{self.class.name}/#{self.id}"
68
+ end
69
+
70
+ def total_hosts(cached: false)
71
+ Rails.cache.fetch("#{cache_key}/total_hosts", expires_in: 1.minute, force: !cached) do
72
+ hosts.count
73
+ end
65
74
  end
66
75
 
67
76
  # Retrieve the list of accessible host collections in the organization specified, returning
@@ -2,7 +2,7 @@ module Katello
2
2
  class Ping
3
3
  OK_RETURN_CODE = 'ok'.freeze
4
4
  FAIL_RETURN_CODE = 'FAIL'.freeze
5
- PACKAGES = %w(katello candlepin pulp foreman hammer).freeze
5
+ PACKAGES = %w(katello candlepin pulp foreman hammer dynflow).freeze
6
6
 
7
7
  class << self
8
8
  def services(capsule_id = nil)
@@ -201,6 +201,12 @@ module Katello
201
201
  joins(:root).where("#{Katello::RootRepository.table_name}.product_id" => products)
202
202
  end
203
203
 
204
+ def self.repo_path_from_content_path(environment, content_path)
205
+ path = content_path.sub(%r|^/|, '')
206
+ path_prefix = [environment.organization.label, environment.label].join('/')
207
+ "#{path_prefix}/#{path}"
208
+ end
209
+
204
210
  def to_label
205
211
  name
206
212
  end
@@ -645,6 +651,33 @@ module Katello
645
651
  for_resource(self).order(:started_at).last
646
652
  end
647
653
 
654
+ def blocking_task
655
+ blocking_task_labels = [
656
+ ::Actions::Katello::Repository::Sync.name,
657
+ ::Actions::Katello::Repository::UploadFiles.name,
658
+ ::Actions::Katello::Repository::RemoveContent.name,
659
+ ::Actions::Katello::Repository::MetadataGenerate.name
660
+ ]
661
+ ForemanTasks::Task::DynflowTask.where(:label => blocking_task_labels)
662
+ .where.not(state: 'stopped')
663
+ .for_resource(self)
664
+ .order(:started_at)
665
+ .last
666
+ end
667
+
668
+ def check_ready_to_act!
669
+ blocking_tasks = content_views&.map { |cv| cv.blocking_task }&.compact
670
+
671
+ if blocking_tasks&.any?
672
+ errored_tasks = blocking_tasks
673
+ .uniq
674
+ .map { |task| "- #{Setting['foreman_url']}/foreman_tasks/tasks/#{task&.id}" }
675
+ .join("\n")
676
+ fail _("This repository has pending tasks in associated content views. Please wait for the tasks: " + errored_tasks +
677
+ " to complete before proceeding.")
678
+ end
679
+ end
680
+
648
681
  # returns other instances of this repo with the same library
649
682
  # equivalent of repo
650
683
  def environmental_instances(view)
@@ -387,10 +387,6 @@ module Katello
387
387
  Katello::RepositoryTypeManager.generic_repository_types(false).values.map(&:id).map(&:to_s).flatten.include? self.content_type
388
388
  end
389
389
 
390
- def metadata_generate_needed?
391
- (%w(unprotected checksum_type container_repsoitory_name) & previous_changes.keys).any?
392
- end
393
-
394
390
  def using_mirrored_content?
395
391
  self.mirroring_policy != Katello::RootRepository::MIRRORING_POLICY_ADDITIVE
396
392
  end
@@ -55,6 +55,15 @@ module Katello
55
55
  end
56
56
  end
57
57
 
58
+ def reimport_units
59
+ units_from_pulp.each do |units|
60
+ to_update = units.map do |unit|
61
+ @service_class.generate_model_row(unit)
62
+ end
63
+ @model_class.upsert_all(to_update, unique_by: :pulp_id)
64
+ end
65
+ end
66
+
58
67
  def import_associations(units)
59
68
  pulp_id_to_id = self.class.pulp_id_to_id_map(@content_type, units.map { |unit| unit[@service_class.unit_identifier] })
60
69
  @service_class.insert_child_associations(units, pulp_id_to_id) if @service_class.respond_to?(:insert_child_associations)
@@ -88,18 +88,16 @@ module Katello
88
88
  end
89
89
 
90
90
  def get_remote(href = smart_proxy_acs.remote_href)
91
- acs.base_url&.start_with?('uln') ? api.remotes_uln_api.read(href) : api.remotes_api.read(href)
91
+ api.get_remotes_api(href: href).read(href)
92
92
  end
93
93
 
94
- def update_remote
95
- api.remotes_api.partial_update(smart_proxy_acs.remote_href, remote_options)
94
+ def update_remote(href = smart_proxy_acs.remote_href)
95
+ api.get_remotes_api(href: href).partial_update(href, remote_options)
96
96
  end
97
97
 
98
- # The old repo URL is needed to determine which remote API to use.
99
98
  def delete_remote(options = {})
100
99
  options[:href] ||= smart_proxy_acs.remote_href
101
- options[:old_url] ||= remote_options[:url]
102
- ignore_404_exception { options[:old_url]&.start_with?('uln') ? api.remotes_uln_api.delete(options[:href]) : api.remotes_api.delete(options[:href]) } if options[:href]
100
+ ignore_404_exception { api.get_remotes_api(href: options[:href]).delete(options[:href]) } if options[:href]
103
101
  end
104
102
 
105
103
  def create
@@ -108,7 +106,7 @@ module Katello
108
106
  if acs.content_type == ::Katello::Repository::FILE_TYPE && acs.subpaths.present?
109
107
  paths = insert_pulp_manifest!(paths)
110
108
  end
111
- response = api.alternate_content_source_api.create(name: generate_backend_object_name, paths: paths,
109
+ response = api.alternate_content_source_api.create(name: generate_backend_object_name, paths: paths.sort,
112
110
  remote: smart_proxy_acs.remote_href)
113
111
  smart_proxy_acs.update!(alternate_content_source_href: response.pulp_href)
114
112
  return response
@@ -125,7 +123,7 @@ module Katello
125
123
  if acs.content_type == ::Katello::Repository::FILE_TYPE && acs.subpaths.present?
126
124
  paths = insert_pulp_manifest!(paths)
127
125
  end
128
- api.alternate_content_source_api.update(href, name: generate_backend_object_name, paths: paths, remote: smart_proxy_acs.remote_href)
126
+ api.alternate_content_source_api.update(href, name: generate_backend_object_name, paths: paths.sort, remote: smart_proxy_acs.remote_href)
129
127
  end
130
128
 
131
129
  def delete_alternate_content_source
@@ -47,6 +47,11 @@ module Katello
47
47
  fail NotImplementedError
48
48
  end
49
49
 
50
+ # Method is called with either :url or :href parameters for the sake of yum content.
51
+ def get_remotes_api(*)
52
+ remotes_api
53
+ end
54
+
50
55
  def publications_api
51
56
  repository_type.publications_api_class.new(api_client) #Optional
52
57
  end
@@ -136,6 +141,10 @@ module Katello
136
141
  client
137
142
  end
138
143
 
144
+ def repair_api
145
+ PulpcoreClient::RepairApi.new(core_api_client)
146
+ end
147
+
139
148
  def uploads_api
140
149
  PulpcoreClient::UploadsApi.new(core_api_client)
141
150
  end
@@ -230,6 +239,10 @@ module Katello
230
239
  end
231
240
  end
232
241
 
242
+ def repair
243
+ repair_api.post(PulpcoreClient::Repair.new(verify_checksums: true))
244
+ end
245
+
233
246
  def self.fetch_from_list
234
247
  page_size = Setting[:bulk_load_size]
235
248
  page_opts = { "offset" => 0, limit: page_size }
@@ -32,6 +32,17 @@ module Katello
32
32
  PulpRpmClient::RemotesUlnApi.new(api_client)
33
33
  end
34
34
 
35
+ def get_remotes_api(href: nil, url: nil)
36
+ fail 'Provide exactly one of href or url for yum remote selection!' if url.blank? && href.blank?
37
+ fail 'The href must be a pulp_rpm remote href!' if href && !href.start_with?('/pulp/api/v3/remotes/rpm/')
38
+
39
+ if href&.start_with?('/pulp/api/v3/remotes/rpm/uln/') || url&.start_with?('uln')
40
+ remotes_uln_api
41
+ else
42
+ remotes_api
43
+ end
44
+ end
45
+
35
46
  def copy_api
36
47
  PulpRpmClient::RpmCopyApi.new(api_client)
37
48
  end
@@ -26,7 +26,11 @@ module Katello
26
26
  {
27
27
  schema_version: unit['schema_version'],
28
28
  digest: unit['digest'],
29
- pulp_id: unit[unit_identifier]
29
+ pulp_id: unit[unit_identifier],
30
+ annotations: unit['annotations'],
31
+ labels: unit['labels'],
32
+ is_bootable: unit['is_bootable'],
33
+ is_flatpak: unit['is_flatpak']
30
34
  }
31
35
  end
32
36
  end
@@ -3,7 +3,7 @@ module Katello
3
3
  class Repository
4
4
  class Generic < ::Katello::Pulp3::Repository
5
5
  def copy_content_for_source(source_repository, _options = {})
6
- copy_units_by_href(source_repository.files.pluck(:pulp_id))
6
+ copy_units_by_href(source_repository.generic_content_units&.pluck(:pulp_id))
7
7
  end
8
8
 
9
9
  def distribution_options(path)