katello 3.16.0.rc4 → 3.16.0.rc4.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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +2 -2
  3. data/app/controllers/katello/api/v2/api_controller.rb +1 -0
  4. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +3 -0
  5. data/app/controllers/katello/api/v2/content_views_controller.rb +7 -0
  6. data/app/controllers/katello/concerns/api/v2/associations_permission_check.rb +67 -0
  7. data/app/lib/actions/katello/capsule_content/refresh_repos.rb +4 -0
  8. data/app/lib/actions/katello/capsule_content/sync.rb +0 -4
  9. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +16 -16
  10. data/app/lib/actions/katello/content_view/incremental_updates.rb +5 -0
  11. data/app/lib/actions/katello/content_view/presenters/incremental_updates_presenter.rb +2 -1
  12. data/app/lib/actions/katello/content_view_version/incremental_update.rb +90 -26
  13. data/app/lib/actions/pulp/abstract_async_task.rb +1 -0
  14. data/app/lib/actions/pulp/consumer/sync_capsule.rb +8 -0
  15. data/app/lib/actions/pulp/repository/presenters/deb_presenter.rb +2 -2
  16. data/app/lib/actions/pulp3/repository/multi_copy_units.rb +48 -0
  17. data/app/lib/actions/pulp3/repository/save_versions.rb +39 -0
  18. data/app/lib/katello/concerns/base_template_scope_extensions.rb +0 -14
  19. data/app/models/katello/glue/pulp/repo.rb +1 -0
  20. data/app/models/katello/host/content_facet.rb +10 -5
  21. data/app/models/setting/content.rb +3 -1
  22. data/app/services/katello/pulp3/repository/yum.rb +36 -15
  23. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/errata.routes.js +1 -1
  24. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +4 -0
  25. data/lib/katello/engine.rb +0 -1
  26. data/lib/katello/plugin.rb +2 -0
  27. data/lib/katello/version.rb +1 -1
  28. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 590a33ff3016ad29aaeca6e8d5a0c967b9053a01cf3dbf8f28fcb68b63d056bd
4
- data.tar.gz: e8c30ca9e88f472f3aabf89b7f2cc3c6122750706e9bdfbb9d1cfa8aa957d4a5
3
+ metadata.gz: 3206fcf99b7e7aa7a1fcbb9b6231173193f89ba0099c5e46f6226b5fc044bc8b
4
+ data.tar.gz: c5ffbe4836c0958563e1448657a5fbc7d8a684ed2a647b19f933728e2436fe5f
5
5
  SHA512:
6
- metadata.gz: 2fbba71f828db21edacf4100aac226a638fa7c6dd59871f6d0f029846af27ff54914c803798fd6054463ae4f44bbfc29d9466fca8a19867e63c10486668ce30c
7
- data.tar.gz: 17347500daf6bb1b2dd1ff7126b97e84f2120e1c12e23066036d2f30402cdb9018dc5c6cb1f74ceff441f069a2733dceb4e3a4958032237034eaff5783915b49
6
+ metadata.gz: c01c07349a208003082823e8a0b50e5d0920506a6b72db57c811c8c13d934cba35ec92f3c3b7088770e6e8f21efca6cd22560380c8838900d7c2fdf99501ebcd
7
+ data.tar.gz: fc2bbb3bab3ac2e163bea0b97941e0fac8d48831d276af542a059ba03cae395c396010ec8a65e3e0a5150bb6032a9d0e1458c848c17a9e74dbd8a4d429f95729
@@ -268,8 +268,8 @@ module Katello
268
268
  end
269
269
 
270
270
  def get_parent_host(headers)
271
- hostnames = headers["HTTP_X_FORWARDED_SERVER"]
272
- host = hostnames.split(",")[0] if hostnames
271
+ hostnames = headers["HTTP_X_FORWARDED_HOST"]
272
+ host = hostnames.split(/[\,,:]/)[0].strip if hostnames
273
273
  host || URI.parse(Setting[:foreman_url]).host
274
274
  end
275
275
 
@@ -5,6 +5,7 @@ module Katello
5
5
  include Api::V2::Rendering
6
6
  include Api::V2::ErrorHandling
7
7
  include ::Foreman::Controller::CsvResponder
8
+ include Concerns::Api::V2::AssociationsPermissionCheck
8
9
 
9
10
  # support for session (thread-local) variables must be the last filter in this class
10
11
  include Foreman::ThreadSession::Cleaner
@@ -143,6 +143,9 @@ module Katello
143
143
  end
144
144
  end
145
145
  def incremental_update
146
+ if params[:add_content].values.flatten.empty?
147
+ fail HttpErrors::BadRequest, _("Incremental update requires at least one content unit")
148
+ end
146
149
  any_environments = params[:content_view_version_environments].any? { |cvve| cvve[:environment_ids].try(:any?) }
147
150
  if params[:add_content]&.key?(:errata_ids) && params[:update_hosts] && any_environments
148
151
  hosts = calculate_hosts_for_incremental(params[:update_hosts], params[:propagate_to_composites])
@@ -22,6 +22,13 @@ module Katello
22
22
  param :solve_dependencies, :bool, :desc => N_("Solve RPM dependencies by default on Content View publish, defaults to false")
23
23
  end
24
24
 
25
+ def filtered_associations
26
+ {
27
+ :component_ids => Katello::ContentViewVersion,
28
+ :repository_ids => Katello::Repository
29
+ }
30
+ end
31
+
25
32
  api :GET, "/organizations/:organization_id/content_views", N_("List content views")
26
33
  api :GET, "/content_views", N_("List content views")
27
34
  param :organization_id, :number, :desc => N_("organization identifier")
@@ -0,0 +1,67 @@
1
+ module Katello
2
+ module Concerns
3
+ module Api::V2::AssociationsPermissionCheck
4
+ extend ActiveSupport::Concern
5
+
6
+ # The purpose of this module is to protect a controller from a user creating or updating some association
7
+ # when they do not have permissions to view the associated items. An example would be adding random repository ids to
8
+ # content view.
9
+ # To support this, within the controller define a method such as:
10
+ # def filtered_associations
11
+ # {
12
+ # :component_ids => Katello::ContentViewVersion,
13
+ # :repository_ids => Katello::Repository
14
+ # }
15
+ # end
16
+ # This assumes that the parameters are 'wrapped'. So the above in the content_views_controller, actually looks at
17
+ # a subhash of 'content_view'
18
+
19
+ included do
20
+ before_action :check_association_ids, :only => [:create, :update]
21
+ end
22
+
23
+ def check_association_ids
24
+ if filtered_associations
25
+ wrapped_params = params[self._wrapper_options.name]
26
+ find_param_arrays(wrapped_params).each do |key_path|
27
+ if (model_class = filtered_associations.with_indifferent_access.dig(*key_path))
28
+ param_ids = wrapped_params.dig(*key_path)
29
+ filtered_ids = model_class.readable.where(:id => param_ids).pluck(:id)
30
+ if (unfound_ids = param_ids_missing(param_ids, filtered_ids)).any?
31
+ fail HttpErrors::NotFound, _("One or more ids (%{ids}) were not found for %{assoc}. You may not have permissions to see them.") %
32
+ {ids: unfound_ids, assoc: key_path.last}
33
+ end
34
+ else
35
+ fail _("Unfiltered params array: %s.") % key_path
36
+ end
37
+ end
38
+ else
39
+ Rails.logger.warn("#{self.class.name} may has unprotected associations, see associations_permission_check.rb for details.") if ENV['RAILS_ENV'] == 'development'
40
+ end
41
+ end
42
+
43
+ def filtered_associations
44
+ #should return {} when supported by all controllers
45
+ nil
46
+ end
47
+
48
+ def param_ids_missing(param_ids, filtered_ids)
49
+ param_ids.map(&:to_i).uniq - filtered_ids.map(&:to_i).uniq
50
+ end
51
+
52
+ #returns an array of list of keys pointing to an array in a params hash i.e.:
53
+ # {"a"=> {"b" => [3]}} => [["a", "b"]]
54
+ def find_param_arrays(hash = params)
55
+ list_of_paths = []
56
+ hash.each do |key, value|
57
+ if value.is_a?(ActionController::Parameters) || value.is_a?(Hash)
58
+ list_of_paths += find_param_arrays(value).compact.map { |inner_keys| [key] + inner_keys }
59
+ elsif value.is_a?(Array)
60
+ list_of_paths << [key]
61
+ end
62
+ end
63
+ list_of_paths.compact
64
+ end
65
+ end
66
+ end
67
+ end
@@ -10,6 +10,10 @@ module Actions
10
10
  fail NotImplementedError
11
11
  end
12
12
 
13
+ def rescue_strategy
14
+ Dynflow::Action::Rescue::Skip if self.state == 'error'
15
+ end
16
+
13
17
  def plan(smart_proxy, options = {})
14
18
  plan_self(:smart_proxy_id => smart_proxy.id,
15
19
  :environment_id => options[:environment]&.id,
@@ -44,10 +44,6 @@ module Actions
44
44
  plan_action(SyncCapsule, smart_proxy, refresh_options)
45
45
  end
46
46
  end
47
-
48
- def rescue_strategy
49
- Dynflow::Action::Rescue::Skip
50
- end
51
47
  end
52
48
  end
53
49
  end
@@ -11,19 +11,23 @@ module Actions
11
11
  skip_metadata_check = options.fetch(:skip_metadata_check, false)
12
12
 
13
13
  smart_proxy_helper = ::Katello::SmartProxyHelper.new(smart_proxy)
14
- concurrence do
15
- smart_proxy_helper.repos_available_to_capsule(environment, content_view, repository).each do |repo|
16
- plan_pulp_action([Actions::Pulp::Orchestration::Repository::SmartProxySync,
17
- Actions::Pulp3::CapsuleContent::Sync],
18
- repo, smart_proxy,
19
- skip_metadata_check: skip_metadata_check)
14
+ sequence do
15
+ smart_proxy_helper.repos_available_to_capsule(environment, content_view, repository).in_groups_of(Setting[:foreman_proxy_content_batch_size], false) do |repos|
16
+ concurrence do
17
+ repos.each do |repo|
18
+ plan_pulp_action([Actions::Pulp::Orchestration::Repository::SmartProxySync,
19
+ Actions::Pulp3::CapsuleContent::Sync],
20
+ repo, smart_proxy,
21
+ skip_metadata_check: skip_metadata_check)
20
22
 
21
- if repo.is_a?(::Katello::Repository) &&
22
- repo.distribution_bootable? &&
23
- repo.download_policy == ::Runcible::Models::YumImporter::DOWNLOAD_ON_DEMAND
24
- plan_action(Katello::Repository::FetchPxeFiles,
25
- id: repo.id,
26
- capsule_id: smart_proxy.id)
23
+ if repo.is_a?(::Katello::Repository) &&
24
+ repo.distribution_bootable? &&
25
+ repo.download_policy == ::Runcible::Models::YumImporter::DOWNLOAD_ON_DEMAND
26
+ plan_action(Katello::Repository::FetchPxeFiles,
27
+ id: repo.id,
28
+ capsule_id: smart_proxy.id)
29
+ end
30
+ end
27
31
  end
28
32
  end
29
33
  end
@@ -32,10 +36,6 @@ module Actions
32
36
  def resource_locks
33
37
  :link
34
38
  end
35
-
36
- def rescue_strategy
37
- Dynflow::Action::Rescue::Skip
38
- end
39
39
  end
40
40
  end
41
41
  end
@@ -80,6 +80,7 @@ module Actions
80
80
  added_units = version_output.try(:[], :output).try(:[], :added_units)
81
81
  if added_units
82
82
  total_count[:errata_count] = added_units[:erratum].try(:count)
83
+ total_count[:modulemd_count] = added_units[:modulemd].try(:count)
83
84
  total_count[:rpm_count] = added_units[:rpm].try(:count)
84
85
  total_count[:puppet_module_count] = added_units[:puppet_module].try(:count)
85
86
  end
@@ -117,6 +118,10 @@ module Actions
117
118
  errata = _(" %{errata_count} Errata" % {:errata_count => total_count[:errata_count]})
118
119
  content << errata
119
120
  end
121
+ if total_count[:modulemd_count] && total_count[:modulemd_count] > 0
122
+ modulemd = _(" %{modulemd_count} Module Stream(s)" % {:modulemd_count => total_count[:modulemd_count]})
123
+ content << modulemd
124
+ end
120
125
  if total_count[:rpm_count] && total_count[:rpm_count] > 0
121
126
  rpm = _(" %{package_count} Package(s)" % {:package_count => total_count[:rpm_count]})
122
127
  content << rpm
@@ -5,6 +5,7 @@ module Actions
5
5
  class IncrementalUpdatesPresenter < Helpers::Presenter::Base
6
6
  HUMANIZED_TYPES = {
7
7
  ::Katello::Erratum::CONTENT_TYPE => "Errata",
8
+ ::Katello::ModuleStream::CONTENT_TYPE => "Module Streams",
8
9
  ::Katello::Rpm::CONTENT_TYPE => "Packages",
9
10
  ::Katello::PuppetModule::CONTENT_TYPE => "Puppet Modules"
10
11
  }.freeze
@@ -25,7 +26,7 @@ module Actions
25
26
  if cvv
26
27
  humanized_lines << "Content View: #{cvv.content_view.name} version #{cvv.version}"
27
28
  humanized_lines << _("Added Content:")
28
- [::Katello::Erratum, ::Katello::Rpm, ::Katello::PuppetModule].each do |content_type|
29
+ [::Katello::Erratum, ::Katello::ModuleStream, ::Katello::Rpm, ::Katello::PuppetModule].each do |content_type|
29
30
  unless output[:added_units][content_type::CONTENT_TYPE].blank?
30
31
  humanized_lines << " #{HUMANIZED_TYPES[content_type::CONTENT_TYPE]}:"
31
32
  humanized_lines += output[:added_units][content_type::CONTENT_TYPE].sort.map { |unit| " #{unit}" }
@@ -51,11 +51,19 @@ module Actions
51
51
  end
52
52
 
53
53
  concurrence do
54
- repos_to_clone.each do |source_repos|
55
- copy_action_outputs += copy_repos(repository_mapping[source_repos],
56
- new_content_view_version,
57
- content,
58
- dep_solve)
54
+ if SmartProxy.pulp_master.pulp3_support?(repos_to_clone.first.first)
55
+ extended_repo_mapping = pulp3_repo_mapping(repository_mapping, old_version)
56
+ unit_map = pulp3_content_mapping(content)
57
+
58
+ copy_action_outputs << plan_action(Pulp3::Repository::MultiCopyUnits, extended_repo_mapping, unit_map,
59
+ dependency_solving: true).output
60
+ else
61
+ repos_to_clone.each do |source_repos|
62
+ copy_action_outputs += copy_repos(repository_mapping[source_repos],
63
+ new_content_view_version,
64
+ content,
65
+ dep_solve)
66
+ end
59
67
  end
60
68
 
61
69
  sequence do
@@ -68,11 +76,37 @@ module Actions
68
76
  plan_self(:content_view_id => old_version.content_view.id,
69
77
  :new_content_view_version_id => self.new_content_view_version.id,
70
78
  :environment_ids => environments.map(&:id), :user_id => ::User.current.id,
71
- :history_id => history.id, :copy_action_outputs => copy_action_outputs)
79
+ :history_id => history.id, :copy_action_outputs => copy_action_outputs,
80
+ :old_version => old_version.id)
72
81
  promote(new_content_view_version, environments)
73
82
  end
74
83
  end
75
84
 
85
+ def pulp3_content_mapping(content)
86
+ units = ::Katello::Erratum.with_identifiers(content[:errata_ids]) +
87
+ ::Katello::Rpm.with_identifiers(content[:package_ids])
88
+ unit_map = { :errata => [], :rpms => [] }
89
+ units.each do |unit|
90
+ if unit.class.name == "Katello::Erratum"
91
+ unit_map[:errata] << unit.id
92
+ elsif unit.class.name == "Katello::Rpm"
93
+ unit_map[:rpms] << unit.id
94
+ end
95
+ end
96
+ unit_map
97
+ end
98
+
99
+ def pulp3_repo_mapping(repo_mapping, old_version)
100
+ pulp3_repo_mapping = {}
101
+ repo_mapping.each do |source_repo, dest_repo|
102
+ source_repo = source_repo.first.library_instance? ? source_repo : [source_repo.first.library_instance]
103
+ pulp3_repo_mapping[source_repo.first.id] = { dest_repo: dest_repo.id,
104
+ base_version: pulp3_dest_base_version(
105
+ ::Katello::ContentViewVersion.find(old_version.id), dest_repo) }
106
+ end
107
+ pulp3_repo_mapping
108
+ end
109
+
76
110
  def repos_to_copy(old_version, new_components)
77
111
  old_version.archived_repos.map do |source_repo|
78
112
  components_repo_instances(source_repo, new_components)
@@ -142,22 +176,46 @@ module Actions
142
176
  ::Katello::PuppetModule::CONTENT_TYPE => []
143
177
  }
144
178
 
145
- input[:copy_action_outputs].each do |copy_output|
146
- copy_output[:pulp_tasks].each do |pulp_task|
147
- pulp_task[:result][:units_successful].each do |unit|
148
- type = unit['type_id']
149
- unit = unit['unit_key']
150
- case type
151
- when ::Katello::Erratum::CONTENT_TYPE
152
- content[::Katello::Erratum::CONTENT_TYPE] << unit['id']
153
- when ::Katello::ModuleStream::CONTENT_TYPE
154
- content[::Katello::ModuleStream::CONTENT_TYPE] << "#{unit['name']}:#{unit['stream']}:#{unit['version']}"
155
- when ::Katello::Rpm::CONTENT_TYPE
156
- content[::Katello::Rpm::CONTENT_TYPE] << ::Katello::Util::Package.build_nvra(unit)
157
- when ::Katello::Deb::CONTENT_TYPE
158
- content[::Katello::Deb::CONTENT_TYPE] << "#{unit['name']}_#{unit['version']}_#{unit['architecture']}"
159
- when ::Katello::PuppetModule::CONTENT_TYPE
160
- content[::Katello::PuppetModule::CONTENT_TYPE] << "#{unit['author']}-#{unit['name']}-#{unit['version']}"
179
+ base_repos = ::Katello::ContentViewVersion.find(input[:old_version]).repositories
180
+ new_repos = ::Katello::ContentViewVersion.find(input[:new_content_view_version_id]).repositories
181
+
182
+ if input[:copy_action_outputs].last[:pulp_tasks].last[:pulp_href]&.include?("/pulp/api/v3/")
183
+ new_repos.each do |new_repo|
184
+ matched_old_repo = base_repos.where(root_id: new_repo.root_id).first
185
+
186
+ new_errata = new_repo.errata - matched_old_repo.errata
187
+ new_module_streams = new_repo.module_streams - matched_old_repo.module_streams
188
+ new_rpms = new_repo.rpms - matched_old_repo.rpms
189
+
190
+ new_errata.each do |erratum|
191
+ content[::Katello::Erratum::CONTENT_TYPE] << erratum.errata_id
192
+ end
193
+ new_module_streams.each do |module_stream|
194
+ content[::Katello::ModuleStream::CONTENT_TYPE] <<
195
+ "#{module_stream.name}:#{module_stream.stream}:#{module_stream.version}"
196
+ end
197
+ new_rpms.each do |rpm|
198
+ content[::Katello::Rpm::CONTENT_TYPE] << rpm.nvra
199
+ end
200
+ end
201
+ else
202
+ input[:copy_action_outputs].each do |copy_output|
203
+ copy_output[:pulp_tasks].each do |pulp_task|
204
+ pulp_task[:result][:units_successful].each do |unit|
205
+ type = unit['type_id']
206
+ unit = unit['unit_key']
207
+ case type
208
+ when ::Katello::Erratum::CONTENT_TYPE
209
+ content[::Katello::Erratum::CONTENT_TYPE] << unit['id']
210
+ when ::Katello::ModuleStream::CONTENT_TYPE
211
+ content[::Katello::ModuleStream::CONTENT_TYPE] << "#{unit['name']}:#{unit['stream']}:#{unit['version']}"
212
+ when ::Katello::Rpm::CONTENT_TYPE
213
+ content[::Katello::Rpm::CONTENT_TYPE] << ::Katello::Util::Package.build_nvra(unit)
214
+ when ::Katello::Deb::CONTENT_TYPE
215
+ content[::Katello::Deb::CONTENT_TYPE] << "#{unit['name']}_#{unit['version']}_#{unit['architecture']}"
216
+ when ::Katello::PuppetModule::CONTENT_TYPE
217
+ content[::Katello::PuppetModule::CONTENT_TYPE] << "#{unit['author']}-#{unit['name']}-#{unit['version']}"
218
+ end
161
219
  end
162
220
  end
163
221
  end
@@ -174,10 +232,12 @@ module Actions
174
232
  history.status = ::Katello::ContentViewHistory::SUCCESSFUL
175
233
  history.save!
176
234
 
177
- version.repositories.each do |repo|
178
- SmartProxy.pulp_master.pulp_api.extensions.send(:module_default).
179
- copy(repo.library_instance.pulp_id,
180
- repo.pulp_id)
235
+ unless SmartProxy.pulp_master.pulp3_support?(version.repositories.first)
236
+ version.repositories.each do |repo|
237
+ SmartProxy.pulp_master.pulp_api.extensions.send(:module_default).
238
+ copy(repo.library_instance.pulp_id,
239
+ repo.pulp_id)
240
+ end
181
241
  end
182
242
  end
183
243
 
@@ -255,6 +315,10 @@ module Actions
255
315
  copy_outputs
256
316
  end
257
317
 
318
+ def pulp3_dest_base_version(old_cvv, new_repo)
319
+ old_cvv.repositories.archived.find_by(root_id: new_repo.root_id).version_href.split("/")[-1].to_i
320
+ end
321
+
258
322
  def copy_yum_content(new_repo, dep_solve, package_ids, errata_ids)
259
323
  copy_outputs = []
260
324
  if new_repo.content_type == ::Katello::Repository::YUM_TYPE
@@ -74,6 +74,7 @@ module Actions
74
74
  end
75
75
 
76
76
  def cancel!
77
+ output[:cancelled] = true
77
78
  cancel
78
79
  self.external_task = poll_external_task
79
80
  # We suspend the action and the polling will take care of finding
@@ -26,6 +26,14 @@ module Actions
26
26
  self.done? ? 1 : 0.1
27
27
  end
28
28
 
29
+ def rescue_strategy_for_self
30
+ if output[:cancelled]
31
+ Dynflow::Action::Rescue::Fail
32
+ else
33
+ Dynflow::Action::Rescue::Skip
34
+ end
35
+ end
36
+
29
37
  def run_progress_weight
30
38
  100
31
39
  end
@@ -54,11 +54,11 @@ module Actions
54
54
  end
55
55
 
56
56
  def items_done
57
- task_details&.inject(0) { |sum, details| sum + details[:num_success].to_i }
57
+ task_details&.inject(0) { |sum, details| sum + details[:num_success].to_i } || 0
58
58
  end
59
59
 
60
60
  def items_total
61
- task_details&.inject(0) { |sum, details| sum + details[:items_total].to_i }
61
+ task_details&.inject(0) { |sum, details| sum + details[:items_total].to_i } || 0
62
62
  end
63
63
 
64
64
  def size_done
@@ -0,0 +1,48 @@
1
+ module Actions
2
+ module Pulp3
3
+ module Repository
4
+ class MultiCopyUnits < Pulp3::AbstractAsyncTask
5
+ # repo_map example: {
6
+ # <source_repo_id>: {
7
+ # dest_repo: <dest_repo_id>,
8
+ # base_version: <base_version>
9
+ # }
10
+ # }
11
+ def plan(repo_map, unit_map, options = {})
12
+ if unit_map.values.flatten.any?
13
+ action_output = plan_self(repo_map: repo_map,
14
+ unit_map: unit_map,
15
+ dependency_solving: options[:dependency_solving],
16
+ incremental_update: options[:incremental_update],
17
+ smart_proxy_id: SmartProxy.pulp_master.id).output
18
+ plan_action(Pulp3::Repository::SaveVersions, repo_map.values.pluck(:dest_repo),
19
+ tasks: action_output[:pulp_tasks]).output
20
+ end
21
+ end
22
+
23
+ def invoke_external_task
24
+ unit_hrefs = []
25
+ repo_map = input[:repo_map]
26
+
27
+ if input[:unit_map][:errata].any?
28
+ unit_hrefs << ::Katello::RepositoryErratum.
29
+ joins("inner join katello_errata on katello_repository_errata.erratum_id = katello_errata.id").
30
+ where("katello_repository_errata.repository_id in (#{repo_map.keys.join(',')}) and
31
+ katello_errata.id in (#{input[:unit_map][:errata].join(",")})").map(&:erratum_pulp3_href)
32
+ end
33
+
34
+ if input[:unit_map][:rpms].any?
35
+ unit_hrefs << ::Katello::Rpm.where(:id => input[:unit_map][:rpms]).map(&:pulp_id)
36
+ end
37
+
38
+ # TODO: Fix this workaround by refactoring copy_units after general content view dep solving is refactored
39
+ source_repo = ::Katello::Repository.find(repo_map.keys.first)
40
+ target_repo = ::Katello::Repository.find(repo_map.values.first[:dest_repo])
41
+ dest_base_version = repo_map.values.first[:base_version]
42
+ repo_map.delete(repo_map.keys.first)
43
+ output[:pulp_tasks] = target_repo.backend_service(SmartProxy.pulp_master).copy_units(source_repo, unit_hrefs.flatten, input[:dependency_solving], dest_base_version, repo_map)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ module Actions
2
+ module Pulp3
3
+ module Repository
4
+ class SaveVersions < Pulp3::Abstract
5
+ def plan(repository_ids, options)
6
+ plan_self(:repository_ids => repository_ids, :tasks => options[:tasks])
7
+ end
8
+
9
+ def run
10
+ version_hrefs = input[:tasks].last[:created_resources]
11
+ repositories = input[:repository_ids].collect do |repo_id|
12
+ ::Katello::Repository.find(repo_id)
13
+ end
14
+
15
+ output[:contents_changed] = false
16
+ output[:updated_repositories] = []
17
+ repositories.each do |repo|
18
+ # Chop off the version number to compare base repo strings
19
+ unversioned_href = repo.version_href[0..-2].rpartition('/').first
20
+ new_version_href = version_hrefs.detect do |version_href|
21
+ unversioned_href == version_href[0..-2].rpartition('/').first
22
+ end
23
+ # Successive incremental updates won't generate a new repo version, so fetch the latest Pulp 3 repo version
24
+ new_version_href ||= ::Katello::Pulp3::Api::Yum.new(SmartProxy.pulp_master!).
25
+ repositories_api.read(repo.backend_service(SmartProxy.pulp_master).
26
+ repository_reference.repository_href).latest_version_href
27
+
28
+ unless new_version_href == repo.version_href
29
+ repo.update(version_href: new_version_href)
30
+ repo.index_content
31
+ output[:contents_changed] = true
32
+ output[:updated_repositories] << repo.id
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -3,20 +3,6 @@ module Katello
3
3
  module BaseTemplateScopeExtensions
4
4
  extend ActiveSupport::Concern
5
5
 
6
- module Overrides
7
- def allowed_helpers
8
- super + [:errata, :host_subscriptions, :host_applicable_errata_ids, :host_applicable_errata_filtered,
9
- :host_latest_applicable_rpm_version, :load_pools, :load_errata_applications, :host_content_facet,
10
- :host_sla, :host_products, :sub_name, :sub_sku, :registered_through, :last_checkin, :host_collections,
11
- :host_subscriptions_names, :host_subscriptions, :host_products_names, :host_collections_names,
12
- :host_redhat_subscription_names, :registered_at]
13
- end
14
- end
15
-
16
- included do
17
- prepend Overrides
18
- end
19
-
20
6
  def errata(id)
21
7
  Katello::Erratum.in_repositories(Katello::Repository.readable).with_identifiers(id).map(&:attributes).first.slice!('created_at', 'updated_at')
22
8
  end
@@ -90,6 +90,7 @@ module Katello
90
90
  def pulp_counts_differ?
91
91
  pulp_counts = pulp_repo_facts[:content_unit_counts]
92
92
  rpms.count != pulp_counts['rpm'].to_i ||
93
+ srpms.count != pulp_counts['srpm'].to_i ||
93
94
  errata.count != pulp_counts['erratum'].to_i ||
94
95
  package_groups.count != pulp_counts['package_group'].to_i ||
95
96
  puppet_modules.count != pulp_counts['puppet_module'].to_i ||
@@ -47,11 +47,13 @@ module Katello
47
47
  bindable_paths = bindable_types
48
48
  relative_paths = []
49
49
 
50
- paths.each do |path|
50
+ # paths == ["/pulp/repos/Default_Organization/Library/custom/Test_product/test2",
51
+ # "/pulp/repos/Default_Organization/Library/custom/Test_product/My_repo"]
52
+ paths.each do |absolute_path|
51
53
  bindable_paths.each do |supported|
52
- relative_path = path.gsub(supported[:matcher], '')
53
- relative_paths << relative_path
54
- if path.starts_with?(supported[:matcher])
54
+ relative_path = absolute_path.gsub(supported[:matcher], '') # remove e.g. '/pulp/repos/' from beginning of string
55
+ relative_paths << relative_path unless relative_path == absolute_path
56
+ if absolute_path.starts_with?(supported[:matcher])
55
57
  supported[:paths] << relative_path
56
58
  break
57
59
  end
@@ -60,10 +62,12 @@ module Katello
60
62
 
61
63
  repos = bindable_paths.flat_map do |supported|
62
64
  repos = Repository.joins(:root).where(RootRepository.table_name => {content_type: supported[:type]}, relative_path: supported[:paths])
63
- relative_paths -= repos.pluck(:relative_path)
65
+ relative_paths -= repos.pluck(:relative_path) # remove relative paths that match our repos
64
66
  repos
65
67
  end
66
68
 
69
+ # Any leftover relative paths do not match the repos we've just retrieved from the db,
70
+ # so we should log warnings about them.
67
71
  relative_paths.each do |repo_path|
68
72
  Rails.logger.warn("System #{self.host.name} (#{self.host.id}) requested binding to unknown repo #{repo_path}")
69
73
  end
@@ -121,6 +125,7 @@ module Katello
121
125
  ::Katello::Applicability::ApplicableContentHelper.new(self, ::Katello::Rpm, bound_repos).calculate_and_import
122
126
  ::Katello::Applicability::ApplicableContentHelper.new(self, ::Katello::Erratum, bound_repos).calculate_and_import
123
127
  ::Katello::Applicability::ApplicableContentHelper.new(self, ::Katello::ModuleStream, bound_repos).calculate_and_import
128
+ update_applicability_counts
124
129
  end
125
130
 
126
131
  def import_applicability(partial = false)
@@ -2,7 +2,7 @@ class Setting::Content < Setting
2
2
  #rubocop:disable Metrics/MethodLength
3
3
  #rubocop:disable Metrics/AbcSize
4
4
 
5
- validate :content_default_http_proxy, if: proc { |s| s.name == 'content_default_http_proxy' }
5
+ validate :content_default_http_proxy, if: proc { |s| s.name == 'content_default_http_proxy' && HttpProxy.table_exists? }
6
6
 
7
7
  after_save :add_organizations_and_locations_if_global_http_proxy
8
8
 
@@ -91,6 +91,8 @@ class Setting::Content < Setting
91
91
  false, N_('Restrict Composite Content View promotion')),
92
92
  self.set('check_services_before_actions', N_("Whether or not to check the status of backend services such as pulp and candlepin prior to performing some actions."),
93
93
  true, N_('Check services before actions')),
94
+ self.set('foreman_proxy_content_batch_size', N_("How many repositories should be synced concurrently on the capsule. A smaller number may lead to longer sync times. A larger number will increase dynflow load."),
95
+ 25, N_('Batch size to sync repositories in.')),
94
96
  self.set('foreman_proxy_content_auto_sync', N_("Whether or not to auto sync the Smart Proxies after a Content View promotion."),
95
97
  true, N_('Sync Smart Proxies after Content View promotion')),
96
98
  self.set('default_download_policy', N_("Default download policy for custom repositories (either 'immediate', 'on_demand', or 'background')"), "immediate",
@@ -70,28 +70,54 @@ module Katello
70
70
  "/pulp/repos/#{repo.relative_path}/".sub('//', '/')
71
71
  end
72
72
 
73
- def copy_units(source_repository_version_href, content_unit_hrefs, dependency_solving)
73
+ def copy_units(source_repository, content_unit_hrefs, dependency_solving, dest_base_version = 0,
74
+ additional_repo_map = {})
74
75
  tasks = []
75
76
 
77
+ content_unit_hrefs.sort!
76
78
  if content_unit_hrefs.any?
77
79
  data = PulpRpmClient::Copy.new
78
- data.config = [
79
- source_repo_version: source_repository_version_href,
80
+ data.config = [{
81
+ source_repo_version: source_repository.version_href,
80
82
  dest_repo: repository_reference.repository_href,
81
- dest_base_version: 0,
82
- content: content_unit_hrefs.sort
83
- ]
83
+ dest_base_version: dest_base_version,
84
+ content: content_unit_hrefs
85
+ }]
84
86
  data.dependency_solving = dependency_solving
87
+ if dependency_solving
88
+ # repo_map example: {
89
+ # <source_repo_id>: {
90
+ # dest_repo: <dest_repo_id>,
91
+ # base_version: <base_version>
92
+ # }
93
+ # }
94
+ additional_repo_map.each do |source_repo, dest_repo_map|
95
+ source_repo_version = ::Katello::Repository.find(source_repo).version_href
96
+
97
+ dest_repo = ::Katello::Repository.find(dest_repo_map[:dest_repo])
98
+ dest_repo_href = ::Katello::Pulp3::Repository::Yum.new(dest_repo, SmartProxy.pulp_master).repository_reference.repository_href
99
+ data.config << {
100
+ source_repo_version: source_repo_version,
101
+ dest_repo: dest_repo_href,
102
+ dest_base_version: dest_repo_map[:base_version],
103
+ content: content_unit_hrefs
104
+ }
105
+ end
106
+ end
85
107
  tasks << api.copy_api.copy_content(data)
86
108
  else
87
- data = PulpRpmClient::RepositoryAddRemoveContent.new(
88
- remove_content_units: ['*'])
89
- tasks << api.repositories_api.modify(repository_reference.repository_href, data)
109
+ tasks << remove_all_content
90
110
  end
91
111
 
92
112
  tasks
93
113
  end
94
114
 
115
+ def remove_all_content
116
+ data = PulpRpmClient::RepositoryAddRemoveContent.new(
117
+ remove_content_units: ['*'])
118
+ api.repositories_api.modify(repository_reference.repository_href, data)
119
+ end
120
+
95
121
  def packageenvironments(options = {})
96
122
  api.content_package_environments_api.list(options)
97
123
  end
@@ -133,7 +159,7 @@ module Katello
133
159
  content_unit_hrefs += source_repository.srpms.pluck(:pulp_id)
134
160
 
135
161
  dependency_solving = options[:solve_dependencies] || false
136
- copy_units(source_repository.version_href, content_unit_hrefs.uniq, dependency_solving)
162
+ copy_units(source_repository, content_unit_hrefs.uniq, dependency_solving)
137
163
  end
138
164
 
139
165
  def additional_content_hrefs(source_repository, content_unit_hrefs)
@@ -158,11 +184,6 @@ module Katello
158
184
  repo_service.distributiontrees(options).results, content_unit_hrefs)
159
185
  content_unit_hrefs + distribution_tree_hrefs_to_include
160
186
  end
161
-
162
- def regenerate_applicability
163
- # TODO
164
- fail NotImplementedError
165
- end
166
187
  end
167
188
  end
168
189
  end
@@ -9,7 +9,7 @@
9
9
  */
10
10
  angular.module('Bastion.errata').config(['$stateProvider', function ($stateProvider) {
11
11
  $stateProvider.state('errata', {
12
- url: '/errata',
12
+ url: '/errata?repositoryId',
13
13
  permission: ['view_products', 'view_content_views'],
14
14
  views: {
15
15
  '@': {
@@ -67,4 +67,8 @@
67
67
 
68
68
  .popover-large {
69
69
  max-width: 100%;
70
+ }
71
+
72
+ .uib-increment, .uib-decrement {
73
+ text-align: center;
70
74
  }
@@ -154,7 +154,6 @@ module Katello
154
154
 
155
155
  # Lib Extensions
156
156
  ::Foreman::Renderer::Scope::Variables::Base.include Katello::Concerns::RendererExtensions
157
- ::Foreman::Renderer::Scope::Base.include Katello::Concerns::BaseTemplateScopeExtensions
158
157
 
159
158
  # Model extensions
160
159
  ::Environment.include Katello::Concerns::EnvironmentExtensions
@@ -220,6 +220,8 @@ Foreman::Plugin.register :katello do
220
220
 
221
221
  allowed_template_helpers :subscription_manager_configuration_url, :repository_url
222
222
  extend_template_helpers Katello::KatelloUrlsHelper
223
+ extend_template_helpers Katello::Concerns::BaseTemplateScopeExtensions
224
+
223
225
  register_global_js_file 'fills'
224
226
 
225
227
  search_path_override("Katello") do |resource|
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.16.0.rc4".freeze
2
+ VERSION = "3.16.0.rc4.1".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katello
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.16.0.rc4
4
+ version: 3.16.0.rc4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - N/A
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-01 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -699,6 +699,7 @@ files:
699
699
  - app/controllers/katello/application_controller.rb
700
700
  - app/controllers/katello/auto_complete_search_controller.rb
701
701
  - app/controllers/katello/concerns/api/api_controller.rb
702
+ - app/controllers/katello/concerns/api/v2/associations_permission_check.rb
702
703
  - app/controllers/katello/concerns/api/v2/bulk_hosts_extensions.rb
703
704
  - app/controllers/katello/concerns/api/v2/content_overrides_controller.rb
704
705
  - app/controllers/katello/concerns/api/v2/hostgroups_controller_extensions.rb
@@ -1014,6 +1015,7 @@ files:
1014
1015
  - app/lib/actions/pulp3/repository/delete_remote.rb
1015
1016
  - app/lib/actions/pulp3/repository/delete_version.rb
1016
1017
  - app/lib/actions/pulp3/repository/import_upload.rb
1018
+ - app/lib/actions/pulp3/repository/multi_copy_units.rb
1017
1019
  - app/lib/actions/pulp3/repository/presenters/abstract_sync_presenter.rb
1018
1020
  - app/lib/actions/pulp3/repository/presenters/content_unit_presenter.rb
1019
1021
  - app/lib/actions/pulp3/repository/refresh_distribution.rb
@@ -1022,6 +1024,7 @@ files:
1022
1024
  - app/lib/actions/pulp3/repository/save_distribution_references.rb
1023
1025
  - app/lib/actions/pulp3/repository/save_publication.rb
1024
1026
  - app/lib/actions/pulp3/repository/save_version.rb
1027
+ - app/lib/actions/pulp3/repository/save_versions.rb
1025
1028
  - app/lib/actions/pulp3/repository/sync.rb
1026
1029
  - app/lib/actions/pulp3/repository/update_cv_repository_cert_guard.rb
1027
1030
  - app/lib/actions/pulp3/repository/update_distributions.rb