katello 3.15.0.1 → 3.15.3.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 (57) hide show
  1. checksums.yaml +5 -5
  2. data/app/controllers/katello/api/v2/docker_tags_controller.rb +17 -0
  3. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +4 -0
  4. data/app/lib/actions/katello/host/upload_profiles.rb +45 -5
  5. data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +13 -0
  6. data/app/lib/actions/katello/pulp_selector.rb +1 -0
  7. data/app/lib/katello/errors.rb +6 -0
  8. data/app/models/katello/concerns/host_managed_extensions.rb +8 -3
  9. data/app/models/katello/concerns/http_proxy_extensions.rb +30 -7
  10. data/app/models/katello/concerns/smart_proxy_extensions.rb +16 -1
  11. data/app/models/katello/docker_meta_tag.rb +1 -1
  12. data/app/models/katello/installed_package.rb +1 -1
  13. data/app/models/katello/repository.rb +6 -2
  14. data/app/models/katello/root_repository.rb +1 -1
  15. data/app/models/setting/content.rb +1 -1
  16. data/app/services/katello/pulp/simple_package.rb +2 -2
  17. data/app/views/foreman/job_templates/install_errata_-_katello_ansible_default.erb +1 -1
  18. data/app/views/foreman/job_templates/install_group_-_katello_ansible_default.erb +1 -1
  19. data/app/views/foreman/job_templates/remove_group_-_katello_ansible_default.erb +1 -1
  20. data/app/views/foreman/job_templates/update_group_-_katello_ansible_default.erb +1 -1
  21. data/app/views/foreman/job_templates/update_package_-_katello_ansible_default.erb +1 -1
  22. data/app/views/katello/api/v2/docker_tags/_base.json.rabl +1 -1
  23. data/app/views/katello/api/v2/repositories/base.json.rabl +8 -0
  24. data/config/routes/api/v2.rb +3 -0
  25. data/db/migrate/20200429153103_installed_package_bad_nvrea.rb +14 -0
  26. data/db/migrate/20200501155054_installed_package_unique_nvrea.rb +64 -0
  27. data/db/seeds.d/111-upgrade_tasks.rb +2 -1
  28. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/details/docker-tag-environments.controller.js +10 -22
  29. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/details/views/docker-tag-environments.html +6 -6
  30. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/docker-tags.controller.js +8 -0
  31. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/docker-tags.factory.js +1 -1
  32. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/views/docker-tags.html +1 -1
  33. data/lib/katello/permission_creator.rb +6 -1
  34. data/lib/katello/tasks/common.rake +7 -0
  35. data/lib/katello/tasks/delete_orphaned_content.rake +3 -1
  36. data/lib/katello/tasks/pulp3_migration.rake +2 -0
  37. data/lib/katello/tasks/repository.rake +2 -4
  38. data/lib/katello/tasks/upgrades/3.16/update_applicable_el8_hosts.rake +29 -0
  39. data/lib/katello/version.rb +1 -1
  40. data/webpack/components/Content/ContentTable.js +2 -0
  41. data/webpack/components/Content/Details/ContentDetails.js +3 -0
  42. data/webpack/scenes/AnsibleCollections/Details/AnsibleCollectionDetails.js +3 -0
  43. data/webpack/scenes/ModuleStreams/Details/ModuleStreamDetails.js +3 -0
  44. data/webpack/scenes/RedHatRepositories/RedHatRepositoriesPage.js +2 -0
  45. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepository.js +2 -0
  46. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository/RepositorySetRepository.js +2 -0
  47. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailAssociations.js +2 -0
  48. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProductContent.js +2 -0
  49. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +2 -0
  50. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +2 -0
  51. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +3 -0
  52. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +2 -0
  53. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +2 -0
  54. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Dialogs/UpdateDialog.js +1 -1
  55. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Dialogs/index.js +4 -4
  56. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Table.js +2 -0
  57. metadata +24 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 92aa6e8e0a5a914d6c6351cd79438c043c6949bd2a5e045bf200377e9b4ff804
4
- data.tar.gz: b3ce81e811303eb3d96b0db1128579a0c65666c23e072bdb769ce85144870ca4
2
+ SHA1:
3
+ metadata.gz: 1491d165d0f7f2ba0be7ed2d06f792caad8a4a8d
4
+ data.tar.gz: 8d7fac36c88ffd9369b8006634c6458e0413b1e6
5
5
  SHA512:
6
- metadata.gz: d214ba3f5a060b6c83045488b0e83d03ca7e89990ccf5e5bf1f0469b7aa3812e2499fce157ed4a10bffe7d0e20843a85b9d744d3f9c4f0ebdf4a4c61aedcf12a
7
- data.tar.gz: 296802f07b77527a7efcc1181d4b2c05aeaaf55551f0db865f0c5c1e3b45ad9f049189436bb2c1d35769ca7ab5470499d2bad343eb798278120e86328b1fb567
6
+ metadata.gz: 3560ef1c772a5e08504f7aacba65568dc8721ee570c067b4c3e0026f1f308bc3e44812b20226a8b058d577f58bfee12e27f7a95c18ba65097a1388fc16284935
7
+ data.tar.gz: 00f6596ceb566699ca560236991bf71a7e2f48d5e6b9c037ea0078b31d517ac8c4531f76350d87e0170bfdd32f9282436ed82e030acfd0a762c157318d3fb469
@@ -25,6 +25,23 @@ module Katello
25
25
  end
26
26
  end
27
27
 
28
+ api :GET, "/docker_tags/:id/repositories", N_("List of repositories for a docker meta tag")
29
+ def repositories
30
+ tag = DockerMetaTag.find(params[:id])
31
+
32
+ if tag.repositories.size > 1 #pulp3
33
+ repos = tag.repositories.non_archived
34
+ else
35
+ repos = []
36
+ tag.related_tags.each do |related|
37
+ repos << related.repositories.non_archived
38
+ end
39
+ repos.flatten!
40
+ end
41
+
42
+ respond_with_template_collection('index', 'repositories', collection: full_result_response(repos))
43
+ end
44
+
28
45
  private
29
46
 
30
47
  def find_repositories
@@ -31,6 +31,10 @@ module Actions
31
31
  end
32
32
  end
33
33
 
34
+ def resource_locks
35
+ :link
36
+ end
37
+
34
38
  def rescue_strategy
35
39
  Dynflow::Action::Rescue::Skip
36
40
  end
@@ -33,16 +33,51 @@ module Actions
33
33
  Dynflow::Action::Rescue::Skip
34
34
  end
35
35
 
36
+ def self.upload_modules_to_pulp(available_streams, host)
37
+ query_name_streams = available_streams.map do |profile|
38
+ ::Katello::ModuleStream.where(profile.slice(:name, :stream))
39
+ end
40
+
41
+ updated_profiles = []
42
+ unless query_name_streams.empty?
43
+ query_name_streams = query_name_streams.inject(&:or)
44
+
45
+ bound_library_instances = host.content_facet.bound_repositories.map(&:library_instance_or_self)
46
+ query = ::Katello::ModuleStream.in_repositories(bound_library_instances).
47
+ select(:name, :stream, :version, :context, :arch).
48
+ merge(query_name_streams)
49
+
50
+ updated_profiles = query.map do |module_stream|
51
+ module_stream.slice(:name, :stream, :version, :context, :arch)
52
+ end
53
+ end
54
+
55
+ # We also need to pass module streams that are not found in the ModuleStream table
56
+ # but are present on the content host
57
+ unassociated_profiles = available_streams.select do |profile|
58
+ updated_profiles.none? { |p| p[:name] == profile[:name] && p[:stream] == profile[:stream] }
59
+ end
60
+
61
+ module_stream_profile = updated_profiles + unassociated_profiles
62
+
63
+ unless module_stream_profile.empty?
64
+ begin
65
+ ::Katello::Pulp::Consumer.new(host.content_facet.uuid).
66
+ upload_module_stream_profile(module_stream_profile)
67
+ rescue RestClient::ResourceNotFound
68
+ Rails.logger.warn("Host with ID %s was not known to Pulp, continuing" % host.id)
69
+ end
70
+ end
71
+ end
72
+
36
73
  def import_module_streams(payload, host)
37
74
  enabled_payload = payload.map do |profile|
38
- profile.slice("name", "stream", "version", "context", "arch") if profile["status"] == "enabled"
75
+ profile.slice("name", "stream", "version", "context", "arch").with_indifferent_access if profile["status"] == "enabled"
39
76
  end
40
77
  enabled_payload.compact!
41
78
 
42
- ::Katello::Pulp::Consumer.new(host.content_facet.uuid).upload_module_stream_profile(enabled_payload)
79
+ UploadProfiles.upload_modules_to_pulp(enabled_payload, host)
43
80
  host.import_module_streams(payload)
44
- rescue RestClient::ResourceNotFound
45
- Rails.logger.warn("Host with ID %s was not known to Pulp, continuing" % input[:host_id])
46
81
  end
47
82
 
48
83
  def import_deb_package_profile(host, profile)
@@ -69,6 +104,7 @@ module Actions
69
104
  payload = profiles.dig("deb_package_profile", "deb_packages") || []
70
105
  import_deb_package_profile(host, payload)
71
106
  else
107
+ module_streams = []
72
108
  profiles.each do |profile|
73
109
  payload = profile["profile"]
74
110
  case profile["content_type"]
@@ -79,9 +115,13 @@ module Actions
79
115
  when "enabled_repos"
80
116
  host.import_enabled_repositories(payload)
81
117
  else
82
- import_module_streams(payload, host)
118
+ module_streams << payload
83
119
  end
84
120
  end
121
+
122
+ module_streams.each do |module_stream_payload|
123
+ import_module_streams(module_stream_payload, host)
124
+ end
85
125
  end
86
126
  end
87
127
  end
@@ -13,6 +13,19 @@ module Actions
13
13
  Actions::Pulp3::Orchestration::OrphanCleanup::RemoveOrphans,
14
14
  proxy)
15
15
  end
16
+ plan_self
17
+ end
18
+ end
19
+
20
+ def run
21
+ models = []
22
+ ::Katello::RepositoryTypeManager.repository_types.each_value do |repo_type|
23
+ indexable_types = repo_type.content_types_to_index
24
+ models += indexable_types&.map(&:model_class)
25
+ models.select! { |model| model.many_repository_associations }
26
+ end
27
+ models.each do |model|
28
+ model.joins("left join katello_#{model.repository_association} on #{model.table_name}.id = katello_#{model.repository_association}.#{model.unit_id_field}").where("katello_#{model.repository_association}.#{model.unit_id_field} IS NULL").destroy_all
16
29
  end
17
30
  end
18
31
  end
@@ -3,6 +3,7 @@ module Actions
3
3
  module PulpSelector
4
4
  def plan_pulp_action(backend_actions, repository, smart_proxy, *args)
5
5
  fail "nil smart_proxy passed to PulpSelector" if smart_proxy.nil?
6
+ smart_proxy.fix_pulp3_capabilities(repository.content_type)
6
7
  planned = plan_optional_pulp_action(backend_actions, repository, smart_proxy, *args)
7
8
  fail "Could not locate an action for type #{smart_proxy.backend_service_type(repository)}" unless planned
8
9
  planned
@@ -45,6 +45,12 @@ module Katello
45
45
  end
46
46
  end
47
47
 
48
+ class PulpcoreMissingCapabilities < StandardError
49
+ def message
50
+ _("A smart proxy seems to have been refreshed without pulpcore being running. You may want to ")
51
+ end
52
+ end
53
+
48
54
  class ConnectionRefusedException < StandardError; end
49
55
 
50
56
  class MaxHostsReachedException < StandardError; end
@@ -106,7 +106,7 @@ module Katello
106
106
 
107
107
  def import_package_profile(simple_packages)
108
108
  found = import_package_profile_in_bulk(simple_packages)
109
- sync_package_associations(found.map(&:id))
109
+ sync_package_associations(found.map(&:id).uniq)
110
110
  end
111
111
 
112
112
  def import_package_profile_in_bulk(simple_packages)
@@ -127,9 +127,14 @@ module Katello
127
127
  :arch => simple_package.arch)
128
128
  end
129
129
  InstalledPackage.import(installed_packages, validate: false, on_duplicate_key_ignore: true)
130
+ #re-lookup all imported to pickup any duplicates/conflicts
131
+ imported = InstalledPackage.where(:nvrea => installed_packages.map(&:nvrea)).select(:id).to_a
130
132
 
131
- found << installed_packages
132
- found.flatten
133
+ if imported.count != installed_packages.count
134
+ Rails.logger.warn("Mismatch found in installed package insertion, expected #{installed_packages.count} but only could find #{imported.count}. This is most likley a bug.")
135
+ end
136
+
137
+ (found + imported).flatten
133
138
  end
134
139
 
135
140
  def import_enabled_repositories(repos)
@@ -8,6 +8,7 @@ module Katello
8
8
  :inverse_of => :http_proxy, :dependent => :nullify
9
9
  after_update :update_default_proxy_setting
10
10
  after_commit :update_repository_proxy_details
11
+ before_destroy :remove_references_to_proxy
11
12
 
12
13
  def self.default_global_content_proxy
13
14
  if Setting[:content_default_http_proxy]
@@ -16,6 +17,34 @@ module Katello
16
17
  end
17
18
  end
18
19
 
20
+ def repositories_with_proxy(proxy_id)
21
+ root_repos = RootRepository.with_selected_proxy(proxy_id)
22
+
23
+ if self == HttpProxy.default_global_content_proxy
24
+ root_repos += RootRepository.with_global_proxy
25
+ end
26
+
27
+ root_repos
28
+ end
29
+
30
+ def remove_references_to_proxy
31
+ root_repos = repositories_with_proxy(nil).uniq.sort
32
+
33
+ setting = Setting.find_by(name: 'content_default_http_proxy')
34
+ if setting&.value && setting.value == self.name
35
+ setting.update_attribute(:value, '')
36
+ end
37
+
38
+ unless root_repos.empty?
39
+ ForemanTasks.async_task(
40
+ ::Actions::BulkAction,
41
+ ::Actions::Katello::Repository::Update,
42
+ root_repos,
43
+ http_proxy_policy: Katello::RootRepository::GLOBAL_DEFAULT_HTTP_PROXY,
44
+ http_proxy_id: nil)
45
+ end
46
+ end
47
+
19
48
  def update_default_proxy_setting
20
49
  changes = self.previous_changes
21
50
  if changes.key?(:name)
@@ -32,13 +61,7 @@ module Katello
32
61
  changes = self.previous_changes
33
62
  if changes.key?(:url) || changes.key?(:username) || changes.key?(:password)
34
63
 
35
- root_repos = RootRepository.with_selected_proxy(id)
36
-
37
- if self == HttpProxy.default_global_content_proxy
38
- root_repos += RootRepository.with_global_proxy
39
- end
40
-
41
- repos = root_repos.uniq.collect(&:library_instance)
64
+ repos = repositories_with_proxy(id).uniq.collect(&:library_instance)
42
65
 
43
66
  unless repos.empty?
44
67
  ForemanTasks.async_task(
@@ -124,6 +124,8 @@ module Katello
124
124
  config.ssl_client_key = ::Cert::Certs.ssl_client_key
125
125
  config.debugging = true
126
126
  config.logger = ::Foreman::Logging.logger('katello/pulp_rest')
127
+ config.username = self.setting(PULP3_FEATURE, 'username')
128
+ config.password = self.setting(PULP3_FEATURE, 'password')
127
129
  end
128
130
  end
129
131
 
@@ -152,6 +154,19 @@ module Katello
152
154
  end
153
155
  end
154
156
 
157
+ def missing_pulp3_capabilities?
158
+ pulp3_enabled? && self.capabilities(PULP3_FEATURE).empty?
159
+ end
160
+
161
+ def fix_pulp3_capabilities(type)
162
+ if missing_pulp3_capabilities? && !pulp2_preferred_for_type?(type)
163
+ self.refresh
164
+ if self.capabilities(::SmartProxy::PULP3_FEATURE).empty?
165
+ fail Katello::Errors::PulpcoreMissingCapabilities
166
+ end
167
+ end
168
+ end
169
+
155
170
  def pulp3_repository_type_support?(repository_type, check_pulp2_preferred = true)
156
171
  repository_type_obj = repository_type.is_a?(String) ? Katello::RepositoryTypeManager.repository_types[repository_type] : repository_type
157
172
  fail "Cannot find repository type #{repository_type}, is it enabled?" unless repository_type_obj
@@ -182,7 +197,7 @@ module Katello
182
197
  pulp3_uri!.host
183
198
  end
184
199
 
185
- def pulp3_url(path = '/pulp/api/v3/')
200
+ def pulp3_url(path = '/pulp/api/v3')
186
201
  pulp_url = self.setting(PULP3_FEATURE, 'pulp_url')
187
202
  path.blank? ? pulp_url : "#{pulp_url.sub(%r|/$|, '')}/#{path.sub(%r|^/|, '')}"
188
203
  end
@@ -107,7 +107,7 @@ module Katello
107
107
  if grouped
108
108
  grouped_fields = "#{table_name}.name, katello_repositories.root_id"
109
109
  ids = distinct.select("ON (#{grouped_fields}) #{table_name}.id").joins(:repositories)
110
- where(:id => ids).where("#{self.table_name}.schema1_id in (#{sql}) or #{self.table_name}.schema2_id in (#{sql})")
110
+ self.where(:id => ids)
111
111
  else
112
112
  self.where("#{self.table_name}.schema1_id in (#{sql}) or #{self.table_name}.schema2_id in (#{sql})")
113
113
  end
@@ -4,8 +4,8 @@ module Katello
4
4
  allow :nvra, :nvrea, :name
5
5
  end
6
6
 
7
- has_many :hosts, :through => :host_installed_packages, :class_name => "::Host"
8
7
  has_many :host_installed_packages, :class_name => "Katello::HostInstalledPackage", :dependent => :destroy, :inverse_of => :installed_package
8
+ has_many :hosts, :through => :host_installed_packages, :class_name => "::Host"
9
9
 
10
10
  scoped_search :on => :name, :complete_value => true
11
11
  scoped_search :on => :nvrea
@@ -422,8 +422,12 @@ module Katello
422
422
  path
423
423
  end
424
424
 
425
+ def library_instance_or_self
426
+ self.library_instance || self
427
+ end
428
+
425
429
  def generate_repo_path(content_path = nil)
426
- _org, _content, content_path = (self.library_instance || self).relative_path.split("/", 3) if content_path.blank?
430
+ _org, _content, content_path = library_instance_or_self.relative_path.split("/", 3) if content_path.blank?
427
431
  content_path = content_path.sub(%r|^/|, '')
428
432
  if self.environment
429
433
  cve = ContentViewEnvironment.where(:environment_id => self.environment,
@@ -496,7 +500,7 @@ module Katello
496
500
  end
497
501
  end
498
502
  clone = Repository.new(:environment => to_env,
499
- :library_instance => self.library_instance || self,
503
+ :library_instance => library_instance_or_self,
500
504
  :root => self.root,
501
505
  :content_view_version => to_version,
502
506
  :saved_checksum_type => checksum_type)
@@ -97,7 +97,7 @@ module Katello
97
97
  scope :with_no_proxy, -> { where(:http_proxy_policy => RootRepository::NO_DEFAULT_HTTP_PROXY) }
98
98
  scope :with_selected_proxy, ->(http_proxy_id) {
99
99
  where(:http_proxy_policy => RootRepository::USE_SELECTED_HTTP_PROXY).
100
- where("http_proxy_id = ?", http_proxy_id)
100
+ where(:http_proxy_id => http_proxy_id)
101
101
  }
102
102
  delegate :redhat?, :provider, :organization, to: :product
103
103
 
@@ -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
 
@@ -13,8 +13,8 @@ module Katello
13
13
  end
14
14
 
15
15
  def nvrea
16
- if epoch == "0"
17
- @nvra
16
+ if epoch.nil? || epoch.to_s == "0"
17
+ nvra
18
18
  else
19
19
  "#{@name}-#{@epoch}:#{@version}-#{@release}.#{@arch}"
20
20
  end
@@ -15,4 +15,4 @@ kind: job_template
15
15
  %>
16
16
 
17
17
  <% advisories = input(:errata).split(',').map { |e| "--advisory=#{e}" }.join(' ') %>
18
- <%= render_template('Run Command - Ansible Default', :command => "yum update-minimal #{advisories}") %>
18
+ <%= render_template('Run Command - Ansible Default', :command => "yum -y update-minimal #{advisories}") %>
@@ -13,4 +13,4 @@ provider_type: Ansible
13
13
  kind: job_template
14
14
  %>
15
15
 
16
- <%= render_template('Run Command - Ansible Default', :command => "yum group install #{input('package')}") %>
16
+ <%= render_template('Run Command - Ansible Default', :command => "yum -y group install #{input('package')}") %>
@@ -13,4 +13,4 @@ provider_type: Ansible
13
13
  kind: job_template
14
14
  %>
15
15
 
16
- <%= render_template('Run Command - Ansible Default', :command => "yum group remove #{input('package')}") %>
16
+ <%= render_template('Run Command - Ansible Default', :command => "yum -y group remove #{input('package')}") %>
@@ -13,4 +13,4 @@ provider_type: Ansible
13
13
  kind: job_template
14
14
  %>
15
15
 
16
- <%= render_template('Run Command - Ansible Default', :command => "yum group update #{input('package')}") %>
16
+ <%= render_template('Run Command - Ansible Default', :command => "yum -y group update #{input('package')}") %>
@@ -13,4 +13,4 @@ provider_type: Ansible
13
13
  kind: job_template
14
14
  %>
15
15
 
16
- <%= render_template('Run Command - Ansible Default', :command => "yum update #{input('package')}") %>
16
+ <%= render_template('Run Command - Ansible Default', :command => "yum -y update #{input('package')}") %>
@@ -18,7 +18,7 @@ child :docker_manifest => :manifest do
18
18
  attributes :schema_version, :digest, :manifest_type
19
19
  end
20
20
 
21
- child :repository => :repository do
21
+ child :repositories => :repositories do
22
22
  attributes :id, :name, :full_path
23
23
  end
24
24
 
@@ -57,3 +57,11 @@ end
57
57
  child :content_view => :content_view do |_repo|
58
58
  attribute :id, :name
59
59
  end
60
+
61
+ child :content_view_version do
62
+ attributes :id, :name, :content_view_id
63
+ end
64
+
65
+ child :environment do
66
+ attributes :id, :name
67
+ end
@@ -163,6 +163,9 @@ Katello::Engine.routes.draw do
163
163
  get :auto_complete_name
164
164
  get :compare
165
165
  end
166
+ member do
167
+ get :repositories
168
+ end
166
169
  end
167
170
 
168
171
  api_resources :environments, :only => [:index, :show, :create, :update, :destroy] do
@@ -0,0 +1,14 @@
1
+ class InstalledPackageBadNvrea < ActiveRecord::Migration[5.2]
2
+ def up
3
+ Katello::InstalledPackage.where(:epoch => "0").find_each do |pkg|
4
+ simple = Katello::Pulp::SimplePackage.new(pkg.attributes)
5
+ if pkg.nvrea != simple.nvrea
6
+ pkg.update_column(:nvrea, simple.nvrea)
7
+ end
8
+ end
9
+ end
10
+
11
+ def down
12
+ #noop
13
+ end
14
+ end
@@ -0,0 +1,64 @@
1
+ class InstalledPackageUniqueNvrea < ActiveRecord::Migration[5.2]
2
+ def fix_missing_attributes
3
+ #bug in dynflow may have resulted in old code running and not properly populating fields
4
+ # This block is basically copied from 20200129172534_add_epoch_version_release_arch_to_katello_installed_packages.rb
5
+ epoch_non_0 = ::Katello::Rpm.where.not(epoch: [0, nil]).pluck(:nvra, :epoch).to_h
6
+ installed_packages = []
7
+ ::Katello::InstalledPackage.where(:nvrea => nil).each do |pkg|
8
+ epoch = epoch_non_0[pkg.nvra] || "0"
9
+
10
+ attributes_hash = ::Katello::Util::Package.parse_nvrea(pkg.nvra)
11
+ attributes_hash[:epoch] = epoch
12
+ attributes_hash[:nvra] = pkg.nvra
13
+ if epoch == "0"
14
+ attributes_hash[:nvrea] = pkg.nvra
15
+ else
16
+ attributes_hash[:nvrea] = "#{pkg.name}-#{epoch}:#{attributes_hash[:version]}-"\
17
+ "#{attributes_hash[:release]}.#{attributes_hash[:arch]}"
18
+ end
19
+
20
+ installed_packages << ::Katello::InstalledPackage.new(attributes_hash)
21
+ end
22
+ ::Katello::InstalledPackage.import(installed_packages, validate: false, batch_size: 50_000,
23
+ on_duplicate_key_update: {conflict_target: [:nvra],
24
+ columns: [:nvrea, :epoch, :version, :release, :arch]})
25
+ end
26
+
27
+ def consolidate_duplicate_nvreas
28
+ host_installed_packages = []
29
+ deletable_installed_package_ids = []
30
+ Katello::InstalledPackage.having('count(nvrea) > 1').group(:nvrea).pluck(:nvrea).each do |nvrea|
31
+ found = Katello::InstalledPackage.includes(:host_installed_packages).where(:nvrea => nvrea).to_a
32
+ to_keep = found.pop
33
+ found.each do |duplicate|
34
+ duplicate.host_ids.each do |host_id|
35
+ host_installed_packages << {:installed_package_id => to_keep.id, :host_id => host_id}
36
+ end
37
+ deletable_installed_package_ids << duplicate.id
38
+ end
39
+ end
40
+ if host_installed_packages.any?
41
+ Katello::HostInstalledPackage.import(host_installed_packages, validate: false, on_duplicate_key_ignore: true)
42
+ end
43
+ if deletable_installed_package_ids.any?
44
+ Katello::HostInstalledPackage.where(installed_package_id: deletable_installed_package_ids).delete_all
45
+ Katello::InstalledPackage.where(id: deletable_installed_package_ids).delete_all
46
+ end
47
+ end
48
+
49
+ def up
50
+ fix_missing_attributes
51
+ #now there should be no NULL nvreas
52
+ change_column :katello_installed_packages, :nvrea, :string, :null => false
53
+
54
+ consolidate_duplicate_nvreas
55
+ add_index "katello_installed_packages", [:nvrea], :unique => true
56
+ remove_index "katello_installed_packages", [:nvra]
57
+ end
58
+
59
+ def down
60
+ remove_index "katello_installed_packages", [:nvrea]
61
+ add_index "katello_installed_packages", [:nvra], :unique => true
62
+ change_column :katello_installed_packages, :nvrea, :string, :null => true
63
+ end
64
+ end
@@ -12,6 +12,7 @@ UpgradeTask.define_tasks(:katello) do
12
12
  {:name => 'katello:upgrades:3.12:remove_pulp2_notifier'},
13
13
  {:name => 'katello:upgrades:3.13:republish_deb_metadata'},
14
14
  {:name => 'katello:upgrades:3.15:set_sub_facet_dmi_uuid'},
15
- {:name => 'katello:upgrades:3.15:reindex_rpm_modular'}
15
+ {:name => 'katello:upgrades:3.15:reindex_rpm_modular'},
16
+ {:name => 'katello:upgrades:3.16:update_applicable_el8_hosts'}
16
17
  ]
17
18
  end
@@ -20,36 +20,24 @@ angular.module('Bastion.docker-tags').controller('DockerTagEnvironmentsControlle
20
20
  'sort_order': 'ASC',
21
21
  'paged': false
22
22
  };
23
+
23
24
  var nutupane = new Nutupane(DockerTag, params, null, {disableAutoLoad: true});
24
25
 
25
26
  var renderTable = function () {
26
- var ids = _.map($scope.tag.related_tags, 'id');
27
- var newParams = {
28
- 'organization_id': CurrentOrganization,
29
- 'search': $location.search().search || "",
30
- 'sort_by': 'name',
31
- 'sort_order': 'ASC',
32
- 'paged': false,
33
- 'ids[]': ids
34
- };
35
- $scope.table = nutupane.table;
36
- nutupane.setParams(newParams);
37
- $scope.panel.loading = false;
38
- if (!_.isEmpty(ids)) {
39
- nutupane.refresh();
40
- }
27
+ params.action = 'repositories';
28
+ params.id = $scope.tag.id;
29
+
30
+ nutupane.setParams(params);
31
+ nutupane.refresh();
41
32
  };
42
33
 
34
+ $scope.table = nutupane.table;
35
+
43
36
  $scope.controllerName = 'katello_docker_tags';
44
37
 
45
- if ($scope.tag) {
38
+ $scope.tag.$promise.then(function() {
46
39
  $scope.panel.loading = false;
47
- }
48
-
49
- if ($scope.tag && $scope.tag.related_tags) {
50
40
  renderTable();
51
- } else {
52
- $scope.tag.$promise.then(renderTable);
53
- }
41
+ });
54
42
  }
55
43
  ]);
@@ -27,19 +27,19 @@
27
27
 
28
28
  <tbody>
29
29
  <tr bst-table-row
30
- ng-repeat="tag in table.rows | filter:dockerTagFilter">
30
+ ng-repeat="repo in table.rows | filter:dockerTagFilter">
31
31
  <td bst-table-cell>
32
- <a ui-sref="environment.details({environmentId: tag.environment.id})">
33
- {{ tag.environment.name }}
32
+ <a ui-sref="environment.details({environmentId: repo.kt_environment.id})">
33
+ {{ repo.kt_environment.name }}
34
34
  </a>
35
35
  </td>
36
36
  <td bst-table-cell>
37
- <a ui-sref="content-view.version.docker({contentViewId: tag.content_view_version.content_view_id, versionId: tag.content_view_version.id})">
38
- {{ tag.content_view_version.name }}
37
+ <a ui-sref="content-view.version.docker({contentViewId: repo.content_view_version.content_view_id, versionId: repo.content_view_version.id})">
38
+ {{ repo.content_view_version.name }}
39
39
  </a>
40
40
  </td>
41
41
  <td bst-table-cell>
42
- {{ tag.repository.full_path }}:{{ tag.name }}
42
+ {{ repo.full_path }}:{{ tag.name }}
43
43
  </td>
44
44
  </tr>
45
45
  </tbody>
@@ -44,5 +44,13 @@ angular.module('Bastion.docker-tags').controller('DockerTagsController',
44
44
  }
45
45
  return versions.join(", ");
46
46
  };
47
+
48
+ $scope.getRepositoryNames = function (tag) {
49
+ return tag.repositories.map(function(repo) {
50
+ return repo.name;
51
+ }).filter(function(item, index, names) {
52
+ return names.indexOf(item) >= index;
53
+ }).sort().join(', ');
54
+ };
47
55
  }]
48
56
  );
@@ -10,7 +10,7 @@
10
10
  angular.module('Bastion.docker-tags').factory('DockerTag',
11
11
  ['BastionResource', function (BastionResource) {
12
12
 
13
- return BastionResource('katello/api/v2/docker_tags/:id/',
13
+ return BastionResource('katello/api/v2/docker_tags/:id/:action/',
14
14
  {id: '@id'},
15
15
  {
16
16
  autocomplete: {method: 'GET', isArray: true, params: {id: 'auto_complete_search'}},
@@ -39,7 +39,7 @@
39
39
  {{ tag.product.name }}
40
40
  </td>
41
41
  <td bst-table-cell>
42
- {{ tag.repository.name }}
42
+ {{ getRepositoryNames(tag) }}
43
43
  </td>
44
44
  </tr>
45
45
  </tbody>
@@ -258,7 +258,12 @@ module Katello
258
258
  'katello/api/v2/package_groups' => [:index, :show, :auto_complete_search, :compare],
259
259
  'katello/api/v2/docker_manifests' => [:index, :show, :auto_complete_search, :compare],
260
260
  'katello/api/v2/docker_manifest_lists' => [:index, :show, :auto_complete_search, :compare],
261
- 'katello/api/v2/docker_tags' => [:index, :show, :auto_complete_search, :auto_complete_name, :compare],
261
+ 'katello/api/v2/docker_tags' => [:index,
262
+ :show,
263
+ :auto_complete_search,
264
+ :auto_complete_name,
265
+ :compare,
266
+ :repositories],
262
267
  'katello/api/v2/file_units' => [:index, :show, :auto_complete_search, :compare],
263
268
  'katello/api/v2/ostree_branches' => [:index, :show, :auto_complete_search, :compare],
264
269
  'katello/api/v2/errata' => [:index, :show, :auto_complete_search, :compare],
@@ -0,0 +1,7 @@
1
+ namespace :katello do
2
+ task :disable_dynflow do
3
+ #Ensures that we run as a dynflow 'client'
4
+ ::Rails.application.dynflow.initialize!
5
+ ForemanTasks.dynflow.config.remote = true
6
+ end
7
+ end
@@ -1,7 +1,9 @@
1
+ load "#{Katello::Engine.root}/lib/katello/tasks/common.rake"
2
+
1
3
  namespace :katello do
2
4
  desc "Remove orphaned and unneeded content/repos from a smart proxy.\
3
5
  Run with SMART_PROXY_ID=1 to run for a single smart proxy."
4
- task :delete_orphaned_content => ["environment"] do
6
+ task :delete_orphaned_content => ["environment", "disable_dynflow"] do
5
7
  User.current = User.anonymous_admin
6
8
  smart_proxy_id = ENV['SMART_PROXY_ID']
7
9
  if smart_proxy_id
@@ -1,3 +1,5 @@
1
+ load "#{Katello::Engine.root}/lib/katello/tasks/common.rake"
2
+
1
3
  namespace :katello do
2
4
  desc "Runs a Pulp 2 to 3 Content Migration for supported types. May be run multiple times. Use wait=false to immediately return with a task url."
3
5
  task :pulp3_migration => ["environment", "disable_dynflow", "check_ping"] do
@@ -1,8 +1,6 @@
1
- namespace :katello do
2
- task :disable_dynflow do
3
- ForemanTasks.dynflow.config.remote = true
4
- end
1
+ load "#{Katello::Engine.root}/lib/katello/tasks/common.rake"
5
2
 
3
+ namespace :katello do
6
4
  def commit?
7
5
  ENV['COMMIT'] == 'true' || ENV['FOREMAN_UPGRADE'] == '1'
8
6
  end
@@ -0,0 +1,29 @@
1
+ namespace :katello do
2
+ namespace :upgrades do
3
+ namespace '3.16' do
4
+ desc <<-DESCRIPTION
5
+ Update the applicability calculations for Rhel8 hosts.
6
+ This migration is to be run to address -> https://bugzilla.redhat.com/show_bug.cgi?id=1814095
7
+ DESCRIPTION
8
+ task :update_applicable_el8_hosts, [:input_file] => ["environment"] do
9
+ User.current = User.anonymous_api_admin
10
+
11
+ # Find me only those hosts that follow ALL the conditions below
12
+ # 1) Have a module stream enabled.
13
+ # 2) Bound to Non Library repositories. (i.e must belong to a CV thats not the default)
14
+ # 3) Bound repositories must have module streams in them
15
+ hosts = Host.joins(:content_facet => :content_facet_repositories).
16
+ where("#{Host.table_name}.id" => ::Katello::HostAvailableModuleStream.enabled.select(:host_id)).
17
+ where("#{Katello::ContentFacetRepository.table_name}.repository_id" =>
18
+ ::Katello::Repository.joins(:repository_module_streams).
19
+ in_non_default_view.
20
+ non_archived)
21
+ hosts.each do |host|
22
+ available_streams = ::Katello::HostAvailableModuleStream.joins(:available_module_stream).
23
+ enabled.where(:host_id => host).select(:name, :stream)
24
+ ::Actions::Katello::Host::UploadProfiles.upload_modules_to_pulp(available_streams, host)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.15.0.1".freeze
2
+ VERSION = "3.15.3.1".freeze
3
3
  end
@@ -34,6 +34,8 @@ const ContentTable = ({ content, tableSchema, onPaginationChange }) => {
34
34
  ContentTable.propTypes = {
35
35
  content: PropTypes.shape({
36
36
  loading: PropTypes.bool,
37
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
38
+ // eslint-disable-next-line react/forbid-prop-types
37
39
  results: PropTypes.array,
38
40
  pagination: PropTypes.shape({}),
39
41
  itemCount: PropTypes.number,
@@ -59,9 +59,12 @@ ContentDetails.propTypes = {
59
59
  contentDetails: PropTypes.shape({
60
60
  loading: PropTypes.bool,
61
61
  name: PropTypes.string,
62
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
63
+ /* eslint-disable react/forbid-prop-types */
62
64
  profiles: PropTypes.array,
63
65
  repositories: PropTypes.array,
64
66
  artifacts: PropTypes.array,
67
+ /* eslint-enable react/forbid-prop-types */
65
68
  stream: PropTypes.string,
66
69
  }).isRequired,
67
70
  schema: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
@@ -83,8 +83,11 @@ AnsibleCollectionDetails.propTypes = {
83
83
  name: PropTypes.string,
84
84
  namespace: PropTypes.string,
85
85
  version: PropTypes.string,
86
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
87
+ /* eslint-disable react/forbid-prop-types */
86
88
  repositories: PropTypes.array,
87
89
  tags: PropTypes.array,
90
+ /* eslint-enable react/forbid-prop-types */
88
91
  }).isRequired,
89
92
  };
90
93
 
@@ -81,9 +81,12 @@ ModuleStreamDetails.propTypes = {
81
81
  moduleStreamDetails: PropTypes.shape({
82
82
  loading: PropTypes.bool,
83
83
  name: PropTypes.string,
84
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
85
+ /* eslint-disable react/forbid-prop-types */
84
86
  profiles: PropTypes.array,
85
87
  repositories: PropTypes.array,
86
88
  artifacts: PropTypes.array,
89
+ /* eslint-enable react/forbid-prop-types */
87
90
  stream: PropTypes.string,
88
91
  }).isRequired,
89
92
  };
@@ -111,6 +111,8 @@ RedHatRepositoriesPage.propTypes = {
111
111
  recommended: PropTypes.bool,
112
112
  loading: PropTypes.bool,
113
113
  search: PropTypes.shape({}),
114
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
115
+ // eslint-disable-next-line react/forbid-prop-types
114
116
  missingPermissions: PropTypes.array,
115
117
  }).isRequired,
116
118
  };
@@ -94,6 +94,8 @@ EnabledRepository.propTypes = {
94
94
  search: PropTypes.shape({
95
95
  query: PropTypes.string,
96
96
  searchList: PropTypes.string,
97
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
98
+ // eslint-disable-next-line react/forbid-prop-types
97
99
  filters: PropTypes.array,
98
100
  }),
99
101
  pagination: PropTypes.shape({
@@ -141,6 +141,8 @@ RepositorySetRepository.propTypes = {
141
141
  enabledSearch: PropTypes.shape({
142
142
  query: PropTypes.string,
143
143
  searchList: PropTypes.string,
144
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
145
+ // eslint-disable-next-line react/forbid-prop-types
144
146
  filters: PropTypes.array,
145
147
  }),
146
148
  enabledPagination: PropTypes.shape({
@@ -45,6 +45,8 @@ SubscriptionDetailAssociations.propTypes = {
45
45
  subscriptionDetails: PropTypes.shape({
46
46
  id: PropTypes.number,
47
47
  host_count: PropTypes.number,
48
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
49
+ // eslint-disable-next-line react/forbid-prop-types
48
50
  activation_keys: PropTypes.array,
49
51
  }).isRequired,
50
52
  };
@@ -50,6 +50,8 @@ const SubscriptionDetailProductContent = ({ productContent }) => {
50
50
 
51
51
  SubscriptionDetailProductContent.propTypes = {
52
52
  productContent: PropTypes.shape({
53
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
54
+ // eslint-disable-next-line react/forbid-prop-types
53
55
  results: PropTypes.array,
54
56
  }).isRequired,
55
57
  };
@@ -18,6 +18,8 @@ const SubscriptionDetailProducts = ({ subscriptionDetails }) => (
18
18
 
19
19
  SubscriptionDetailProducts.propTypes = {
20
20
  subscriptionDetails: PropTypes.shape({
21
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
22
+ // eslint-disable-next-line react/forbid-prop-types
21
23
  provided_products: PropTypes.array,
22
24
  }).isRequired,
23
25
  };
@@ -352,6 +352,8 @@ ManageManifestModal.propTypes = {
352
352
  simpleContentAccess: PropTypes.bool,
353
353
  manifestHistory: PropTypes.shape({
354
354
  loading: PropTypes.bool,
355
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
356
+ // eslint-disable-next-line react/forbid-prop-types
355
357
  results: PropTypes.array,
356
358
  }).isRequired,
357
359
  setModalClosed: PropTypes.func.isRequired,
@@ -264,10 +264,13 @@ SubscriptionsPage.propTypes = {
264
264
  loadTableColumns: PropTypes.func.isRequired,
265
265
  simpleContentAccess: PropTypes.bool,
266
266
  subscriptions: PropTypes.shape({
267
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
268
+ /* eslint-disable react/forbid-prop-types */
267
269
  disconnected: PropTypes.bool,
268
270
  tableColumns: PropTypes.array,
269
271
  selectedTableColumns: PropTypes.array,
270
272
  missingPermissions: PropTypes.array,
273
+ /* eslint-enable react/forbid-prop-types */
271
274
  }).isRequired,
272
275
  activePermissions: PropTypes.shape({
273
276
  can_delete_manifest: PropTypes.bool,
@@ -262,6 +262,8 @@ UpstreamSubscriptionsPage.propTypes = {
262
262
  upstreamSubscriptions: PropTypes.shape({
263
263
  loading: PropTypes.bool,
264
264
  itemCount: PropTypes.number,
265
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
266
+ // eslint-disable-next-line react/forbid-prop-types
265
267
  results: PropTypes.array,
266
268
  pagination: PropTypes.shape({}),
267
269
  task: PropTypes.shape({
@@ -276,6 +276,8 @@ SubscriptionsTable.propTypes = {
276
276
  subscriptions: PropTypes.shape({
277
277
  loading: PropTypes.bool,
278
278
  availableQuantities: PropTypes.shape({}),
279
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
280
+ // eslint-disable-next-line react/forbid-prop-types
279
281
  results: PropTypes.array,
280
282
  }).isRequired,
281
283
  subscriptionDeleteModalOpen: PropTypes.bool.isRequired,
@@ -47,7 +47,7 @@ const UpdateDialog = ({
47
47
  UpdateDialog.propTypes = {
48
48
  show: PropTypes.bool.isRequired,
49
49
  updateQuantity: PropTypes.func.isRequired,
50
- updatedQuantity: PropTypes.shape(PropTypes.Object).isRequired,
50
+ updatedQuantity: PropTypes.shape({}).isRequired,
51
51
  showUpdateConfirm: PropTypes.func.isRequired,
52
52
  enableEditing: PropTypes.func.isRequired,
53
53
  };
@@ -17,10 +17,10 @@ const Dialogs = ({
17
17
  );
18
18
 
19
19
  Dialogs.propTypes = {
20
- updateDialog: PropTypes.shape(UpdateDialog.propTypes).isRequired,
21
- unsavedChangesDialog: PropTypes.shape(UnsavedChangesDialog.propTypes).isRequired,
22
- inputsErrorsDialog: PropTypes.shape(InputsErrorsDialog.propTypes).isRequired,
23
- deleteDialog: PropTypes.shape(DeleteDialog.propTypes).isRequired,
20
+ updateDialog: PropTypes.shape({}).isRequired,
21
+ unsavedChangesDialog: PropTypes.shape({}).isRequired,
22
+ inputsErrorsDialog: PropTypes.shape({}).isRequired,
23
+ deleteDialog: PropTypes.shape({}).isRequired,
24
24
  };
25
25
 
26
26
  export default Dialogs;
@@ -95,6 +95,8 @@ Table.propTypes = {
95
95
  searchIsActive: PropTypes.bool,
96
96
  itemCount: PropTypes.number,
97
97
  pagination: PropTypes.shape({}),
98
+ // Disabling rule as existing code failed due to an eslint-plugin-react update
99
+ // eslint-disable-next-line react/forbid-prop-types
98
100
  results: PropTypes.array,
99
101
  }).isRequired,
100
102
  loadSubscriptions: PropTypes.func.isRequired,
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.15.0.1
4
+ version: 3.15.3.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-04-21 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
@@ -84,16 +84,28 @@ dependencies:
84
84
  name: foreman-tasks
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "<"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.2.0
90
+ - - "!="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.1.1
93
+ - - "!="
88
94
  - !ruby/object:Gem::Version
89
- version: 0.14.1
95
+ version: 1.1.2
90
96
  type: :runtime
91
97
  prerelease: false
92
98
  version_requirements: !ruby/object:Gem::Requirement
93
99
  requirements:
94
- - - ">="
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: 1.2.0
103
+ - - "!="
104
+ - !ruby/object:Gem::Version
105
+ version: 1.1.1
106
+ - - "!="
95
107
  - !ruby/object:Gem::Version
96
- version: 0.14.1
108
+ version: 1.1.2
97
109
  - !ruby/object:Gem::Dependency
98
110
  name: dynflow
99
111
  requirement: !ruby/object:Gem::Requirement
@@ -1894,6 +1906,8 @@ files:
1894
1906
  - db/migrate/20200121213430_katello_repository_rpms_id_big_int.rb
1895
1907
  - db/migrate/20200129172534_add_epoch_version_release_arch_to_katello_installed_packages.rb
1896
1908
  - db/migrate/20200402130013_add_repsoitory_docker_meta_tag_f_key.rb
1909
+ - db/migrate/20200429153103_installed_package_bad_nvrea.rb
1910
+ - db/migrate/20200501155054_installed_package_unique_nvrea.rb
1897
1911
  - db/seeds.d/101-locations.rb
1898
1912
  - db/seeds.d/102-organizations.rb
1899
1913
  - db/seeds.d/104-proxy.rb
@@ -4123,6 +4137,7 @@ files:
4123
4137
  - lib/katello/tasks/clean_backend_objects.rake
4124
4138
  - lib/katello/tasks/clean_old_file_repos.rake
4125
4139
  - lib/katello/tasks/clean_published_repo_directories.rake
4140
+ - lib/katello/tasks/common.rake
4126
4141
  - lib/katello/tasks/delete_orphaned_content.rake
4127
4142
  - lib/katello/tasks/import_applicability.rake
4128
4143
  - lib/katello/tasks/import_subscriptions.rake
@@ -4149,6 +4164,7 @@ files:
4149
4164
  - lib/katello/tasks/upgrades/3.13/republish_deb_metadata.rake
4150
4165
  - lib/katello/tasks/upgrades/3.15/reindex_rpm_modular.rake
4151
4166
  - lib/katello/tasks/upgrades/3.15/set_sub_facet_dmi_uuid.rake
4167
+ - lib/katello/tasks/upgrades/3.16/update_applicable_el8_hosts.rake
4152
4168
  - lib/katello/tasks/upgrades/3.8/clear_checksum_type.rake
4153
4169
  - lib/katello/tasks/virt_who_report.rake
4154
4170
  - lib/katello/url_constrained_cookie_store.rb
@@ -4649,7 +4665,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
4649
4665
  - !ruby/object:Gem::Version
4650
4666
  version: '0'
4651
4667
  requirements: []
4652
- rubygems_version: 3.0.3
4668
+ rubyforge_project:
4669
+ rubygems_version: 2.5.2.1
4653
4670
  signing_key:
4654
4671
  specification_version: 4
4655
4672
  summary: Content and Subscription Management plugin for Foreman