diff options
-rw-r--r-- | lib/chef/audit/audit_event_proxy.rb | 46 | ||||
-rw-r--r-- | lib/chef/audit/chef_json_formatter.rb | 11 | ||||
-rw-r--r-- | lib/chef/audit/runner.rb | 11 | ||||
-rw-r--r-- | lib/chef/client.rb | 6 | ||||
-rw-r--r-- | lib/chef/dsl/audit.rb | 1 | ||||
-rw-r--r-- | lib/chef/event_dispatch/base.rb | 27 | ||||
-rw-r--r-- | lib/chef/formatters/doc.rb | 54 | ||||
-rw-r--r-- | lib/chef/run_context.rb | 1 |
8 files changed, 128 insertions, 29 deletions
diff --git a/lib/chef/audit/audit_event_proxy.rb b/lib/chef/audit/audit_event_proxy.rb new file mode 100644 index 0000000000..1052821946 --- /dev/null +++ b/lib/chef/audit/audit_event_proxy.rb @@ -0,0 +1,46 @@ +RSpec::Support.require_rspec_core "formatters/base_text_formatter" + +class Chef + class Audit + class AuditEventProxy < ::RSpec::Core::Formatters::BaseFormatter + ::RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, + :example_passed, :example_failed + + # TODO I don't like this, but I don't see another way to pass this in + # see configuration.rb#L671 and formatters.rb#L129 + def self.events=(events) + @@events = events + end + + def events + @@events + end + + def initialize(output) + super + end + + def example_group_started(notification) + events.control_group_start(notification.group.description.strip) + end + + def example_group_finished(_notification) + events.control_group_end + end + + def example_passed(passed) + events.control_example_success(passed.example.description.strip) + end + + def example_failed(failed) + events.control_example_failure(failed.example.description.strip, failed.example.execution_result.exception) + end + + private + + def example_group_chain + example_group.parent_groups.reverse + end + end + end +end diff --git a/lib/chef/audit/chef_json_formatter.rb b/lib/chef/audit/chef_json_formatter.rb index 5dcbdb50b7..50dfbffbb3 100644 --- a/lib/chef/audit/chef_json_formatter.rb +++ b/lib/chef/audit/chef_json_formatter.rb @@ -5,7 +5,7 @@ require 'ffi_yajl' class Chef class Audit class ChefJsonFormatter < ::RSpec::Core::Formatters::BaseFormatter - ::RSpec::Core::Formatters.register self, :example_group_started, :message, :stop, :close, :example_failed + ::RSpec::Core::Formatters.register self, :example_group_started, :stop, :close attr_reader :control_group_data @@ -25,15 +25,6 @@ class Chef end end - def example_failed(notification) - e = notification.example.metadata[:execution_result].exception - raise e unless e.kind_of? ::RSpec::Expectations::ExpectationNotMetError - end - - def message(notification) - puts "message: #{notification}" - end - def stop(notification) notification.examples.each do |example| control_data = build_control_from(example) diff --git a/lib/chef/audit/runner.rb b/lib/chef/audit/runner.rb index 0f439a1aa5..1408c67327 100644 --- a/lib/chef/audit/runner.rb +++ b/lib/chef/audit/runner.rb @@ -17,12 +17,15 @@ # require 'chef/audit' +require 'chef/audit/audit_event_proxy' require 'chef/config' class Chef class Audit class Runner + attr_reader :run_context + def initialize(run_context) @run_context = run_context end @@ -57,6 +60,8 @@ class Chef # for people-friendly output of audit results and json for reporting. Also # configures expectation frameworks. def setup + # We're setting the output stream, but that will only be used for error situations + # Our formatter forwards events to the Chef event message bus configuration.output_stream = Chef::Config[:log_location] configuration.error_stream = Chef::Config[:log_location] @@ -66,8 +71,8 @@ class Chef end def add_formatters - configuration.add_formatter(RSpec::Core::Formatters::DocumentationFormatter) - configuration.add_formatter(ChefJsonFormatter) + configuration.add_formatter(Chef::Audit::AuditEventProxy) + Chef::Audit::AuditEventProxy.events = run_context.events end # Explicitly disable :should syntax. @@ -92,7 +97,7 @@ class Chef # Register each controls group with the world, which will handle # the ordering of the audits that will be run. def register_controls_groups - @run_context.controls_groups.each { |ctls_grp| world.register(ctls_grp) } + run_context.controls_groups.each { |ctls_grp| world.register(ctls_grp) } end end diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 3818f9fad6..bf8c83eee2 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -344,12 +344,12 @@ class Chef def run_audits(run_context) audit_exception = nil begin - @events.audit_start(run_context) + @events.audit_phase_start(run_context) auditor = Chef::Audit::Runner.new(run_context) auditor.run - @events.audit_complete + @events.audit_phase_complete rescue Exception => e - @events.audit_failed(e) + @events.audit_phase_failed(e) audit_exception = e end audit_exception diff --git a/lib/chef/dsl/audit.rb b/lib/chef/dsl/audit.rb index 948db72921..a417e51b5d 100644 --- a/lib/chef/dsl/audit.rb +++ b/lib/chef/dsl/audit.rb @@ -26,7 +26,6 @@ class Chef def controls(group_name, &group_block) raise ::Chef::Exceptions::NoAuditsProvided unless group_block - # TODO add the @example_groups list to the runner for later execution run_context.controls_groups << ::Chef::Audit::ChefExampleGroup.describe(group_name, &group_block) end diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb index 555998ced4..e55f752065 100644 --- a/lib/chef/event_dispatch/base.rb +++ b/lib/chef/event_dispatch/base.rb @@ -230,15 +230,32 @@ class Chef end # Called before audit phase starts - def audit_start(run_context) + def audit_phase_start(run_context) end - # Called when the audit phase is finished. - def audit_complete + # Called when audit phase successfully finishes + def audit_phase_complete end - # Called if the audit phase fails - def audit_failed(exception) + # Called if there is an uncaught exception during the audit phase. The audit runner should + # be catching and handling errors from the examples, so this is only uncaught errors (like + # bugs in our handling code) + def audit_phase_failed(exception) + end + + def control_group_start(name) + # TODO use this only for stdout formatting, controls indentation + end + + def control_group_end + end + + def control_example_success(description) + # TODO Use this for both stdout and resource_reporter, need to pass ancestor tree for resource_reporter + # but that is ignored by stdout + end + + def control_example_failure(description, exception) end # TODO: need events for notification resolve? diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb index 66ee6ccabe..96ca283b9f 100644 --- a/lib/chef/formatters/doc.rb +++ b/lib/chef/formatters/doc.rb @@ -156,17 +156,57 @@ class Chef converge_complete end - def audit_start(run_context) - # TODO read the number of `controls` blocks to run from the run_context.audit_runner - puts_line "Running collected audits" + ############# + # TODO + # Make all these document printers neater + ############# + + # Called before audit phase starts + def audit_phase_start(run_context) + puts_line "" + puts_line "Audit phase starting" + end + + # Called when audit phase successfully finishes + def audit_phase_complete + puts_line "Audit phase ended" + end + + # Called if there is an uncaught exception during the audit phase. The audit runner should + # be catching and handling errors from the examples, so this is only uncaught errors (like + # bugs in our handling code) + def audit_phase_failed(error) + puts_line "Audit phase exception:" + indent + # TODO error_mapper ? + puts_line "#{error.message}" + error.backtrace.each do |l| + puts_line l + end end - def audit_complete - # TODO + def control_group_start(name) + puts_line "Control group #{name} started" + indent end - def audit_failed(exception) - # TODO + def control_group_end + unindent + end + + def control_example_success(description) + puts_line "SUCCESS - #{description}" + end + + def control_example_failure(description, error) + puts_line "FAILURE - #{description}" + indent + # TODO error_mapper ? + puts_line "#{error.message}" + # error.backtrace.each do |l| + # puts_line l + # end + unindent end # Called before action is executed on a resource. diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index 749e4cf388..c6d11eaaa1 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -50,6 +50,7 @@ class Chef # recipes, which is triggered by #load. (See also: CookbookCompiler) attr_accessor :resource_collection + # The list of control groups to execute during the audit phase attr_accessor :controls_groups # Chef::ProviderResolver for this run |