foreman_rh_cloud 2.0.8 → 2.0.9

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: 4b4d5750b4b0ff6361c7694fb3808a4c33d5ff12e37bd5d946c1baa454b805a1
4
- data.tar.gz: 5e18ea289049d0525a82adb8f7cbeec66d5ac4abf2cae5867aa18c3aab753640
3
+ metadata.gz: c164b990c325cd1f5e90004585c0074c558ee29ece8b687d37115d88f278274d
4
+ data.tar.gz: 01f04d99170a49224c7687949acff8d7171ce73d0d620343ce348c324b2b6040
5
5
  SHA512:
6
- metadata.gz: 7e9b9c292ed88641c954bc79d665c7f3e77a0c04e426bde5e12d92e25d53b72ef7ade25a69b08da5f20442c3a4a41a7d8854dac529108376eae49b188c1eb839
7
- data.tar.gz: 94998762071b568f438dd03c37f22c969a55cc2c71410bf60c2b4e21ebda259e1e20a85d6a821324014d98683f1b928cce4fe94e39a0a4f8f34dd338237252ed
6
+ metadata.gz: dc211d399ff2f518b47ccfe76e8a569cac8b3356bab5dc6f2dabfc8c0a3de2926dd8fe99f2a84ea8dba9e4dea3b871cdd3380dfebb48e51cdcb1198dbac16bc8
7
+ data.tar.gz: 622e9894c0bef62e38f25b687d2acb0c5db74cf8e299e5a327f102052704324e2aafaee71fa30b595de66a29124789a815899e3f324000c559e3c75ce2ce401c
@@ -3,7 +3,7 @@ class Setting::RhCloud < Setting
3
3
  return unless ActiveRecord::Base.connection.table_exists?('settings')
4
4
  return unless super
5
5
  [
6
- set('allow_auto_inventory_upload', N_('Allow automatic upload of the host inventory to the Red Hat cloud'), true),
6
+ set('allow_auto_inventory_upload', N_('Allow automatic upload of the host inventory to the Red Hat cloud'), false),
7
7
  set('obfuscate_inventory_hostnames', N_('Obfuscate host names sent to Red Hat cloud'), false),
8
8
  set('rh_cloud_token', N_('Authentication token to Red Hat cloud services. Used to authenticate requests to cloud APIs'), 'DEFAULT', N_('Red Hat Cloud token'), nil, encrypted: true),
9
9
  ]
@@ -1 +1,6 @@
1
- <%= mount_react_component('InsightsCloudSync', '#ForemanRhCloudReactRoot') %>
1
+ <%= mount_react_component(
2
+ 'InsightsCloudSync',
3
+ '#ForemanRhCloudReactRoot',
4
+ {
5
+ settingsUrl: settings_url(search: 'name = rh_cloud_token')
6
+ }.to_json) %>
@@ -9,7 +9,7 @@ module ForemanInventoryUpload
9
9
  klass_name = self.class.name
10
10
  logger.debug("Starting #{klass_name} with label #{instance_label}")
11
11
  progress_output = ProgressOutput.register(instance_label)
12
- Open3.popen2e(hash_to_s(env), command) do |_stdin, stdout_stderr, wait_thread|
12
+ Open3.popen2e(hash_to_s(env), *preprocess_command(command)) do |_stdin, stdout_stderr, wait_thread|
13
13
  progress_output.status = "Running in pid #{wait_thread.pid}"
14
14
 
15
15
  stdout_stderr.each do |out_line|
@@ -33,6 +33,12 @@ module ForemanInventoryUpload
33
33
  def logger
34
34
  Foreman::Logging.logger('background')
35
35
  end
36
+
37
+ private
38
+
39
+ def preprocess_command(command)
40
+ command.kind_of?(Array) ? command : [command]
41
+ end
36
42
  end
37
43
  end
38
44
  end
@@ -21,7 +21,7 @@ module ForemanInventoryUpload
21
21
  end
22
22
 
23
23
  def command
24
- File.join(File.dirname(@filename), ForemanInventoryUpload.upload_script_file)
24
+ ['/bin/bash', File.join(File.dirname(@filename), ForemanInventoryUpload.upload_script_file)]
25
25
  end
26
26
 
27
27
  def env
@@ -36,6 +36,16 @@ module ForemanInventoryUpload
36
36
  @out << ',' unless last
37
37
  end
38
38
 
39
+ def string_array_value(name, value, last = false)
40
+ return if value.empty?
41
+
42
+ string_value = value.map { |v| stringify_value(v) }
43
+
44
+ array_field(name, last) do
45
+ raw(string_value.join(', '))
46
+ end
47
+ end
48
+
39
49
  def object_field(name, last = false, &block)
40
50
  @out << "\"#{name}\": "
41
51
  object(&block)
@@ -45,16 +45,8 @@ module ForemanInventoryUpload
45
45
  @stream.simple_field('satellite_id', host.subscription_facet&.uuid)
46
46
  @stream.simple_field('bios_uuid', fact_value(host, 'dmi::system::uuid'))
47
47
  @stream.simple_field('vm_uuid', fact_value(host, 'virt::uuid'))
48
- @stream.array_field('ip_addresses') do
49
- @stream.raw(host.interfaces.map do |nic|
50
- @stream.stringify_value(nic.ip) if nic.ip
51
- end.compact.join(', '))
52
- end
53
- @stream.array_field('mac_addresses') do
54
- @stream.raw(host.interfaces.map do |nic|
55
- @stream.stringify_value(nic.mac) if nic.mac
56
- end.compact.join(', '))
57
- end
48
+ report_ip_addresses(host)
49
+ report_mac_addresses(host)
58
50
  @stream.object_field('system_profile') do
59
51
  report_system_profile(host)
60
52
  end
@@ -161,6 +153,18 @@ module ForemanInventoryUpload
161
153
  @stream.simple_field('organization_id', host.organization_id, :last)
162
154
  end
163
155
 
156
+ def report_ip_addresses(host)
157
+ ip_addresses = host.interfaces.map { |nic| nic.ip }.compact
158
+
159
+ @stream.string_array_value('ip_addresses', ip_addresses)
160
+ end
161
+
162
+ def report_mac_addresses(host)
163
+ macs = host.interfaces.map { |nic| nic.mac }.compact
164
+
165
+ @stream.string_array_value('mac_addresses', macs)
166
+ end
167
+
164
168
  def os_release_value(name:, version:, codename:)
165
169
  "#{name} #{version} (#{codename})"
166
170
  end
@@ -1,4 +1,4 @@
1
- #! /bin/sh
1
+ #! /bin/bash
2
2
 
3
3
  DEST=<%= @upload_url %>
4
4
  RH_USERNAME=<%= @rh_username %>
@@ -1,3 +1,3 @@
1
1
  module ForemanRhCloud
2
- VERSION = '2.0.8'.freeze
2
+ VERSION = '2.0.9'.freeze
3
3
  end
@@ -68,7 +68,7 @@ module InsightsCloud
68
68
  def replace_hits_data(hits)
69
69
  InsightsHit.transaction do
70
70
  InsightsHit.delete_all
71
- InsightsHit.create(hits.map { |hits_hash| to_model_hash(hits_hash) })
71
+ InsightsHit.create(hits.map { |hits_hash| to_model_hash(hits_hash) }.compact)
72
72
  # create new facets for hosts that are missing one
73
73
  hosts_with_existing_facets = InsightsFacet.where(host_id: @host_ids.values).pluck(:host_id)
74
74
  InsightsFacet.create((@host_ids.values - hosts_with_existing_facets).map { |id| {host_id: id} })
@@ -76,8 +76,12 @@ module InsightsCloud
76
76
  end
77
77
 
78
78
  def to_model_hash(hit_hash)
79
+ hit_host_id = host_id(hit_hash['hostname'])
80
+
81
+ return unless hit_host_id
82
+
79
83
  {
80
- host_id: host_id(hit_hash['hostname']),
84
+ host_id: hit_host_id,
81
85
  last_seen: DateTime.parse(hit_hash['last_seen']),
82
86
  publish_date: DateTime.parse(hit_hash['publish_date']),
83
87
  title: hit_hash['title'],
@@ -59,4 +59,34 @@ class InsightsFullSyncTest < ActiveJob::TestCase
59
59
  assert_equal 2, @host1.insights.hits.count
60
60
  assert_equal 1, @host2.insights.hits.count
61
61
  end
62
+
63
+ test 'Hits ignoring non-existent hosts' do
64
+ hits_json = <<-HITS_JSON
65
+ [
66
+ {
67
+ "hostname": "#{@host1.name}_non_existent",
68
+ "rhel_version": "7.5",
69
+ "uuid": "accdf444-5628-451d-bf3e-cf909ad72756",
70
+ "last_seen": "2019-11-22T08:41:42.447244Z",
71
+ "title": "New Ansible Engine packages are inaccessible when dedicated Ansible repo is not enabled",
72
+ "solution_url": "",
73
+ "total_risk": 2,
74
+ "likelihood": 2,
75
+ "publish_date": "2018-04-16T10:03:16Z",
76
+ "results_url": "https://cloud.redhat.com/insights/overview/stability/ansible_deprecated_repo%7CANSIBLE_DEPRECATED_REPO/accdf444-5628-451d-bf3e-cf909ad72756/"
77
+ }
78
+ ]
79
+ HITS_JSON
80
+ hits = JSON.parse(hits_json)
81
+
82
+ InsightsCloud::Async::InsightsFullSync.any_instance.expects(:query_insights_hits).returns(hits)
83
+
84
+ InsightsCloud::Async::InsightsFullSync.perform_now(@host1.organization)
85
+
86
+ @host1.reload
87
+ @host2.reload
88
+
89
+ assert_nil @host1.insights
90
+ assert_nil @host2.insights
91
+ end
62
92
  end
@@ -63,6 +63,25 @@ class ReportGeneratorTest < ActiveSupport::TestCase
63
63
 
64
64
  assert_equal 'slice_123', actual['report_slice_id']
65
65
  assert_not_nil(actual_host = actual['hosts'].first)
66
+ assert_nil actual_host['ip_addresses']
67
+ assert_nil actual_host['mac_addresses']
68
+ assert_equal @host.fqdn, actual_host['fqdn']
69
+ assert_equal '1234', actual_host['account']
70
+ assert_equal 1, generator.hosts_count
71
+ end
72
+
73
+ test 'generates ip_address and mac_address fields' do
74
+ @host.interfaces << FactoryBot.build(:nic_managed)
75
+ batch = Host.where(id: @host.id).in_batches.first
76
+ generator = create_generator(batch)
77
+
78
+ json_str = generator.render
79
+ actual = JSON.parse(json_str.join("\n"))
80
+
81
+ assert_equal 'slice_123', actual['report_slice_id']
82
+ assert_not_nil(actual_host = actual['hosts'].first)
83
+ assert_equal @host.interfaces.where.not(ip: nil).first.ip, actual_host['ip_addresses'].first
84
+ assert_equal @host.interfaces.where.not(mac: nil).first.mac, actual_host['mac_addresses'].first
66
85
  assert_equal @host.fqdn, actual_host['fqdn']
67
86
  assert_equal '1234', actual_host['account']
68
87
  assert_equal 1, generator.hosts_count
@@ -262,10 +281,17 @@ class ReportGeneratorTest < ActiveSupport::TestCase
262
281
  first_pool = @host.organization.pools.first
263
282
  second_pool = FactoryBot.create(:katello_pool, account_number: nil, cp_id: 2)
264
283
  new_org = FactoryBot.create(:organization, pools: [first_pool, second_pool])
265
- @host.organization = new_org
266
- @host.save!
267
284
 
268
- batch = Host.where(id: @host.id).in_batches.first
285
+ another_host = FactoryBot.create(
286
+ :host,
287
+ :with_subscription,
288
+ :with_content,
289
+ content_view: @host.content_view,
290
+ lifecycle_environment: @host.lifecycle_environment,
291
+ organization: new_org
292
+ )
293
+
294
+ batch = Host.where(id: another_host.id).in_batches.first
269
295
  generator = create_generator(batch)
270
296
 
271
297
  json_str = generator.render
@@ -10,12 +10,12 @@ export const PageDescription = () => (
10
10
  </p>
11
11
  <p>
12
12
  {__(
13
- 'In order to utilize these servies, you can set the auto upload in the settings to "ON".'
13
+ 'In order to utilize these services, you can set the auto upload in the settings to "ON".'
14
14
  )}
15
15
  </p>
16
16
  <p>
17
17
  {__(
18
- 'You can also trigger the upload manually by openning the relevant organization card, and clicking on the "Restart" button'
18
+ 'You can also trigger the upload manually by opening the relevant organization card, and clicking on the "Restart" button'
19
19
  )}
20
20
  </p>
21
21
  </div>
@@ -8,10 +8,10 @@ exports[`PageDescription rendering render without Props 1`] = `
8
8
  Red Hat Insights is a set of cloud services which provide unified subscription reporting, predictive analysis and remediation of issues through this Satellite instance.
9
9
  </p>
10
10
  <p>
11
- In order to utilize these servies, you can set the auto upload in the settings to "ON".
11
+ In order to utilize these services, you can set the auto upload in the settings to "ON".
12
12
  </p>
13
13
  <p>
14
- You can also trigger the upload manually by openning the relevant organization card, and clicking on the "Restart" button
14
+ You can also trigger the upload manually by opening the relevant organization card, and clicking on the "Restart" button
15
15
  </p>
16
16
  </div>
17
17
  `;
@@ -2,18 +2,44 @@ import React from 'react';
2
2
  import { IntlProvider } from 'react-intl';
3
3
  import PropTypes from 'prop-types';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
- import { Button } from 'patternfly-react';
5
+ import { Button, Icon } from 'patternfly-react';
6
6
  import { INSIGHTS_SYNC_PAGE_TITLE } from './InsightsCloudSyncConstants';
7
7
 
8
- const InsightsCloudSync = ({ syncInsights }) => {
8
+ const InsightsCloudSync = ({ data: { settingsUrl }, syncInsights }) => {
9
9
  document.title = INSIGHTS_SYNC_PAGE_TITLE;
10
10
  return (
11
11
  <IntlProvider locale={navigator.language}>
12
12
  <div className="insights-cloud-sync">
13
13
  <h1>{__('Red Hat Insights Sync')}</h1>
14
- <Button bsStyle="primary" onClick={syncInsights}>
15
- {__('Sync now')}
16
- </Button>
14
+ <p>
15
+ {__(`Insights synchronization process is used to provide Insights
16
+ recommendations output for hosts managed here`)}
17
+ </p>
18
+ <p>
19
+ {__(`1. Obtain an RHSM API token: `)}
20
+ <a
21
+ href="https://access.redhat.com/management/api"
22
+ target="_blank"
23
+ rel="noopener noreferrer"
24
+ >
25
+ access.redhat.com <Icon name="external-link" size="xs" />
26
+ </a>
27
+ <br />
28
+ {__("2. Copy the token to 'Red Hat Cloud token' setting: ")}
29
+ <a href={settingsUrl} target="_blank" rel="noopener noreferrer">
30
+ {__('Red Hat Cloud token ')}
31
+ <Icon name="external-link" size="xs" />
32
+ </a>
33
+ <br />
34
+ {__(
35
+ '3. Now you can syncronize recommendations manually using the "Sync now" button.'
36
+ )}
37
+ </p>
38
+ <div>
39
+ <Button bsStyle="primary" onClick={syncInsights}>
40
+ {__('Sync now')}
41
+ </Button>
42
+ </div>
17
43
  </div>
18
44
  </IntlProvider>
19
45
  );
@@ -21,6 +47,9 @@ const InsightsCloudSync = ({ syncInsights }) => {
21
47
 
22
48
  InsightsCloudSync.propTypes = {
23
49
  syncInsights: PropTypes.func.isRequired,
50
+ data: PropTypes.shape({
51
+ settingsUrl: PropTypes.string.isRequired,
52
+ }).isRequired,
24
53
  };
25
54
 
26
55
  export default InsightsCloudSync;
@@ -6,6 +6,9 @@ import InsightsCloudSync from './InsightsCloudSync';
6
6
  const fixtures = {
7
7
  render: {
8
8
  syncInsights: noop,
9
+ data: {
10
+ settingsUrl: 'www.example.com/settings',
11
+ },
9
12
  },
10
13
  };
11
14
 
@@ -10,16 +10,53 @@ exports[`InsightsCloudSync render 1`] = `
10
10
  <h1>
11
11
  Red Hat Insights Sync
12
12
  </h1>
13
- <Button
14
- active={false}
15
- block={false}
16
- bsClass="btn"
17
- bsStyle="primary"
18
- disabled={false}
19
- onClick={[Function]}
20
- >
21
- Sync now
22
- </Button>
13
+ <p>
14
+ Insights synchronization process is used to provide Insights
15
+ recommendations output for hosts managed here
16
+ </p>
17
+ <p>
18
+ 1. Obtain an RHSM API token:
19
+ <a
20
+ href="https://access.redhat.com/management/api"
21
+ rel="noopener noreferrer"
22
+ target="_blank"
23
+ >
24
+ access.redhat.com
25
+ <Icon
26
+ name="external-link"
27
+ size="xs"
28
+ type="fa"
29
+ />
30
+ </a>
31
+ <br />
32
+ 2. Copy the token to 'Red Hat Cloud token' setting:
33
+ <a
34
+ href="www.example.com/settings"
35
+ rel="noopener noreferrer"
36
+ target="_blank"
37
+ >
38
+ Red Hat Cloud token
39
+ <Icon
40
+ name="external-link"
41
+ size="xs"
42
+ type="fa"
43
+ />
44
+ </a>
45
+ <br />
46
+ 3. Now you can syncronize recommendations manually using the "Sync now" button.
47
+ </p>
48
+ <div>
49
+ <Button
50
+ active={false}
51
+ block={false}
52
+ bsClass="btn"
53
+ bsStyle="primary"
54
+ disabled={false}
55
+ onClick={[Function]}
56
+ >
57
+ Sync now
58
+ </Button>
59
+ </div>
23
60
  </div>
24
61
  </IntlProvider>
25
62
  `;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_rh_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.8
4
+ version: 2.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Red Hat Cloud team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-30 00:00:00.000000000 Z
11
+ date: 2020-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: katello