foreman_remote_execution 13.2.4 → 14.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.
- checksums.yaml +4 -4
- data/app/controllers/ui_job_wizard_controller.rb +1 -1
- data/app/lib/foreman_remote_execution/renderer_methods.rb +14 -0
- data/config/initializers/inflections.rb +6 -0
- data/lib/foreman_remote_execution/engine.rb +243 -250
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/functional/ui_job_wizard_controller_test.rb +1 -1
- data/webpack/JobWizard/JobWizardPageRerun.js +80 -16
- data/webpack/JobWizard/JobWizardSelectors.js +7 -0
- data/webpack/JobWizard/__tests__/fixtures.js +6 -0
- data/webpack/JobWizard/steps/ReviewDetails/ReviewDetails.test.js +2 -1
- metadata +4 -3
- data/app/services/renderer_methods.rb +0 -12
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 4399d9a8e85b8b79562fd8209acf25f2137887480607b465d0ab414b52bf11c8
         | 
| 4 | 
            +
              data.tar.gz: c0f6b8be46eaf2cd537bd714338135ec86a6c21b11c9d544e15e26e164f11799
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a4f25bb7c8a1b2cee96fc4559f9d1184a35606a77ef027c353d95279f028298f42f4f03266a1b26dad18411303e0c08428a3072a242b1209f5191f1637c9ff7d
         | 
| 7 | 
            +
              data.tar.gz: '0689a879588c08bd9c689d406ed02a3ccb3b1cba0d89cd54dbf76fff7965472ba4fb3d44d5f4afac5ede4a5f3c0663f53ba59dac59c4709c3021b19001db03da'
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # macros to fetch information about invoked jobs
         | 
| 4 | 
            +
            module ForemanRemoteExecution
         | 
| 5 | 
            +
              module RendererMethods
         | 
| 6 | 
            +
                extend ActiveSupport::Concern
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def find_job_invocation_by_id(job_id, preload: nil)
         | 
| 9 | 
            +
                  JobInvocation.preload(preload).find_by(id: job_id)
         | 
| 10 | 
            +
                rescue ActiveRecord::NotFound => _e
         | 
| 11 | 
            +
                  raise ::Foreman::Exception.new(N_("Can't find Job Invocation for an id %s"), job_id)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -26,15 +26,6 @@ module ForemanRemoteExecution | |
| 26 26 | 
             
                  end
         | 
| 27 27 | 
             
                end
         | 
| 28 28 |  | 
| 29 | 
            -
                # A workaround for https://projects.theforeman.org/issues/30685
         | 
| 30 | 
            -
                initializer 'foreman_remote_execution.rails_loading_workaround' do
         | 
| 31 | 
            -
                  # Without this, in production environment the module gets prepended too
         | 
| 32 | 
            -
                  # late and the extensions do not get applied
         | 
| 33 | 
            -
                  # TODO: Remove this and from config.to_prepare once there is an extension
         | 
| 34 | 
            -
                  # point in Foreman
         | 
| 35 | 
            -
                  ProvisioningTemplatesHelper.prepend ForemanRemoteExecution::JobTemplatesExtensions
         | 
| 36 | 
            -
                end
         | 
| 37 | 
            -
             | 
| 38 29 | 
             
                initializer 'foreman_remote_execution.apipie' do
         | 
| 39 30 | 
             
                  Apipie.configuration.checksum_path += ['/api/']
         | 
| 40 31 | 
             
                end
         | 
| @@ -45,257 +36,259 @@ module ForemanRemoteExecution | |
| 45 36 | 
             
                  ForemanTasks.dynflow.config.eager_load_paths << File.join(ForemanRemoteExecution::Engine.root, 'app/lib/actions')
         | 
| 46 37 | 
             
                end
         | 
| 47 38 |  | 
| 48 | 
            -
                initializer 'foreman_remote_execution.register_plugin', before: :finisher_hook do | | 
| 49 | 
            -
                   | 
| 50 | 
            -
                     | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
                       | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
                       | 
| 64 | 
            -
                         | 
| 65 | 
            -
                           | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
                           | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
                           | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
                           | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
                           | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
                           | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
                           | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
                           | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
                           | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
                           | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
                           | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
                           | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
                           | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
                           | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
                           | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
                           | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
                           | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
                           | 
| 161 | 
            -
             | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 39 | 
            +
                initializer 'foreman_remote_execution.register_plugin', before: :finisher_hook do |app|
         | 
| 40 | 
            +
                  app.reloader.to_prepare do
         | 
| 41 | 
            +
                    Foreman::Plugin.register :foreman_remote_execution do
         | 
| 42 | 
            +
                      requires_foreman '>= 3.13'
         | 
| 43 | 
            +
                      register_global_js_file 'global'
         | 
| 44 | 
            +
                      register_gettext
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      apipie_documented_controllers ["#{ForemanRemoteExecution::Engine.root}/app/controllers/api/v2/*.rb"]
         | 
| 47 | 
            +
                      ApipieDSL.configuration.dsl_classes_matchers += [
         | 
| 48 | 
            +
                        "#{ForemanRemoteExecution::Engine.root}/app/lib/foreman_remote_execution/renderer/**/*.rb",
         | 
| 49 | 
            +
                      ]
         | 
| 50 | 
            +
                      automatic_assets(false)
         | 
| 51 | 
            +
                      precompile_assets(*assets_to_precompile)
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                      # Add settings to a Remote Execution category
         | 
| 54 | 
            +
                      settings do
         | 
| 55 | 
            +
                        category :remote_execution, N_('Remote Execution') do
         | 
| 56 | 
            +
                          setting 'remote_execution_fallback_proxy',
         | 
| 57 | 
            +
                            type: :boolean,
         | 
| 58 | 
            +
                            description: N_('Search the host for any proxy with Remote Execution, useful when the host has no subnet or the subnet does not have an execution proxy'),
         | 
| 59 | 
            +
                            default: false,
         | 
| 60 | 
            +
                            full_name: N_('Fallback to Any Proxy')
         | 
| 61 | 
            +
                          setting 'remote_execution_global_proxy',
         | 
| 62 | 
            +
                            type: :boolean,
         | 
| 63 | 
            +
                            description: N_('Search for remote execution proxy outside of the proxies assigned to the host. The search will be limited to the host\'s organization and location.'),
         | 
| 64 | 
            +
                            default: true,
         | 
| 65 | 
            +
                            full_name: N_('Enable Global Proxy')
         | 
| 66 | 
            +
                          setting 'remote_execution_ssh_user',
         | 
| 67 | 
            +
                            type: :string,
         | 
| 68 | 
            +
                            description: N_('Default user to use for SSH.  You may override per host by setting a parameter called remote_execution_ssh_user.'),
         | 
| 69 | 
            +
                            default: 'root',
         | 
| 70 | 
            +
                            full_name: N_('SSH User')
         | 
| 71 | 
            +
                          setting 'remote_execution_effective_user',
         | 
| 72 | 
            +
                            type: :string,
         | 
| 73 | 
            +
                            description: N_('Default user to use for executing the script. If the user differs from the SSH user, su or sudo is used to switch the user.'),
         | 
| 74 | 
            +
                            default: 'root',
         | 
| 75 | 
            +
                            full_name: N_('Effective User')
         | 
| 76 | 
            +
                          setting 'remote_execution_effective_user_method',
         | 
| 77 | 
            +
                            type: :string,
         | 
| 78 | 
            +
                            description: N_('What command should be used to switch to the effective user. One of %s') % ::SSHExecutionProvider::EFFECTIVE_USER_METHODS.inspect,
         | 
| 79 | 
            +
                            default: 'sudo',
         | 
| 80 | 
            +
                            full_name: N_('Effective User Method'),
         | 
| 81 | 
            +
                            collection: proc { Hash[::SSHExecutionProvider::EFFECTIVE_USER_METHODS.map { |method| [method, method] }] }
         | 
| 82 | 
            +
                          setting 'remote_execution_effective_user_password',
         | 
| 83 | 
            +
                            type: :string,
         | 
| 84 | 
            +
                            description: N_('Effective user password'),
         | 
| 85 | 
            +
                            default: '',
         | 
| 86 | 
            +
                            full_name: N_('Effective user password'),
         | 
| 87 | 
            +
                            encrypted: true
         | 
| 88 | 
            +
                          setting 'remote_execution_sync_templates',
         | 
| 89 | 
            +
                            type: :boolean,
         | 
| 90 | 
            +
                            description: N_('Whether we should sync templates from disk when running db:seed.'),
         | 
| 91 | 
            +
                            default: true,
         | 
| 92 | 
            +
                            full_name: N_('Sync Job Templates')
         | 
| 93 | 
            +
                          setting 'remote_execution_ssh_port',
         | 
| 94 | 
            +
                            type: :integer,
         | 
| 95 | 
            +
                            description: N_('Port to use for SSH communication. Default port 22. You may override per host by setting a parameter called remote_execution_ssh_port.'),
         | 
| 96 | 
            +
                            default: 22,
         | 
| 97 | 
            +
                            full_name: N_('SSH Port')
         | 
| 98 | 
            +
                          setting 'remote_execution_connect_by_ip',
         | 
| 99 | 
            +
                            type: :boolean,
         | 
| 100 | 
            +
                            description: N_('Should the ip addresses on host interfaces be preferred over the fqdn? '\
         | 
| 101 | 
            +
                                            'It is useful when DNS not resolving the fqdns properly. You may override this per host by setting a parameter called remote_execution_connect_by_ip. '\
         | 
| 102 | 
            +
                                            'For dual-stacked hosts you should consider the remote_execution_connect_by_ip_prefer_ipv6 setting'),
         | 
| 103 | 
            +
                            default: false,
         | 
| 104 | 
            +
                            full_name: N_('Connect by IP')
         | 
| 105 | 
            +
                          setting 'remote_execution_connect_by_ip_prefer_ipv6',
         | 
| 106 | 
            +
                            type: :boolean,
         | 
| 107 | 
            +
                            description: N_('When connecting using ip address, should the IPv6 addresses be preferred? '\
         | 
| 108 | 
            +
                                            'If no IPv6 address is set, it falls back to IPv4 automatically. You may override this per host by setting a parameter called remote_execution_connect_by_ip_prefer_ipv6. '\
         | 
| 109 | 
            +
                                            'By default and for compatibility, IPv4 will be preferred over IPv6 by default'),
         | 
| 110 | 
            +
                            default: false,
         | 
| 111 | 
            +
                            full_name: N_('Prefer IPv6 over IPv4')
         | 
| 112 | 
            +
                          setting 'remote_execution_ssh_password',
         | 
| 113 | 
            +
                            type: :string,
         | 
| 114 | 
            +
                            description: N_('Default password to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_password'),
         | 
| 115 | 
            +
                            default: nil,
         | 
| 116 | 
            +
                            full_name: N_('Default SSH password'),
         | 
| 117 | 
            +
                            encrypted: true
         | 
| 118 | 
            +
                          setting 'remote_execution_ssh_key_passphrase',
         | 
| 119 | 
            +
                            type: :string,
         | 
| 120 | 
            +
                            description: N_('Default key passphrase to use for SSH. You may override per host by setting a parameter called remote_execution_ssh_key_passphrase'),
         | 
| 121 | 
            +
                            default: nil,
         | 
| 122 | 
            +
                            full_name: N_('Default SSH key passphrase'),
         | 
| 123 | 
            +
                            encrypted: true
         | 
| 124 | 
            +
                          setting 'remote_execution_workers_pool_size',
         | 
| 125 | 
            +
                            type: :integer,
         | 
| 126 | 
            +
                            description: N_('Amount of workers in the pool to handle the execution of the remote execution jobs. Restart of the dynflowd/foreman-tasks service is required.'),
         | 
| 127 | 
            +
                            default: 5,
         | 
| 128 | 
            +
                            full_name: N_('Workers pool size')
         | 
| 129 | 
            +
                          setting 'remote_execution_cleanup_working_dirs',
         | 
| 130 | 
            +
                            type: :boolean,
         | 
| 131 | 
            +
                            description: N_('When enabled, working directories will be removed after task completion. You may override this per host by setting a parameter called remote_execution_cleanup_working_dirs.'),
         | 
| 132 | 
            +
                            default: true,
         | 
| 133 | 
            +
                            full_name: N_('Cleanup working directories')
         | 
| 134 | 
            +
                          setting 'remote_execution_cockpit_url',
         | 
| 135 | 
            +
                            type: :string,
         | 
| 136 | 
            +
                            description: N_('Where to find the Cockpit instance for the Web Console button.  By default, no button is shown.'),
         | 
| 137 | 
            +
                            default: nil,
         | 
| 138 | 
            +
                            full_name: N_('Cockpit URL')
         | 
| 139 | 
            +
                          setting 'remote_execution_form_job_template',
         | 
| 140 | 
            +
                            type: :string,
         | 
| 141 | 
            +
                            description: N_('Choose a job template that is pre-selected in job invocation form'),
         | 
| 142 | 
            +
                            default: 'Run Command - Script Default',
         | 
| 143 | 
            +
                            full_name: N_('Form Job Template'),
         | 
| 144 | 
            +
                            collection: proc { Hash[JobTemplate.unscoped.map { |template| [template.name, template.name] }] }
         | 
| 145 | 
            +
                          setting 'remote_execution_job_invocation_report_template',
         | 
| 146 | 
            +
                            type: :string,
         | 
| 147 | 
            +
                            description: N_('Select a report template used for generating a report for a particular remote execution job'),
         | 
| 148 | 
            +
                            default: 'Job - Invocation Report',
         | 
| 149 | 
            +
                            full_name: N_('Job Invocation Report Template'),
         | 
| 150 | 
            +
                            collection: proc { ForemanRemoteExecution.job_invocation_report_templates_select }
         | 
| 151 | 
            +
                          setting 'remote_execution_time_to_pickup',
         | 
| 152 | 
            +
                            type: :integer,
         | 
| 153 | 
            +
                            description: N_('Time in seconds within which the host has to pick up a job. If the job is not picked up within this limit, the job will be cancelled. Defaults to 1 day. Applies only to pull-mqtt based jobs.'),
         | 
| 154 | 
            +
                            default: 24 * 60 * 60,
         | 
| 155 | 
            +
                            full_name: N_('Time to pickup')
         | 
| 156 | 
            +
                        end
         | 
| 164 157 | 
             
                      end
         | 
| 165 | 
            -
                    end
         | 
| 166 158 |  | 
| 167 | 
            -
             | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 159 | 
            +
                      # Add permissions
         | 
| 160 | 
            +
                      security_block :foreman_remote_execution do
         | 
| 161 | 
            +
                        permission :view_job_templates, { :job_templates => [:index, :show, :revision, :auto_complete_search, :auto_complete_job_category, :preview, :export],
         | 
| 162 | 
            +
                                                          :'api/v2/job_templates' => [:index, :show, :revision, :export],
         | 
| 163 | 
            +
                                                          :'api/v2/template_inputs' => [:index, :show],
         | 
| 164 | 
            +
                                                          :'api/v2/foreign_input_sets' => [:index, :show],
         | 
| 165 | 
            +
                                                          :ui_job_wizard => [:categories, :template, :resources, :job_invocation]}, :resource_type => 'JobTemplate'
         | 
| 166 | 
            +
                        permission :create_job_templates, { :job_templates => [:new, :create, :clone_template, :import],
         | 
| 167 | 
            +
                                                            :'api/v2/job_templates' => [:create, :clone, :import] }, :resource_type => 'JobTemplate'
         | 
| 168 | 
            +
                        permission :edit_job_templates, { :job_templates => [:edit, :update],
         | 
| 169 | 
            +
                                                          :'api/v2/job_templates' => [:update],
         | 
| 170 | 
            +
                                                          :'api/v2/template_inputs' => [:create, :update, :destroy],
         | 
| 171 | 
            +
                                                          :'api/v2/foreign_input_sets' => [:create, :update, :destroy]}, :resource_type => 'JobTemplate'
         | 
| 172 | 
            +
                        permission :view_remote_execution_features, { :remote_execution_features => [:index, :show],
         | 
| 173 | 
            +
                                                                      :'api/v2/remote_execution_features' => [:index, :show, :available_remote_execution_features]},
         | 
| 174 | 
            +
                          :resource_type => 'RemoteExecutionFeature'
         | 
| 175 | 
            +
                        permission :edit_remote_execution_features, { :remote_execution_features => [:update],
         | 
| 176 | 
            +
                                                                      :'api/v2/remote_execution_features' => [:update ]}, :resource_type => 'RemoteExecutionFeature'
         | 
| 177 | 
            +
                        permission :destroy_job_templates, { :job_templates => [:destroy],
         | 
| 178 | 
            +
                                                            :'api/v2/job_templates' => [:destroy] }, :resource_type => 'JobTemplate'
         | 
| 179 | 
            +
                        permission :lock_job_templates, { :job_templates => [:lock, :unlock] }, :resource_type => 'JobTemplate'
         | 
| 180 | 
            +
                        permission :create_job_invocations, { :job_invocations => [:new, :create, :legacy_create, :refresh, :rerun, :preview_hosts],
         | 
| 181 | 
            +
                                                              'api/v2/job_invocations' => [:create, :rerun] }, :resource_type => 'JobInvocation'
         | 
| 182 | 
            +
                        permission :view_job_invocations, { :job_invocations => [:index, :chart, :show, :auto_complete_search, :preview_job_invocations_per_host], :template_invocations => [:show],
         | 
| 183 | 
            +
                                                            'api/v2/job_invocations' => [:index, :show, :output, :raw_output, :outputs] }, :resource_type => 'JobInvocation'
         | 
| 184 | 
            +
                        permission :view_template_invocations, { :template_invocations => [:show],
         | 
| 185 | 
            +
                                                                'api/v2/template_invocations' => [:template_invocations], :ui_job_wizard => [:job_invocation] }, :resource_type => 'TemplateInvocation'
         | 
| 186 | 
            +
                        permission :create_template_invocations, {}, :resource_type => 'TemplateInvocation'
         | 
| 187 | 
            +
                        permission :execute_jobs_on_infrastructure_hosts, {}, :resource_type => 'JobInvocation'
         | 
| 188 | 
            +
                        permission :cancel_job_invocations, { :job_invocations => [:cancel], 'api/v2/job_invocations' => [:cancel] }, :resource_type => 'JobInvocation'
         | 
| 189 | 
            +
                        # this permissions grants user to get auto completion hints when setting up filters
         | 
| 190 | 
            +
                        permission :filter_autocompletion_for_template_invocation, { :template_invocations => [ :auto_complete_search, :index ] },
         | 
| 191 | 
            +
                          :resource_type => 'TemplateInvocation'
         | 
| 192 | 
            +
                        permission :cockpit_hosts, { 'cockpit' => [:redirect, :host_ssh_params] }, :resource_type => 'Host'
         | 
| 193 | 
            +
                      end
         | 
| 202 194 |  | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
             | 
| 260 | 
            -
             | 
| 261 | 
            -
             | 
| 262 | 
            -
             | 
| 263 | 
            -
             | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 195 | 
            +
                      USER_PERMISSIONS = [
         | 
| 196 | 
            +
                        :view_job_templates,
         | 
| 197 | 
            +
                        :view_job_invocations,
         | 
| 198 | 
            +
                        :create_job_invocations,
         | 
| 199 | 
            +
                        :create_template_invocations,
         | 
| 200 | 
            +
                        :view_hosts,
         | 
| 201 | 
            +
                        :view_smart_proxies,
         | 
| 202 | 
            +
                        :view_remote_execution_features,
         | 
| 203 | 
            +
                      ].freeze
         | 
| 204 | 
            +
                      MANAGER_PERMISSIONS = USER_PERMISSIONS + [
         | 
| 205 | 
            +
                        :cancel_job_invocations,
         | 
| 206 | 
            +
                        :destroy_job_templates,
         | 
| 207 | 
            +
                        :edit_job_templates,
         | 
| 208 | 
            +
                        :create_job_templates,
         | 
| 209 | 
            +
                        :lock_job_templates,
         | 
| 210 | 
            +
                        :view_audit_logs,
         | 
| 211 | 
            +
                        :filter_autocompletion_for_template_invocation,
         | 
| 212 | 
            +
                        :edit_remote_execution_features,
         | 
| 213 | 
            +
                      ]
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                      # Add a new role called 'Remote Execution User ' if it doesn't exist
         | 
| 216 | 
            +
                      role 'Remote Execution User', USER_PERMISSIONS, 'Role with permissions to run remote execution jobs against hosts'
         | 
| 217 | 
            +
                      role 'Remote Execution Manager', MANAGER_PERMISSIONS, 'Role with permissions to manage job templates, remote execution features, cancel jobs and view audit logs'
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                      add_all_permissions_to_default_roles(except: [:execute_jobs_on_infrastructure_hosts])
         | 
| 220 | 
            +
                      add_permissions_to_default_roles({
         | 
| 221 | 
            +
                        Role::MANAGER => [:execute_jobs_on_infrastructure_hosts],
         | 
| 222 | 
            +
                        Role::SITE_MANAGER => USER_PERMISSIONS + [:execute_jobs_on_infrastructure_hosts],
         | 
| 223 | 
            +
                      })
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                      # add menu entry
         | 
| 226 | 
            +
                      menu :top_menu, :job_templates,
         | 
| 227 | 
            +
                        url_hash: { controller: :job_templates, action: :index },
         | 
| 228 | 
            +
                        caption: N_('Job templates'),
         | 
| 229 | 
            +
                        parent: :hosts_menu,
         | 
| 230 | 
            +
                        after: :provisioning_templates
         | 
| 231 | 
            +
                      menu :admin_menu, :remote_execution_features,
         | 
| 232 | 
            +
                        url_hash: { controller: :remote_execution_features, action: :index },
         | 
| 233 | 
            +
                        caption: N_('Remote Execution Features'),
         | 
| 234 | 
            +
                        parent: :administer_menu,
         | 
| 235 | 
            +
                        after: :bookmarks
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                      menu :top_menu, :job_invocations,
         | 
| 238 | 
            +
                        url_hash: { controller: :job_invocations, action: :index },
         | 
| 239 | 
            +
                        caption: N_('Jobs'),
         | 
| 240 | 
            +
                        parent: :monitor_menu,
         | 
| 241 | 
            +
                        after: :audits
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                      menu :labs_menu, :job_invocations_detail,
         | 
| 244 | 
            +
                        url_hash: { controller: :job_invocations, action: :show },
         | 
| 245 | 
            +
                        caption: N_('Job invocations detail'),
         | 
| 246 | 
            +
                        parent: :lab_features_menu,
         | 
| 247 | 
            +
                        url: '/experimental/job_invocations_detail/1'
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                      register_custom_status HostStatus::ExecutionStatus
         | 
| 250 | 
            +
                      # add dashboard widget
         | 
| 251 | 
            +
                      # widget 'foreman_remote_execution_widget', name: N_('Foreman plugin template widget'), sizex: 4, sizey: 1
         | 
| 252 | 
            +
                      widget 'dashboard/latest-jobs', :name => N_('Latest Jobs'), :sizex => 6, :sizey => 1
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                      parameter_filter Subnet, :remote_execution_proxies, :remote_execution_proxy_ids => []
         | 
| 255 | 
            +
                      parameter_filter Nic::Interface do |ctx|
         | 
| 256 | 
            +
                        ctx.permit :execution
         | 
| 257 | 
            +
                      end
         | 
| 266 258 |  | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 259 | 
            +
                      register_graphql_query_field :job_invocations, '::Types::JobInvocation', :collection_field
         | 
| 260 | 
            +
                      register_graphql_query_field :job_invocation, '::Types::JobInvocation', :record_field
         | 
| 269 261 |  | 
| 270 | 
            -
             | 
| 262 | 
            +
                      register_graphql_mutation_field :create_job_invocation, ::Mutations::JobInvocations::Create
         | 
| 271 263 |  | 
| 272 | 
            -
             | 
| 264 | 
            +
                      extend_template_helpers ForemanRemoteExecution::RendererMethods
         | 
| 273 265 |  | 
| 274 | 
            -
             | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
             | 
| 278 | 
            -
             | 
| 266 | 
            +
                      extend_rabl_template 'api/v2/smart_proxies/main', 'api/v2/smart_proxies/pubkey'
         | 
| 267 | 
            +
                      extend_rabl_template 'api/v2/interfaces/main', 'api/v2/interfaces/execution_flag'
         | 
| 268 | 
            +
                      extend_rabl_template 'api/v2/subnets/show', 'api/v2/subnets/remote_execution_proxies'
         | 
| 269 | 
            +
                      extend_rabl_template 'api/v2/hosts/main', 'api/v2/host/main'
         | 
| 270 | 
            +
                      parameter_filter ::Subnet, :remote_execution_proxy_ids
         | 
| 279 271 |  | 
| 280 | 
            -
             | 
| 281 | 
            -
             | 
| 282 | 
            -
             | 
| 283 | 
            -
             | 
| 272 | 
            +
                      describe_host do
         | 
| 273 | 
            +
                        multiple_actions_provider :rex_hosts_multiple_actions
         | 
| 274 | 
            +
                        overview_buttons_provider :rex_host_overview_buttons
         | 
| 275 | 
            +
                      end
         | 
| 284 276 |  | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
             | 
| 288 | 
            -
             | 
| 289 | 
            -
             | 
| 290 | 
            -
             | 
| 291 | 
            -
             | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
             | 
| 295 | 
            -
             | 
| 277 | 
            +
                      # Extend Registration module
         | 
| 278 | 
            +
                      extend_allowed_registration_vars :remote_execution_interface
         | 
| 279 | 
            +
                      extend_allowed_registration_vars :setup_remote_execution_pull
         | 
| 280 | 
            +
                      ForemanTasks.dynflow.eager_load_actions!
         | 
| 281 | 
            +
                      extend_observable_events(
         | 
| 282 | 
            +
                        ::Dynflow::Action.descendants.select do |klass|
         | 
| 283 | 
            +
                          klass <= ::Actions::ObservableAction
         | 
| 284 | 
            +
                        end.map(&:namespaced_event_names) +
         | 
| 285 | 
            +
                        RemoteExecutionFeature.all.pluck(:label).flat_map do |label|
         | 
| 286 | 
            +
                          [::Actions::RemoteExecution::RunHostJob, ::Actions::RemoteExecution::RunHostsJob].map do |klass|
         | 
| 287 | 
            +
                            klass.feature_job_event_names(label)
         | 
| 288 | 
            +
                          end
         | 
| 296 289 | 
             
                        end
         | 
| 297 | 
            -
                       | 
| 298 | 
            -
                     | 
| 290 | 
            +
                      )
         | 
| 291 | 
            +
                    end
         | 
| 299 292 | 
             
                  end
         | 
| 300 293 | 
             
                end
         | 
| 301 294 |  | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require 'test_plugin_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            class  | 
| 3 | 
            +
            class UIJobWizardControllerTest < ActionController::TestCase
         | 
| 4 4 | 
             
              def setup
         | 
| 5 5 | 
             
                FactoryBot.create(:job_template, :job_category => 'cat1')
         | 
| 6 6 | 
             
                FactoryBot.create(:job_template, :job_category => 'cat2')
         | 
| @@ -1,16 +1,33 @@ | |
| 1 | 
            +
            import React, { useState, useEffect } from 'react';
         | 
| 1 2 | 
             
            import PropTypes from 'prop-types';
         | 
| 2 | 
            -
            import React from 'react';
         | 
| 3 3 | 
             
            import URI from 'urijs';
         | 
| 4 | 
            -
            import {  | 
| 4 | 
            +
            import { useDispatch, useSelector } from 'react-redux';
         | 
| 5 | 
            +
            import {
         | 
| 6 | 
            +
              Alert,
         | 
| 7 | 
            +
              Divider,
         | 
| 8 | 
            +
              Skeleton,
         | 
| 9 | 
            +
              Button,
         | 
| 10 | 
            +
              Title,
         | 
| 11 | 
            +
              EmptyState,
         | 
| 12 | 
            +
              EmptyStateVariant,
         | 
| 13 | 
            +
              EmptyStateIcon,
         | 
| 14 | 
            +
              EmptyStateBody,
         | 
| 15 | 
            +
            } from '@patternfly/react-core';
         | 
| 16 | 
            +
            import { ExclamationCircleIcon } from '@patternfly/react-icons';
         | 
| 17 | 
            +
            import { global_palette_red_200 as exclamationColor } from '@patternfly/react-tokens';
         | 
| 18 | 
            +
            import { get } from 'foremanReact/redux/API';
         | 
| 19 | 
            +
            import { sprintf, translate as __ } from 'foremanReact/common/I18n';
         | 
| 20 | 
            +
            import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
         | 
| 21 | 
            +
            import { STATUS } from 'foremanReact/constants';
         | 
| 5 22 | 
             
            import {
         | 
| 6 23 | 
             
              useForemanLocation,
         | 
| 7 24 | 
             
              useForemanOrganization,
         | 
| 8 25 | 
             
            } from 'foremanReact/Root/Context/ForemanContext';
         | 
| 9 | 
            -
            import { translate as __, sprintf } from 'foremanReact/common/I18n';
         | 
| 10 | 
            -
            import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
         | 
| 11 | 
            -
            import { STATUS } from 'foremanReact/constants';
         | 
| 12 | 
            -
            import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
         | 
| 13 26 | 
             
            import { JobWizard } from './JobWizard';
         | 
| 27 | 
            +
            import {
         | 
| 28 | 
            +
              selectRerunJobInvocationResponse,
         | 
| 29 | 
            +
              selectRerunJobInvocationStatus,
         | 
| 30 | 
            +
            } from './JobWizardSelectors';
         | 
| 14 31 | 
             
            import { JOB_API_KEY } from './JobWizardConstants';
         | 
| 15 32 |  | 
| 16 33 | 
             
            const JobWizardPageRerun = ({
         | 
| @@ -19,6 +36,7 @@ const JobWizardPageRerun = ({ | |
| 19 36 | 
             
              },
         | 
| 20 37 | 
             
              location: { search },
         | 
| 21 38 | 
             
            }) => {
         | 
| 39 | 
            +
              const dispatch = useDispatch();
         | 
| 22 40 | 
             
              const uri = new URI(search);
         | 
| 23 41 | 
             
              const { failed_only: failedOnly } = uri.search(true);
         | 
| 24 42 | 
             
              const { succeeded_only: succeededOnly } = uri.search(true);
         | 
| @@ -28,11 +46,6 @@ const JobWizardPageRerun = ({ | |
| 28 46 | 
             
              } else if (succeededOnly) {
         | 
| 29 47 | 
             
                queryParams = '&succeeded_only=1';
         | 
| 30 48 | 
             
              }
         | 
| 31 | 
            -
              const { response, status } = useAPI(
         | 
| 32 | 
            -
                'get',
         | 
| 33 | 
            -
                `/ui_job_wizard/job_invocation?id=${id}${queryParams}`,
         | 
| 34 | 
            -
                JOB_API_KEY
         | 
| 35 | 
            -
              );
         | 
| 36 49 | 
             
              const title = __('Run job');
         | 
| 37 50 | 
             
              const breadcrumbOptions = {
         | 
| 38 51 | 
             
                breadcrumbItems: [
         | 
| @@ -41,11 +54,55 @@ const JobWizardPageRerun = ({ | |
| 41 54 | 
             
                ],
         | 
| 42 55 | 
             
              };
         | 
| 43 56 |  | 
| 44 | 
            -
              const  | 
| 45 | 
            -
              const  | 
| 57 | 
            +
              const [errorMessage, setErrorMessage] = useState('');
         | 
| 58 | 
            +
              const jobInvocationResponse = useSelector(selectRerunJobInvocationResponse);
         | 
| 59 | 
            +
              const jobInvocationStatus = useSelector(selectRerunJobInvocationStatus);
         | 
| 60 | 
            +
              const jobOrganization = jobInvocationResponse.job_organization;
         | 
| 61 | 
            +
              const jobLocation = jobInvocationResponse.job_location;
         | 
| 46 62 | 
             
              const currentOrganization = useForemanOrganization();
         | 
| 47 63 | 
             
              const currentLocation = useForemanLocation();
         | 
| 48 64 |  | 
| 65 | 
            +
              const emptyStateLarge = (
         | 
| 66 | 
            +
                <EmptyState variant={EmptyStateVariant.large}>
         | 
| 67 | 
            +
                  <EmptyStateIcon
         | 
| 68 | 
            +
                    icon={ExclamationCircleIcon}
         | 
| 69 | 
            +
                    color={exclamationColor.value}
         | 
| 70 | 
            +
                  />
         | 
| 71 | 
            +
                  <Title ouiaId="job-wizard-empty-state-header" headingLevel="h4" size="lg">
         | 
| 72 | 
            +
                    {__('Unable to run job')}
         | 
| 73 | 
            +
                  </Title>
         | 
| 74 | 
            +
                  <EmptyStateBody>{sprintf(errorMessage)}</EmptyStateBody>
         | 
| 75 | 
            +
                  <Button
         | 
| 76 | 
            +
                    ouiaId="job-wizard-run-job-button"
         | 
| 77 | 
            +
                    component="a"
         | 
| 78 | 
            +
                    href="/job_invocations/new"
         | 
| 79 | 
            +
                    variant="primary"
         | 
| 80 | 
            +
                  >
         | 
| 81 | 
            +
                    {__('Create job')}
         | 
| 82 | 
            +
                  </Button>
         | 
| 83 | 
            +
                </EmptyState>
         | 
| 84 | 
            +
              );
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              useEffect(() => {
         | 
| 87 | 
            +
                let isMounted = true;
         | 
| 88 | 
            +
                if (id !== undefined) {
         | 
| 89 | 
            +
                  dispatch(
         | 
| 90 | 
            +
                    get({
         | 
| 91 | 
            +
                      key: JOB_API_KEY,
         | 
| 92 | 
            +
                      url: `/ui_job_wizard/job_invocation?id=${id}${queryParams}`,
         | 
| 93 | 
            +
                      handleError: ({ response }) => {
         | 
| 94 | 
            +
                        if (isMounted) {
         | 
| 95 | 
            +
                          setErrorMessage(response?.data?.error?.message);
         | 
| 96 | 
            +
                        }
         | 
| 97 | 
            +
                      },
         | 
| 98 | 
            +
                    })
         | 
| 99 | 
            +
                  );
         | 
| 100 | 
            +
                }
         | 
| 101 | 
            +
                return () => {
         | 
| 102 | 
            +
                  isMounted = false;
         | 
| 103 | 
            +
                };
         | 
| 104 | 
            +
              }, [dispatch, id, failedOnly, queryParams]);
         | 
| 105 | 
            +
             | 
| 49 106 | 
             
              return (
         | 
| 50 107 | 
             
                <PageLayout
         | 
| 51 108 | 
             
                  header={title}
         | 
| @@ -66,14 +123,16 @@ const JobWizardPageRerun = ({ | |
| 66 123 | 
             
                    <React.Fragment>
         | 
| 67 124 | 
             
                      <Divider component="div" />
         | 
| 68 125 | 
             
                    </React.Fragment>
         | 
| 69 | 
            -
                    { | 
| 126 | 
            +
                    {jobInvocationStatus === STATUS.ERROR && emptyStateLarge}
         | 
| 127 | 
            +
                    {(!jobInvocationStatus || jobInvocationStatus === STATUS.PENDING) && (
         | 
| 70 128 | 
             
                      <div style={{ height: '400px' }}>
         | 
| 71 129 | 
             
                        <Skeleton
         | 
| 72 130 | 
             
                          height="100%"
         | 
| 73 131 | 
             
                          screenreaderText="Loading large rectangle contents"
         | 
| 74 132 | 
             
                        />
         | 
| 75 133 | 
             
                      </div>
         | 
| 76 | 
            -
                    ) | 
| 134 | 
            +
                    )}
         | 
| 135 | 
            +
                    {jobInvocationStatus === STATUS.RESOLVED && (
         | 
| 77 136 | 
             
                      <React.Fragment>
         | 
| 78 137 | 
             
                        {jobOrganization?.id !== currentOrganization?.id && (
         | 
| 79 138 | 
             
                          <Alert
         | 
| @@ -107,7 +166,12 @@ const JobWizardPageRerun = ({ | |
| 107 166 | 
             
                        )}
         | 
| 108 167 | 
             
                        <Divider component="div" />
         | 
| 109 168 | 
             
                        <JobWizard
         | 
| 110 | 
            -
                          rerunData={ | 
| 169 | 
            +
                          rerunData={
         | 
| 170 | 
            +
                            {
         | 
| 171 | 
            +
                              ...jobInvocationResponse?.job,
         | 
| 172 | 
            +
                              inputs: jobInvocationResponse?.inputs,
         | 
| 173 | 
            +
                            } || null
         | 
| 174 | 
            +
                          }
         | 
| 111 175 | 
             
                        />
         | 
| 112 176 | 
             
                      </React.Fragment>
         | 
| 113 177 | 
             
                    )}
         | 
| @@ -14,8 +14,15 @@ import { | |
| 14 14 | 
             
              JOB_TEMPLATE,
         | 
| 15 15 | 
             
              HOSTS_API,
         | 
| 16 16 | 
             
              JOB_INVOCATION,
         | 
| 17 | 
            +
              JOB_API_KEY,
         | 
| 17 18 | 
             
            } from './JobWizardConstants';
         | 
| 18 19 |  | 
| 20 | 
            +
            export const selectRerunJobInvocationResponse = state =>
         | 
| 21 | 
            +
              selectAPIResponse(state, JOB_API_KEY) || {};
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            export const selectRerunJobInvocationStatus = state =>
         | 
| 24 | 
            +
              selectAPIStatus(state, JOB_API_KEY);
         | 
| 25 | 
            +
             | 
| 19 26 | 
             
            export const selectJobTemplatesStatus = state =>
         | 
| 20 27 | 
             
              selectAPIStatus(state, JOB_TEMPLATES);
         | 
| 21 28 |  | 
| @@ -114,6 +114,8 @@ export const jobCategories = ['Services', 'Ansible Commands', 'Puppet']; | |
| 114 114 |  | 
| 115 115 | 
             
            export const testSetup = (selectors, api) => {
         | 
| 116 116 | 
             
              jest.spyOn(api, 'get');
         | 
| 117 | 
            +
              jest.spyOn(selectors, 'selectRerunJobInvocationResponse');
         | 
| 118 | 
            +
              jest.spyOn(selectors, 'selectRerunJobInvocationStatus');
         | 
| 117 119 | 
             
              jest.spyOn(selectors, 'selectJobTemplate');
         | 
| 118 120 | 
             
              jest.spyOn(selectors, 'selectJobTemplates');
         | 
| 119 121 | 
             
              jest.spyOn(selectors, 'selectJobCategories');
         | 
| @@ -123,6 +125,10 @@ export const testSetup = (selectors, api) => { | |
| 123 125 |  | 
| 124 126 | 
             
              jest.spyOn(selectors, 'selectTemplateInputs');
         | 
| 125 127 | 
             
              jest.spyOn(selectors, 'selectAdvancedTemplateInputs');
         | 
| 128 | 
            +
              selectors.selectRerunJobInvocationResponse.mockImplementation(
         | 
| 129 | 
            +
                () => jobInvocation
         | 
| 130 | 
            +
              );
         | 
| 131 | 
            +
              selectors.selectRerunJobInvocationStatus.mockImplementation(() => 'RESOLVED');
         | 
| 126 132 | 
             
              selectors.selectWithKatello.mockImplementation(() => true);
         | 
| 127 133 | 
             
              selectors.selectTemplateInputs.mockImplementation(
         | 
| 128 134 | 
             
                () => jobTemplateResponse.template_inputs
         | 
| @@ -14,16 +14,17 @@ import { | |
| 14 14 | 
             
              jobInvocation,
         | 
| 15 15 | 
             
            } from '../../__tests__/fixtures';
         | 
| 16 16 |  | 
| 17 | 
            +
            jest.useFakeTimers();
         | 
| 17 18 | 
             
            const store = testSetup(selectors, api);
         | 
| 18 19 | 
             
            mockApi(api);
         | 
| 19 20 | 
             
            jest.spyOn(APIHooks, 'useAPI');
         | 
| 21 | 
            +
            store.dispatch = jest.fn();
         | 
| 20 22 | 
             
            APIHooks.useAPI.mockImplementation((action, url) => {
         | 
| 21 23 | 
             
              if (url === '/ui_job_wizard/job_invocation?id=57') {
         | 
| 22 24 | 
             
                return { response: jobInvocation, status: 'RESOLVED' };
         | 
| 23 25 | 
             
              }
         | 
| 24 26 | 
             
              return {};
         | 
| 25 27 | 
             
            });
         | 
| 26 | 
            -
            jest.useFakeTimers();
         | 
| 27 28 |  | 
| 28 29 | 
             
            describe('ReviewDetails', () => {
         | 
| 29 30 | 
             
              it('should call goToStepByName function when StepButton is clicked', async () => {
         | 
    
        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:  | 
| 4 | 
            +
              version: 14.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: 2024- | 
| 11 | 
            +
            date: 2024-09-10 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: deface
         | 
| @@ -170,6 +170,7 @@ files: | |
| 170 170 | 
             
            - app/lib/actions/remote_execution/template_invocation_progress_logging.rb
         | 
| 171 171 | 
             
            - app/lib/foreman_remote_execution/provider_input.rb
         | 
| 172 172 | 
             
            - app/lib/foreman_remote_execution/renderer/scope/input.rb
         | 
| 173 | 
            +
            - app/lib/foreman_remote_execution/renderer_methods.rb
         | 
| 173 174 | 
             
            - app/lib/proxy_api/remote_execution_ssh.rb
         | 
| 174 175 | 
             
            - app/mailers/.gitkeep
         | 
| 175 176 | 
             
            - app/mailers/rex_job_mailer.rb
         | 
| @@ -213,7 +214,6 @@ files: | |
| 213 214 | 
             
            - app/overrides/subnet_proxies.rb
         | 
| 214 215 | 
             
            - app/services/default_proxy_proxy_selector.rb
         | 
| 215 216 | 
             
            - app/services/remote_execution_proxy_selector.rb
         | 
| 216 | 
            -
            - app/services/renderer_methods.rb
         | 
| 217 217 | 
             
            - app/services/ui_notifications/remote_execution_jobs/base_job_finish.rb
         | 
| 218 218 | 
             
            - app/views/api/v2/foreign_input_sets/base.json.rabl
         | 
| 219 219 | 
             
            - app/views/api/v2/foreign_input_sets/create.json.rabl
         | 
| @@ -297,6 +297,7 @@ files: | |
| 297 297 | 
             
            - app/views/templates/script/run_command.erb
         | 
| 298 298 | 
             
            - app/views/templates/script/run_downloaded_script.erb
         | 
| 299 299 | 
             
            - app/views/templates/script/service_action.erb
         | 
| 300 | 
            +
            - config/initializers/inflections.rb
         | 
| 300 301 | 
             
            - config/routes.rb
         | 
| 301 302 | 
             
            - db/migrate/20150612121541_add_job_template_to_template.rb
         | 
| 302 303 | 
             
            - db/migrate/20150708133241_add_targeting.rb
         | 
| @@ -1,12 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            # macros to fetch information about invoked jobs
         | 
| 4 | 
            -
            module RendererMethods
         | 
| 5 | 
            -
              extend ActiveSupport::Concern
         | 
| 6 | 
            -
             | 
| 7 | 
            -
              def find_job_invocation_by_id(job_id, preload: nil)
         | 
| 8 | 
            -
                JobInvocation.preload(preload).find_by(id: job_id)
         | 
| 9 | 
            -
              rescue ActiveRecord::NotFound => _e
         | 
| 10 | 
            -
                raise ::Foreman::Exception.new(N_("Can't find Job Invocation for an id %s"), job_id)
         | 
| 11 | 
            -
              end
         | 
| 12 | 
            -
            end
         |