katello 3.15.0.rc2 → 3.15.2

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 (38) 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/lib/katello/util/package.rb +0 -1
  9. data/app/models/katello/concerns/host_managed_extensions.rb +8 -3
  10. data/app/models/katello/concerns/smart_proxy_extensions.rb +16 -1
  11. data/app/models/katello/docker_meta_tag.rb +3 -6
  12. data/app/models/katello/installed_package.rb +1 -1
  13. data/app/models/katello/repository.rb +6 -2
  14. data/app/services/katello/pulp/simple_package.rb +2 -2
  15. data/app/services/katello/pulp3/migration_switchover.rb +94 -0
  16. data/app/views/foreman/job_templates/install_errata_-_katello_ansible_default.erb +1 -1
  17. data/app/views/foreman/job_templates/install_group_-_katello_ansible_default.erb +1 -1
  18. data/app/views/foreman/job_templates/remove_group_-_katello_ansible_default.erb +1 -1
  19. data/app/views/foreman/job_templates/update_group_-_katello_ansible_default.erb +1 -1
  20. data/app/views/foreman/job_templates/update_package_-_katello_ansible_default.erb +1 -1
  21. data/app/views/katello/api/v2/docker_tags/_base.json.rabl +1 -1
  22. data/app/views/katello/api/v2/repositories/base.json.rabl +8 -0
  23. data/config/routes/api/v2.rb +3 -0
  24. data/db/migrate/20200402130013_add_repsoitory_docker_meta_tag_f_key.rb +44 -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/pulp3_content_switchover.rake +7 -13
  35. data/lib/katello/tasks/pulp3_post_migration_check.rake +27 -11
  36. data/lib/katello/tasks/upgrades/3.16/update_applicable_el8_hosts.rake +29 -0
  37. data/lib/katello/version.rb +1 -1
  38. metadata +15 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 85ee4f1e17bf63eec8c349a58dbe28aea05c1736937fa253c921c997e50247f8
4
- data.tar.gz: 696c9f65f17d7a2405f4b2c807d6db42a269b728bb30cb10484fe0c6b75a88b5
2
+ SHA1:
3
+ metadata.gz: 4ad9b04f40e657a51875c8695653860da9fb8ae7
4
+ data.tar.gz: 812424e72605d87d742fa45d14b09a9eaebeaa30
5
5
  SHA512:
6
- metadata.gz: 882b95014f435cf75227bf1969ce47294f45988d29f757c61d6c5c3a02d43af75d4b4238b8c654609cc03fa1269bed5afbc43bc2590ff49d59fab908c508a812
7
- data.tar.gz: 9edd9187a9e65364ccd41687adf5a81414a8651eb9a02d20524e7d22fb56ddcd41d817b64d81112ba851ce7b13327eadb9640796e7f8db7e247936f819de9d90
6
+ metadata.gz: 5e2c8979164f4403578cd093a6b34cb88bc091aa28179bb2c420730cc2bb10e2bf0cdf7ba2e5ac445b78cc0ba3fa46a21c4ce85c3447b88a8535b0ef5898f7c4
7
+ data.tar.gz: a8634db2c5e979b92723e368dbf92e42766d5f20d0f8757b4f88f3ac6bf56eb7c7e4f86e14510b6bb6101d517713b915aff01f6d5145ea2ac2c85ac05e0fb87c
@@ -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
@@ -22,7 +22,6 @@ module Katello
22
22
  def self.parse_nvrea(name)
23
23
  name, suffix = extract_suffix(name)
24
24
  name, arch = extract_arch(name)
25
- return unless arch
26
25
 
27
26
  if (nvre = parse_nvre(name))
28
27
  nvre.merge(:suffix => suffix, :arch => arch).delete_if { |_k, v| v.nil? }
@@ -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)
@@ -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
@@ -153,17 +153,14 @@ module Katello
153
153
  end
154
154
 
155
155
  unless params_to_query_for_delete.empty?
156
- DockerMetaTag.where(:id => repository_association_class.
157
- where(:repository_id => repo.id).
158
- select(:docker_meta_tag_id)).
159
- where(params_to_query_for_delete.join(" OR ")).delete_all
156
+ RepositoryDockerMetaTag.where(:docker_meta_tag => DockerMetaTag.where(params_to_query_for_delete.join(" OR "))).delete_all
160
157
  end
161
158
 
162
159
  metatags = []
163
160
  (tag_table_values - meta_tag_table_values).each do |schema1, schema2, name|
164
161
  metatags << DockerMetaTag.where(:schema1_id => schema1,
165
162
  :schema2_id => schema2,
166
- :name => name).create!
163
+ :name => name).first_or_create
167
164
  end
168
165
  repo.docker_meta_tags += metatags
169
166
  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)
@@ -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
@@ -0,0 +1,94 @@
1
+ require 'pulp_2to3_migration_client'
2
+
3
+ module Katello
4
+ module Pulp3
5
+ class SwitchoverError < StandardError; end
6
+
7
+ class MigrationSwitchover
8
+ def initialize(*argv)
9
+ @migration = Katello::Pulp3::Migration.new(*argv)
10
+ end
11
+
12
+ def content_types
13
+ @migration.content_types_for_migration
14
+ end
15
+
16
+ def run
17
+ check_already_migrated_content
18
+ cleanup_v1_docker_tags if docker_migration?
19
+ migrated_content_type_check
20
+ combine_duplicate_docker_tags if docker_migration?
21
+ migrate_pulp3_hrefs
22
+ end
23
+
24
+ def docker_migration?
25
+ content_types.any? { |content_type| content_type.model_class::CONTENT_TYPE == "docker_tag" }
26
+ end
27
+
28
+ def migrate_pulp3_hrefs
29
+ content_types.each do |content_type|
30
+ content_type.model_class
31
+ .where.not("pulp_id=migrated_pulp3_href")
32
+ .update_all("pulp_id = migrated_pulp3_href")
33
+ end
34
+ end
35
+
36
+ def check_already_migrated_content
37
+ content_types.each do |content_type|
38
+ if content_type.model_class.where("pulp_id=migrated_pulp3_href").any?
39
+ Rails.logger.error("Content Switchover: #{content_type.label} seems to have already migrated content, switchover may fail. Did you already perform the switchover?")
40
+ end
41
+ end
42
+ end
43
+
44
+ def cleanup_v1_docker_tags
45
+ unmigrated_docker_tags = Katello::DockerTag.includes(:schema1_meta_tag, :schema2_meta_tag).where(migrated_pulp3_href: nil)
46
+ unmigrated_docker_tags.find_in_batches(batch_size: 50_000) do |batch|
47
+ to_delete = []
48
+
49
+ batch.each do |unmigrated_tag|
50
+ if unmigrated_tag.schema1_meta_tag && unmigrated_tag.schema1_meta_tag.schema2.try(:migrated_pulp3_href)
51
+ Rails.logger.warn("Content Switchover: Deleting Docker tag #{unmigrated_tag.name} with pulp id: #{unmigrated_tag.pulp_id}")
52
+ to_delete << unmigrated_tag.id
53
+ end
54
+ end
55
+ Katello::DockerMetaTag.where(:schema1_id => to_delete).update_all(:schema1_id => nil)
56
+ Katello::RepositoryDockerTag.where(:docker_tag_id => to_delete).delete_all
57
+ Katello::DockerTag.where(:id => to_delete).delete_all
58
+ end
59
+
60
+ Katello::DockerMetaTag.cleanup_tags
61
+ end
62
+
63
+ def combine_duplicate_docker_tags
64
+ to_delete = []
65
+ Katello::DockerTag.having("count(migrated_pulp3_href) > 1").group(:migrated_pulp3_href).pluck(:migrated_pulp3_href).each do |duplicate_href|
66
+ tags = Katello::DockerTag.where(:migrated_pulp3_href => duplicate_href).includes(:schema1_meta_tag, :schema2_meta_tag).to_a
67
+ main_tag = tags.pop
68
+ main_meta_v1 = main_tag.schema1_meta_tag
69
+ main_meta_v2 = main_tag.schema2_meta_tag
70
+
71
+ Katello::RepositoryDockerTag.where(:docker_tag_id => tags.map(&:id)).update_all(:docker_tag_id => main_tag.id)
72
+ Katello::RepositoryDockerMetaTag.joins(:docker_meta_tag).where("#{Katello::DockerMetaTag.table_name}.schema1_id" => tags).update_all(:docker_meta_tag_id => main_meta_v1.id) if main_meta_v1
73
+ Katello::RepositoryDockerMetaTag.joins(:docker_meta_tag).where("#{Katello::DockerMetaTag.table_name}.schema2_id" => tags).update_all(:docker_meta_tag_id => main_meta_v2.id) if main_meta_v2
74
+
75
+ to_delete += tags.map(&:id)
76
+ end
77
+
78
+ to_delete.each_slice(10_000) do |group|
79
+ Katello::RepositoryDockerTag.where(:docker_tag_id => group).delete_all
80
+ Katello::DockerMetaTag.where(:schema1_id => group).or(Katello::DockerMetaTag.where(:schema2_id => group)).delete_all
81
+ Katello::DockerTag.where(:id => group).delete_all
82
+ end
83
+ end
84
+
85
+ def migrated_content_type_check
86
+ content_types.each do |content_type|
87
+ if content_type.model_class.where(migrated_pulp3_href: nil).any?
88
+ fail SwitchoverError, "ERROR: at least one #{content_type.model_class.table_name} record has migrated_pulp3_href NULL value\n"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ 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,44 @@
1
+ class AddRepsoitoryDockerMetaTagFKey < ActiveRecord::Migration[5.2]
2
+ def up
3
+ Katello::RepositoryDockerMetaTag.where.not(:repository_id => Katello::Repository.select(:id)).delete_all
4
+ Katello::RepositoryDockerMetaTag.where.not(:docker_meta_tag_id => Katello::DockerMetaTag.select(:id)).delete_all
5
+
6
+ add_foreign_key :katello_repository_docker_meta_tags, :katello_repositories, :column => :repository_id
7
+ add_foreign_key :katello_repository_docker_meta_tags, :katello_docker_meta_tags, :column => :docker_meta_tag_id
8
+
9
+ if Katello::DockerMetaTag.any?
10
+ query = "DELETE FROM katello_repository_docker_meta_tags T1
11
+ USING katello_repository_docker_meta_tags T2
12
+ WHERE T1.ctid < T2.ctid
13
+ AND T1.repository_id = T2.repository_id
14
+ AND T1.docker_meta_tag_id = T2.docker_meta_tag_id;"
15
+ ActiveRecord::Base.connection.execute(query)
16
+ end
17
+ add_index :katello_repository_docker_meta_tags, [:repository_id, :docker_meta_tag_id], :unique => true, :name => 'repository_docker_meta_tags_rid_dmtid'
18
+
19
+ Katello::RepositoryDockerTag.where.not(:repository_id => Katello::Repository.select(:id)).delete_all
20
+ Katello::RepositoryDockerTag.where.not(:docker_tag_id => Katello::DockerTag.select(:id)).delete_all
21
+
22
+ add_foreign_key :katello_repository_docker_tags, :katello_repositories, :column => :repository_id
23
+ add_foreign_key :katello_repository_docker_tags, :katello_docker_tags, :column => :docker_tag_id
24
+
25
+ if Katello::DockerTag.any?
26
+ query = "DELETE FROM katello_repository_docker_tags T1
27
+ USING katello_repository_docker_tags T2
28
+ WHERE T1.ctid < T2.ctid
29
+ AND T1.repository_id = T2.repository_id
30
+ AND T1.docker_tag_id = T2.docker_tag_id;"
31
+ ActiveRecord::Base.connection.execute(query)
32
+ end
33
+ add_index :katello_repository_docker_tags, [:repository_id, :docker_tag_id], :unique => true, :name => 'repository_docker_tags_rid_dtid'
34
+ end
35
+
36
+ def down
37
+ remove_foreign_key :katello_repository_docker_meta_tags, :katello_repositories
38
+ remove_foreign_key :katello_repository_docker_meta_tags, :katello_docker_meta_tags
39
+ remove_index :katello_repository_docker_meta_tags, [:repository_id, :docker_meta_tag_id]
40
+ remove_foreign_key :katello_repository_docker_tags, :katello_repositories
41
+ remove_foreign_key :katello_repository_docker_tags, :katello_docker_tags
42
+ remove_index :katello_repository_docker_tags, [:repository_id, :docker_tag_id]
43
+ end
44
+ end
@@ -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],
@@ -3,20 +3,14 @@ require File.expand_path("../engine", File.dirname(__FILE__))
3
3
  namespace :katello do
4
4
  desc "Runs a Pulp 3 migration of pulp3 hrefs to pulp ids for supported content types."
5
5
  task :pulp3_content_switchover => :environment do
6
- migration_service = Katello::Pulp3::Migration.new(SmartProxy.pulp_master)
7
- content_types = migration_service.content_types_for_migration
8
-
9
- content_types.each do |content_type|
10
- if content_type.model_class.where(migrated_pulp3_href: nil).any?
11
- $stderr.print("ERROR: at least one #{content_type.model_class.table_name} record has migrated_pulp3_href NULL value\n")
12
- exit 1
6
+ begin
7
+ ActiveRecord::Base.transaction do
8
+ switchover_service = Katello::Pulp3::MigrationSwitchover.new(SmartProxy.pulp_master)
9
+ switchover_service.run
13
10
  end
14
- end
15
-
16
- content_types.each do |content_type|
17
- content_type.model_class
18
- .where.not("pulp_id=migrated_pulp3_href")
19
- .update_all("pulp_id = migrated_pulp3_href")
11
+ rescue Katello::Pulp3::SwitchoverError => e
12
+ $stderr.print(e.message)
13
+ exit 1
20
14
  end
21
15
  end
22
16
  end
@@ -6,25 +6,41 @@ namespace :katello do
6
6
  repository_types = Katello::Pulp3::Migration::REPOSITORY_TYPES
7
7
 
8
8
  repository_types.each do |type|
9
- filter = 'version_href is NULL OR remote_href is NULL'
10
-
11
- unless type == Katello::Repository::DOCKER_TYPE
12
- filter += ' OR publication_href is NULL'
9
+ # check version
10
+ nil_version_ids = Katello::Repository.with_type(type).where(version_href: nil).pluck(:id)
11
+ unless nil_version_ids.empty?
12
+ $stderr.print("ERROR: #{type} repositories with ID [#{nil_version_ids.join(',')}] have a NULL value for version_href\n")
13
+ exit 1
13
14
  end
14
- repositories = Katello::Repository.with_type(type).where(filter)
15
15
 
16
- if repositories.any?
17
- $stderr.print("ERROR: #{type} repository #{repositories.first.id} has a NULL value for remote_href, version_href, publication_href\n")
16
+ # check remote
17
+ nil_remote_ids = Katello::Repository.with_type(type).where(remote_href: nil).collect do |repo|
18
+ repo.id if repo.in_default_view? && !repo.root.url.nil?
19
+ end
20
+ nil_remote_ids.compact!
21
+ unless nil_remote_ids.empty?
22
+ $stderr.print("ERROR: #{type} repositories with ID [#{nil_remote_ids.join(',')}] have a NULL value for remote_href\n")
18
23
  exit 1
19
24
  end
20
25
 
26
+ # check publication
27
+ unless type == Katello::Repository::DOCKER_TYPE
28
+ nil_publication_ids = Katello::Repository.with_type(type).where(publication_href: nil).pluck(:id)
29
+ unless nil_publication_ids.empty?
30
+ $stderr.print("ERROR: #{type} repositories with ID [#{nil_publication_ids.join(',')}] have a NULL value for publication_href\n")
31
+ exit 1
32
+ end
33
+ end
34
+
35
+ # check distribution
21
36
  non_archived_repositories = Katello::Repository.with_type(type).non_archived
22
- with_no_distribution_references = non_archived_repositories
23
- .left_outer_joins(:distribution_references)
24
- .where(katello_distribution_references: { id: nil })
37
+ with_no_distribution_references = non_archived_repositories.
38
+ left_outer_joins(:distribution_references).
39
+ where(katello_distribution_references: { id: nil }).
40
+ pluck(:id)
25
41
 
26
42
  if with_no_distribution_references.any?
27
- $stderr.print("ERROR: A non-archive #{type} repository #{with_no_distribution_references.first.id} did not have a distribution reference\n")
43
+ $stderr.print("ERROR: Non-archived #{type} repositories with ID [#{with_no_distribution_references.join(',')}] have no distribution reference\n")
28
44
  exit 1
29
45
  end
30
46
  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.rc2".freeze
2
+ VERSION = "3.15.2".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.15.0.rc2
4
+ version: 3.15.2
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-03-30 00:00:00.000000000 Z
11
+ date: 2020-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -84,16 +84,16 @@ dependencies:
84
84
  name: foreman-tasks
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "<"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.14.1
89
+ version: 1.2.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "<"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.14.1
96
+ version: 1.2.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: dynflow
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -1317,6 +1317,7 @@ files:
1317
1317
  - app/services/katello/pulp3/file_unit.rb
1318
1318
  - app/services/katello/pulp3/migration.rb
1319
1319
  - app/services/katello/pulp3/migration_plan.rb
1320
+ - app/services/katello/pulp3/migration_switchover.rb
1320
1321
  - app/services/katello/pulp3/module_stream.rb
1321
1322
  - app/services/katello/pulp3/package_group.rb
1322
1323
  - app/services/katello/pulp3/pulp_content_unit.rb
@@ -1892,6 +1893,9 @@ files:
1892
1893
  - db/migrate/20200109162354_drop_host_update_lock_setting.rb
1893
1894
  - db/migrate/20200121213430_katello_repository_rpms_id_big_int.rb
1894
1895
  - db/migrate/20200129172534_add_epoch_version_release_arch_to_katello_installed_packages.rb
1896
+ - db/migrate/20200402130013_add_repsoitory_docker_meta_tag_f_key.rb
1897
+ - db/migrate/20200429153103_installed_package_bad_nvrea.rb
1898
+ - db/migrate/20200501155054_installed_package_unique_nvrea.rb
1895
1899
  - db/seeds.d/101-locations.rb
1896
1900
  - db/seeds.d/102-organizations.rb
1897
1901
  - db/seeds.d/104-proxy.rb
@@ -4147,6 +4151,7 @@ files:
4147
4151
  - lib/katello/tasks/upgrades/3.13/republish_deb_metadata.rake
4148
4152
  - lib/katello/tasks/upgrades/3.15/reindex_rpm_modular.rake
4149
4153
  - lib/katello/tasks/upgrades/3.15/set_sub_facet_dmi_uuid.rake
4154
+ - lib/katello/tasks/upgrades/3.16/update_applicable_el8_hosts.rake
4150
4155
  - lib/katello/tasks/upgrades/3.8/clear_checksum_type.rake
4151
4156
  - lib/katello/tasks/virt_who_report.rake
4152
4157
  - lib/katello/url_constrained_cookie_store.rb
@@ -4643,11 +4648,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
4643
4648
  version: '0'
4644
4649
  required_rubygems_version: !ruby/object:Gem::Requirement
4645
4650
  requirements:
4646
- - - ">"
4651
+ - - ">="
4647
4652
  - !ruby/object:Gem::Version
4648
- version: 1.3.1
4653
+ version: '0'
4649
4654
  requirements: []
4650
- rubygems_version: 3.0.3
4655
+ rubyforge_project:
4656
+ rubygems_version: 2.5.2.1
4651
4657
  signing_key:
4652
4658
  specification_version: 4
4653
4659
  summary: Content and Subscription Management plugin for Foreman