foreman_remote_execution 3.2.2 → 3.3.4

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc +5 -30
  3. data/.github/workflows/ci.yml +101 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop_todo.yml +3 -0
  6. data/Gemfile +1 -0
  7. data/app/assets/stylesheets/foreman_remote_execution/job_invocations.scss +6 -5
  8. data/app/controllers/api/v2/job_invocations_controller.rb +17 -0
  9. data/app/helpers/remote_execution_helper.rb +38 -33
  10. data/app/lib/actions/remote_execution/run_host_job.rb +3 -2
  11. data/app/models/remote_execution_provider.rb +5 -0
  12. data/app/services/default_proxy_proxy_selector.rb +20 -0
  13. data/app/views/api/v2/job_invocations/main.json.rabl +6 -0
  14. data/app/views/job_invocations/_card_target_hosts.html.erb +1 -1
  15. data/app/views/job_invocations/_tab_hosts.html.erb +3 -23
  16. data/app/views/job_invocations/index.html.erb +2 -1
  17. data/app/views/job_invocations/show.html.erb +0 -6
  18. data/app/views/job_invocations/show.json.erb +4 -0
  19. data/app/views/templates/ssh/package_action.erb +1 -0
  20. data/app/views/templates/ssh/puppet_agent_disable.erb +3 -0
  21. data/app/views/templates/ssh/puppet_agent_enable.erb +3 -0
  22. data/app/views/templates/ssh/puppet_install_modules_from_forge.erb +3 -0
  23. data/app/views/templates/ssh/puppet_run_once.erb +3 -0
  24. data/db/seeds.d/70-job_templates.rb +1 -1
  25. data/foreman_remote_execution.gemspec +4 -5
  26. data/lib/foreman_remote_execution/version.rb +1 -1
  27. data/locale/action_names.rb +0 -1
  28. data/package.json +16 -33
  29. data/webpack/__mocks__/foremanReact/common/I18n.js +1 -0
  30. data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
  31. data/webpack/__mocks__/foremanReact/constants.js +3 -0
  32. data/webpack/index.js +9 -7
  33. data/webpack/react_app/components/TargetingHosts/TargetingHosts.js +52 -0
  34. data/webpack/react_app/components/TargetingHosts/TargetingHostsActions.js +8 -0
  35. data/webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js +1 -0
  36. data/webpack/react_app/components/TargetingHosts/TargetingHostsSelectors.js +12 -0
  37. data/webpack/react_app/components/TargetingHosts/__tests__/HostItem.test.js +6 -0
  38. data/webpack/react_app/components/TargetingHosts/__tests__/HostStatus.test.js +6 -0
  39. data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHosts.test.js +6 -0
  40. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostItem.test.js.snap +31 -0
  41. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostStatus.test.js.snap +12 -0
  42. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap +81 -0
  43. data/webpack/react_app/components/TargetingHosts/__tests__/fixtures.js +43 -0
  44. data/webpack/react_app/components/TargetingHosts/components/HostItem.js +39 -0
  45. data/webpack/react_app/components/TargetingHosts/components/HostStatus.js +54 -0
  46. data/webpack/react_app/components/TargetingHosts/index.js +37 -0
  47. data/webpack/react_app/components/jobInvocations/AggregateStatus/index.js +10 -0
  48. data/webpack/react_app/components/jobInvocations/AggregateStatus/index.test.js +6 -3
  49. data/webpack/react_app/components/jobInvocations/index.js +19 -7
  50. data/webpack/react_app/redux/actions/jobInvocations/index.js +12 -8
  51. data/webpack/react_app/redux/consts.js +1 -2
  52. data/webpack/react_app/redux/reducers/jobInvocations/index.fixtures.js +8 -40
  53. data/webpack/react_app/redux/reducers/jobInvocations/index.test.js +17 -11
  54. data/webpack/test_setup.js +2 -1
  55. metadata +26 -12
  56. data/.hound.yml +0 -19
  57. data/.travis.yml +0 -6
  58. data/app/views/job_invocations/_host_actions_td.html.erb +0 -3
  59. data/app/views/job_invocations/_host_name_td.html.erb +0 -8
  60. data/app/views/job_invocations/_host_status_td.html.erb +0 -1
  61. data/app/views/job_invocations/show.js.erb +0 -23
@@ -0,0 +1,4 @@
1
+ {
2
+ "autoRefresh": "<%= @auto_refresh %>",
3
+ "hosts": <%= targeting_hosts(@job_invocation, @hosts).to_json.html_safe %>
4
+ }
@@ -97,6 +97,7 @@ handle_zypp_res_codes () {
97
97
  end
98
98
  end
99
99
  -%>
100
+ [ -x "$(command -v subscription-manager)" ] && subscription-manager refresh
100
101
  apt-get -y update
101
102
  apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y <%= action %> <%= input("package") %>
102
103
  <% elsif package_manager == 'zypper' -%>
@@ -13,4 +13,7 @@ template_inputs:
13
13
  provider_type: SSH
14
14
  kind: job_template
15
15
  -%>
16
+ <% if @host.operatingsystem.family == 'Debian' -%>
17
+ export PATH=/opt/puppetlabs/bin:$PATH
18
+ <% end -%>
16
19
  puppet agent --disable "<%= input("comment").present? ? input("comment") : "Disabled using Foreman Remote Execution" %> - <%= current_user %> - $(date "+%d/%m/%Y %H:%M")"
@@ -7,4 +7,7 @@ snippet: false
7
7
  provider_type: SSH
8
8
  kind: job_template
9
9
  -%>
10
+ <% if @host.operatingsystem.family == 'Debian' -%>
11
+ export PATH=/opt/puppetlabs/bin:$PATH
12
+ <% end -%>
10
13
  puppet agent --enable
@@ -33,4 +33,7 @@ template_inputs:
33
33
  provider_type: SSH
34
34
  kind: job_template
35
35
  -%>
36
+ <% if @host.operatingsystem.family == 'Debian' -%>
37
+ export PATH=/opt/puppetlabs/bin:$PATH
38
+ <% end -%>
36
39
  puppet module install <%= input('puppet_module') %> <%= "--target-dir #{input('target_dir')}" if input('target_dir').present? %> <%= "--version #{input('version')}" if input('version').present? %> <%= "--force" if input('force') == "true" %> <%= "--ignore-dependencies" if input('ignore_dependencies') == "true" %>
@@ -11,4 +11,7 @@ template_inputs:
11
11
  input_type: user
12
12
  required: false
13
13
  %>
14
+ <% if @host.operatingsystem.family == 'Debian' -%>
15
+ export PATH=/opt/puppetlabs/bin:$PATH
16
+ <% end -%>
14
17
  puppet agent --onetime --no-usecacheonfailure --no-daemonize <%= input("puppet_options") %>
@@ -4,7 +4,7 @@ User.as_anonymous_admin do
4
4
  JobTemplate.without_auditing do
5
5
  Dir[File.join("#{ForemanRemoteExecution::Engine.root}/app/views/templates/**/*.erb")].each do |template|
6
6
  sync = !Rails.env.test? && Setting[:remote_execution_sync_templates]
7
- template = JobTemplate.import_raw!(File.read(template), :default => true, :locked => true, :update => sync)
7
+ template = JobTemplate.import_raw!(File.read(template), :default => true, :lock => true, :update => sync)
8
8
  template.organizations = organizations if template.present?
9
9
  template.locations = locations if template.present?
10
10
  end
@@ -15,10 +15,9 @@ Gem::Specification.new do |s|
15
15
  s.description = 'A plugin bringing remote execution to the Foreman, completing the config ' +
16
16
  'management functionality with remote management functionality.'
17
17
 
18
- s.files = `git ls-files`.split("\n").reject do |file|
19
- file =~ /^scripts/ ||
20
- file.start_with?('lib/foreman_remote_execution_core') ||
21
- file == 'foreman_remote_execution_core.gemspec'
18
+ s.files = `git ls-files`.split("\n").reject do |file|
19
+ file.start_with?('scripts', 'lib/foreman_remote_execution_core') ||
20
+ file == 'foreman_remote_execution_core.gemspec'
22
21
  end
23
22
 
24
23
  s.test_files = `git ls-files test`.split("\n")
@@ -30,6 +29,6 @@ Gem::Specification.new do |s|
30
29
  s.add_dependency 'foreman-tasks', '>= 0.15.1'
31
30
 
32
31
  s.add_development_dependency 'factory_bot_rails', '~> 4.8.0'
33
- s.add_development_dependency 'rubocop'
32
+ s.add_development_dependency 'rubocop', '~> 0.80.0'
34
33
  s.add_development_dependency 'rdoc'
35
34
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanRemoteExecution
2
- VERSION = '3.2.2'.freeze
2
+ VERSION = '3.3.4'.freeze
3
3
  end
@@ -3,4 +3,3 @@ _("Action with sub plans")
3
3
  _("Import facts")
4
4
  _("Import Puppet classes")
5
5
  _("Remote action:")
6
-
@@ -3,25 +3,14 @@
3
3
  "version": "1.0.0",
4
4
  "license": "GPL-3.0",
5
5
  "scripts": {
6
- "lint": "./node_modules/.bin/eslint -c .eslintrc webpack/ script/",
7
- "test": "node node_modules/.bin/jest webpack",
8
- "test:watch": "node node_modules/.bin/jest webpack --watchAll",
9
- "test:current": "node node_modules/.bin/jest webpack --watch"
10
- },
11
- "jest": {
12
- "verbose": true,
13
- "moduleDirectories": [
14
- "node_modules",
15
- "webpack"
16
- ],
17
- "setupFiles": [
18
- "raf/polyfill",
19
- "./webpack/test_setup.js"
20
- ],
21
- "testPathIgnorePatterns": [
22
- "/node_modules/",
23
- "<rootDir>/foreman/"
24
- ]
6
+ "lint": "tfm-lint --plugin -d /webpack",
7
+ "test": "tfm-test --plugin",
8
+ "test:watch": "tfm-test --plugin --watchAll",
9
+ "test:current": "tfm-test --plugin --watch",
10
+ "publish-coverage": "tfm-publish-coverage",
11
+ "stories": "tfm-stories --plugin",
12
+ "stories:build": "tfm-build-stories --plugin",
13
+ "stories:deploy": "surge --project .storybook-dist"
25
14
  },
26
15
  "repository": {
27
16
  "type": "git",
@@ -32,22 +21,16 @@
32
21
  },
33
22
  "devDependencies": {
34
23
  "@babel/core": "^7.7.0",
35
- "@theforeman/builder": "^4.0.2",
36
- "@theforeman/vendor-dev": "^4.0.2",
24
+ "@theforeman/builder": "^4.2.1",
25
+ "@theforeman/eslint-plugin-foreman": "^4.2.1",
26
+ "@theforeman/stories": "^4.2.1",
27
+ "@theforeman/test": "^4.2.1",
28
+ "@theforeman/vendor-dev": "^4.2.1",
37
29
  "babel-eslint": "^10.0.0",
38
- "babel-jest": "^24.9.0",
39
- "enzyme": "^3.2.0",
40
- "enzyme-adapter-react-16": "^1.1.0",
41
- "enzyme-to-json": "^3.1.2",
42
- "eslint": "^4.10.0",
43
- "eslint-config-airbnb": "^16.0.0",
44
- "eslint-plugin-import": "^2.8.0",
45
- "eslint-plugin-jest": "^21.2.0",
46
- "eslint-plugin-jsx-a11y": "^6.0.2",
47
- "eslint-plugin-react": "^7.4.0",
48
- "jest": "^24.9.0"
30
+ "eslint": "^6.8.0",
31
+ "prettier": "^1.19.1"
49
32
  },
50
33
  "peerDependencies": {
51
- "@theforeman/vendor": ">= 4.0.2"
34
+ "@theforeman/vendor": ">= 4.2.1"
52
35
  }
53
36
  }
@@ -0,0 +1 @@
1
+ export const translate = s => s;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+
3
+ export const ActionButtons = () => <div />;
@@ -0,0 +1,3 @@
1
+ export const STATUS = {
2
+ ERROR: 'ERROR',
3
+ };
@@ -1,14 +1,16 @@
1
- import URI from 'urijs';
2
- // eslint-disable-next-line import/no-extraneous-dependencies
3
- import { mount, registerReducer } from 'foremanReact/common/MountingService';
4
- // eslint-disable-next-line import/no-extraneous-dependencies
1
+ import { registerReducer } from 'foremanReact/common/MountingService';
5
2
  import componentRegistry from 'foremanReact/components/componentRegistry';
6
3
  import JobInvocationContainer from './react_app/components/jobInvocations';
4
+ import TargetingHosts from './react_app/components/TargetingHosts';
7
5
  import rootReducer from './react_app/redux/reducers';
8
6
 
9
- componentRegistry.register({
10
- name: 'JobInvocationContainer',
11
- type: JobInvocationContainer,
7
+ const components = [
8
+ { name: 'JobInvocationContainer', type: JobInvocationContainer },
9
+ { name: 'TargetingHosts', type: TargetingHosts },
10
+ ];
11
+
12
+ components.forEach(component => {
13
+ componentRegistry.register(component);
12
14
  });
13
15
 
14
16
  registerReducer('foremanRemoteExecutionReducers', rootReducer);
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+ import { LoadingState, Alert } from 'patternfly-react';
5
+ import { STATUS } from 'foremanReact/constants';
6
+ import HostItem from './components/HostItem';
7
+
8
+ const TargetingHosts = ({ status, items }) => {
9
+ if (status === STATUS.ERROR) {
10
+ return (
11
+ <Alert type="error">
12
+ {__(
13
+ 'There was an error while updating the status, try refreshing the page.'
14
+ )}
15
+ </Alert>
16
+ );
17
+ }
18
+
19
+ return (
20
+ <LoadingState loading={!items.length}>
21
+ <div>
22
+ <table className="table table-bordered table-striped table-hover">
23
+ <thead>
24
+ <tr>
25
+ <th>{__('Host')}</th>
26
+ <th>{__('Status')}</th>
27
+ <th>{__('Actions')}</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ {items.map(host => (
32
+ <HostItem
33
+ key={host.name}
34
+ name={host.name}
35
+ link={host.link}
36
+ status={host.status}
37
+ actions={host.actions}
38
+ />
39
+ ))}
40
+ </tbody>
41
+ </table>
42
+ </div>
43
+ </LoadingState>
44
+ );
45
+ };
46
+
47
+ TargetingHosts.propTypes = {
48
+ status: PropTypes.string.isRequired,
49
+ items: PropTypes.array.isRequired,
50
+ };
51
+
52
+ export default TargetingHosts;
@@ -0,0 +1,8 @@
1
+ import { getURI } from 'foremanReact/common/urlHelpers';
2
+ import { get } from 'foremanReact/redux/API';
3
+ import { withInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
4
+ import { TARGETING_HOSTS } from './TargetingHostsConsts';
5
+
6
+ const url = getURI().addQuery('format', 'json');
7
+ export const getData = () =>
8
+ withInterval(get({ key: TARGETING_HOSTS, url }), 1000);
@@ -0,0 +1 @@
1
+ export const TARGETING_HOSTS = 'TARGETING_HOSTS';
@@ -0,0 +1,12 @@
1
+ import {
2
+ selectAPIStatus,
3
+ selectAPIResponse,
4
+ } from 'foremanReact/redux/API/APISelectors';
5
+ import { TARGETING_HOSTS } from './TargetingHostsConsts';
6
+
7
+ export const selectItems = state =>
8
+ selectAPIResponse(state, TARGETING_HOSTS).hosts || [];
9
+
10
+ export const selectAutoRefresh = state =>
11
+ selectAPIResponse(state, TARGETING_HOSTS).autoRefresh;
12
+ export const selectStatus = state => selectAPIStatus(state, TARGETING_HOSTS);
@@ -0,0 +1,6 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+ import HostItem from '../components/HostItem';
3
+ import { HostItemFixtures } from './fixtures';
4
+
5
+ describe('HostItem', () =>
6
+ testComponentSnapshotsWithFixtures(HostItem, HostItemFixtures));
@@ -0,0 +1,6 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+ import HostStatus from '../components/HostStatus';
3
+ import { HostStatusFixtures } from './fixtures';
4
+
5
+ describe('HostStatus', () =>
6
+ testComponentSnapshotsWithFixtures(HostStatus, HostStatusFixtures));
@@ -0,0 +1,6 @@
1
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+ import TargetingHosts from '../TargetingHosts';
3
+ import { TargetingHostsFixtures } from './fixtures';
4
+
5
+ describe('TargetingHosts', () =>
6
+ testComponentSnapshotsWithFixtures(TargetingHosts, TargetingHostsFixtures));
@@ -0,0 +1,31 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`HostItem renders 1`] = `
4
+ <tr
5
+ id="targeting-host-Host1"
6
+ >
7
+ <td
8
+ className="host_name"
9
+ >
10
+ <a
11
+ href="/host1"
12
+ >
13
+ Host1
14
+ </a>
15
+ </td>
16
+ <td
17
+ className="host_status"
18
+ >
19
+ <HostStatus
20
+ status="success"
21
+ />
22
+ </td>
23
+ <td
24
+ className="host_actions"
25
+ >
26
+ <ActionButtons
27
+ buttons={Array []}
28
+ />
29
+ </td>
30
+ </tr>
31
+ `;
@@ -0,0 +1,12 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`HostStatus renders 1`] = `
4
+ <div>
5
+ <Icon
6
+ name="ok"
7
+ type="pf"
8
+ />
9
+
10
+ success
11
+ </div>
12
+ `;
@@ -0,0 +1,81 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TargetingHosts renders 1`] = `
4
+ <LoadingState
5
+ additionalClasses=""
6
+ loading={false}
7
+ loadingText="Loading"
8
+ size="lg"
9
+ timeout={300}
10
+ >
11
+ <div>
12
+ <table
13
+ className="table table-bordered table-striped table-hover"
14
+ >
15
+ <thead>
16
+ <tr>
17
+ <th>
18
+ Host
19
+ </th>
20
+ <th>
21
+ Status
22
+ </th>
23
+ <th>
24
+ Actions
25
+ </th>
26
+ </tr>
27
+ </thead>
28
+ <tbody>
29
+ <HostItem
30
+ actions={Array []}
31
+ key="host"
32
+ link="/link"
33
+ name="host"
34
+ status="success"
35
+ />
36
+ </tbody>
37
+ </table>
38
+ </div>
39
+ </LoadingState>
40
+ `;
41
+
42
+ exports[`TargetingHosts renders with error 1`] = `
43
+ <Alert
44
+ className=""
45
+ onDismiss={null}
46
+ type="error"
47
+ >
48
+ There was an error while updating the status, try refreshing the page.
49
+ </Alert>
50
+ `;
51
+
52
+ exports[`TargetingHosts renders with loading 1`] = `
53
+ <LoadingState
54
+ additionalClasses=""
55
+ loading={true}
56
+ loadingText="Loading"
57
+ size="lg"
58
+ timeout={300}
59
+ >
60
+ <div>
61
+ <table
62
+ className="table table-bordered table-striped table-hover"
63
+ >
64
+ <thead>
65
+ <tr>
66
+ <th>
67
+ Host
68
+ </th>
69
+ <th>
70
+ Status
71
+ </th>
72
+ <th>
73
+ Actions
74
+ </th>
75
+ </tr>
76
+ </thead>
77
+ <tbody />
78
+ </table>
79
+ </div>
80
+ </LoadingState>
81
+ `;
@@ -0,0 +1,43 @@
1
+ export const HostItemFixtures = {
2
+ renders: {
3
+ name: 'Host1',
4
+ link: '/host1',
5
+ status: 'success',
6
+ actions: [],
7
+ },
8
+ };
9
+
10
+ export const HostStatusFixtures = {
11
+ renders: {
12
+ status: 'success',
13
+ },
14
+ };
15
+
16
+ export const TargetingHostsFixtures = {
17
+ renders: {
18
+ status: '',
19
+ items: [
20
+ {
21
+ name: 'host',
22
+ link: '/link',
23
+ status: 'success',
24
+ actions: [],
25
+ },
26
+ ],
27
+ },
28
+ 'renders with error': {
29
+ status: 'ERROR',
30
+ items: [
31
+ {
32
+ name: 'host',
33
+ link: '/link',
34
+ status: 'success',
35
+ actions: [],
36
+ },
37
+ ],
38
+ },
39
+ 'renders with loading': {
40
+ status: '',
41
+ items: [],
42
+ },
43
+ };