Class: ChefHandlerForeman::ForemanResourceReporter

Inherits:
Chef::ResourceReporter
  • Object
show all
Defined in:
lib/chef_handler_foreman/foreman_resource_reporter.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ ForemanResourceReporter

Returns a new instance of ForemanResourceReporter.



5
6
7
8
9
10
11
12
13
14
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 5

def initialize(*args)
  @total_up_to_date     = 0
  @total_skipped        = 0
  @total_updated        = 0
  @total_failed         = 0
  @total_restarted      = 0
  @total_failed_restart = 0
  @all_resources        = []
  super
end

Instance Attribute Details

#log_levelObject

Returns the value of attribute log_level.



3
4
5
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 3

def log_level
  @log_level
end

#uploaderObject

Returns the value of attribute uploader.



3
4
5
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 3

def uploader
  @uploader
end

Instance Method Details

#chef_logObject



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 164

def chef_log
  message = 'run'
  if @status == 'success' && exception.nil?
    level = 'notice'
  else
    message += " (#{exception.class} #{exception.message})"
    level   = 'err'
  end

  { "log" => {
      "sources"  => { "source" => 'Chef' },
      "messages" => { "message" => message },
      "level"    => level
  } }
end

#filter_logs(logs) ⇒ Object

currently we support only three log levels:

'debug' means do not filter,
'notice' updated resources and errors
'error' means only errors


185
186
187
188
189
190
191
192
193
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 185

def filter_logs(logs)
  if log_level == 'error'
    logs.select { |log| log['log']['level'] == 'err' }
  elsif log_level == 'notice'
    logs.select { |log| ['err','notice'].include? log['log']['level'] }
  else
    logs
  end
end

#format_message(message, resource) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 140

def format_message(message, resource)
  case resource.resource_name.to_s
    when 'template', 'cookbook_file'
      unless resource.diff.nil?
        message += " with diff " + resource.diff.gsub('\\n', "\n")
      end
    when 'package'
      message += " package in #{resource.version}" unless resource.version.nil?
    else
      message = resource.action.to_s
  end
  message
end

#post_reporting_dataObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 71

def post_reporting_data
  if reporting_enabled?
    run_data = prepare_run_data
    Chef::Log.info("Sending resource update report to foreman (run-id: #{@run_id})")
    Chef::Log.debug run_data.inspect
    begin
      Chef::Log.debug("Sending data...")
      if uploader
        uploader.foreman_request('/api/reports', { "report" => run_data }, node_name)
      else
        Chef::Log.error "No uploader registered for foreman reporting, skipping report upload"
      end
    rescue => e
      Chef::Log.error "Sending failed with #{e.class} #{e.message}"
      Chef::Log.error e.backtrace.join("\n")
    end
  else
    Chef::Log.debug("Reporting disabled, skipping report upload")
  end
end

#prepare_run_dataObject



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 92

def prepare_run_data
  run_data                = {}
  run_data["host"]        = node_name
  run_data["reported_at"] = end_time.to_s
  run_data["status"]      = resources_per_status

  run_data["metrics"] = {
      "resources" => { "total" => @total_res_count },
      "time"      => resources_per_time
  }

  run_data["logs"] = filter_logs(resources_logs + [chef_log])
  run_data
end

#resource_completed(new_resource) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 63

def resource_completed(new_resource)
  if @pending_update && !nested_resource?(new_resource)
    @pending_update.finish
    @updated_resources << @pending_update
    @pending_update = nil
  end
end

#resource_current_state_loaded(new_resource, action, current_resource) ⇒ Object



35
36
37
38
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 35

def resource_current_state_loaded(new_resource, action, current_resource)
  super
  @all_resources.push @pending_update unless @pending_update.nil?
end

#resource_failed(new_resource, action, exception) ⇒ Object



57
58
59
60
61
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 57

def resource_failed(new_resource, action, exception)
  @total_failed         += 1
  @total_failed_restart += 1 if action.to_s == 'restart'
  super
end

#resource_level(resource) ⇒ Object



154
155
156
157
158
159
160
161
162
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 154

def resource_level(resource)
  if ! resource.exception.nil?
    return 'err'
  elsif resource.new_resource.updated
    return 'notice'
  else
    return 'debug'
  end
end

#resource_skipped(resource, action, conditional) ⇒ Object



46
47
48
49
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 46

def resource_skipped(resource, action, conditional)
  @total_skipped += 1
  super
end

#resource_up_to_date(new_resource, action) ⇒ Object



41
42
43
44
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 41

def resource_up_to_date(new_resource, action)
  @total_up_to_date += 1
  super
end

#resource_updated(new_resource, action) ⇒ Object



51
52
53
54
55
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 51

def resource_updated(new_resource, action)
  @total_updated   += 1
  @total_restarted += 1 if action.to_s == 'restart'
  super
end

#resources_logsObject



125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 125

def resources_logs
  @all_resources.map do |resource|
    action  = resource.new_resource.action
    message = action.is_a?(Array) ? action.first.to_s : action.to_s
    message = format_message(message, resource.new_resource)
    message += " (#{resource.exception.class} #{resource.exception.message})" unless resource.exception.nil?
    level   =  resource_level(resource)
    { "log" => {
        "sources"  => { "source" => resource.new_resource.to_s },
        "messages" => { "message" => message },
        "level"    => level
    } }
  end
end

#resources_per_statusObject



107
108
109
110
111
112
113
114
115
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 107

def resources_per_status
  { "applied"         => @total_updated,
    "restarted"       => @total_restarted,
    "failed"          => @total_failed,
    "failed_restarts" => @total_failed_restart,
    "skipped"         => @total_skipped,
    "pending"         => 0
  }
end

#resources_per_timeObject



117
118
119
120
121
122
123
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 117

def resources_per_time
  @run_status.all_resources.inject({}) do |memo, resource|
    name, time = resource.resource_name.to_s, resource.elapsed_time || 0
    memo[name] = memo[name] ? memo[name] + time : time
    memo
  end
end

#run_completed(node) ⇒ Object



20
21
22
23
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 20

def run_completed(node)
  @status = "success"
  post_reporting_data
end

#run_failed(exception) ⇒ Object



25
26
27
28
29
30
31
32
33
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 25

def run_failed(exception)
  @exception = exception
  @status    = "failure"
  # If we failed before we received the run_started callback, there's not much we can do
  # in terms of reporting
  if @run_status
    post_reporting_data
  end
end

#run_started(run_status) ⇒ Object



16
17
18
# File 'lib/chef_handler_foreman/foreman_resource_reporter.rb', line 16

def run_started(run_status)
  @run_status = run_status
end