katello 3.18.0 → 3.18.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 (19) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +2 -1
  3. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +7 -2
  4. data/app/lib/actions/katello/content_view_version/incremental_update.rb +19 -3
  5. data/app/lib/actions/middleware/record_smart_proxy_sync_history.rb +24 -4
  6. data/app/lib/actions/pulp3/orchestration/content_view_version/export.rb +4 -2
  7. data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +0 -4
  8. data/app/models/katello/concerns/pulp_database_unit.rb +7 -0
  9. data/app/models/katello/host/subscription_facet.rb +4 -0
  10. data/app/models/katello/subscription_status.rb +3 -2
  11. data/app/services/katello/applicability/applicable_content_helper.rb +12 -1
  12. data/app/services/katello/pulp3/content_view_version/import_validator.rb +0 -30
  13. data/app/views/katello/api/v2/content_views/show.json.rabl +6 -0
  14. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/deletion/content-view-version-deletion-activation-keys.controller.js +8 -3
  15. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/deletion/content-view-version-deletion-content-hosts.controller.js +9 -3
  16. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-details.html +1 -1
  17. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-publish.html +4 -0
  18. data/lib/katello/version.rb +1 -1
  19. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dbd0716cd63dcfb9f135e084f2dcd07401019b45f4a0c6c4f61ddf0953fbb00b
4
- data.tar.gz: d7ae76869fc68b2046637b8eb116f9f23048b0f5dce7042b3c65d77556d9d7c4
3
+ metadata.gz: 78239ba1e921e408588db439d4b929151e1a9c10408e23c63f0ec5c76a23c66b
4
+ data.tar.gz: f945779353ab8cedce6a30e33f5ac4a264f6790e486a00126f15d3862babdfce
5
5
  SHA512:
6
- metadata.gz: b86b93fe297e88ea9c5bac35ae1dbc746ffd2ddcbfdd06046552cef774153182ab5938483ff6663d6d382613603066ede7a0cccc99386d3def6c63db46194f2b
7
- data.tar.gz: 3813c0ec50e517fbe18575d033322e0ee7df5f63b5aad7abe514e62eda523339e6f3d9a54c1734e5fdc07031217fff59ece0dc17b4d02f1e28b86db93dbb13dd
6
+ metadata.gz: f5526ccfbae423e0315e89349253756acf60bb920c9e3f1e2b7f581f677312e19d0141a185f58adeea0b08dc4d1a2d323bd051404c6c0d54faedd06ed5667427
7
+ data.tar.gz: 5f7d476d2061439219dc468b5ead1291835fe68bfacf1396b54db46f3e9afe3ca13c3383e5d5ce92f1d07c76ab5a0f59cffa78cda0c9500345dc5813c6ea24dc
@@ -267,8 +267,9 @@ module Katello
267
267
  api :POST, "/hosts/bulk/available_incremental_updates", N_("Given a set of hosts and errata, lists the content view versions" \
268
268
  " and environments that need updating.")
269
269
  param_group :bulk_params
270
- param :errata_ids, Array, :desc => N_("List of Errata ids")
270
+ param :errata_ids, Array, :desc => N_("List of Errata ids"), :required => true
271
271
  def available_incremental_updates
272
+ fail HttpErrors::BadRequest, _("errata_ids is a required parameter") if params[:errata_ids].empty?
272
273
  version_environments = {}
273
274
  content_facets = Katello::Host::ContentFacet.with_non_installable_errata(@errata, @hosts)
274
275
 
@@ -19,9 +19,14 @@ module Actions
19
19
  Actions::Pulp3::CapsuleContent::Sync],
20
20
  repo, smart_proxy,
21
21
  skip_metadata_check: skip_metadata_check)
22
+ end
23
+ end
24
+
25
+ concurrence do
26
+ repo_batch.each do |repo|
22
27
  if repo.is_a?(::Katello::Repository) &&
23
- repo.distribution_bootable? &&
24
- repo.download_policy == ::Runcible::Models::YumImporter::DOWNLOAD_ON_DEMAND
28
+ repo.distribution_bootable? &&
29
+ repo.download_policy == ::Runcible::Models::YumImporter::DOWNLOAD_ON_DEMAND
25
30
  plan_action(Katello::Repository::FetchPxeFiles,
26
31
  id: repo.id,
27
32
  capsule_id: smart_proxy.id)
@@ -352,20 +352,36 @@ module Actions
352
352
  end
353
353
 
354
354
  def copy_yum_content(new_repo, dep_solve, package_ids, errata_ids)
355
+ return [] unless new_repo.content_type == ::Katello::Repository::YUM_TYPE
356
+
355
357
  copy_outputs = []
356
- if new_repo.content_type == ::Katello::Repository::YUM_TYPE
357
- unless errata_ids.blank?
358
+
359
+ unless errata_ids.blank?
360
+ content_present_in_this_repo = new_repo
361
+ .library_instance
362
+ .errata
363
+ .with_identifiers(errata_ids)
364
+ .exists?
365
+ if content_present_in_this_repo
358
366
  copy_outputs << plan_action(Pulp::Repository::CopyUnits, new_repo.library_instance, new_repo,
359
367
  ::Katello::Erratum.with_identifiers(errata_ids),
360
368
  incremental_update: dep_solve).output
361
369
  end
370
+ end
362
371
 
363
- unless package_ids.blank?
372
+ unless package_ids.blank?
373
+ content_present_in_this_repo = new_repo
374
+ .library_instance
375
+ .rpms
376
+ .with_identifiers(package_ids)
377
+ .exists?
378
+ if content_present_in_this_repo
364
379
  copy_outputs << plan_action(Pulp::Repository::CopyUnits, new_repo.library_instance, new_repo,
365
380
  ::Katello::Rpm.with_identifiers(package_ids),
366
381
  incremental_update: dep_solve).output
367
382
  end
368
383
  end
384
+
369
385
  copy_outputs
370
386
  end
371
387
 
@@ -1,12 +1,32 @@
1
1
  module Actions
2
2
  module Middleware
3
3
  class RecordSmartProxySyncHistory < Dynflow::Middleware
4
- def run(*args)
4
+ def save_smart_proxy_sync_history
5
5
  if (action.input[:repository_id] && (action.input[:smart_proxy_id] || action.input[:capsule_id]) && !self.action.output[:smart_proxy_history_id])
6
- repo = ::Katello::Repository.find(action.input[:repository_id])
6
+ repo_id = action.input[:repository_id]
7
+ repo = ::Katello::Repository.find_by(id: repo_id)
7
8
  smart_proxy_id = action.input[:smart_proxy_id] || action.input[:capsule_id]
8
- smart_proxy = ::SmartProxy.find(smart_proxy_id)
9
- self.action.output[:smart_proxy_history_id] = repo.create_smart_proxy_sync_history(smart_proxy)
9
+ smart_proxy = ::SmartProxy.find_by(id: smart_proxy_id)
10
+
11
+ #skip pulp2 puppet syncs
12
+ if (repo_pulp_id = action.input[:repo_pulp_id])
13
+ return if ::Katello::ContentViewPuppetEnvironment.find_by(pulp_id: repo_pulp_id)
14
+ end
15
+
16
+ if repo && smart_proxy
17
+ self.action.output[:smart_proxy_history_id] = repo.create_smart_proxy_sync_history(smart_proxy)
18
+ else
19
+ fail "Smart Proxy could not be found with id #{smart_proxy_id}" if smart_proxy.nil?
20
+ fail "Repository could not be found with id #{repo_id}" if repo.nil?
21
+ end
22
+ end
23
+ end
24
+
25
+ def run(*args)
26
+ begin
27
+ save_smart_proxy_sync_history
28
+ rescue => error
29
+ Rails.logger.error("Error saving smart proxy history: #{error.message}")
10
30
  end
11
31
  pass(*args)
12
32
  end
@@ -76,8 +76,10 @@ module Actions
76
76
  content_view_version: cvv,
77
77
  smart_proxy: smart_proxy,
78
78
  from_content_view_version: from_cvv).generate_metadata
79
- toc = Dir.glob("#{path}/*toc.json").first
80
- export_metadata[:toc] = File.basename(toc) if toc
79
+
80
+ toc_path_info = output[:exported_file_checksum].find { |item| item.first.end_with?("toc.json") }
81
+ export_metadata[:toc] = File.basename(toc_path_info.first)
82
+
81
83
  history = ::Katello::ContentViewVersionExportHistory.create!(
82
84
  content_view_version_id: input[:content_view_version_id],
83
85
  destination_server: input[:destination_server],
@@ -36,10 +36,6 @@ module Actions
36
36
  def humanized_name
37
37
  _("Import")
38
38
  end
39
-
40
- def rescue_strategy
41
- Dynflow::Action::Rescue::Skip
42
- end
43
39
  end
44
40
  end
45
41
  end
@@ -91,6 +91,13 @@ module Katello
91
91
  service_class.pulp_units_batch_all(pulp_ids).each do |units|
92
92
  units.each do |unit|
93
93
  unit = unit.with_indifferent_access
94
+ if content_type == 'rpm' && repository
95
+ rpms_to_disassociate = ::Katello::Rpm.where(name: unit[:name], version: unit[:version], release: unit[:release],
96
+ epoch: unit[:epoch], arch: unit[:arch]).select(:id)
97
+ if rpms_to_disassociate.any?
98
+ ::Katello::RepositoryRpm.where(rpm_id: rpms_to_disassociate, repository_id: repository.id).destroy_all
99
+ end
100
+ end
94
101
  model = Katello::Util::Support.active_record_retry do
95
102
  self.where(:pulp_id => unit[service_class.unit_identifier]).first_or_create
96
103
  end
@@ -282,6 +282,10 @@ module Katello
282
282
  name.gsub('_', '-').chomp('.').downcase
283
283
  end
284
284
 
285
+ def unsubscribed_hypervisor?
286
+ self.hypervisor && !self.candlepin_consumer.entitlements?
287
+ end
288
+
285
289
  def candlepin_consumer
286
290
  @candlepin_consumer ||= Katello::Candlepin::Consumer.new(self.uuid, self.host.organization.label)
287
291
  end
@@ -43,9 +43,10 @@ module Katello
43
43
 
44
44
  def to_status(options = {})
45
45
  return UNKNOWN unless host.subscription_facet.try(:uuid)
46
- status_override = 'unsubscribed_hypervisor' if host.subscription_facet.hypervisor && !host.subscription_facet.candlepin_consumer.entitlements?
46
+ return DISABLED if host.organization.simple_content_access?
47
+ status_override = 'unsubscribed_hypervisor' if host.subscription_facet.unsubscribed_hypervisor?
47
48
  status_override ||= options.fetch(:status_override, nil)
48
- status = status_override || Katello::Candlepin::Consumer.new(host.subscription_facet.uuid, host.organization.label).entitlement_status
49
+ status = status_override || host.subscription_facet.candlepin_consumer.entitlement_status
49
50
 
50
51
  case status
51
52
  when Katello::Candlepin::Consumer::ENTITLEMENTS_DISABLED
@@ -78,7 +78,8 @@ module Katello
78
78
  joins("INNER JOIN katello_installed_packages ON
79
79
  katello_rpms.name = katello_installed_packages.name AND
80
80
  katello_rpms.arch = katello_installed_packages.arch AND
81
- katello_rpms.evr > katello_installed_packages.evr").
81
+ katello_rpms.evr > katello_installed_packages.evr AND
82
+ katello_installed_packages.id in (#{newest_distinct_installed_packages_query})").
82
83
  joins("LEFT JOIN katello_module_stream_rpms ON
83
84
  katello_rpms.id = katello_module_stream_rpms.rpm_id").
84
85
  joins("INNER JOIN katello_host_installed_packages ON
@@ -92,6 +93,16 @@ module Katello
92
93
  :enabled_module_streams => enabled_module_stream_ids).pluck(:id).uniq
93
94
  end
94
95
 
96
+ def newest_distinct_installed_packages_query
97
+ "SELECT DISTINCT ON (katello_installed_packages.name) katello_installed_packages.id " \
98
+ "FROM katello_installed_packages INNER JOIN " \
99
+ "katello_host_installed_packages ON " \
100
+ "katello_installed_packages.id = " \
101
+ "katello_host_installed_packages.installed_package_id " \
102
+ "WHERE katello_host_installed_packages.host_id = " \
103
+ "#{content_facet.host.id} ORDER BY katello_installed_packages.name, katello_installed_packages.evr DESC"
104
+ end
105
+
95
106
  def applicable_differences
96
107
  consumer_ids = content_facet.send(applicable_units).pluck("#{content_unit_class.table_name}.id")
97
108
  content_ids = fetch_content_ids
@@ -2,7 +2,6 @@ module Katello
2
2
  module Pulp3
3
3
  module ContentViewVersion
4
4
  class ImportValidator
5
- BASEDIR = '/var/lib/pulp'.freeze
6
5
  attr_accessor :metadata, :path, :content_view
7
6
  def initialize(content_view:, path:, metadata:)
8
7
  self.content_view = content_view
@@ -11,7 +10,6 @@ module Katello
11
10
  end
12
11
 
13
12
  def check!
14
- check_permissions!
15
13
  unless content_view.default?
16
14
  ensure_importing_cvv_does_not_exist!
17
15
  ensure_from_cvv_exists!
@@ -71,34 +69,6 @@ module Katello
71
69
  end
72
70
  end
73
71
 
74
- def check_permissions!
75
- fail _("Invalid path specified.") if path.blank? || !File.directory?(path)
76
- fail _("The import path must be in a subdirectory under '%s'." % BASEDIR) unless path.starts_with?(BASEDIR)
77
- fail _("Pulp user or group unable to read content in '%s'." % path) unless pulp_user_accessible?(path)
78
-
79
- Dir.glob("#{path}/*").each do |file|
80
- fail _("Pulp user or group unable to read '%s'." % file) unless pulp_user_accessible?(file)
81
- end
82
- toc_path = "#{path}/#{metadata[:toc]}"
83
- fail _("The TOC file specified in the metadata does not exist. %s " % toc_path) unless File.exist?(toc_path)
84
- end
85
-
86
- def pulp_user_accessible?(path)
87
- pulp_info = fetch_pulp_user_info
88
- return false if pulp_info.blank?
89
-
90
- stat = File.stat(path)
91
- stat.gid.to_s == pulp_info.gid ||
92
- stat.uid.to_s == pulp_info.uid ||
93
- stat.mode.to_s(8)[-1].to_i >= 4
94
- end
95
-
96
- def fetch_pulp_user_info
97
- pulp_user = nil
98
- Etc.passwd { |u| pulp_user = u if u.name == 'pulp' }
99
- pulp_user
100
- end
101
-
102
72
  def generate_product_repo_i18n_string(product_repos)
103
73
  # product_repos look like [["prod1", "repo1", false], ["prod2", "repo2", false]]
104
74
  product_repos.map do |product, repo, redhat|
@@ -4,6 +4,12 @@ extends "katello/api/v2/content_views/base"
4
4
 
5
5
  attributes :content_host_count
6
6
 
7
+ node :errors do
8
+ unless @resource.valid?
9
+ attribute :messages => @resource.errors.full_messages
10
+ end
11
+ end
12
+
7
13
  child :duplicate_repositories_to_publish => :duplicate_repositories_to_publish do
8
14
  attributes :id, :name
9
15
  node :components do |repo|
@@ -16,16 +16,20 @@
16
16
  angular.module('Bastion.content-views').controller('ContentViewVersionDeletionActivationKeysController',
17
17
  ['$scope', '$location', 'Organization', 'CurrentOrganization', 'Nutupane', 'ActivationKey',
18
18
  function ($scope, $location, Organization, CurrentOrganization, Nutupane, ActivationKey) {
19
- var params, nutupane;
19
+ var params, nutupane, nutupaneParams;
20
20
 
21
21
  $scope.validateEnvironmentSelection();
22
22
  params = {
23
23
  'organization_id': CurrentOrganization,
24
- 'content_view_id': $scope.contentView.id,
25
24
  'sort_by': 'name',
26
25
  'sort_order': 'ASC'
27
26
  };
28
- nutupane = new Nutupane(ActivationKey, params);
27
+
28
+ nutupaneParams = {
29
+ 'disableAutoLoad': true
30
+ };
31
+
32
+ nutupane = new Nutupane(ActivationKey, params, undefined, nutupaneParams);
29
33
  $scope.controllerName = 'katello_activation_keys';
30
34
 
31
35
  nutupane.searchTransform = function (term) {
@@ -43,6 +47,7 @@ angular.module('Bastion.content-views').controller('ContentViewVersionDeletionAc
43
47
 
44
48
  return term + " AND " + addition;
45
49
  };
50
+ nutupane.load();
46
51
 
47
52
  $scope.table = nutupane.table;
48
53
  $scope.table.closeItem = function () {};
@@ -17,16 +17,20 @@ angular.module('Bastion.content-views').controller('ContentViewVersionDeletionCo
17
17
  ['$scope', '$location', 'Organization', 'CurrentOrganization', 'Nutupane', 'Host',
18
18
  function ($scope, $location, Organization, CurrentOrganization, Nutupane, Host) {
19
19
 
20
- var params, nutupane;
20
+ var params, nutupane, nutupaneParams;
21
21
 
22
22
  $scope.validateEnvironmentSelection();
23
23
  params = {
24
24
  'organization_id': CurrentOrganization,
25
- 'content_view_id': $scope.contentView.id,
26
25
  'sort_by': 'name',
27
26
  'sort_order': 'ASC'
28
27
  };
29
- nutupane = new Nutupane(Host, params);
28
+
29
+ nutupaneParams = {
30
+ 'disableAutoLoad': true
31
+ };
32
+
33
+ nutupane = new Nutupane(Host, params, undefined, nutupaneParams);
30
34
  $scope.controllerName = 'hosts';
31
35
 
32
36
  nutupane.searchTransform = function (term) {
@@ -44,6 +48,8 @@ angular.module('Bastion.content-views').controller('ContentViewVersionDeletionCo
44
48
 
45
49
  return term + " AND " + addition;
46
50
  };
51
+
52
+ nutupane.load();
47
53
  $scope.table = nutupane.table;
48
54
  $scope.table.closeItem = function () {};
49
55
 
@@ -13,7 +13,7 @@
13
13
  </div>
14
14
 
15
15
  <nav data-block="item-actions">
16
- <button type="button" class="btn btn-primary" ng-hide="denied('publish_content_views', contentView) || contentView.import_only"
16
+ <button type="button" class="btn btn-primary" ng-hide="denied('publish_content_views', contentView) || contentView.import_only"
17
17
  ui-sref="content-view.publish">
18
18
  <span translate>Publish New Version</span>
19
19
  </button>
@@ -7,6 +7,10 @@
7
7
  It can be promoted to other environments from the Versions tab of this Content View.
8
8
  </p>
9
9
 
10
+ <div bst-alert="warning" ng-show="contentView.errors['messages'].length > 0">
11
+ <span translate>{{contentView.errors['messages'][0]}}</span>
12
+ </div>
13
+
10
14
  <header class="details-header">
11
15
  <h3 translate>Version Details</h3>
12
16
  </header>
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.18.0".freeze
2
+ VERSION = "3.18.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.18.0
4
+ version: 3.18.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-12-10 00:00:00.000000000 Z
11
+ date: 2021-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails