foreman_puppet 3.0.5 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/db/migrate/20220421204325_drop_environment_from_host_and_hg.foreman_puppet.rb +8 -0
- data/lib/foreman_puppet/register.rb +4 -4
- data/lib/foreman_puppet/version.rb +1 -1
- data/locale/ca/foreman_puppet.edit.po +237 -111
- data/locale/cs_CZ/foreman_puppet.edit.po +213 -105
- data/locale/de/foreman_puppet.edit.po +326 -148
- data/locale/en/foreman_puppet.edit.po +80 -172
- data/locale/en_GB/foreman_puppet.edit.po +200 -100
- data/locale/es/foreman_puppet.edit.po +304 -133
- data/locale/fr/foreman_puppet.edit.po +313 -135
- data/locale/gl/foreman_puppet.edit.po +210 -102
- data/locale/it/foreman_puppet.edit.po +250 -116
- data/locale/ja/foreman_puppet.edit.po +223 -107
- data/locale/ko/foreman_puppet.edit.po +202 -101
- data/locale/messages.mo +0 -0
- data/locale/nl_NL/foreman_puppet.edit.po +243 -115
- data/locale/pl/foreman_puppet.edit.po +260 -121
- data/locale/pt_BR/foreman_puppet.edit.po +317 -139
- data/locale/ru/foreman_puppet.edit.po +258 -122
- data/locale/sv_SE/foreman_puppet.edit.po +209 -103
- data/locale/zh_CN/foreman_puppet.edit.po +209 -105
- data/locale/zh_TW/foreman_puppet.edit.po +202 -103
- data/package.json +7 -7
- data/test/controllers/foreman_puppet/api/v2/override_values_controller_test.rb +6 -2
- data/test/models/foreman_puppet/host_test.rb +6 -0
- data/webpack/global_index.js +11 -0
- data/webpack/index.js +0 -7
- data/webpack/legacy.js +31 -0
- data/webpack/src/Extends/Fills/index.js +26 -0
- data/webpack/src/Extends/Host/PuppetTab/Routes.js +47 -0
- data/webpack/src/Extends/Host/PuppetTab/SubTabs/ENCPreview/ENCTab.js +61 -0
- data/webpack/src/Extends/Host/PuppetTab/SubTabs/ENCPreview/index.js +53 -0
- data/webpack/src/Extends/Host/PuppetTab/SubTabs/EmptyPage.js +19 -0
- data/webpack/src/Extends/Host/PuppetTab/SubTabs/Reports/components/DescriptionCard.js +71 -0
- data/webpack/src/Extends/Host/PuppetTab/SubTabs/Reports/index.js +45 -0
- data/webpack/src/Extends/Host/PuppetTab/SubTabs/Reports/styles.scss +7 -0
- data/webpack/src/Extends/Host/PuppetTab/constants.js +8 -0
- data/webpack/src/Extends/Host/PuppetTab/helpers.js +3 -0
- data/webpack/src/Extends/Host/PuppetTab/index.js +51 -0
- metadata +67 -55
- data/app/views/smart_proxies/plugins/_puppet_ca.html.erb +0 -44
- data/webpack/fills_index.js +0 -30
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": "^
|
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": "^
|
30
|
-
"@theforeman/eslint-plugin-foreman": "^
|
31
|
-
"@theforeman/find-foreman": "^
|
32
|
-
"@theforeman/stories": "^
|
33
|
-
"@theforeman/test": "^
|
34
|
-
"@theforeman/vendor-dev": "^
|
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
|
-
|
79
|
-
|
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,47 @@
|
|
1
|
+
import PropTypes from 'prop-types';
|
2
|
+
import React from 'react';
|
3
|
+
import { Route, Switch, Redirect } from 'react-router-dom';
|
4
|
+
import { route } from './helpers';
|
5
|
+
import EmptyPage from './SubTabs/EmptyPage';
|
6
|
+
import Reports from './SubTabs/Reports';
|
7
|
+
import ENCPreview from './SubTabs/ENCPreview';
|
8
|
+
|
9
|
+
const SecondaryTabRoutes = ({ hostName, hostInfo, status }) => (
|
10
|
+
<Switch>
|
11
|
+
<Route path={route('reports')}>
|
12
|
+
{hostName ? (
|
13
|
+
<Reports hostName={hostName} hostInfo={hostInfo} status={status} />
|
14
|
+
) : (
|
15
|
+
<EmptyPage header="Reports" />
|
16
|
+
)}
|
17
|
+
</Route>
|
18
|
+
<Route path={route('assigned')}>
|
19
|
+
<EmptyPage header="Assigned classes" />
|
20
|
+
</Route>
|
21
|
+
<Route path={route('smart-classes')}>
|
22
|
+
<EmptyPage header="Smart class parameters" />
|
23
|
+
</Route>
|
24
|
+
<Route path={route('yaml')}>
|
25
|
+
{hostName ? (
|
26
|
+
<ENCPreview hostName={hostName} />
|
27
|
+
) : (
|
28
|
+
<EmptyPage header="ENC Preview" />
|
29
|
+
)}
|
30
|
+
</Route>
|
31
|
+
<Redirect to={route('reports')} />
|
32
|
+
</Switch>
|
33
|
+
);
|
34
|
+
|
35
|
+
SecondaryTabRoutes.propTypes = {
|
36
|
+
hostName: PropTypes.string,
|
37
|
+
hostInfo: PropTypes.object,
|
38
|
+
status: PropTypes.string,
|
39
|
+
};
|
40
|
+
|
41
|
+
SecondaryTabRoutes.defaultProps = {
|
42
|
+
hostName: '',
|
43
|
+
hostInfo: {},
|
44
|
+
status: undefined,
|
45
|
+
};
|
46
|
+
|
47
|
+
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,53 @@
|
|
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) {
|
27
|
+
const icon = (
|
28
|
+
<EmptyStateIcon icon={ExclamationCircleIcon} color={dangerColor.value} />
|
29
|
+
);
|
30
|
+
return (
|
31
|
+
<EmptyState
|
32
|
+
header={__('Error!')}
|
33
|
+
icon={icon}
|
34
|
+
description={response?.response?.data?.message}
|
35
|
+
/>
|
36
|
+
);
|
37
|
+
}
|
38
|
+
if (response !== '' || response !== undefined) {
|
39
|
+
return (
|
40
|
+
<div className="yaml-tab" padding="16px 24px">
|
41
|
+
<ENCTab encData={response} />
|
42
|
+
</div>
|
43
|
+
);
|
44
|
+
}
|
45
|
+
|
46
|
+
return null;
|
47
|
+
};
|
48
|
+
|
49
|
+
ENCPreview.propTypes = {
|
50
|
+
hostName: PropTypes.string.isRequired,
|
51
|
+
};
|
52
|
+
|
53
|
+
export default ENCPreview;
|
@@ -0,0 +1,19 @@
|
|
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 }) => (
|
6
|
+
<div className="host-details-tab-item">
|
7
|
+
<PFEmptyPage
|
8
|
+
icon="enterprise"
|
9
|
+
header={header}
|
10
|
+
description="This is a demo for adding content to the new host page"
|
11
|
+
/>
|
12
|
+
</div>
|
13
|
+
);
|
14
|
+
|
15
|
+
EmptyPage.propTypes = {
|
16
|
+
header: PropTypes.string.isRequired,
|
17
|
+
};
|
18
|
+
|
19
|
+
export default EmptyPage;
|
@@ -0,0 +1,71 @@
|
|
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 = ({ proxyName, caProxy, env, status }) => (
|
16
|
+
<CardTemplate header={__('Puppet details')} expandable>
|
17
|
+
<DescriptionList isCompact>
|
18
|
+
<DescriptionListGroup>
|
19
|
+
<DescriptionListTerm>{__('Puppet environment')}</DescriptionListTerm>
|
20
|
+
<DescriptionListDescription>
|
21
|
+
<SkeletonLoader
|
22
|
+
emptyState={<DefaultLoaderEmptyState />}
|
23
|
+
status={status}
|
24
|
+
>
|
25
|
+
{env && (
|
26
|
+
<a href={`/foreman_puppet/environments/${env}/edit`}>{env}</a>
|
27
|
+
)}
|
28
|
+
</SkeletonLoader>
|
29
|
+
</DescriptionListDescription>
|
30
|
+
</DescriptionListGroup>
|
31
|
+
<DescriptionListGroup>
|
32
|
+
<DescriptionListTerm>{__('Puppet smart proxy')}</DescriptionListTerm>
|
33
|
+
<DescriptionListDescription>
|
34
|
+
<SkeletonLoader
|
35
|
+
emptyState={<DefaultLoaderEmptyState />}
|
36
|
+
status={status}
|
37
|
+
>
|
38
|
+
{proxyName}
|
39
|
+
</SkeletonLoader>
|
40
|
+
</DescriptionListDescription>
|
41
|
+
</DescriptionListGroup>
|
42
|
+
<DescriptionListGroup>
|
43
|
+
<DescriptionListTerm>{__('Puppet server CA')}</DescriptionListTerm>
|
44
|
+
<DescriptionListDescription>
|
45
|
+
<SkeletonLoader
|
46
|
+
emptyState={<DefaultLoaderEmptyState />}
|
47
|
+
status={status}
|
48
|
+
>
|
49
|
+
{caProxy}
|
50
|
+
</SkeletonLoader>
|
51
|
+
</DescriptionListDescription>
|
52
|
+
</DescriptionListGroup>
|
53
|
+
</DescriptionList>
|
54
|
+
</CardTemplate>
|
55
|
+
);
|
56
|
+
|
57
|
+
DescriptionCard.propTypes = {
|
58
|
+
caProxy: PropTypes.string,
|
59
|
+
env: PropTypes.string,
|
60
|
+
proxyName: PropTypes.string,
|
61
|
+
status: PropTypes.string,
|
62
|
+
};
|
63
|
+
|
64
|
+
DescriptionCard.defaultProps = {
|
65
|
+
caProxy: undefined,
|
66
|
+
env: undefined,
|
67
|
+
proxyName: undefined,
|
68
|
+
status: STATUS.PENDING,
|
69
|
+
};
|
70
|
+
|
71
|
+
export default DescriptionCard;
|
@@ -0,0 +1,45 @@
|
|
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
|
+
},
|
16
|
+
}) => (
|
17
|
+
<div className="report-tab">
|
18
|
+
<Grid hasGutter>
|
19
|
+
<GridItem span={4}>
|
20
|
+
<DescriptionCard
|
21
|
+
proxyName={proxyName}
|
22
|
+
caProxy={caProxy}
|
23
|
+
env={env}
|
24
|
+
status={status}
|
25
|
+
/>
|
26
|
+
</GridItem>
|
27
|
+
<GridItem span={12}>
|
28
|
+
<ReportsTab hostName={hostName} origin="Puppet" />
|
29
|
+
</GridItem>
|
30
|
+
</Grid>
|
31
|
+
</div>
|
32
|
+
);
|
33
|
+
|
34
|
+
Reports.propTypes = {
|
35
|
+
hostName: PropTypes.string.isRequired,
|
36
|
+
hostInfo: PropTypes.object,
|
37
|
+
status: PropTypes.string,
|
38
|
+
};
|
39
|
+
|
40
|
+
Reports.defaultProps = {
|
41
|
+
hostInfo: {},
|
42
|
+
status: undefined,
|
43
|
+
};
|
44
|
+
|
45
|
+
export default Reports;
|
@@ -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,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;
|