On Foreman/Katello 3.13/4.15 and when using the “Host - Installed packages” report in html format there is a couple of uses:
All data in the tables comes unsorted Would be nice is it could sort in perhaps host?
When more then one package is added to the search, packages are randomly placed in different columns. See attachment (replaced my real hostnames with dummy.dummmy.local).
Since I do not know this programming language, I have tried to use AI but all attempts ends up with the “Safemode doesn’t allow to access” error in the production.log.
ex.
2025-01-24T18:12:57 [E|bac|819a4836] Safemode doesn't allow to access 'attrasgn' on hash[p.to_jail.name] = p.to_jail.nvrea (Safemode::SecurityError)
819a4836 | /usr/share/gems/gems/safemode-1.5.0/lib/safemode/parser.rb:140:in `raise_security_error'
819a4836 | /usr/share/gems/gems/safemode-1.5.0/lib/safemode/parser.rb:121:in `block (2 levels) in <class:Parser>'
2025-01-24T18:12:57 [E|app|819a4836] Error performing TemplateRenderJob (Job ID: a79208a9-4ff9-4772-8937-a961afe1dcfc) from Dynflow(default) in 17.28ms: Safemode::SecurityError (Safemode doesn't allow to access 'attrasgn' on hash[p.to_jail.name] = p.to_jail.nvrea):
819a4836 | /usr/share/gems/gems/safemode-1.5.0/lib/safemode/parser.rb:140:in `raise_security_error'
When editing a template you can go to the “Help” tab and scroll down, and see a list of all methods that are available in safemode. I see that .sort is available on arrays. So you could try changing host_pkgs.each to host_pkgs.sort.each and see if that helps.
With that code I get again the “Safemode doesn’t allow to access ‘attrasgn’ on this_row[k] = contains.to_jail[k] (Safemode::SecurityError)”
I however sat just now with copilot just now, fed it the safe mode documentation and after like 10 failed attempts it spit out some code that actually worked this time:
<%- hosts_data = [] -%>
<%- load_hosts(includes: :installed_packages).each_record do |host| -%>
<% pkgs = input('packages').split(',') %>
<% host_pkgs = host.installed_packages.select { |p| pkgs.include?(p.name) } %>
<% unless host_pkgs.empty? %>
<% contains = {} %>
<% pkgs.each do |pkg| %>
<% package = host_pkgs.find { |p| p.name == pkg } %>
<% contains.store(pkg, package ? package.nvrea : '') %>
<% end %>
<% hosts_data << { 'Host' => host.name }.merge(contains) %>
<% end %>
<%- end -%>
<%# Sort the collected data by host name %>
<%- sorted_hosts_data = hosts_data.sort_by { |row| row['Host'] } -%>
<%# Generate the report from the sorted data %>
<%- sorted_hosts_data.each do |row| -%>
<% report_row(row) %>
<%- end -%>
<%= report_render %>
Not a programmer so no idea if the code make sense or is ugly but it worked!
From Copilot:
Explanation:
Collect Data:
We use select to filter the installed packages that match the input packages.
We initialize an empty hash contains.
Ensure Consistent Columns:
We iterate over the input packages (pkgs) and check if each package is installed on the host.
If the package is installed, we add it to the contains hash with its version (nvrea) using the store method.
If the package is not installed, we add an empty string to ensure the column exists.
Sort Data:
We sort the hosts_data array by the ‘Host’ key using sort_by.
Generate Report:
We iterate over the sorted data and use report_row to generate the report.
This approach should help you avoid the Safemode errors while achieving the desired sorting and column alignment. Let me know if this works for you or if you need any further adjustments!