diff --git a/.eslintrc b/.eslintrc index 0de7f9bd00b..1b3658bc274 100644 --- a/.eslintrc +++ b/.eslintrc @@ -182,6 +182,7 @@ "vnc", "vnic", "webpack", + "wget", "wss", "x86_64", "xml", diff --git a/app/controllers/api/v2/registration_commands_controller.rb b/app/controllers/api/v2/registration_commands_controller.rb index 3fa023dca4d..bb442523f76 100644 --- a/app/controllers/api/v2/registration_commands_controller.rb +++ b/app/controllers/api/v2/registration_commands_controller.rb @@ -15,7 +15,7 @@ class RegistrationCommandsController < V2::BaseController param :setup_insights, :bool, desc: N_("Set 'host_registration_insights' parameter for the host. If it is set to true, insights client will be installed and registered on Red Hat family operating systems") param :setup_remote_execution, :bool, desc: N_("Set 'host_registration_remote_execution' parameter for the host. If it is set to true, SSH keys will be installed on the host") param :jwt_expiration, :number, desc: N_("Expiration of the authorization token (in hours), 0 means 'unlimited'.") - param :insecure, :bool, desc: N_("Enable insecure argument for the initial curl") + param :insecure, :bool, desc: N_("Enable insecure argument for the initial curl/wget ") param :packages, String, desc: N_("Packages to install on the host when registered. Can be set by `host_packages` parameter, example: `pkg1 pkg2`") param :update_packages, :bool, desc: N_("Update all packages on the host") param :repo, String, desc: N_("DEPRECATED, use the `repo_data` param instead."), deprecated: true @@ -25,6 +25,7 @@ class RegistrationCommandsController < V2::BaseController param :repo, String, desc: N_("Repository URL / details, for example, for Debian OS family: 'deb http://deb.example.com/ buster 1.0', for Red Hat and SUSE OS family: 'http://yum.theforeman.org/client/latest/el8/x86_64/'") param :repo_gpg_key_url, String, desc: N_("URL of the GPG key for the repository") end + param :download_utility, ["curl", "wget"], desc: N_("The download utility to use during host registration") end def create unless os_with_template? diff --git a/app/controllers/concerns/foreman/controller/registration.rb b/app/controllers/concerns/foreman/controller/registration.rb index 0d71e7a15ad..5727cd699ee 100644 --- a/app/controllers/concerns/foreman/controller/registration.rb +++ b/app/controllers/concerns/foreman/controller/registration.rb @@ -41,6 +41,7 @@ def global_registration_vars packages: params['packages'], update_packages: params['update_packages'], repo_data: repo_data, + download_utility: params['download_utility'], } params.permit(permitted) diff --git a/app/controllers/concerns/foreman/controller/registration_commands.rb b/app/controllers/concerns/foreman/controller/registration_commands.rb index 6c002096a3c..a2fcccc9796 100644 --- a/app/controllers/concerns/foreman/controller/registration_commands.rb +++ b/app/controllers/concerns/foreman/controller/registration_commands.rb @@ -9,7 +9,7 @@ module Foreman::Controller::RegistrationCommands def command args_query = "?#{registration_args.to_query}" - "set -o pipefail && curl -sS #{insecure} '#{registration_url(@smart_proxy)}#{args_query if args_query != '?'}' #{command_headers} | bash" + "set -o pipefail && #{utility[:download_command]} #{utility[:output_pipe]} #{insecure} '#{registration_url(@smart_proxy)}#{args_query if args_query != '?'}' #{command_headers} | bash" end def registration_args @@ -19,8 +19,12 @@ def registration_args .permit! end + def utility + Foreman.download_utilities.fetch(registration_params['download_utility'] || 'curl') + end + def insecure - registration_params['insecure'] ? '--insecure' : '' + registration_params['insecure'] ? utility[:insecure] : '' end def registration_url(proxy = nil) @@ -65,7 +69,7 @@ def command_headers else invalid_expiration_error end - "-H 'Authorization: Bearer #{User.current.jwt_token!(**jwt_args)}'" + "--header 'Authorization: Bearer #{User.current.jwt_token!(**jwt_args)}'" end def host_config_params diff --git a/app/services/foreman/renderer/configuration.rb b/app/services/foreman/renderer/configuration.rb index b86b0213ebf..42f08623a9a 100644 --- a/app/services/foreman/renderer/configuration.rb +++ b/app/services/foreman/renderer/configuration.rb @@ -80,7 +80,8 @@ class Configuration :host_puppet_environment, :host_enc, :install_packages, - :update_packages + :update_packages, + :generate_web_request ] DEFAULT_ALLOWED_VARIABLES = [ diff --git a/app/services/foreman/renderer/scope/macros/helpers.rb b/app/services/foreman/renderer/scope/macros/helpers.rb index 1d4cf589bfc..590e539073e 100644 --- a/app/services/foreman/renderer/scope/macros/helpers.rb +++ b/app/services/foreman/renderer/scope/macros/helpers.rb @@ -155,6 +155,32 @@ def truthy?(value = nil) def falsy?(value = nil) Foreman::Cast.to_bool(value) == false end + + apipie :method, 'Generate a web request' do + required :utility, String, desc: 'The utility to use for the web request ("curl" or "wget").' + required :url, String, desc: 'The URL for the web request.' + optional :ssl_ca_cert, String, desc: 'The path to the SSL certificate.' + optional :headers, Array, of: String, desc: 'Array containing the headers for the web request starting with "--header".' + optional :params, Array, of: String, desc: 'Array containing the POST parameters for the web request.' + optional :output_file, String, desc: 'The path were the result of the web request will be stored.' + returns String, desc: 'The web request.' + example 'generate_web_request(utility: "curl", url: "https://www.example.com/register", ssl_ca_cert: "/etc/ssl/custom_certs/ca_cert.crt", headers: ["--header \'Authorization: Bearer \'"], params: ["host[build]=false", "host[organization_id]=1"])' + example 'generate_web_request(utility: "curl", url: "https://www.example.com/keys/client.asc", output_file: "/etc/apt/trusted.gpg.d/client1.asc")' + end + def generate_web_request(utility:, url:, ssl_ca_cert: nil, headers: nil, params: nil, output_file: nil) + utility = Foreman.download_utilities.fetch(utility || 'curl') + command = ["#{utility[:download_command]} #{url}"] + command << "#{utility[:ca_cert]} #{ssl_ca_cert}" if ssl_ca_cert + command << utility[:request_type_post] if params && utility[:request_type_post] + if output_file + command << "#{utility[:output_file]} #{output_file}" + elsif utility[:output_pipe] + command << utility[:output_pipe] + end + headers&.each { |header| command << header } + utility[:format_params].call(params).each { |param| command << param } if params + command.join(" \\\n ") + end end end end diff --git a/app/views/unattended/provisioning_templates/registration/global_registration.erb b/app/views/unattended/provisioning_templates/registration/global_registration.erb index 973f1156c88..4668c92c891 100644 --- a/app/views/unattended/provisioning_templates/registration/global_registration.erb +++ b/app/views/unattended/provisioning_templates/registration/global_registration.erb @@ -14,7 +14,7 @@ description: | # Make sure, all command output can be parsed (e.g. from subscription-manager) export LC_ALL=C LANG=C <% - headers = ["-H 'Authorization: Bearer #{@auth_token}'"] + headers = ["--header 'Authorization: Bearer #{@auth_token}'"] activation_keys = [(@hostgroup.params['kt_activation_keys'] if @hostgroup), @activation_keys].compact.join(',') -%> @@ -35,6 +35,7 @@ export LC_ALL=C LANG=C <%= "\n# Ignore subman errors: [#{@ignore_subman_errors}]" unless @ignore_subman_errors.nil? -%> <%= "\n# Lifecycle environment id: [#{@lifecycle_environment_id}]" if @lifecycle_environment_id.present? -%> <%= "\n# Activation keys: [#{activation_keys}]" if activation_keys.present? -%> +<%= "\n# Download utility: [#{@download_utility}]" unless @download_utility.nil? -%> if ! [ $(id -u) = 0 ]; then @@ -92,10 +93,10 @@ elif [ -f /etc/debian_version ]; then <%# "apt 1.2.35" on Ubuntu 16.04 does not support storing GPG public keys in "/etc/apt/trusted.gpg.d/" in ASCII format -%> if [ "$(. /etc/os-release ; echo "$VERSION_ID")" = "16.04" ]; then $PKG_MANAGER_INSTALL ca-certificates curl gnupg - curl --silent --show-error <%= shell_escape repo_gpg_key_url %> | gpg --dearmor > /etc/apt/trusted.gpg.d/client<%= index %>.gpg + <%= indent(4, skip1: true) { generate_web_request(utility: @download_utility, url: shell_escape(repo_gpg_key_url)) } %> | gpg --dearmor > /etc/apt/trusted.gpg.d/client<%= index %>.gpg else $PKG_MANAGER_INSTALL ca-certificates curl - curl --silent --show-error --output /etc/apt/trusted.gpg.d/client<%= index %>.asc <%= shell_escape repo_gpg_key_url %> + <%= indent(4, skip1: true) { generate_web_request(utility: @download_utility, url: shell_escape(repo_gpg_key_url), output_file: "/etc/apt/trusted.gpg.d/client#{index}.asc") } %> fi <% end -%> apt-get update @@ -108,22 +109,23 @@ fi <% end -%> register_host() { - curl --silent --show-error --cacert $SSL_CA_CERT --request POST <%= @registration_url %> \ - <%= headers.join(' ') %> \ - --data "host[name]=$(hostname --fqdn)" \ - --data "host[build]=false" \ - --data "host[managed]=false" \ -<%= " --data 'host[organization_id]=#{@organization.id}' \\\n" if @organization -%> -<%= " --data 'host[location_id]=#{@location.id}' \\\n" if @location -%> -<%= " --data 'host[hostgroup_id]=#{@hostgroup.id}' \\\n" if @hostgroup -%> -<%= " --data 'host[operatingsystem_id]=#{@operatingsystem.id}' \\\n" if @operatingsystem -%> -<%= " --data host[interfaces_attributes][0][identifier]=#{shell_escape(@remote_execution_interface)} \\\n" if @remote_execution_interface.present? -%> -<%= " --data 'setup_insights=#{@setup_insights}' \\\n" unless @setup_insights.nil? -%> -<%= " --data 'setup_remote_execution=#{@setup_remote_execution}' \\\n" unless @setup_remote_execution.nil? -%> -<%= " --data remote_execution_interface=#{shell_escape(@remote_execution_interface)} \\\n" if @remote_execution_interface.present? -%> -<%= " --data packages=#{shell_escape(@packages)} \\\n" if @packages.present? -%> -<%= " --data 'update_packages=#{@update_packages}' \\\n" unless @update_packages.nil? -%> - +<% + params = [] + params << "host[name]=$(hostname --fqdn)" + params << "host[build]=false" + params << "host[managed]=false" + params << "host[organization_id]=#{@organization.id}" if @organization + params << "host[location_id]=#{@location.id}" if @location + params << "host[hostgroup_id]=#{@hostgroup.id}" if @hostgroup + params << "host[operatingsystem_id]=#{@operatingsystem.id}" if @operatingsystem + params << "host[interfaces_attributes][0][identifier]=#{shell_escape(@remote_execution_interface)}" if @remote_execution_interface.present? + params << "setup_insights=#{@setup_insights}" unless @setup_insights.nil? + params << "setup_remote_execution=#{@setup_remote_execution}" unless @setup_remote_execution.nil? + params << "remote_execution_interface=#{shell_escape(@remote_execution_interface)}" if @remote_execution_interface.present? + params << "packages=#{shell_escape(@packages)}" if @packages.present? + params << "update_packages=#{@update_packages}" unless @update_packages.nil? +-%> + <%= indent(2, skip1: true) { generate_web_request(utility: @download_utility, url: @registration_url, ssl_ca_cert: "$SSL_CA_CERT", headers: headers, params: params) } %> } echo "#" @@ -132,22 +134,23 @@ echo "#" <% if plugin_present?('katello') && activation_keys.present? -%> register_katello_host(){ - UUID=$(subscription-manager identity | grep --max-count 1 --only-matching '\([[:xdigit:]]\{8\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{12\}\)') - curl --silent --show-error --cacert $KATELLO_SERVER_CA_CERT --request POST "<%= @registration_url %>" \ - <%= headers.join(' ') %> \ - --data "uuid=$UUID" \ - --data "host[build]=false" \ -<%= " --data 'host[organization_id]=#{@organization.id}' \\\n" if @organization -%> -<%= " --data 'host[location_id]=#{@location.id}' \\\n" if @location -%> -<%= " --data 'host[hostgroup_id]=#{@hostgroup.id}' \\\n" if @hostgroup -%> -<%= " --data 'host[lifecycle_environment_id]=#{@lifecycle_environment_id}' \\\n" if @lifecycle_environment_id.present? -%> -<%= " --data 'setup_insights=#{@setup_insights}' \\\n" unless @setup_insights.nil? -%> -<%= " --data 'setup_remote_execution=#{@setup_remote_execution}' \\\n" unless @setup_remote_execution.nil? -%> -<%= " --data remote_execution_interface=#{shell_escape(@remote_execution_interface)} \\\n" if @remote_execution_interface.present? -%> -<%= " --data 'setup_remote_execution_pull=#{@setup_remote_execution_pull}' \\\n" unless @setup_remote_execution_pull.nil? -%> -<%= " --data packages=#{shell_escape(@packages)} \\\n" if @packages.present? -%> -<%= " --data 'update_packages=#{@update_packages}' \\\n" unless @update_packages.nil? -%> - +<% + params = [] + params << "uuid=$UUID" + params << "host[build]=false" + params << "host[organization_id]=#{@organization.id}" if @organization + params << "host[location_id]=#{@location.id}" if @location + params << "host[hostgroup_id]=#{@hostgroup.id}" if @hostgroup + params << "host[lifecycle_environment_id]=#{@lifecycle_environment_id}" if @lifecycle_environment_id.present? + params << "setup_insights=#{@setup_insights}" unless @setup_insights.nil? + params << "setup_remote_execution=#{@setup_remote_execution}" unless @setup_remote_execution.nil? + params << "remote_execution_interface=#{shell_escape(@remote_execution_interface)}" if @remote_execution_interface.present? + params << "setup_remote_execution_pull=#{@setup_remote_execution_pull}" unless @setup_remote_execution_pull.nil? + params << "packages=#{shell_escape(@packages)}" if @packages.present? + params << "update_packages=#{@update_packages}" unless @update_packages.nil? +-%> + UUID=$(subscription-manager identity | grep --max-count 1 --only-matching '\([[:xdigit:]]\{8\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{4\}-[[:xdigit:]]\{12\}\)') + <%= indent(2, skip1: true) { generate_web_request(utility: @download_utility, url: @registration_url, ssl_ca_cert: "$KATELLO_SERVER_CA_CERT", headers: headers, params: params) } %> } # Set up subscription-manager diff --git a/lib/foreman.rb b/lib/foreman.rb index ccb5e65b270..dcabc80bec3 100644 --- a/lib/foreman.rb +++ b/lib/foreman.rb @@ -45,4 +45,27 @@ def self.input_types_registry def self.settings SettingRegistry.instance end + + def self.download_utilities + { + 'curl' => { + :ca_cert => '--cacert', + :download_command => 'curl --silent --show-error', + :insecure => '--insecure', + :output_file => '--output', + :request_type_post => '--request POST', + :registration_command => 'curl --silent --show-error --request POST --cacert', + :format_params => proc { |params| params.map { |param| "--data \"#{param}\"" } }, + }, + 'wget' => { + :ca_cert => '--ca-certificate', + :download_command => 'wget --no-verbose', + :insecure => '--no-check-certificate', + :output_file => '--output-document', + :output_pipe => '--output-document -', + :registration_command => 'wget --no-verbose -O- --ca-certificate', + :format_params => proc { |params| ["--post-data \"#{params.join('&')}\""] }, + }, + }.freeze + end end diff --git a/test/controllers/api/v2/registration_commands_controller_test.rb b/test/controllers/api/v2/registration_commands_controller_test.rb index 52176a93ec0..bf6a601354a 100644 --- a/test/controllers/api/v2/registration_commands_controller_test.rb +++ b/test/controllers/api/v2/registration_commands_controller_test.rb @@ -7,8 +7,8 @@ class Api::V2::RegistrationCommandsControllerTest < ActionController::TestCase assert_response :success response = ActiveSupport::JSON.decode(@response.body)['registration_command'] - assert_includes response, "curl -sS 'http://test.host/register'" - assert_includes response, "-H 'Authorization: Bearer" + assert_includes response, "curl --silent --show-error 'http://test.host/register'" + assert_includes response, "--header 'Authorization: Bearer" end test 'with params' do @@ -50,7 +50,7 @@ class Api::V2::RegistrationCommandsControllerTest < ActionController::TestCase assert_response :success response = ActiveSupport::JSON.decode(@response.body)['registration_command'] - assert_includes response, "curl -sS --insecure '#{proxy.url}/register'" + assert_includes response, "curl --silent --show-error --insecure '#{proxy.url}/register'" end test 'os without host_init_config template' do @@ -65,5 +65,32 @@ class Api::V2::RegistrationCommandsControllerTest < ActionController::TestCase post :create, params: { smart_proxy_id: smart_proxies(:one).id } assert_response :unprocessable_entity end + + test 'using wget' do + params = { + download_utility: 'wget', + } + + post :create, params: params + assert_response :success + + response = ActiveSupport::JSON.decode(@response.body)['registration_command'] + assert_includes response, "wget --no-verbose --output-document - 'http://test.host/register?download_utility=wget'" + assert_includes response, "--header 'Authorization: Bearer" + end + + test 'using wget with insecure option' do + params = { + download_utility: 'wget', + insecure: true, + } + + post :create, params: params + assert_response :success + + response = ActiveSupport::JSON.decode(@response.body)['registration_command'] + assert_includes response, "wget --no-verbose --output-document - --no-check-certificate 'http://test.host/register?download_utility=wget'" + assert_includes response, "--header 'Authorization: Bearer" + end end end diff --git a/test/controllers/api/v2/registration_controller_test.rb b/test/controllers/api/v2/registration_controller_test.rb index d9d44fbbf6e..ee4baf47193 100644 --- a/test/controllers/api/v2/registration_controller_test.rb +++ b/test/controllers/api/v2/registration_controller_test.rb @@ -26,6 +26,7 @@ class Api::V2::RegistrationControllerTest < ActionController::TestCase location_id: taxonomies(:location1).id, hostgroup_id: hostgroups(:common).id, operatingsystem_id: operatingsystems(:centos5_3).id, + download_utility: 'wget', } get :global, params: params, session: set_session_user @@ -38,6 +39,7 @@ class Api::V2::RegistrationControllerTest < ActionController::TestCase assert_equal operatingsystems(:centos5_3), vars[:operatingsystem] assert_equal users(:admin), vars[:user] assert_equal register_url, vars[:registration_url].to_s + assert_equal 'wget', vars[:download_utility].to_s end test "should not pass unpermitted params to template" do diff --git a/test/controllers/registration_commands_controller_test.rb b/test/controllers/registration_commands_controller_test.rb index b0bc2b69c2a..a96a67123e1 100644 --- a/test/controllers/registration_commands_controller_test.rb +++ b/test/controllers/registration_commands_controller_test.rb @@ -37,6 +37,7 @@ class RegistrationCommandsControllerTest < ActionController::TestCase hostgroupId: hostgroups(:common).id, operatingsystemId: operatingsystems(:redhat).id, update_packages: true, + download_utility: 'wget', } post :create, params: params, session: set_session_user command = JSON.parse(@response.body)['command'] @@ -46,6 +47,7 @@ class RegistrationCommandsControllerTest < ActionController::TestCase assert_includes command, 'hostgroupId=' assert_includes command, 'operatingsystemId=' assert_includes command, 'update_packages=true' + assert_includes command, 'download_utility=wget' end test 'with params ignored in URL' do diff --git a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/__snapshots__/integration.test.js.snap b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/__snapshots__/integration.test.js.snap index 352a3bd8f12..3e8fb08d94c 100644 --- a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/__snapshots__/integration.test.js.snap +++ b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/__snapshots__/integration.test.js.snap @@ -8,6 +8,7 @@ Object { "payload": Object { "key": "REGISTRATION_COMMANDS", "params": Object { + "downloadUtility": undefined, "hostgroupId": undefined, "insecure": false, "jwtExpiration": 4, diff --git a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/components/__snapshots__/General.test.js.snap b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/components/__snapshots__/General.test.js.snap index 6017a5ef5e0..a774869dacc 100644 --- a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/components/__snapshots__/General.test.js.snap +++ b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/__tests__/components/__snapshots__/General.test.js.snap @@ -33,6 +33,10 @@ exports[`RegistrationCommandsPage - General renders 1`] = ` smartProxies={Array []} smartProxyId={0} /> + {}, handleInvalidField: () => {}, isLoading: false, + downloadUtility: DownloadUtilities.curl, + handleDownloadUtility: () => {}, }; export const advancedComponentProps = { configParams: {}, @@ -98,6 +101,12 @@ export const updatePackagesProps = { isLoading: false, }; +export const downloadUtilityProps = { + downloadUtility: DownloadUtilities.curl, + handleDownloadUtility: () => {}, + isLoading: false, +}; + export const repositoryProps = { repoData: [], handleRepoData: () => {}, diff --git a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/General.js b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/General.js index 146ba504e32..9a1ea1186c0 100644 --- a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/General.js +++ b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/components/General.js @@ -6,6 +6,7 @@ import HostGroup from './fields/HostGroup'; import OperatingSystem from './fields/OperatingSystem'; import SmartProxy from './fields/SmartProxy'; import Insecure from './fields/Insecure'; +import DownloadUtility from './fields/DownloadUtility'; const General = ({ organizationId, @@ -28,6 +29,8 @@ const General = ({ handleInsecure, handleInvalidField, isLoading, + downloadUtility, + handleDownloadUtility, }) => ( <> + + ( + + handleDownloadUtility(v)} + className="without_select2" + id="reg_download_utility" + isDisabled={isLoading} + > + {DownloadUtilities.map(item => ( + + ))} + + +); + +DownloadUtility.propTypes = { + downloadUtility: PropTypes.oneOf([ + DownloadUtilities.curl, + DownloadUtilities.wget, + ]), + handleDownloadUtility: PropTypes.func.isRequired, + isLoading: PropTypes.bool.isRequired, +}; + +DownloadUtility.defaultProps = { + downloadUtility: DownloadUtilities.curl, +}; + +export default DownloadUtility; diff --git a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/index.js b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/index.js index 27b81b3f410..1ee65ba4054 100644 --- a/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/index.js +++ b/webpack/assets/javascripts/react_app/routes/RegistrationCommands/RegistrationCommandsPage/index.js @@ -44,6 +44,7 @@ import Advanced from './components/Advanced'; import Actions from './components/Actions'; import Command from './components/Command'; import './RegistrationCommandsPage.scss'; +import { DownloadUtilities } from './components/fields/DownloadUtility'; const RegistrationCommandsPage = () => { const dispatch = useDispatch(); @@ -88,6 +89,9 @@ const RegistrationCommandsPage = () => { const [repoData, setRepoData] = useState([]); const [repoDataInternal, setRepoDataInternal] = useState([]); const [invalidFields, setInvalidFields] = useState([]); + const [downloadUtility, setDownloadUtility] = useState( + DownloadUtilities.curl + ); // Command const command = useSelector(selectCommand); @@ -128,6 +132,7 @@ const RegistrationCommandsPage = () => { packages, repoData, updatePackages, + downloadUtility, ...pluginValues, }; @@ -274,6 +279,8 @@ const RegistrationCommandsPage = () => { handleInvalidField={handleInvalidField} invalidFields={invalidFields} isLoading={isLoading} + downloadUtility={downloadUtility} + handleDownloadUtility={setDownloadUtility} />