foreman_rh_cloud 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
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