We use OTRS for our Service Desk, and R & D use JIRA for Change Management. Naturally we would like to integrate those two systems in a good way. Typically we would like to have a field or two in OTRS. So here is how we have integrated the two systems:
- jiraid to hold the jira identifier of type hubba-123
- Name: jiraid
- Label: Jira
- Field Order: (What you like it to be)
- Field Type: Text
- ObjectType: Ticket
- Default value: (blank)
- Show Link: This makes a link that you can click on in OTRS and go directly to the JIRA ticket
Code: Select all
https://<YOUR-JIRA-HOST>/browse/$LQData{"jiraid"}
- jirastate to hold the jira state
- Name: jirastate
- Label: Jira state
- Field Order: (What you like it to be)
- Field Type: Text
- ObjectType: Ticket
- Default value: (blank)
- Show Link: (blank)
So go into SysConfig and find the following config
Code: Select all
Frontend::Agent::Ticket::ViewFreeText
Code: Select all
Ticket::Frontend::AgentTicketFreeText###DynamicField
Next is to show the values of the two fields in the Ticket Information if they have content. That is done by doing the same as above but on the follwing SysConfig category:
Code: Select all
Ticket::Frontend::AgentTicketZoom###DynamicField
If you now add a valid JIRA ID to a ticket in the Free Fields, and hit save you will now see a clickable link to Jira in the Ticket Information window. Next we need to get the state out of JIRA for those tickets.
Here I got inspiration from https://github.com/rttag/RTT-JiraWebhook. Basically we are going to use the Web Hook call back feature of JIRA https://developer.atlassian.com/display ... s+Overview. To use that we need to set up a thing on the OTRS server to handle the POST request from JIRA.
The following is the content of the file
Code: Select all
<OTRS-INSTALL-DIR>/bin/cgi-bin/jira.pl
Code: Select all
#!/usr/bin/perl
#
# RTT-JiraWebhook
#
# Copyright (C) 2013-2014 Realtime Technology AG, http://rtt.ag/
#
# Author: Martin Gross <martin.gross@rtt.ag>
# License: GNU AFFERO GENERAL PUBLIC LICENSE Version 3, November 2007
#
# THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
# PARTICULAR PURPOSE.
#
# Amended by: Stein Erik Berget, seberget@esenic.com
#
use strict;
use warnings;
use FindBin qw($Bin);
use lib "$Bin/../..";
use lib "$Bin/../../Kernel/cpan -lib";
use lib "$Bin/../../Custom";
use Kernel::System::Encode;
use Kernel::System::Log;
use Kernel::System::Time;
use Kernel::System::DB;
use Kernel::System::Main;
use Kernel::Config;
use Kernel::System::Ticket;
use CGI;
use JSON::XS;
# create common objects
my %CommonObject = ();
$CommonObject{ConfigObject} = Kernel::Config->new();
$CommonObject{LogObject} = Kernel::System::Log->new(
LogPrefix => 'JIRA Webhook',
%CommonObject,
);
$CommonObject{MainObject} = Kernel::System::Main->new(%CommonObject);
$CommonObject{TimeObject} = Kernel::System::Time->new(%CommonObject);
$CommonObject{DBObject} = Kernel::System::DB->new(%CommonObject);
$CommonObject{TicketObject} = Kernel::System::Ticket->new(%CommonObject);
my $q = new CGI;
my @fields = $q->param();
print $q->header();
my $jsondata;
if (!defined($q->param('POSTDATA'))) {
exit('No Postdata!');
}
$jsondata = decode_json($q->param('POSTDATA'));
my @TicketIDs = $CommonObject{TicketObject}->TicketSearch(
Result => 'ARRAY',
DynamicField_jiraid => {
Equals => $jsondata->{'issue'}->{'key'},
},
UserID => '1',
Permission => 'rw',
CacheTTL => '1',
);
foreach my $TicketID(@TicketIDs) {
my %Ticket = $CommonObject{TicketObject}->TicketGet(
TicketID => $TicketID,
UserID => 1,
);
my $newState = $jsondata->{'issue'}->{'fields'}->{'status'}->{'name'};
my $oldState = $CommonObject{TicketObject}->{DynamicFieldBackendObject}->ValueGet(
DynamicFieldConfig => $CommonObject{TicketObject}->{DynamicFieldObject}->DynamicFieldGet(Name => "jirastate"),
ObjectID => $TicketID,
);
if ($newState ne $oldState) {
$CommonObject{TicketObject}->{DynamicFieldBackendObject}->ValueSet(
DynamicFieldConfig => $CommonObject{TicketObject}->{DynamicFieldObject}->DynamicFieldGet(Name => "jirastate"),
ObjectID => $TicketID,
Value => $newState,
UserID => 1,
);
}
}
This next part is optional.
I wanted to do as litle custom development as possible, and make use of the standard features of OTRS. Since I'm on OTRS 3.3.3 I can use the Event feature of GenericAgent. There I've configured to listen to
Code: Select all
Ticket:TicketDynamicFieldUpdate_jirastate
The first time you create the link from OTRS the jirastate field will be empty. Which is something I hope I'll fix in part II of this endeavour. That is have OTRS invoke JIRA with a webhook like feature so I'll add the OTRS ticket ID to a field in JIRA. To be continued...