katello 4.2.0.1 → 4.2.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/content_uploads_controller.rb +6 -3
  3. data/app/controllers/katello/api/v2/generic_content_units_controller.rb +26 -0
  4. data/app/controllers/katello/api/v2/repositories_controller.rb +16 -4
  5. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +6 -47
  6. data/app/lib/actions/katello/content_view/promote_to_environment.rb +2 -7
  7. data/app/lib/actions/katello/content_view/publish.rb +4 -2
  8. data/app/lib/actions/katello/repository/filtered_index_content.rb +5 -0
  9. data/app/lib/actions/katello/repository/import_upload.rb +5 -1
  10. data/app/lib/actions/katello/repository/index_content.rb +2 -1
  11. data/app/lib/actions/katello/repository/remove_content.rb +5 -1
  12. data/app/lib/actions/katello/repository/upload_files.rb +6 -1
  13. data/app/lib/actions/pulp3/orchestration/repository/import_upload.rb +2 -4
  14. data/app/lib/actions/pulp3/orchestration/repository/upload_content.rb +2 -7
  15. data/app/lib/actions/pulp3/repository/save_artifact.rb +4 -1
  16. data/app/lib/katello/concerns/base_template_scope_extensions.rb +1 -1
  17. data/app/lib/katello/util/errata.rb +3 -1
  18. data/app/models/katello/concerns/host_managed_extensions.rb +19 -0
  19. data/app/models/katello/concerns/pulp_database_unit.rb +32 -11
  20. data/app/models/katello/concerns/smart_proxy_extensions.rb +39 -4
  21. data/app/models/katello/content_view.rb +13 -0
  22. data/app/models/katello/content_view_repository.rb +1 -1
  23. data/app/models/katello/docker_tag.rb +2 -2
  24. data/app/models/katello/erratum.rb +13 -0
  25. data/app/models/katello/generic_content_unit.rb +4 -1
  26. data/app/models/katello/repository.rb +15 -7
  27. data/app/models/katello/root_repository.rb +9 -2
  28. data/app/models/katello/yum_metadata_file.rb +2 -2
  29. data/app/services/katello/applicability/applicable_content_helper.rb +4 -3
  30. data/app/services/katello/pulp/content.rb +1 -1
  31. data/app/services/katello/pulp3/content.rb +6 -2
  32. data/app/services/katello/pulp3/erratum.rb +12 -4
  33. data/app/services/katello/pulp3/generic_content_unit.rb +1 -1
  34. data/app/services/katello/pulp3/pulp_content_unit.rb +26 -1
  35. data/app/services/katello/pulp3/repository/apt.rb +16 -0
  36. data/app/services/katello/pulp3/repository/yum.rb +18 -19
  37. data/app/services/katello/pulp3/repository_mirror.rb +9 -1
  38. data/app/services/katello/repository_type.rb +8 -6
  39. data/app/services/katello/repository_type_manager.rb +25 -22
  40. data/app/views/katello/api/v2/generic_content_units/base.json.rabl +7 -0
  41. data/app/views/katello/api/v2/generic_content_units/compare.json.rabl +10 -0
  42. data/app/views/katello/api/v2/generic_content_units/index.json.rabl +7 -0
  43. data/app/views/katello/api/v2/generic_content_units/show.json.rabl +3 -0
  44. data/app/views/katello/api/v2/repositories/show.json.rabl +2 -1
  45. data/config/initializers/filter_parameters.rb +1 -0
  46. data/config/routes/api/v2.rb +12 -1
  47. data/db/migrate/20210512192745_fix_red_hat_root_repository_arch.rb +1 -1
  48. data/db/migrate/20210831161843_add_upstream_auth_token_to_root_repository.rb +5 -0
  49. data/db/seeds.d/111-upgrade_tasks.rb +3 -1
  50. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +3 -1
  51. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +6 -0
  52. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +11 -0
  53. data/lib/katello/permission_creator.rb +2 -0
  54. data/lib/katello/repository_types/deb.rb +1 -1
  55. data/lib/katello/repository_types/docker.rb +1 -1
  56. data/lib/katello/repository_types/file.rb +1 -1
  57. data/lib/katello/repository_types/ostree.rb +1 -1
  58. data/lib/katello/repository_types/python.rb +4 -1
  59. data/lib/katello/repository_types/yum.rb +1 -1
  60. data/lib/katello/tasks/reset.rake +6 -5
  61. data/lib/katello/tasks/test.rake +1 -2
  62. data/lib/katello/tasks/upgrades/4.1/{update_content_import_export_perms.rake → reupdate_content_import_export_perms.rake} +24 -1
  63. data/lib/katello/tasks/upgrades/4.2/remove_checksum_values.rake +17 -0
  64. data/lib/katello/version.rb +1 -1
  65. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/ActivationKeys.test.js.snap +1 -0
  66. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/Force.test.js.snap +1 -0
  67. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/IgnoreSubmanErrors.test.js.snap +1 -0
  68. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +2 -4
  69. metadata +15 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 584f61c17131168930ed4c8e69fc57b3365790d54e0a213d863b8f51fc08886f
4
- data.tar.gz: 314009b6f1ff799a12f311733c84e63418d35fbc8df5d88bdb3655ae256829eb
3
+ metadata.gz: 86442b066cfb028bec4edcd99bc079e29675037545b33af48336a8e176ffc43d
4
+ data.tar.gz: 9cbab83302f8791feafc1912bc7c81ea31d4d08169d1f554cfc1361f995941e2
5
5
  SHA512:
6
- metadata.gz: 4b1a04cb53666ed27b91417aafa1a560ef60c6ba5a2867e920241f09c1a7d0848ef6066317746b24c88492426790f13ff3abfffadc9bd3da29719ad0190009ab
7
- data.tar.gz: 5e633218d1dc29742b64649697b358637df14e57c249ef21ca2a7d3341b4fe4826ed4a7c505d3105ef810dec2368d40f484a3e07d869c1bba3068fb6e1ca2f08
6
+ metadata.gz: e4c1529274b2d229ac784ccdad9f3c9b90b67f92df7eca9d8228e79e675bbcfb9766c33b4af3bbad3b87524c4cee1cdb13e607cd9a39f5d3aa5d865d032bee02
7
+ data.tar.gz: 62a2813d45436694cce0f721d26d0ec2782f112e9154cfa051ed650b4aa2d86dd4624708a835f03adca3b65280ccbabccfa3d83d506224e8616eeedb6d8aec4c
@@ -15,9 +15,12 @@ module Katello
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
17
17
  RepositoryTypeManager.check_content_matches_repo_type!(@repository, content_type)
18
-
19
- unit_type_id = SmartProxy.pulp_primary.content_service(content_type).content_type
20
- render :json => @repository.backend_content_service(::SmartProxy.pulp_primary).create_upload(params[:size], params[:checksum], unit_type_id)
18
+ if ::Katello::RepositoryTypeManager.generic_content_type?(content_type)
19
+ unit_type_id = content_type
20
+ else
21
+ unit_type_id = SmartProxy.pulp_primary.content_service(content_type).content_type
22
+ end
23
+ render :json => @repository.backend_content_service(::SmartProxy.pulp_primary).create_upload(params[:size], params[:checksum], unit_type_id, @repository)
21
24
  end
22
25
 
23
26
  api :PUT, "/repositories/:repository_id/content_uploads/:id", N_("Upload a chunk of the file's content")
@@ -0,0 +1,26 @@
1
+ module Katello
2
+ class Api::V2::GenericContentUnitsController < Api::V2::ApiController
3
+ Katello::RepositoryTypeManager.generic_content_types(enabled_only: 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
8
+ end
9
+
10
+ include Katello::Concerns::Api::V2::RepositoryContentController
11
+
12
+ def default_sort
13
+ %w(name asc)
14
+ end
15
+
16
+ def resource_class
17
+ ::Katello::GenericContentUnit.where(content_type: params[:content_type].singularize)
18
+ end
19
+
20
+ private
21
+
22
+ def repo_association
23
+ :repository_id
24
+ end
25
+ end
26
+ end
@@ -56,6 +56,7 @@ module Katello
56
56
  param :verify_ssl_on_sync, :bool, :desc => N_("if true, Katello will verify the upstream url's SSL certifcates are signed by a trusted CA")
57
57
  param :upstream_username, String, :desc => N_("Username of the upstream repository user used for authentication")
58
58
  param :upstream_password, String, :desc => N_("Password of the upstream repository user used for authentication")
59
+ param :upstream_authentication_token, String, :desc => N_("Password of the upstream authentication token.")
59
60
  param :ostree_upstream_sync_policy, ::Katello::RootRepository::OSTREE_UPSTREAM_SYNC_POLICIES, :desc => N_("policies for syncing upstream ostree repositories")
60
61
  param :ostree_upstream_sync_depth, :number, :desc => N_("if a custom sync policy is chosen for ostree repositories then a 'depth' value must be provided")
61
62
  param :deb_releases, String, :desc => N_("whitespace-separated list of releases to be synced from deb-archive")
@@ -462,10 +463,11 @@ module Katello
462
463
 
463
464
  # rubocop:disable Metrics/CyclomaticComplexity
464
465
  def repository_params
465
- keys = [:download_policy, :mirror_on_sync, :arch, :verify_ssl_on_sync, :upstream_password, :upstream_username, :download_concurrency,
466
+ keys = [:download_policy, :mirror_on_sync, :arch, :verify_ssl_on_sync, :upstream_password,
467
+ :upstream_username, :download_concurrency, :upstream_authentication_token,
466
468
  :ostree_upstream_sync_depth, :ostree_upstream_sync_policy, {:os_versions => []},
467
- :deb_releases, :deb_components, :deb_architectures, :description, :http_proxy_policy, :http_proxy_id, :retain_package_versions_count,
468
- {:ignorable_content => []}
469
+ :deb_releases, :deb_components, :deb_architectures, :description, :http_proxy_policy,
470
+ :http_proxy_id, :retain_package_versions_count, {:ignorable_content => []}
469
471
  ]
470
472
 
471
473
  keys += [{:docker_tags_whitelist => []}, :docker_upstream_name] if params[:action] == 'create' || @repository&.docker?
@@ -512,6 +514,7 @@ module Katello
512
514
  root.verify_ssl_on_sync = ::Foreman::Cast.to_bool(repo_params[:verify_ssl_on_sync]) if repo_params.key?(:verify_ssl_on_sync)
513
515
  root.upstream_username = repo_params[:upstream_username] if repo_params.key?(:upstream_username)
514
516
  root.upstream_password = repo_params[:upstream_password] if repo_params.key?(:upstream_password)
517
+ root.upstream_authentication_token = repo_params[:upstream_authentication_token] if repo_params.key?(:upstream_authentication_token)
515
518
  root.ignorable_content = repo_params[:ignorable_content] if root.yum? && repo_params.key?(:ignorable_content)
516
519
  root.http_proxy_policy = repo_params[:http_proxy_policy] if repo_params.key?(:http_proxy_policy)
517
520
  root.http_proxy_id = repo_params[:http_proxy_id] if repo_params.key?(:http_proxy_id)
@@ -563,12 +566,21 @@ module Katello
563
566
  content_type = params[:content_type]
564
567
 
565
568
  if content_type
569
+ RepositoryTypeManager.check_content_matches_repo_type!(@repository, params[:content_type]) if params[:content_type]
566
570
  @content = @repository.units_for_removal(params[:ids], content_type)
567
571
  else
568
572
  @content = @repository.units_for_removal(params[:ids])
569
573
  end
570
574
 
571
- RepositoryTypeManager.check_content_matches_repo_type!(@repository, @content.first.class::CONTENT_TYPE)
575
+ if @repository.generic?
576
+ if content_type
577
+ RepositoryTypeManager.check_content_matches_repo_type!(@repository, @content.first.content_type)
578
+ else
579
+ RepositoryTypeManager.check_content_matches_repo_type!(@repository, @repository.repository_type.default_managed_content_type.label)
580
+ end
581
+ else
582
+ RepositoryTypeManager.check_content_matches_repo_type!(@repository, @content.first.class::CONTENT_TYPE)
583
+ end
572
584
  end
573
585
 
574
586
  def filter_by_content_view(query, content_view_id, environment_id, is_available_for)
@@ -4,6 +4,7 @@ module Actions
4
4
  class SyncCapsule < ::Actions::EntryAction
5
5
  include Actions::Katello::PulpSelector
6
6
  def plan(smart_proxy, options = {})
7
+ plan_self(:smart_proxy_id => smart_proxy.id, :options => options)
7
8
  action_subject(smart_proxy)
8
9
  environment = options[:environment]
9
10
  content_view = options[:content_view]
@@ -37,53 +38,6 @@ module Actions
37
38
  end
38
39
  end
39
40
  end
40
- sync_container_gateway(smart_proxy)
41
- end
42
-
43
- def sync_container_gateway(smart_proxy)
44
- if smart_proxy.has_feature?(::SmartProxy::CONTAINER_GATEWAY_FEATURE)
45
- update_container_repo_list(smart_proxy)
46
- users = smart_proxy.container_gateway_users
47
- update_user_container_repo_mapping(smart_proxy, users) if users.any?
48
- end
49
- end
50
-
51
- def unauthenticated_container_repositories
52
- ::Katello::Repository.joins(:environment).where("#{::Katello::KTEnvironment.table_name}.registry_unauthenticated_pull" => true).select(:id).pluck(:id)
53
- end
54
-
55
- def update_container_repo_list(smart_proxy)
56
- # [{ repository: "repoA", auth_required: false }]
57
- repo_list = []
58
- ::Katello::SmartProxyHelper.new(smart_proxy).combined_repos_available_to_capsule.each do |repo|
59
- if repo.docker? && !repo.container_repository_name.nil?
60
- repo_list << { repository: repo.container_repository_name,
61
- auth_required: !unauthenticated_container_repositories.include?(repo.id) }
62
- end
63
- end
64
- smart_proxy.update_container_repo_list(repo_list)
65
- end
66
-
67
- def update_user_container_repo_mapping(smart_proxy, users)
68
- # Example user-repo mapping:
69
- # { users:
70
- # [
71
- # 'user a' => [{ repository: 'repo 1', auth_required: true }]
72
- # ]
73
- # }
74
-
75
- user_repo_map = { users: [] }
76
- users.each do |user|
77
- inner_repo_list = []
78
- repositories = ::Katello::Repository.readable_docker_catalog_as(user)
79
- repositories.each do |repo|
80
- next if repo.container_repository_name.nil?
81
- inner_repo_list << { repository: repo.container_repository_name,
82
- auth_required: !unauthenticated_container_repositories.include?(repo.id) }
83
- end
84
- user_repo_map[:users] << { user.login => inner_repo_list }
85
- end
86
- smart_proxy.update_user_container_repo_mapping(user_repo_map)
87
41
  end
88
42
 
89
43
  def repos_to_sync(smart_proxy, environment, content_view, repository, skip_metatadata_check = false)
@@ -109,6 +63,11 @@ module Actions
109
63
  :link
110
64
  end
111
65
 
66
+ def run
67
+ smart_proxy = ::SmartProxy.find(input[:smart_proxy_id])
68
+ smart_proxy.sync_container_gateway
69
+ end
70
+
112
71
  def rescue_strategy
113
72
  Dynflow::Action::Rescue::Skip
114
73
  end
@@ -45,17 +45,12 @@ module Actions
45
45
  end
46
46
 
47
47
  def finalize
48
- # update errata applicability counts for all hosts in the CV & LE
49
- ::Katello::Host::ContentFacet.where(:content_view_id => input[:content_view_id],
50
- :lifecycle_environment_id => input[:environment_id]).each do |facet|
51
- facet.update_applicability_counts
52
- facet.update_errata_status
53
- end
48
+ environment = ::Katello::KTEnvironment.find(input[:environment_id])
49
+ ::Katello::ContentView.find(input[:content_view_id]).update_host_statuses(environment)
54
50
 
55
51
  history = ::Katello::ContentViewHistory.find(input[:history_id])
56
52
  history.status = ::Katello::ContentViewHistory::SUCCESSFUL
57
53
  history.save!
58
- environment = ::Katello::KTEnvironment.find(input[:environment_id])
59
54
 
60
55
  if !input[:incremental_update] && sync_proxies?(environment)
61
56
  ForemanTasks.async_task(ContentView::CapsuleSync,
@@ -193,12 +193,14 @@ module Actions
193
193
  def handle_import(version, path:, metadata:)
194
194
  sequence do
195
195
  plan_action(::Actions::Pulp3::Orchestration::ContentViewVersion::Import, version, path: path, metadata: metadata)
196
- plan_action(::Actions::Pulp3::Orchestration::ContentViewVersion::CopyVersionUnitsToLibrary, version)
197
196
  concurrence do
198
197
  version.importable_repositories.pluck(:id).each do |id|
199
- plan_action(Katello::Repository::IndexContent, id: id)
198
+ # need to force full_indexing for these version repositories
199
+ # on import. This will then help us correctly copy version units to the library
200
+ plan_action(Katello::Repository::IndexContent, id: id, full_index: true)
200
201
  end
201
202
  end
203
+ plan_action(::Actions::Pulp3::Orchestration::ContentViewVersion::CopyVersionUnitsToLibrary, version)
202
204
  end
203
205
  end
204
206
 
@@ -13,6 +13,7 @@ module Actions
13
13
  # rubocop:disable Metrics/MethodLength
14
14
  # rubocop:disable Metrics/CyclomaticComplexity
15
15
  # rubocop:disable Metrics/PerceivedComplexity
16
+ # rubocop:disable Metrics/AbcSize
16
17
  def run
17
18
  repo = ::Katello::Repository.find(input[:id])
18
19
  if repo.docker?
@@ -21,6 +22,10 @@ module Actions
21
22
  ::Katello::DockerManifestList.import_for_repository(repo)
22
23
  elsif repo.file?
23
24
  ::Katello::FileUnit.import_for_repository(repo)
25
+ elsif repo.generic?
26
+ repo.repository_type.content_types_to_index.each do |type|
27
+ type.model_class.import_for_repository(repo, generic_content_type: type.content_type)
28
+ end
24
29
  elsif repo.deb?
25
30
  if input[:import_upload_task] && input[:import_upload_task][:content_unit_href]
26
31
  unit_ids = [input[:import_upload_task][:content_unit_href]]
@@ -16,7 +16,11 @@ module Actions
16
16
  generate_applicability = options.fetch(:generate_applicability, repository.yum?)
17
17
 
18
18
  options[:content_type] ||= ::Katello::RepositoryTypeManager.find(repository.content_type).default_managed_content_type.label
19
- unit_type_id = SmartProxy.pulp_primary.content_service(options[:content_type])::CONTENT_TYPE
19
+ if ::Katello::RepositoryTypeManager.generic_content_type?(options[:content_type])
20
+ unit_type_id = options[:content_type]
21
+ else
22
+ unit_type_id = SmartProxy.pulp_primary.content_service(options[:content_type])::CONTENT_TYPE
23
+ end
20
24
 
21
25
  sequence do
22
26
  upload_results = concurrence do
@@ -10,12 +10,13 @@ module Actions
10
10
  param :contents_changed
11
11
  param :matching_content
12
12
  param :source_repository_id
13
+ param :full_index
13
14
  end
14
15
 
15
16
  def run
16
17
  source_repository = ::Katello::Repository.find(input[:source_repository_id]) if input[:source_repository_id]
17
18
  repo = ::Katello::Repository.find(input[:id])
18
- repo.index_content(source_repository: source_repository)
19
+ repo.index_content(source_repository: source_repository, full_index: input[:full_index].present?)
19
20
  end
20
21
  end
21
22
  end
@@ -16,7 +16,11 @@ module Actions
16
16
  action_subject(repository)
17
17
 
18
18
  content_unit_ids = content_units.map(&:id)
19
- content_unit_type = options[:content_type] || content_units.first.class::CONTENT_TYPE
19
+ if repository.generic?
20
+ content_unit_type = options[:content_type] || content_units.first.content_type
21
+ else
22
+ content_unit_type = options[:content_type] || content_units.first.class::CONTENT_TYPE
23
+ end
20
24
  ::Katello::RepositoryTypeManager.check_content_matches_repo_type!(repository, content_unit_type)
21
25
 
22
26
  generate_applicability = options.fetch(:generate_applicability, repository.yum?)
@@ -15,7 +15,12 @@ module Actions
15
15
  content_type ||= ::Katello::RepositoryTypeManager.find(repository.content_type).default_managed_content_type.label
16
16
  ::Katello::RepositoryTypeManager.check_content_matches_repo_type!(repository, content_type)
17
17
 
18
- unit_type_id = SmartProxy.pulp_primary.content_service(content_type)::CONTENT_TYPE
18
+ if ::Katello::RepositoryTypeManager.generic_content_type?(content_type)
19
+ unit_type_id = content_type
20
+ else
21
+ unit_type_id = SmartProxy.pulp_primary.content_service(content_type)::CONTENT_TYPE
22
+ end
23
+
19
24
  upload_actions = []
20
25
 
21
26
  generate_applicability = options.fetch(:generate_applicability, repository.yum?)
@@ -11,11 +11,9 @@ module Actions
11
11
  docker_tag = (args.dig(:unit_type_id) == "docker_tag")
12
12
  sequence do
13
13
  if content_unit_href
14
- content_backend_service = SmartProxy.pulp_primary.content_service(args.dig(:unit_type_id))
15
- duplicate_sha_path_content_list = content_backend_service.content_api.list(
16
- "sha256": file[:sha256],
17
- "relative_path": file[:filename])
14
+ duplicate_sha_path_content_list = ::Katello::Pulp3::PulpContentUnit.find_duplicate_unit(repository, args.dig(:unit_type_id), file, file[:sha256])
18
15
  duplicate_content_href = duplicate_sha_path_content_list&.results&.first&.pulp_href
16
+
19
17
  if duplicate_content_href
20
18
  plan_self(:commit_output => [], :content_unit_href => duplicate_content_href)
21
19
  action_output = plan_action(Pulp3::Repository::ImportUpload, duplicate_content_href, repository, smart_proxy).output
@@ -6,18 +6,13 @@ module Actions
6
6
  include Actions::Helpers::OutputPropagator
7
7
  def plan(repository, smart_proxy, file, unit_type_id)
8
8
  sequence do
9
- content_backend_service = SmartProxy.pulp_primary.content_service(unit_type_id)
10
- duplicate_sha_path_content_list = content_backend_service.content_api.list(
11
- "sha256": Digest::SHA256.hexdigest(File.read(file[:path])),
12
- "relative_path": file[:filename])
9
+ checksum = Digest::SHA256.hexdigest(File.read(file[:path]))
10
+ duplicate_sha_path_content_list = ::Katello::Pulp3::PulpContentUnit.find_duplicate_unit(repository, unit_type_id, file, checksum)
13
11
  duplicate_content_href = duplicate_sha_path_content_list&.results&.first&.pulp_href
14
12
 
15
13
  unless duplicate_content_href
16
14
  duplicate_sha_artifact_list = ::Katello::Pulp3::Api::Core.new(smart_proxy).artifacts_api.list("sha256": Digest::SHA256.hexdigest(File.read(file[:path])))
17
15
  duplicate_sha_artifact_href = duplicate_sha_artifact_list&.results&.first&.pulp_href
18
- end
19
-
20
- unless duplicate_content_href
21
16
  if duplicate_sha_artifact_href
22
17
  artifact_action_output = plan_action(Pulp3::Repository::SaveArtifact, file, repository, smart_proxy, nil, unit_type_id, artifact_href: duplicate_sha_artifact_href).output
23
18
  else
@@ -13,7 +13,10 @@ module Actions
13
13
  fail _("Content not uploaded to pulp") unless artifact_href
14
14
  content_type = input[:unit_type_id]
15
15
  content_backend_service = SmartProxy.pulp_primary.content_service(content_type)
16
- output[:pulp_tasks] = [content_backend_service.content_api_create(relative_path: input[:options][:file_name], artifact: artifact_href)]
16
+ output[:pulp_tasks] = [content_backend_service.content_api_create(relative_path: input[:options][:file_name],
17
+ artifact: artifact_href,
18
+ repository_id: input[:repository_id],
19
+ content_type: content_type)]
17
20
  end
18
21
 
19
22
  def fetch_artifact_href
@@ -244,7 +244,7 @@ module Katello
244
244
 
245
245
  batch.each do |task|
246
246
  next if skip_task?(task)
247
- next if !only_host_ids.nil? && only_host_ids.include?(task.input['host']['id'].to_i)
247
+ next unless only_host_ids.nil? || only_host_ids.include?(task.input['host']['id'].to_i)
248
248
  parse_errata(task).each do |erratum_id|
249
249
  current_erratum_errata_type = preloaded_errata.find { |k, _| k == erratum_id }.last
250
250
 
@@ -49,7 +49,9 @@ module Katello
49
49
  def filter_errata_by_pulp_href(errata, package_pulp_hrefs, source_repo_rpm_filenames)
50
50
  return [] if package_pulp_hrefs.empty?
51
51
  rpms = Katello::Rpm.where(:pulp_id => package_pulp_hrefs)
52
+ srpms = Katello::Srpm.where(:pulp_id => package_pulp_hrefs)
52
53
  rpm_filenames = rpms.map { |rpm| File.basename(rpm.filename) }
54
+ srpm_filenames = srpms.map { |srpm| File.basename(srpm.filename) }
53
55
  source_repo_rpm_filenames = source_repo_rpm_filenames.map { |rpm| File.basename(rpm) }
54
56
  matching_errata = []
55
57
  errata.each do |erratum|
@@ -57,7 +59,7 @@ module Katello
57
59
  next if erratum.packages.empty?
58
60
  rpms_in_erratum_and_source_repo = erratum.packages.pluck(:filename) & source_repo_rpm_filenames
59
61
  next if rpms_in_erratum_and_source_repo.empty?
60
- if (rpms_in_erratum_and_source_repo - rpm_filenames).empty?
62
+ if (rpms_in_erratum_and_source_repo - rpm_filenames - srpm_filenames).empty?
61
63
  matching_errata << erratum
62
64
  end
63
65
  end
@@ -33,6 +33,8 @@ module Katello
33
33
  included do
34
34
  prepend Overrides
35
35
 
36
+ delegate :content_source_id, :content_view_id, :lifecycle_environment_id, :kickstart_repository_id, to: :content_facet, allow_nil: true
37
+
36
38
  has_many :dispatch_histories, :class_name => "::Katello::Agent::DispatchHistory", :foreign_key => :host_id, :dependent => :delete_all
37
39
 
38
40
  has_many :host_installed_packages, :class_name => "::Katello::HostInstalledPackage", :foreign_key => :host_id, :dependent => :delete_all
@@ -56,6 +58,9 @@ module Katello
56
58
  after_validation :queue_reset_content_host_status
57
59
  register_rebuild(:queue_reset_content_host_status, N_("Content_Host_Status"))
58
60
 
61
+ after_validation :queue_refresh_content_host_status
62
+ register_rebuild(:queue_refresh_content_host_status, N_("Refresh_Content_Host_Status"))
63
+
59
64
  scope :with_pools_expiring_in_days, ->(days) { joins(:pools).merge(Katello::Pool.expiring_in_days(days)).distinct }
60
65
 
61
66
  scoped_search :relation => :host_collections, :on => :id, :complete_value => false, :rename => :host_collection_id, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
@@ -99,6 +104,20 @@ module Katello
99
104
  end
100
105
  end
101
106
 
107
+ def refresh_content_host_status
108
+ self.host_statuses.where(type: ::Katello::HostStatusManager::STATUSES.map(&:name)).each do |status|
109
+ status.refresh!
110
+ end
111
+ refresh_global_status!
112
+ end
113
+
114
+ def queue_refresh_content_host_status
115
+ if !new_record? && !build && self.changes.key?('build')
116
+ queue.create(id: "refresh_content_host_status_#{id}", name: _("Refresh Content Host Statuses for %s") % self,
117
+ priority: 300, action: [self, :refresh_content_host_status])
118
+ end
119
+ end
120
+
102
121
  def reset_katello_status
103
122
  self.host_statuses.where(type: ::Katello::HostStatusManager::STATUSES.map(&:name)).each do |status|
104
123
  status.update!(:status => status.class.const_get(:UNKNOWN))
@@ -127,9 +127,13 @@ module Katello
127
127
  "#{self.name.demodulize.underscore}_id"
128
128
  end
129
129
 
130
- def import_all(pulp_ids = nil, repository = nil, content_type_name = nil)
130
+ def import_all(pulp_ids = nil, repository = nil, generic_content_type = nil)
131
131
  ids_to_associate = []
132
- service_class = SmartProxy.pulp_primary!.content_service(content_type)
132
+ if generic_content_type
133
+ service_class = SmartProxy.pulp_primary!.content_service(generic_content_type)
134
+ else
135
+ service_class = SmartProxy.pulp_primary!.content_service(content_type)
136
+ end
133
137
  service_class.pulp_units_batch_all(pulp_ids).each do |units|
134
138
  units.each do |unit|
135
139
  unit = unit.with_indifferent_access
@@ -146,7 +150,7 @@ module Katello
146
150
  service = service_class.new(model.pulp_id)
147
151
  service.backend_data = unit
148
152
  if repository&.generic?
149
- service.update_model(model, repository.repository_type, content_type_name)
153
+ service.update_model(model, repository.repository_type, generic_content_type)
150
154
  else
151
155
  service.update_model(model)
152
156
  end
@@ -156,14 +160,21 @@ module Katello
156
160
  sync_repository_associations(repository, :pulp_ids => ids_to_associate, :additive => true) if self.many_repository_associations && repository && ids_to_associate.present?
157
161
  end
158
162
 
159
- def import_for_repository(repository, content_type_name = nil)
163
+ # rubocop:disable Metrics/MethodLength
164
+ def import_for_repository(repository, generic_content_type: nil, full_index: false)
160
165
  pulp_id_href_map = {}
161
- service_class = SmartProxy.pulp_primary!.content_service(content_type)
162
- fetch_only_ids = !repository.content_view.default? &&
166
+ if generic_content_type
167
+ service_class = SmartProxy.pulp_primary!.content_service(generic_content_type)
168
+ else
169
+ service_class = SmartProxy.pulp_primary!.content_service(content_type)
170
+ end
171
+ fetch_only_ids = !full_index &&
172
+ !repository.content_view.default? &&
163
173
  !repository.repository_type.unique_content_per_repo &&
164
174
  service_class.supports_id_fetch?
165
175
 
166
- service_class.pulp_units_batch_for_repo(repository, fetch_identifiers: fetch_only_ids, content_type: content_type_name).each do |units|
176
+ erratum_updated_ids = []
177
+ service_class.pulp_units_batch_for_repo(repository, fetch_identifiers: fetch_only_ids, content_type: generic_content_type).each do |units|
167
178
  units.each do |unit|
168
179
  unit = unit.with_indifferent_access
169
180
  pulp_id = unit[service_class.unit_identifier]
@@ -176,7 +187,10 @@ module Katello
176
187
  service.backend_data = unit
177
188
  model.repository_id = repository.id unless many_repository_associations
178
189
  if repository.generic?
179
- service.update_model(model, repository.repository_type, content_type_name)
190
+ service.update_model(model, repository.repository_type, generic_content_type)
191
+ elsif self == ::Katello::Erratum
192
+ # Errata will change pulp_hrefs if the upstream repo updates them
193
+ erratum_updated_ids << service.update_model(model)
180
194
  else
181
195
  service.update_model(model)
182
196
  end
@@ -184,7 +198,7 @@ module Katello
184
198
  pulp_id_href_map[pulp_id] = backend_identifier
185
199
  end
186
200
  end
187
- sync_repository_associations(repository, :pulp_id_href_map => pulp_id_href_map) if self.many_repository_associations
201
+ sync_repository_associations(repository, :pulp_id_href_map => pulp_id_href_map, generic_content_type: generic_content_type, erratum_updated_ids: erratum_updated_ids.uniq) if self.many_repository_associations
188
202
  end
189
203
 
190
204
  def sync_repository_associations(repository, options = {})
@@ -196,21 +210,28 @@ module Katello
196
210
  id_href_map_for_repository = {}
197
211
  ids_for_repository.each { |id_href| id_href_map_for_repository[id_href[0]] = id_href[1] }
198
212
  id_href_map_for_repository.each_pair { |k, v| id_href_map_for_repository[k] = pulp_id_href_map[v] }
213
+ erratum_updated_ids = options.fetch(:erratum_updated_ids, []).flatten.compact
199
214
 
200
215
  existing_ids = self.repository_association_class.uncached do
201
216
  self.repository_association_class.where(:repository_id => repository).pluck(unit_id_field)
202
217
  end
203
218
 
219
+ new_ids = associated_ids - existing_ids
204
220
  ActiveRecord::Base.transaction do
205
221
  if !additive && (delete_ids = existing_ids - associated_ids).any?
206
222
  query = "DELETE FROM #{self.repository_association_class.table_name} WHERE repository_id=#{repository.id} AND #{unit_id_field} IN (#{delete_ids.join(', ')})"
207
223
  ActiveRecord::Base.connection.execute(query)
208
224
  end
209
- unless (new_ids = associated_ids - existing_ids).empty?
210
- self.repository_association_class.import(db_columns_sync, db_values(new_ids, id_href_map_for_repository, repository), validate: false)
225
+ if self == ::Katello::Erratum
226
+ self.update_repo_association_records(new_ids, erratum_updated_ids, id_href_map_for_repository, repository)
227
+ else
228
+ unless new_ids.empty?
229
+ self.repository_association_class.import(db_columns_sync, db_values(new_ids, id_href_map_for_repository, repository), validate: false)
230
+ end
211
231
  end
212
232
  end
213
233
  end
234
+ # rubocop:enable Metrics/MethodLength
214
235
 
215
236
  def copy_repository_associations(source_repo, dest_repo)
216
237
  if many_repository_associations
@@ -4,6 +4,7 @@ require 'proxy_api/pulp_node'
4
4
 
5
5
  module Katello
6
6
  module Concerns
7
+ # rubocop:disable Metrics/ModuleLength
7
8
  module SmartProxyExtensions
8
9
  extend ActiveSupport::Concern
9
10
 
@@ -110,18 +111,52 @@ module Katello
110
111
  end
111
112
  end
112
113
 
113
- def update_unauthenticated_repo_list(repo_names)
114
- ProxyAPI::ContainerGateway.new(url: self.url).unauthenticated_repository_list("repositories": repo_names)
114
+ def sync_container_gateway
115
+ if has_feature?(::SmartProxy::CONTAINER_GATEWAY_FEATURE)
116
+ update_container_repo_list
117
+ users = container_gateway_users
118
+ update_user_container_repo_mapping(users) if users.any?
119
+ end
115
120
  end
116
121
 
117
- def update_container_repo_list(repo_list)
122
+ def update_container_repo_list
123
+ # [{ repository: "repoA", auth_required: false }]
124
+ repo_list = []
125
+ ::Katello::SmartProxyHelper.new(self).combined_repos_available_to_capsule.each do |repo|
126
+ if repo.docker? && !repo.container_repository_name.nil?
127
+ repo_list << { repository: repo.container_repository_name,
128
+ auth_required: !unauthenticated_container_repositories.include?(repo.id) }
129
+ end
130
+ end
118
131
  ProxyAPI::ContainerGateway.new(url: self.url).repository_list({ repositories: repo_list })
119
132
  end
120
133
 
121
- def update_user_container_repo_mapping(user_repo_map)
134
+ def update_user_container_repo_mapping(users)
135
+ # Example user-repo mapping:
136
+ # { users:
137
+ # [
138
+ # 'user a' => [{ repository: 'repo 1', auth_required: true }]
139
+ # ]
140
+ # }
141
+
142
+ user_repo_map = { users: [] }
143
+ users.each do |user|
144
+ inner_repo_list = []
145
+ repositories = ::Katello::Repository.readable_docker_catalog_as(user)
146
+ repositories.each do |repo|
147
+ next if repo.container_repository_name.nil?
148
+ inner_repo_list << { repository: repo.container_repository_name,
149
+ auth_required: !unauthenticated_container_repositories.include?(repo.id) }
150
+ end
151
+ user_repo_map[:users] << { user.login => inner_repo_list }
152
+ end
122
153
  ProxyAPI::ContainerGateway.new(url: self.url).user_repository_mapping(user_repo_map)
123
154
  end
124
155
 
156
+ def unauthenticated_container_repositories
157
+ ::Katello::Repository.joins(:environment).where("#{::Katello::KTEnvironment.table_name}.registry_unauthenticated_pull" => true).select(:id).pluck(:id)
158
+ end
159
+
125
160
  def container_gateway_users
126
161
  usernames = ProxyAPI::ContainerGateway.new(url: self.url).users
127
162
  ::User.where(login: usernames['users'])
@@ -370,6 +370,19 @@ module Katello
370
370
  end
371
371
  end
372
372
 
373
+ def update_host_statuses(environment)
374
+ # update errata applicability counts for all hosts in the CV & LE
375
+ Location.no_taxonomy_scope do
376
+ User.as_anonymous_admin do
377
+ ::Katello::Host::ContentFacet.where(:content_view_id => self,
378
+ :lifecycle_environment_id => environment).each do |facet|
379
+ facet.update_applicability_counts
380
+ facet.update_errata_status
381
+ end
382
+ end
383
+ end
384
+ end
385
+
373
386
  def component_repositories
374
387
  components.map(&:archived_repos).flatten
375
388
  end
@@ -6,7 +6,7 @@ module Katello
6
6
  Repository::FILE_TYPE,
7
7
  Repository::DEB_TYPE,
8
8
  Repository::ANSIBLE_COLLECTION_TYPE,
9
- Katello::RepositoryTypeManager.generic_repository_types(enabled_only: false).keys.flatten
9
+ Katello::RepositoryTypeManager.generic_repository_types(false).keys.flatten
10
10
  ].flatten.freeze
11
11
 
12
12
  ALLOWED_IMPORT_REPOSITORY_TYPES = Repository::EXPORTABLE_TYPES
@@ -58,8 +58,8 @@ module Katello
58
58
  docker_taggable_id
59
59
  end
60
60
 
61
- def self.import_for_repository(repository)
62
- super(repository)
61
+ def self.import_for_repository(repository, options = {})
62
+ super(repository, options)
63
63
  ::Katello::DockerMetaTag.import_meta_tags([repository])
64
64
  end
65
65