foreman_discovery 26.1.3 → 26.2.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: a6a3c47ba004165224710132b067bcd2fb2f240fa7fd684c788891730e2efc77
4
- data.tar.gz: 21bb4c7c7f00cc7431e7c490d74d5789ae1229b52be1a1e63d504896d573ec5a
3
+ metadata.gz: db9a40b5eced1c71a3724f822961f21e18ec8f785da702eb3ec9618bfb5ac68a
4
+ data.tar.gz: 44e6f535f5c82c87dcbd66283cd7c2184b39279bd9280946b0ff59a4d9e6b397
5
5
  SHA512:
6
- metadata.gz: b15b447fab37b8bf9447bc4337827ad3ea688107013e938487e2719a9d5ec8d3a4a97abdfed8df5cd84dc84ea91745d8402a21671a7fb346b3626b9043ebe35f
7
- data.tar.gz: faeec5cbd30ca4d9cbac9f50fe14a38cb60fa088fcfb4f7bfafecf6bf35f8dfdd2667efd8cf15408baf9953f38182159e0fe2da9e79900b518cd1cb393368870
6
+ metadata.gz: dd5dda0f43e6173fefbfaf295b9da9d6ba5c6b4d4099aee461796616da9f6a57fd6fa2d74724cd397f16069387cf479f9bb4a501083ceccbb684a71bfcbae2c8
7
+ data.tar.gz: 10dfc2528a92aacc77c741b6a1d623912ba9592f37625c819be6e8f5993037780e1fe3713528a470b3617f76df070d2824eacaa72ef3681159f9552fc5709699
@@ -19,6 +19,16 @@ module ForemanDiscovery
19
19
 
20
20
  @host = ::ForemanDiscovery::HostConverter.to_managed(@host, true, false, host_params) if @host.is_a?(Host::Discovered)
21
21
  end
22
+
23
+ def find_resource
24
+ if (id = params[:id]).blank?
25
+ not_found
26
+ return false
27
+ end
28
+ @host = Host::Discovered.authorized(:edit_discovered_hosts, Host::Discovered).find_by(id: id)
29
+ @host ||= super
30
+ @host
31
+ end
22
32
  end
23
33
  end
24
34
  end
@@ -55,7 +55,7 @@ class ForemanDiscovery::HostConverter
55
55
  end
56
56
 
57
57
  def self.ip_for_subnet(subnet, mac, ip)
58
- return ip if ip && subnet&.unused_ip(mac)&.ip_include?(ip)
58
+ return ip if ip.present? && subnet&.unused_ip(mac)&.ip_include?(ip)
59
59
 
60
60
  unused_ip_for_subnet(subnet, mac, ip)
61
61
  end
@@ -1,2 +1,2 @@
1
1
  f = Feature.unscoped.where(:name => 'Discovery').first_or_create
2
- raise "Unable to create proxy feature: #{format_errors f}" if f.nil? || f.errors.any?
2
+ raise "Unable to create proxy feature: #{SeedHelper.format_errors(f)}" if f.nil? || f.errors.any?
@@ -1,3 +1,3 @@
1
1
  module ForemanDiscovery
2
- VERSION = "26.1.3"
2
+ VERSION = "26.2.0"
3
3
  end
data/package.json CHANGED
@@ -5,9 +5,9 @@
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "lint": "tfm-lint --plugin -d /webpack",
8
- "test": "tfm-test --plugin",
9
- "test:watch": "tfm-test --plugin --watchAll",
10
- "test:current": "tfm-test --plugin --watch",
8
+ "test": "tfm-test --plugin --config jest.config.js",
9
+ "test:watch": "tfm-test --plugin --config jest.config.js --watchAll",
10
+ "test:current": "tfm-test --plugin --config jest.config.js --watch",
11
11
  "publish-coverage": "tfm-publish-coverage",
12
12
  "create-react-component": "yo react-domain"
13
13
  },
@@ -25,6 +25,7 @@
25
25
  "@babel/core": "^7.7.0",
26
26
  "@theforeman/builder": ">= 0",
27
27
  "@theforeman/eslint-plugin-foreman": ">= 0",
28
+ "@theforeman/find-foreman": ">= 0",
28
29
  "@theforeman/test": ">= 0",
29
30
  "eslint": "^6.7.2",
30
31
  "prettier": "^1.19.1",
@@ -50,6 +50,47 @@ module ForemanDiscovery
50
50
  assert_instance_of Host::Managed, assigns(:host)
51
51
  end
52
52
  end
53
+
54
+ describe 'find_resource' do
55
+ include FactImporterIsolation
56
+ allow_transactions_for_any_importer
57
+
58
+ setup do
59
+ @facts = {
60
+ "interfaces" => "lo,eth0",
61
+ "ipaddress" => "192.168.100.42",
62
+ "ipaddress_eth0" => "192.168.100.42",
63
+ "macaddress_eth0" => "AA:BB:CC:DD:EE:FF",
64
+ "discovery_bootif" => "AA:BB:CC:DD:EE:FF",
65
+ "physicalprocessorcount" => "42",
66
+ "discovery_version" => "3.0.0",
67
+ }
68
+ end
69
+
70
+ test 'finds a discovered host directly without converting it' do
71
+ host = discover_host_from_facts(@facts)
72
+ get :build_errors, params: { id: host.id }, session: set_session_user
73
+
74
+ assert_response :success
75
+ assert_instance_of Host::Discovered, assigns(:host)
76
+ assert_equal host, assigns(:host)
77
+ end
78
+
79
+ test 'falls back to the core lookup for a managed host' do
80
+ host = FactoryBot.create(:host, :managed)
81
+ get :build_errors, params: { id: host.id }, session: set_session_user
82
+
83
+ assert_response :success
84
+ assert_instance_of Host::Managed, assigns(:host)
85
+ assert_equal host, assigns(:host)
86
+ end
87
+
88
+ test 'renders not found for an unknown host id' do
89
+ get :build_errors, params: { id: 0 }, session: set_session_user
90
+
91
+ assert_response :not_found
92
+ end
93
+ end
53
94
  end
54
95
  end
55
96
  end
@@ -238,8 +238,8 @@ class DiscoveredExtensionsTest < ActiveSupport::TestCase
238
238
  ::ForemanDiscovery::HostConverter.unstub(:unused_ip_for_host)
239
239
  facts = @facts_ipv6.merge({"somefact" => "abc"})
240
240
  domain = FactoryBot.create(:domain)
241
- subnet = FactoryBot.create(:subnet_ipv6, :tftp, :dhcp, :network => "2001:db8::/32", :mask => "ffff:ffff::", :name => "ipv6_discovered", :ipam => IPAM::MODES[:eui64], :organizations => [Organization.find_by_name("Organization 1")], :locations => [Location.find_by_name("Location 1")])
242
- subnet2 = FactoryBot.create(:subnet_ipv6, :tftp, :dhcp, :network => "2001:db9::/32", :mask => "ffff:ffff::", :name => "ipv6_provision", :ipam => IPAM::MODES[:eui64], :organizations => [Organization.find_by_name("Organization 1")], :locations => [Location.find_by_name("Location 1")])
241
+ subnet = FactoryBot.create(:subnet_ipv6, :tftp, :dhcp, :network => "2001:db8::", :mask => "ffff:ffff::", :name => "ipv6_discovered", :ipam => IPAM::MODES[:eui64], :organizations => [Organization.find_by_name("Organization 1")], :locations => [Location.find_by_name("Location 1")])
242
+ subnet2 = FactoryBot.create(:subnet_ipv6, :tftp, :dhcp, :network => "2001:db9::", :mask => "ffff:ffff::", :name => "ipv6_provision", :ipam => IPAM::MODES[:eui64], :organizations => [Organization.find_by_name("Organization 1")], :locations => [Location.find_by_name("Location 1")])
243
243
  host = discover_host_from_facts(facts)
244
244
  assert_equal subnet, host.subnet6
245
245
  hostgroup = FactoryBot.create(:hostgroup, :with_rootpass, :with_os, :pxe_loader => "PXELinux BIOS", :subnet6 => subnet2, :domain => domain)
@@ -1,12 +1,37 @@
1
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
1
+ import React from 'react';
2
+ import { screen } from '@testing-library/react';
3
+ import { rtlHelpers } from 'foremanReact/common/testHelpers';
2
4
 
3
5
  import ForemanEmptyState from '../EmptyState';
4
6
 
5
- const fixtures = {
6
- 'render with Props': { docUrl: 'https://foreman.example.com' },
7
- };
7
+ const docUrl = 'https://foreman.example.com';
8
8
 
9
9
  describe('ForemanEmptyState', () => {
10
- describe('rendering', () =>
11
- testComponentSnapshotsWithFixtures(ForemanEmptyState, fixtures));
10
+ it('renders discovered hosts empty state content', () => {
11
+ rtlHelpers.renderWithStore(<ForemanEmptyState docUrl={docUrl} />);
12
+
13
+ expect(
14
+ screen.getByRole('heading', { name: 'Foreman Discovery', level: 5 })
15
+ ).toBeInTheDocument();
16
+ expect(
17
+ screen.getByText(
18
+ 'No discovered hosts found in this context. This page shows discovered bare-metal or virtual nodes waiting to be provisioned.'
19
+ )
20
+ ).toBeInTheDocument();
21
+ expect(
22
+ screen.getByText('For more information please see')
23
+ ).toBeInTheDocument();
24
+
25
+ const docLink = screen.getByRole('link', { name: 'documentation' });
26
+ expect(docLink).toHaveAttribute('href', docUrl);
27
+ expect(docLink).toHaveAttribute('target', '_blank');
28
+ expect(docLink).toHaveAttribute('rel', 'external noreferrer noopener');
29
+
30
+ expect(screen.queryByText('Create Rule')).not.toBeInTheDocument();
31
+ expect(
32
+ document.querySelector(
33
+ '[data-ouia-component-id="empty-state-action-button"]'
34
+ )
35
+ ).not.toBeInTheDocument();
36
+ });
12
37
  });
@@ -1,19 +1,37 @@
1
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
- import ForemanEmptyState from '../EmptyState';
1
+ import React from 'react';
2
+ import { screen } from '@testing-library/react';
3
+ import { rtlHelpers } from 'foremanReact/common/testHelpers';
3
4
 
4
- const action = {
5
- title: 'action-title',
6
- url: `action-url`,
7
- };
5
+ import ForemanEmptyState from '../EmptyState';
8
6
 
9
- const fixtures = {
10
- 'render with Props': {
11
- docUrl: 'https://foreman.example.com',
12
- action,
13
- },
14
- };
7
+ const docUrl = 'https://foreman.example.com';
15
8
 
16
9
  describe('ForemanEmptyState', () => {
17
- describe('rendering', () =>
18
- testComponentSnapshotsWithFixtures(ForemanEmptyState, fixtures));
10
+ it('renders discovery rules empty state content', () => {
11
+ rtlHelpers.renderWithStore(<ForemanEmptyState docUrl={docUrl} />);
12
+
13
+ expect(
14
+ screen.getByRole('heading', { name: 'Discovery Rules', level: 5 })
15
+ ).toBeInTheDocument();
16
+ expect(
17
+ screen.getByText(
18
+ 'No Discovery Rules found in this context. Create Discovery Rules to perform automated provisioning on Discovered Hosts'
19
+ )
20
+ ).toBeInTheDocument();
21
+ expect(
22
+ screen.getByText('For more information please see')
23
+ ).toBeInTheDocument();
24
+
25
+ const docLink = screen.getByRole('link', { name: 'documentation' });
26
+ expect(docLink).toHaveAttribute('href', docUrl);
27
+ expect(docLink).toHaveAttribute('target', '_blank');
28
+ expect(docLink).toHaveAttribute('rel', 'external noreferrer noopener');
29
+
30
+ const actionButton = screen.getByText('Create Rule');
31
+ expect(actionButton).toBeInTheDocument();
32
+ expect(actionButton).toHaveAttribute(
33
+ 'data-ouia-component-id',
34
+ 'empty-state-action-button'
35
+ );
36
+ });
19
37
  });
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_discovery
3
3
  version: !ruby/object:Gem::Version
4
- version: 26.1.3
4
+ version: 26.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aditi Puntambekar
@@ -295,23 +295,14 @@ files:
295
295
  - test/unit/managed_extensions_test.rb
296
296
  - test/unit/ui_notifications/destroy_host_test.rb
297
297
  - test/unit/ui_notifications/new_host_test.rb
298
- - webpack/__mocks__/foremanReact/common/I18n.js
299
- - webpack/__mocks__/foremanReact/common/helpers.js
300
- - webpack/__mocks__/foremanReact/common/index.js
301
- - webpack/__mocks__/foremanReact/components/common/EmptyState/DefaultEmptyState.js
302
- - webpack/__mocks__/foremanReact/components/common/EmptyState/EmptyStatePattern.js
303
- - webpack/__mocks__/foremanReact/components/common/EmptyState/EmptyStatePropTypes.js
304
- - webpack/__mocks__/foremanReact/components/common/EmptyState/index.js
305
298
  - webpack/index.js
306
299
  - webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/EmptyState.js
307
300
  - webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/__test__/EmptyState.test.js
308
- - webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/__test__/__snapshots__/EmptyState.test.js.snap
309
301
  - webpack/src/ForemanDiscovery/DiscoveredHosts/Components/EmptyState/index.js
310
302
  - webpack/src/ForemanDiscovery/DiscoveredHosts/index.js
311
303
  - webpack/src/ForemanDiscovery/DiscoveryRules/Components/EmptyState/EmptyState.js
312
304
  - webpack/src/ForemanDiscovery/DiscoveryRules/Components/EmptyState/index.js
313
305
  - webpack/src/ForemanDiscovery/DiscoveryRules/Components/__test__/EmptyState.test.js
314
- - webpack/src/ForemanDiscovery/DiscoveryRules/Components/__test__/__snapshots__/EmptyState.test.js.snap
315
306
  - webpack/src/ForemanDiscovery/DiscoveryRules/index.js
316
307
  - webpack/src/reducers.js
317
308
  homepage: https://github.com/theforeman/foreman_discovery
@@ -332,7 +323,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
332
323
  - !ruby/object:Gem::Version
333
324
  version: '0'
334
325
  requirements: []
335
- rubygems_version: 4.0.3
326
+ rubygems_version: 4.0.20
336
327
  specification_version: 4
337
328
  summary: MaaS Discovery Plugin for Foreman
338
329
  test_files:
@@ -1,3 +0,0 @@
1
- export const translate = s => s;
2
-
3
- export const ngettext = s => s;
@@ -1 +0,0 @@
1
- export const foremanUrl = path => `${window.URL_PREFIX}${path}`;
@@ -1,5 +0,0 @@
1
- import EmptyStatePattern from '../components/common/EmptyState/EmptyStatePattern';
2
- import DefaultEmptyState from '../components/common/EmptyState/DefaultEmptyState';
3
-
4
- export default DefaultEmptyState;
5
- export { EmptyStatePattern };
@@ -1,71 +0,0 @@
1
- import React from 'react';
2
- import { useDispatch } from 'react-redux';
3
- import { push } from 'connected-react-router';
4
- import { Button } from '@patternfly/react-core';
5
- import EmptyStatePattern from './EmptyStatePattern';
6
- import { defaultEmptyStatePropTypes } from './EmptyStatePropTypes';
7
-
8
- const DefaultEmptyState = props => {
9
- const {
10
- icon,
11
- iconType,
12
- header,
13
- description,
14
- documentation,
15
- action,
16
- secondaryActions,
17
- } = props;
18
-
19
- const dispatch = useDispatch();
20
- const actionButtonClickHandler = ({ url, onClick }) => {
21
- if (onClick) onClick();
22
- else if (url) dispatch(push(url));
23
- };
24
-
25
- const ActionButton = action ? (
26
- <Button
27
- component="a"
28
- onClick={() => actionButtonClickHandler(action)}
29
- variant="primary"
30
- ouiaId="empty-state-primary-action-button"
31
- >
32
- {action.title}
33
- </Button>
34
- ) : null;
35
-
36
- const SecondaryButton = secondaryActions
37
- ? secondaryActions.map(({ title, url, onClick }) => (
38
- <Button
39
- component="a"
40
- key={`sec-button-${title}`}
41
- onClick={() => actionButtonClickHandler({ url, onClick })}
42
- variant="secondary"
43
- ouiaId="empty-state-secondary-action-button"
44
- >
45
- {title}
46
- </Button>
47
- ))
48
- : null;
49
-
50
- return (
51
- <EmptyStatePattern
52
- icon={icon}
53
- iconType={iconType}
54
- header={header}
55
- description={description}
56
- documentation={documentation}
57
- action={ActionButton}
58
- secondaryActions={SecondaryButton}
59
- />
60
- );
61
- };
62
-
63
- DefaultEmptyState.propTypes = defaultEmptyStatePropTypes;
64
-
65
- DefaultEmptyState.defaultProps = {
66
- icon: 'add-circle-o',
67
- secondaryActions: [],
68
- iconType: 'pf',
69
- };
70
-
71
- export default DefaultEmptyState;
@@ -1,76 +0,0 @@
1
- import React from 'react';
2
- import { Icon } from 'patternfly-react';
3
- import {
4
- EmptyState,
5
- EmptyStateVariant,
6
- EmptyStateBody,
7
- EmptyStateActions,
8
- EmptyStateHeader,
9
- EmptyStateFooter,
10
- } from '@patternfly/react-core';
11
- import { emptyStatePatternPropTypes } from './EmptyStatePropTypes';
12
- import { translate as __ } from '../../../common/I18n';
13
-
14
- const EmptyStatePattern = props => {
15
- const {
16
- documentation,
17
- action,
18
- secondaryActions,
19
- iconType,
20
- icon,
21
- header,
22
- description,
23
- } = props;
24
-
25
- const DocumentationBlock = () => {
26
- if (!documentation) {
27
- return null;
28
- }
29
- // The documentation prop can also be a customized node
30
- if (React.isValidElement(documentation)) {
31
- return documentation;
32
- }
33
- const {
34
- label = __('For more information please see '), // eslint-disable-line react/prop-types
35
- buttonLabel = __('documentation'), // eslint-disable-line react/prop-types
36
- url, // eslint-disable-line react/prop-types
37
- } = documentation;
38
- return (
39
- <span>
40
- {label}
41
- <a href={url}>{buttonLabel}</a>
42
- </span>
43
- );
44
- };
45
-
46
- return (
47
- <EmptyState variant={EmptyStateVariant.xl}>
48
- <span className="empty-state-icon">
49
- {/* TODO: Add pf4 icons, Redmine issue: #30865 */}
50
- <Icon name={icon} type={iconType} size="2x" />
51
- </span>
52
- <EmptyStateHeader titleText={<>{header}</>} headingLevel="h5" />
53
- <EmptyStateBody>
54
- <div className="empty-state-description">{description}</div>
55
- <DocumentationBlock />
56
- </EmptyStateBody>
57
- <EmptyStateFooter>
58
- {action}
59
- <EmptyStateActions>{secondaryActions}</EmptyStateActions>
60
- </EmptyStateFooter>
61
- </EmptyState>
62
- );
63
- };
64
-
65
- EmptyStatePattern.propTypes = emptyStatePatternPropTypes;
66
-
67
- EmptyStatePattern.defaultProps = {
68
- icon: 'add-circle-o',
69
- secondaryActions: [],
70
- documentation: {
71
- url: '#',
72
- },
73
- iconType: 'pf',
74
- };
75
-
76
- export default EmptyStatePattern;
@@ -1,29 +0,0 @@
1
- import PropTypes from 'prop-types';
2
-
3
- export const actionButtonPropTypes = {
4
- title: PropTypes.node.isRequired,
5
- url: PropTypes.string,
6
- onChange: PropTypes.func,
7
- };
8
-
9
- export const emptyStatePatternPropTypes = {
10
- icon: PropTypes.string.isRequired,
11
- header: PropTypes.string.isRequired,
12
- documentation: PropTypes.oneOfType([
13
- PropTypes.shape({
14
- label: PropTypes.string,
15
- buttonLabel: PropTypes.string,
16
- url: PropTypes.string.isRequired,
17
- }),
18
- PropTypes.node,
19
- ]),
20
- description: PropTypes.string.isRequired,
21
- action: PropTypes.node,
22
- secondaryActions: PropTypes.node,
23
- };
24
-
25
- export const defaultEmptyStatePropTypes = {
26
- ...emptyStatePatternPropTypes,
27
- action: PropTypes.shape(actionButtonPropTypes),
28
- secondaryActions: PropTypes.arrayOf(PropTypes.shape(actionButtonPropTypes)),
29
- };
@@ -1,5 +0,0 @@
1
- import EmptyStatePattern from './EmptyStatePattern';
2
- import DefaultEmptyState from './DefaultEmptyState';
3
-
4
- export default DefaultEmptyState;
5
- export { EmptyStatePattern };
@@ -1,16 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`ForemanEmptyState rendering render with Props 1`] = `
4
- <DefaultEmptyState
5
- description="No discovered hosts found in this context. This page shows discovered bare-metal or virtual nodes waiting to be provisioned."
6
- documentation={
7
- Object {
8
- "url": "https://foreman.example.com",
9
- }
10
- }
11
- header="Foreman Discovery"
12
- icon="gears"
13
- iconType="fa"
14
- secondaryActions={Array []}
15
- />
16
- `;
@@ -1,22 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`ForemanEmptyState rendering render with Props 1`] = `
4
- <DefaultEmptyState
5
- action={
6
- Object {
7
- "title": "Create Rule",
8
- "url": "/discovery_rules/new",
9
- }
10
- }
11
- description="No Discovery Rules found in this context. Create Discovery Rules to perform automated provisioning on Discovered Hosts"
12
- documentation={
13
- Object {
14
- "url": "https://foreman.example.com",
15
- }
16
- }
17
- header="Discovery Rules"
18
- icon="gavel"
19
- iconType="fa"
20
- secondaryActions={Array []}
21
- />
22
- `;