summaryrefslogtreecommitdiff
path: root/lib/chef/audit/control_group_data.rb
blob: 42a91ef5a7061546910ada978c6a014f6d2475f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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