Skip to content

Commit

Permalink
Initial Check_MK integration.
Browse files Browse the repository at this point in the history
  • Loading branch information
martini committed Aug 21, 2017
1 parent ab33cd4 commit 24696c0
Show file tree
Hide file tree
Showing 20 changed files with 780 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class Index extends App.ControllerIntegrationBase
featureIntegration: 'check_mk_integration'
featureName: 'Check_MK'
featureConfig: 'check_mk_config'
description: [
['This service receives http requests from %s and creates tickets with host and service.', 'Check_MK']
['If the host and service is recovered again, the ticket will be closed automatically.']
]

render: =>
super
new App.SettingsForm(
area: 'Integration::CheckMK'
el: @$('.js-form')
)

new App.ScriptSnipped(
el: @$('.js-scriptSnipped')
facility: 'check_mk'
style: 'bash'
content: "#!/bin/bash\n\ncurl -X POST -F 'event_id=123' -F 'host=host1' -F 'service=http' -F 'state=down' #{App.Config.get('http_type')}://#{App.Config.get('fqdn')}/api/v1/integration/check_mk/#{App.Setting.get('check_mk_token')}"
description: [
['To enable %s for sending http requests to %s, you need create "%s" in the admin interface if %s.', 'Check_MK', 'Zammad', 'Event Actions', 'Check_MK']
]
)

new App.HttpLog(
el: @$('.js-log')
facility: 'check_mk'
)

class State
@current: ->
App.Setting.get('check_mk_integration')

App.Config.set(
'IntegrationCheckMk'
{
name: 'Check_MK'
target: '#system/integration/check_mk'
description: 'An open source monitoring tool.'
controller: Index
state: State
}
'NavBarIntegrations'
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class SidebarCustomer extends App.Controller
sidebarItem: =>
return if !@permissionCheck('ticket.agent')
{
items = {
head: 'Customer'
name: 'customer'
icon: 'person'
Expand All @@ -11,14 +11,16 @@ class SidebarCustomer extends App.Controller
name: 'customer-change'
callback: @changeCustomer
},
{
title: 'Edit Customer'
name: 'customer-edit'
callback: @editCustomer
},
]
callback: @showCustomer
}
return items if @ticket && @ticket.customer_id == 1
items.actions.push {
title: 'Edit Customer'
name: 'customer-edit'
callback: @editCustomer
}
items

showCustomer: (el) =>
@el = el
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class App.HttpLog extends App.Controller
render: =>
@html App.view('widget/http_log')(
records: @records
description: @description
)

show: (e) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class App.ScriptSnipped extends App.Controller
#events:
# 'click .js-record': 'show'

elements:
'.js-code': 'code'


constructor: ->
super
#@fetch()
@records = []
@render()

render: =>
@html App.view('widget/script_snipped')(
records: @records
description: @description
style: @style
content: @content
)

@code.each (i, block) ->
hljs.highlightBlock block
3 changes: 2 additions & 1 deletion app/assets/javascripts/app/lib/base/highlight.pack.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion app/assets/javascripts/app/views/integration/base.jst.eco
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
<div class="page-content">
<% if @description: %>
<% for item in @description: %>
<p><%- @T(item[0], item[1], item[2]) %></p>
<p><%- @T(item...) %></p>
<% end %>
<% end %>
<div class="js-form"></div>
<div class="js-scriptSnipped"></div>
<div class="js-log"></div>
</div>
46 changes: 25 additions & 21 deletions app/assets/javascripts/app/views/widget/http_log.jst.eco
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
<hr>

<h2><%- @T('Recent logs') %></h2>
<div class="settings-entry">
<h2><%- @T('Recent logs') %></h2>
<% if @description: %>
<% for item in @description: %>
<p><%- @T(item...) %></p>
<% end %>
<% end %>
<div class="settings-entry">
<% if [email protected]: %>
<table class="settings-list settings-list--stretch settings-list--placeholder">
<thead><tr><th><%- @T('No Entries') %>
</table>
<table class="settings-list settings-list--stretch settings-list--placeholder">
<thead><tr><th><%- @T('No Entries') %>
</table>
<% else: %>
<table class="settings-list settings-list--stretch">
<thead>
<tr>
<th width="10%"><%- @T('Direction') %>
<th><%- @T('Request') %>
<th width="25%"><%- @T('Created at') %>
</thead>
<tbody>
<table class="settings-list settings-list--stretch">
<thead>
<tr>
<th width="10%"><%- @T('Direction') %>
<th><%- @T('Request') %>
<th width="25%"><%- @T('Created at') %>
</thead>
<tbody>
<% for record in @records: %>
<tr data-id="<%= record.id %>" class="js-record">
<td><%- @T(record.direction) %>
<td><a href="#"><%= record.status %> <%= record.method %> <%= record.url %></a>
<td><%- @humanTime(record.created_at) %>
<tr data-id="<%= record.id %>" class="js-record">
<td><%- @T(record.direction) %>
<td><a href="#"><%= record.status %> <%= record.method %> <%= record.url %></a>
<td><%- @humanTime(record.created_at) %>
<% end %>
</tbody>
</table>
</tbody>
</table>
<% end %>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<hr>
<h2><%- @T('Usage') %></h2>
<% if @description: %>
<% for item in @description: %>
<p><%- @T(item...) %></p>
<% end %>
<% end %>
<pre><code class="language-<%- @style %> js-code"><%- @content %></code></pre>
4 changes: 4 additions & 0 deletions app/controllers/application_controller/handles_errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,26 @@ module ApplicationController::HandlesErrors
def not_found(e)
logger.error e
respond_to_exception(e, :not_found)
http_log
end

def unprocessable_entity(e)
logger.error e
respond_to_exception(e, :unprocessable_entity)
http_log
end

def internal_server_error(e)
logger.error e
respond_to_exception(e, :internal_server_error)
http_log
end

def unauthorized(e)
error = humanize_error(e.message)
response.headers['X-Failure'] = error.fetch(:error_human, error[:error])
respond_to_exception(e, :unauthorized)
http_log
end

private
Expand Down
138 changes: 138 additions & 0 deletions app/controllers/integration/check_mk_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/

class Integration::CheckMkController < ApplicationController
skip_before_action :verify_csrf_token
before_action :check_configured

def update

# check params
raise Exceptions::UnprocessableEntity, 'event_id is missing!' if params[:event_id].blank?
raise Exceptions::UnprocessableEntity, 'state is missing!' if params[:state].blank?
raise Exceptions::UnprocessableEntity, 'host is missing!' if params[:host].blank?

# search for open ticket
auto_close = Setting.get('check_mk_auto_close')
auto_close_state_id = Setting.get('check_mk_auto_close_state_id')
group_id = Setting.get('check_mk_group_id')
state_recovery_match = '(OK|UP)'

# check if ticket with host is open
customer = User.lookup(id: 1)

# follow up detection by meta data
integration = 'check_mk'
open_states = Ticket::State.by_category(:open)
ticket_ids = Ticket.where(state: open_states).order(created_at: :desc).limit(5000).pluck(:id)
ticket_ids_found = []
ticket_ids.each { |ticket_id|
ticket = Ticket.find_by(id: ticket_id)
next if !ticket
next if !ticket.preferences
next if !ticket.preferences[integration]
next if !ticket.preferences[integration]['host']
next if ticket.preferences[integration]['host'] != params[:host]
next if ticket.preferences[integration]['service'] != params[:service]

# found open ticket for service+host
ticket_ids_found.push ticket.id
}

# new ticket, set meta data
title = "#{params[:host]} is #{params[:state]}"
body = "EventID: #{params[:event_id]}
Host: #{params[:host]}
Service: #{params[:service]}
State: #{params[:state]}
Text: #{params[:text]}
RemoteIP: #{request.remote_ip}
UserAgent: #{request.env['HTTP_USER_AGENT']}
"

# add article
if params[:state].present? && ticket_ids_found.present?
ticket_ids_found.each { |ticket_id|
ticket = Ticket.find_by(id: ticket_id)
next if !ticket
article = Ticket::Article.create!(
ticket_id: ticket_id,
type_id: Ticket::Article::Type.find_by(name: 'web').id,
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
body: body,
subject: title,
internal: false,
)
}
if (!auto_close && params[:state].match(/#{state_recovery_match}/i)) || !params[:state].match(/#{state_recovery_match}/i)
render json: {
result: 'ticket already open, added note',
ticket_ids: ticket_ids_found,
}
return
end
end

# check if service is recovered
if auto_close && params[:state].present? && params[:state].match(/#{state_recovery_match}/i)
if ticket_ids_found.blank?
render json: {
result: 'no open tickets found, ignore action',
}
return
end
state = Ticket::State.lookup(id: auto_close_state_id)
ticket_ids_found.each { |ticket_id|
ticket = Ticket.find_by(id: ticket_id)
next if !ticket
ticket.state_id = auto_close_state_id
ticket.save!
}
render json: {
result: "closed tickets with ids #{ticket_ids_found.join(',')}",
ticket_ids: ticket_ids_found,
}
return
end

ticket = Ticket.create!(
group_id: group_id,
customer_id: customer.id,
title: title,
preferences: {
check_mk: {
host: params[:host],
service: params[:service],
},
}
)
article = Ticket::Article.create!(
ticket_id: ticket.id,
type_id: Ticket::Article::Type.find_by(name: 'web').id,
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
body: body,
subject: title,
internal: false,
)

render json: {
result: "new ticket created (ticket id: #{ticket.id})",
ticket_id: ticket.id,
ticket_number: ticket.number,
}
end

private

def check_configured
http_log_config facility: 'check_mk'

if !Setting.get('check_mk_integration')
raise Exceptions::UnprocessableEntity, 'Feature is disable, please contact your admin to enable it!'
end

if Setting.get('check_mk_token') != params[:token]
raise Exceptions::UnprocessableEntity, 'Invalid token!'
end
end

end
3 changes: 0 additions & 3 deletions app/models/channel/filter/monitoring_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ def self.run(_channel, mail)
ticket = Ticket.find_by(id: ticket_id)
next if !ticket
next if !ticket.preferences
next if !ticket.preferences['integration']
next if ticket.preferences['integration'] != integration
next if !ticket.preferences[integration]
next if !ticket.preferences[integration]['host']
next if ticket.preferences[integration]['host'] != result['host']
Expand All @@ -88,7 +86,6 @@ def self.run(_channel, mail)
mail[ 'x-zammad-ticket-preferences'.to_sym ] = {}
end
preferences = {}
preferences['integration'] = integration
preferences[integration] = result
preferences.each { |key, value|
mail[ 'x-zammad-ticket-preferences'.to_sym ][key] = value
Expand Down
Loading

0 comments on commit 24696c0

Please sign in to comment.