We have Ubuntu 16.04 / 18.04 with chef-client 14.1.12.
Handlers are added to client.d folder.
template "/etc/chef/client.d/httpapi_handler.rb" do
source "httpapi_handler.rb.erb"
mode '0644'
end
Handler itself. HTTPAPI part is based on https://github.com/b1-systems/chef-handler-httpapi
I tried to use http call for slack as well but it didn’t work so I added new class with curl
require 'rubygems'
require 'chef'
require 'chef/handler'
require "net/http"
require "uri"
require "json"
class Httpapi < Chef::Handler
def initialize(api_url, api_user, api_pass)
@api_url = api_url
@api_user = api_user
@api_pass = api_pass
end
def report
uri = URI.parse(@api_url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.basic_auth(@api_user, @api_pass)
if run_status.success?
api_data = { :id => "#{node.name}/chef", :message => "Chef successfull on #{node.name}", :details => { :Tags => { :host => "#{node.name}" }, :Level => "OK" } }
else
api_data = { :id => "#{node.name}/chef", :message => "Chef failed on #{node.name}, exception: #{run_status.exception}", :details => { :Tags => { :host => "#{node.name}" }, :Level => "CRITICAL" } }
end
request.body = api_data.to_json
response = http.request(request)
puts response
end
end
class Slack < Chef::Handler
def initialize(webhook_url)
@webhook_url = webhook_url
end
def report
if run_status.failed?
message = { :text => "Chef failed on #{node.name}\n#{run_status.exception}" }
payload = message.to_json
cmd = "curl -X POST --data-urlencode 'payload=#{payload}' #{@webhook_url}"
system(cmd)
end
end
end
api_url = "<%= node['dashboard']['api_url'] %>"
api_user = "<%= node['dashboard']['admin'] %>"
api_pass = "<%= node['dashboard']['password'] %>"
webhook_url = "<%= node['slack']['webhook_url'] %>"
Httpapi_handler = Httpapi.new(api_url, api_user, api_pass)
Slack_handler = Slack.new(webhook_url)
report_handlers << Slack_handler
exception_handlers << Slack_handler
report_handlers << Httpapi_handler
exception_handlers << Httpapi_handler
Notifications to HTTPAPI and Slack works but sometimes 100 same massages can came from one host.
Like host can’t be resolved
STDERR: ssh: Could not resolve hostname example.com: Temporary failure in name resolution
fatal: Could not read from remote repository.
or service can’t start
STDERR: Job for openvpn.service failed because a configured resource limit was exceeded. See "systemctl status openvpn.service" and "journalctl -xe" for details.
Logs from chef-client run
2018-06-18 16:56:47 6 chef-client[980]: #<Net::HTTPOK:0x000000000594fc28>
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Httpapi#033[0m
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Slack#033[0m
2018-06-18 16:56:47 6 chef-client[980]: #<Net::HTTPOK:0x000000000594a1d8>
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Httpapi#033[0m
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Slack#033[0m
2018-06-18 16:56:47 6 chef-client[980]: #<Net::HTTPOK:0x00000000059447d8>
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Httpapi#033[0m
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Slack#033[0m
2018-06-18 16:56:47 6 chef-client[980]: #<Net::HTTPOK:0x000000000593f378>
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Httpapi#033[0m
2018-06-18 16:56:47 6 chef-client[980]: - #<Class:0x00000000029fe050>::Slack#033[0m
2018-06-18 16:56:48 6 chef-client[980]: #<Net::HTTPOK:0x0000000005cbe0a8>
2018-06-18 16:56:48 6 chef-client[980]: - #<Class:0x00000000029fe050>::Httpapi#033[0m
2018-06-18 16:56:48 6 chef-client[980]: - #<Class:0x00000000029fe050>::Slack#033[0m
Why Slack Class belongs to Net::HTTPOK
?
What should I do to send only one message to Slack? Add “exit” to cmd command?
Thanks in advance.