summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/chef/audit/audit_event_proxy.rb46
-rw-r--r--lib/chef/audit/chef_json_formatter.rb11
-rw-r--r--lib/chef/audit/runner.rb11
-rw-r--r--lib/chef/client.rb6
-rw-r--r--lib/chef/dsl/audit.rb1
-rw-r--r--lib/chef/event_dispatch/base.rb27
-rw-r--r--lib/chef/formatters/doc.rb54
-rw-r--r--lib/chef/run_context.rb1
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