katello 4.0.0 → 4.0.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +5 -7
  3. data/app/controllers/katello/api/v2/repositories_controller.rb +4 -3
  4. data/app/lib/actions/katello/agent_action.rb +26 -17
  5. data/app/lib/actions/katello/bulk_agent_action.rb +18 -5
  6. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  7. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +44 -6
  8. data/app/lib/actions/katello/content_view/promote.rb +25 -0
  9. data/app/lib/actions/katello/content_view/publish.rb +29 -0
  10. data/app/lib/actions/katello/content_view_version/incremental_update.rb +14 -3
  11. data/app/lib/actions/katello/jail_concern/content_view.rb +30 -0
  12. data/app/lib/actions/katello/jail_concern/organization.rb +30 -0
  13. data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +2 -2
  14. data/app/lib/actions/katello/repository/check_matching_content.rb +3 -4
  15. data/app/lib/actions/katello/repository/sync.rb +59 -0
  16. data/app/lib/actions/pulp3/content_guard/refresh.rb +6 -10
  17. data/app/lib/actions/pulp3/orchestration/orphan_cleanup/remove_orphans.rb +1 -1
  18. data/app/lib/katello/agent/client_message_handler.rb +12 -3
  19. data/app/lib/katello/errors.rb +1 -1
  20. data/app/lib/katello/event_daemon/monitor.rb +1 -0
  21. data/app/lib/katello/event_daemon/services/agent_event_receiver.rb +6 -10
  22. data/app/lib/katello/util/hostgroup_facets_helper.rb +126 -0
  23. data/app/models/katello/agent/dispatch_history.rb +2 -0
  24. data/app/models/katello/authorization/content_view.rb +12 -0
  25. data/app/models/katello/authorization/repository.rb +18 -0
  26. data/app/models/katello/concerns/hostgroup_extensions.rb +4 -2
  27. data/app/models/katello/concerns/redhat_extensions.rb +23 -18
  28. data/app/models/katello/concerns/smart_proxy_extensions.rb +23 -0
  29. data/app/models/katello/content_view.rb +13 -7
  30. data/app/models/katello/glue/pulp/repo.rb +0 -19
  31. data/app/models/katello/ping.rb +3 -10
  32. data/app/models/katello/repository.rb +16 -2
  33. data/app/models/katello/root_repository.rb +1 -1
  34. data/app/services/cert/certs.rb +4 -0
  35. data/app/services/katello/agent/dispatcher.rb +18 -24
  36. data/app/services/katello/applicability/applicable_content_helper.rb +8 -6
  37. data/app/services/katello/managed_content_medium_provider.rb +3 -3
  38. data/app/services/katello/pulp3/api/content_guard.rb +39 -5
  39. data/app/services/katello/pulp3/migration.rb +4 -3
  40. data/app/services/katello/pulp3/repository.rb +32 -4
  41. data/app/services/katello/pulp3/repository/apt.rb +1 -2
  42. data/app/services/katello/pulp3/repository/yum.rb +1 -1
  43. data/app/services/katello/ui_notifications/pulp/proxy_disk_space.rb +1 -0
  44. data/app/views/overrides/smart_proxies/_download_policy.erb +1 -1
  45. data/db/migrate/20200514092553_move_katello_fields_from_hostgroups.katello.rb +1 -1
  46. data/db/migrate/20210119162528_delete_puppet_and_ostree_repos.rb +25 -22
  47. data/db/migrate/20210512192745_fix_red_hat_root_repository_arch.rb +11 -0
  48. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/views/products-bulk-advanced-sync-modal.html +2 -2
  49. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +3 -4
  50. data/lib/katello.rb +1 -1
  51. data/lib/katello/engine.rb +11 -11
  52. data/lib/katello/plugin.rb +5 -2
  53. data/lib/katello/tasks/clean_backend_objects.rake +0 -25
  54. data/lib/katello/tasks/fix_hostgroup_facets.rake +8 -0
  55. data/lib/katello/version.rb +1 -1
  56. data/lib/proxy_api/container_gateway.rb +22 -11
  57. metadata +28 -10
  58. data/app/lib/actions/pulp3/capsule_content/refresh_content_guard.rb +0 -17
@@ -1,13 +1,13 @@
1
1
  module Actions
2
2
  module Katello
3
3
  module OrphanCleanup
4
- class RemoveOrphans < Pulp::Abstract
4
+ class RemoveOrphans < Actions::Base
5
5
  input_format do
6
6
  param :capsule_id
7
7
  end
8
8
  def plan(proxy)
9
9
  sequence do
10
- plan_action(Actions::Pulp::Orchestration::OrphanCleanup::RemoveOrphans, proxy)
10
+ plan_action(Actions::Pulp::Orchestration::OrphanCleanup::RemoveOrphans, proxy) if (proxy.has_feature?(SmartProxy::PULP_FEATURE) || proxy.has_feature?(SmartProxy::PULP_NODE_FEATURE))
11
11
  if proxy.pulp3_enabled?
12
12
  plan_action(
13
13
  Actions::Pulp3::Orchestration::OrphanCleanup::RemoveOrphans,
@@ -13,6 +13,7 @@ module Actions
13
13
  def run
14
14
  source_repo = ::Katello::Repository.find(input[:source_repo_id])
15
15
  target_repo = ::Katello::Repository.find(input[:target_repo_id])
16
+ target_repo_published = target_repo.backend_service(SmartProxy.pulp_primary).published?
16
17
 
17
18
  if source_repo.content_type == ::Katello::Repository::YUM_TYPE
18
19
  srpms_match = srpms_match?(source_repo, target_repo)
@@ -23,16 +24,14 @@ module Actions
23
24
  yum_metadata_files = yum_metadata_files_match?(source_repo, target_repo)
24
25
  checksum_match = (target_repo.saved_checksum_type == source_repo.saved_checksum_type)
25
26
 
26
- published = target_repo.backend_service(SmartProxy.pulp_primary).published?
27
-
28
27
  output[:checksum_match] = checksum_match
29
- output[:matching_content] = yum_metadata_files && srpms_match && rpms && errata && package_groups && distributions && published && checksum_match
28
+ output[:matching_content] = yum_metadata_files && srpms_match && rpms && errata && package_groups && distributions && target_repo_published && checksum_match
30
29
  end
31
30
 
32
31
  if source_repo.content_type == ::Katello::Repository::DEB_TYPE
33
32
  debs = debs_match?(source_repo, target_repo)
34
33
 
35
- output[:matching_content] = debs && target_repo.published?
34
+ output[:matching_content] = debs && target_repo_published
36
35
  end
37
36
  end
38
37
 
@@ -3,8 +3,10 @@ module Actions
3
3
  module Katello
4
4
  module Repository
5
5
  class Sync < Actions::EntryAction
6
+ extend ApipieDSL::Class
6
7
  include Helpers::Presenter
7
8
  include Actions::Katello::PulpSelector
9
+ include ::Actions::ObservableAction
8
10
  middleware.use Actions::Middleware::ExecuteIfContentsChanged
9
11
 
10
12
  input_format do
@@ -124,6 +126,63 @@ module Actions
124
126
  def rescue_strategy
125
127
  Dynflow::Action::Rescue::Skip
126
128
  end
129
+
130
+ def repository_id
131
+ input['repository']['id']
132
+ end
133
+
134
+ def repository_name
135
+ input['repository']['name']
136
+ end
137
+
138
+ def repository_label
139
+ input['repository']['label']
140
+ end
141
+
142
+ def product_id
143
+ input['product']['id']
144
+ end
145
+
146
+ def product_name
147
+ input['product']['name']
148
+ end
149
+
150
+ def product_label
151
+ input['product']['label']
152
+ end
153
+
154
+ def contents_changed
155
+ input['contents_changed']
156
+ end
157
+
158
+ def sync_result
159
+ input['sync_result']
160
+ end
161
+
162
+ apipie :class, "A class representing #{self} object" do
163
+ desc 'This object is available as **@object** variable in
164
+ webhook templates when a corresponding event occures.
165
+ The following properties can be used to retrieve the needed information.'
166
+ name "#{class_scope}"
167
+ refs "#{class_scope}"
168
+ sections only: %w[all webhooks]
169
+ property :task, object_of: 'Task', desc: 'Returns the task to which this action belongs'
170
+ property :repository_id, Integer, desc: 'Returns synced repository id'
171
+ property :repository_name, String, desc: 'Returns synced repository name'
172
+ property :repository_label, String, desc: 'Returns synced repository label'
173
+ property :product_id, Integer, desc: 'Returns product id the synced repository belongs to'
174
+ property :product_name, String, desc: 'Returns product name the synced repository belongs to'
175
+ property :product_label, String, desc: 'Returns product label the synced repository belongs to'
176
+ property :sync_result, Hash, desc: 'Returns Hash object with sync result'
177
+ property :contents_changed, one_of: [true, false], desc: 'Returns true if repository content was changed due to sync, false otherwise'
178
+ end
179
+ include Actions::Katello::JailConcern::Organization
180
+ class Jail < ::Actions::ObservableAction::Jail
181
+ allow :organization_id, :organization_name, :organization_label,
182
+ :repository_id, :repository_name, :repository_label,
183
+ :product_id, :product_name, :product_label,
184
+ :sync_result, :contents_changed
185
+ end
127
186
  end
128
187
  end
129
188
  end
@@ -2,16 +2,12 @@ module Actions
2
2
  module Pulp3
3
3
  module ContentGuard
4
4
  class Refresh < Pulp3::Abstract
5
- def plan(smart_proxy, options = {})
6
- return if (::Katello::Pulp3::ContentGuard.count > 0 || options.try(:[], :update))
7
- content_guard_api = ::Katello::Pulp3::Api::ContentGuard.new(smart_proxy)
8
- if options.try(:[], :update)
9
- content_guard_href = ::Katello::Pulp3::ContentGuard.first.href
10
- content_guard_api.partial_update content_guard_href
11
- else
12
- content_guard_api.create
13
- ::Katello::Pulp3::ContentGuard.import(smart_proxy)
14
- end
5
+ def plan(smart_proxy)
6
+ plan_self(smart_proxy_id: smart_proxy.id)
7
+ end
8
+
9
+ def run
10
+ ::Katello::Pulp3::Api::ContentGuard.new(smart_proxy).refresh
15
11
  end
16
12
  end
17
13
  end
@@ -2,7 +2,7 @@ module Actions
2
2
  module Pulp3
3
3
  module Orchestration
4
4
  module OrphanCleanup
5
- class RemoveOrphans < Pulp::Abstract
5
+ class RemoveOrphans < Pulp3::Abstract
6
6
  def plan(proxy)
7
7
  if proxy.pulp3_enabled?
8
8
  sequence do
@@ -8,6 +8,7 @@ module Katello
8
8
  @dispatch_history = Katello::Agent::DispatchHistory.find_by_id(dispatch_history_id)
9
9
 
10
10
  unless @dispatch_history
11
+ logger.error("Invalid client message: #{@json}")
11
12
  fail("No valid dispatch history in client message")
12
13
  end
13
14
  end
@@ -33,9 +34,17 @@ module Katello
33
34
  private
34
35
 
35
36
  def handle_dynflow_event
36
- task_exists = ForemanTasks::Task.exists?(external_id: @dispatch_history.dynflow_execution_plan_id, result: 'pending')
37
- unless task_exists
38
- logger.warn("Couldn't find pending task with external_id=#{@dispatch_history.dynflow_execution_plan_id} dispatch_history_id=#{@dispatch_history.id}")
37
+ return unless accepted? || result
38
+
39
+ task = ForemanTasks::Task.find_by_external_id(@dispatch_history.dynflow_execution_plan_id)
40
+
41
+ unless task
42
+ logger.info("Task external_id=#{@dispatch_history.dynflow_execution_plan_id} wasn't found. Skipping dynflow event dispatch")
43
+ return
44
+ end
45
+
46
+ unless task.result == 'pending'
47
+ logger.info("Task is no longer pending. Skipping dynflow event dispatch. task_result=#{task.result} external_id=#{@dispatch_history.dynflow_execution_plan_id} dispatch_history_id=#{@dispatch_history.id}")
39
48
  return
40
49
  end
41
50
 
@@ -53,7 +53,7 @@ module Katello
53
53
 
54
54
  class PulpcoreMissingCapabilities < StandardError
55
55
  def message
56
- _("A smart proxy seems to have been refreshed without pulpcore being running. You may want to ")
56
+ _("A smart proxy seems to have been refreshed without pulpcore being running. Please refresh the smart proxy after ensuring that pulpcore services are running.")
57
57
  end
58
58
  end
59
59
 
@@ -38,6 +38,7 @@ module Katello
38
38
  begin
39
39
  service_class.close
40
40
  service_class.run
41
+ sleep 0.1
41
42
  @service_statuses[service_name] = service_class.status
42
43
  rescue => error
43
44
  Rails.logger.error("Error occurred while starting #{service_class}")
@@ -2,8 +2,6 @@ module Katello
2
2
  module EventDaemon
3
3
  module Services
4
4
  class AgentEventReceiver
5
- STATUS_CACHE_KEY = 'katello_agent_events'.freeze
6
-
7
5
  class Handler
8
6
  attr_accessor :processed, :failed
9
7
 
@@ -48,14 +46,12 @@ module Katello
48
46
  @agent_connection&.open? && @thread&.status.present?
49
47
  end
50
48
 
51
- def self.status(refresh: true)
52
- Rails.cache.fetch(STATUS_CACHE_KEY, force: refresh) do
53
- {
54
- running: running?,
55
- processed_count: @handler&.processed || 0,
56
- failed_count: @handler&.failed || 0
57
- }
58
- end
49
+ def self.status
50
+ {
51
+ running: running?,
52
+ processed_count: @handler&.processed || 0,
53
+ failed_count: @handler&.failed || 0
54
+ }
59
55
  end
60
56
  end
61
57
  end
@@ -0,0 +1,126 @@
1
+ # Used exclusively by fix_hostgroup_facets.rake task
2
+ module Katello
3
+ module Util
4
+ class HostgroupFacetsHelper
5
+ def initialize
6
+ @logger = Logger.new($stdout)
7
+ end
8
+
9
+ def interested_hostgroups
10
+ groups = ::Hostgroup.unscoped.where(
11
+ id: Katello::Hostgroup::ContentFacet.
12
+ where(content_source_id: nil,
13
+ kickstart_repository_id: nil,
14
+ content_view_id: nil,
15
+ lifecycle_environment_id: nil).select(:hostgroup_id))
16
+ parents = groups.select { |group| group.parent.blank? }
17
+ children = groups.reject { |group| group.parent.blank? }
18
+ # we want the parents to get created before the children
19
+ # hence the order
20
+ parents + children
21
+ end
22
+
23
+ def pick_facet_values(hg)
24
+ # This call looks at the audit logs for a host group.
25
+ # Pries out information related to lce, ks, cv and content_source_id from the audit logs.
26
+ # The audit logs typically only contain updates.
27
+ # So if the user changed just the content_view_id, then that is the only thing marked as audited_changes.
28
+ # Hence we need to go through all the audit logs until we have information on lce, ks, cv and cs.
29
+ # If there was only one audit log and that was during the creation of hostgroup
30
+ # the audited changes look like this
31
+ # ```ruby
32
+ # {
33
+ # content_view_id: 10,
34
+ # kickstart_repository_id: 1000
35
+ # ......
36
+ # }
37
+ # ```
38
+ # However if you updated the hostgroup and set the kickstart_repository_id, or
39
+ # content_view_id then audited changes look like
40
+ # ```ruby
41
+ # {
42
+ # content_view_id: [10, 11],
43
+ # kickstart_repository_id: [1000, 1200]
44
+ # ......
45
+ # }
46
+ # ```
47
+ # So the code says "if the attribute value is an array pick the last value else just keep the value as it is "
48
+
49
+ # Further along it is to be noted that `hostgroup.audits` returns the audits ordered by the version number in ascending order, so the latest audit will be `hostgroup.audits.last`
50
+
51
+ # We want to iterate though each audit from latest audit to start, and as soon as we find a content_view_id key or kickstart_repository_id key or lifecycle environment_id key or content_source_id key we want it to be set once.
52
+
53
+ # So if I had an audit history like
54
+ # ``` ruby
55
+ # {
56
+ # content_view_id: 10,
57
+ # kickstart_repository_id: 1000,
58
+ # version:1
59
+ # ......
60
+ # },
61
+ # {
62
+ # content_view_id: [10, 11],
63
+ # kickstart_repository_id: [1000, 1200],
64
+ # version: 2
65
+ # ......
66
+ # }
67
+ # ```
68
+
69
+ # The code would start at version 2, notice that cv_id and ks_repo were set there
70
+ # and keep them as the final.
71
+ # So when it goes to version 1 since cv_id and ks_repo are already set,
72
+ # it will ignore. It will finally
73
+ # return {content_view_id: 11, kickstart_repository_id: 1200}
74
+ facet_values = {}
75
+ hg.audits.reverse_each do |audit|
76
+ hg_changes = audit.audited_changes.slice("lifecycle_environment_id",
77
+ "kickstart_repository_id",
78
+ "content_view_id",
79
+ "content_source_id")
80
+ facet_values = hg_changes.merge(facet_values)
81
+ end
82
+
83
+ values = facet_values.map do |k, v|
84
+ v = v[-1] if v.is_a? Array
85
+ [k, v]
86
+ end
87
+ values.to_h.with_indifferent_access
88
+ end
89
+
90
+ def main
91
+ bad_hgs = []
92
+ good_hgs = []
93
+
94
+ groups = interested_hostgroups.each do |hg|
95
+ facet = hg.content_facet
96
+ values = pick_facet_values(hg)
97
+ if !values.empty? && facet.update(values)
98
+ good_hgs << { hostgroup: hg, facet_values: values }
99
+ else
100
+ bad_hgs << { hostgroup: hg, facet_values: values }
101
+ facet.save(validate: false)
102
+ end
103
+ end
104
+
105
+ unless bad_hgs.empty?
106
+ @logger.warn "Some of the hostgroups reported a validation error. "\
107
+ "The hostgroups have been updated. "\
108
+ "Check via the Web UI."
109
+
110
+ bad_hgs.each do |bad_group|
111
+ @logger.warn "Hostgroup #{bad_group[:hostgroup]}"
112
+ @logger.warn "Facet Values #{bad_group[:facet_values]}"
113
+ end
114
+ end
115
+ unless good_hgs.empty?
116
+ @logger.info "Following hostgroups were succesfully updated."
117
+ good_hgs.each do |good_group|
118
+ @logger.info "Hostgroup #{good_group[:hostgroup]}"
119
+ @logger.info "Facet Values #{good_group[:facet_values]}"
120
+ end
121
+ end
122
+ @logger.info("#{groups.count} Hostgroup(s) were updated.")
123
+ end
124
+ end
125
+ end
126
+ end
@@ -3,6 +3,8 @@ module Katello
3
3
  class DispatchHistory < Katello::Model
4
4
  self.table_name = 'katello_agent_dispatch_histories'
5
5
 
6
+ belongs_to :host, :class_name => "::Host::Managed"
7
+
6
8
  serialize :result, Hash
7
9
 
8
10
  def accepted?
@@ -33,6 +33,18 @@ module Katello
33
33
  authorized(:view_content_views)
34
34
  end
35
35
 
36
+ def creatable
37
+ authorized(:view_content_views)
38
+ end
39
+
40
+ def importable?
41
+ creatable? && publishable?
42
+ end
43
+
44
+ def readable_as(user)
45
+ authorized_as(user, :view_content_views)
46
+ end
47
+
36
48
  def readable?
37
49
  ::User.current.can?(:view_content_views)
38
50
  end
@@ -27,6 +27,24 @@ module Katello
27
27
  joins(:root).where("#{Repository.table_name}.id in (?) or #{self.table_name}.id in (?) or #{self.table_name}.id in (?) or #{self.table_name}.id in (?)", in_products, in_content_views, in_versions, in_environments)
28
28
  end
29
29
 
30
+ def readable_as(user)
31
+ in_products = Repository.in_product(Katello::Product.authorized_as(user, :view_products)).select(:id)
32
+ in_environments = Repository.where(:environment_id => Katello::KTEnvironment.authorized_as(user, :view_lifecycle_environments)).select(:id)
33
+ in_content_views = Repository.joins(:content_view_repositories).where("#{ContentViewRepository.table_name}.content_view_id" => Katello::ContentView.readable_as(user)).select(:id)
34
+ in_versions = Repository.joins(:content_view_version).where("#{Katello::ContentViewVersion.table_name}.content_view_id" => Katello::ContentView.readable_as(user)).select(:id)
35
+ joins(:root).where("#{Repository.table_name}.id in (?) or #{self.table_name}.id in (?) or #{self.table_name}.id in (?) or #{self.table_name}.id in (?)", in_products, in_content_views, in_versions, in_environments)
36
+ end
37
+
38
+ def readable_docker_catalog
39
+ readable_docker_catalog_as(User.current)
40
+ end
41
+
42
+ def readable_docker_catalog_as(user)
43
+ table_name = Repository.table_name
44
+ in_unauth_environments = Repository.joins(:environment).where("#{Katello::KTEnvironment.table_name}.registry_unauthenticated_pull" => true).select(:id)
45
+ Repository.readable_as(user).or(Repository.joins(:root).where("#{table_name}.id in (?)", in_unauth_environments)).non_archived.docker_type
46
+ end
47
+
30
48
  def exportable
31
49
  in_product(Katello::Product.exportable)
32
50
  end
@@ -107,7 +107,9 @@ module Katello
107
107
  return true unless operatingsystem
108
108
 
109
109
  if operatingsystem.respond_to? :kickstart_repos
110
- return operatingsystem.kickstart_repos(self).any? { |repo| repo[:id] == (content_facet&.kickstart_repository_id || content_facet&.kickstart_repository&.id) }
110
+ operatingsystem.kickstart_repos(self, content_facet: content_facet).any? do |repo|
111
+ repo[:id] == (content_facet&.kickstart_repository_id || content_facet&.kickstart_repository&.id)
112
+ end
111
113
  end
112
114
  end
113
115
 
@@ -126,7 +128,7 @@ module Katello
126
128
  facet_model = Facets.registered_facets[facet].hostgroup_configuration.model
127
129
  value = facet_model.where.not(attribute => nil).joins(:hostgroup).merge(
128
130
  ::Hostgroup.where(id: self.ancestor_ids).reorder(ancestry: :desc)
129
- ).limit(1).pluck(attribute)
131
+ ).limit(1).pluck(attribute).first
130
132
  end
131
133
  value
132
134
  end
@@ -10,8 +10,15 @@ module Katello
10
10
  minor ||= '' # treat minor versions as empty string to not confuse with nil
11
11
  os = ::Redhat.where(:name => os_name, :major => major, :minor => minor).try(:first)
12
12
  return os if os
13
- description = "#{os_name}-#{repo.distribution_version}"
14
- create_os = lambda { ::Redhat.create!(:name => os_name, :major => major, :minor => minor, :description => description) }
13
+
14
+ if ::Redhat.where(:title => "#{os_name} #{repo.distribution_version}").present?
15
+ description = "#{os_name} #{repo.distribution_version} #{SecureRandom.uuid}"
16
+ create_os = lambda do
17
+ ::Redhat.create!(:name => os_name, :major => major, :minor => minor, :description => description)
18
+ end
19
+ else
20
+ create_os = lambda { ::Redhat.create!(:name => os_name, :major => major, :minor => minor) }
21
+ end
15
22
 
16
23
  begin
17
24
  create_os.call
@@ -42,33 +49,31 @@ module Katello
42
49
  end
43
50
  end
44
51
 
45
- def kickstart_repos(host)
46
- distros = distribution_repositories(host).where(distribution_bootable: true)
47
- if distros && host&.content_facet&.content_source
48
- distros.map { |distro| distro.to_hash(host.content_facet.content_source) }
52
+ def kickstart_repos(host, content_facet: nil)
53
+ distros = distribution_repositories(host, content_facet: content_facet).where(distribution_bootable: true)
54
+ content_facet ||= host.content_facet
55
+ if distros && content_facet&.content_source
56
+ distros.map { |distro| distro.to_hash(content_facet.content_source) }
49
57
  else
50
58
  []
51
59
  end
52
60
  end
53
61
 
54
- def variant_repo(host, variant)
62
+ def variant_repos(host, variant)
55
63
  if variant && host.content_source
56
64
  product_id = host.try(:content_facet).try(:kickstart_repository).try(:product_id) || host.try(:kickstart_repository).try(:product_id)
57
- distro = distribution_repositories(host)
65
+ distros = distribution_repositories(host)
58
66
  .joins(:product)
59
- .where(
60
- distribution_variant: variant,
61
- "#{Katello::Product.table_name}.id": product_id
62
- ).first
63
-
64
- distro&.to_hash(host.content_source)
67
+ .where("#{Katello::Repository.table_name}.distribution_variant LIKE :variant", { variant: "%#{variant}%" })
68
+ .where("#{Katello::Product.table_name}.id": product_id).collect { |repo| repo.to_hash(host.content_source, true) }
69
+ distros
65
70
  end
66
71
  end
67
72
 
68
- def distribution_repositories(host)
69
- content_view = host.try(:content_facet).try(:content_view) || host.try(:content_view)
70
- lifecycle_environment = host.try(:content_facet).try(:lifecycle_environment) || host.try(:lifecycle_environment)
71
-
73
+ def distribution_repositories(host, content_facet: nil)
74
+ content_facet ||= host.content_facet
75
+ content_view = content_facet.try(:content_view) || host.try(:content_view)
76
+ lifecycle_environment = content_facet.try(:lifecycle_environment) || host.try(:lifecycle_environment)
72
77
  if content_view && lifecycle_environment && host.os && host.architecture
73
78
  Katello::Repository.in_environment(lifecycle_environment).in_content_views([content_view]).
74
79
  where(:distribution_arch => host.architecture.name).