foreman_inventory_upload 0.0.1.dev1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +619 -0
- data/README.md +38 -0
- data/Rakefile +47 -0
- data/app/controllers/foreman_inventory_upload/react_controller.rb +7 -0
- data/app/controllers/foreman_inventory_upload/reports_controller.rb +23 -0
- data/app/controllers/foreman_inventory_upload/statuses_controller.rb +41 -0
- data/app/controllers/foreman_inventory_upload/uploads_controller.rb +31 -0
- data/app/helpers/foreman_inventory_upload_helper.rb +13 -0
- data/app/views/dashboard/_inventory_upload_widget.html.erb +2 -0
- data/app/views/foreman_inventory_upload/layouts/react.html.erb +16 -0
- data/app/views/scripts/uploader.sh.erb +31 -0
- data/config/routes.rb +10 -0
- data/lib/foreman_inventory_upload/async/generate_report_job.rb +29 -0
- data/lib/foreman_inventory_upload/async/progress_output.rb +61 -0
- data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +52 -0
- data/lib/foreman_inventory_upload/async/shell_process.rb +35 -0
- data/lib/foreman_inventory_upload/async/upload_report_job.rb +40 -0
- data/lib/foreman_inventory_upload/engine.rb +52 -0
- data/lib/foreman_inventory_upload/generators/archived_report.rb +53 -0
- data/lib/foreman_inventory_upload/generators/json_stream.rb +55 -0
- data/lib/foreman_inventory_upload/generators/metadata.rb +36 -0
- data/lib/foreman_inventory_upload/generators/queries.rb +52 -0
- data/lib/foreman_inventory_upload/generators/slice.rb +117 -0
- data/lib/foreman_inventory_upload/version.rb +3 -0
- data/lib/foreman_inventory_upload.rb +48 -0
- data/lib/tasks/foreman_inventory_upload_tasks.rake +37 -0
- data/lib/tasks/generator.rake +15 -0
- data/locale/Makefile +60 -0
- data/locale/en/foreman_yupana.po +19 -0
- data/locale/foreman_yupana.pot +19 -0
- data/locale/gemspec.rb +2 -0
- data/test/controllers/reports_controller_test.rb +21 -0
- data/test/controllers/statuses_controller_test.rb +26 -0
- data/test/controllers/uploads_controller_test.rb +21 -0
- data/test/factories/inventory_upload_factories.rb +88 -0
- data/test/test_plugin_helper.rb +26 -0
- data/test/unit/archived_report_generator_test.rb +61 -0
- data/test/unit/metadata_generator_test.rb +40 -0
- data/test/unit/shell_process_job_test.rb +27 -0
- data/test/unit/slice_generator_test.rb +60 -0
- metadata +149 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
module ForemanInventoryUpload
|
2
|
+
module Generators
|
3
|
+
class Queries
|
4
|
+
def self.fact_names
|
5
|
+
@fact_names ||= Hash[
|
6
|
+
Katello::RhsmFactName.where(name:
|
7
|
+
[
|
8
|
+
'dmi::system::uuid',
|
9
|
+
'virt::uuid',
|
10
|
+
'cpu::cpu(s)',
|
11
|
+
'cpu::cpu_socket(s)',
|
12
|
+
'cpu::core(s)_per_socket',
|
13
|
+
'memory::memtotal',
|
14
|
+
'dmi::bios::vendor',
|
15
|
+
'dmi::bios::version',
|
16
|
+
'dmi::bios::relase_date',
|
17
|
+
'distribution::name',
|
18
|
+
'uname::release',
|
19
|
+
'lscpu::flags'
|
20
|
+
]).pluck(:name, :id)
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.for_slice(base)
|
25
|
+
fact_values = FactValue.where(fact_name_id: fact_names.values)
|
26
|
+
base
|
27
|
+
.joins(:subscription_facet)
|
28
|
+
.eager_load(:fact_values)
|
29
|
+
.preload(
|
30
|
+
:interfaces,
|
31
|
+
:installed_packages,
|
32
|
+
:content_facet,
|
33
|
+
:host_statuses,
|
34
|
+
subscription_facet: %i[pools installed_products]
|
35
|
+
)
|
36
|
+
.merge(fact_values)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.for_report(portal_user)
|
40
|
+
org_ids = Organization
|
41
|
+
.joins(:telemetry_configuration)
|
42
|
+
.where(
|
43
|
+
redhat_access_telemetry_configurations: {
|
44
|
+
portal_user: portal_user,
|
45
|
+
enable_telemetry: true
|
46
|
+
}
|
47
|
+
).pluck(:id)
|
48
|
+
for_slice(Host.where(organization_id: org_ids)).in_batches(of: 1_000)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module ForemanInventoryUpload
|
2
|
+
module Generators
|
3
|
+
class Slice
|
4
|
+
attr_accessor :slice_id
|
5
|
+
|
6
|
+
def initialize(hosts, output = [], slice_id = Foreman.uuid)
|
7
|
+
@stream = JsonStream.new(output)
|
8
|
+
@hosts = hosts
|
9
|
+
@slice_id = slice_id
|
10
|
+
end
|
11
|
+
|
12
|
+
def render
|
13
|
+
report_slice(@hosts)
|
14
|
+
@stream.out
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def report_slice(hosts_batch)
|
20
|
+
@stream.object do
|
21
|
+
@stream.simple_field('report_slice_id', @slice_id)
|
22
|
+
@stream.array_field('hosts', :last) do
|
23
|
+
first = true
|
24
|
+
hosts_batch.each do |host|
|
25
|
+
@stream.comma unless first
|
26
|
+
first = false
|
27
|
+
report_host(host)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def report_host(host)
|
34
|
+
@stream.object do
|
35
|
+
@stream.simple_field('display_name', host.name)
|
36
|
+
@stream.simple_field('fqdn', host.fqdn)
|
37
|
+
@stream.simple_field('account', host.subscription_facet.pools.first.account_number.to_s)
|
38
|
+
@stream.simple_field('subscription_manager_id', host.subscription_facet.uuid)
|
39
|
+
@stream.simple_field('satellite_id', host.subscription_facet.uuid)
|
40
|
+
@stream.simple_field('bios_uuid', fact_value(host, 'dmi::system::uuid'))
|
41
|
+
@stream.simple_field('vm_uuid', fact_value(host, 'virt::uuid'))
|
42
|
+
@stream.array_field('ip_addresses') do
|
43
|
+
@stream.raw(host.interfaces.map do |nic|
|
44
|
+
@stream.stringify_value(nic.ip) if nic.ip
|
45
|
+
end.compact.join(', '))
|
46
|
+
end
|
47
|
+
@stream.array_field('mac_addresses') do
|
48
|
+
@stream.raw(host.interfaces.map do |nic|
|
49
|
+
@stream.stringify_value(nic.mac) if nic.mac
|
50
|
+
end.compact.join(', '))
|
51
|
+
end
|
52
|
+
@stream.object_field('system_profile', :last) do
|
53
|
+
report_system_profile(host)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def report_system_profile(host)
|
59
|
+
@stream.simple_field('number_of_cpus', fact_value(host, 'cpu::cpu(s)').to_i)
|
60
|
+
@stream.simple_field('number_of_sockets', fact_value(host, 'cpu::cpu_socket(s)').to_i)
|
61
|
+
@stream.simple_field('cores_per_socket', fact_value(host, 'cpu::core(s)_per_socket').to_i)
|
62
|
+
@stream.simple_field('system_memory_bytes', fact_value(host, 'memory::memtotal').to_i)
|
63
|
+
@stream.array_field('network_interfaces') do
|
64
|
+
@stream.raw(host.interfaces.map do |nic|
|
65
|
+
{
|
66
|
+
'ipv4_addresses': [nic.ip].compact,
|
67
|
+
'ipv6_addresses': [nic.ip6].compact,
|
68
|
+
'mtu': nic.mtu,
|
69
|
+
'mac_address': nic.mac,
|
70
|
+
'name': nic.identifier
|
71
|
+
}.compact.to_json
|
72
|
+
end.join(', '))
|
73
|
+
end
|
74
|
+
@stream.simple_field('bios_vendor', fact_value(host, 'dmi::bios::vendor'))
|
75
|
+
@stream.simple_field('bios_version', fact_value(host, 'dmi::bios::version'))
|
76
|
+
@stream.simple_field('bios_release_date', fact_value(host, 'dmi::bios::relase_date'))
|
77
|
+
if (cpu_flags = fact_value(host, 'lscpu::flags'))
|
78
|
+
@stream.array_field('cpu_flags') do
|
79
|
+
@stream.raw(cpu_flags.split.map do |flag|
|
80
|
+
@stream.stringify_value(flag)
|
81
|
+
end.join(', '))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
@stream.simple_field('os_release', fact_value(host, 'distribution::name'))
|
85
|
+
@stream.simple_field('os_kernel_version', fact_value(host, 'uname::release'))
|
86
|
+
@stream.simple_field('arch', host.architecture&.name)
|
87
|
+
@stream.simple_field('subscription_status', host.subscription_status_label)
|
88
|
+
@stream.simple_field('katello_agent_running', host.content_facet&.katello_agent_installed?)
|
89
|
+
@stream.simple_field('satellite_managed', true)
|
90
|
+
unless (installed_products = host.subscription_facet&.installed_products).empty?
|
91
|
+
@stream.array_field('installed_products') do
|
92
|
+
@stream.raw(installed_products.map do |product|
|
93
|
+
{
|
94
|
+
'name': product.name,
|
95
|
+
'id': product.cp_product_id
|
96
|
+
}.to_json
|
97
|
+
end.join(', '))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
@stream.array_field('installed_packages', :last) do
|
101
|
+
first = true
|
102
|
+
host.installed_packages.each do |package|
|
103
|
+
@stream.raw("#{first ? '' : ', '}#{@stream.stringify_value(package.nvra)}")
|
104
|
+
first = false
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def fact_value(host, fact_name)
|
110
|
+
value_record = host.fact_values.find do |fact_value|
|
111
|
+
fact_value.fact_name_id == ForemanInventoryUpload::Generators::Queries.fact_names[fact_name]
|
112
|
+
end
|
113
|
+
value_record&.value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'foreman_inventory_upload/engine'
|
2
|
+
|
3
|
+
module ForemanInventoryUpload
|
4
|
+
def self.base_folder
|
5
|
+
# in production setup, where selinux is enabled, we only have rights to
|
6
|
+
# create folders under /ver/lib/foreman. If the folder does not exist, it's
|
7
|
+
# a dev setup, where we can use our current root
|
8
|
+
@base_folder ||= File.join(
|
9
|
+
Dir.glob('/var/lib/foreman').first || Dir.getwd,
|
10
|
+
'red_hat_inventory/'
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.uploads_folder(group)
|
15
|
+
@uploads_folders ||= {}
|
16
|
+
cache = @uploads_folders[group]
|
17
|
+
return cache if cache
|
18
|
+
|
19
|
+
@uploads_folders[group] = ensure_folder(
|
20
|
+
File.join(
|
21
|
+
ForemanInventoryUpload.base_folder,
|
22
|
+
'uploads/',
|
23
|
+
"#{group}/"
|
24
|
+
)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.outputs_folder
|
29
|
+
@outputs_folder ||= ensure_folder(File.join(ForemanInventoryUpload.base_folder, 'outputs/'))
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.upload_script_file
|
33
|
+
'uploader.sh'
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.facts_archive_name
|
37
|
+
'hosts_report.tar.gz'
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.upload_url
|
41
|
+
'https://ci.cloud.paas.psi.redhat.com/api/ingress/v1/upload'
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.ensure_folder(folder)
|
45
|
+
FileUtils.mkdir_p(folder)
|
46
|
+
folder
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
# Tests
|
4
|
+
namespace :test do
|
5
|
+
desc 'Test ForemanInventoryUpload'
|
6
|
+
Rake::TestTask.new(:foreman_inventory_upload) do |t|
|
7
|
+
test_dir = File.join(File.dirname(__FILE__), '../..', 'test')
|
8
|
+
t.libs << ['test', test_dir]
|
9
|
+
t.pattern = "#{test_dir}/**/*_test.rb"
|
10
|
+
t.verbose = true
|
11
|
+
t.warning = false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
namespace :foreman_inventory_upload do
|
16
|
+
task :rubocop do
|
17
|
+
begin
|
18
|
+
require 'rubocop/rake_task'
|
19
|
+
RuboCop::RakeTask.new(:rubocop_foreman_inventory_upload) do |task|
|
20
|
+
task.patterns = ["#{ForemanInventoryUpload::Engine.root}/app/**/*.rb",
|
21
|
+
"#{ForemanInventoryUpload::Engine.root}/lib/**/*.rb",
|
22
|
+
"#{ForemanInventoryUpload::Engine.root}/test/**/*.rb"]
|
23
|
+
end
|
24
|
+
rescue
|
25
|
+
puts 'Rubocop not loaded.'
|
26
|
+
end
|
27
|
+
|
28
|
+
Rake::Task['rubocop_foreman_inventory_upload'].invoke
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Rake::Task[:test].enhance ['test:foreman_inventory_upload']
|
33
|
+
|
34
|
+
load 'tasks/jenkins.rake'
|
35
|
+
if Rake::Task.task_defined?(:'jenkins:unit')
|
36
|
+
Rake::Task['jenkins:unit'].enhance ['test:foreman_inventory_upload', 'foreman_inventory_upload:rubocop']
|
37
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
namespace :foreman_inventory_upload do
|
4
|
+
namespace :report do
|
5
|
+
desc 'Generate inventory report to be sent to Red Hat cloud'
|
6
|
+
task generate: :environment do
|
7
|
+
target = ENV['target'] || ForemanInventoryUpload.facts_archive_name
|
8
|
+
portal_user = ENV['portal_user'] || 'anonymous'
|
9
|
+
|
10
|
+
archived_report_generator = ForemanInventoryUpload::Generators::ArchivedReport.new(target, Logger.new(STDOUT))
|
11
|
+
archived_report_generator.render(portal_user)
|
12
|
+
puts "Successfully generated #{target} for #{portal_user}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/locale/Makefile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Makefile for PO merging and MO generation. More info in the README.
|
3
|
+
#
|
4
|
+
# make all-mo (default) - generate MO files
|
5
|
+
# make check - check translations using translate-tool
|
6
|
+
# make tx-update - download and merge translations from Transifex
|
7
|
+
# make clean - clean everything
|
8
|
+
#
|
9
|
+
DOMAIN = foreman_yupana
|
10
|
+
VERSION = $(shell ruby -e 'require "rubygems";spec = Gem::Specification::load(Dir.glob("../*.gemspec")[0]);puts spec.version')
|
11
|
+
POTFILE = $(DOMAIN).pot
|
12
|
+
MOFILE = $(DOMAIN).mo
|
13
|
+
POFILES = $(shell find . -name '$(DOMAIN).po')
|
14
|
+
MOFILES = $(patsubst %.po,%.mo,$(POFILES))
|
15
|
+
POXFILES = $(patsubst %.po,%.pox,$(POFILES))
|
16
|
+
EDITFILES = $(patsubst %.po,%.edit.po,$(POFILES))
|
17
|
+
|
18
|
+
%.mo: %.po
|
19
|
+
mkdir -p $(shell dirname $@)/LC_MESSAGES
|
20
|
+
msgfmt -o $(shell dirname $@)/LC_MESSAGES/$(MOFILE) $<
|
21
|
+
|
22
|
+
# Generate MO files from PO files
|
23
|
+
all-mo: $(MOFILES)
|
24
|
+
|
25
|
+
# Check for malformed strings
|
26
|
+
%.pox: %.po
|
27
|
+
msgfmt -c $<
|
28
|
+
pofilter --nofuzzy -t variables -t blank -t urls -t emails -t long -t newlines \
|
29
|
+
-t endwhitespace -t endpunc -t puncspacing -t options -t printf -t validchars --gnome $< > $@
|
30
|
+
cat $@
|
31
|
+
! grep -q msgid $@
|
32
|
+
|
33
|
+
%.edit.po:
|
34
|
+
touch $@
|
35
|
+
|
36
|
+
check: $(POXFILES)
|
37
|
+
|
38
|
+
# Unify duplicate translations
|
39
|
+
uniq-po:
|
40
|
+
for f in $(shell find ./ -name "*.po") ; do \
|
41
|
+
msguniq $$f -o $$f ; \
|
42
|
+
done
|
43
|
+
|
44
|
+
tx-pull: $(EDITFILES)
|
45
|
+
tx pull -f
|
46
|
+
for f in $(EDITFILES) ; do \
|
47
|
+
sed -i 's/^\("Project-Id-Version: \).*$$/\1$(DOMAIN) $(VERSION)\\n"/' $$f; \
|
48
|
+
done
|
49
|
+
|
50
|
+
tx-update: tx-pull
|
51
|
+
@echo
|
52
|
+
@echo Run rake plugin:gettext[$(DOMAIN)] from the Foreman installation, then make -C locale mo-files to finish
|
53
|
+
@echo
|
54
|
+
|
55
|
+
mo-files: $(MOFILES)
|
56
|
+
git add $(POFILES) $(POTFILE) ../locale/*/LC_MESSAGES
|
57
|
+
git commit -m "i18n - pulling from tx"
|
58
|
+
@echo
|
59
|
+
@echo Changes commited!
|
60
|
+
@echo
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# foreman_yupana
|
2
|
+
#
|
3
|
+
# This file is distributed under the same license as foreman_yupana.
|
4
|
+
#
|
5
|
+
#, fuzzy
|
6
|
+
msgid ""
|
7
|
+
msgstr ""
|
8
|
+
"Project-Id-Version: version 0.0.1\n"
|
9
|
+
"Report-Msgid-Bugs-To: \n"
|
10
|
+
"POT-Creation-Date: 2014-08-20 08:46+0100\n"
|
11
|
+
"PO-Revision-Date: 2014-08-20 08:54+0100\n"
|
12
|
+
"Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
|
13
|
+
"Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
|
14
|
+
"Language: \n"
|
15
|
+
"MIME-Version: 1.0\n"
|
16
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
17
|
+
"Content-Transfer-Encoding: 8bit\n"
|
18
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
19
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# foreman_yupana
|
2
|
+
#
|
3
|
+
# This file is distributed under the same license as foreman_yupana.
|
4
|
+
#
|
5
|
+
#, fuzzy
|
6
|
+
msgid ""
|
7
|
+
msgstr ""
|
8
|
+
"Project-Id-Version: version 0.0.1\n"
|
9
|
+
"Report-Msgid-Bugs-To: \n"
|
10
|
+
"POT-Creation-Date: 2014-08-20 08:46+0100\n"
|
11
|
+
"PO-Revision-Date: 2014-08-20 08:46+0100\n"
|
12
|
+
"Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
|
13
|
+
"Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
|
14
|
+
"Language: \n"
|
15
|
+
"MIME-Version: 1.0\n"
|
16
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
17
|
+
"Content-Transfer-Encoding: 8bit\n"
|
18
|
+
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
19
|
+
|
data/locale/gemspec.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class ReportsControllerTest < ActionController::TestCase
|
4
|
+
tests ForemanInventoryUpload::ReportsController
|
5
|
+
|
6
|
+
test 'Returns latest report generation status' do
|
7
|
+
progress_output = mock('progress_output')
|
8
|
+
test_portal_user = 'test_portal_user'
|
9
|
+
ForemanInventoryUpload::Async::ProgressOutput
|
10
|
+
.expects(:get)
|
11
|
+
.with(ForemanInventoryUpload::Async::GenerateReportJob.output_label(test_portal_user))
|
12
|
+
.returns(progress_output)
|
13
|
+
progress_output.expects(:full_output).returns('test output')
|
14
|
+
|
15
|
+
get :last, params: { portal_user: test_portal_user }, session: set_session_user
|
16
|
+
|
17
|
+
assert_response :success
|
18
|
+
actual = JSON.parse(response.body)
|
19
|
+
assert_equal 'test output', actual['output']
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class StatusesControllerTest < ActionController::TestCase
|
4
|
+
tests ForemanInventoryUpload::StatusesController
|
5
|
+
|
6
|
+
include FolderIsolation
|
7
|
+
|
8
|
+
test 'Returns statuses for each process type' do
|
9
|
+
configuration = RedhatAccess::TelemetryConfiguration.new(enable_telemetry: true, portal_user: 'test')
|
10
|
+
configuration.save!
|
11
|
+
|
12
|
+
generate_label = ForemanInventoryUpload::Async::GenerateReportJob.output_label('test')
|
13
|
+
generate_output = ForemanInventoryUpload::Async::ProgressOutput.register(generate_label)
|
14
|
+
generate_output.status = 'generate_status_test'
|
15
|
+
upload_label = ForemanInventoryUpload::Async::UploadReportJob.output_label('test')
|
16
|
+
upload_output = ForemanInventoryUpload::Async::ProgressOutput.register(upload_label)
|
17
|
+
upload_output.status = 'upload_status_test'
|
18
|
+
|
19
|
+
get :index, session: set_session_user
|
20
|
+
|
21
|
+
assert_response :success
|
22
|
+
actual = JSON.parse(response.body)['statuses']['test']
|
23
|
+
assert_equal 'generate_status_test', actual['generate_report_status']
|
24
|
+
assert_equal 'upload_status_test', actual['upload_report_status']
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class UploadsControllerTest < ActionController::TestCase
|
4
|
+
tests ForemanInventoryUpload::UploadsController
|
5
|
+
|
6
|
+
test 'Returns latest upload status' do
|
7
|
+
progress_output = mock('progress_output')
|
8
|
+
test_portal_user = 'test_portal_user'
|
9
|
+
ForemanInventoryUpload::Async::ProgressOutput
|
10
|
+
.expects(:get)
|
11
|
+
.with(ForemanInventoryUpload::Async::UploadReportJob.output_label(test_portal_user))
|
12
|
+
.returns(progress_output)
|
13
|
+
progress_output.expects(:full_output).returns('test output')
|
14
|
+
|
15
|
+
get :last, params: { portal_user: test_portal_user }, session: set_session_user
|
16
|
+
|
17
|
+
assert_response :success
|
18
|
+
actual = JSON.parse(response.body)
|
19
|
+
assert_equal 'test output', actual['output']
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# redefine katello factories, as long as katello is not compatible with dynamic properties
|
2
|
+
FactoryBot.define do
|
3
|
+
factory :katello_organization, :class => "Organization" do
|
4
|
+
type {"Organization"}
|
5
|
+
sequence(:name) { |n| "Organization#{n}" }
|
6
|
+
sequence(:label) { |n| "org#{n}" }
|
7
|
+
sequence(:id) { |n| n }
|
8
|
+
|
9
|
+
trait :acme_corporation do
|
10
|
+
name {"ACME_Corporation"}
|
11
|
+
type {"Organization"}
|
12
|
+
description {"This is the first Organization."}
|
13
|
+
label {"acme_corporation_label"}
|
14
|
+
end
|
15
|
+
|
16
|
+
trait :with_library do
|
17
|
+
association :library, :factory => :katello_library
|
18
|
+
end
|
19
|
+
|
20
|
+
factory :acme_corporation, :traits => [:acme_corporation]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
FactoryBot.define do
|
25
|
+
factory :katello_content_view, :class => Katello::ContentView do
|
26
|
+
sequence(:name) { |n| "Database#{n}" }
|
27
|
+
description {"This content view is for database content"}
|
28
|
+
association :organization, :factory => :katello_organization
|
29
|
+
|
30
|
+
trait :composite do
|
31
|
+
composite {true}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
FactoryBot.define do
|
37
|
+
factory :katello_k_t_environment, :aliases => [:katello_environment], :class => Katello::KTEnvironment do
|
38
|
+
sequence(:name) { |n| "Environment#{n}" }
|
39
|
+
sequence(:label) { |n| "environment#{n}" }
|
40
|
+
association :organization, :factory => :katello_organization
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
FactoryBot.define do
|
45
|
+
factory :katello_content_facets, :aliases => [:content_facet], :class => ::Katello::Host::ContentFacet do
|
46
|
+
sequence(:uuid) { |n| "uuid-#{n}" }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
FactoryBot.define do
|
51
|
+
factory :katello_subscription_facets, :aliases => [:subscription_facet], :class => ::Katello::Host::SubscriptionFacet do
|
52
|
+
sequence(:uuid) { |n| "uuid-#{n}-#{rand(500)}" }
|
53
|
+
facts { {'memory.memtotal' => "12 GB"} }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
FactoryBot.define do
|
58
|
+
factory :katello_pool, :class => Katello::Pool do
|
59
|
+
active {true}
|
60
|
+
end_date {Date.today + 1.year}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
FactoryBot.modify do
|
65
|
+
factory :host do
|
66
|
+
transient do
|
67
|
+
content_view {nil}
|
68
|
+
lifecycle_environment {nil}
|
69
|
+
content_source {nil}
|
70
|
+
end
|
71
|
+
|
72
|
+
trait :with_content do
|
73
|
+
association :content_facet, :factory => :content_facet, :strategy => :build
|
74
|
+
|
75
|
+
after(:build) do |host, evaluator|
|
76
|
+
if host.content_facet
|
77
|
+
host.content_facet.content_view = evaluator.content_view if evaluator.content_view
|
78
|
+
host.content_facet.lifecycle_environment = evaluator.lifecycle_environment if evaluator.lifecycle_environment
|
79
|
+
host.content_facet.content_source = evaluator.content_source if evaluator.content_source
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
trait :with_subscription do
|
85
|
+
association :subscription_facet, :factory => :subscription_facet, :strategy => :build
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This calls the main test_helper in Foreman-core
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
# Add plugin to FactoryBot's paths
|
5
|
+
FactoryBot.definition_file_paths << File.join(File.dirname(__FILE__), 'factories')
|
6
|
+
# FactoryBot.definition_file_paths << "#{Katello::Engine.root}/test/factories"
|
7
|
+
FactoryBot.reload
|
8
|
+
|
9
|
+
module FolderIsolation
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
setup do
|
14
|
+
@tmpdir = Dir.mktmpdir(self.class.name.underscore)
|
15
|
+
|
16
|
+
ForemanInventoryUpload.stubs(:base_folder).returns(@tmpdir)
|
17
|
+
ForemanInventoryUpload.instance_variable_set(:@outputs_folder, nil)
|
18
|
+
ForemanInventoryUpload.instance_variable_set(:@uploads_folders, nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
teardown do
|
22
|
+
FileUtils.remove_entry @tmpdir
|
23
|
+
ForemanInventoryUpload.unstub(:base_folder)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class ArchivedReportGeneratorTest < ActiveSupport::TestCase
|
4
|
+
setup do
|
5
|
+
User.current = User.find_by(login: 'secret_admin')
|
6
|
+
|
7
|
+
env = FactoryBot.create(:katello_k_t_environment)
|
8
|
+
cv = env.content_views << FactoryBot.create(:katello_content_view, organization: env.organization)
|
9
|
+
|
10
|
+
@host = FactoryBot.create(
|
11
|
+
:host,
|
12
|
+
:with_subscription,
|
13
|
+
:with_content,
|
14
|
+
content_view: cv.first,
|
15
|
+
lifecycle_environment: env,
|
16
|
+
organization: env.organization
|
17
|
+
)
|
18
|
+
|
19
|
+
@host.subscription_facet.pools << FactoryBot.create(:katello_pool, account_number: '1234', cp_id: 1)
|
20
|
+
end
|
21
|
+
|
22
|
+
def interesting_facts
|
23
|
+
[
|
24
|
+
'dmi::system::uuid',
|
25
|
+
'virt::uuid',
|
26
|
+
'cpu::cpu(s)',
|
27
|
+
'cpu::cpu_socket(s)',
|
28
|
+
'cpu::core(s)_per_socket',
|
29
|
+
'memory::memtotal',
|
30
|
+
'dmi::bios::vendor',
|
31
|
+
'dmi::bios::version',
|
32
|
+
'dmi::bios::relase_date',
|
33
|
+
'distribution::name',
|
34
|
+
'uname::release',
|
35
|
+
'lscpu::flags'
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
def fact_names
|
40
|
+
@fact_names ||= Hash[
|
41
|
+
interesting_facts.map do |fact|
|
42
|
+
[fact, FactoryBot.create(:fact_name, name: fact, type: 'Katello::RhsmFactName')]
|
43
|
+
end
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
test 'generates a report for a single host' do
|
48
|
+
batches = Host.where(id: @host.id).in_batches
|
49
|
+
portal_user = 'test_portal_user'
|
50
|
+
|
51
|
+
ForemanInventoryUpload::Generators::Queries.expects(:for_report).with(portal_user).returns(batches)
|
52
|
+
Dir.mktmpdir do |tmpdir|
|
53
|
+
target = File.join(tmpdir, 'test.tar.gz')
|
54
|
+
generator = ForemanInventoryUpload::Generators::ArchivedReport.new(target, Logger.new(STDOUT))
|
55
|
+
generator.render(portal_user)
|
56
|
+
|
57
|
+
files = Dir["#{tmpdir}/*"]
|
58
|
+
assert_equal "#{tmpdir}/test.tar.gz", files.first
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
class MetadataGeneratorTest < ActiveSupport::TestCase
|
4
|
+
setup do
|
5
|
+
end
|
6
|
+
|
7
|
+
test 'generates an empty report' do
|
8
|
+
generator = ForemanInventoryUpload::Generators::Metadata.new
|
9
|
+
|
10
|
+
json_str = generator.render do
|
11
|
+
end
|
12
|
+
actual = JSON.parse(json_str.join("\n"))
|
13
|
+
|
14
|
+
assert_not_nil actual['report_id']
|
15
|
+
assert_equal 'Satellite', actual['source']
|
16
|
+
assert_equal({}, actual['report_slices'])
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'generates a report for a single slice' do
|
20
|
+
generator = ForemanInventoryUpload::Generators::Metadata.new
|
21
|
+
|
22
|
+
json_str = generator.render do |gen|
|
23
|
+
gen.add_slice('test_123', 1, true)
|
24
|
+
gen.add_slice('test_1234', 2, false)
|
25
|
+
gen.add_slice('test_12345', 3, false)
|
26
|
+
end
|
27
|
+
|
28
|
+
actual = JSON.parse(json_str.join("\n"))
|
29
|
+
|
30
|
+
assert_not_nil actual['report_id']
|
31
|
+
assert_equal 'Satellite', actual['source']
|
32
|
+
assert_not_nil(slices = actual['report_slices'])
|
33
|
+
assert_not_nil(slice = slices['test_123'])
|
34
|
+
assert_equal 1, slice['number_hosts']
|
35
|
+
assert_not_nil(slice = slices['test_1234'])
|
36
|
+
assert_equal 2, slice['number_hosts']
|
37
|
+
assert_not_nil(slice = slices['test_12345'])
|
38
|
+
assert_equal 3, slice['number_hosts']
|
39
|
+
end
|
40
|
+
end
|