katello 4.3.0.rc2.1 → 4.3.0.rc3

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/capsule_content_controller.rb +11 -3
  3. data/app/controllers/katello/api/v2/content_uploads_controller.rb +1 -1
  4. data/app/controllers/katello/api/v2/generic_content_units_controller.rb +10 -4
  5. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +8 -0
  6. data/app/controllers/katello/api/v2/repositories_controller.rb +35 -3
  7. data/app/lib/actions/katello/repository/import_upload.rb +12 -2
  8. data/app/lib/actions/pulp3/capsule_content/reclaim_space.rb +25 -0
  9. data/app/lib/actions/pulp3/orchestration/repository/import_repository_upload.rb +36 -0
  10. data/app/lib/actions/pulp3/orchestration/repository/import_upload.rb +1 -1
  11. data/app/lib/actions/pulp3/repository/commit_upload.rb +3 -1
  12. data/app/lib/actions/pulp3/repository/import_upload.rb +4 -2
  13. data/app/lib/actions/pulp3/repository/reclaim_space.rb +25 -0
  14. data/app/lib/actions/pulp3/repository/save_artifact.rb +12 -8
  15. data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -1
  16. data/app/models/katello/pulp3/repository_reference.rb +7 -0
  17. data/app/models/katello/root_repository.rb +0 -1
  18. data/app/models/setting/content.rb +2 -8
  19. data/app/services/katello/pulp3/api/core.rb +16 -2
  20. data/app/services/katello/pulp3/content.rb +4 -2
  21. data/app/services/katello/pulp3/pulp_content_unit.rb +9 -3
  22. data/app/services/katello/pulp3/repository.rb +9 -0
  23. data/app/services/katello/repository_type.rb +2 -1
  24. data/app/views/foreman/smart_proxies/_content_sync.html.erb +10 -4
  25. data/app/views/foreman/smart_proxies/_reclaim_space.html.erb +12 -0
  26. data/app/views/foreman/smart_proxies/show.html.erb +4 -2
  27. data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +2 -0
  28. data/config/routes/api/v2.rb +5 -0
  29. data/db/migrate/20211129200124_remove_dependency_solving_algorithm_setting.rb +5 -0
  30. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/bastion-katello-bootstrap.js +1 -0
  31. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/bastion_katello.js +3 -0
  32. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/capsule-content.controller.js +21 -1
  33. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/capsule-content.factory.js +2 -1
  34. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/sync-state.service.js +2 -0
  35. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/product-repositories.controller.js +14 -2
  36. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-reclaim-space-modal.controller.js +36 -0
  37. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +16 -2
  38. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details-reclaim-space-modal.html +18 -0
  39. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +13 -0
  40. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/product-repositories-reclaim-space-modal.controller.js +35 -0
  41. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository.factory.js +3 -1
  42. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/views/product-repositories-reclaim-space-modal.html +18 -0
  43. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/views/product-repositories.html +7 -0
  44. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/pulp-primary/pulp-primary.controller.js +35 -0
  45. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/pulp-primary/pulp-primary.factory.js +18 -0
  46. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/pulp-primary/pulp-primary.module.js +14 -0
  47. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/pulp-primary/pulp-primary.routes.js +16 -0
  48. data/lib/katello/permission_creator.rb +3 -3
  49. data/lib/katello/plugin.rb +4 -0
  50. data/lib/katello/repository_types/ostree.rb +3 -1
  51. data/lib/katello/tasks/upgrades/4.3/fix_url_auth.rake +25 -0
  52. data/lib/katello/version.rb +1 -1
  53. data/package.json +1 -0
  54. data/webpack/components/AddedStatusLabel.js +2 -1
  55. data/webpack/components/EditableTextInput/EditableTextInput.js +76 -17
  56. data/webpack/components/EditableTextInput/__tests__/editableTextInput.test.js +82 -0
  57. data/webpack/components/EditableTextInput/editableTextInput.scss +4 -0
  58. data/webpack/components/RoutedTabs/index.js +3 -1
  59. data/webpack/components/Table/EmptyStateMessage.js +4 -2
  60. data/webpack/components/Table/TableWrapper.js +3 -1
  61. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +24 -30
  62. data/webpack/global_index.js +10 -5
  63. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +36 -31
  64. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +8 -8
  65. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +1 -8
  66. data/webpack/scenes/ContentViews/Details/Filters/Add/CVFilterAddModal.js +2 -2
  67. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +1 -4
  68. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +6 -6
  69. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +11 -5
  70. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +6 -9
  71. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +5 -8
  72. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +40 -43
  73. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +2 -2
  74. data/webpack/scenes/ContentViews/Details/Filters/ContentType.js +4 -4
  75. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetailsHeader.js +6 -8
  76. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +6 -1
  77. data/webpack/scenes/ContentViews/Details/Filters/Rules/ContainerTag/AddEditContainerTagRuleModal.js +1 -1
  78. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +16 -22
  79. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +7 -7
  80. data/webpack/scenes/ContentViews/Details/Filters/__tests__/ContentViewPackageGroupFilter.test.js +3 -5
  81. data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetails.test.js +2 -1
  82. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErrataDateFilterContent.test.js +1 -9
  83. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErrataIDFilter.test.js +2 -4
  84. data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvModuleStreamFilter.test.js +2 -4
  85. data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromote.js +3 -3
  86. data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +4 -0
  87. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +4 -7
  88. data/webpack/scenes/ContentViews/Details/Repositories/LastSync.js +1 -1
  89. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +44 -41
  90. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionErrata.js +4 -4
  91. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +6 -2
  92. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +3 -3
  93. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +2 -2
  94. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +2 -1
  95. data/webpack/scenes/ContentViews/Publish/CVPublishForm.js +4 -4
  96. data/webpack/scenes/ContentViews/components/ContentViewIcon.js +6 -2
  97. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationForm.js +185 -0
  98. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationForm.scss +3 -0
  99. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +95 -266
  100. data/webpack/scenes/Subscriptions/Manifest/__tests__/CdnConfigurationForm.test.js +114 -0
  101. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +0 -29
  102. data/webpack/utils/helpers.js +1 -1
  103. metadata +19 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bef8f9a19283e1e922e5fd790b8cad66e87076521d03f8ee38a3b943d2c836db
4
- data.tar.gz: f43be54d4e047f721872fc83ad6bf084412aa79e09d0b0fe615a5a857e653705
3
+ metadata.gz: fa69b2700d8537140c39e127e5e94f121aeead00124eeddd6c2e7fa94e9fed32
4
+ data.tar.gz: 67ff63f7def7af9ed99bf7e73d14aa6e82cb41bd65ca73d4ec0fdd8867b2285d
5
5
  SHA512:
6
- metadata.gz: 7a9be75ea348924a76d51e354203f184a6079173c29bf9273310beee15c7a4f5f677cda11740321abad79d39df25f63d427dd218173ff818263d2ffdc5132126
7
- data.tar.gz: 61e8e11e80f1f8c7a5e3a4376777213fc0ce186da26971fdbc180bdd12e01cd3fcb6d188402eade222c157bd2321b8227c7ef1a2f66bfee79b745c280f824d07
6
+ metadata.gz: 7b8d403df79ab4e58b40d3bb675c9908f5bae448d03e410c0fb256eaa974a043c80f8bcc371ceb9e2827311cd138f8bf209f255c3a3c295f6294af6b0799b69f
7
+ data.tar.gz: 469abe1ecd5ae6ce1117c9978fa3d9a1bf3dd2ad8e775de21bc6c61ba4d394e338ccec4b12e1d6226293189dfc2965f68c4377a6a5911130f1d723da14524516
@@ -4,7 +4,7 @@ module Katello
4
4
  api_base_url "/katello/api"
5
5
  end
6
6
 
7
- before_action :find_capsule, :except => [:sync, :cancel_sync, :add_lifecycle_environment, :remove_lifecycle_environment]
7
+ before_action :find_capsule, :except => [:sync, :cancel_sync, :add_lifecycle_environment, :remove_lifecycle_environment, :reclaim_space]
8
8
  before_action :find_editable_capsule, :only => [:sync, :cancel_sync, :add_lifecycle_environment, :remove_lifecycle_environment]
9
9
  before_action :find_environment, :only => [:add_lifecycle_environment, :remove_lifecycle_environment]
10
10
  before_action :find_optional_organization, :only => [:sync_status]
@@ -86,6 +86,14 @@ module Katello
86
86
  end
87
87
  end
88
88
 
89
+ api :POST, '/capsules/:id/reclaim_space', N_('Reclaim space from all On Demand repositories on a smart proxy')
90
+ param :id, :number, :required => true, :desc => N_('Id of the smart proxy')
91
+ def reclaim_space
92
+ find_capsule(true)
93
+ task = async_task(::Actions::Pulp3::CapsuleContent::ReclaimSpace, @capsule)
94
+ respond_for_async :resource => task
95
+ end
96
+
89
97
  protected
90
98
 
91
99
  def respond_for_lifecycle_environments_index(environments)
@@ -104,9 +112,9 @@ module Katello
104
112
  end
105
113
  end
106
114
 
107
- def find_capsule
115
+ def find_capsule(primary_okay = false)
108
116
  @capsule = SmartProxy.unscoped.authorized(:view_capsule_content).find(params[:id])
109
- unless @capsule&.pulp_mirror?
117
+ unless @capsule&.pulp_mirror? || primary_okay
110
118
  fail _("This request may only be performed on a Smart proxy that has the Pulpcore feature with mirror=true.")
111
119
  end
112
120
  end
@@ -10,7 +10,7 @@ module Katello
10
10
  param :repository_id, :number, :required => true, :desc => N_("repository id")
11
11
  param :size, :number, :required => true, :desc => N_("Size of file to upload")
12
12
  param :checksum, String, :required => false, :desc => N_("Checksum of file to upload")
13
- param :content_type, RepositoryTypeManager.uploadable_content_types(false).map(&:label), :required => false, :desc => N_("content type ('deb', 'docker_manifest', 'file', 'ostree', 'rpm', 'srpm')")
13
+ param :content_type, RepositoryTypeManager.uploadable_content_types(false).map(&:label), :required => false, :desc => N_("content type ('deb', 'docker_manifest', 'file', 'ostree_ref', 'rpm', 'srpm')")
14
14
  def create
15
15
  fail Katello::Errors::InvalidRepositoryContent, _("Cannot upload Ansible collections.") if @repository.ansible_collection?
16
16
  content_type = params[:content_type] || ::Katello::RepositoryTypeManager.find(@repository.content_type)&.default_managed_content_type&.label
@@ -1,10 +1,15 @@
1
1
  module Katello
2
2
  class Api::V2::GenericContentUnitsController < Api::V2::ApiController
3
+ resource_description do
4
+ name 'Content Units'
5
+ param :content_type, String, desc: N_("Possible values: #{Katello::RepositoryTypeManager.generic_content_types.join(", ")}"), required: true
6
+ end
7
+ apipie_concern_subst(:a_resource => N_("a content unit"), :resource_id => "content_units")
8
+
3
9
  Katello::RepositoryTypeManager.generic_content_types(false).each do |type|
4
- apipie_concern_subst(:a_resource => N_(type), :resource_id => type.pluralize)
5
- resource_description do
6
- name type.pluralize.titleize
7
- end
10
+ api :GET, "/#{type.pluralize}", N_("List %s" % type.pluralize)
11
+ api :GET, "/#{type.pluralize}/:id", N_("Show %s" % type.gsub(/_/, ' '))
12
+ api :GET, "/repositories/:repository_id/#{type.pluralize}/:id", N_("Show %s" % type.gsub(/_/, ' '))
8
13
  end
9
14
 
10
15
  include Katello::Concerns::Api::V2::RepositoryContentController
@@ -14,6 +19,7 @@ module Katello
14
19
  end
15
20
 
16
21
  def resource_class
22
+ fail "Required param content_type is missing" unless params[:content_type]
17
23
  ::Katello::GenericContentUnit.where(content_type: params[:content_type].singularize)
18
24
  end
19
25
 
@@ -50,6 +50,14 @@ module Katello
50
50
  end
51
51
  end
52
52
 
53
+ api :POST, "/repositories/bulk/reclaim_space", N_("Reclaim space from On Demand repositories")
54
+ param :ids, Array, :desc => N_("List of repository ids"), :required => true
55
+ def reclaim_space_from_repositories
56
+ task = async_task(::Actions::Pulp3::Repository::ReclaimSpace, @repositories)
57
+
58
+ respond_for_async :resource => task
59
+ end
60
+
53
61
  private
54
62
 
55
63
  def find_repositories
@@ -23,7 +23,7 @@ module Katello
23
23
  before_action :find_unauthorized_katello_resource, :only => [:gpg_key_content]
24
24
  before_action :find_authorized_katello_resource, :only => [:show, :update, :destroy, :sync,
25
25
  :remove_content, :upload_content, :republish,
26
- :import_uploads, :verify_checksum]
26
+ :import_uploads, :verify_checksum, :reclaim_space]
27
27
  before_action :find_content, :only => :remove_content
28
28
  before_action :find_organization_from_repo, :only => [:update]
29
29
  before_action :error_on_rh_product, :only => [:create]
@@ -234,6 +234,10 @@ module Katello
234
234
  fail HttpErrors::UnprocessableEntity, msg
235
235
  end
236
236
 
237
+ if !repo_params[:url].nil? && URI(repo_params[:url]).userinfo
238
+ fail "Do not include the username/password in the URL. Use the username/password settings instead."
239
+ end
240
+
237
241
  gpg_key = get_content_credential(repo_params, CONTENT_CREDENTIAL_GPG_KEY_TYPE)
238
242
  ssl_ca_cert = get_content_credential(repo_params, CONTENT_CREDENTIAL_SSL_CA_CERT_TYPE)
239
243
  ssl_client_cert = get_content_credential(repo_params, CONTENT_CREDENTIAL_SSL_CLIENT_CERT_TYPE)
@@ -317,6 +321,15 @@ module Katello
317
321
  raise HttpErrors::BadRequest, e.message
318
322
  end
319
323
 
324
+ api :POST, "/repositories/:id/reclaim_space", N_("Reclaim space from an On Demand repository")
325
+ param :id, :number, :required => true, :desc => N_("repository ID")
326
+ def reclaim_space
327
+ task = async_task(::Actions::Pulp3::Repository::ReclaimSpace, @repository)
328
+ respond_for_async :resource => task
329
+ rescue Errors::InvalidActionOptionError => e
330
+ raise HttpErrors::BadRequest, e.message
331
+ end
332
+
320
333
  api :PUT, "/repositories/:id", N_("Update a repository")
321
334
  param :id, :number, :required => true, :desc => N_("repository ID")
322
335
  param :name, String, :required => false
@@ -324,6 +337,9 @@ module Katello
324
337
  param_group :repo
325
338
  def update
326
339
  repo_params = repository_params
340
+ if !repo_params[:url].nil? && URI(repo_params[:url]).userinfo
341
+ fail "Do not include the username/password in the URL. Use the username/password settings instead."
342
+ end
327
343
 
328
344
  if @repository.generic?
329
345
  generic_remote_options = generic_remote_options_hash(repo_params)
@@ -421,10 +437,16 @@ module Katello
421
437
  end
422
438
 
423
439
  begin
440
+ upload_args = {
441
+ content_type: params[:content_type],
442
+ generate_metadata: generate_metadata,
443
+ sync_capsule: sync_capsule
444
+ }
445
+ upload_args.merge!(generic_content_type_import_upload_args)
446
+
424
447
  respond_for_async(resource: send(
425
448
  async ? :async_task : :sync_task,
426
- ::Actions::Katello::Repository::ImportUpload, @repository, uploads,
427
- generate_metadata: generate_metadata, sync_capsule: sync_capsule, content_type: params[:content_type]))
449
+ ::Actions::Katello::Repository::ImportUpload, @repository, uploads, upload_args))
428
450
  rescue => e
429
451
  raise HttpErrors::BadRequest, e.message
430
452
  end
@@ -617,6 +639,16 @@ module Katello
617
639
  generic_remote_options
618
640
  end
619
641
 
642
+ def generic_content_type_import_upload_args
643
+ args = {}
644
+ @repository.repository_type&.import_attributes&.collect do |import_attribute|
645
+ if params[import_attribute.api_param]
646
+ args[import_attribute.api_param] = params[import_attribute.api_param]
647
+ end
648
+ end
649
+ args
650
+ end
651
+
620
652
  def check_import_parameters
621
653
  @repository.repository_type&.import_attributes&.each do |import_attribute|
622
654
  if import_attribute.required && params[import_attribute.api_param].blank?
@@ -4,6 +4,7 @@ module Actions
4
4
  module Repository
5
5
  class ImportUpload < Actions::EntryAction
6
6
  include Actions::Katello::PulpSelector
7
+ # rubocop:disable Metrics/MethodLength
7
8
  def plan(repository, uploads, options = {})
8
9
  action_subject(repository)
9
10
  repository.clear_smart_proxy_sync_histories
@@ -21,6 +22,7 @@ module Actions
21
22
  else
22
23
  unit_type_id = SmartProxy.pulp_primary.content_service(options[:content_type])::CONTENT_TYPE
23
24
  end
25
+ content_type = ::Katello::RepositoryTypeManager.find_content_type(options[:content_type])
24
26
 
25
27
  sequence do
26
28
  upload_results = concurrence do
@@ -34,8 +36,15 @@ module Actions
34
36
  unit_metadata: unit_metadata
35
37
  }
36
38
 
37
- import_upload = plan_action(Actions::Pulp3::Orchestration::Repository::ImportUpload,
38
- repository, SmartProxy.pulp_primary, import_upload_args)
39
+ import_upload_args.merge!(options)
40
+
41
+ if content_type.repository_import_on_upload
42
+ action_class = ::Actions::Pulp3::Orchestration::Repository::ImportRepositoryUpload
43
+ else
44
+ action_class = ::Actions::Pulp3::Orchestration::Repository::ImportUpload
45
+ end
46
+
47
+ import_upload = plan_action(action_class, repository, SmartProxy.pulp_primary, import_upload_args)
39
48
  plan_action(FinishUpload, repository, :import_upload_task => import_upload.output,
40
49
  generate_metadata: false, content_type: options[:content_type])
41
50
  import_upload.output
@@ -46,6 +55,7 @@ module Actions
46
55
  plan_self(repository_id: repository.id, sync_capsule: sync_capsule, upload_results: upload_results)
47
56
  end
48
57
  end
58
+ # rubocop:enable Metrics/MethodLength
49
59
 
50
60
  def run
51
61
  repository = ::Katello::Repository.find(input[:repository_id])
@@ -0,0 +1,25 @@
1
+ module Actions
2
+ module Pulp3
3
+ module CapsuleContent
4
+ class ReclaimSpace < Pulp3::AbstractAsyncTask
5
+ def plan(smart_proxy)
6
+ if smart_proxy.pulp_primary?
7
+ repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs(::Katello::Repository.unscoped.on_demand, ::Organization.all)
8
+ repository_hrefs.flatten!
9
+ else
10
+ if smart_proxy.download_policy != ::Katello::RootRepository::DOWNLOAD_ON_DEMAND
11
+ fail _('Only On Demand smart proxies may have space reclaimed.')
12
+ end
13
+ repository_hrefs = ::Katello::Pulp3::Api::Core.new(smart_proxy).core_repositories_list_all(fields: 'pulp_href').map(&:pulp_href)
14
+ end
15
+ plan_self(repository_hrefs: repository_hrefs, smart_proxy_id: smart_proxy.id)
16
+ end
17
+
18
+ def invoke_external_task
19
+ output[:pulp_tasks] = ::Katello::Pulp3::Api::Core.new(SmartProxy.find(input[:smart_proxy_id])).
20
+ repositories_reclaim_space_api.reclaim(repo_hrefs: input[:repository_hrefs])
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ module Actions
2
+ module Pulp3
3
+ module Orchestration
4
+ module Repository
5
+ #Used for a different type of uploading where you are importing an entire repository, not a single content unit
6
+ # This workflow involves never actually creating a content unit directly, but instead importing the artifact directly into the repository
7
+ class ImportRepositoryUpload < Pulp3::Abstract
8
+ def plan(repository, smart_proxy, args)
9
+ file = {:filename => args.dig(:unit_key, :name), :sha256 => args.dig(:unit_key, :checksum) }
10
+ sequence do
11
+ upload_href = "/pulp/api/v3/uploads/#{args.dig(:upload_id)}/" if args.dig(:upload_id) && args.dig(:upload_id) != 'duplicate'
12
+ commit_output = plan_action(Pulp3::Repository::CommitUpload,
13
+ repository,
14
+ smart_proxy,
15
+ upload_href,
16
+ args.dig(:unit_key, :checksum)).output
17
+
18
+ artifact_output = plan_action(Pulp3::Repository::SaveArtifact,
19
+ file,
20
+ repository,
21
+ smart_proxy,
22
+ commit_output[:pulp_tasks],
23
+ args.dig(:unit_type_id), args).output
24
+ plan_self(:artifact_output => artifact_output)
25
+ plan_action(Pulp3::Repository::SaveVersion, repository, tasks: artifact_output[:pulp_tasks])
26
+ end
27
+ end
28
+
29
+ def run
30
+ output[:content_unit_href] = input[:artifact_output][:content_unit_href] || input[:artifact_output][:pulp_tasks].last[:created_resources].first
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -33,7 +33,7 @@ module Actions
33
33
  repository,
34
34
  smart_proxy,
35
35
  commit_output[:pulp_tasks],
36
- args.dig(:unit_type_id)).output
36
+ args.dig(:unit_type_id), args).output
37
37
  end
38
38
 
39
39
  plan_self(:commit_output => commit_output[:pulp_tasks], :artifact_output => artifact_output)
@@ -1,6 +1,7 @@
1
1
  module Actions
2
2
  module Pulp3
3
3
  module Repository
4
+ #Creates an artifacts
4
5
  class CommitUpload < Pulp3::AbstractAsyncTask
5
6
  def plan(repository, smart_proxy, upload_href, sha256)
6
7
  plan_self(:repository_id => repository.id, :smart_proxy_id => smart_proxy.id, :upload_href => upload_href, :sha256 => sha256)
@@ -10,10 +11,11 @@ module Actions
10
11
  repo = ::Katello::Repository.find(input[:repository_id])
11
12
  repo_backend_service = repo.backend_service(smart_proxy)
12
13
  uploads_api = repo_backend_service.core_api.uploads_api
14
+
13
15
  duplicate_sha_artifact_list = ::Katello::Pulp3::Api::Core.new(smart_proxy).artifacts_api.list("sha256": input[:sha256])
14
16
  duplicate_sha_artifact_href = duplicate_sha_artifact_list&.results&.first&.pulp_href
15
17
  if duplicate_sha_artifact_href
16
- uploads_api.delete(input[:upload_href])
18
+ uploads_api.delete(input[:upload_href]) if input[:upload_href]
17
19
  output[:artifact_href] = duplicate_sha_artifact_href
18
20
  output[:pulp_tasks] = nil
19
21
  else
@@ -4,10 +4,11 @@ module Actions
4
4
  module Pulp3
5
5
  module Repository
6
6
  class ImportUpload < Pulp3::AbstractAsyncTask
7
- def plan(save_artifact_output, repository, smart_proxy)
7
+ def plan(save_artifact_output, repository, smart_proxy, options = {})
8
8
  plan_self(:save_artifact_output => save_artifact_output,
9
9
  :repository_id => repository.id,
10
- :smart_proxy_id => smart_proxy.id)
10
+ :smart_proxy_id => smart_proxy.id,
11
+ :options => options)
11
12
  end
12
13
 
13
14
  def invoke_external_task
@@ -19,6 +20,7 @@ module Actions
19
20
 
20
21
  repo = ::Katello::Repository.find(input[:repository_id])
21
22
  repo_backend_service = repo.backend_service(smart_proxy)
23
+
22
24
  output[:content_unit_href] = content_unit_href
23
25
  output[:pulp_tasks] = [repo_backend_service.add_content(content_unit_href)]
24
26
  end
@@ -0,0 +1,25 @@
1
+ module Actions
2
+ module Pulp3
3
+ module Repository
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)
15
+ plan_self(repository_hrefs: repository_hrefs, smart_proxy_id: smart_proxy.id)
16
+ end
17
+
18
+ def invoke_external_task
19
+ output[:pulp_tasks] = ::Katello::Pulp3::Api::Core.new(SmartProxy.find(input[:smart_proxy_id])).
20
+ repositories_reclaim_space_api.reclaim(repo_hrefs: input[:repository_hrefs])
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -2,6 +2,7 @@ module Actions
2
2
  module Pulp3
3
3
  module Repository
4
4
  class SaveArtifact < Pulp3::AbstractAsyncTask
5
+ #This task creates a content unit and may or may not create a new repository version in the process
5
6
  def plan(file, repository, smart_proxy, tasks, unit_type_id, options = {})
6
7
  options[:file_name] = file[:filename]
7
8
  options[:sha256] = file[:sha256] || Digest::SHA256.hexdigest(File.read(file[:path]))
@@ -15,17 +16,20 @@ module Actions
15
16
  content_type = input[:unit_type_id]
16
17
  content_backend_service = SmartProxy.pulp_primary.content_service(content_type)
17
18
 
18
- existing_content = ::Katello::Pulp3::PulpContentUnit.find_duplicate_unit(repository, input['unit_type_id'], {filename: input[:options][:file_name]}, input[:options][:sha256])
19
+ existing_content = ::Katello::Pulp3::PulpContentUnit.find_duplicate_unit(repository, input[:unit_type_id], {filename: input[:options][:file_name]}, input[:options][:sha256])
19
20
  existing_content_href = existing_content&.results&.first&.pulp_href
20
21
 
21
- if existing_content_href
22
- output[:content_unit_href] = existing_content_href
23
- []
22
+ if ::Katello::RepositoryTypeManager.find_content_type(input[:unit_type_id]).repository_import_on_upload
23
+ output[:pulp_tasks] = [repository.backend_service(smart_proxy).repository_import_content(artifact_href, input[:options])]
24
24
  else
25
- output[:pulp_tasks] = [content_backend_service.content_api_create(relative_path: input[:options][:file_name],
26
- artifact: artifact_href,
27
- repository_id: input[:repository_id],
28
- content_type: content_type)]
25
+ if existing_content_href
26
+ output[:content_unit_href] = existing_content_href
27
+ []
28
+ else
29
+ output[:pulp_tasks] = [content_backend_service.content_api_create(relative_path: input[:options][:file_name],
30
+ artifact: artifact_href,
31
+ content_type: content_type)]
32
+ end
29
33
  end
30
34
  end
31
35
 
@@ -186,7 +186,7 @@ module Katello
186
186
  end
187
187
 
188
188
  def pulp3_ssl_configuration(config)
189
- legacy_pulp_cert = !self.setting(PULP3_FEATURE, 'client_authentication')&.include?('client_certificates')
189
+ legacy_pulp_cert = !self.setting(PULP3_FEATURE, 'client_authentication')&.include?('client_certificate')
190
190
 
191
191
  if Faraday.default_adapter == :excon
192
192
  config.ssl_client_cert = ::Cert::Certs.ssl_client_cert_filename(use_admin_as_cn_cert: legacy_pulp_cert)
@@ -3,6 +3,13 @@ module Katello
3
3
  class RepositoryReference < Katello::Model
4
4
  belongs_to :root_repository, :class_name => 'Katello::RootRepository'
5
5
  belongs_to :content_view, :class_name => 'Katello::ContentView'
6
+
7
+ def self.default_cv_repository_hrefs(repositories, organizations)
8
+ organizations = [organizations] if organizations.is_a?(::Organization)
9
+ where(content_view_id: organizations.map(&:default_content_view).compact.pluck(:id)).
10
+ where(root_repository_id: repositories.pluck(:root_id)).
11
+ select(:repository_href).pluck(:repository_href)
12
+ end
6
13
  end
7
14
  end
8
15
  end
@@ -74,7 +74,6 @@ module Katello
74
74
  validate :ensure_valid_authentication_token, :if => :yum?
75
75
  validate :ensure_valid_deb_constraints, :if => :deb?
76
76
  validate :ensure_no_checksum_on_demand
77
- validates :url, presence: true, if: :ostree?
78
77
  validates :checksum_type, :inclusion => {:in => CHECKSUM_TYPES}, :allow_blank => true
79
78
  validates :product_id, :presence => true
80
79
  validates :content_type, :inclusion => {
@@ -13,7 +13,6 @@ class Setting::Content < Setting
13
13
  download_policies = proc { hashify_parameters(::Katello::RootRepository::DOWNLOAD_POLICIES) }
14
14
 
15
15
  proxy_download_policies = proc { hashify_parameters(::SmartProxy::DOWNLOAD_POLICIES) }
16
- dependency_solving_options = proc { hashify_parameters(['conservative', 'greedy']) }
17
16
  cdn_ssl_versions = proc { hashify_parameters(Katello::Resources::CDN::SUPPORTED_SSL_VERSIONS) }
18
17
  http_proxy_select = [{
19
18
  name: _("HTTP Proxies"),
@@ -125,12 +124,6 @@ class Setting::Content < Setting
125
124
  self.set('content_view_solve_dependencies',
126
125
  N_('The default dependency solving value for new Content Views.'),
127
126
  false, N_('Content View Dependency Solving Default')),
128
- self.set('dependency_solving_algorithm',
129
- N_("How the logic of solving dependencies in a Content View is managed. Conservative will only add " \
130
- "packages to solve the dependencies if the package needed doesn't exist. Greedy will pull in the " \
131
- "latest package to solve a dependency even if it already does exist in the repository."),
132
- 'conservative', N_('Content View Dependency Solving Algorithm'), nil,
133
- :collection => dependency_solving_options),
134
127
  self.set('host_dmi_uuid_duplicates',
135
128
  N_("If hosts fail to register because of duplicate DMI UUIDs " \
136
129
  "add their comma-separated values here. Subsequent registrations will generate a unique DMI UUID for the affected hosts."),
@@ -154,7 +147,8 @@ class Setting::Content < Setting
154
147
  self.set('bulk_load_size', N_('The number of items fetched from a single paged Pulp API call.'), 2000,
155
148
  N_('Pulp bulk load size')),
156
149
  self.set('upload_profiles_without_dynflow', N_('Allow Katello to update host installed packages, enabled repos, and module inventory directly instead of wrapped in Dynflow tasks (try turning off if Puma processes are using too much memory)'), true,
157
- N_('Upload profiles without Dynflow'))
150
+ N_('Upload profiles without Dynflow')),
151
+ self.set('orphan_protection_time', N_('Time in minutes to consider orphan content as orphaned.'), 1440, N_('Orphaned Content Protection Time'))
158
152
  ]
159
153
  end
160
154
 
@@ -55,6 +55,10 @@ module Katello
55
55
  repository_type.distributions_api_class.new(api_client)
56
56
  end
57
57
 
58
+ def core_repositories_api
59
+ PulpcoreClient::RepositoriesApi.new(core_api_client)
60
+ end
61
+
58
62
  def repositories_api
59
63
  repository_type.repositories_api_class.new(api_client)
60
64
  end
@@ -81,6 +85,10 @@ module Katello
81
85
  end
82
86
  end
83
87
 
88
+ def repositories_reclaim_space_api
89
+ PulpcoreClient::RepositoriesReclaimSpaceApi.new(core_api_client)
90
+ end
91
+
84
92
  def exporter_api
85
93
  PulpcoreClient::ExportersPulpApi.new(core_api_client)
86
94
  end
@@ -102,7 +110,7 @@ module Katello
102
110
  end
103
111
 
104
112
  def orphans_api
105
- PulpcoreClient::OrphansApi.new(core_api_client)
113
+ PulpcoreClient::OrphansCleanupApi.new(core_api_client)
106
114
  end
107
115
 
108
116
  def artifacts_api
@@ -152,7 +160,7 @@ module Katello
152
160
  end
153
161
 
154
162
  def delete_orphans
155
- [orphans_api.delete]
163
+ [orphans_api.cleanup(PulpcoreClient::OrphansCleanup.new(orphan_protection_time: Setting[:orphan_protection_time]))]
156
164
  end
157
165
 
158
166
  def delete_remote(remote_href)
@@ -192,6 +200,12 @@ module Katello
192
200
  ignore_404_exception { distributions_api.delete(href) }
193
201
  end
194
202
 
203
+ def core_repositories_list_all(options = {})
204
+ self.class.fetch_from_list do |page_opts|
205
+ core_repositories_api.list(page_opts.merge(options))
206
+ end
207
+ end
208
+
195
209
  def list_all(options = {})
196
210
  self.class.fetch_from_list do |page_opts|
197
211
  repositories_api.list(page_opts.merge(options))
@@ -6,10 +6,12 @@ module Katello
6
6
  class << self
7
7
  def create_upload(size = 0, checksum = nil, content_type = nil, repository = nil)
8
8
  content_unit_href = nil
9
- if checksum
9
+ content_type = ::Katello::RepositoryTypeManager.find_content_type(content_type)
10
+
11
+ if checksum && !content_type.repository_import_on_upload
10
12
  content_backend_service = SmartProxy.pulp_primary.content_service(content_type)
11
13
  if repository&.generic?
12
- content_list = content_backend_service.content_api(repository.repository_type, content_type).list("sha256": checksum)
14
+ content_list = content_backend_service.content_api(repository.repository_type, content_type).list('sha256': checksum)
13
15
  else
14
16
  content_list = content_backend_service.content_api.list("sha256": checksum)
15
17
  end
@@ -116,24 +116,30 @@ module Katello
116
116
  content_unit_list page_opts
117
117
  end
118
118
 
119
+ # rubocop:disable Lint/UselessAssignment
119
120
  def self.find_duplicate_unit(repository, unit_type_id, file, checksum)
121
+ filter_label = 'sha256'
122
+ if unit_type_id == 'ostree_ref'
123
+ filter_label = 'checksum'
124
+ end
120
125
  content_backend_service = SmartProxy.pulp_primary.content_service(unit_type_id)
121
126
  duplicates_allowed = ::Katello::RepositoryTypeManager.find_content_type(unit_type_id).try(:duplicates_allowed)
122
127
  if repository.generic? && duplicates_allowed
123
128
  filename_key = ::Katello::RepositoryTypeManager.find_content_type(unit_type_id).filename_key
124
129
  duplicate_sha_path_content_list = content_backend_service.content_api(repository.repository_type, unit_type_id).list(
125
- "sha256": checksum,
130
+ filter_label: checksum,
126
131
  filename_key => file[:filename])
127
132
  elsif repository.generic?
128
133
  duplicate_sha_path_content_list = content_backend_service.content_api(repository.repository_type, unit_type_id).list(
129
- "sha256": checksum)
134
+ filter_label: checksum)
130
135
  else
131
136
  duplicate_sha_path_content_list = content_backend_service.content_api.list(
132
- "sha256": checksum,
137
+ filter_label: checksum,
133
138
  "relative_path": file[:filename])
134
139
  end
135
140
  duplicate_sha_path_content_list
136
141
  end
142
+ # rubocop:enable Lint/UselessAssignment
137
143
  end
138
144
  end
139
145
  end
@@ -478,6 +478,15 @@ module Katello
478
478
  end
479
479
  end
480
480
 
481
+ def repository_import_content(artifact_href, options = {})
482
+ ostree_import = PulpOstreeClient::OstreeRepoImport.new
483
+ ostree_import.artifact = artifact_href
484
+ ostree_import.repository_name = options[:ostree_repository_name]
485
+ ostree_import.ref = options[:ostree_ref]
486
+ ostree_import.parent_commit = options[:ostree_parent_commit]
487
+ api.repositories_api.import_commits(repository_reference.repository_href, ostree_import)
488
+ end
489
+
481
490
  def add_content(content_unit_href, remove_all_units = false)
482
491
  content_unit_href = [content_unit_href] unless content_unit_href.is_a?(Array)
483
492
  if remove_all_units
@@ -145,7 +145,7 @@ module Katello
145
145
 
146
146
  class ContentType
147
147
  attr_accessor :model_class, :priority, :pulp2_service_class, :pulp3_service_class, :index, :uploadable, :removable,
148
- :primary_content, :index_on_pulp3, :generic_browser, :content_type
148
+ :primary_content, :index_on_pulp3, :generic_browser, :content_type, :repository_import_on_upload
149
149
 
150
150
  def initialize(options)
151
151
  self.model_class = options[:model_class]
@@ -159,6 +159,7 @@ module Katello
159
159
  self.removable = options[:removable] || false
160
160
  self.primary_content = options[:primary_content] || false
161
161
  self.generic_browser = options[:generic_browser]
162
+ self.repository_import_on_upload = options[:repository_import_on_upload]
162
163
  end
163
164
 
164
165
  def label