Revision 63fbccbf
Added by Martin Bacovsky over 5 years ago
app/views/unattended/report_templates/host_statuses_csv.erb | ||
---|---|---|
snippet: false
|
||
model: ReportTemplate
|
||
-%>
|
||
Name,Global,<%= all_host_statuses.map { |s| s.status_name }.join(',') %>
|
||
<%- load_hosts(includes: :host_statuses).each_record do |host| -%>
|
||
<%= host.name -%>,<%= host.global_status -%>,<%= all_host_statuses.map { |s| host_status(host, s.status_name).status }.join(',') %>
|
||
<%- report_row({
|
||
'Name': host.name,
|
||
'Global': host.global_status
|
||
}.merge(all_host_statuses_hash(host))) -%>
|
||
<%- end -%>
|
||
<%= report_render -%>
|
lib/foreman/renderer/configuration.rb | ||
---|---|---|
:medium_uri,
|
||
:load_hosts,
|
||
:all_host_statuses,
|
||
:all_host_statuses_hash,
|
||
:host_status,
|
||
:preview?,
|
||
:raise
|
lib/foreman/renderer/scope/macros/base.rb | ||
---|---|---|
@all_host_statuses ||= HostStatus.status_registry.to_a.sort_by(&:status_name)
|
||
end
|
||
|
||
def all_host_statuses_hash(host)
|
||
all_host_statuses.map { |status| [status.status_name, host_status(host, status.status_name).status] }.to_h
|
||
end
|
||
|
||
def host_status(host, name)
|
||
klass = all_host_statuses.find { |status| status.status_name == name }
|
||
raise UnknownHostStatusError.new(status: name, statuses: all_host_statuses.map(&:status_name).join(',')) if klass.nil?
|
lib/foreman/renderer/scope/report.rb | ||
---|---|---|
module Renderer
|
||
module Scope
|
||
class Report < Foreman::Renderer::Scope::Base
|
||
def initialize(**args)
|
||
super
|
||
@report_data = []
|
||
@report_headers = []
|
||
end
|
||
|
||
def report_render(format: :csv)
|
||
case format
|
||
when :csv
|
||
report_render_csv
|
||
when :yaml
|
||
report_render_yaml
|
||
end
|
||
end
|
||
|
||
def report_row(row_data)
|
||
@report_headers = row_data.keys.map(&:to_s) if @report_headers.empty?
|
||
@report_data << row_data.values
|
||
end
|
||
|
||
def allowed_helpers
|
||
@allowed_helpers ||= super + [ :report_row, :report_render ]
|
||
end
|
||
|
||
private
|
||
|
||
def report_render_yaml
|
||
@report_data.map do |row|
|
||
valid_row = row.map { |cell| valid_yaml_type(cell) }
|
||
Hash[@report_headers.zip(valid_row)]
|
||
end.to_yaml
|
||
end
|
||
|
||
def report_render_csv
|
||
CSV.generate(headers: true, encoding: Encoding::UTF_8) do |csv|
|
||
csv << @report_headers
|
||
@report_data.each do |row|
|
||
csv << row.map { |cell| serialize_cell(cell) }
|
||
end
|
||
end
|
||
end
|
||
|
||
def serialize_cell(cell)
|
||
if cell.is_a?(Enumerable)
|
||
cell.map(&:to_s).join(',')
|
||
else
|
||
cell.to_s
|
||
end
|
||
end
|
||
|
||
def valid_yaml_type(cell)
|
||
if cell.is_a?(String) || [true, false].include?(cell) || cell.is_a?(Numeric) || cell.nil?
|
||
cell
|
||
elsif cell.is_a?(Enumerable)
|
||
cell.map { |item| valid_yaml_type(item) }
|
||
else
|
||
cell.to_s
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
test/unit/foreman/renderer/scope/report_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class ReportScopeTest < ActiveSupport::TestCase
|
||
setup do
|
||
source = Foreman::Renderer::Source::String.new(content: '')
|
||
@scope = Foreman::Renderer::Scope::Report.new(source: source)
|
||
end
|
||
|
||
describe '#report_render' do
|
||
test 'render headers' do
|
||
@scope.report_row('Col1': 'Val1', 'Col2': 'Val2')
|
||
@scope.report_row('Col3': 'Val3', 'Col4': 'Val4')
|
||
expected_csv = "Col1,Col2\nVal1,Val2\nVal3,Val4\n"
|
||
assert_equal expected_csv, @scope.report_render(format: :csv)
|
||
|
||
expected_yaml = <<~OUT
|
||
---
|
||
- Col1: Val1
|
||
Col2: Val2
|
||
- Col1: Val3
|
||
Col2: Val4
|
||
OUT
|
||
assert_equal expected_yaml, @scope.report_render(format: :yaml)
|
||
end
|
||
|
||
test 'empty report' do
|
||
expected_csv = "\n"
|
||
assert_equal expected_csv, @scope.report_render(format: :csv)
|
||
|
||
expected_yaml = <<~OUT
|
||
--- []
|
||
OUT
|
||
assert_equal expected_yaml, @scope.report_render(format: :yaml)
|
||
end
|
||
|
||
test 'render types' do
|
||
@scope.report_row(
|
||
'List': ['Val1', 1, true],
|
||
'String': 'Text',
|
||
'Number': 1,
|
||
'Bool': false,
|
||
'Empty': '',
|
||
'Nil': nil
|
||
)
|
||
expected_csv = "List,String,Number,Bool,Empty,Nil\n\"Val1,1,true\",Text,1,false,\"\",\"\"\n"
|
||
assert_equal expected_csv, @scope.report_render(format: :csv)
|
||
|
||
expected_yaml = <<~OUT + " Nil: \n"
|
||
---
|
||
- List:
|
||
- Val1
|
||
- 1
|
||
- true
|
||
String: Text
|
||
Number: 1
|
||
Bool: false
|
||
Empty: ''
|
||
OUT
|
||
assert_equal expected_yaml, @scope.report_render(format: :yaml)
|
||
end
|
||
end
|
||
end
|
Also available in: Unified diff
Fixes #25099 - Add macros for easier report definition
Add rows to a report with
<%- report_row(
'Column header 1': 'Value 1',
'Column header 2': `Value 2`,
) ->
and render the report with
<= report_render -%>
Each row of the report needs to have the same columns.
report_render produces properly quoted valid CSV.
Values are converted to a String using to_s.
Enumerable values are comma separated and serialized.
Experimental render to YAML is included (report_render(format: :yaml)
Enumerable values are kept structured in this format.