Closes #3004 - Enhance Check_MK integration to set ticket attributes (e. g. for SLAs) and improve code snippeds for integration

This commit is contained in:
Martin Edenhofer 2020-04-02 13:28:18 +02:00
parent 2843a92de0
commit 16b876e3e8
6 changed files with 517 additions and 202 deletions

View file

@ -15,10 +15,8 @@ class Index extends App.ControllerIntegrationBase
) )
new App.ScriptSnipped( new App.ScriptSnipped(
el: @$('.js-scriptSnipped') el: @$('.js-scriptSnippedPre')
facility: 'check_mk'
style: 'bash' style: 'bash'
content: "#!/bin/bash\n\ncurl -X POST -F \"event_id=$NOTIFY_SERVICEPROBLEMID\" -F \"host=$NOTIFY_HOSTNAME\" -F \"service=$NOTIFY_SERVICEDESC\" -F \"state=$NOTIFY_SERVICESTATE\" -F \"text=$NOTIFY_SERVICEOUTPUT\" #{App.Config.get('http_type')}://#{App.Config.get('fqdn')}/api/v1/integration/check_mk/#{App.Setting.get('check_mk_token')}"
description: [ description: [
['To enable %s for sending http requests to %s, you need create a own "notification rule" in %s.', 'Check_MK', 'Zammad', 'Check_MK'] ['To enable %s for sending http requests to %s, you need create a own "notification rule" in %s.', 'Check_MK', 'Zammad', 'Check_MK']
['Configurable in the admin interface of %s.', 'Check_MK'] ['Configurable in the admin interface of %s.', 'Check_MK']
@ -26,6 +24,38 @@ class Index extends App.ControllerIntegrationBase
] ]
) )
new App.ScriptSnipped(
el: @$('.js-scriptSnipped')
header: 'Service Notification'
style: 'bash'
description: [
['Script can be located under: ||%s||', '/opt/omd/site/SITENAME/local/share/check_mk/notifications/zammad-service']
['Please make sure that the script is executable: ||%s||', 'chmod +x /opt/omd/site/SITENAME/local/share/check_mk/notifications/zammad-service']
]
content: "#!/bin/bash\n\ncurl -X POST -F \"event_id=$NOTIFY_SERVICEPROBLEMID\" -F \"host=$NOTIFY_HOSTNAME\" -F \"service=$NOTIFY_SERVICEDESC\" -F \"state=$NOTIFY_SERVICESTATE\" -F \"text=$NOTIFY_SERVICEOUTPUT\" #{App.Config.get('http_type')}://#{App.Config.get('fqdn')}/api/v1/integration/check_mk/#{App.Setting.get('check_mk_token')}"
)
new App.ScriptSnipped(
el: @$('.js-scriptSnippedExtended')
header: 'Host Notification'
style: 'bash'
description: [
['Script can be located under: ||%s||', '/opt/omd/site/SITENAME/local/share/check_mk/notifications/zammad-host']
['Please make sure that the script is executable: ||%s||', 'chmod +x /opt/omd/site/SITENAME/local/share/check_mk/notifications/zammad-host']
]
content: "#!/bin/bash\n\ncurl -X POST -F \"event_id=$NOTIFY_HOSTPROBLEMID\" -F \"host=$NOTIFY_HOSTNAME\" -F \"service=$NOTIFY_SERVICEDESC\" -F \"state=$NOTIFY_HOSTSTATE\" -F \"text=$NOTIFY_HOSTOUTPUT\" #{App.Config.get('http_type')}://#{App.Config.get('fqdn')}/api/v1/integration/check_mk/#{App.Setting.get('check_mk_token')}"
)
new App.ScriptSnipped(
el: @$('.js-scriptSnippedPost')
header: 'Further Attributes'
style: 'bash'
description: [
['It is also possible to set further attributes of created tickets. To do this, you only need to pass one additional parameter.']
]
content: '... -F "additional_ticket_attribute=some_value" ...'
)
new App.HttpLog( new App.HttpLog(
el: @$('.js-log') el: @$('.js-log')
facility: 'check_mk' facility: 'check_mk'

View file

@ -1,24 +1,19 @@
class App.ScriptSnipped extends App.Controller class App.ScriptSnipped extends App.Controller
#events:
# 'click .js-record': 'show'
elements: elements:
'.js-code': 'code' '.js-code': 'code'
constructor: -> constructor: ->
super super
#@fetch()
@records = []
@render() @render()
render: => render: =>
@html App.view('widget/script_snipped')( @html App.view('widget/script_snipped')(
records: @records header: @header || 'Usage',
description: @description description: @description
style: @style style: @style
content: @content content: @content
) )
@code.each (i, block) -> @code.each((i, block) ->
hljs.highlightBlock block hljs.highlightBlock block
)

View file

@ -14,6 +14,9 @@
<% end %> <% end %>
<% end %> <% end %>
<div class="js-form"></div> <div class="js-form"></div>
<div class="js-scriptSnippedPre"></div>
<div class="js-scriptSnipped"></div> <div class="js-scriptSnipped"></div>
<div class="js-scriptSnippedExtended"></div>
<div class="js-scriptSnippedPost"></div>
<div class="js-log"></div> <div class="js-log"></div>
</div> </div>

View file

@ -1,8 +1,10 @@
<hr> <hr>
<h2><%- @T('Usage') %></h2> <h2><%- @T(@header) %></h2>
<% if @description: %> <% if @description: %>
<% for item in @description: %> <% for item in @description: %>
<p><%- @T(item...) %></p> <p><%- @T(item...) %></p>
<% end %> <% end %>
<% end %> <% end %>
<% if @content: %>
<pre><code class="language-<%- @style %> js-code"><%- @content %></code></pre> <pre><code class="language-<%- @style %> js-code"><%- @content %></code></pre>
<% end %>

View file

@ -17,9 +17,6 @@ class Integration::CheckMkController < ApplicationController
group_id = Setting.get('check_mk_group_id') group_id = Setting.get('check_mk_group_id')
state_recovery_match = '(OK|UP)' state_recovery_match = '(OK|UP)'
# check if ticket with host is open
customer = User.lookup(id: 1)
# follow-up detection by meta data # follow-up detection by meta data
integration = 'check_mk' integration = 'check_mk'
open_states = Ticket::State.by_category(:open) open_states = Ticket::State.by_category(:open)
@ -95,17 +92,32 @@ UserAgent: #{request.env['HTTP_USER_AGENT']}
return return
end end
ticket = Ticket.create!( # define customer of ticket
group_id: group_id, customer = nil
customer_id: customer.id, if params[:customer].present?
title: title, customer = User.find_by(login: params[:customer].downcase)
preferences: { if !customer
customer = User.find_by(email: params[:customer].downcase)
end
end
if !customer
customer = User.lookup(id: 1)
end
params[:state] = nil
params[:customer] = nil
ticket = Ticket.new(Ticket.param_cleanup(Ticket.association_name_to_id_convert(params)))
ticket.group_id ||= group_id
ticket.customer_id = customer.id
ticket.title = title
ticket.preferences = {
check_mk: { check_mk: {
host: params[:host], host: params[:host],
service: params[:service], service: params[:service],
}, },
} }
) ticket.save!
Ticket::Article.create!( Ticket::Article.create!(
ticket_id: ticket.id, ticket_id: ticket.id,
type_id: Ticket::Article::Type.find_by(name: 'web').id, type_id: Ticket::Article::Type.find_by(name: 'web').id,

View file

@ -1,6 +1,12 @@
require 'rails_helper' require 'rails_helper'
RSpec.describe 'Integration Check MK', type: :request do RSpec.describe 'Integration Check MK', type: :request do
let(:customer_user) do
create(:customer_user)
end
let(:group) do
create(:group)
end
before do before do
token = SecureRandom.urlsafe_base64(16) token = SecureRandom.urlsafe_base64(16)
@ -9,6 +15,7 @@ RSpec.describe 'Integration Check MK', type: :request do
end end
describe 'request handling' do describe 'request handling' do
it 'does fail without a token' do it 'does fail without a token' do
post '/api/v1/integration/check_mk/', params: {} post '/api/v1/integration/check_mk/', params: {}
expect(response).to have_http_status(:not_found) expect(response).to have_http_status(:not_found)
@ -22,6 +29,97 @@ RSpec.describe 'Integration Check MK', type: :request do
expect(json_response['error']).to eq('Invalid token!') expect(json_response['error']).to eq('Invalid token!')
end end
context 'service check' do
it 'does create ticket with customer email' do
params = {
event_id: '123',
state: 'down',
host: 'some host',
service: 'some service',
customer: customer_user.email,
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.customer.email).to eq(customer_user.email)
expect(ticket.articles.count).to eq(1)
end
it 'does create ticket with customer login' do
params = {
event_id: '123',
state: 'down',
host: 'some host',
service: 'some service',
customer: customer_user.login,
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.customer.email).to eq(customer_user.email)
expect(ticket.articles.count).to eq(1)
end
it 'does create ticket with group' do
params = {
event_id: '123',
state: 'down',
host: 'some host',
service: 'some service',
group: group.name,
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.group.name).to eq(group.name)
expect(ticket.articles.count).to eq(1)
end
it 'does create ticket with extra field', db_strategy: :reset do
create :object_manager_attribute_text, name: 'text1'
ObjectManager::Attribute.migration_execute
params = {
event_id: '123',
state: 'down',
host: 'some host',
service: 'some service',
text1: 'some text'
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.text1).to eq('some text')
end
it 'does create and close a ticket' do it 'does create and close a ticket' do
params = { params = {
event_id: '123', event_id: '123',
@ -182,7 +280,80 @@ RSpec.describe 'Integration Check MK', type: :request do
expect(ticket.articles.count).to eq(3) expect(ticket.articles.count).to eq(3)
end end
it 'does double create and auto close - host only' do it 'does double create and auto close - with host recover' do
params = {
event_id: '123',
state: 'down',
host: 'some host',
service: 'some service',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
params = {
event_id: '123',
state: 'up',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to eq('no open tickets found, ignore action')
expect(json_response['ticket_ids']).to eq(nil)
ticket.reload
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
end
end
context 'host check' do
it 'does create and close a ticket' do
params = {
event_id: '123',
state: 'down',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
params = {
event_id: '123',
state: 'up',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).not_to be_empty
expect(json_response['ticket_ids']).to include(ticket.id)
ticket.reload
expect(ticket.state.name).to eq('closed')
expect(ticket.articles.count).to eq(2)
end
it 'does double create and auto close' do
params = { params = {
event_id: '123', event_id: '123',
state: 'down', state: 'down',
@ -232,6 +403,108 @@ RSpec.describe 'Integration Check MK', type: :request do
expect(ticket.state.name).to eq('closed') expect(ticket.state.name).to eq('closed')
expect(ticket.articles.count).to eq(3) expect(ticket.articles.count).to eq(3)
end end
it 'does ticket close which get ignored' do
params = {
event_id: '123',
state: 'up',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to eq('no open tickets found, ignore action')
end
it 'does double create and no auto close' do
Setting.set('check_mk_auto_close', false)
params = {
event_id: '123',
state: 'down',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
params = {
event_id: '123',
state: 'down',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to eq('ticket already open, added note')
expect(json_response['ticket_ids']).to include(ticket.id)
ticket.reload
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(2)
params = {
event_id: '123',
state: 'up',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to eq('ticket already open, added note')
expect(json_response['ticket_ids']).to include(ticket.id)
ticket.reload
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(3)
end
it 'does double create and auto close - with service recover' do
params = {
event_id: '123',
state: 'down',
host: 'some host',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to be_truthy
expect(json_response['ticket_id']).to be_truthy
expect(json_response['ticket_number']).to be_truthy
ticket = Ticket.find(json_response['ticket_id'])
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
params = {
event_id: '123',
state: 'up',
host: 'some host',
service: 'some service',
}
post "/api/v1/integration/check_mk/#{Setting.get('check_mk_token')}", params: params
expect(response).to have_http_status(:ok)
expect(json_response).to be_a_kind_of(Hash)
expect(json_response['result']).to eq('no open tickets found, ignore action')
expect(json_response['ticket_ids']).to eq(nil)
ticket.reload
expect(ticket.state.name).to eq('new')
expect(ticket.articles.count).to eq(1)
end
end
end end
end end