mirror of
https://github.com/inspec/inspec
synced 2025-02-16 22:18:38 +00:00
Get unit and functional tests passing
Signed-off-by: Clinton Wolfe <clintoncwolfe@gmail.com>
This commit is contained in:
parent
502cf1d7b9
commit
7d2028287c
28 changed files with 235 additions and 349 deletions
|
@ -26,8 +26,23 @@ module Inspec
|
|||
with_resource_dsl resources_dsl
|
||||
|
||||
# allow attributes to be accessed within control blocks
|
||||
define_method :attribute do |name|
|
||||
Inspec::InputRegistry.find_input(name, profile_id).value
|
||||
# TODO: deprecate name, use input()
|
||||
define_method :attribute do |input_name, options = {}|
|
||||
if options.empty?
|
||||
# Simply an access, no event here
|
||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id).value
|
||||
else
|
||||
options[:priority] = 20
|
||||
options[:provider] = :inline_control_code
|
||||
evt = Inspec::Input.infer_event(options)
|
||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_name, event: evt).value
|
||||
end
|
||||
end
|
||||
|
||||
# Find the Input object, but don't collapse to a value.
|
||||
# Will return nil on a miss.
|
||||
define_method :input_object do |input_name|
|
||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id)
|
||||
end
|
||||
|
||||
# Support for Control DSL plugins.
|
||||
|
@ -169,14 +184,24 @@ module Inspec
|
|||
|
||||
# method for inputs; import input handling
|
||||
# TODO: deprecate name, use input()
|
||||
define_method :attribute do |name, options = nil|
|
||||
if options.nil?
|
||||
Inspec::InputRegistry.find_input(name, profile_id).value
|
||||
define_method :attribute do |input_name, options = {}|
|
||||
if options.empty?
|
||||
# Simply an access, no event here
|
||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id).value
|
||||
else
|
||||
Inspec::InputRegistry.register_input(name, profile_id, options).value
|
||||
options[:priority] = 20
|
||||
options[:provider] = :inline_control_code
|
||||
evt = Inspec::Input.infer_event(options)
|
||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_name, event: evt).value
|
||||
end
|
||||
end
|
||||
|
||||
# Find the Input object, but don't collapse to a value.
|
||||
# Will return nil on a miss.
|
||||
define_method :input_object do |input_name|
|
||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id)
|
||||
end
|
||||
|
||||
define_method :skip_control do |id|
|
||||
profile_context_owner.unregister_rule(id)
|
||||
end
|
||||
|
|
|
@ -118,6 +118,7 @@ module Inspec
|
|||
return @profile unless @profile.nil?
|
||||
opts = @opts.dup
|
||||
opts[:backend] = @backend
|
||||
opts[:runner_conf] = Inspec::Config.cached
|
||||
if !@dependencies.nil? && !@dependencies.empty?
|
||||
opts[:dependencies] = Inspec::DependencySet.from_array(@dependencies, @cwd, @cache, @backend)
|
||||
end
|
||||
|
|
|
@ -23,6 +23,7 @@ module Inspec
|
|||
# implementation of the fetcher being used.
|
||||
#
|
||||
class Resolver
|
||||
# Here deps is an Array of Hashes
|
||||
def self.resolve(dependencies, cache, working_dir, backend)
|
||||
reqs = dependencies.map do |dep|
|
||||
req = Inspec::Requirement.from_metadata(dep, cache, cwd: working_dir, backend: backend)
|
||||
|
@ -47,6 +48,7 @@ module Inspec
|
|||
end
|
||||
end
|
||||
|
||||
# Here deps is an Array of Inspec::Requirement
|
||||
def resolve(deps, top_level = true, seen_items = {}, path_string = '') # rubocop:disable Metrics/AbcSize
|
||||
graph = {}
|
||||
if top_level
|
||||
|
|
|
@ -79,7 +79,7 @@ module Inspec::DSL
|
|||
|
||||
def self.filter_included_controls(context, profile, &block)
|
||||
mock = Inspec::Backend.create(Inspec::Config.mock)
|
||||
include_ctx = Inspec::ProfileContext.for_profile(profile, mock, {})
|
||||
include_ctx = Inspec::ProfileContext.for_profile(profile, mock)
|
||||
include_ctx.load(block) if block_given?
|
||||
# remove all rules that were not registered
|
||||
context.all_rules.each do |r|
|
||||
|
|
|
@ -12,11 +12,12 @@ module Inspec
|
|||
include Singleton
|
||||
extend Forwardable
|
||||
|
||||
attr_reader :inputs_by_profile
|
||||
attr_reader :inputs_by_profile, :profile_aliases
|
||||
def_delegator :inputs_by_profile, :each
|
||||
def_delegator :inputs_by_profile, :[]
|
||||
def_delegator :inputs_by_profile, :key?, :profile_known?
|
||||
def_delegator :inputs_by_profile, :select
|
||||
def_delegator :profile_aliases, :key?, :profile_alias?
|
||||
|
||||
def initialize
|
||||
# Keyed on String profile_name => Hash of String input_name => Input object
|
||||
|
@ -43,35 +44,44 @@ module Inspec
|
|||
# Support for Individual Inputs
|
||||
#-------------------------------------------------------------#
|
||||
|
||||
def find_input(name, profile)
|
||||
profile = @profile_aliases[profile] if !profile_known?(profile) && @profile_aliases[profile]
|
||||
unless profile_known?(profile)
|
||||
error = Inspec::InputRegistry::ProfileLookupError.new
|
||||
error.profile_name = profile
|
||||
raise error, "Profile '#{error.profile_name}' does not have any inputs"
|
||||
def find_or_register_input(input_name, profile_name, options = {})
|
||||
if profile_alias?(profile_name)
|
||||
alias_name = profile_name
|
||||
profile_name = profile_aliases[profile_name]
|
||||
handle_late_arriving_alias(alias_name, profile_name) if profile_known?(alias_name)
|
||||
end
|
||||
|
||||
unless inputs_by_profile[profile].key?(name)
|
||||
error = Inspec::InputRegistry::InputLookupError.new
|
||||
error.input_name = name
|
||||
error.profile_name = profile
|
||||
raise error, "Profile '#{error.profile_name}' does not have an input with name '#{error.input_name}'"
|
||||
end
|
||||
inputs_by_profile[profile][name]
|
||||
end
|
||||
|
||||
def register_input(input_name, profile_name, options = {})
|
||||
if profile_known?(profile_name) && inputs_by_profile[profile_name][input_name] && options.empty?
|
||||
# Just accessing the input - then why did they call register???
|
||||
# TODO: handle the "declaration" case better
|
||||
inputs_by_profile[profile_name][input_name]
|
||||
inputs_by_profile[profile_name] ||= {}
|
||||
if inputs_by_profile[profile_name].key?(input_name)
|
||||
inputs_by_profile[profile_name][input_name].update(options)
|
||||
else
|
||||
inputs_by_profile[profile_name] = {} unless profile_known?(profile_name)
|
||||
# BUG: This a clobbering operation, regardless of precendence!
|
||||
inputs_by_profile[profile_name][input_name] = Inspec::Input.new(input_name, options)
|
||||
end
|
||||
|
||||
inputs_by_profile[profile_name][input_name]
|
||||
end
|
||||
|
||||
# It is possible for a wrapper profile to create an input in metadata,
|
||||
# referring to the child profile by an alias that has not yet been registered.
|
||||
# The registry will then store the inputs under the alias, as if the alias
|
||||
# were a true profile.
|
||||
# If that happens and the child profile also mentions the input, we will
|
||||
# need to move some things - all inputs should be stored under the true
|
||||
# profile name, and no inputs should be stored under the alias.
|
||||
def handle_late_arriving_alias(alias_name, profile_name)
|
||||
inputs_by_profile[profile_name] ||= {}
|
||||
inputs_by_profile[alias_name].each do |input_name, input_from_alias|
|
||||
# Move the inpuut, or if it exists, merge events
|
||||
existing = inputs_by_profile[profile_name][input_name]
|
||||
if existing
|
||||
existing.events.concat(input_from_alias.events)
|
||||
else
|
||||
inputs_by_profile[profile_name][input_name] = input_from_alias
|
||||
end
|
||||
end
|
||||
# Finally, delete the (now copied-out) entry for the alias
|
||||
inputs_by_profile.delete(alias_name)
|
||||
end
|
||||
#-------------------------------------------------------------#
|
||||
# Support for Binding Inputs
|
||||
#-------------------------------------------------------------#
|
||||
|
@ -84,7 +94,7 @@ module Inspec
|
|||
# In a more perfect world, we could let the core plugins choose
|
||||
# self-determine what to do; but as-is, the APIs that call this
|
||||
# are a bit over-constrained.
|
||||
bind_inputs_from_metadata(profile_name, sources[:metadata])
|
||||
bind_inputs_from_metadata(profile_name, sources[:profile_metadata])
|
||||
bind_inputs_from_input_files(profile_name, sources[:cli_input_files])
|
||||
bind_inputs_from_runner_api(profile_name, sources[:runner_api])
|
||||
end
|
||||
|
@ -99,8 +109,15 @@ module Inspec
|
|||
|
||||
# These arrive as a bare hash - values are raw values, not options
|
||||
input_hash.each do |input_name, input_value|
|
||||
input_options = { value: input_value }
|
||||
register_input(input_name, profile_name, input_options)
|
||||
loc = Inspec::Input::Event.probe_stack # TODO: likely modify this to look for a kitchen.yml, if that is realistic
|
||||
evt = Inspec::Input::Event.new(
|
||||
value: input_value,
|
||||
provider: :runner_api, # TODO: suss out if audit cookbook or kitchen-inspec or something unknown
|
||||
priority: 40,
|
||||
file: loc.path,
|
||||
line: loc.lineno,
|
||||
)
|
||||
find_or_register_input(input_name, profile_name, event: evt)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -123,8 +140,14 @@ module Inspec
|
|||
|
||||
next if data.inputs.nil?
|
||||
data.inputs.each do |input_name, input_value|
|
||||
input_options = { value: input_value }
|
||||
register_input(input_name, profile_name, input_options)
|
||||
evt = Inspec::Input::Event.new(
|
||||
value: input_value,
|
||||
provider: :cli_files,
|
||||
priority: 40,
|
||||
file: path,
|
||||
# TODO: any way we could get a line number?
|
||||
)
|
||||
find_or_register_input(input_name, profile_name, event: evt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -151,10 +174,23 @@ module Inspec
|
|||
return if profile_metadata_obj.nil? # Metadata files are technically optional
|
||||
|
||||
if profile_metadata_obj.params.key?(:attributes) && profile_metadata_obj.params[:attributes].is_a?(Array)
|
||||
profile_metadata_obj.params[:attributes].each do |input|
|
||||
input_options = input.dup
|
||||
profile_metadata_obj.params[:attributes].each do |input_orig|
|
||||
input_options = input_orig.dup
|
||||
input_name = input_options.delete(:name)
|
||||
register_input(input_name, profile_name, input_options)
|
||||
input_options.merge!({ priority: 30, provider: :profile_metadata, file: File.join(profile_name, 'inspec.yml') })
|
||||
evt = Inspec::Input.infer_event(input_options)
|
||||
|
||||
# Profile metadata may set inputs in other profiles by naming them.
|
||||
if input_options[:profile]
|
||||
profile_name = input_options[:profile] || profile_name
|
||||
# Override priority to force this to win. Allow user to set their own priority.
|
||||
evt.priority = input_orig[:priority] || 35
|
||||
end
|
||||
find_or_register_input(input_name,
|
||||
profile_name,
|
||||
type: input_options[:type],
|
||||
required: input_options[:required],
|
||||
event: evt)
|
||||
end
|
||||
elsif profile_metadata_obj.params.key?(:attributes)
|
||||
Inspec::Log.warn 'Inputs must be defined as an Array. Skipping current definition.'
|
||||
|
@ -175,8 +211,7 @@ module Inspec
|
|||
# These class methods are convenience methods so you don't always
|
||||
# have to call #instance when calling the registry
|
||||
[
|
||||
:find_input,
|
||||
:register_input,
|
||||
:find_or_register_input,
|
||||
:register_profile_alias,
|
||||
:list_inputs_for_profile,
|
||||
:bind_profile_inputs,
|
||||
|
|
|
@ -70,6 +70,12 @@ module Inspec
|
|||
hash[prop] = send(prop)
|
||||
end
|
||||
end
|
||||
|
||||
def self.probe_stack
|
||||
frames = caller_locations(2, 40)
|
||||
frames.reject! { |f| f.path && f.path.include?('/lib/inspec/') }
|
||||
frames.first
|
||||
end
|
||||
end
|
||||
|
||||
#===========================================================================#
|
||||
|
@ -197,7 +203,7 @@ module Inspec
|
|||
Inspec::Log.warn "Do not provide both an Event and a value as an option to attribute('#{name}') - using value from event"
|
||||
end
|
||||
else
|
||||
infer_event(options) # Sets options[:event]
|
||||
self.class.infer_event(options) # Sets options[:event]
|
||||
end
|
||||
end
|
||||
events << options[:event] if options.key? :event
|
||||
|
@ -205,44 +211,17 @@ module Inspec
|
|||
enforce_type_restriction!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _update_set_metadata(options)
|
||||
# Basic metadata
|
||||
@title = options[:title] if options.key?(:title)
|
||||
@description = options[:description] if options.key?(:description)
|
||||
@required = options[:required] if options.key?(:required)
|
||||
@identifier = options[:identifier] if options.key?(:identifier) # TODO: determine if this is ever used
|
||||
@type = options[:type] if options.key?(:type)
|
||||
end
|
||||
|
||||
def make_creation_event(options)
|
||||
loc = options[:location] || probe_stack
|
||||
Input::Event.new(
|
||||
action: :create,
|
||||
provider: options[:provider],
|
||||
file: loc.path,
|
||||
line: loc.lineno,
|
||||
)
|
||||
end
|
||||
|
||||
def probe_stack
|
||||
frames = caller_locations(2, 40)
|
||||
frames.reject! { |f| f.path && f.path.include?('/lib/inspec/') }
|
||||
frames.first
|
||||
end
|
||||
|
||||
# We can determine a value:
|
||||
# 1. By event.value (preferred)
|
||||
# 2. By options[:value]
|
||||
# 3. By options[:default] (deprecated)
|
||||
def infer_event(options)
|
||||
def self.infer_event(options)
|
||||
# Don't rely on this working; you really should be passing a proper Input::Event
|
||||
# with the context information you have.
|
||||
location = probe_stack
|
||||
location = Input::Event.probe_stack
|
||||
event = Input::Event.new(
|
||||
action: :set,
|
||||
provider: :unknown,
|
||||
provider: options[:provider] || :unknown,
|
||||
priority: options[:priority] || Inspec::Input::DEFAULT_PRIORITY_FOR_UNKNOWN_CALLER,
|
||||
file: location.path,
|
||||
line: location.lineno,
|
||||
|
@ -261,6 +240,27 @@ module Inspec
|
|||
options[:event] = event
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _update_set_metadata(options)
|
||||
# Basic metadata
|
||||
@title = options[:title] if options.key?(:title)
|
||||
@description = options[:description] if options.key?(:description)
|
||||
@required = options[:required] if options.key?(:required)
|
||||
@identifier = options[:identifier] if options.key?(:identifier) # TODO: determine if this is ever used
|
||||
@type = options[:type] if options.key?(:type)
|
||||
end
|
||||
|
||||
def make_creation_event(options)
|
||||
loc = options[:location] || Event.probe_stack
|
||||
Input::Event.new(
|
||||
action: :create,
|
||||
provider: options[:provider],
|
||||
file: loc.path,
|
||||
line: loc.lineno,
|
||||
)
|
||||
end
|
||||
|
||||
# Determine the current winning value, but don't validate it
|
||||
def current_value
|
||||
# Examine the events to determine highest-priority value. Tie-break
|
||||
|
@ -282,7 +282,7 @@ module Inspec
|
|||
|
||||
def value=(new_value, priority = DEFAULT_PRIORITY_FOR_VALUE_SET)
|
||||
# Inject a new Event with the new value.
|
||||
location = probe_stack
|
||||
location = Event.probe_stack
|
||||
events << Event.new(
|
||||
action: :set,
|
||||
provider: :value_setter,
|
||||
|
|
|
@ -121,14 +121,15 @@ module Inspec
|
|||
# The AttributeRegistry is in charge of keeping track of inputs;
|
||||
# it is the single source of truth. Now that we have a profile object,
|
||||
# we can create any inputs that were provided by various mechanisms.
|
||||
options[:runner_conf] ||= Inspec::Config.cached
|
||||
Inspec::InputRegistry.bind_profile_inputs(
|
||||
# Every input only exists in the context of a profile
|
||||
metadata.params[:name], # TODO: test this with profile aliasing
|
||||
# Remaining args are possible sources of inputs
|
||||
# TODO: deprecation checks throughout
|
||||
cli_input_files: options[:runner_conf].final_options[:attrs], # From --attrs
|
||||
cli_input_files: options[:runner_conf][:attrs], # From --attrs
|
||||
profile_metadata: metadata,
|
||||
runner_api: options[:runner_conf].final_options[:attributes], # This is the route the audit_cookbook and kitchen-inspec take
|
||||
runner_api: options[:runner_conf][:attributes], # This is the route the audit_cookbook and kitchen-inspec take
|
||||
)
|
||||
|
||||
@runner_context =
|
||||
|
|
|
@ -66,9 +66,13 @@ end
|
|||
class RSpec::Core::ExampleGroup
|
||||
# This DSL method allows us to access the values of inputs within InSpec tests
|
||||
def attribute(name)
|
||||
Inspec::InputRegistry.find_input(name, self.class.metadata[:profile_id]).value
|
||||
Inspec::InputRegistry.find_or_register_input(name, self.class.metadata[:profile_id]).value
|
||||
end
|
||||
define_example_method :attribute
|
||||
def input_obj(name)
|
||||
Inspec::InputRegistry.find_or_register_input(name, self.class.metadata[:profile_id])
|
||||
end
|
||||
define_example_method :input_obj
|
||||
|
||||
# Here, we have to ensure our method_missing gets called prior
|
||||
# to RSpec::Core::ExampleGroup.method_missing (the class method).
|
||||
|
|
|
@ -5,9 +5,12 @@ require 'functional/helper'
|
|||
describe 'inputs' do
|
||||
include FunctionalHelper
|
||||
let(:inputs_profiles_path) { File.join(profile_path, 'inputs') }
|
||||
|
||||
# This tests being able to load complex structures from
|
||||
# cli option-specified files.
|
||||
[
|
||||
'flat',
|
||||
#'nested',
|
||||
'nested',
|
||||
].each do |input_file|
|
||||
it "runs OK on #{input_file} inputs" do
|
||||
cmd = 'exec '
|
||||
|
@ -58,28 +61,21 @@ describe 'inputs' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'run profile with yaml inputs' do
|
||||
it "runs using yml inputs" do
|
||||
describe 'when accessing inputs in a variety of scopes' do
|
||||
it "is able to read the inputs" do
|
||||
cmd = 'exec '
|
||||
cmd += File.join(inputs_profiles_path, 'global')
|
||||
cmd += ' --no-create-lockfile'
|
||||
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
|
||||
# we have one failing case on this - run manually to see
|
||||
# For now, reduce cases to 20; we'll be reworking all this soon anyway
|
||||
# result.stdout.must_include '21 successful'
|
||||
# result.exit_status.must_equal 0
|
||||
|
||||
result.stdout.must_include '20 successful' # and one failing
|
||||
cmd += File.join(inputs_profiles_path, 'scoping')
|
||||
result = run_inspec_process(cmd, json: true)
|
||||
result.must_have_all_controls_passing
|
||||
end
|
||||
end
|
||||
|
||||
describe 'run profile with metadata inputs' do
|
||||
it "does not error when inputs are empty" do
|
||||
cmd = 'exec '
|
||||
cmd += File.join(inputs_profiles_path, 'metadata-empty')
|
||||
result = run_inspec_process(cmd, json: true)
|
||||
result.stdout.must_include 'WARN: Inputs must be defined as an Array. Skipping current definition.'
|
||||
result.stderr.must_include 'WARN: Inputs must be defined as an Array. Skipping current definition.'
|
||||
result.exit_status.must_equal 0
|
||||
end
|
||||
|
||||
|
@ -88,19 +84,26 @@ describe 'inputs' do
|
|||
cmd += File.join(inputs_profiles_path, 'metadata-invalid')
|
||||
result = run_inspec_process(cmd, json: true)
|
||||
result.stderr.must_equal "Type 'Color' is not a valid input type.\n"
|
||||
result.stdout.must_equal ''
|
||||
result.exit_status.must_equal 1
|
||||
end
|
||||
|
||||
it "errors with required input not defined" do
|
||||
cmd = 'exec '
|
||||
cmd += File.join(inputs_profiles_path, 'required')
|
||||
cmd += File.join(inputs_profiles_path, 'metadata-required')
|
||||
result = run_inspec_process(cmd, json: true)
|
||||
result.stderr.must_equal "Input 'username' is required and does not have a value.\n"
|
||||
result.stdout.must_equal ''
|
||||
result.stderr.must_include "Input 'a_required_input' is required and does not have a value.\n"
|
||||
result.exit_status.must_equal 1
|
||||
end
|
||||
|
||||
# TODO - add test for backwards compatibility using 'attribute' in DSL
|
||||
describe 'when profile inheritance is used' do
|
||||
it 'should correctly assign input values using namespacing' do
|
||||
cmd = 'exec ' + File.join(inputs_profiles_path, 'inheritance', 'wrapper')
|
||||
result = run_inspec_process(cmd, json: true)
|
||||
result.must_have_all_controls_passing
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# # TODO - add test for backwards compatibility using 'attribute' in DSL
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,60 +13,48 @@ describe Inspec::InputRegistry do
|
|||
|
||||
describe 'creating a profile input' do
|
||||
it 'creates an input without options' do
|
||||
registry.register_input('test_input', 'dummy_profile')
|
||||
# confirm we get the dummy default
|
||||
registry.find_input('test_input', 'dummy_profile').value.class.must_equal Inspec::Input::NO_VALUE_SET
|
||||
registry.find_or_register_input('test_input', 'dummy_profile')
|
||||
# confirm we get the dummy value
|
||||
registry.find_or_register_input('test_input', 'dummy_profile').value.class.must_equal Inspec::Input::NO_VALUE_SET
|
||||
end
|
||||
|
||||
it 'creates an input with a default value' do
|
||||
registry.register_input('color', 'dummy_profile', default: 'silver')
|
||||
registry.find_input('color', 'dummy_profile').value.must_equal 'silver'
|
||||
it 'creates an input with a value' do
|
||||
registry.find_or_register_input('color', 'dummy_profile', value: 'silver')
|
||||
registry.find_or_register_input('color', 'dummy_profile').value.must_equal 'silver'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'creating a profile with a name alias' do
|
||||
it 'creates a default input on a profile with an alias' do
|
||||
it 'creates a value input on a profile with an alias' do
|
||||
registry.register_profile_alias('old_profile', 'new_profile')
|
||||
registry.register_input('color', 'new_profile', default: 'blue')
|
||||
registry.find_input('color', 'new_profile').value.must_equal 'blue'
|
||||
registry.find_input('color', 'old_profile').value.must_equal 'blue'
|
||||
registry.find_or_register_input('color', 'new_profile', value: 'blue')
|
||||
registry.find_or_register_input('color', 'new_profile').value.must_equal 'blue'
|
||||
registry.find_or_register_input('color', 'old_profile').value.must_equal 'blue'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'creating a profile and select it' do
|
||||
it 'creates a profile with inputs' do
|
||||
registry.register_input('color', 'dummy_profile', default: 'silver')
|
||||
registry.register_input('color2', 'dummy_profile', default: 'blue')
|
||||
registry.register_input('color3', 'dummy_profile', default: 'green')
|
||||
registry.find_or_register_input('color', 'dummy_profile', value: 'silver')
|
||||
registry.find_or_register_input('color2', 'dummy_profile', value: 'blue')
|
||||
registry.find_or_register_input('color3', 'dummy_profile', value: 'green')
|
||||
registry.list_inputs_for_profile('dummy_profile').size.must_equal 3
|
||||
end
|
||||
end
|
||||
|
||||
describe 'validate the correct objects are getting created' do
|
||||
it 'creates a profile with inputs' do
|
||||
registry.register_input('color', 'dummy_profile', default: 'silver').class.must_equal Inspec::Input
|
||||
registry.find_or_register_input('color', 'dummy_profile', value: 'silver').class.must_equal Inspec::Input
|
||||
registry.list_inputs_for_profile('dummy_profile').size.must_equal 1
|
||||
end
|
||||
end
|
||||
|
||||
describe 'validate find_input method' do
|
||||
describe 'validate find_or_register_input method' do
|
||||
it 'find an input which exist' do
|
||||
input = registry.register_input('color', 'dummy_profile')
|
||||
input = registry.find_or_register_input('color', 'dummy_profile')
|
||||
input.value = 'black'
|
||||
|
||||
registry.find_input('color', 'dummy_profile').value.must_equal 'black'
|
||||
end
|
||||
|
||||
it 'errors when trying to find an input on an unknown profile' do
|
||||
input = registry.register_input('color', 'dummy_profile')
|
||||
ex = assert_raises(Inspec::InputRegistry::ProfileLookupError) { registry.find_input('color', 'unknown_profile') }
|
||||
ex.message.must_match "Profile 'unknown_profile' does not have any inputs"
|
||||
end
|
||||
|
||||
it 'errors when trying to find an unknown input on a known profile' do
|
||||
input = registry.register_input('color', 'dummy_profile')
|
||||
ex = assert_raises(Inspec::InputRegistry::InputLookupError) { registry.find_input('unknown_input', 'dummy_profile') }
|
||||
ex.message.must_match "Profile 'dummy_profile' does not have an input with name 'unknown_input'"
|
||||
registry.find_or_register_input('color', 'dummy_profile').value.must_equal 'black'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ tests = expecteds.keys.map do |test_name|
|
|||
name: test_name,
|
||||
expected: expecteds[test_name],
|
||||
input_via_string: attribute(test_name.to_s, value: "#{test_name}_default"),
|
||||
input_via_symbol: attribute(test_name, value: "#{test_name}_default"),
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
describe 'test the val_string input set in the global inspec.yml' do
|
||||
subject { attribute('val_string') }
|
||||
it { should cmp 'test-attr' }
|
||||
end
|
||||
|
||||
describe 'test the val_numeric input set in the global inspec.yml' do
|
||||
subject { attribute('val_numeric') }
|
||||
it { should cmp 443 }
|
||||
end
|
||||
|
||||
describe 'test the val_boolean input set in the global inspec.yml' do
|
||||
subject { attribute('val_boolean') }
|
||||
it { should cmp true }
|
||||
end
|
||||
|
||||
describe 'test the val_regex input set in the global inspec.yml' do
|
||||
subject { attribute('val_regex') }
|
||||
it { should cmp '/^\d*/'}
|
||||
end
|
||||
|
||||
describe 'test the val_array input set in the global inspec.yml' do
|
||||
subject { attribute('val_array') }
|
||||
check_array = [ 'a', 'b', 'c' ]
|
||||
it { should cmp check_array }
|
||||
end
|
||||
|
||||
describe 'test the val_hash input set in the global inspec.yml' do
|
||||
subject { attribute('val_hash') }
|
||||
check_hash = { a: true, b: false, c: '123' }
|
||||
it { should cmp check_hash }
|
||||
end
|
||||
|
||||
describe 'test input when no default or value is set' do
|
||||
subject { attribute('val_no_default').respond_to?(:fake_method) }
|
||||
it { should cmp true }
|
||||
end
|
||||
|
||||
describe 'test input with no defualt but has type' do
|
||||
subject { attribute('val_no_default_with_type').respond_to?(:fake_method) }
|
||||
it { should cmp true }
|
||||
end
|
||||
|
||||
empty_hash_input = attribute('val_with_empty_hash_default', {})
|
||||
describe 'test input with default as empty hash' do
|
||||
subject { empty_hash_input }
|
||||
it { should cmp 'success' }
|
||||
end
|
|
@ -1,15 +0,0 @@
|
|||
include_controls 'child_profile_NEW_NAME'
|
||||
|
||||
include_controls 'child_profile2' do
|
||||
control 'test override control on parent using child attribute' do
|
||||
describe attribute('val_numeric') do
|
||||
it { should cmp 654321 }
|
||||
end
|
||||
end
|
||||
|
||||
control 'test override control on parent using parent attribute' do
|
||||
describe Inspec::InputRegistry.find_input('val_numeric', 'inputs').value do
|
||||
it { should cmp 443 }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
control 'test using the val_numeric_override with a default in the inspec.yml overridden by the secrets file' do
|
||||
desc 'test the val_numeric_override attr'
|
||||
describe attribute('val_numeric_override') do
|
||||
it { should cmp 9999 }
|
||||
end
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
val_user = attribute('val_user', default: 'alice', description: 'An identification for the user')
|
||||
val_user_override = attribute('val_user_override', default: 'alice', description: 'An identification for the user')
|
||||
|
||||
describe 'reading an input in a file-level definition with a default value' do
|
||||
subject { val_user }
|
||||
it { should cmp 'alice' }
|
||||
end
|
||||
|
||||
describe 'reading an input in a file-level definition with a default value and a value in secrets file' do
|
||||
subject { val_user_override }
|
||||
it { should cmp 'bob' }
|
||||
end
|
||||
|
||||
control 'test using an input inside a control block as the describe subject' do
|
||||
desc 'test the val_numeric attr'
|
||||
describe attribute('val_user') do
|
||||
it { should cmp 'alice' }
|
||||
end
|
||||
end
|
||||
|
||||
# test using a input outside controls and as the describe subject
|
||||
describe attribute('val_user') do
|
||||
it { should cmp 'alice' }
|
||||
end
|
||||
|
||||
control "test using inputs in the test it's block" do
|
||||
describe 'alice' do
|
||||
it { should cmp attribute('val_user') }
|
||||
end
|
||||
end
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
val_user_override: bob
|
||||
val_numeric_override: 9999
|
||||
val_with_empty_hash_default: 'success'
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
lockfile_version: 1
|
||||
depends:
|
||||
- name: child_profile_NEW_NAME
|
||||
resolved_source:
|
||||
url: https://example.com/child_profile.tar.gz
|
||||
sha256: e39eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477
|
||||
version_constraints: ">= 0"
|
||||
- name: child_profile2
|
||||
resolved_source:
|
||||
url: https://example.com/child_profile2.tar.gz
|
||||
sha256: f24eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477
|
||||
version_constraints: ">= 0"
|
|
@ -1,43 +0,0 @@
|
|||
name: global-inputs
|
||||
title: Profile to test inputs in a variety of locations
|
||||
maintainer: The Authors
|
||||
copyright: The Authors
|
||||
copyright_email: you@example.com
|
||||
license: Apache-2.0
|
||||
summary: An InSpec Compliance Profile
|
||||
version: 0.1.0
|
||||
depends:
|
||||
- name: child_profile_NEW_NAME
|
||||
url: https://example.com/child_profile.tar.gz
|
||||
- url: https://example.com/child_profile2.tar.gz
|
||||
attributes:
|
||||
- name: val_numeric
|
||||
type: numeric
|
||||
default: 443
|
||||
- name: val_numeric_override
|
||||
type: numeric
|
||||
default: '72.88'
|
||||
- name: val_string
|
||||
type: string
|
||||
default: 'test-attr'
|
||||
- name: val_boolean
|
||||
type: boolean
|
||||
default: true
|
||||
- name: val_regex
|
||||
type: regex
|
||||
default: '/^\d*/'
|
||||
- name: val_array
|
||||
type: array
|
||||
default:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
- name: val_hash
|
||||
type: hash
|
||||
default:
|
||||
a: true
|
||||
b: false
|
||||
c: '123'
|
||||
- name: val_no_default
|
||||
- name: val_no_default_with_type
|
||||
type: hash
|
|
@ -1,4 +0,0 @@
|
|||
# Demo Compliance Profile
|
||||
|
||||
copyright: Demo Company Ltd
|
||||
license: All rights reserved
|
|
@ -1,10 +0,0 @@
|
|||
describe 'test child attribute when using a profile with a name override' do
|
||||
subject { attribute('val_numeric') }
|
||||
it { should cmp '123456' }
|
||||
end
|
||||
|
||||
control 'test child attribute inside a it block when using a profile with a name override' do
|
||||
describe '123456' do
|
||||
it { should cmp attribute('val_numeric') }
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
name: child_profile
|
||||
title: Child Profile
|
||||
maintainer: Demo, Inc.
|
||||
copyright: Demo, Inc.
|
||||
copyright_email: support@example.com
|
||||
license: Apache-2.0
|
||||
summary: My Profile 1 summary
|
||||
version: 1.0.0
|
||||
attributes:
|
||||
- name: val_numeric
|
||||
type: numeric
|
||||
default: 123456
|
|
@ -1,4 +0,0 @@
|
|||
# Demo Compliance Profile
|
||||
|
||||
copyright: Demo Company Ltd
|
||||
license: All rights reserved
|
|
@ -1,22 +0,0 @@
|
|||
describe 'test child attribute when using a profile without a name override' do
|
||||
subject { attribute('val_numeric') }
|
||||
it { should cmp 654321 }
|
||||
end
|
||||
|
||||
control 'test override control on parent using child attribute' do
|
||||
describe 'dummy' do
|
||||
it { should cmp 9999 }
|
||||
end
|
||||
end
|
||||
|
||||
control 'test override control on parent using parent attribute' do
|
||||
describe 'dummy' do
|
||||
it { should cmp 9999 }
|
||||
end
|
||||
end
|
||||
|
||||
control 'test child attribute inside a it block when using a profile without a name override' do
|
||||
describe '654321' do
|
||||
it { should cmp attribute('val_numeric') }
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
name: child_profile2
|
||||
title: Child Profile2
|
||||
maintainer: Demo, Inc.
|
||||
copyright: Demo, Inc.
|
||||
copyright_email: support@example.com
|
||||
license: Apache-2.0
|
||||
summary: My Profile 1 summary
|
||||
version: 1.0.0
|
||||
attributes:
|
||||
- name: val_numeric
|
||||
type: numeric
|
||||
default: 654321
|
|
@ -0,0 +1 @@
|
|||
attribute('a_required_input')
|
|
@ -7,6 +7,6 @@ license: Apache-2.0
|
|||
summary: An InSpec Compliance Profile
|
||||
version: 0.1.0
|
||||
attributes:
|
||||
- name: username
|
||||
- name: a_required_input
|
||||
type: string
|
||||
required: true
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
# This should simply not error
|
||||
unless attribute('test-01') == 'test-01'
|
||||
raise 'Failed bare input access'
|
||||
end
|
||||
|
||||
describe attribute('test-02') do
|
||||
it { should cmp 'test-02' }
|
||||
end
|
||||
|
||||
describe 'mentioning an input in a bare describe block as a redirected subject' do
|
||||
subject { attribute('test-03') }
|
||||
it { should cmp 'test-03' }
|
||||
end
|
||||
|
||||
control 'test using an input inside a control block as the describe subject' do
|
||||
desc 'test the val_numeric attr'
|
||||
describe attribute('test-04') do
|
||||
it { should cmp 'test-04' }
|
||||
end
|
||||
end
|
||||
|
||||
control "test using inputs in the test its block" do
|
||||
describe 'test-05' do
|
||||
it { should cmp attribute('test-05') }
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: add test for OR
|
20
test/unit/mock/profiles/inputs/scoping/inspec.yml
Normal file
20
test/unit/mock/profiles/inputs/scoping/inspec.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
name: input-scoping
|
||||
title: Profile to test reading attributes in a variety of scopes
|
||||
maintainer: Chef InSpec team
|
||||
copyright: Chef InSpec team
|
||||
copyright_email: inspec@chef.io
|
||||
license: Apache-2.0
|
||||
summary: Profile to test reading attributes in a variety of scopes
|
||||
version: 0.1.0
|
||||
|
||||
attributes:
|
||||
- name: test-01
|
||||
value: test-01
|
||||
- name: test-02
|
||||
value: test-02
|
||||
- name: test-03
|
||||
value: test-03
|
||||
- name: test-04
|
||||
value: test-04
|
||||
- name: test-05
|
||||
value: test-05
|
Loading…
Add table
Reference in a new issue