diff --git a/lib/inspec/base_cli.rb b/lib/inspec/base_cli.rb index 18e792db0..041054f93 100644 --- a/lib/inspec/base_cli.rb +++ b/lib/inspec/base_cli.rb @@ -107,8 +107,10 @@ module Inspec option :reporter, type: :array, banner: 'one two:/output/file/path', desc: 'Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit, yaml' - option :attrs, type: :array, + option :input_file, type: :array, desc: 'Load one or more input files, a YAML file with values for the profile to use' + option :attrs, type: :array, + desc: 'Legacy name for --input-file - deprecated.' option :create_lockfile, type: :boolean, desc: 'Write out a lockfile based on this execution (unless one already exists)' option :backend_cache, type: :boolean, diff --git a/lib/inspec/objects/input.rb b/lib/inspec/objects/input.rb index 50c26adc4..eac094c4c 100644 --- a/lib/inspec/objects/input.rb +++ b/lib/inspec/objects/input.rb @@ -23,8 +23,8 @@ module Inspec # output warn message if we are in a exec call Inspec::Log.warn( - "Attribute '#{@name}' does not have a value. "\ - "Use --attrs to provide a value for '#{@name}' or specify a "\ + "Input '#{@name}' does not have a value. "\ + "Use --input-file to provide a value for '#{@name}' or specify a "\ "value with `attribute('#{@name}', value: 'somevalue', ...)`.", ) if Inspec::BaseCLI.inspec_cli_command == :exec end diff --git a/lib/inspec/runner.rb b/lib/inspec/runner.rb index 462e84b73..636f971c6 100644 --- a/lib/inspec/runner.rb +++ b/lib/inspec/runner.rb @@ -151,10 +151,14 @@ module Inspec # determine all inputs before the execution, fetch data from secrets backend def load_inputs(options) - # TODO: - rename :attributes and :attrs - these are both user-visible + # TODO: - rename :attributes - it is user-visible options[:attributes] ||= {} - secrets_targets = options[:attrs] + if options.key?(:attrs) + Inspec.deprecate(:rename_attributes_to_inputs, 'Use --input-file on the command line instead of --attrs.') + options[:input_file] = options.delete(:attrs) + end + secrets_targets = options[:input_file] return options[:attributes] if secrets_targets.nil? secrets_targets.each do |target| diff --git a/test/functional/inheritance_test.rb b/test/functional/inheritance_test.rb index e8f6de3f0..3355274ea 100644 --- a/test/functional/inheritance_test.rb +++ b/test/functional/inheritance_test.rb @@ -68,7 +68,7 @@ describe 'example inheritance profile' do end it 'can execute a profile inheritance' do - out = inspec('exec ' + path + ' --reporter json --no-create-lockfile --attrs ' + input_file) + out = inspec('exec ' + path + ' --reporter json --no-create-lockfile --input-file ' + input_file) out.stderr.must_equal '' out.exit_status.must_equal 101 JSON.load(out.stdout).must_be_kind_of Hash diff --git a/test/functional/inputs_test.rb b/test/functional/inputs_test.rb index c49060d98..d9c938022 100644 --- a/test/functional/inputs_test.rb +++ b/test/functional/inputs_test.rb @@ -13,7 +13,7 @@ describe 'inputs' do cmd = 'exec ' cmd += File.join(inputs_profiles_path, 'basic') cmd += ' --no-create-lockfile' - cmd += ' --attrs ' + File.join(inputs_profiles_path, 'basic', 'files', "#{input_file}.yaml") + cmd += ' --input-file ' + File.join(inputs_profiles_path, 'basic', 'files', "#{input_file}.yaml") cmd += ' --controls ' + input_file out = inspec(cmd) out.stderr.must_equal '' @@ -21,12 +21,49 @@ describe 'inputs' do end end + describe 'when asking for usage help' do + it 'includes the new --input-file option' do + result = run_inspec_process('exec help', lock: true) # --no-create-lockfile option breaks usage help + lines = result.stdout.split("\n") + line = lines.detect { |l| l.include? '--input-file' } + line.wont_be_nil + end + it 'includes the legacy --attrs option' do + result = run_inspec_process('exec help', lock: true) + lines = result.stdout.split("\n") + line = lines.detect { |l| l.include? '--attrs' } + line.wont_be_nil + end + end + + describe 'when using a cli-specified file' do + let(:result) do + cmd = 'exec ' + cmd += File.join(inputs_profiles_path, 'basic') + ' ' + cmd += flag + ' ' + File.join(inputs_profiles_path, 'basic', 'files', 'flat.yaml') + cmd += ' --controls flat' + run_inspec_process(cmd) + end + describe 'when the --input-file flag is used' do + let(:flag) { '--input-file' } + it 'works' do + result.exit_status.must_equal 0 + end + end + describe 'when the --attrs flag is used' do + let(:flag) { '--attrs' } + it 'works' do + result.exit_status.must_equal 0 + end + end + end + describe 'run profile with yaml inputs' do it "runs using yml inputs" do cmd = 'exec ' cmd += File.join(inputs_profiles_path, 'global') cmd += ' --no-create-lockfile' - cmd += ' --attrs ' + File.join(inputs_profiles_path, 'global', 'files', "inputs.yml") + cmd += ' --input-file ' + File.join(inputs_profiles_path, 'global', 'files', "inputs.yml") out = inspec(cmd) out.stderr.must_equal '' # TODO: fix attribute inheritance override test diff --git a/test/functional/inspec_exec_test.rb b/test/functional/inspec_exec_test.rb index 8639666c0..bc2b39610 100644 --- a/test/functional/inspec_exec_test.rb +++ b/test/functional/inspec_exec_test.rb @@ -98,7 +98,7 @@ Test Summary: 0 successful, 0 failures, 0 skipped end it "executes a profile and reads inputs" do - out = inspec("exec #{File.join(examples_path, 'profile-attribute')} --no-create-lockfile --attrs #{File.join(examples_path, "profile-attribute.yml")}") + out = inspec("exec #{File.join(examples_path, 'profile-attribute')} --no-create-lockfile --input-file #{File.join(examples_path, "profile-attribute.yml")}") out.stderr.must_equal '' out.exit_status.must_equal 0 out.stdout.force_encoding(Encoding::UTF_8).must_include "Test Summary: \e[38;5;41m2 successful\e[0m, 0 failures, 0 skipped" diff --git a/test/unit/runner_test.rb b/test/unit/runner_test.rb index 579d8fa53..3ae3fa952 100644 --- a/test/unit/runner_test.rb +++ b/test/unit/runner_test.rb @@ -65,34 +65,34 @@ describe Inspec::Runner do end end - describe 'when no attrs are specified' do + describe 'when no input files are specified' do it 'returns an empty hash' do options = {} runner.load_inputs(options).must_equal({}) end end - describe 'when an attr is provided and does not resolve' do + describe 'when an input file is provided and does not resolve' do it 'raises an exception' do - options = { attrs: ['nope.jpg'] } + options = { input_file: ['nope.jpg'] } Inspec::SecretsBackend.expects(:resolve).with('nope.jpg').returns(nil) proc { runner.load_inputs(options) }.must_raise Inspec::Exceptions::SecretsBackendNotFound end end - describe 'when an attr is provided and has no inputs' do + describe 'when an input file is provided and has no inputs' do it 'returns an empty hash' do secrets = mock secrets.stubs(:inputs).returns(nil) - options = { attrs: ['empty.yaml'] } + options = { input_file: ['empty.yaml'] } Inspec::SecretsBackend.expects(:resolve).with('empty.yaml').returns(secrets) runner.load_inputs(options).must_equal({}) end end - describe 'when an attr is provided and has inputs' do + describe 'when an input file is provided and has inputs' do it 'returns a hash containing the inputs' do - options = { attrs: ['file1.yaml'] } + options = { input_file: ['file1.yaml'] } inputs = { foo: 'bar' } secrets = mock secrets.stubs(:inputs).returns(inputs) @@ -101,9 +101,9 @@ describe Inspec::Runner do end end - describe 'when multiple attrs are provided and one fails' do + describe 'when multiple input files are provided and one fails' do it 'raises an exception' do - options = { attrs: ['file1.yaml', 'file2.yaml'] } + options = { input_file: ['file1.yaml', 'file2.yaml'] } secrets = mock secrets.stubs(:inputs).returns(nil) Inspec::SecretsBackend.expects(:resolve).with('file1.yaml').returns(secrets) @@ -112,9 +112,9 @@ describe Inspec::Runner do end end - describe 'when multiple attrs are provided and one has no inputs' do + describe 'when multiple input files are provided and one has no inputs' do it 'returns a hash containing the inputs from the valid files' do - options = { attrs: ['file1.yaml', 'file2.yaml'] } + options = { input_file: ['file1.yaml', 'file2.yaml'] } inputs = { foo: 'bar' } secrets1 = mock secrets1.stubs(:inputs).returns(nil) @@ -126,9 +126,9 @@ describe Inspec::Runner do end end - describe 'when multiple attrs are provided and all have inputs' do + describe 'when multiple input files are provided and all have inputs' do it 'returns a hash containing all the inputs' do - options = { attrs: ['file1.yaml', 'file2.yaml'] } + options = { input_file: ['file1.yaml', 'file2.yaml'] } secrets1 = mock secrets1.stubs(:inputs).returns({ key1: 'value1' }) secrets2 = mock