foreman_remote_execution 16.3.1 → 16.4.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 +4 -4
- data/app/controllers/api/v2/job_invocations_controller.rb +3 -5
- data/app/lib/proxy_api/remote_execution_ssh.rb +9 -0
- data/app/models/concerns/foreman_remote_execution/host_extensions.rb +12 -4
- data/app/models/concerns/foreman_remote_execution/smart_proxy_extensions.rb +14 -0
- data/app/views/api/v2/smart_proxies/ca_pubkey.json.rabl +1 -0
- data/db/migrate/20250606125543_add_ca_pub_key_to_smart_proxy.rb +5 -0
- data/lib/foreman_remote_execution/plugin.rb +1 -0
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/unit/concerns/host_extensions_test.rb +43 -0
- data/webpack/JobInvocationDetail/JobInvocationDetail.scss +4 -0
- data/webpack/JobInvocationDetail/JobInvocationHostTable.js +216 -129
- data/webpack/JobInvocationDetail/TemplateInvocation.js +19 -15
- data/webpack/JobInvocationDetail/TemplateInvocationComponents/OutputToggleGroup.js +43 -25
- data/webpack/JobInvocationDetail/TemplateInvocationPage.js +16 -1
- data/webpack/JobInvocationDetail/__tests__/TemplateInvocation.test.js +114 -72
- data/webpack/JobInvocationDetail/index.js +4 -5
- data/webpack/JobWizard/JobWizard.js +11 -10
- data/webpack/JobWizard/autofill.js +10 -2
- data/webpack/JobWizard/steps/AdvancedFields/__tests__/__snapshots__/AdvancedFields.test.js.snap +1 -1
- data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +25 -13
- data/webpack/JobWizard/steps/HostsAndInputs/SelectAPI.js +16 -11
- data/webpack/JobWizard/steps/form/ResourceSelect.js +18 -16
- data/webpack/JobWizard/steps/form/SearchSelect.js +6 -7
- data/webpack/JobWizard/validation.js +1 -3
- data/webpack/react_app/components/TargetingHosts/index.js +49 -32
- metadata +5 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import {
|
|
4
4
|
Select,
|
|
@@ -25,14 +25,13 @@ export const SearchSelect = ({
|
|
|
25
25
|
const [onSearch, response, isLoading] = useNameSearch(apiKey, url);
|
|
26
26
|
const [isOpen, setIsOpen] = useState(false);
|
|
27
27
|
const [typingTimeout, setTypingTimeout] = useState(null);
|
|
28
|
+
const initializedRef = useRef(false);
|
|
28
29
|
useEffect(() => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if (!initializedRef.current) {
|
|
31
|
+
onSearch(selected.name || '');
|
|
32
|
+
initializedRef.current = true;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35
|
-
}, []);
|
|
34
|
+
}, [onSearch, selected.name]);
|
|
36
35
|
let selectOptions = [];
|
|
37
36
|
if (response.subtotal > maxResults) {
|
|
38
37
|
selectOptions = [
|
|
@@ -46,8 +46,6 @@ export const useValidation = ({ advancedValues, templateValues }) => {
|
|
|
46
46
|
setValid(currValid => ({ ...currValid, advanced: false }));
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
|
-
|
|
50
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
|
-
}, [advancedValues, templateValues]);
|
|
49
|
+
}, [advancedValues, templateValues, templateInputs, advancedTemplateInputs]);
|
|
52
50
|
return [valid, setValid];
|
|
53
51
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useState, useCallback, useRef } from 'react';
|
|
2
2
|
import { useSelector, useDispatch } from 'react-redux';
|
|
3
3
|
|
|
4
4
|
import { get } from 'foremanReact/redux/API';
|
|
@@ -50,38 +50,55 @@ const WrappedTargetingHosts = () => {
|
|
|
50
50
|
const [apiUrl, setApiUrl] = useState(getApiUrl(searchQuery, pagination));
|
|
51
51
|
const intervalExists = useSelector(selectIntervalExists);
|
|
52
52
|
|
|
53
|
-
const
|
|
54
|
-
const defaultPagination = { page: 1, per_page: pagination.per_page };
|
|
55
|
-
stopApiInterval();
|
|
56
|
-
|
|
57
|
-
setApiUrl(getApiUrl(buildSearchQuery(query, status), defaultPagination));
|
|
58
|
-
setSearchQuery(query);
|
|
59
|
-
setPagination(defaultPagination);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const handlePagination = args => {
|
|
63
|
-
stopApiInterval();
|
|
64
|
-
setPagination(args);
|
|
65
|
-
setApiUrl(getApiUrl(buildSearchQuery(searchQuery, statusFilter), args));
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const stopApiInterval = () => {
|
|
53
|
+
const stopApiInterval = useCallback(() => {
|
|
69
54
|
if (intervalExists) {
|
|
70
55
|
dispatch(stopInterval(TARGETING_HOSTS));
|
|
71
56
|
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
57
|
+
}, [dispatch, intervalExists]);
|
|
58
|
+
|
|
59
|
+
// Use ref to avoid infinite loop from handleSearch depending on pagination.per_page
|
|
60
|
+
const perPageRef = useRef(pagination.per_page);
|
|
61
|
+
|
|
62
|
+
const handleSearch = useCallback(
|
|
63
|
+
(query, status) => {
|
|
64
|
+
const defaultPagination = { page: 1, per_page: perPageRef.current };
|
|
65
|
+
stopApiInterval();
|
|
66
|
+
|
|
67
|
+
setApiUrl(getApiUrl(buildSearchQuery(query, status), defaultPagination));
|
|
68
|
+
setSearchQuery(query);
|
|
69
|
+
setPagination(defaultPagination);
|
|
70
|
+
},
|
|
71
|
+
[stopApiInterval]
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Keep ref in sync with pagination
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
perPageRef.current = pagination.per_page;
|
|
77
|
+
}, [pagination.per_page]);
|
|
78
|
+
|
|
79
|
+
const handlePagination = useCallback(
|
|
80
|
+
args => {
|
|
81
|
+
stopApiInterval();
|
|
82
|
+
setPagination(args);
|
|
83
|
+
setApiUrl(getApiUrl(buildSearchQuery(searchQuery, statusFilter), args));
|
|
84
|
+
},
|
|
85
|
+
[searchQuery, statusFilter, stopApiInterval]
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const getData = useCallback(
|
|
89
|
+
url =>
|
|
90
|
+
withInterval(
|
|
91
|
+
get({
|
|
92
|
+
key: TARGETING_HOSTS,
|
|
93
|
+
url,
|
|
94
|
+
handleError: () => {
|
|
95
|
+
dispatch(stopInterval(TARGETING_HOSTS));
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
1000
|
|
99
|
+
),
|
|
100
|
+
[dispatch]
|
|
101
|
+
);
|
|
85
102
|
|
|
86
103
|
useEffect(() => {
|
|
87
104
|
dispatch(getData(apiUrl));
|
|
@@ -93,11 +110,11 @@ const WrappedTargetingHosts = () => {
|
|
|
93
110
|
return () => {
|
|
94
111
|
dispatch(stopInterval(TARGETING_HOSTS));
|
|
95
112
|
};
|
|
96
|
-
}, [dispatch, apiUrl, autoRefresh]);
|
|
113
|
+
}, [dispatch, apiUrl, autoRefresh, getData]);
|
|
97
114
|
|
|
98
115
|
useEffect(() => {
|
|
99
116
|
handleSearch(searchQuery, statusFilter);
|
|
100
|
-
}, [statusFilter, searchQuery]);
|
|
117
|
+
}, [statusFilter, searchQuery, handleSearch]);
|
|
101
118
|
|
|
102
119
|
return (
|
|
103
120
|
<TargetingHostsPage
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: foreman_remote_execution
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 16.
|
|
4
|
+
version: 16.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Foreman Remote Execution team
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-01-06 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: deface
|
|
@@ -223,6 +223,7 @@ files:
|
|
|
223
223
|
- app/views/api/v2/remote_execution_features/index.json.rabl
|
|
224
224
|
- app/views/api/v2/remote_execution_features/main.json.rabl
|
|
225
225
|
- app/views/api/v2/remote_execution_features/show.json.rabl
|
|
226
|
+
- app/views/api/v2/smart_proxies/ca_pubkey.json.rabl
|
|
226
227
|
- app/views/api/v2/smart_proxies/pubkey.json.rabl
|
|
227
228
|
- app/views/api/v2/subnets/remote_execution_proxies.json.rabl
|
|
228
229
|
- app/views/api/v2/template_invocations/base.json.rabl
|
|
@@ -340,6 +341,7 @@ files:
|
|
|
340
341
|
- db/migrate/20240522093412_add_smart_proxy_id_to_template_invocation.rb
|
|
341
342
|
- db/migrate/20240522093413_migrate_smart_proxy_ids_to_template_invocations.rb
|
|
342
343
|
- db/migrate/20241126150849_remove_remote_execution_workers_pool_size.rb
|
|
344
|
+
- db/migrate/20250606125543_add_ca_pub_key_to_smart_proxy.rb
|
|
343
345
|
- db/seeds.d/100-assign_features_with_templates.rb
|
|
344
346
|
- db/seeds.d/20-permissions.rb
|
|
345
347
|
- db/seeds.d/50-notification_blueprints.rb
|
|
@@ -606,7 +608,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
606
608
|
- !ruby/object:Gem::Version
|
|
607
609
|
version: '0'
|
|
608
610
|
requirements: []
|
|
609
|
-
rubygems_version:
|
|
611
|
+
rubygems_version: 4.0.3
|
|
610
612
|
specification_version: 4
|
|
611
613
|
summary: A plugin bringing remote execution to the Foreman, completing the config
|
|
612
614
|
management functionality with remote management functionality.
|