Merge pull request #161 from chef/bugfix-profile

Merged change 5ce5796b-e97e-4826-a9de-9848865207af

From review branch bugfix-profile into master

Signed-off-by: chartmann <chartmann@chef.io>
This commit is contained in:
chef-delivery 2015-10-27 01:50:36 -07:00
commit 6ddc45446d
9 changed files with 114 additions and 40 deletions

View file

@ -27,17 +27,17 @@ module Inspec
description
version
}.each do |name|
define_method name do |arg|
params[name] = arg
define_method name.to_sym do |arg|
params[name.to_sym] = arg
end
end
def supports(sth, version = nil)
params['supports'] ||= []
params['supports'].push(
params[:supports] ||= []
params[:supports].push(
{
'os' => sth,
'version' => version,
os: sth,
version: version,
},
)
end
@ -45,20 +45,20 @@ module Inspec
def valid?
is_valid = true
%w{ name title version summary }.each do |field|
next unless params[field].nil?
@log.error("Missing profile #{field} in metadata.rb")
next unless params[field.to_sym].nil?
@logger.error("Missing profile #{field} in metadata.rb")
is_valid = false
end
%w{ maintainer copyright }.each do |field|
next unless params[field].nil?
@log.warn("Missing profile #{field} in metadata.rb")
next unless params[field.to_sym].nil?
@logger.warn("Missing profile #{field} in metadata.rb")
is_valid = false
end
is_valid && @missing_methods.empty?
end
def method_missing(sth, *args)
@log.warn "metadata.rb doesn't support: #{sth} #{args}"
@logger.warn "metadata.rb doesn't support: #{sth} #{args}"
@missing_methods.push(sth)
end
@ -72,7 +72,7 @@ module Inspec
res = Metadata.new(logger)
res.instance_eval(File.read(path), path, 1)
res.dict['name'] = profile_id.to_s unless profile_id.to_s.empty?
res.params[:name] = profile_id.to_s unless profile_id.to_s.empty?
res
end
end

View file

@ -8,7 +8,8 @@ require 'inspec/metadata'
module Inspec
class Profile
def self.from_path(path, options = nil)
opt = options.dup || {}
opt = {}
options.each { |k, v| opt[k.to_sym] = v } unless options.nil?
opt[:path] = path
Profile.new(opt)
end
@ -18,9 +19,9 @@ module Inspec
def initialize(options = nil)
@options = options || {}
@profile_id = options[:id] || nil
@params = {}
@logger = options.delete(:logger) || Logger.new(nil)
@profile_id = options.delete(:profile_id)
@logger = options[:logger] || Logger.new(nil)
@path = @options[:path]
fail 'Cannot read an empty path.' if @path.nil? || @path.empty?
@ -29,14 +30,16 @@ module Inspec
@metadata = read_metadata
@params = @metadata.params unless @metadata.nil?
@params['rules'] = rules = {}
@params[:rules] = rules = {}
@runner = Runner.new(
id: @profile_id,
backend: :mock,
)
@runner.add_tests([@path])
@runner.rules.each do |id, rule|
rules[id] = {
file = rule.instance_variable_get(:@__file)
rules[file] ||= {}
rules[file][id] = {
title: rule.title,
desc: rule.desc,
impact: rule.impact,
@ -49,17 +52,21 @@ module Inspec
def info
res = @params.dup
rules = {}
res['rules'].each do |id, rule|
next if id.to_s.empty?
data = rule.dup
data.delete(:checks)
data[:impact] ||= 0.5
data[:impact] = 1.0 if data[:impact] > 1.0
data[:impact] = 0.0 if data[:impact] < 0.0
rules[id] = data
res[:rules].each do |gid, group|
next if gid.to_s.empty?
path = gid.sub(File.join(@path, ''), '')
rules[path] = { title: '', rules: {} }
group.each do |id, rule|
next if id.to_s.empty?
data = rule.dup
data.delete(:checks)
data[:impact] ||= 0.5
data[:impact] = 1.0 if data[:impact] > 1.0
data[:impact] = 0.0 if data[:impact] < 0.0
rules[path][:rules][id] = data
end
end
res['rules'] = rules
res[:rules] = rules
res
end
@ -81,26 +88,26 @@ module Inspec
@logger.info "Checking profile in #{@path}"
if @params['name'].to_s.empty?
if @params[:name].to_s.empty?
error.call('No profile name defined')
elsif !(@params['name'].to_s =~ %r{^\S+\/\S+$})
elsif !(@params[:name].to_s =~ %r{^\S+\/\S+$})
error.call('Profile name must be defined as: OWNER/ID')
end
warn.call('No version defined') if @params['version'].to_s.empty?
warn.call('No title defined') if @params['title'].to_s.empty?
warn.call('No maintainer defined') if @params['maintainer'].to_s.empty?
warn.call('No supports defined') if @params['supports'].empty?
warn.call('No version defined') if @params[:name].to_s.empty?
warn.call('No title defined') if @params[:name].to_s.empty?
warn.call('No maintainer defined') if @params[:name].to_s.empty?
warn.call('No supports defined') if @params[:name].empty?
@logger.info 'Metadata OK.' if no_warnings
no_warnings = true
if @params['rules'].empty?
if @params[:name].empty?
warn.call('No rules were found.')
else
@logger.debug "Found #{@params['rules'].length} rules."
@logger.debug "Found #{@params[:name].length} rules."
end
@params['rules'].each do |id, rule|
@params[:name].each do |id, rule|
error.call('Avoid rules with empty IDs') if id.nil? or id.empty?
warn.call("Rule #{id} has no title") if rule[:title].to_s.empty?
warn.call("Rule #{id} has no description") if rule[:desc].to_s.empty?

View file

@ -27,6 +27,7 @@ module Inspec
end
def load(content, source = nil, line = nil)
@current_file = source
@profile_context.instance_eval(content, source || 'unknown', line || 1)
end
@ -37,6 +38,7 @@ module Inspec
def register_rule(r)
# get the full ID
r.instance_variable_set(:@__file, @current_file)
full_id = Inspec::Rule.full_id(@profile_id, r)
if full_id.nil?
# TODO: error

View file

@ -26,8 +26,15 @@ module Inspec
def example_group
that = self
outer_clr = calls[0][3]
RSpec::Core::ExampleGroup.describe(that.value, caller: outer_clr) do
opts = { 'caller' => calls[0][3] }
if !calls[0][3].nil? && !calls[0][3].empty? &&
(m = calls[0][3][0].match(/^([^:]*):(\d+):/))
opts['file_path'] = m[0]
opts['line_number'] = m[1]
end
RSpec::Core::ExampleGroup.describe(that.value, opts) do
that.calls.each do |method, args, block, clr|
it(nil, caller: clr) do
x = expect(that.value, &that.block).method(method)

View file

@ -83,17 +83,24 @@ module Inspec
private
def get_check_example(method_name, arg, block)
opts = {}
if !block.nil? && block.respond_to?(:source_location)
file_path, line = block.source_location
opts['file_path'] = file_path
opts['line_number'] = line
end
if !arg.empty? &&
arg[0].respond_to?(:resource_skipped) &&
!arg[0].resource_skipped.nil?
return RSpec::Core::ExampleGroup.describe(*arg) do
return RSpec::Core::ExampleGroup.describe(*arg, opts) do
it arg[0].resource_skipped
end
else
# add the resource
case method_name
when 'describe'
return RSpec::Core::ExampleGroup.describe(*arg, &block)
return RSpec::Core::ExampleGroup.describe(*arg, opts, &block)
when 'expect'
return block.example_group
else

View file

@ -15,6 +15,7 @@ end
require 'inspec/resource'
require 'inspec/backend'
require 'inspec/profile'
class MockLoader
# pass the os identifier to emulate a specific operating system

View file

@ -0,0 +1 @@
name 'metadata profile'

49
test/unit/profile_test.rb Normal file
View file

@ -0,0 +1,49 @@
# encoding: utf-8
# author: Christoph Hartmann
# author: Dominik Richter
require 'helper'
def load_profile(name)
pwd = File.dirname(__FILE__)
Inspec::Profile.from_path("#{pwd}/mock/profiles/#{name}")
end
describe Inspec::Profile do
before {
# mock up the profile runner
# TODO: try to take the real profile runner here;
# currently it's stopped at test runner conflicts
class Inspec::Profile::Runner
def initialize(opts) end
def add_tests(tests) end
def rules
{}
end
end
}
describe 'with empty profile' do
let(:profile) { load_profile('empty') }
it 'has no metadata' do
profile.params[:name].must_be_nil
end
it 'has no rules' do
profile.params[:rules].must_equal({})
end
end
describe 'with normal metadata in profile' do
let(:profile) { load_profile('metadata') }
it 'has metadata' do
profile.params[:name].must_equal 'metadata profile'
end
it 'has no rules' do
profile.params[:rules].must_equal({})
end
end
end