CHEF-4115 Added ability to merge reporter configurations from both CLI and config (#6568) (#6579)

* Added ability to merge cli and config reporter options



* Test cases to validate working of reporter configuration using cli and config



* Documentation change to add information on reporter configurations usage with both



* Added Doc review changes and text fixture for config json



* Verify fix



* Verify pipeline test fixes for reporter options to be read successfully



* Test changes in both cli and config reporter usage scenarios to fix verify pipeline



* Review comments to improvise



* Renamed testing fixture file for reporter cli config file



---------

Signed-off-by: Nikita Mathur <nikita.mathur@chef.io>
Co-authored-by: Nikita Mathur <Nik08@users.noreply.github.com>
This commit is contained in:
Clinton Wolfe 2023-07-25 08:45:42 -04:00 committed by GitHub
parent 3146906c3e
commit eff13369f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 13 deletions

View file

@ -15,7 +15,7 @@ A `reporter` is a facility for formatting and delivering the results of a Chef I
Chef InSpec allows you to output your test results to one or more reporters.
Configure the reporter(s) using either the `--reporter` option or as part of the general configuration file using the `--config` (or `--json-config`, prior to v3.6) option. While you can configure multiple reporters to write to different files, only one reporter can output to the screen(stdout).
Configure the reporter(s) using the `--reporter` option or as part of the general configuration file using the `--config` (or `--json-config`, prior to v3.6) option. Both the --reporter and --config options may be used, in which case the options are merged. While you can configure multiple reporters to write to different files, only one reporter can output to the screen(stdout).
## Syntax

View file

@ -561,7 +561,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
end
def run_command(opts)
runner = Inspec::Runner.new(Inspec::Config.new(opts))
runner = Inspec::Runner.new(opts)
res = runner.eval_with_virtual_profile(opts[:command])
runner.load

View file

@ -448,6 +448,13 @@ module Inspec
# Reporter options may be defined top-level.
options.merge!(config_file_reporter_options)
if @cli_opts["reporter"]
# Add reporter_cli_opts in options to capture reporter cli opts separately
options.merge!({ "reporter_cli_opts" => @cli_opts["reporter"] })
# Delete reporter from cli_opts to avoid direct merging of reporter info of cli and config
@cli_opts.delete("reporter")
end
# Highest precedence: merge in any options defined via the CLI
options.merge!(@cli_opts)
@ -476,13 +483,13 @@ module Inspec
end
def finalize_parse_reporters(options) # rubocop:disable Metrics/AbcSize
# default to cli report for ad-hoc runners
options["reporter"] = ["cli"] if options["reporter"].nil?
# Default to cli report for ad-hoc runners
options["reporter_cli_opts"] = ["cli"] if (options["reporter"].nil? || options["reporter"].empty?) && options["reporter_cli_opts"].nil?
# parse out cli to proper report format
if options["reporter"].is_a?(Array)
# Parse out reporter_cli_opts to proper report format
if options["reporter_cli_opts"].is_a?(Array)
reports = {}
options["reporter"].each do |report|
options["reporter_cli_opts"].each do |report|
reporter_name, destination = report.split(":", 2)
if destination.nil? || destination.strip == "-"
reports[reporter_name] = { "stdout" => true }
@ -494,7 +501,12 @@ module Inspec
reports[reporter_name]["target_id"] = options["target_id"] if options["target_id"]
end
end
options["reporter"] = reports
if options["reporter"].nil? || options["reporter"].empty?
options["reporter"] = reports
else
options["reporter"].merge!(reports)
end
end
# add in stdout if not specified
@ -507,6 +519,10 @@ module Inspec
end
validate_reporters!(options["reporter"])
# Delete reporter_cli_opts after graceful merging of cli and config reporters
options.delete("reporter_cli_opts")
options
end
@ -548,15 +564,12 @@ module Inspec
class Defaults
DEFAULTS = {
exec: {
"reporter" => ["cli"],
"show_progress" => false,
"color" => true,
"create_lockfile" => true,
"backend_cache" => true,
},
shell: {
"reporter" => ["cli"],
},
shell: {},
}.freeze
def self.for_command(command_name)

View file

@ -0,0 +1,7 @@
{
"reporter": {
"cli" : {
"stdout" : true
}
}
}

View file

@ -81,7 +81,7 @@ describe "inputs" do
let(:common_options) do
{
profile: "#{inputs_profiles_path}/via-runner",
reporter: ["json"],
"reporter" => ["json"],
}
end

View file

@ -1085,6 +1085,34 @@ describe "inspec exec" do
end
end
describe "When specifying a config file and --reporter option to configure reporter in a run in a correct manner" do
it "should obey the configurations of both --reporter and config reporter options" do
outpath = Dir.tmpdir
cli_args = "--no-create-lockfile --reporter json:#{outpath}/foo/bar/test.json --config " + File.join(config_dir_path, "json-config", "reporter-cli-config.json")
inspec("exec #{complete_profile} #{cli_args}")
# File specified with --reporter option - test to see file exists
_(File.exist?("#{outpath}/foo/bar/test.json")).must_equal true
_(File.stat("#{outpath}/foo/bar/test.json").size).must_be :>, 0
# STDOUT true set using config - test to see if this is obeyed
_(stdout).must_include "complete example profile (complete)"
_(stdout).must_include "1 successful control"
_(stdout).must_include "0 control failures"
_(stdout).must_include "0 controls skipped"
_(stderr).must_be_empty
assert_exit_code 0, out
end
end
describe "When specifying a config file and --reporter option to configure reporter with stdout true from both the options" do
let(:cli_args) { "--config " + File.join(config_dir_path, "json-config", "reporter-cli-config.json") + " --reporter json html2" }
let(:run_result) { run_inspec_process("exec " + File.join(profile_path, "basic_profile") + " " + cli_args) }
it "should raise error that only single reporter can have output to stdout" do
_(run_result.stderr).wont_equal ""
_(run_result.stderr).must_include "The option --reporter can only have a single report outputting to stdout."
end
end
describe "when specifying the execution target" do
let(:local_plat) do
json = run_inspec_process("detect --format json", {}).stdout