summaryrefslogtreecommitdiff
path: root/lib/chef/audit/chef_json_formatter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/audit/chef_json_formatter.rb')
-rw-r--r--lib/chef/audit/chef_json_formatter.rb88
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/chef/audit/chef_json_formatter.rb b/lib/chef/audit/chef_json_formatter.rb
new file mode 100644
index 0000000000..3c164120b4
--- /dev/null
+++ b/lib/chef/audit/chef_json_formatter.rb
@@ -0,0 +1,88 @@
+RSpec::Support.require_rspec_core "formatters/base_formatter"
+require 'control_group_data'
+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
+
+ attr_reader :control_group_data
+
+ # TODO hopefully the runner can take care of this for us since there won't be an outer-most
+ # control group
+ @@outer_example_group_found = false
+
+ def initialize(output)
+ super
+ end
+
+ # Invoked for each `control`, `describe`, `context` block
+ def example_group_started(notification)
+ unless @@outer_example_group_found
+ @control_group_data = ControlGroupData.new(notification.group.description)
+ @@outer_example_group_found = true
+ 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)
+ e = example.exception
+ if e
+ control = control_group_data.example_failure(e.message, control_data)
+ else
+ control = control_group_data.example_success(control_data)
+ end
+ control.line_number = example.metadata[:line_number]
+ end
+ end
+
+ def close(notification)
+ output.write FFI_Yajl::Encoder.encode(control_group_data.to_hash, pretty: true)
+ output.close if IO === output && output != $stdout
+ end
+
+ private
+
+ def build_control_from(example)
+ described_class = example.metadata[:described_class]
+ if described_class
+ resource_type = described_class.class.name.split(':')[-1]
+ # TODO submit github PR to expose this
+ resource_name = described_class.instance_variable_get(:@name)
+ end
+
+ describe_groups = []
+ group = example.metadata[:example_group]
+ # If the innermost block has a resource instead of a string, don't include it in context
+ describe_groups.unshift(group[:description]) if described_class.nil?
+ group = group[:parent_example_group]
+ while !group.nil?
+ describe_groups.unshift(group[:description])
+ group = group[:parent_example_group]
+ end
+ # TODO remove this when we're no longer wrapping everything with "mysql audit"
+ describe_groups.shift
+
+ {
+ :name => example.description,
+ :desc => example.full_description,
+ :resource_type => resource_type,
+ :resource_name => resource_name,
+ :context => describe_groups
+ }
+ end
+
+ end
+ end
+end