foreman_inventory_upload 0.0.1.dev1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +38 -0
  4. data/Rakefile +47 -0
  5. data/app/controllers/foreman_inventory_upload/react_controller.rb +7 -0
  6. data/app/controllers/foreman_inventory_upload/reports_controller.rb +23 -0
  7. data/app/controllers/foreman_inventory_upload/statuses_controller.rb +41 -0
  8. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +31 -0
  9. data/app/helpers/foreman_inventory_upload_helper.rb +13 -0
  10. data/app/views/dashboard/_inventory_upload_widget.html.erb +2 -0
  11. data/app/views/foreman_inventory_upload/layouts/react.html.erb +16 -0
  12. data/app/views/scripts/uploader.sh.erb +31 -0
  13. data/config/routes.rb +10 -0
  14. data/lib/foreman_inventory_upload/async/generate_report_job.rb +29 -0
  15. data/lib/foreman_inventory_upload/async/progress_output.rb +61 -0
  16. data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +52 -0
  17. data/lib/foreman_inventory_upload/async/shell_process.rb +35 -0
  18. data/lib/foreman_inventory_upload/async/upload_report_job.rb +40 -0
  19. data/lib/foreman_inventory_upload/engine.rb +52 -0
  20. data/lib/foreman_inventory_upload/generators/archived_report.rb +53 -0
  21. data/lib/foreman_inventory_upload/generators/json_stream.rb +55 -0
  22. data/lib/foreman_inventory_upload/generators/metadata.rb +36 -0
  23. data/lib/foreman_inventory_upload/generators/queries.rb +52 -0
  24. data/lib/foreman_inventory_upload/generators/slice.rb +117 -0
  25. data/lib/foreman_inventory_upload/version.rb +3 -0
  26. data/lib/foreman_inventory_upload.rb +48 -0
  27. data/lib/tasks/foreman_inventory_upload_tasks.rake +37 -0
  28. data/lib/tasks/generator.rake +15 -0
  29. data/locale/Makefile +60 -0
  30. data/locale/en/foreman_yupana.po +19 -0
  31. data/locale/foreman_yupana.pot +19 -0
  32. data/locale/gemspec.rb +2 -0
  33. data/test/controllers/reports_controller_test.rb +21 -0
  34. data/test/controllers/statuses_controller_test.rb +26 -0
  35. data/test/controllers/uploads_controller_test.rb +21 -0
  36. data/test/factories/inventory_upload_factories.rb +88 -0
  37. data/test/test_plugin_helper.rb +26 -0
  38. data/test/unit/archived_report_generator_test.rb +61 -0
  39. data/test/unit/metadata_generator_test.rb +40 -0
  40. data/test/unit/shell_process_job_test.rb +27 -0
  41. data/test/unit/slice_generator_test.rb +60 -0
  42. 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,3 @@
1
+ module ForemanInventoryUpload
2
+ VERSION = '0.0.1.dev1'.freeze
3
+ 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,2 @@
1
+ # Matches foreman_yupana.gemspec
2
+ _('TODO: Description of ForemanYupana.')
@@ -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