foreman_remote_execution 3.3.7 → 4.0.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +1 -1
  3. data/app/controllers/job_invocations_controller.rb +22 -8
  4. data/app/lib/actions/remote_execution/run_host_job.rb +1 -1
  5. data/app/lib/actions/remote_execution/run_hosts_job.rb +1 -1
  6. data/app/lib/foreman_remote_execution/renderer/scope/input.rb +35 -0
  7. data/app/models/job_invocation.rb +6 -3
  8. data/app/models/job_invocation_composer.rb +2 -2
  9. data/app/models/remote_execution_provider.rb +2 -2
  10. data/app/models/setting/remote_execution.rb +2 -2
  11. data/app/models/ssh_execution_provider.rb +1 -1
  12. data/app/views/job_invocations/_form.html.erb +1 -1
  13. data/app/views/job_invocations/_tab_hosts.html.erb +1 -20
  14. data/app/views/job_invocations/show.html.erb +3 -0
  15. data/app/views/job_invocations/show.json.erb +2 -1
  16. data/db/migrate/20200623073022_rename_sudo_password_to_effective_user_password.rb +34 -0
  17. data/db/seeds.d/20-permissions.rb +9 -0
  18. data/lib/foreman_remote_execution/engine.rb +4 -10
  19. data/lib/foreman_remote_execution/version.rb +1 -1
  20. data/test/functional/api/v2/job_invocations_controller_test.rb +64 -1
  21. data/test/functional/job_invocations_controller_test.rb +71 -0
  22. data/test/support/remote_execution_helper.rb +5 -0
  23. data/test/unit/actions/run_host_job_test.rb +3 -3
  24. data/test/unit/actions/run_hosts_job_test.rb +1 -1
  25. data/test/unit/job_invocation_composer_test.rb +5 -5
  26. data/test/unit/remote_execution_provider_test.rb +6 -6
  27. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
  28. data/webpack/__mocks__/foremanReact/components/SearchBar.js +2 -0
  29. data/webpack/__mocks__/foremanReact/constants.js +21 -0
  30. data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +2 -0
  31. data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js +1 -0
  32. data/webpack/react_app/components/TargetingHosts/TargetingHosts.js +21 -15
  33. data/webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js +10 -0
  34. data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.js +62 -0
  35. data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.scss +6 -0
  36. data/webpack/react_app/components/TargetingHosts/TargetingHostsSelectors.js +10 -2
  37. data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsPage.test.js +9 -0
  38. data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js +26 -0
  39. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap +17 -2
  40. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +68 -0
  41. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsSelectors.test.js.snap +11 -0
  42. data/webpack/react_app/components/TargetingHosts/__tests__/fixtures.js +35 -19
  43. data/webpack/react_app/components/TargetingHosts/index.js +73 -13
  44. metadata +17 -3
  45. data/webpack/react_app/components/TargetingHosts/TargetingHostsActions.js +0 -8
@@ -0,0 +1,68 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TargetingHostsPage renders 1`] = `
4
+ <div
5
+ id="targeting_hosts"
6
+ >
7
+ <Row
8
+ bsClass="row"
9
+ componentClass="div"
10
+ >
11
+ <Col
12
+ bsClass="col"
13
+ className="title_filter"
14
+ componentClass="div"
15
+ md={6}
16
+ >
17
+ <SearchBar
18
+ data={
19
+ Object {
20
+ "autocomplete": Object {
21
+ "id": "targeting_hosts_search",
22
+ "searchQuery": "",
23
+ "url": "/hosts/auto_complete_search",
24
+ "useKeyShortcuts": true,
25
+ },
26
+ "bookmarks": Object {},
27
+ "controller": "hosts",
28
+ }
29
+ }
30
+ onSearch={[Function]}
31
+ />
32
+ </Col>
33
+ </Row>
34
+ <br />
35
+ <TargetingHosts
36
+ apiStatus="RESOLVED"
37
+ items={
38
+ Array [
39
+ Object {
40
+ "actions": Array [],
41
+ "link": "/link",
42
+ "name": "host",
43
+ "status": "success",
44
+ },
45
+ Object {
46
+ "actions": Array [],
47
+ "link": "/link2",
48
+ "name": "host2",
49
+ "status": "success",
50
+ },
51
+ ]
52
+ }
53
+ />
54
+ <PaginationWrapper
55
+ className="targeting-hosts-pagination"
56
+ dropdownButtonId="targeting-hosts-pagination-dropdown"
57
+ itemCount={1}
58
+ onChange={[Function]}
59
+ pagination={
60
+ Object {
61
+ "page": 1,
62
+ "perPage": 20,
63
+ }
64
+ }
65
+ viewType="list"
66
+ />
67
+ </div>
68
+ `;
@@ -0,0 +1,11 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TargetingHostsSelectors should return apiStatus 1`] = `"RESOLVED"`;
4
+
5
+ exports[`TargetingHostsSelectors should return autoRefresh 1`] = `"true"`;
6
+
7
+ exports[`TargetingHostsSelectors should return hosts 1`] = `Array []`;
8
+
9
+ exports[`TargetingHostsSelectors should return intervalExists 1`] = `false`;
10
+
11
+ exports[`TargetingHostsSelectors should return totalHosts 1`] = `0`;
@@ -1,3 +1,18 @@
1
+ const items = [
2
+ {
3
+ name: 'host',
4
+ link: '/link',
5
+ status: 'success',
6
+ actions: [],
7
+ },
8
+ {
9
+ name: 'host2',
10
+ link: '/link2',
11
+ status: 'success',
12
+ actions: [],
13
+ },
14
+ ];
15
+
1
16
  export const HostItemFixtures = {
2
17
  renders: {
3
18
  name: 'Host1',
@@ -15,29 +30,30 @@ export const HostStatusFixtures = {
15
30
 
16
31
  export const TargetingHostsFixtures = {
17
32
  renders: {
18
- status: '',
19
- items: [
20
- {
21
- name: 'host',
22
- link: '/link',
23
- status: 'success',
24
- actions: [],
25
- },
26
- ],
33
+ apiStatus: 'RESOLVED',
34
+ items,
27
35
  },
28
36
  'renders with error': {
29
- status: 'ERROR',
30
- items: [
31
- {
32
- name: 'host',
33
- link: '/link',
34
- status: 'success',
35
- actions: [],
36
- },
37
- ],
37
+ apiStatus: 'ERROR',
38
+ items,
38
39
  },
39
40
  'renders with loading': {
40
- status: '',
41
+ apiStatus: 'PENDING',
41
42
  items: [],
42
43
  },
43
44
  };
45
+
46
+ export const TargetingHostsPageFixtures = {
47
+ renders: {
48
+ handleSearch: () => {},
49
+ searchQuery: '',
50
+ apiStatus: 'RESOLVED',
51
+ items,
52
+ totalHosts: 1,
53
+ pagination: {
54
+ page: 1,
55
+ perPage: 20,
56
+ },
57
+ handlePagination: () => {},
58
+ },
59
+ };
@@ -1,37 +1,97 @@
1
- import React, { useEffect } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { useSelector, useDispatch } from 'react-redux';
3
- import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
4
- import TargetingHosts from './TargetingHosts';
3
+
4
+ import { get } from 'foremanReact/redux/API';
5
+ import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
6
+ import {
7
+ withInterval,
8
+ stopInterval,
9
+ } from 'foremanReact/redux/middlewares/IntervalMiddleware';
5
10
 
6
11
  import {
7
12
  selectItems,
8
- selectStatus,
13
+ selectApiStatus,
9
14
  selectAutoRefresh,
15
+ selectTotalHosts,
16
+ selectIntervalExists,
10
17
  } from './TargetingHostsSelectors';
11
- import { getData } from './TargetingHostsActions';
18
+ import { getApiUrl } from './TargetingHostsHelpers';
12
19
  import { TARGETING_HOSTS } from './TargetingHostsConsts';
20
+ import TargetingHostsPage from './TargetingHostsPage';
13
21
 
14
22
  const WrappedTargetingHosts = () => {
15
23
  const dispatch = useDispatch();
24
+ const { perPage, perPageOptions } = useForemanSettings();
25
+
16
26
  const autoRefresh = useSelector(selectAutoRefresh);
17
27
  const items = useSelector(selectItems);
18
- const status = useSelector(selectStatus);
28
+ const apiStatus = useSelector(selectApiStatus);
29
+ const totalHosts = useSelector(selectTotalHosts);
30
+ const [searchQuery, setSearchQuery] = useState('');
31
+ const [pagination, setPagination] = useState({
32
+ page: 1,
33
+ perPage,
34
+ perPageOptions,
35
+ });
36
+ const [apiUrl, setApiUrl] = useState(getApiUrl(searchQuery, pagination));
37
+ const intervalExists = useSelector(selectIntervalExists);
19
38
 
20
- useEffect(() => {
21
- dispatch(getData());
39
+ const handleSearch = query => {
40
+ const defaultPagination = { page: 1, perPage: pagination.perPage };
41
+ stopApiInterval();
22
42
 
23
- return () => {
43
+ setApiUrl(getApiUrl(query, defaultPagination));
44
+ setSearchQuery(query);
45
+ setPagination(defaultPagination);
46
+ };
47
+
48
+ const handlePagination = args => {
49
+ stopApiInterval();
50
+ setPagination(args);
51
+ setApiUrl(getApiUrl(searchQuery, args));
52
+ };
53
+
54
+ const stopApiInterval = () => {
55
+ if (intervalExists) {
24
56
  dispatch(stopInterval(TARGETING_HOSTS));
25
- };
26
- }, [dispatch]);
57
+ }
58
+ };
59
+
60
+ const getData = url =>
61
+ withInterval(
62
+ get({
63
+ key: TARGETING_HOSTS,
64
+ url,
65
+ handleError: () => {
66
+ dispatch(stopInterval(TARGETING_HOSTS));
67
+ },
68
+ }),
69
+ 1000
70
+ );
27
71
 
28
72
  useEffect(() => {
73
+ dispatch(getData(apiUrl));
74
+
29
75
  if (autoRefresh === 'false') {
30
76
  dispatch(stopInterval(TARGETING_HOSTS));
31
77
  }
32
- }, [autoRefresh, dispatch]);
33
78
 
34
- return <TargetingHosts status={status} items={items} />;
79
+ return () => {
80
+ dispatch(stopInterval(TARGETING_HOSTS));
81
+ };
82
+ }, [dispatch, apiUrl, autoRefresh]);
83
+
84
+ return (
85
+ <TargetingHostsPage
86
+ handleSearch={handleSearch}
87
+ searchQuery={searchQuery}
88
+ apiStatus={apiStatus}
89
+ items={items}
90
+ totalHosts={totalHosts}
91
+ pagination={pagination}
92
+ handlePagination={handlePagination}
93
+ />
94
+ );
35
95
  };
36
96
 
37
97
  export default WrappedTargetingHosts;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.7
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-31 00:00:00.000000000 Z
11
+ date: 2020-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -323,7 +323,9 @@ files:
323
323
  - db/migrate/20180411160809_add_sudo_password_to_job_invocation.rb
324
324
  - db/migrate/20180913101042_add_randomized_ordering_to_targeting.rb
325
325
  - db/migrate/20190111153330_remove_remote_execution_without_proxy_setting.rb
326
+ - db/migrate/20200623073022_rename_sudo_password_to_effective_user_password.rb
326
327
  - db/seeds.d/100-assign_features_with_templates.rb
328
+ - db/seeds.d/20-permissions.rb
327
329
  - db/seeds.d/50-notification_blueprints.rb
328
330
  - db/seeds.d/60-ssh_proxy_feature.rb
329
331
  - db/seeds.d/70-job_templates.rb
@@ -377,6 +379,7 @@ files:
377
379
  - test/functional/job_templates_controller_test.rb
378
380
  - test/helpers/remote_execution_helper_test.rb
379
381
  - test/models/orchestration/ssh_test.rb
382
+ - test/support/remote_execution_helper.rb
380
383
  - test/test_plugin_helper.rb
381
384
  - test/unit/actions/run_host_job_test.rb
382
385
  - test/unit/actions/run_hosts_job_test.rb
@@ -395,19 +398,29 @@ files:
395
398
  - test/unit/targeting_test.rb
396
399
  - test/unit/template_invocation_input_value_test.rb
397
400
  - webpack/__mocks__/foremanReact/common/I18n.js
401
+ - webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js
402
+ - webpack/__mocks__/foremanReact/components/SearchBar.js
398
403
  - webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js
399
404
  - webpack/__mocks__/foremanReact/constants.js
405
+ - webpack/__mocks__/foremanReact/redux/API/APISelectors.js
406
+ - webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js
400
407
  - webpack/index.js
401
408
  - webpack/react_app/components/TargetingHosts/TargetingHosts.js
402
- - webpack/react_app/components/TargetingHosts/TargetingHostsActions.js
403
409
  - webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js
410
+ - webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js
411
+ - webpack/react_app/components/TargetingHosts/TargetingHostsPage.js
412
+ - webpack/react_app/components/TargetingHosts/TargetingHostsPage.scss
404
413
  - webpack/react_app/components/TargetingHosts/TargetingHostsSelectors.js
405
414
  - webpack/react_app/components/TargetingHosts/__tests__/HostItem.test.js
406
415
  - webpack/react_app/components/TargetingHosts/__tests__/HostStatus.test.js
407
416
  - webpack/react_app/components/TargetingHosts/__tests__/TargetingHosts.test.js
417
+ - webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsPage.test.js
418
+ - webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js
408
419
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostItem.test.js.snap
409
420
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/HostStatus.test.js.snap
410
421
  - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap
422
+ - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap
423
+ - webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsSelectors.test.js.snap
411
424
  - webpack/react_app/components/TargetingHosts/__tests__/fixtures.js
412
425
  - webpack/react_app/components/TargetingHosts/components/HostItem.js
413
426
  - webpack/react_app/components/TargetingHosts/components/HostStatus.js
@@ -460,6 +473,7 @@ test_files:
460
473
  - test/functional/job_templates_controller_test.rb
461
474
  - test/helpers/remote_execution_helper_test.rb
462
475
  - test/models/orchestration/ssh_test.rb
476
+ - test/support/remote_execution_helper.rb
463
477
  - test/test_plugin_helper.rb
464
478
  - test/unit/actions/run_host_job_test.rb
465
479
  - test/unit/actions/run_hosts_job_test.rb
@@ -1,8 +0,0 @@
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);