forked from Katello/katello
-
Notifications
You must be signed in to change notification settings - Fork 0
/
applicable_content_helper.rb
164 lines (142 loc) · 8.18 KB
/
applicable_content_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
module Katello
module Applicability
class ApplicableContentHelper
attr_accessor :content_facet, :content_unit_class, :bound_library_instance_repos
def initialize(content_facet, content_unit_class, bound_library_instance_repos)
self.content_facet = content_facet
self.content_unit_class = content_unit_class
self.bound_library_instance_repos = bound_library_instance_repos
end
def calculate_and_import
if self.bound_library_instance_repos.any?
to_add, to_remove = applicable_differences
ActiveRecord::Base.transaction do
insert(to_add) unless to_add.blank?
remove(to_remove) unless to_remove.blank?
end
end
end
def fetch_content_ids
if self.content_unit_class == ::Katello::Erratum
fetch_errata_content_ids
elsif self.content_unit_class == ::Katello::ModuleStream
fetch_module_stream_content_ids
else
fetch_rpm_content_ids
end
end
def fetch_errata_content_ids
# Query for all Errata ids that are attached to the host's applicable packages
query = 'SELECT DISTINCT katello_repository_errata.erratum_id AS id FROM katello_repository_errata
INNER JOIN katello_erratum_packages
ON katello_repository_errata.erratum_id = katello_erratum_packages.erratum_id
INNER JOIN katello_rpms
ON katello_rpms.nvra = katello_erratum_packages.nvrea
INNER JOIN katello_content_facet_applicable_rpms
ON katello_content_facet_applicable_rpms.rpm_id = katello_rpms.id
WHERE katello_content_facet_applicable_rpms.content_facet_id = :content_facet_id
AND katello_repository_errata.repository_id IN (:repo_ids)'
return Katello::Erratum.find_by_sql([query, { content_facet_id: content_facet.id, repo_ids: self.bound_library_instance_repos }]).map(&:id)
end
def fetch_module_stream_content_ids
# Query for all applicable module stream ids
query = 'SELECT DISTINCT katello_repository_module_streams.module_stream_id AS id FROM katello_repository_module_streams
INNER JOIN katello_module_stream_rpms
ON katello_repository_module_streams.module_stream_id = katello_module_stream_rpms.module_stream_id
INNER JOIN katello_rpms
ON katello_rpms.id = katello_module_stream_rpms.rpm_id
INNER JOIN katello_content_facet_applicable_rpms
ON katello_content_facet_applicable_rpms.rpm_id = katello_rpms.id
WHERE katello_content_facet_applicable_rpms.content_facet_id = :content_facet_id
AND katello_repository_module_streams.repository_id IN (:repo_ids)'
return Katello::ModuleStream.find_by_sql([query, { content_facet_id: content_facet.id, repo_ids: self.bound_library_instance_repos }]).map(&:id)
end
def fetch_rpm_content_ids
enabled_module_stream_ids = fetch_enabled_module_stream_ids
::Katello::Rpm.
joins("INNER JOIN katello_repository_rpms ON
katello_rpms.id = katello_repository_rpms.rpm_id").
joins("INNER JOIN katello_installed_packages ON
katello_rpms.name = katello_installed_packages.name AND
katello_rpms.arch = katello_installed_packages.arch AND
katello_rpms.evr > katello_installed_packages.evr AND
katello_installed_packages.id in (#{newest_distinct_installed_packages_query})").
joins("LEFT JOIN katello_module_stream_rpms ON
katello_rpms.id = katello_module_stream_rpms.rpm_id").
joins("INNER JOIN katello_host_installed_packages ON
katello_installed_packages.id = katello_host_installed_packages.installed_package_id").
where("katello_repository_rpms.repository_id in (:bound_library_repos)",
:bound_library_repos => self.bound_library_instance_repos).
where("katello_host_installed_packages.host_id = :content_facet_id",
:content_facet_id => self.content_facet.host.id).
where("(katello_module_stream_rpms.module_stream_id IS NULL AND
katello_installed_packages.id NOT IN (:locked_modular_installed_packages)) OR
(katello_module_stream_rpms.module_stream_id IN (:enabled_module_streams)
AND katello_installed_packages.id IN (:locked_modular_installed_packages))",
:enabled_module_streams => enabled_module_stream_ids,
:locked_modular_installed_packages => locked_modular_installed_packages(enabled_module_stream_ids)).pluck(:id).uniq
end
def fetch_enabled_module_stream_ids
# Query for applicable RPM ids
# -> Include all non-modular rpms or rpms that exist within installed module streams
::Katello::ModuleStream.
joins("inner join katello_available_module_streams on
katello_module_streams.name = katello_available_module_streams.name and
katello_module_streams.stream = katello_available_module_streams.stream").
joins("inner join katello_host_available_module_streams on
katello_available_module_streams.id = katello_host_available_module_streams.available_module_stream_id").
where("katello_host_available_module_streams.host_id = :content_facet_id and
katello_host_available_module_streams.status = 'enabled'",
:content_facet_id => self.content_facet.host.id).select(:id)
end
# Installed packages that are locked for the host due to enabled module stream membership
def locked_modular_installed_packages(enabled_module_streams)
rpms_in_enabled_module_streams = ::Katello::Rpm.
joins("INNER JOIN katello_module_stream_rpms ON katello_rpms.id = katello_module_stream_rpms.rpm_id").
where("katello_module_stream_rpms.module_stream_id IN (:enabled_module_streams)",
:enabled_module_streams => enabled_module_streams).select(:nvra, :epoch)
::Katello::InstalledPackage.where(nvra: rpms_in_enabled_module_streams.map(&:nvra),
epoch: rpms_in_enabled_module_streams.map(&:epoch)).select(:id)
end
def newest_distinct_installed_packages_query
"SELECT DISTINCT ON (katello_installed_packages.name) katello_installed_packages.id " \
"FROM katello_installed_packages INNER JOIN " \
"katello_host_installed_packages ON " \
"katello_installed_packages.id = " \
"katello_host_installed_packages.installed_package_id " \
"WHERE katello_host_installed_packages.host_id = " \
"#{content_facet.host.id} ORDER BY katello_installed_packages.name, katello_installed_packages.evr DESC"
end
def applicable_differences
consumer_ids = content_facet.send(applicable_units).pluck("#{content_unit_class.table_name}.id")
content_ids = fetch_content_ids
to_remove = consumer_ids - content_ids
to_add = content_ids - consumer_ids
[to_add, to_remove]
end
def insert(applicable_ids)
unless applicable_ids.empty?
inserts = applicable_ids.map { |applicable_id| "(#{applicable_id.to_i}, #{content_facet.id.to_i})" }
sql = "INSERT INTO #{content_facet_association_class.table_name} (#{content_unit_association_id}, content_facet_id) VALUES #{inserts.join(', ')}"
ActiveRecord::Base.connection.execute(sql)
end
end
def remove(applicable_ids)
content_facet_association_class.where(:content_facet_id => content_facet.id, content_unit_association_id => applicable_ids).delete_all
end
def content_unit_association_id
"#{content_unit_class.name.demodulize.underscore}_id".to_sym
end
def content_facet_association_class
# Example: ContentFacetErratum
self.content_unit_class.content_facet_association_class
end
def content_units
content_unit_class.name.demodulize.pluralize.underscore.to_sym
end
def applicable_units
"applicable_#{content_units}".to_sym
end
end
end
end