foreman_leapp 4.3.0 → 5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b21b7465db5f87cfccd517c018e30bb3aa5f6c7878cbef6e314c981b5c21870
4
- data.tar.gz: dd0f2a71a7d5c5858aa3c6336d4d92fafb6ebd3c890404265262491ce2311057
3
+ metadata.gz: 0b1d949c6e610cc2063defc9a50b0cf522f37fdf6ca8c839a4fb506cffd7460f
4
+ data.tar.gz: 927658988954a6db9379f26497f27c6bb68253e1f8ccb11dc1061a21169a2ee1
5
5
  SHA512:
6
- metadata.gz: c6e3d0c62affb53415a88dc5fd5ab55f44a9a3dfa601964a8fdf85bf7264f6a3e41622e63f8a213547197f7f23b5bcb139ed3f034df27ac25e564c915c0a622e
7
- data.tar.gz: 021af94cf62a318c7aadace3ed71f8171862f2820a5f7d67dcd800ffc8d52ef0caeb4df53be11a8a7bad4c722db43486095e1f10184234f7c8b84c873a8764da
6
+ metadata.gz: d93ffcc5320a5339bc97d9a3130bdf3ee0d3b96028d8d883c0895bdeb8abb8ec15dd4593aecbfeedd578027eb85606684f194b5fc19771d2c5c9947d82be87fe
7
+ data.tar.gz: 9b2e14599a9949e7c5040c71b3eb7d193a1cd88dc29ad388e05a49c8b71cf93a7253484481f7e54584b8002bd2fcb86675018afd9f096b3ac8ffa26adcd3fb5f
@@ -4,11 +4,8 @@ module ForemanLeapp
4
4
  module TemplateHelper
5
5
  def build_remediation_plan(remediation_ids, host)
6
6
  PreupgradeReportEntry.remediation_details(remediation_ids, host)
7
- .map { |e| e['remediations'] }
8
- .flatten
9
- .compact
10
- .select { |r| r['type'] == 'command' }
11
- .map { |r| "#{r['context'].join(' ')}\n" }
7
+ .group_by { |_detail, leapp_version| leapp_version }
8
+ .map { |leapp_version, pairs| RemediationPlan.build(pairs.map(&:first), leapp_version) }
12
9
  .join
13
10
  end
14
11
  end
@@ -3,6 +3,9 @@
3
3
  module Actions
4
4
  module ForemanLeapp
5
5
  class PreupgradeJob < Actions::EntryAction
6
+ # The `rpm -q leapp` line of the job output, e.g. leapp-0.21.0-1.el8.noarch
7
+ LEAPP_NVR = /^leapp-(\d[\d.]*)/.freeze
8
+
6
9
  def self.subscribe
7
10
  Actions::RemoteExecution::RunHostJob
8
11
  end
@@ -15,9 +18,11 @@ module Actions
15
18
 
16
19
  def finalize(*_args)
17
20
  host = Host.find(input[:host_id])
18
- leapp_report = format_output(task.main_action.continuous_output.humanize)
21
+ job_output = task.main_action.continuous_output.humanize
22
+ leapp_report = format_output(job_output)
19
23
 
20
- PreupgradeReport.create_report(host, leapp_report, input[:job_invocation_id])
24
+ PreupgradeReport.create_report(host, leapp_report, input[:job_invocation_id],
25
+ leapp_version(job_output))
21
26
  end
22
27
 
23
28
  private
@@ -30,6 +35,12 @@ module Actions
30
35
  .join('')
31
36
  JSON.parse(output)
32
37
  end
38
+
39
+ # The version of the leapp package the report was generated with. It drives
40
+ # how the remediation commands from the report have to be quoted.
41
+ def leapp_version(job_output)
42
+ job_output[LEAPP_NVR, 1]
43
+ end
33
44
  end
34
45
  end
35
46
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
4
+
5
+ module ForemanLeapp
6
+ # Assembles the shell script out of the command remediations found in a leapp report.
7
+ #
8
+ # Leapp changed the way remediation commands are quoted. Up to leapp 0.21 the
9
+ # arguments in the "context" list were already quoted by leapp itself, so they
10
+ # were meant to be joined verbatim. Starting with leapp 0.22 the arguments are
11
+ # reported as they are and have to be escaped by the consumer of the report.
12
+ # See https://github.com/oamg/leapp-repository/pull/1520
13
+ #
14
+ # The new quoting is shipped by leapp-upgrade-el<X>toel<Y> 0.25, which is released
15
+ # together with leapp 0.22, so the version of the leapp package tells the two
16
+ # formats apart.
17
+ module RemediationPlan
18
+ # The first leapp version that reports remediation command arguments unquoted.
19
+ UNQUOTED_ARGUMENTS_SINCE = Gem::Version.new('0.22')
20
+
21
+ class << self
22
+ def build(detail, leapp_version)
23
+ quoted = quoted_by_leapp?(leapp_version)
24
+ Array.wrap(detail)
25
+ .flat_map { |d| d['remediations'] }
26
+ .compact
27
+ .select { |remediation| remediation['type'] == 'command' }
28
+ .map { |remediation| "#{command_line(remediation['context'], quoted)}\n" }
29
+ .join
30
+ end
31
+
32
+ def command_line(context, quoted)
33
+ arguments = Array.wrap(context)
34
+ return arguments.join(' ') if quoted
35
+
36
+ arguments.map { |argument| Shellwords.escape(argument) }.join(' ')
37
+ end
38
+
39
+ # Unknown versions are treated as old leapp, so that reports collected
40
+ # before the version was recorded keep rendering the way they used to.
41
+ def quoted_by_leapp?(leapp_version)
42
+ version = Gem::Version.new(leapp_version.to_s[/\A[0-9][0-9.]*/].to_s.chomp('.'))
43
+ version < UNQUOTED_ARGUMENTS_SINCE
44
+ rescue ArgumentError
45
+ true
46
+ end
47
+ end
48
+ end
49
+ end
@@ -6,7 +6,7 @@ class PreupgradeReport < ::Report
6
6
 
7
7
  scoped_search on: :job_invocation_id, only_explicit: true
8
8
 
9
- def self.create_report(host, data, job_invocation_id)
9
+ def self.create_report(host, data, job_invocation_id, leapp_version = nil)
10
10
  # We don't have specific permissions for the Preupgrade leapp reports,
11
11
  # so we need to skip the permission check for non-admin users.
12
12
  # The user is still required to have permission to run the job and view the hosts.
@@ -16,12 +16,12 @@ class PreupgradeReport < ::Report
16
16
  reported_at: DateTime.now.utc
17
17
 
18
18
  data['entries']&.each do |entry|
19
- PreupgradeReportEntry.create! entry_params(report, entry, host, data)
19
+ PreupgradeReportEntry.create! entry_params(report, entry, host, data, leapp_version)
20
20
  end
21
21
  end
22
22
  end
23
23
 
24
- def self.entry_params(report, entry, host, data)
24
+ def self.entry_params(report, entry, host, data, leapp_version = nil)
25
25
  { preupgrade_report: report,
26
26
  host_id: host.id,
27
27
  hostname: host.name,
@@ -30,6 +30,7 @@ class PreupgradeReport < ::Report
30
30
  audience: entry['audience'],
31
31
  severity: entry['severity'],
32
32
  leapp_run_id: data['leapp_run_id'],
33
+ leapp_version: leapp_version,
33
34
  summary: entry['summary'],
34
35
  tags: entry['tags'],
35
36
  flags: entry['flags'],
@@ -50,8 +50,10 @@ class PreupgradeReportEntry < ApplicationRecord
50
50
  ))
51
51
  }
52
52
 
53
+ # Returns [detail, leapp_version] pairs. The leapp version is needed because
54
+ # the quoting of the remediation commands differs between leapp versions.
53
55
  def self.remediation_details(remediation_ids, host)
54
- where(id: remediation_ids, host: host).where.not(detail: nil).pluck(:detail)
56
+ where(id: remediation_ids, host: host).where.not(detail: nil).pluck(:detail, :leapp_version)
55
57
  end
56
58
 
57
59
  def self.search_yes_no_fields(key, operator, value)
@@ -1,4 +1,5 @@
1
1
  object @preupgrade_report_entry
2
2
 
3
3
  attributes :id, :detail, :preupgrade_report_id, :host_id, :hostname, :title, :actor, :audience,
4
- :severity, :leapp_run_id, :summary, :tags, :flags, :created_at, :updated_at
4
+ :severity, :leapp_run_id, :leapp_version, :summary, :tags, :flags, :created_at,
5
+ :updated_at
@@ -27,6 +27,8 @@ template_inputs:
27
27
 
28
28
  <%= render_template 'Check Leapp' %>
29
29
 
30
+ rpm -q leapp
31
+
30
32
  rm -f /var/log/leapp/leapp-report.json
31
33
  leapp preupgrade <%= options_string %>
32
34
 
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddLeappVersionToReportEntries < ActiveRecord::Migration[7.0]
4
+ def change
5
+ add_column :preupgrade_report_entries, :leapp_version, :string
6
+ end
7
+ end
@@ -17,7 +17,7 @@ module ForemanLeapp
17
17
  initializer 'foreman_leapp.register_plugin', before: :finisher_hook do |app|
18
18
  app.reloader.to_prepare do
19
19
  Foreman::Plugin.register :foreman_leapp do
20
- requires_foreman '>= 5.0'
20
+ requires_foreman '>= 5.1'
21
21
  register_gettext
22
22
 
23
23
  apipie_documented_controllers ["#{ForemanLeapp::Engine.root}/app/controllers/api/v2/*.rb"]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ForemanLeapp
4
- VERSION = '4.3.0'
4
+ VERSION = '5.0.0'
5
5
  end
data/package.json CHANGED
@@ -4,12 +4,7 @@
4
4
  "description": "Plugin for RHEL upgrades using Foreman.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "lint": "tfm-lint --plugin -d /webpack",
8
- "link-leapp-js": "./script/link_leapp_js.sh",
9
- "test": "tfm-test --plugin --config jest.config.js",
10
- "test:watch": "tfm-test --plugin --watchAll",
11
- "test:current": "tfm-test --plugin --watch",
12
- "publish-coverage": "tfm-publish-coverage"
7
+ "link-leapp-js": "./script/link_leapp_js.sh"
13
8
  },
14
9
  "repository": {
15
10
  "type": "git",
@@ -21,16 +16,8 @@
21
16
  "url": "http://projects.theforeman.org/projects/foreman_leapp/issues"
22
17
  },
23
18
  "homepage": "https://github.com/oamg/foreman_leapp",
24
- "peerDependencies": {
25
- "@theforeman/vendor": ">= 12.0.1"
26
- },
27
19
  "devDependencies": {
28
20
  "@babel/core": "^7.7.0",
29
- "@theforeman/builder": ">= 12.0.1",
30
- "@theforeman/eslint-plugin-foreman": ">= 12.0.1",
31
- "@theforeman/eslint-plugin-rules": ">= 12.0.1",
32
- "@theforeman/test": ">= 12.0.1",
33
- "@theforeman/vendor-dev": ">= 12.0.1",
34
21
  "babel-eslint": "^10.0.0",
35
22
  "eslint": "^6.8.0",
36
23
  "prettier": "^1.19.1"
@@ -8,6 +8,17 @@ module ForemanLeapp
8
8
  let(:report) { FactoryBot.create(:preupgrade_report, host: host) }
9
9
  let(:entry) { FactoryBot.create(:preupgrade_report_entry, host: host, preupgrade_report: report) }
10
10
 
11
+ let(:quoting_context) do
12
+ {
13
+ remediations: [
14
+ {
15
+ type: 'command',
16
+ context: ['bash', '-c', 'ln -snf "var/log/leapp" "/space space"'],
17
+ },
18
+ ],
19
+ }
20
+ end
21
+
11
22
  describe 'build_remediation_plan' do
12
23
  test 'with remediation commands' do
13
24
  template = build_remediation_plan([entry.id], host)
@@ -26,6 +37,40 @@ module ForemanLeapp
26
37
  template = build_remediation_plan([entry.id], FactoryBot.create(:host))
27
38
  assert_equal template, ''
28
39
  end
40
+
41
+ test 'joins the arguments verbatim for reports from leapp older than 0.22' do
42
+ old_entry = FactoryBot.create(:preupgrade_report_entry, host: host, preupgrade_report: report,
43
+ leapp_version: '0.21.0', detail: quoting_context)
44
+
45
+ template = build_remediation_plan([old_entry.id], host)
46
+
47
+ assert_equal "bash -c ln -snf \"var/log/leapp\" \"/space space\"\n", template
48
+ end
49
+
50
+ test 'escapes the arguments for reports from leapp 0.22 and newer' do
51
+ new_entry = FactoryBot.create(:preupgrade_report_entry, host: host, preupgrade_report: report,
52
+ leapp_version: '0.22.0', detail: quoting_context)
53
+
54
+ template = build_remediation_plan([new_entry.id], host)
55
+
56
+ assert_equal ['bash', '-c', 'ln -snf "var/log/leapp" "/space space"'],
57
+ Shellwords.split(template)
58
+ end
59
+
60
+ test 'quotes every entry according to the leapp version it was reported by' do
61
+ old_entry = FactoryBot.create(:preupgrade_report_entry, host: host, preupgrade_report: report,
62
+ leapp_version: '0.21.0', detail: quoting_context)
63
+ new_entry = FactoryBot.create(:preupgrade_report_entry, host: host, preupgrade_report: report,
64
+ leapp_version: '0.22.0', detail: quoting_context)
65
+
66
+ lines = build_remediation_plan([old_entry.id, new_entry.id], host).lines
67
+ verbatim_line = "bash -c ln -snf \"var/log/leapp\" \"/space space\"\n"
68
+
69
+ assert_equal 2, lines.size
70
+ assert_includes lines, verbatim_line
71
+ assert_equal ['bash', '-c', 'ln -snf "var/log/leapp" "/space space"'],
72
+ Shellwords.split(lines.find { |line| line != verbatim_line })
73
+ end
29
74
  end
30
75
  end
31
76
  end
@@ -20,14 +20,15 @@ class PreupgradeReportEntryTest < ActiveSupport::TestCase
20
20
  @host = FactoryBot.create(:host)
21
21
 
22
22
  report = FactoryBot.create(:preupgrade_report)
23
- @entry1 = FactoryBot.create(:preupgrade_report_entry, preupgrade_report: report, host: @host)
23
+ @entry1 = FactoryBot.create(:preupgrade_report_entry, preupgrade_report: report, host: @host,
24
+ leapp_version: '0.22.0')
24
25
  @entry2 = FactoryBot.create(:preupgrade_report_entry, preupgrade_report: report, host: @host, detail: nil)
25
26
  end
26
27
 
27
28
  it do
28
29
  details = PreupgradeReportEntry.remediation_details([@entry1.id, @entry2.id], @host.id)
29
30
  assert_equal details.size, 1
30
- assert_equal details[0], @entry1.detail
31
+ assert_equal details[0], [@entry1.detail, '0.22.0']
31
32
 
32
33
  details = PreupgradeReportEntry.remediation_details([@entry1.id, @entry2.id], FactoryBot.create(:host))
33
34
  assert_equal details.size, 0
@@ -19,6 +19,22 @@ class PreupgradeReportTest < ActiveSupport::TestCase
19
19
  end
20
20
  end
21
21
 
22
+ it 'stores the leapp version the report was generated with' do
23
+ data = { 'leapp_run_id' => 'leapp_c13e471c', 'entries' => [sample_entry_1] }
24
+
25
+ PreupgradeReport.create_report(host, data, job_invocation, '0.22.0')
26
+
27
+ assert_equal ['0.22.0'], PreupgradeReportEntry.where(host: host).pluck(:leapp_version)
28
+ end
29
+
30
+ it 'leaves the leapp version empty when it is not known' do
31
+ data = { 'leapp_run_id' => 'leapp_c13e471c', 'entries' => [sample_entry_1] }
32
+
33
+ PreupgradeReport.create_report(host, data, job_invocation)
34
+
35
+ assert_nil PreupgradeReportEntry.where(host: host).first.leapp_version
36
+ end
37
+
22
38
  it 'no entries' do
23
39
  data = { 'leapp_run_id' => 'leapp_c13e471c' }
24
40
 
@@ -40,4 +40,31 @@ module ForemanLeapp
40
40
  it { assert_finalize_phase planned_action }
41
41
  end
42
42
  end
43
+
44
+ # Parsing the job output does not need any of the remote execution setup.
45
+ class PreupgradeJobOutputTest < ActiveSupport::TestCase
46
+ include Dynflow::Testing
47
+
48
+ let(:action) { create_action(Actions::ForemanLeapp::PreupgradeJob) }
49
+
50
+ describe '#leapp_version' do
51
+ test 'picks the leapp version up from the rpm output' do
52
+ output = "leapp-0.22.0-1.el9.noarch\n===leap_upgrade_report_start===\n{}\nExit status: 0\n"
53
+
54
+ assert_equal '0.22.0', action.send(:leapp_version, output)
55
+ end
56
+
57
+ test 'ignores other leapp packages' do
58
+ output = "leapp-upgrade-el8toel9-0.25.0-1.el8.noarch\nleapp-0.22.0-1.el8.noarch\n"
59
+
60
+ assert_equal '0.22.0', action.send(:leapp_version, output)
61
+ end
62
+
63
+ test 'returns nil when the leapp package is not reported' do
64
+ output = "package leapp is not installed\n===leap_upgrade_report_start===\n{}\n"
65
+
66
+ assert_nil action.send(:leapp_version, output)
67
+ end
68
+ end
69
+ end
43
70
  end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ module ForemanLeapp
6
+ class RemediationPlanTest < ActiveSupport::TestCase
7
+ # Taken from a leapp <= 0.21 report - leapp quoted the arguments itself.
8
+ OLD_SYMLINK_CONTEXT = [
9
+ 'sh',
10
+ '-c',
11
+ '"ln -snf usr/lib /lib && ln -snf var/log/leapp /space space && ' \
12
+ 'ln -snf var/log/leapp /quote\'quote"',
13
+ ].freeze
14
+
15
+ # The very same remediation as reported by leapp >= 0.22 - the arguments
16
+ # are reported verbatim. https://github.com/oamg/leapp-repository/pull/1520
17
+ NEW_SYMLINK_CONTEXT = [
18
+ 'bash',
19
+ '-c',
20
+ 'ln -snf "usr/lib" "/lib" && ln -snf "var/log/leapp" "/space space" && ' \
21
+ 'ln -snf "var/log/leapp" "/quote\'quote"',
22
+ ].freeze
23
+
24
+ describe '#command_line' do
25
+ test 'joins the arguments verbatim when leapp did the quoting' do
26
+ assert_equal OLD_SYMLINK_CONTEXT.join(' '),
27
+ RemediationPlan.command_line(OLD_SYMLINK_CONTEXT, true)
28
+ end
29
+
30
+ test 'escapes the arguments when leapp reports them verbatim' do
31
+ line = RemediationPlan.command_line(NEW_SYMLINK_CONTEXT, false)
32
+
33
+ assert_equal NEW_SYMLINK_CONTEXT, Shellwords.split(line)
34
+ end
35
+
36
+ test 'escapes shell metacharacters when leapp reports them verbatim' do
37
+ context = ['sed', '-i', 's/^AllowZoneDrifting=.*/AllowZoneDrifting=no/',
38
+ '/etc/firewalld/firewalld.conf']
39
+
40
+ line = RemediationPlan.command_line(context, false)
41
+
42
+ assert_equal context, Shellwords.split(line)
43
+ assert_not_includes line, '.*'
44
+ end
45
+ end
46
+
47
+ describe '#quoted_by_leapp?' do
48
+ test 'true for leapp older than 0.22' do
49
+ assert RemediationPlan.quoted_by_leapp?('0.21.0')
50
+ end
51
+
52
+ test 'false for leapp 0.22 and newer' do
53
+ assert_not RemediationPlan.quoted_by_leapp?('0.22.0')
54
+ assert_not RemediationPlan.quoted_by_leapp?('0.22')
55
+ end
56
+
57
+ test 'keeps the old quoting when the leapp version is unknown' do
58
+ [nil, ''].each do |leapp_version|
59
+ assert RemediationPlan.quoted_by_leapp?(leapp_version)
60
+ end
61
+ end
62
+
63
+ test 'keeps the old quoting when the leapp version cannot be parsed' do
64
+ assert RemediationPlan.quoted_by_leapp?('not-a-version')
65
+ end
66
+
67
+ test 'handles a leapp version with a release suffix' do
68
+ assert_not RemediationPlan.quoted_by_leapp?('0.22.0-1.el9')
69
+ end
70
+ end
71
+
72
+ describe '#build' do
73
+ let(:detail) do
74
+ { 'remediations' => [
75
+ { 'type' => 'hint', 'context' => 'Set AllowZoneDrifting=no' },
76
+ { 'type' => 'command', 'context' => %w[vgimportdevices] },
77
+ { 'type' => 'command', 'context' => NEW_SYMLINK_CONTEXT },
78
+ ] }
79
+ end
80
+
81
+ test 'renders one line per command remediation and skips the hints' do
82
+ lines = RemediationPlan.build(detail, '0.22.0').lines
83
+
84
+ assert_equal 2, lines.size
85
+ assert_equal ['vgimportdevices'], Shellwords.split(lines.first)
86
+ assert_equal NEW_SYMLINK_CONTEXT, Shellwords.split(lines.second)
87
+ end
88
+
89
+ test 'returns an empty plan when there is nothing to run' do
90
+ assert_equal '', RemediationPlan.build(nil, '0.22.0')
91
+ assert_equal '',
92
+ RemediationPlan.build({ 'remediations' => [{ 'type' => 'hint', 'context' => 'meh.' }] },
93
+ '0.22.0')
94
+ end
95
+ end
96
+ end
97
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_leapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Leapp team
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-10-09 00:00:00.000000000 Z
10
+ date: 2026-10-26 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: foreman_remote_execution
@@ -61,6 +61,7 @@ files:
61
61
  - app/helpers/foreman_leapp/hosts_helper.rb
62
62
  - app/helpers/foreman_leapp/template_helper.rb
63
63
  - app/lib/actions/foreman_leapp/preupgrade_job.rb
64
+ - app/lib/foreman_leapp/remediation_plan.rb
64
65
  - app/lib/helpers/job_helper.rb
65
66
  - app/models/concerns/foreman_leapp/job_invocation_extensions.rb
66
67
  - app/models/preupgrade_report.rb
@@ -82,6 +83,7 @@ files:
82
83
  - db/migrate/20200326142259_add_job_id_to_report.rb
83
84
  - db/migrate/20200327091009_add_host_to_report.rb
84
85
  - db/migrate/20200429080939_report_entries_flags.rb
86
+ - db/migrate/20260825120000_add_leapp_version_to_report_entries.rb
85
87
  - db/seeds.d/10_leapp_preupgrade.rb
86
88
  - lib/foreman_leapp.rb
87
89
  - lib/foreman_leapp/engine.rb
@@ -115,6 +117,7 @@ files:
115
117
  - test/test_plugin_helper.rb
116
118
  - test/unit/actions/preupgrade_job_test.rb
117
119
  - test/unit/helpers/job_helper_test.rb
120
+ - test/unit/remediation_plan_test.rb
118
121
  - webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js
119
122
  - webpack/components/PreupgradeReportsTable/PreupgradeReportsTable.scss
120
123
  - webpack/components/PreupgradeReportsTable/PreupgradeReportsTableHelpers.js
@@ -157,3 +160,4 @@ test_files:
157
160
  - test/test_plugin_helper.rb
158
161
  - test/unit/actions/preupgrade_job_test.rb
159
162
  - test/unit/helpers/job_helper_test.rb
163
+ - test/unit/remediation_plan_test.rb