katello 4.4.0.rc1 → 4.4.0.1

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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/content_views_controller.rb +2 -0
  3. data/app/controllers/katello/api/v2/environments_controller.rb +2 -0
  4. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +10 -1
  5. data/app/controllers/katello/api/v2/repositories_controller.rb +3 -0
  6. data/app/lib/actions/katello/cdn_configuration/update.rb +2 -2
  7. data/app/lib/actions/katello/repository/errata_mail.rb +4 -5
  8. data/app/lib/actions/katello/repository/sync.rb +2 -2
  9. data/app/lib/actions/pulp3/abstract.rb +1 -1
  10. data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +14 -4
  11. data/app/lib/actions/pulp3/content_view_version/create_import_history.rb +1 -2
  12. data/app/lib/actions/pulp3/repository/reclaim_space.rb +3 -10
  13. data/app/lib/katello/resources/cdn/katello_cdn.rb +37 -14
  14. data/app/lib/katello/util/pulpcore_content_filters.rb +2 -1
  15. data/app/models/katello/candlepin/repository_mapper.rb +11 -2
  16. data/app/models/katello/cdn_configuration.rb +2 -0
  17. data/app/models/katello/concerns/audit_comment_extensions.rb +17 -0
  18. data/app/models/katello/concerns/host_managed_extensions.rb +11 -1
  19. data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -0
  20. data/app/models/katello/content_view_version_export_history.rb +2 -1
  21. data/app/models/katello/content_view_version_import_history.rb +4 -4
  22. data/app/models/katello/host_available_module_stream.rb +10 -0
  23. data/app/models/katello/installed_package.rb +1 -0
  24. data/app/models/katello/kt_environment.rb +1 -0
  25. data/app/models/katello/root_repository.rb +14 -2
  26. data/app/models/setting/content.rb +9 -2
  27. data/app/services/katello/organization_creator.rb +9 -5
  28. data/app/services/katello/pulp3/api/yum.rb +4 -0
  29. data/app/services/katello/pulp3/repository/yum.rb +11 -4
  30. data/app/services/katello/pulp3/repository.rb +4 -2
  31. data/app/services/katello/registration_manager.rb +1 -0
  32. data/app/views/foreman/job_templates/remove_packages_by_search_query.erb +19 -0
  33. data/app/views/foreman/job_templates/update_packages_by_search_query.erb +19 -0
  34. data/app/views/katello/api/v2/content_views/base.json.rabl +8 -4
  35. data/app/views/katello/api/v2/host_module_streams/base.json.rabl +1 -0
  36. data/app/views/katello/api/v2/repositories/show.json.rabl +2 -2
  37. data/db/migrate/20210119162528_delete_puppet_and_ostree_repos.rb +2 -0
  38. data/db/migrate/20211019192121_create_cdn_configuration.katello.rb +11 -2
  39. data/db/migrate/20220124191056_add_type_to_cdn_configuration.rb +1 -7
  40. data/db/migrate/20220209205137_expand_sync_timeout_settings.rb +23 -0
  41. data/db/migrate/20220303160220_remove_duplicate_errata.rb +40 -0
  42. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +10 -3
  43. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +4 -0
  44. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +17 -12
  45. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/views/sync-plan-products.html +1 -1
  46. data/lib/katello/plugin.rb +2 -0
  47. data/lib/katello/repository_types/ostree.rb +0 -6
  48. data/lib/katello/tasks/pulp2to3_migrate_deb_attributes.rake +20 -0
  49. data/lib/katello/version.rb +1 -1
  50. data/webpack/components/Errata/index.js +57 -57
  51. data/webpack/components/ErratumTypeLabel.js +16 -16
  52. data/webpack/components/MultiSelect/index.js +2 -2
  53. data/webpack/components/Select/Select.js +1 -1
  54. data/webpack/components/SelectOrg/SelectOrgReducer.js +15 -15
  55. data/webpack/components/SelectOrg/SetOrganization.js +1 -1
  56. data/webpack/components/Table/TableHooks.js +1 -0
  57. data/webpack/components/Table/TableWrapper.js +4 -1
  58. data/webpack/components/TypeAhead/helpers/commonPropTypes.js +1 -1
  59. data/webpack/components/TypeAhead/helpers/helpers.js +14 -14
  60. data/webpack/components/TypeAhead/pf3Search/TypeAheadSearch.js +1 -1
  61. data/webpack/components/WithOrganization/withOrganization.js +3 -3
  62. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +2 -1
  63. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +2 -1
  64. data/webpack/components/extensions/HostDetails/Cards/__tests__/contentViewDetailsCard.test.js +30 -31
  65. data/webpack/components/extensions/HostDetails/Cards/__tests__/errataOverviewCard.test.js +30 -3
  66. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +6 -4
  67. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/constants.js +1 -0
  68. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +1 -1
  69. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErratumExpansionContents.js +3 -3
  70. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsActions.js +16 -0
  71. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsConstants.js +3 -0
  72. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsSelectors.js +19 -0
  73. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +241 -0
  74. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/moduleStreamsTab.test.js +108 -0
  75. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/modules.fixtures.json +34 -0
  76. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesActions.js +58 -0
  77. data/webpack/components/extensions/HostDetails/{HostPackages → Tabs/PackagesTab}/HostPackagesConstants.js +3 -2
  78. data/webpack/components/extensions/HostDetails/{HostPackages → Tabs/PackagesTab}/HostPackagesSelectors.js +0 -0
  79. data/webpack/components/extensions/HostDetails/Tabs/{PackageInstallModal.js → PackagesTab/PackageInstallModal.js} +14 -14
  80. data/webpack/components/extensions/HostDetails/Tabs/{PackageInstallModal.scss → PackagesTab/PackageInstallModal.scss} +0 -0
  81. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +420 -0
  82. data/webpack/components/extensions/HostDetails/Tabs/{PackagesTab.scss → PackagesTab/PackagesTab.scss} +0 -0
  83. data/webpack/components/extensions/HostDetails/{YumInstallablePackages → Tabs/PackagesTab}/YumInstallablePackagesActions.js +1 -1
  84. data/webpack/components/extensions/HostDetails/{YumInstallablePackages → Tabs/PackagesTab}/YumInstallablePackagesConstants.js +0 -0
  85. data/webpack/components/extensions/HostDetails/{YumInstallablePackages → Tabs/PackagesTab}/YumInstallablePackagesSelectors.js +0 -0
  86. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +77 -1
  87. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +4 -0
  88. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +2 -2
  89. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +260 -10
  90. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +22 -26
  91. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +14 -1
  92. data/webpack/components/extensions/HostDetails/hostDetailsHelpers.js +10 -1
  93. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/ActivationKeys.test.js.snap +4 -0
  94. data/webpack/components/extensions/RegistrationCommands/fields/ActivationKeys.js +1 -1
  95. data/webpack/components/extensions/RegistrationCommands/fields/LifecycleEnvironment.js +1 -1
  96. data/webpack/components/extensions/about/SystemStatuses.js +1 -1
  97. data/webpack/components/extensions/about/SystemStatusesReducer.js +10 -10
  98. data/webpack/components/pf3Table/components/Table.js +2 -2
  99. data/webpack/components/pf3Table/components/TableBody.js +2 -2
  100. data/webpack/global_index.js +4 -3
  101. data/webpack/redux/OrganizationProducts/OrganizationProductsReducer.js +15 -15
  102. data/webpack/redux/reducers/RedHatRepositories/enabled.js +43 -43
  103. data/webpack/redux/reducers/RedHatRepositories/repositorySetRepositories.js +43 -43
  104. data/webpack/redux/reducers/RedHatRepositories/sets.js +31 -31
  105. data/webpack/scenes/AnsibleCollections/AnsibleCollectionsReducer.js +26 -26
  106. data/webpack/scenes/AnsibleCollections/Details/AnsibleCollectionDetailsReducer.js +19 -19
  107. data/webpack/scenes/Content/Table/ContentTable.js +1 -1
  108. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +2 -1
  109. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignHostsForm.js +2 -2
  110. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +1 -1
  111. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +1 -1
  112. data/webpack/scenes/ContentViews/Details/ContentViewDetailReducer.js +8 -8
  113. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +1 -1
  114. data/webpack/scenes/ContentViews/Details/Filters/ArtifactsWithNoErrata.js +8 -8
  115. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +1 -1
  116. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +1 -1
  117. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +1 -1
  118. data/webpack/scenes/ContentViews/Details/Filters/CVFilterDetailType.js +46 -46
  119. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +14 -14
  120. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +14 -14
  121. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +1 -1
  122. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +1 -1
  123. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +17 -17
  124. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +1 -1
  125. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +19 -18
  126. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVEnvironmentSelectionForm.js +18 -18
  127. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignActivationKeysForm.js +3 -3
  128. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignHostsForm.js +3 -3
  129. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedActivationKeys.js +1 -1
  130. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedHosts.js +1 -1
  131. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +1 -1
  132. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +15 -19
  133. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +46 -34
  134. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionRepositoryCell.js +65 -48
  135. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +1 -1
  136. data/webpack/scenes/ContentViews/Publish/CVPublishFinish.js +2 -2
  137. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +4 -4
  138. data/webpack/scenes/ContentViews/components/EnvironmentLabels.js +18 -18
  139. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +10 -10
  140. data/webpack/scenes/ContentViews/expansions/DetailsExpansion.js +2 -2
  141. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +7 -7
  142. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +7 -7
  143. data/webpack/scenes/Hosts/ChangeContentSource/components/FormField.js +3 -3
  144. data/webpack/scenes/ModuleStreams/Details/ModuleStreamDetailsReducer.js +18 -18
  145. data/webpack/scenes/ModuleStreams/ModuleStreamsReducer.js +26 -26
  146. data/webpack/scenes/Organizations/OrganizationReducer.js +8 -8
  147. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepositoryContent.js +4 -4
  148. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepositories.js +1 -1
  149. data/webpack/scenes/Settings/SettingsReducer.js +14 -14
  150. data/webpack/scenes/Settings/Tables/TableReducer.js +23 -23
  151. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailInfo.js +2 -2
  152. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProductContent.js +15 -15
  153. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +1 -1
  154. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +34 -34
  155. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +13 -13
  156. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/AirGappedTypeForm.js +3 -3
  157. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +4 -4
  158. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/UpstreamServerTypeForm.js +6 -5
  159. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +5 -5
  160. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +16 -16
  161. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +149 -149
  162. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsReducer.js +41 -41
  163. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Dialogs/DeleteDialog.js +6 -6
  164. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Table.js +12 -12
  165. data/webpack/services/index.js +36 -36
  166. data/webpack/utils/helpers.js +5 -5
  167. metadata +30 -18
  168. data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesActions.js +0 -27
  169. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +0 -244
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2cffead633d7427ab354f070ad520ef1436914690ae62a83707bd51f0ff94156
4
- data.tar.gz: 759afa6d6768f23db062327899cd38db646b99c59d5068027dcf4bdc74f47896
3
+ metadata.gz: 2b7c14fb8d3608a0596bbe874028ed8966b14c2d530e8f22dd33253e678e7f7b
4
+ data.tar.gz: 4d762d2ac2cbe0c7362b52901c4fdf671421aae11fe9c3fdf6146b8729221895
5
5
  SHA512:
6
- metadata.gz: f4d6669e6c29532fe48cb70fd014bc0fb0fd9e7ddfb29a3832e175134be2ecb40b2dbcedd458cef5303805680e28ec3d17a3ea9f250a3482403490c7dd22b3d1
7
- data.tar.gz: 458b225423b94a7cfb95034ee9bbff4d0fceca0effcf2dfd2651bb98bf535cadc681791ccbbaca19175cd17446fffab9b1190140f07973e8b220c28239aaf398
6
+ metadata.gz: 63470c8748cb2f52087d0e6afb152b3e1d7ac7b0985f755ea662189acf807945fba766f6def46417995b665a914adfcf62d5041bb2ea1381c03031a07d34ac34
7
+ data.tar.gz: 39dfbe4fe023dd34b8f371b2df102ffe8a9318c7f8ee0e67aa37b371c06ac171a8ab73fe6359ca17209209c73e7d083caf91e301b9e3ff040bb68069d48103c0
@@ -53,6 +53,7 @@ module Katello
53
53
  param :composite, :bool, :desc => N_("Filter only composite content views")
54
54
  param :without, Array, :desc => N_("Do not include this array of content views")
55
55
  param :name, String, :desc => N_("Name of the content view"), :required => false
56
+ param :label, String, :desc => N_("Label of the content view"), :required => false
56
57
  param_group :search, Api::V2::ApiController
57
58
  add_scoped_search_description_for(ContentView)
58
59
  def index
@@ -69,6 +70,7 @@ module Katello
69
70
  content_views = ::Foreman::Cast.to_bool(params[:noncomposite]) ? content_views.non_composite : content_views.composite if params[:noncomposite]
70
71
  content_views = ::Foreman::Cast.to_bool(params[:composite]) ? content_views.composite : content_views.non_composite if params[:composite]
71
72
  content_views = content_views.where(:name => params[:name]) if params[:name]
73
+ content_views = content_views.where(:label => params[:label]) if params[:label]
72
74
  content_views = content_views.where("#{ContentView.table_name}.id NOT IN (?)", params[:without]) if params[:without]
73
75
  content_views
74
76
  end
@@ -48,6 +48,7 @@ module Katello
48
48
  param :organization_id, :number, :desc => N_("organization identifier")
49
49
  param :library, [true, false], :desc => N_("set true if you want to see only library environments")
50
50
  param :name, String, :desc => N_("filter only environments containing this name")
51
+ param :label, String, :desc => N_("filter only environments containing this label"), :required => false
51
52
  param_group :search, Api::V2::ApiController
52
53
  add_scoped_search_description_for(KTEnvironment)
53
54
  def index
@@ -58,6 +59,7 @@ module Katello
58
59
  query = KTEnvironment.readable
59
60
  query = query.where(organization: @organization) if @organization
60
61
  query = query.where(:name => params[:name]) if params[:name]
62
+ query = query.where(:label => params[:label]) if params[:label]
61
63
  query = query.where(:library => params[:library]) if params[:library]
62
64
  query
63
65
  end
@@ -53,7 +53,16 @@ module Katello
53
53
  api :POST, "/repositories/bulk/reclaim_space", N_("Reclaim space from On Demand repositories")
54
54
  param :ids, Array, :desc => N_("List of repository ids"), :required => true
55
55
  def reclaim_space_from_repositories
56
- task = async_task(::Actions::Pulp3::Repository::ReclaimSpace, @repositories)
56
+ if @repositories.empty?
57
+ fail _("No repositories selected.")
58
+ end
59
+ repositories = @repositories.select { |repo| repo.download_policy == ::Katello::RootRepository::DOWNLOAD_ON_DEMAND }
60
+ if repositories.empty?
61
+ fail _("Only On Demand repositories may have space reclaimed.")
62
+ end
63
+ task = async_task(::Actions::BulkAction,
64
+ ::Actions::Pulp3::Repository::ReclaimSpace,
65
+ repositories)
57
66
 
58
67
  respond_for_async :resource => task
59
68
  end
@@ -327,6 +327,9 @@ module Katello
327
327
  api :POST, "/repositories/:id/reclaim_space", N_("Reclaim space from an On Demand repository")
328
328
  param :id, :number, :required => true, :desc => N_("repository ID")
329
329
  def reclaim_space
330
+ if @repository.download_policy != ::Katello::RootRepository::DOWNLOAD_ON_DEMAND
331
+ fail HttpErrors::BadRequest, _("Only On Demand repositories may have space reclaimed.")
332
+ end
330
333
  task = async_task(::Actions::Pulp3::Repository::ReclaimSpace, @repository)
331
334
  respond_for_async :resource => task
332
335
  rescue Errors::InvalidActionOptionError => e
@@ -4,10 +4,10 @@ module Actions
4
4
  class Update < Actions::EntryAction
5
5
  def plan(cdn_configuration, options)
6
6
  cdn_configuration.update!(options)
7
- return if cdn_configuration.airgapped?
8
7
 
9
8
  if cdn_configuration.upstream_server?
10
9
  resource = ::Katello::Resources::CDN::CdnResource.create(cdn_configuration: cdn_configuration)
10
+ resource.validate!
11
11
  keypair = resource.debug_certificate
12
12
  cdn_configuration.ssl_cert = OpenSSL::X509::Certificate.new(keypair)
13
13
  cdn_configuration.ssl_key = OpenSSL::PKey::RSA.new(keypair)
@@ -20,7 +20,7 @@ module Actions
20
20
  roots.each do |root|
21
21
  full_path = if cdn_configuration.redhat_cdn?
22
22
  root.product.repo_url(root.library_instance.generate_content_path)
23
- else
23
+ elsif cdn_configuration.upstream_server?
24
24
  resource.repository_url(content_label: root.content.label)
25
25
  end
26
26
  plan_action(::Actions::Katello::Repository::Update, root, url: full_path)
@@ -4,17 +4,16 @@ module Actions
4
4
  class ErrataMail < Actions::EntryAction
5
5
  middleware.use Actions::Middleware::ExecuteIfContentsChanged
6
6
 
7
- def plan(repo, last_updated = nil, contents_changed = nil)
8
- last_updated ||= repo.repository_errata.order('updated_at ASC').last.try(:updated_at) || Time.now
9
- plan_self(:repo => repo.id, :last_updated => last_updated.to_s, :contents_changed => contents_changed)
7
+ def plan(repo, contents_changed = nil)
8
+ plan_self(:repo => repo.id, :contents_changed => contents_changed)
10
9
  end
11
10
 
12
11
  def run
13
12
  ::User.current = ::User.anonymous_admin
14
-
15
13
  repo = ::Katello::Repository.find(input[:repo])
14
+ last_updated = repo.repository_errata.order('updated_at ASC').last.try(:updated_at) || Time.now
16
15
  users = ::User.select { |user| user.receives?(:sync_errata) && user.organization_ids.include?(repo.organization.id) && user.can?(:view_products, repo.product) }.compact
17
- errata = ::Katello::Erratum.where(:id => repo.repository_errata.where('katello_repository_errata.updated_at > ?', input[:last_updated].to_datetime).pluck(:erratum_id))
16
+ errata = ::Katello::Erratum.where(:id => repo.repository_errata.where('katello_repository_errata.updated_at > ?', last_updated).pluck(:erratum_id))
18
17
 
19
18
  begin
20
19
  MailNotification[:sync_errata].deliver(:users => users, :repo => repo, :errata => errata) unless (users.blank? || errata.blank?)
@@ -51,11 +51,11 @@ module Actions
51
51
  plan_action(Katello::Repository::FetchPxeFiles, :id => repo.id)
52
52
  plan_action(Katello::Repository::CorrectChecksum, repo)
53
53
  concurrence do
54
- plan_action(Katello::Repository::ErrataMail, repo, nil, contents_changed)
54
+ plan_action(Katello::Repository::ErrataMail, repo, output[:contents_changed])
55
55
  plan_action(Actions::Katello::Applicability::Repository::Regenerate, :repo_ids => [repo.id]) if generate_applicability
56
56
  end
57
57
  plan_self(:id => repo.id, :sync_result => output, :skip_metadata_check => skip_metadata_check, :validate_contents => validate_contents,
58
- :contents_changed => contents_changed)
58
+ :contents_changed => output[:contents_changed])
59
59
  plan_action(Katello::Repository::SyncHook, :id => repo.id)
60
60
  end
61
61
  end
@@ -1,6 +1,6 @@
1
1
  module Actions
2
2
  module Pulp3
3
- class Abstract < Actions::Base
3
+ class Abstract < Actions::EntryAction
4
4
  middleware.use ::Actions::Middleware::RemoteAction
5
5
  middleware.use Actions::Middleware::Pulp3ServicesCheck
6
6
 
@@ -11,15 +11,25 @@ module Actions
11
11
  def invoke_external_task
12
12
  tasks = []
13
13
  content_view = ::Katello::ContentView.find(input[:content_view_id])
14
- content_view.repository_references.each do |repository_reference|
14
+ to_delete = content_view.repository_references.select do |repository_reference|
15
15
  repo = repository_reference.root_repository.library_instance
16
- #force pulp3 in case we've done migrations, but haven't switched over yet
17
- tasks << repo.backend_service(smart_proxy, true).delete_repository(repository_reference)
16
+ if delete_href?(repository_reference.repository_href, content_view)
17
+ #force pulp3 in case we've done migrations, but haven't switched over yet
18
+ tasks << repo.backend_service(smart_proxy, true).delete_repository(repository_reference)
19
+ true
20
+ else
21
+ false
22
+ end
18
23
  end
19
- content_view.repository_references.destroy_all
24
+ to_delete.each(&:destroy)
20
25
 
21
26
  output[:pulp_tasks] = tasks
22
27
  end
28
+
29
+ #migrated composites may have the same RepositoryReference as their component
30
+ def delete_href?(href, content_view)
31
+ ::Katello::Pulp3::RepositoryReference.where(:repository_href => href).where.not(:content_view_id => content_view.id).empty?
32
+ end
23
33
  end
24
34
  end
25
35
  end
@@ -18,8 +18,7 @@ module Actions
18
18
  content_view_version_id: input[:content_view_version_id],
19
19
  path: input[:path],
20
20
  metadata: input[:metadata],
21
- audit_comment: ::Katello::ContentViewVersionImportHistory.generate_audit_comment(path: input[:path],
22
- user: User.current,
21
+ audit_comment: ::Katello::ContentViewVersionImportHistory.generate_audit_comment(user: User.current,
23
22
  content_view_name: input[:content_view_name])
24
23
  )
25
24
  output[:import_history_id] = history.id
@@ -2,16 +2,9 @@ module Actions
2
2
  module Pulp3
3
3
  module Repository
4
4
  class ReclaimSpace < Pulp3::AbstractAsyncTask
5
- def plan(repositories, smart_proxy = SmartProxy.pulp_primary)
6
- repositories = [repositories] if repositories.is_a?(::Katello::Repository)
7
- if repositories.empty?
8
- fail _("No repositories selected.")
9
- end
10
- repositories = repositories.select { |repo| repo.download_policy == ::Katello::RootRepository::DOWNLOAD_ON_DEMAND }
11
- if repositories.empty?
12
- fail _("Only On Demand repositories may have space reclaimed.")
13
- end
14
- repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs(repositories, Organization.current)
5
+ def plan(repo, smart_proxy = SmartProxy.pulp_primary)
6
+ action_subject(repo)
7
+ repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs([repo], Organization.current || repositories.first.organization)
15
8
  plan_self(repository_hrefs: repository_hrefs, smart_proxy_id: smart_proxy.id)
16
9
  end
17
10
 
@@ -4,8 +4,8 @@ module Katello
4
4
  class KatelloCdn < CdnResource
5
5
  def initialize(url, options)
6
6
  @organization_label = options.delete(:organization_label)
7
- @content_view_label = options.delete(:content_view_label)
8
- @lifecycle_environment_label = options.delete(:lifecycle_environment_label)
7
+ @content_view_label = options.delete(:content_view_label) || ::Katello::OrganizationCreator::DEFAULT_CONTENT_VIEW_LABEL
8
+ @lifecycle_environment_label = options.delete(:lifecycle_environment_label) || ::Katello::OrganizationCreator::DEFAULT_LIFECYCLE_ENV_LABEL
9
9
  fail ArgumentError, "No upstream organization was specified" if @organization_label.nil?
10
10
 
11
11
  super
@@ -18,16 +18,33 @@ module Katello
18
18
 
19
19
  fail _("Upstream organization %s does not provide this content path") % @organization_label if repo_set.nil?
20
20
 
21
- # now get available repositories when we know the upstream repo set ID
22
- url = "/katello/api/v2/repository_sets/#{repo_set['id']}/available_repositories?organization_id=#{organization['id']}"
21
+ params = {
22
+ full_result: true,
23
+ organization_id: organization['id'],
24
+ content_view_id: content_view_id,
25
+ environment_id: lifecycle_environment_id,
26
+ search: CGI.escape("content_label = #{repo_set['label']}")
27
+ }
28
+ query_params = params.map { |key, value| "#{key}=#{value}" }
29
+
30
+ url = "/katello/api/v2/repositories?#{query_params.join("&")}"
23
31
  response = get(url)
24
32
  json_body = JSON.parse(response)
25
33
  results = json_body['results']
26
34
 
27
- results.map do |r|
35
+ results.map do |repo|
36
+ arch = repo['arch']
37
+ arch = nil if arch == "noarch"
38
+ substitutions = {
39
+ :releasever => repo['minor'],
40
+ :basearch => arch
41
+ }.compact
42
+ path = substitutions.inject(content_path) do |path_url, (key, value)|
43
+ path_url.gsub("$#{key}", value)
44
+ end
28
45
  {
29
- path: r['path'],
30
- substitutions: r['substitutions']
46
+ path: path,
47
+ substitutions: substitutions
31
48
  }
32
49
  end
33
50
  end
@@ -36,12 +53,16 @@ module Katello
36
53
  true
37
54
  end
38
55
 
56
+ def validate!
57
+ organization && content_view_id && lifecycle_environment_id
58
+ end
59
+
39
60
  def debug_certificate
40
61
  get("/katello/api/v2/organizations/#{organization['id']}/download_debug_certificate")
41
62
  end
42
63
 
43
64
  def content_view_id
44
- rs = get("/katello/api/v2/organizations/#{organization['id']}/content_views?name=#{CGI.escape(@content_view_label)}")
65
+ rs = get("/katello/api/v2/organizations/#{organization['id']}/content_views?search=#{CGI.escape("label=#{@content_view_label}")}")
45
66
  content_view = JSON.parse(rs)['results']&.first
46
67
  if content_view.blank?
47
68
  fail _("Upstream organization %{org_label} does not have a content view with the label %{cv_label}") % { org_label: @organization_label,
@@ -51,7 +72,7 @@ module Katello
51
72
  end
52
73
 
53
74
  def lifecycle_environment_id
54
- rs = get("/katello/api/v2/organizations/#{organization['id']}/environments")
75
+ rs = get("/katello/api/v2/organizations/#{organization['id']}/environments?full_result=true")
55
76
  env = JSON.parse(rs)['results'].find { |lce| lce['label'] == @lifecycle_environment_label }
56
77
 
57
78
  if env.blank?
@@ -61,7 +82,7 @@ module Katello
61
82
  env["id"]
62
83
  end
63
84
 
64
- def repository_url(content_label:)
85
+ def repository_url(content_label:, arch:, major:, minor:)
65
86
  params = {
66
87
  search: CGI.escape("content_label = #{content_label}")
67
88
  }
@@ -72,17 +93,19 @@ module Katello
72
93
  query_params = params.map { |key, value| "#{key}=#{value}" }
73
94
  url = "/katello/api/v2/organizations/#{organization['id']}/repositories?#{query_params.join('&')}"
74
95
  response = get(url)
75
- repository = JSON.parse(response)['results'].first
76
-
96
+ repository = JSON.parse(response)['results']&.find { |r| r['arch'] == arch && r['major'] == major && r['minor'] == minor }
77
97
  if repository.nil?
78
98
  msg_params = { content_label: content_label,
99
+ arch: arch,
100
+ major: major,
101
+ minor: minor,
79
102
  org_label: @organization_label,
80
103
  cv_label: @content_view_label || Katello::OrganizationCreator::DEFAULT_CONTENT_VIEW_LABEL,
81
104
  env_label: @lifecycle_environment_label || Katello::OrganizationCreator::DEFAULT_LIFECYCLE_ENV_LABEL
82
105
  }
83
106
 
84
- fail _("Repository with content label %{content_label} was not found in upstream organization %{org_label},"\
85
- " content view %{cv_label} and lifecycle environment %{env_label} ") % msg_params
107
+ fail _("Repository with content label: '%{content_label}'#{arch ? ', arch: \'%{arch}\'' : ''}#{minor ? ', version: \'%{minor}\'' : ''} was not found in upstream organization '%{org_label}',"\
108
+ " content view '%{cv_label}' and lifecycle environment '%{env_label}'") % msg_params
86
109
  end
87
110
  repository['full_path']
88
111
  end
@@ -8,8 +8,9 @@ module Katello
8
8
  def filter_package_groups_by_pulp_href(package_groups, package_pulp_hrefs)
9
9
  rpms = Katello::Rpm.where(:pulp_id => package_pulp_hrefs)
10
10
  package_groups.reject do |package_group|
11
+ #copy the package group as long as we have 1 package from the group
11
12
  package_group.package_names.empty? ||
12
- (package_group.package_names - rpms.pluck(:name)).any?
13
+ (package_group.package_names & rpms.pluck(:name)).empty?
13
14
  end
14
15
  end
15
16
 
@@ -34,7 +34,7 @@ module Katello
34
34
  :content_type => katello_content_type,
35
35
  :unprotected => unprotected?,
36
36
  :download_policy => download_policy,
37
- :mirroring_policy => Katello::RootRepository::MIRRORING_POLICY_COMPLETE
37
+ :mirroring_policy => mirroring_policy
38
38
  )
39
39
 
40
40
  Repository.new(:root => root,
@@ -74,8 +74,9 @@ module Katello
74
74
  end
75
75
 
76
76
  def feed_url
77
+ return if product.organization.cdn_configuration.airgapped?
77
78
  @feed_url ||= if product.cdn_resource&.respond_to?(:repository_url)
78
- product.cdn_resource.repository_url(content_label: content.label)
79
+ product.cdn_resource.repository_url(content_label: content.label, arch: arch, major: version[:major], minor: version[:minor])
79
80
  else
80
81
  product.repo_url(path)
81
82
  end
@@ -136,6 +137,14 @@ module Katello
136
137
  ""
137
138
  end
138
139
  end
140
+
141
+ def mirroring_policy
142
+ if katello_content_type == Repository::YUM_TYPE
143
+ Katello::RootRepository::MIRRORING_POLICY_COMPLETE
144
+ else
145
+ Katello::RootRepository::MIRRORING_POLICY_CONTENT
146
+ end
147
+ end
139
148
  end
140
149
  end
141
150
  end
@@ -53,6 +53,8 @@ module Katello
53
53
  self.ssl_ca_credential_id = nil
54
54
  self.upstream_content_view_label = nil
55
55
  self.upstream_lifecycle_environment_label = nil
56
+ self.ssl_cert = nil
57
+ self.ssl_key = nil
56
58
  end
57
59
 
58
60
  def non_redhat_configuration
@@ -0,0 +1,17 @@
1
+ module Katello
2
+ module Concerns::AuditCommentExtensions
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ # to prevent PG::StringDataRightTruncation: ERROR: value too long for type character varying(255)
7
+ def truncate_audit_comment(long_comment)
8
+ if long_comment.length > 255
9
+ Rails.logger.info "Truncating audit comment: #{long_comment}"
10
+ "#{long_comment[0..250]}..."
11
+ else
12
+ long_comment
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -401,10 +401,20 @@ module Katello
401
401
  end
402
402
 
403
403
  def package_names_for_job_template(action:, search:)
404
- actions = ['install']
404
+ actions = %w(install remove update).freeze
405
405
  case action
406
406
  when 'install'
407
407
  ::Katello::Rpm.yum_installable_for_host(self).search_for(search).distinct.pluck(:name)
408
+ when 'remove'
409
+ return [] if search.empty?
410
+
411
+ installed_packages.search_for(search).distinct.pluck(:name)
412
+ when 'update'
413
+ return [] if search.empty?
414
+
415
+ pkg_names = installed_packages.search_for(search).distinct.pluck(:name)
416
+ upgrades = ::Katello::Rpm.installable_for_hosts([self]).select(:id, :name, :nvra, :evr).order(evr: :desc).group_by(&:name)
417
+ pkg_names.map { |p| upgrades[p]&.first&.nvra }.compact
408
418
  else
409
419
  fail ::Foreman::Exception.new(N_("package_names_for_job_template: Action must be one of %s"), actions.join(', '))
410
420
  end
@@ -179,6 +179,7 @@ module Katello
179
179
  config.scheme = uri.scheme
180
180
  pulp3_ssl_configuration(config)
181
181
  config.debugging = false
182
+ config.timeout = SETTINGS[:katello][:rest_client_timeout]
182
183
  config.logger = ::Foreman::Logging.logger('katello/pulp_rest')
183
184
  config.username = self.setting(PULP3_FEATURE, 'username')
184
185
  config.password = self.setting(PULP3_FEATURE, 'password')
@@ -1,6 +1,7 @@
1
1
  module Katello
2
2
  class ContentViewVersionExportHistory < Katello::Model
3
3
  include Authorization::ContentViewVersionExportHistory
4
+ include Concerns::AuditCommentExtensions
4
5
  audited except: :metadata
5
6
  delegate :organization, to: :content_view_version
6
7
  delegate :id, to: :organization, prefix: true
@@ -58,7 +59,7 @@ module Katello
58
59
  export_descriptor = "export of content view '#{content_view_version.content_view.name}' version #{content_view_version.version}"
59
60
  export_descriptor += " from #{from_version.name}" if from_version
60
61
  end
61
- "#{export_type&.capitalize} #{export_descriptor} created by #{user.to_label}"
62
+ truncate_audit_comment("#{export_type&.capitalize} #{export_descriptor} created by #{user.to_label}")
62
63
  end
63
64
  end
64
65
  end
@@ -1,6 +1,7 @@
1
1
  module Katello
2
2
  class ContentViewVersionImportHistory < Katello::Model
3
3
  include Authorization::ContentViewVersionImportHistory
4
+ include Concerns::AuditCommentExtensions
4
5
 
5
6
  audited except: :metadata
6
7
  delegate :organization, to: :content_view_version
@@ -31,12 +32,11 @@ module Katello
31
32
  scoped_search :on => :id, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
32
33
  scoped_search :on => :import_type, :rename => :type, :complete_value => ContentViewVersionExportHistory::EXPORT_TYPES
33
34
 
34
- def self.generate_audit_comment(user:, path:, content_view_name:)
35
- _("Content imported from %{path} into content view '%{name}' by %{user}") % {
36
- path: path,
35
+ def self.generate_audit_comment(user:, content_view_name:)
36
+ truncate_audit_comment(_("Content imported by %{user} into content view '%{name}'") % {
37
37
  user: user.to_label,
38
38
  name: content_view_name
39
- }
39
+ })
40
40
  end
41
41
  end
42
42
  end
@@ -37,6 +37,16 @@ module Katello
37
37
  :stream => available_module_stream.stream}).exists?
38
38
  end
39
39
 
40
+ def install_status
41
+ return 'Not installed' if installed_profiles.blank?
42
+ case status
43
+ when 'disabled'
44
+ 'Installed'
45
+ when 'enabled'
46
+ upgradable? ? 'Upgradable' : 'Up-to-date'
47
+ end
48
+ end
49
+
40
50
  def self.upgradable(host)
41
51
  upgradable_module_name_streams = ModuleStream.installable_for_hosts([host]).select(:name, :stream)
42
52
 
@@ -15,6 +15,7 @@ module Katello
15
15
  has_many :host_installed_packages, :class_name => "Katello::HostInstalledPackage", :dependent => :destroy, :inverse_of => :installed_package
16
16
  has_many :hosts, :through => :host_installed_packages, :class_name => "::Host"
17
17
 
18
+ scoped_search :on => :id, :complete_value => true
18
19
  scoped_search :on => :name, :complete_value => true
19
20
  scoped_search :on => :nvrea
20
21
  scoped_search :on => :nvra
@@ -75,6 +75,7 @@ module Katello
75
75
  ERROR_CLASS_NAME = "Environment".freeze
76
76
 
77
77
  scoped_search :on => :name, :complete_value => true
78
+ scoped_search :on => :label, :complete_value => true
78
79
  scoped_search :on => :organization_id, :complete_value => true, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
79
80
  scoped_search :on => :id, :complete_value => true, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
80
81
 
@@ -62,7 +62,8 @@ module Katello
62
62
  validates_lengths_from_database :except => [:label]
63
63
  validates_with Validators::KatelloLabelFormatValidator, :attributes => :label
64
64
  validates_with Validators::KatelloNameFormatValidator, :attributes => :name
65
- validates_with Validators::KatelloUrlFormatValidator, :attributes => :url, :nil_allowed => proc { |repo| repo.custom? },
65
+ validates_with Validators::KatelloUrlFormatValidator, :attributes => :url,
66
+ :nil_allowed => proc { |repo| repo.custom? || repo.organization.cdn_configuration.airgapped? },
66
67
  :field_name => :url
67
68
  validates_with Validators::RootRepositoryUniqueAttributeValidator, :attributes => :name
68
69
  validates_with Validators::RootRepositoryUniqueAttributeValidator, :attributes => :label
@@ -83,6 +84,7 @@ module Katello
83
84
  validate :ensure_valid_deb_constraints, :if => :deb?
84
85
  validate :ensure_no_checksum_on_demand
85
86
  validate :ensure_valid_mirroring_policy
87
+ validate :ensure_valid_retain_package_versions_count
86
88
  validates :checksum_type, :inclusion => {:in => CHECKSUM_TYPES}, :allow_blank => true
87
89
  validates :product_id, :presence => true
88
90
  validates :content_type, :inclusion => {
@@ -306,6 +308,16 @@ module Katello
306
308
  end
307
309
  end
308
310
 
311
+ def ensure_valid_retain_package_versions_count
312
+ return unless self.retain_package_versions_count
313
+ unless yum?
314
+ errors.add(:retain_package_versions_count, N_("is only allowed for Yum repositories."))
315
+ end
316
+ if self.retain_package_versions_count.to_i < 0
317
+ errors.add(:retain_package_versions_count, N_("must not be a negative value."))
318
+ end
319
+ end
320
+
309
321
  def custom_content_path
310
322
  parts = []
311
323
  # We generate repo path only for custom product content. We add this
@@ -372,7 +384,7 @@ module Katello
372
384
 
373
385
  def pulp_update_needed?
374
386
  changeable_attributes = %w(url unprotected checksum_type docker_upstream_name download_policy mirroring_policy verify_ssl_on_sync
375
- upstream_username upstream_password ignorable_content
387
+ upstream_username upstream_password ignorable_content retain_package_versions_count
376
388
  ssl_ca_cert_id ssl_client_cert_id ssl_client_key_id http_proxy_policy http_proxy_id download_concurrency)
377
389
  changeable_attributes += %w(name container_repository_name include_tags exclude_tags) if docker?
378
390
  changeable_attributes += %w(deb_releases deb_components deb_architectures gpg_key_id) if deb?
@@ -105,8 +105,15 @@ class Setting::Content < Setting
105
105
  "/etc/pki/katello/private/pulp-client.key", N_('Pulp client key')),
106
106
  self.set('pulp_client_cert', N_("Path for ssl cert used for pulp server auth"),
107
107
  "/etc/pki/katello/certs/pulp-client.crt", N_('Pulp client cert')),
108
- self.set('sync_connect_timeout', N_("Total timeout in seconds for connections when syncing"),
109
- 300, N_('Sync Connection Timeout')),
108
+ self.set('sync_total_timeout', N_("The maximum number of second that Pulp can take to do a single sync operation, e.g., download a single metadata file."),
109
+ 3600, N_('Sync Total Timeout')),
110
+ self.set('sync_connect_timeout_v2',
111
+ N_("The maximum number of seconds for Pulp to establish a new connection or for waiting for a free connection from a pool if pool connection limits are exceeded."),
112
+ 60, N_('Sync Connect Timeout')),
113
+ self.set('sync_sock_connect_timeout', N_("The maximum number of seconds for Pulp to connect to a peer for a new connection not given from a pool."),
114
+ 60, N_('Sync Sock Connect Timeout')),
115
+ self.set('sync_sock_read_timeout', N_("The maximum number of seconds that Pulp can take to download a file, not counting connection time."),
116
+ 3600, N_('Sync Sock Read Timeout')),
110
117
  self.set('remote_execution_by_default', N_("If this is enabled, remote execution is used instead of katello-agent for remote actions"),
111
118
  false, N_('Use remote execution by default')),
112
119
  self.set('unregister_delete_host', N_("When unregistering a host via subscription-manager, also delete the host record. Managed resources linked to host " \
@@ -133,11 +133,15 @@ module Katello
133
133
  end
134
134
 
135
135
  def create_cdn_configuration
136
- @cdn_configuration = Katello::CdnConfiguration.where(
137
- organization: @organization,
138
- url: ::Katello::Resources::CDN::CdnResource.redhat_cdn_url,
139
- type: ::Katello::CdnConfiguration::CDN_TYPE
140
- ).first_or_create!
136
+ @cdn_configuration = Katello::CdnConfiguration.where(organization: @organization)
137
+
138
+ if @cdn_configuration.blank?
139
+ Katello::CdnConfiguration.where(
140
+ organization: @organization,
141
+ url: ::Katello::Resources::CDN::CdnResource.redhat_cdn_url,
142
+ type: ::Katello::CdnConfiguration::CDN_TYPE
143
+ ).first_or_create!
144
+ end
141
145
  end
142
146
  end
143
147
  end
@@ -36,6 +36,10 @@ module Katello
36
36
  PulpRpmClient::ContentPackageenvironmentsApi.new(api_client)
37
37
  end
38
38
 
39
+ def content_modulemd_defaults_api
40
+ PulpRpmClient::ContentModulemdDefaultsApi.new(api_client)
41
+ end
42
+
39
43
  def content_repo_metadata_files_api
40
44
  PulpRpmClient::ContentRepoMetadataFilesApi.new(api_client)
41
45
  end