# # Author:: Tyler Ball () # # Copyright:: Copyright (c) 2014 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'securerandom' class Chef class Audit class AuditData attr_reader :node_name, :run_id, :control_groups attr_accessor :start_time, :end_time def initialize(node_name, run_id) @node_name = node_name @run_id = run_id @control_groups = [] end def add_control_group(control_group) control_groups << control_group end def to_hash { :node_name => node_name, :run_id => run_id, :start_time => start_time, :end_time => end_time, :control_groups => control_groups.collect { |c| c.to_hash } } end end class ControlGroupData attr_reader :name, :status, :number_succeeded, :number_failed, :controls, :metadata def initialize(name, metadata={}) @status = "success" @controls = [] @number_succeeded = 0 @number_failed = 0 @name = name @metadata = metadata end def example_success(control_data) @number_succeeded += 1 control = create_control(control_data) control.status = "success" controls << control control end def example_failure(control_data, details) @number_failed += 1 @status = "failure" control = create_control(control_data) control.details = details if details control.status = "failure" controls << control control end def to_hash # We sort it so the examples appear in the output in the same order # they appeared in the recipe controls.sort! {|x,y| x.line_number <=> y.line_number} h = { :name => name, :status => status, :number_succeeded => number_succeeded, :number_failed => number_failed, :controls => controls.collect { |c| c.to_hash } } # If there is a duplicate key, metadata will overwrite it add_display_only_data(h).merge(metadata) end private def create_control(control_data) ControlData.new(control_data) end # The id and control sequence number are ephemeral data - they are not needed # to be persisted and can be regenerated at will. They are only needed # for display purposes. def add_display_only_data(group) group[:id] = SecureRandom.uuid group[:controls].collect!.with_index do |c, i| # i is zero-indexed, and we want the display one-indexed c[:sequence_number] = i+1 c end group end end class ControlData attr_reader :name, :resource_type, :resource_name, :context, :line_number attr_accessor :status, :details def initialize(control_data={}) control_data.each do |k, v| self.instance_variable_set("@#{k}", v) end end def to_hash h = { :name => name, :status => status, :details => details, :resource_type => resource_type, :resource_name => resource_name } h[:context] = context || [] h end end end end