katello 4.4.0.rc1 → 4.4.0.rc2

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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +10 -1
  3. data/app/controllers/katello/api/v2/repositories_controller.rb +3 -0
  4. data/app/lib/actions/katello/repository/errata_mail.rb +4 -5
  5. data/app/lib/actions/katello/repository/sync.rb +2 -2
  6. data/app/lib/actions/pulp3/abstract.rb +1 -1
  7. data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +14 -4
  8. data/app/lib/actions/pulp3/content_view_version/create_import_history.rb +1 -2
  9. data/app/lib/actions/pulp3/repository/reclaim_space.rb +3 -10
  10. data/app/lib/katello/util/pulpcore_content_filters.rb +2 -1
  11. data/app/models/katello/candlepin/repository_mapper.rb +1 -0
  12. data/app/models/katello/concerns/audit_comment_extensions.rb +17 -0
  13. data/app/models/katello/concerns/host_managed_extensions.rb +11 -1
  14. data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -0
  15. data/app/models/katello/content_view_version_export_history.rb +2 -1
  16. data/app/models/katello/content_view_version_import_history.rb +4 -4
  17. data/app/models/katello/host_available_module_stream.rb +10 -0
  18. data/app/models/katello/installed_package.rb +1 -0
  19. data/app/models/katello/root_repository.rb +14 -2
  20. data/app/models/setting/content.rb +9 -2
  21. data/app/services/katello/pulp3/api/yum.rb +4 -0
  22. data/app/services/katello/pulp3/repository/yum.rb +11 -4
  23. data/app/services/katello/pulp3/repository.rb +4 -2
  24. data/app/views/foreman/job_templates/remove_packages_by_search_query.erb +19 -0
  25. data/app/views/foreman/job_templates/update_packages_by_search_query.erb +19 -0
  26. data/app/views/katello/api/v2/content_views/base.json.rabl +8 -4
  27. data/app/views/katello/api/v2/host_module_streams/base.json.rabl +1 -0
  28. data/db/migrate/20210119162528_delete_puppet_and_ostree_repos.rb +2 -0
  29. data/db/migrate/20211019192121_create_cdn_configuration.katello.rb +11 -2
  30. data/db/migrate/20220209205137_expand_sync_timeout_settings.rb +23 -0
  31. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +10 -3
  32. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +4 -0
  33. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +17 -12
  34. data/lib/katello/plugin.rb +2 -0
  35. data/lib/katello/repository_types/ostree.rb +0 -6
  36. data/lib/katello/version.rb +1 -1
  37. data/webpack/components/Errata/index.js +57 -57
  38. data/webpack/components/ErratumTypeLabel.js +16 -16
  39. data/webpack/components/MultiSelect/index.js +2 -2
  40. data/webpack/components/Select/Select.js +1 -1
  41. data/webpack/components/SelectOrg/SelectOrgReducer.js +15 -15
  42. data/webpack/components/SelectOrg/SetOrganization.js +1 -1
  43. data/webpack/components/Table/TableHooks.js +1 -0
  44. data/webpack/components/Table/TableWrapper.js +4 -1
  45. data/webpack/components/TypeAhead/helpers/commonPropTypes.js +1 -1
  46. data/webpack/components/TypeAhead/helpers/helpers.js +14 -14
  47. data/webpack/components/TypeAhead/pf3Search/TypeAheadSearch.js +1 -1
  48. data/webpack/components/WithOrganization/withOrganization.js +3 -3
  49. data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesActions.js +32 -1
  50. data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesConstants.js +3 -2
  51. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +5 -3
  52. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/constants.js +1 -0
  53. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErratumExpansionContents.js +3 -3
  54. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsActions.js +16 -0
  55. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsConstants.js +3 -0
  56. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsSelectors.js +19 -0
  57. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +241 -0
  58. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/moduleStreamsTab.test.js +108 -0
  59. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/modules.fixtures.json +34 -0
  60. data/webpack/components/extensions/HostDetails/Tabs/PackageInstallModal.js +5 -5
  61. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +255 -79
  62. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +76 -0
  63. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +4 -0
  64. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +259 -9
  65. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +22 -26
  66. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +13 -0
  67. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/ActivationKeys.test.js.snap +4 -0
  68. data/webpack/components/extensions/RegistrationCommands/fields/ActivationKeys.js +1 -1
  69. data/webpack/components/extensions/RegistrationCommands/fields/LifecycleEnvironment.js +1 -1
  70. data/webpack/components/extensions/about/SystemStatuses.js +1 -1
  71. data/webpack/components/extensions/about/SystemStatusesReducer.js +10 -10
  72. data/webpack/components/pf3Table/components/Table.js +2 -2
  73. data/webpack/components/pf3Table/components/TableBody.js +2 -2
  74. data/webpack/redux/OrganizationProducts/OrganizationProductsReducer.js +15 -15
  75. data/webpack/redux/reducers/RedHatRepositories/enabled.js +43 -43
  76. data/webpack/redux/reducers/RedHatRepositories/repositorySetRepositories.js +43 -43
  77. data/webpack/redux/reducers/RedHatRepositories/sets.js +31 -31
  78. data/webpack/scenes/AnsibleCollections/AnsibleCollectionsReducer.js +26 -26
  79. data/webpack/scenes/AnsibleCollections/Details/AnsibleCollectionDetailsReducer.js +19 -19
  80. data/webpack/scenes/Content/Table/ContentTable.js +1 -1
  81. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +2 -1
  82. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignHostsForm.js +2 -2
  83. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +1 -1
  84. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +1 -1
  85. data/webpack/scenes/ContentViews/Details/ContentViewDetailReducer.js +8 -8
  86. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +1 -1
  87. data/webpack/scenes/ContentViews/Details/Filters/ArtifactsWithNoErrata.js +8 -8
  88. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +1 -1
  89. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +1 -1
  90. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +1 -1
  91. data/webpack/scenes/ContentViews/Details/Filters/CVFilterDetailType.js +46 -46
  92. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +14 -14
  93. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +14 -14
  94. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +1 -1
  95. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +1 -1
  96. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +17 -17
  97. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +1 -1
  98. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +19 -18
  99. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVEnvironmentSelectionForm.js +18 -18
  100. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignActivationKeysForm.js +3 -3
  101. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignHostsForm.js +3 -3
  102. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedActivationKeys.js +1 -1
  103. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedHosts.js +1 -1
  104. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +1 -1
  105. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +46 -34
  106. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionRepositoryCell.js +65 -48
  107. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +1 -1
  108. data/webpack/scenes/ContentViews/Publish/CVPublishFinish.js +2 -2
  109. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +4 -4
  110. data/webpack/scenes/ContentViews/components/EnvironmentLabels.js +18 -18
  111. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +10 -10
  112. data/webpack/scenes/ContentViews/expansions/DetailsExpansion.js +2 -2
  113. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +7 -7
  114. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +7 -7
  115. data/webpack/scenes/Hosts/ChangeContentSource/components/FormField.js +3 -3
  116. data/webpack/scenes/ModuleStreams/Details/ModuleStreamDetailsReducer.js +18 -18
  117. data/webpack/scenes/ModuleStreams/ModuleStreamsReducer.js +26 -26
  118. data/webpack/scenes/Organizations/OrganizationReducer.js +8 -8
  119. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepositoryContent.js +4 -4
  120. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepositories.js +1 -1
  121. data/webpack/scenes/Settings/SettingsReducer.js +14 -14
  122. data/webpack/scenes/Settings/Tables/TableReducer.js +23 -23
  123. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailInfo.js +2 -2
  124. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProductContent.js +15 -15
  125. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +1 -1
  126. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +34 -34
  127. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +13 -13
  128. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/AirGappedTypeForm.js +3 -3
  129. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +4 -4
  130. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/UpstreamServerTypeForm.js +3 -3
  131. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +5 -5
  132. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +16 -16
  133. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +149 -149
  134. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsReducer.js +41 -41
  135. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Dialogs/DeleteDialog.js +6 -6
  136. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Table.js +12 -12
  137. data/webpack/services/index.js +36 -36
  138. data/webpack/utils/helpers.js +5 -5
  139. metadata +16 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2cffead633d7427ab354f070ad520ef1436914690ae62a83707bd51f0ff94156
4
- data.tar.gz: 759afa6d6768f23db062327899cd38db646b99c59d5068027dcf4bdc74f47896
3
+ metadata.gz: 294ac07f46dd213e4ebbdd13f97d387b39ef2e5859ed6224e354672f4b26f244
4
+ data.tar.gz: b08b1182252900cc7390ae257b1a9243fcdb26f00d64b1f668cc17faff4f08e8
5
5
  SHA512:
6
- metadata.gz: f4d6669e6c29532fe48cb70fd014bc0fb0fd9e7ddfb29a3832e175134be2ecb40b2dbcedd458cef5303805680e28ec3d17a3ea9f250a3482403490c7dd22b3d1
7
- data.tar.gz: 458b225423b94a7cfb95034ee9bbff4d0fceca0effcf2dfd2651bb98bf535cadc681791ccbbaca19175cd17446fffab9b1190140f07973e8b220c28239aaf398
6
+ metadata.gz: 85c64b73f97252bd9f99c28071bddd97aebc83a525a5ec8559f4538180c733eca336e433e4d2f06204e6d57c5333246fc512e155c2396622daa369fd0dc0bbb4
7
+ data.tar.gz: e5d7904f19cb93eac89ff6e27b6c585e53f9419e925c4c5bedce2b30ac7a1d8df6c3e518574ad86c6607edbacc99a21360df54cef3b3ddfb94c4c38570f945a7
@@ -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,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
 
@@ -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
 
@@ -74,6 +74,7 @@ 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
79
  product.cdn_resource.repository_url(content_label: content.label)
79
80
  else
@@ -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
@@ -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 " \
@@ -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
@@ -101,16 +101,18 @@ module Katello
101
101
  # -> Unless incrementally updating a CV repo that is a soft copy of its library instance.
102
102
  # -> I.e. no filters and not an incremental version.
103
103
  unless dest_repo_id_map[:base_version]
104
- source_repo_for_package_envs = ::Katello::Repository.find(source_repo_ids.first)
105
- unless source_repo_for_package_envs.library_instance?
106
- source_repo_for_package_envs = source_repo_for_package_envs.library_instance
104
+ source_repo_for_content = ::Katello::Repository.find(source_repo_ids.first)
105
+ unless source_repo_for_content.library_instance?
106
+ source_repo_for_content = source_repo_for_content.library_instance
107
107
  end
108
- package_env_hrefs = packageenvironments({ :repository_version => source_repo_for_package_envs.version_href }).map(&:pulp_href).sort
108
+ modulemd_defaults_hrefs = modulemd_defaults({ :repository_version => source_repo_for_content.version_href }).map(&:pulp_href).sort
109
+ package_env_hrefs = packageenvironments({ :repository_version => source_repo_for_content.version_href }).map(&:pulp_href).sort
109
110
  # Don't perform extra content actions if the repo is a soft copy of its library instance.
110
111
  # Taken care of by the IncrementalUpdate action.
111
112
  unless dest_repo.soft_copy_of_library?
112
113
  tasks << remove_all_content_from_repo(dest_repo_href)
113
114
  tasks << add_content_for_repo(dest_repo_href, package_env_hrefs) unless package_env_hrefs.empty?
115
+ tasks << add_content_for_repo(dest_repo_href, modulemd_defaults_hrefs) unless modulemd_defaults_hrefs.empty?
114
116
  end
115
117
  end
116
118
  source_repo_ids.each do |source_repo_id|
@@ -201,6 +203,7 @@ module Katello
201
203
 
202
204
  if content_unit_hrefs.sort!.any?
203
205
  content_unit_hrefs += packageenvironments({ :repository_version => source_repository.version_href }).map(&:pulp_href).sort
206
+ content_unit_hrefs += modulemd_defaults({ :repository_version => source_repository.version_href }).map(&:pulp_href).sort
204
207
  first_slice = remove_all
205
208
  content_unit_hrefs.each_slice(UNIT_LIMIT) do |slice|
206
209
  tasks << add_content(slice, first_slice)
@@ -228,6 +231,10 @@ module Katello
228
231
  Katello::Pulp3::Api::Core.fetch_from_list { |page_opts| api.content_package_environments_api.list(page_opts.merge(options)) }
229
232
  end
230
233
 
234
+ def modulemd_defaults(options = {})
235
+ Katello::Pulp3::Api::Core.fetch_from_list { |page_opts| api.content_modulemd_defaults_api.list(page_opts.merge(options)) }
236
+ end
237
+
231
238
  def metadatafiles(options = {})
232
239
  api.content_repo_metadata_files_api.list(options)
233
240
  end
@@ -406,7 +406,10 @@ module Katello
406
406
  proxy_url: root.http_proxy&.url,
407
407
  proxy_username: root.http_proxy&.username,
408
408
  proxy_password: root.http_proxy&.password,
409
- total_timeout: Setting[:sync_connect_timeout],
409
+ total_timeout: Setting[:sync_total_timeout],
410
+ connect_timeout: Setting[:sync_connect_timeout_v2],
411
+ sock_connect_timeout: Setting[:sync_sock_connect_timeout],
412
+ sock_read_timeout: Setting[:sync_sock_read_timeout],
410
413
  rate_limit: Setting[:download_rate_limit]
411
414
  }
412
415
  remote_options[:url] = root.url unless root.url.blank?
@@ -498,7 +501,6 @@ module Katello
498
501
  ostree_import.artifact = artifact_href
499
502
  ostree_import.repository_name = options[:ostree_repository_name]
500
503
  ostree_import.ref = options[:ostree_ref]
501
- ostree_import.parent_commit = options[:ostree_parent_commit]
502
504
  api.repositories_api.import_commits(repository_reference.repository_href, ostree_import)
503
505
  end
504
506
 
@@ -0,0 +1,19 @@
1
+ <%#
2
+ kind: job_template
3
+ name: Remove Packages by search query - Katello SSH Default
4
+ job_category: Katello
5
+ description_format: 'Remove packages %{Packages search query}'
6
+ feature: katello_packages_remove_by_search
7
+ provider_type: SSH
8
+ template_inputs:
9
+ - name: Packages search query
10
+ description: Filter criteria for packages to be removed.
11
+ input_type: user
12
+ required: true
13
+ %>
14
+ <% package_names = @host.package_names_for_job_template(
15
+ action: 'remove',
16
+ search: input('Packages search query')
17
+ ) -%>
18
+
19
+ <%= render_template('Package Action - SSH Default', :action => 'remove', :package => package_names.join(' ')) %>
@@ -0,0 +1,19 @@
1
+ <%#
2
+ kind: job_template
3
+ name: Update Packages by search query - Katello SSH Default
4
+ job_category: Katello
5
+ description_format: 'Update package(s) %{Packages search query}'
6
+ feature: katello_packages_update_by_search
7
+ provider_type: SSH
8
+ template_inputs:
9
+ - name: Packages search query
10
+ description: Filter criteria for packages to be updated.
11
+ input_type: user
12
+ required: false
13
+ %>
14
+ <% package_names = @host.package_names_for_job_template(
15
+ action: 'update',
16
+ search: input('Packages search query')
17
+ ) -%>
18
+
19
+ <%= render_template('Package Action - SSH Default', :action => 'update', :package => package_names.join(' ')) %>
@@ -36,11 +36,15 @@ node :last_published do |content_view|
36
36
  end
37
37
  end
38
38
 
39
- child :environments => :environments do
40
- attributes :id, :name, :label
41
- node :permissions do |env|
39
+ node :environments do |cv|
40
+ cv.environments.map do |env|
42
41
  {
43
- :readable => env.readable?
42
+ id: env.id,
43
+ label: env.label,
44
+ name: env.label,
45
+ activation_keys: cv&.activation_keys&.in_environment(env)&.ids,
46
+ hosts: cv&.hosts&.in_environment(env)&.ids,
47
+ permissions: {readable: env.readable?}
44
48
  }
45
49
  end
46
50
  end
@@ -2,6 +2,7 @@ object @resource
2
2
 
3
3
  attributes :status, :installed_profiles
4
4
  attributes :upgradable? => :upgradable
5
+ attributes :install_status? => :install_status
5
6
 
6
7
  glue(@object.available_module_stream) do
7
8
  attributes :name, :stream, :module_spec
@@ -39,6 +39,8 @@ class DeletePuppetAndOstreeRepos < ActiveRecord::Migration[6.0]
39
39
  FakeContentViewPuppetEnvironment.delete_all
40
40
  FakePuppetModule.delete_all
41
41
 
42
+ ::Katello::RepositoryErratum.where(:repository_id => ::Katello::Repository.where(:root_id => ::Katello::RootRepository.where(:content_type => [:ostree, :puppet]))).delete_all
43
+
42
44
  if puppet_repositories.any?
43
45
  User.as_anonymous_admin do
44
46
  ::Katello::Repository.delete(puppet_repositories)
@@ -1,4 +1,8 @@
1
1
  class CreateCdnConfiguration < ActiveRecord::Migration[6.0]
2
+ class FakeCdnConfiguration < Katello::Model
3
+ self.table_name = 'katello_cdn_configurations'
4
+ end
5
+
2
6
  def up
3
7
  create_table :katello_cdn_configurations do |t|
4
8
  t.integer :organization_id
@@ -14,17 +18,22 @@ class CreateCdnConfiguration < ActiveRecord::Migration[6.0]
14
18
  add_foreign_key :katello_cdn_configurations, :taxonomies, name: 'katello_cdn_configurations_organization_id', column: :organization_id
15
19
  add_foreign_key :katello_cdn_configurations, :katello_content_credentials, name: 'katello_cdn_configurations_ssl_ca_credential_id', column: :ssl_ca_credential_id
16
20
 
21
+ FakeCdnConfiguration.reset_column_information
22
+
17
23
  ::Organization.all.each do |org|
18
- Katello::CdnConfiguration.where(
19
- organization: org,
24
+ FakeCdnConfiguration.where(
25
+ organization_id: org.id,
20
26
  url: org.redhat_provider.repository_url || ::Katello::Resources::CDN::CdnResource.redhat_cdn_url
21
27
  ).first_or_create!
22
28
  end
23
29
 
24
30
  remove_column :katello_providers, :repository_url
31
+ ::Katello::Provider.reset_column_information
25
32
  end
26
33
 
27
34
  def down
35
+ add_column :katello_providers, :repository_url, :string
36
+ ::Katello::Provider.reset_column_information
28
37
  drop_table :katello_cdn_configurations
29
38
  end
30
39
  end
@@ -0,0 +1,23 @@
1
+ class ExpandSyncTimeoutSettings < ActiveRecord::Migration[6.0]
2
+ def up
3
+ old_timeout_setting = Setting.find_by(name: 'sync_connect_timeout', category: 'Setting::Content')
4
+ if old_timeout_setting && (old_timeout_setting&.value != old_timeout_setting&.default)
5
+ Setting.find_by(name: 'sync_total_timeout')&.update(value: old_timeout_setting&.value)
6
+ Setting.find_by(name: 'sync_sock_read_timeout')&.update(value: old_timeout_setting&.value)
7
+ end
8
+ Setting.where(name: 'sync_connect_timeout', category: 'Setting::Content').delete_all
9
+ end
10
+
11
+ def down
12
+ timeout = Setting.find_by(name: 'sync_total_timeout', category: 'Setting::Content')&.value
13
+
14
+ Setting.where(name: 'sync_total_timeout', category: 'Setting::Content').delete_all
15
+ Setting.where(name: 'sync_connect_timeout_v2', category: 'Setting::Content').delete_all
16
+ Setting.where(name: 'sync_sock_connect_timeout', category: 'Setting::Content').delete_all
17
+ Setting.where(name: 'sync_sock_read_timeout', category: 'Setting::Content').delete_all
18
+
19
+ Setting.create(Setting.set('sync_connect_timeout', N_("Timeout in seconds for downloads when syncing"),
20
+ 300, N_('Sync Connection Timeout')))
21
+ Setting.find_by(name: 'sync_connect_timeout')&.update(value: timeout)
22
+ end
23
+ end
@@ -10,13 +10,14 @@
10
10
  * @requires ContentViewVersion
11
11
  * @requires CurrentOrganization
12
12
  * @requires Notification
13
+ * @requires BastionConfig
13
14
  *
14
15
  * @description
15
16
  * Display confirmation screen and apply Errata.
16
17
  */
17
18
  angular.module('Bastion.errata').controller('ApplyErrataController',
18
- ['$scope', '$window', 'translate', 'IncrementalUpdate', 'HostBulkAction', 'ContentViewVersion', 'CurrentOrganization', 'Notification',
19
- function ($scope, $window, translate, IncrementalUpdate, HostBulkAction, ContentViewVersion, CurrentOrganization, Notification) {
19
+ ['$scope', '$window', 'translate', 'IncrementalUpdate', 'HostBulkAction', 'ContentViewVersion', 'CurrentOrganization', 'Notification', 'BastionConfig',
20
+ function ($scope, $window, translate, IncrementalUpdate, HostBulkAction, ContentViewVersion, CurrentOrganization, Notification, BastionConfig) {
20
21
  var applyErrata, incrementalUpdate;
21
22
 
22
23
  function transitionToTask(task) {
@@ -31,6 +32,8 @@ angular.module('Bastion.errata').controller('ApplyErrataController',
31
32
 
32
33
  $scope.applyingErrata = false;
33
34
 
35
+ $scope.remoteExecutionPresent = BastionConfig.remoteExecutionPresent;
36
+ $scope.remoteExecutionByDefault = BastionConfig.remoteExecutionByDefault;
34
37
  $scope.errataActionFormValues = {
35
38
  authenticityToken: $window.AUTH_TOKEN.replace(/&quot;/g, ''),
36
39
  errata: IncrementalUpdate.getErrataIds().join(','),
@@ -133,7 +136,11 @@ angular.module('Bastion.errata').controller('ApplyErrataController',
133
136
  $scope.confirmApply = function() {
134
137
  $scope.applyingErrata = true;
135
138
  if ($scope.updates.length === 0) {
136
- applyErrata();
139
+ if ($scope.remoteExecutionPresent && $scope.remoteExecutionByDefault) {
140
+ angular.element('#errataActionForm').submit();
141
+ } else {
142
+ applyErrata();
143
+ }
137
144
  } else {
138
145
  incrementalUpdate();
139
146
  }
@@ -119,6 +119,8 @@ angular.module('Bastion.repositories').controller('RepositoryDetailsInfoControll
119
119
  if (!_.isEmpty(repository.commaIncludeTags)) {
120
120
  repository["include_tags"] = repository.commaIncludeTags.split(",").map(function(tag) {
121
121
  return tag.trim();
122
+ }).filter(function(el) {
123
+ return el;
122
124
  });
123
125
  } else {
124
126
  repository["include_tags"] = [];
@@ -126,6 +128,8 @@ angular.module('Bastion.repositories').controller('RepositoryDetailsInfoControll
126
128
  if (!_.isEmpty(repository.commaExcludeTags)) {
127
129
  repository["exclude_tags"] = repository.commaExcludeTags.split(",").map(function(tag) {
128
130
  return tag.trim();
131
+ }).filter(function(el) {
132
+ return el;
129
133
  });
130
134
  } else {
131
135
  repository["exclude_tags"] = [];