foreman_maintain 1.10.3 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd92aa45510fd828c1ff73193cffba5fba7f161842992465023d0028c0a2e80b
4
- data.tar.gz: '011833c73f3200e6858dd572fbc1b2eaebaea64c803ebf60720dd516770cdae8'
3
+ metadata.gz: 0573bbda58a16e7632d6c074d5d99d4ddbace818cede03002efbc47ca9896f33
4
+ data.tar.gz: '009f7cf5f9fc5d2a7916041266c97dc76fbf44e1c6d670b368edcc0a4bf2c15c'
5
5
  SHA512:
6
- metadata.gz: 011a42195a870265ce392f72c05f6e65a085491879850f59ccf137acdbb39c9963b0929d842b3e8fcb116ea8dd03c70cc296bdc252f7da2101281235923d99ca
7
- data.tar.gz: 62f0782ce86392e56f9a49eb7ba6b076d817b812c0b19d1587e3a14cd359dd871367e486d68145771dcc9aec38fc7d6c38cc8c504700fb7ab6101b406e514112
6
+ metadata.gz: 94f026030c038110b5d7fae4985313b3c00fb7e21e51bdd0026915ae017fb4bad826c72e8fa1797cfe78dc5dd89bcfe8d92d17ae25ffe288433e9a4cf278f79d
7
+ data.tar.gz: e7cc1350ad46e6d71a7651e83f9bbb4cdfb3db1eabe39691f84d102bb3ef12491db6920c682e364e8ed1e1db4e762fff2c6d4e11cb370a5b135ff820bc079c37
@@ -0,0 +1,33 @@
1
+ module Reports
2
+ class AdvisorOnPremRemediations < ForemanMaintain::Report
3
+ metadata do
4
+ description 'Report number of remediations based on advisor rules from advisor on premise'
5
+ end
6
+
7
+ def run
8
+ data_field('advisor_on_prem_remediations_enabled') { advisor_on_prem_remediations_enabled }
9
+ data_field('advisor_on_prem_remediations_count') { advisor_on_prem_remediations_count }
10
+ end
11
+
12
+ def advisor_on_prem_remediations_enabled
13
+ if @iop_enabled.nil?
14
+ @iop_enabled = feature(:installer)&.answers&.dig(
15
+ 'foreman::plugin::rh_cloud', 'enable_iop_advisor_engine'
16
+ ) || false
17
+ end
18
+ @iop_enabled
19
+ end
20
+
21
+ def advisor_on_prem_remediations_count
22
+ if advisor_on_prem_remediations_enabled
23
+ return sql_count('
24
+ job_invocations AS jobs
25
+ INNER JOIN remote_execution_features AS rexf ON jobs.remote_execution_feature_id = rexf.id
26
+ INNER JOIN template_invocations AS tinv ON jobs.id = tinv.job_invocation_id
27
+ WHERE rexf.label = \'rh_cloud_remediate_hosts\'
28
+ AND tinv.host_id IS NOT NULL
29
+ ')
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,46 @@
1
+ module Checks
2
+ module Report
3
+ class AlternateContentSources < ForemanMaintain::Report
4
+ metadata do
5
+ description 'Facts about ACSs'
6
+ confine do
7
+ feature(:katello)
8
+ end
9
+ end
10
+
11
+ def run
12
+ data_field('custom_alternate_content_sources_count') { custom_alternate_content_sources }
13
+ data_field('simplified_alternate_content_sources_count') do
14
+ simplified_alternate_content_sources
15
+ end
16
+ data_field('rhui_alternate_content_sources_count') { rhui_alternate_content_sources }
17
+ data_field('yum_alternate_content_sources_count') { yum_alternate_content_sources }
18
+ data_field('file_alternate_content_sources_count') { file_alternate_content_sources }
19
+ end
20
+
21
+ def custom_alternate_content_sources
22
+ sql_count(
23
+ "katello_alternate_content_sources WHERE alternate_content_source_type = 'custom'"
24
+ )
25
+ end
26
+
27
+ def simplified_alternate_content_sources
28
+ sql_count(
29
+ "katello_alternate_content_sources WHERE alternate_content_source_type = 'simplified'"
30
+ )
31
+ end
32
+
33
+ def rhui_alternate_content_sources
34
+ sql_count("katello_alternate_content_sources WHERE alternate_content_source_type = 'rhui'")
35
+ end
36
+
37
+ def yum_alternate_content_sources
38
+ sql_count("katello_alternate_content_sources WHERE content_type = 'yum'")
39
+ end
40
+
41
+ def file_alternate_content_sources
42
+ sql_count("katello_alternate_content_sources WHERE content_type = 'file'")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ module Checks
2
+ module Report
3
+ class Content < ForemanMaintain::Report
4
+ metadata do
5
+ description 'Facts about Katello content'
6
+ confine do
7
+ feature(:katello)
8
+ end
9
+ end
10
+
11
+ def run
12
+ data_field('custom_library_yum_repositories_count') { custom_library_yum_repositories }
13
+ data_field('redhat_library_yum_repositories_count') { redhat_library_yum_repositories }
14
+ data_field('library_debian_repositories_count') { library_repositories('deb') }
15
+ data_field('library_container_repositories_count') { library_repositories('docker') }
16
+ data_field('library_file_repositories_count') { library_repositories('file') }
17
+ data_field('library_python_repositories_count') { library_repositories('python') }
18
+ data_field('library_ansible_collection_repositories_count') do
19
+ library_repositories('ansible_collection')
20
+ end
21
+ data_field('library_ostree_repositories_count') { library_repositories('ostree') }
22
+ end
23
+
24
+ def custom_library_yum_repositories
25
+ query_snippet =
26
+ <<-SQL
27
+ "katello_root_repositories"
28
+ WHERE "katello_root_repositories"."id" NOT IN
29
+ (SELECT "katello_root_repositories"."id" FROM "katello_root_repositories" INNER JOIN "katello_products"
30
+ ON "katello_products"."id" = "katello_root_repositories"."product_id" INNER JOIN "katello_providers"
31
+ ON "katello_providers"."id" = "katello_products"."provider_id" WHERE "katello_providers"."provider_type" = 'Red Hat')
32
+ AND "katello_root_repositories"."content_type" = 'yum'
33
+ SQL
34
+ sql_count(query_snippet)
35
+ end
36
+
37
+ def redhat_library_yum_repositories
38
+ query_snippet =
39
+ <<-SQL
40
+ "katello_root_repositories"
41
+ INNER JOIN "katello_products" ON "katello_products"."id" = "katello_root_repositories"."product_id"
42
+ INNER JOIN "katello_providers" ON "katello_providers"."id" = "katello_products"."provider_id"
43
+ WHERE "katello_providers"."provider_type" = 'Red Hat'
44
+ AND "katello_root_repositories"."content_type" = 'yum'
45
+ SQL
46
+ sql_count(query_snippet)
47
+ end
48
+
49
+ def library_repositories(content_type)
50
+ sql_count("katello_root_repositories WHERE content_type = '#{content_type}'")
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,27 @@
1
+ module Reports
2
+ class ImageModeHosts < ForemanMaintain::Report
3
+ metadata do
4
+ description 'Report number of image mode hosts registered by operating system'
5
+ confine do
6
+ feature(:katello)
7
+ end
8
+ end
9
+
10
+ def run
11
+ merge_data('image_mode_hosts_by_os_count') { image_mode_hosts_by_os_count }
12
+ end
13
+
14
+ # OS usage on image mode hosts
15
+ def image_mode_hosts_by_os_count
16
+ query(
17
+ <<-SQL
18
+ select max(operatingsystems.name) as os_name, count(*) as hosts_count
19
+ from hosts inner join operatingsystems on operatingsystem_id = operatingsystems.id inner join katello_content_facets on hosts.id = katello_content_facets.host_id
20
+ where bootc_booted_digest is not null
21
+ group by operatingsystems.name
22
+ SQL
23
+ ).
24
+ to_h { |row| [row['os_name'], row['hosts_count'].to_i] }
25
+ end
26
+ end
27
+ end
@@ -10,6 +10,7 @@ module Reports
10
10
  merge_data('facts_by_type') { facts_by_type }
11
11
  merge_data('audits') { audits }
12
12
  merge_data('parameters_count') { parameters }
13
+ hosts_running_rhel_ai
13
14
  end
14
15
 
15
16
  # Hosts
@@ -24,7 +25,7 @@ module Reports
24
25
  <<-SQL
25
26
  select max(operatingsystems.name) as os_name, count(*) as hosts_count
26
27
  from hosts inner join operatingsystems on operatingsystem_id = operatingsystems.id
27
- group by operatingsystem_id
28
+ group by operatingsystems.name
28
29
  SQL
29
30
  ).
30
31
  to_h { |row| [row['os_name'], row['hosts_count'].to_i] }
@@ -80,5 +81,16 @@ module Reports
80
81
  max_created_at: row['max_created_at'],
81
82
  }
82
83
  end
84
+
85
+ def hosts_running_rhel_ai
86
+ query = <<~SQL
87
+ hosts
88
+ INNER JOIN katello_subscription_facets AS ksf ON hosts.id = ksf.host_id
89
+ INNER JOIN katello_subscription_facet_installed_products AS ksfip ON ksfip.subscription_facet_id = ksf.id
90
+ INNER JOIN katello_installed_products AS kip ON ksfip.installed_product_id = kip.id
91
+ WHERE kip.name = 'Red Hat Enterprise Linux AI'
92
+ SQL
93
+ data_field('rhel_ai_workload_host_count') { sql_count(query) }
94
+ end
83
95
  end
84
96
  end
@@ -0,0 +1,78 @@
1
+ require 'socket'
2
+
3
+ module Reports
4
+ class Networking < ForemanMaintain::Report
5
+ metadata do
6
+ description 'Report information about networking'
7
+ end
8
+
9
+ def run
10
+ subnet_counts_by_type
11
+ hosts_by_address_family
12
+ interfaces_by_address_family
13
+ preference_settings
14
+ end
15
+
16
+ private
17
+
18
+ # How many ipv4 subnets are defined in Foreman?
19
+ # How many ipv6 subnets are defined in Foreman?
20
+ def subnet_counts_by_type
21
+ %w[Ipv4 Ipv6].each do |type|
22
+ data_field("subnet_#{type.downcase}_count") do
23
+ sql_count("subnets where type = 'Subnet::#{type}'")
24
+ end
25
+ end
26
+ end
27
+
28
+ # How many hosts in Foreman have an interface with an ipv4 address but no ipv6 address?
29
+ # How many hosts in Foreman have an interface with no ipv4 address but an ipv6 address?
30
+ # How many hosts in Foreman have an interface with both ipv4 and ipv6 addresses?
31
+ def hosts_by_address_family
32
+ { 'ipv4only': 'nics.ip IS NOT NULL AND nics.ip6 IS NULL',
33
+ 'ipv6only': 'nics.ip IS NULL AND nics.ip6 IS NOT NULL',
34
+ 'dualstack': 'nics.ip IS NOT NULL AND nics.ip6 IS NOT NULL' }.each do |kind, condition|
35
+ query = <<~SQL
36
+ hosts
37
+ WHERE id IN (SELECT host_id FROM nics WHERE #{condition})
38
+ SQL
39
+ data_field("hosts_with_#{kind}_interface_count") { sql_count(query) }
40
+ end
41
+ end
42
+
43
+ # How many of Foreman's interfaces:
44
+ # - only have a non-loopback, non-multicast ipv4 address?
45
+ # - only have a non-loopback, non-multicast, non-link-local ipv6 address?
46
+ # - have a non-loopback, non-multicast ipv4 address
47
+ # as well as a non-loopback, non-multicast, non-link-local ipv6 address?
48
+ def interfaces_by_address_family
49
+ by_name = Socket.getifaddrs.group_by(&:name).transform_values { |addrs| addrs.map(&:addr) }
50
+ with_ipv4, without_ipv4 = by_name.partition { |_name, addrs| relevant_ipv4?(addrs) }
51
+ dualstack, ipv4_only = with_ipv4.partition { |_name, addrs| relevant_ipv6?(addrs) }
52
+ ipv6_only = without_ipv4.select { |_name, addrs| relevant_ipv6?(addrs) }
53
+
54
+ data_field("foreman_interfaces_ipv4only_count") { ipv4_only.count }
55
+ data_field("foreman_interfaces_ipv6only_count") { ipv6_only.count }
56
+ data_field("foreman_interfaces_dualstack_count") { dualstack.count }
57
+ end
58
+
59
+ def relevant_ipv4?(addrs)
60
+ addrs.any? { |addr| addr.ipv4? && !(addr.ipv4_loopback? || addr.ipv4_multicast?) }
61
+ end
62
+
63
+ def relevant_ipv6?(addrs)
64
+ addrs.any? do |addr|
65
+ addr.ipv6? && !(addr.ipv6_loopback? || addr.ipv6_multicast? || addr.ipv6_linklocal?)
66
+ end
67
+ end
68
+
69
+ def preference_settings
70
+ %w[remote_execution_connect_by_ip_prefer_ipv6 discovery_prefer_ipv6].each do |setting|
71
+ data_field("setting_#{setting}") do
72
+ value = sql_setting(setting)
73
+ value.nil? ? false : YAML.safe_load(value)
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -57,7 +57,7 @@ module Reports
57
57
 
58
58
  def settings_fields
59
59
  data_field('modified_settings') do
60
- query("select name from settings").
60
+ query("select name from settings WHERE value IS NOT NULL").
61
61
  map { |setting_line| setting_line['name'] }.
62
62
  join(',')
63
63
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanMaintain
2
- VERSION = '1.10.3'.freeze
2
+ VERSION = '1.11.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_maintain
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.3
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-02 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: clamp
@@ -306,13 +306,18 @@ files:
306
306
  - definitions/procedures/service/stop.rb
307
307
  - definitions/procedures/sync_plans/disable.rb
308
308
  - definitions/procedures/sync_plans/enable.rb
309
+ - definitions/reports/advisor_on_prem_remediations.rb
310
+ - definitions/reports/alternate_content_sources.rb
309
311
  - definitions/reports/compliance.rb
312
+ - definitions/reports/content.rb
310
313
  - definitions/reports/external_auth_source.rb
311
314
  - definitions/reports/grouping.rb
315
+ - definitions/reports/image_mode_hosts.rb
312
316
  - definitions/reports/instance.rb
313
317
  - definitions/reports/inventory.rb
314
318
  - definitions/reports/kerberos.rb
315
319
  - definitions/reports/ldap_auth_source.rb
320
+ - definitions/reports/networking.rb
316
321
  - definitions/reports/oidc_usage.rb
317
322
  - definitions/reports/platform.rb
318
323
  - definitions/reports/provisioning.rb
@@ -446,7 +451,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
446
451
  - !ruby/object:Gem::Version
447
452
  version: '0'
448
453
  requirements: []
449
- rubygems_version: 3.6.2
454
+ rubygems_version: 3.6.7
450
455
  specification_version: 4
451
456
  summary: Foreman maintenance tool belt
452
457
  test_files: []