foreman_puppet 3.0.7 → 4.0.2

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/lib/foreman_puppet/engine.rb +1 -0
  4. data/lib/foreman_puppet/register.rb +2 -2
  5. data/lib/foreman_puppet/version.rb +1 -1
  6. data/package.json +7 -7
  7. data/test/controllers/foreman_puppet/api/v2/override_values_controller_test.rb +6 -2
  8. data/test/models/foreman_puppet/host_test.rb +6 -0
  9. data/webpack/global_index.js +11 -0
  10. data/webpack/index.js +0 -7
  11. data/webpack/legacy.js +31 -0
  12. data/webpack/src/Extends/Fills/index.js +26 -0
  13. data/webpack/src/Extends/Host/PuppetTab/Routes.js +46 -0
  14. data/webpack/src/Extends/Host/PuppetTab/SubTabs/ENCPreview/ENCTab.js +61 -0
  15. data/webpack/src/Extends/Host/PuppetTab/SubTabs/ENCPreview/index.js +56 -0
  16. data/webpack/src/Extends/Host/PuppetTab/SubTabs/EmptyPage.js +20 -0
  17. data/webpack/src/Extends/Host/PuppetTab/SubTabs/Reports/components/DescriptionCard.js +88 -0
  18. data/webpack/src/Extends/Host/PuppetTab/SubTabs/Reports/index.js +50 -0
  19. data/webpack/src/Extends/Host/PuppetTab/SubTabs/Reports/styles.scss +7 -0
  20. data/webpack/src/Extends/Host/PuppetTab/constants.js +8 -0
  21. data/webpack/src/Extends/Host/PuppetTab/helpers.js +3 -0
  22. data/webpack/src/Extends/Host/PuppetTab/index.js +51 -0
  23. metadata +62 -88
  24. data/locale/ca/foreman_puppet.edit.po +0 -1221
  25. data/locale/ca/foreman_puppet.po.time_stamp +0 -0
  26. data/locale/cs_CZ/foreman_puppet.edit.po +0 -1208
  27. data/locale/cs_CZ/foreman_puppet.po.time_stamp +0 -0
  28. data/locale/de/foreman_puppet.edit.po +0 -1300
  29. data/locale/de/foreman_puppet.po.time_stamp +0 -0
  30. data/locale/en/foreman_puppet.edit.po +0 -998
  31. data/locale/en/foreman_puppet.po.time_stamp +0 -0
  32. data/locale/en/foreman_puppet.pox +0 -0
  33. data/locale/en_GB/foreman_puppet.edit.po +0 -1197
  34. data/locale/en_GB/foreman_puppet.po.time_stamp +0 -0
  35. data/locale/es/foreman_puppet.edit.po +0 -1275
  36. data/locale/es/foreman_puppet.po.time_stamp +0 -0
  37. data/locale/fr/foreman_puppet.edit.po +0 -1290
  38. data/locale/fr/foreman_puppet.po.time_stamp +0 -0
  39. data/locale/gl/foreman_puppet.edit.po +0 -1203
  40. data/locale/gl/foreman_puppet.po.time_stamp +0 -0
  41. data/locale/it/foreman_puppet.edit.po +0 -1233
  42. data/locale/it/foreman_puppet.po.time_stamp +0 -0
  43. data/locale/ja/foreman_puppet.edit.po +0 -1223
  44. data/locale/ja/foreman_puppet.po.time_stamp +0 -0
  45. data/locale/ko/foreman_puppet.edit.po +0 -1197
  46. data/locale/ko/foreman_puppet.po.time_stamp +0 -0
  47. data/locale/messages.mo +0 -0
  48. data/locale/nl_NL/foreman_puppet.edit.po +0 -1228
  49. data/locale/nl_NL/foreman_puppet.po.time_stamp +0 -0
  50. data/locale/pl/foreman_puppet.edit.po +0 -1238
  51. data/locale/pl/foreman_puppet.po.time_stamp +0 -0
  52. data/locale/pt_BR/foreman_puppet.edit.po +0 -1281
  53. data/locale/pt_BR/foreman_puppet.po.time_stamp +0 -0
  54. data/locale/ru/foreman_puppet.edit.po +0 -1240
  55. data/locale/ru/foreman_puppet.po.time_stamp +0 -0
  56. data/locale/sv_SE/foreman_puppet.edit.po +0 -1205
  57. data/locale/sv_SE/foreman_puppet.po.time_stamp +0 -0
  58. data/locale/zh_CN/foreman_puppet.edit.po +0 -1212
  59. data/locale/zh_CN/foreman_puppet.po.time_stamp +0 -0
  60. data/locale/zh_TW/foreman_puppet.edit.po +0 -1197
  61. data/locale/zh_TW/foreman_puppet.po.time_stamp +0 -0
  62. data/webpack/fills_index.js +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 772e941b4202bbfdde858905799bfeea60fa6709ba5e473041b514f8a90697a8
4
- data.tar.gz: 967448785c3adaddf2987365df7f990794d5c354160d78feb4e546472399bca4
3
+ metadata.gz: ad4345e5b4481b1263e0d9a6af568f6d899288fb6e25843dbc0bb5cabf86b5b9
4
+ data.tar.gz: 61e41f2886a32d9b73b42513b69d1eb5f0ba28b3151a68c0be21a14b62ca039f
5
5
  SHA512:
6
- metadata.gz: 742a59e022663c55a15838049c8eaf5827180a0abcfa8989759a409c40b3bf59f912e8deeaf5ebd730dbb16787698968e0ed71879d9183c2f14c99a7780e648a
7
- data.tar.gz: 4c32122d44b7cf75abdcfa1119c9cda80771b43511fa575bb8f155015ee5b191f3d1f8420072a32e749487da777bd719ca301bbc794e65d50af8edddf90f00ce
6
+ metadata.gz: ae6266081bbf344be643d88bbd57dfa2a8028f897dee6df45d6e08d5c7bddc451cae45b49759c484d8561a84fd8d96b35636fc5aa4165df49193e5b17d65edc8
7
+ data.tar.gz: 829314db4098020a1471276f94f6f1e8bc3421f7f3c1af3d5d08228f4ac811e999c5ce48bade42871a86775f9e630f40e991044a4411a07fb343a9ed8f9a2811
data/README.md CHANGED
@@ -37,6 +37,7 @@ You can install it on Foreman 2.5 to prepare for the Foreman update.
37
37
 
38
38
  |Foreman version|Plugin version|Notes |
39
39
  |---------------|--------------|------------------------------------------|
40
+ | >= 3.3 | ~> 4.0 | Required |
40
41
  | >= 3.2 | ~> 3.0 | Required |
41
42
  | ~> 3.1 | ~> 2.0 | Required |
42
43
  | ~> 3.0 | ~> 1.0 | Required |
@@ -78,7 +79,7 @@ Fork and send a Pull Request. Thanks!
78
79
 
79
80
  ## Copyright
80
81
 
81
- Copyright (c) *2021* *The Foreman developers*
82
+ Copyright (c) *2022* *The Foreman developers*
82
83
 
83
84
  This program is free software: you can redistribute it and/or modify
84
85
  it under the terms of the GNU General Public License as published by
@@ -58,6 +58,7 @@ module ForemanPuppet
58
58
  ::Api::V2::TemplateCombinationsController.include ForemanPuppet::Extensions::ApiTemplateCombinationsController
59
59
  ::Api::V2::HostsController.include ForemanPuppet::Extensions::ParametersHost
60
60
  ::Api::V2::HostgroupsController.include ForemanPuppet::Extensions::ParametersHostgroup
61
+ ::ComputeResourcesVmsController.helper ForemanPuppet::HostsAndHostgroupsHelper
61
62
  ::OperatingsystemsController.prepend ForemanPuppet::Extensions::OperatingsystemsController
62
63
  ::HostsController.include ForemanPuppet::Extensions::HostsControllerExtensions
63
64
  ::HostsController.include ForemanPuppet::Extensions::ParametersHost
@@ -1,7 +1,7 @@
1
1
  Foreman::Plugin.register :foreman_puppet do
2
- requires_foreman '>= 3.0.0'
2
+ requires_foreman '>= 3.3.0'
3
3
  # Add Global JS file for extending foreman-core components and routes
4
- register_global_js_file 'fills'
4
+ register_global_js_file 'global'
5
5
 
6
6
  settings do
7
7
  category(:facts, N_('Facts')) do
@@ -1,3 +1,3 @@
1
1
  module ForemanPuppet
2
- VERSION = '3.0.7'.freeze
2
+ VERSION = '4.0.2'.freeze
3
3
  end
data/package.json CHANGED
@@ -21,17 +21,17 @@
21
21
  "url": "http://projects.theforeman.org/projects/foreman_puppet/issues"
22
22
  },
23
23
  "peerDependencies": {
24
- "@theforeman/vendor": "^8.15.0"
24
+ "@theforeman/vendor": "^10.1.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@babel/core": "^7.7.0",
28
28
  "@sheerun/mutationobserver-shim": "^0.3.3",
29
- "@theforeman/builder": "^8.15.0",
30
- "@theforeman/eslint-plugin-foreman": "^8.15.0",
31
- "@theforeman/find-foreman": "^8.15.0",
32
- "@theforeman/stories": "^8.15.0",
33
- "@theforeman/test": "^8.15.0",
34
- "@theforeman/vendor-dev": "^8.15.0",
29
+ "@theforeman/builder": "^10.1.0",
30
+ "@theforeman/eslint-plugin-foreman": "^10.1.0",
31
+ "@theforeman/find-foreman": "^10.1.0",
32
+ "@theforeman/stories": "^10.1.0",
33
+ "@theforeman/test": "^10.1.0",
34
+ "@theforeman/vendor-dev": "^10.1.0",
35
35
  "babel-eslint": "^10.0.3",
36
36
  "eslint": "^6.7.2",
37
37
  "jed": "^1.1.1",
@@ -75,8 +75,12 @@ module ForemanPuppet
75
75
  post :create, params: { smart_class_parameter_id: lookup_key.id, override_value: override_value }
76
76
  end
77
77
  response = ActiveSupport::JSON.decode(@response.body)
78
- param_not_posted = (override_value.keys.first.to_s == 'match') ? 'Value' : 'Match' # The opposite of override_value is missing
79
- assert_match(/Validation failed: #{param_not_posted} can't be blank/, response['error']['message'])
78
+ if override_value.keys.first.to_s == 'match'
79
+ # The opposite of override_value is missing and should fail
80
+ assert_match(/Validation failed: Value can't be blank/, response['error']['message'])
81
+ else # match is missing
82
+ assert_match(/Failed to save the record/, response['error']['message'])
83
+ end
80
84
  assert_response :error
81
85
  end
82
86
  end
@@ -110,6 +110,12 @@ module ForemanPuppet
110
110
  end
111
111
 
112
112
  describe '#info puppet bits' do
113
+ test 'ENC YAML omits environment if no puppet facet' do
114
+ host = FactoryBot.build_stubbed(:host)
115
+ enc = host.info
116
+ assert_not_includes enc.keys, 'environment'
117
+ end
118
+
113
119
  test 'ENC YAML uses Classification::ClassParam for parameterized output' do
114
120
  skip 'No idea whats wrong here'
115
121
  host = FactoryBot.build_stubbed(:host, :with_environment)
@@ -0,0 +1,11 @@
1
+ import { registerReducer } from 'foremanReact/common/MountingService';
2
+ import reducers from './src/reducers';
3
+ import { registerFills } from './src/Extends/Fills';
4
+ import { registerLegacy } from './legacy';
5
+
6
+ // register reducers
7
+ registerReducer('puppet', reducers);
8
+ // add fills
9
+ registerFills();
10
+ // TODO: the checkForUnavailablePuppetclasses is very nasty
11
+ registerLegacy();
data/webpack/index.js CHANGED
@@ -2,16 +2,9 @@
2
2
  /* eslint-disable import/no-extraneous-dependencies */
3
3
  /* eslint-disable import/extensions */
4
4
  import componentRegistry from 'foremanReact/components/componentRegistry';
5
- import { registerReducer } from 'foremanReact/common/MountingService';
6
- import reducers from './src/reducers';
7
5
  import ForemanPuppet from './src/ForemanPuppet';
8
6
  import { WelcomeEnv } from './src/Components/Environments/Welcome';
9
7
 
10
- // register reducers
11
- Object.entries(reducers).forEach(([key, reducer]) =>
12
- registerReducer(key, reducer)
13
- );
14
-
15
8
  // register components for erb mounting
16
9
  componentRegistry.register({ name: 'WelcomeEnv', type: WelcomeEnv });
17
10
  componentRegistry.register({ name: 'ForemanPuppet', type: ForemanPuppet });
data/webpack/legacy.js ADDED
@@ -0,0 +1,31 @@
1
+ import $ from 'jquery';
2
+ import * as classEditor from './src/foreman_class_edit';
3
+ import * as hostForm from './src/foreman_puppet_host_form';
4
+
5
+ export const registerLegacy = () => {
6
+ window.tfm = Object.assign(window.tfm || {}, {
7
+ classEditor,
8
+ puppetEnc: {
9
+ hostForm,
10
+ },
11
+ });
12
+
13
+ // TODO: the checkForUnavailablePuppetclasses is very nasty
14
+ $(document)
15
+ .on('change', '.hostgroup-select', evt => {
16
+ const form = $('form.host-form')[0];
17
+ if (form && form.dataset.id) hostForm.updatePuppetclasses(evt.target);
18
+ })
19
+ .on('change', '.interface_domain', evt => {
20
+ hostForm.reloadPuppetclassParams();
21
+ })
22
+ .on('change', '.host-architecture-os-select', evt => {
23
+ hostForm.reloadPuppetclassParams();
24
+ })
25
+ .on('ContentLoad', evt => {
26
+ hostForm.checkForUnavailablePuppetclasses();
27
+ });
28
+ $(window).on('load', evt => {
29
+ hostForm.checkForUnavailablePuppetclasses();
30
+ });
31
+ };
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import { translate as __ } from 'foremanReact/common/I18n';
3
+ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
4
+ import PuppetTab from '../Host/PuppetTab';
5
+
6
+ const fills = [
7
+ {
8
+ slot: 'host-details-page-tabs',
9
+ name: 'Puppet',
10
+ component: props => <PuppetTab {...props} />,
11
+ weight: 500,
12
+ metadata: { title: __('Puppet') },
13
+ },
14
+ ];
15
+
16
+ export const registerFills = () => {
17
+ fills.forEach(({ slot, name, component: Component, weight, metadata }) =>
18
+ addGlobalFill(
19
+ slot,
20
+ name,
21
+ <Component key={`puppet-fill-${name}`} />,
22
+ weight,
23
+ metadata
24
+ )
25
+ );
26
+ };
@@ -0,0 +1,46 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import { Route, Switch, Redirect } from 'react-router-dom';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
5
+ import { route } from './helpers';
6
+ import EmptyPage from './SubTabs/EmptyPage';
7
+ import Reports from './SubTabs/Reports';
8
+ import ENCPreview from './SubTabs/ENCPreview';
9
+
10
+ const SecondaryTabRoutes = ({ hostName, hostInfo, status }) => (
11
+ <Switch>
12
+ <Route path={route('reports')}>
13
+ <Reports hostName={hostName} hostInfo={hostInfo} status={status} />
14
+ </Route>
15
+ <Route path={route('assigned')}>
16
+ <EmptyPage
17
+ header={__('Assigned classes')}
18
+ description={__('This tab is still a work in progress')}
19
+ />
20
+ </Route>
21
+ <Route path={route('smart-classes')}>
22
+ <EmptyPage
23
+ header={__('Smart class parameters')}
24
+ description={__('This tab is still a work in progress')}
25
+ />
26
+ </Route>
27
+ <Route path={route('yaml')}>
28
+ <ENCPreview hostName={hostName} />
29
+ </Route>
30
+ <Redirect to={route('reports')} />
31
+ </Switch>
32
+ );
33
+
34
+ SecondaryTabRoutes.propTypes = {
35
+ hostName: PropTypes.string,
36
+ hostInfo: PropTypes.object,
37
+ status: PropTypes.string,
38
+ };
39
+
40
+ SecondaryTabRoutes.defaultProps = {
41
+ hostName: '',
42
+ hostInfo: {},
43
+ status: undefined,
44
+ };
45
+
46
+ export default SecondaryTabRoutes;
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ CodeBlock,
5
+ CodeBlockAction,
6
+ CodeBlockCode,
7
+ ClipboardCopyButton,
8
+ } from '@patternfly/react-core';
9
+
10
+ export const ENCTab = ({ encData }) => {
11
+ const [copied, setCopied] = React.useState(false);
12
+
13
+ const code = `${encData}`;
14
+
15
+ const clipboardCopyFunc = (event, text) => {
16
+ const clipboard = event.currentTarget.parentElement;
17
+ const el = document.createElement('textarea');
18
+ el.value = text.toString();
19
+ clipboard.appendChild(el);
20
+ el.select();
21
+ document.execCommand('copy');
22
+ clipboard.removeChild(el);
23
+ };
24
+
25
+ const onClick = (event, text) => {
26
+ clipboardCopyFunc(event, text);
27
+ setCopied(true);
28
+ };
29
+
30
+ const actions = (
31
+ <CodeBlockAction>
32
+ <ClipboardCopyButton
33
+ id="copy-button"
34
+ textId="code-content"
35
+ aria-label="Copy to clipboard"
36
+ onClick={e => onClick(e, code)}
37
+ exitDelay={600}
38
+ maxWidth="110px"
39
+ variant="plain"
40
+ >
41
+ {copied ? 'Successfully copied to clipboard!' : 'Copy to clipboard'}
42
+ </ClipboardCopyButton>
43
+ </CodeBlockAction>
44
+ );
45
+
46
+ return (
47
+ <CodeBlock actions={actions}>
48
+ <CodeBlockCode id="code-content">{code}</CodeBlockCode>
49
+ </CodeBlock>
50
+ );
51
+ };
52
+
53
+ ENCTab.propTypes = {
54
+ encData: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
55
+ };
56
+
57
+ ENCTab.defaultProps = {
58
+ encData: undefined,
59
+ };
60
+
61
+ export default ENCTab;
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
3
+ import PropTypes from 'prop-types';
4
+
5
+ import Skeleton from 'react-loading-skeleton';
6
+ import EmptyState from 'foremanReact/components/common/EmptyState/EmptyStatePattern';
7
+ import { STATUS } from 'foremanReact/constants';
8
+ import { EmptyStateIcon } from '@patternfly/react-core';
9
+ import { ExclamationCircleIcon } from '@patternfly/react-icons';
10
+ import { global_danger_color_200 as dangerColor } from '@patternfly/react-tokens';
11
+ import { translate as __ } from 'foremanReact/common/I18n';
12
+ import { ENCTab } from './ENCTab';
13
+
14
+ const ENCPreview = ({ hostName }) => {
15
+ const options = {
16
+ params: { name: hostName, format: 'yml' },
17
+ key: 'PUPPET_ENC_PREVIEW',
18
+ };
19
+ const url = `${window.location.origin.toString()}/foreman_puppet/hosts/${hostName}/externalNodes`;
20
+ const { response, status } = useAPI('get', url, options);
21
+
22
+ if (status === STATUS.PENDING) {
23
+ return <Skeleton count={5} />;
24
+ }
25
+
26
+ if (status === STATUS.ERROR || !hostName) {
27
+ const description = !hostName
28
+ ? __("Couldn't find any ENC data for this host")
29
+ : response?.response?.data?.message;
30
+ const icon = (
31
+ <EmptyStateIcon icon={ExclamationCircleIcon} color={dangerColor.value} />
32
+ );
33
+ return (
34
+ <EmptyState header={__('Error!')} icon={icon} description={description} />
35
+ );
36
+ }
37
+ if (response !== '' || response !== undefined) {
38
+ return (
39
+ <div className="enc-preview-tab" padding="16px 24px">
40
+ <ENCTab encData={response} />
41
+ </div>
42
+ );
43
+ }
44
+
45
+ return null;
46
+ };
47
+
48
+ ENCPreview.propTypes = {
49
+ hostName: PropTypes.string,
50
+ };
51
+
52
+ ENCPreview.defaultProps = {
53
+ hostName: undefined,
54
+ };
55
+
56
+ export default ENCPreview;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import PFEmptyPage from 'foremanReact/components/common/EmptyState/EmptyStatePattern';
4
+
5
+ const EmptyPage = ({ header, description }) => (
6
+ <div className="host-details-tab-item">
7
+ <PFEmptyPage icon="enterprise" header={header} description={description} />
8
+ </div>
9
+ );
10
+
11
+ EmptyPage.propTypes = {
12
+ header: PropTypes.string.isRequired,
13
+ description: PropTypes.string,
14
+ };
15
+
16
+ EmptyPage.defaultProps = {
17
+ description: null,
18
+ };
19
+
20
+ export default EmptyPage;
@@ -0,0 +1,88 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import CardTemplate from 'foremanReact/components/HostDetails/Templates/CardItem/CardTemplate';
4
+ import {
5
+ DescriptionList,
6
+ DescriptionListTerm,
7
+ DescriptionListGroup,
8
+ DescriptionListDescription,
9
+ } from '@patternfly/react-core';
10
+ import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
11
+ import DefaultLoaderEmptyState from 'foremanReact/components/HostDetails/DetailsCard/DefaultLoaderEmptyState';
12
+ import { STATUS } from 'foremanReact/constants';
13
+ import { translate as __ } from 'foremanReact/common/I18n';
14
+
15
+ const DescriptionCard = ({
16
+ proxyName,
17
+ caProxy,
18
+ proxyId,
19
+ caProxyId,
20
+ env,
21
+ status,
22
+ }) => (
23
+ <CardTemplate header={__('Puppet details')} expandable>
24
+ <DescriptionList isCompact>
25
+ <DescriptionListGroup>
26
+ <DescriptionListTerm>{__('Puppet environment')}</DescriptionListTerm>
27
+ <DescriptionListDescription>
28
+ <SkeletonLoader
29
+ emptyState={<DefaultLoaderEmptyState />}
30
+ status={status}
31
+ >
32
+ {env && (
33
+ <a href={`/foreman_puppet/environments/?search=name+%3D+${env}`}>
34
+ {env}
35
+ </a>
36
+ )}
37
+ </SkeletonLoader>
38
+ </DescriptionListDescription>
39
+ </DescriptionListGroup>
40
+ <DescriptionListGroup>
41
+ <DescriptionListTerm>{__('Puppet Smart Proxy')}</DescriptionListTerm>
42
+ <DescriptionListDescription>
43
+ <SkeletonLoader
44
+ emptyState={<DefaultLoaderEmptyState />}
45
+ status={status}
46
+ >
47
+ {proxyName && (
48
+ <a href={`/smart_proxies/${proxyId}#puppet`}>{proxyName}</a>
49
+ )}
50
+ </SkeletonLoader>
51
+ </DescriptionListDescription>
52
+ </DescriptionListGroup>
53
+ <DescriptionListGroup>
54
+ <DescriptionListTerm>{__('Puppet CA Smart Proxy')}</DescriptionListTerm>
55
+ <DescriptionListDescription>
56
+ <SkeletonLoader
57
+ emptyState={<DefaultLoaderEmptyState />}
58
+ status={status}
59
+ >
60
+ {caProxy && (
61
+ <a href={`/smart_proxies/${caProxyId}#puppet-ca`}>{caProxy}</a>
62
+ )}
63
+ </SkeletonLoader>
64
+ </DescriptionListDescription>
65
+ </DescriptionListGroup>
66
+ </DescriptionList>
67
+ </CardTemplate>
68
+ );
69
+
70
+ DescriptionCard.propTypes = {
71
+ caProxy: PropTypes.string,
72
+ caProxyId: PropTypes.number,
73
+ env: PropTypes.string,
74
+ proxyId: PropTypes.number,
75
+ proxyName: PropTypes.string,
76
+ status: PropTypes.string,
77
+ };
78
+
79
+ DescriptionCard.defaultProps = {
80
+ caProxy: undefined,
81
+ caProxyId: undefined,
82
+ env: undefined,
83
+ proxyId: undefined,
84
+ proxyName: undefined,
85
+ status: STATUS.PENDING,
86
+ };
87
+
88
+ export default DescriptionCard;
@@ -0,0 +1,50 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import { Grid, GridItem } from '@patternfly/react-core';
4
+ import ReportsTab from 'foremanReact/components/HostDetails/Tabs/ReportsTab';
5
+ import DescriptionCard from './components/DescriptionCard';
6
+ import './styles.scss';
7
+
8
+ const Reports = ({
9
+ hostName,
10
+ status,
11
+ hostInfo: {
12
+ puppet_proxy_name: proxyName,
13
+ puppet_ca_proxy_name: caProxy,
14
+ environment_name: env,
15
+ puppet_proxy_id: proxyId,
16
+ puppet_ca_proxy_id: caProxyId,
17
+ },
18
+ }) => (
19
+ <div className="report-tab">
20
+ <Grid hasGutter>
21
+ <GridItem span={4}>
22
+ <DescriptionCard
23
+ proxyName={proxyName}
24
+ caProxy={caProxy}
25
+ proxyId={proxyId}
26
+ caProxyId={caProxyId}
27
+ env={env}
28
+ status={status}
29
+ />
30
+ </GridItem>
31
+ <GridItem span={12}>
32
+ <ReportsTab hostName={hostName} origin="Puppet" />
33
+ </GridItem>
34
+ </Grid>
35
+ </div>
36
+ );
37
+
38
+ Reports.propTypes = {
39
+ hostName: PropTypes.string,
40
+ hostInfo: PropTypes.object,
41
+ status: PropTypes.string,
42
+ };
43
+
44
+ Reports.defaultProps = {
45
+ hostName: undefined,
46
+ hostInfo: {},
47
+ status: undefined,
48
+ };
49
+
50
+ export default Reports;
@@ -0,0 +1,7 @@
1
+ .report-tab {
2
+ padding: 16px 24px;
3
+
4
+ .pf-c-card {
5
+ height: 100%;
6
+ }
7
+ }
@@ -0,0 +1,8 @@
1
+ import { translate as __ } from 'foremanReact/common/I18n';
2
+
3
+ export const SECONDARY_TABS = [
4
+ { key: 'reports', title: __('Reports') },
5
+ { key: 'assigned', title: __('Assigned classes') },
6
+ { key: 'smart-classes', title: __('Smart class parameters') },
7
+ { key: 'yaml', title: __('ENC Preview') },
8
+ ];
@@ -0,0 +1,3 @@
1
+ export const hashRoute = subpath => `#/Puppet/${subpath}`;
2
+ export const route = subpath => hashRoute(subpath).substring(1);
3
+ export const activeTab = path => path.split('/')[2];
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useHistory } from 'react-router-dom';
4
+ import { Tabs, Tab, TabTitleText } from '@patternfly/react-core';
5
+ import { STATUS } from 'foremanReact/constants';
6
+
7
+ import SecondaryTabRoutes from './Routes';
8
+ import { activeTab } from './helpers';
9
+ import { SECONDARY_TABS } from './constants';
10
+
11
+ const PuppetTab = ({ response, status, location: { pathname } }) => {
12
+ const hashHistory = useHistory();
13
+ return (
14
+ <>
15
+ <Tabs
16
+ className="margin-0-24"
17
+ onSelect={(evt, subTab) => hashHistory.push(subTab)}
18
+ isSecondary
19
+ activeKey={activeTab(pathname)}
20
+ >
21
+ {SECONDARY_TABS.map(({ key, title }) => (
22
+ <Tab
23
+ key={key}
24
+ eventKey={key}
25
+ title={<TabTitleText>{title}</TabTitleText>}
26
+ />
27
+ ))}
28
+ </Tabs>
29
+ <SecondaryTabRoutes
30
+ hostName={response.name}
31
+ hostInfo={response}
32
+ status={status}
33
+ />
34
+ </>
35
+ );
36
+ };
37
+
38
+ PuppetTab.propTypes = {
39
+ response: PropTypes.object,
40
+ status: PropTypes.string,
41
+ location: PropTypes.shape({
42
+ pathname: PropTypes.string,
43
+ }),
44
+ };
45
+ PuppetTab.defaultProps = {
46
+ location: { pathname: '' },
47
+ response: { name: '' },
48
+ status: STATUS.PENDING,
49
+ };
50
+
51
+ export default PuppetTab;