Home Python Integrating with Jira APIs | Zato

Integrating with Jira APIs | Zato

0
Integrating with Jira APIs | Zato

[ad_1]

Overview

Persevering with within the sequence of articles about latest cloud connections in Zato 3.2, this episode covers Atlassian Jira from the attitude of invoking its APIs to construct integrations between Jira and different programs.

There are basically two use modes of integrations with Jira:

  1. Jira reacts to occasions going down in your initiatives and invokes your endpoints accordingly through WebHooks. On this case, it’s Jira that explicitly establishes connections with and sends requests to your APIs.
  2. Jira initiatives are queried periodically or as a consequence of occasions triggered by Jira utilizing means apart from WebHooks.

The primary case is often extra easy to conceptualize – you create a WebHook in Jira, level it to your endpoint and Jira invokes it when a scenario of curiosity arises, e.g. a brand new ticket is opened or up to date. I’ll speak about this variant of integrations with Jira in a future instalment as the present one is in regards to the different scenario, when it’s your programs that set up connections with Jira.

The rationale why it’s extra sensible to first communicate in regards to the second kind is that, even when WebHooks are considerably simpler to motive about, they do include their very own ramifications.

To begin off, assuming that you just use the cloud-based model of Jira (e.g. https://instance.atlassian.web), it’s good to have a publicly accessible endpoint for Jira to invoke via WebHooks. Fairly often, that is undesirable as a result of the programs that it’s good to combine with could also be inside ones, by no means meant to be uncovered to public networks.

Secondly, your endpoints have to have a TLS certificates signed by a public Certificates Authority and so they should be accessible on port 443. Once more, each of those are one thing that almost all enterprise programs is not going to permit in any respect or it could take months or years to course of such a change internally throughout the assorted company departments concerned.

Lastly, even when a WebHook can be utilized, it’s not at all times a provided that the preliminary info that you just obtain within the request from a WebHook will already comprise all the things that you just want in your specific integration service. Thus, you’ll nonetheless want a technique to problem requests to Jira to lookup particulars of a specific object, reminiscent of tickets, on this method decreasing WebHooks to the position of preliminary triggers of an interplay with Jira, e.g. a WebHook invokes your endpoint, you may have a ticket ID on enter and then you definately invoke Jira again anyway to acquire all the main points that you just really want in your small business integration.

The tip scenario is that, though WebHooks are a helpful idea that I’ll write about in a future article, they might very properly not be ample for a lot of integration use instances. That’s the reason I begin with integration strategies which are various to WebHooks.

Alternate options to WebHooks

If, in our case, we can not use WebHooks then what subsequent? Two good approaches are:

  1. Scheduled jobs
  2. Reacting to emails (through IMAP)

Scheduled jobs will allow you to periodically inquire with Jira in regards to the modifications that you haven’t processed but. As an illustration, with a job definition as beneath:

Now, the service configured for this job will probably be invoked as soon as per minute to hold out any integration works required. As an illustration, it will possibly get a listing of tickets for the reason that final time it ran, course of every of them as required in your small business context and replace a database with details about what has been simply carried out – the database will be based mostly on Redis, MongoDB, SQL or the rest.

Integrations constructed round scheduled jobs make most sense when it’s good to make periodic sweeps throughout a big swaths of enterprise knowledge, these are the “Give me all the things that modified within the final interval” sort of interactions if you have no idea exactly how a lot knowledge you’re going to obtain.

Within the particular case of Jira tickets, although, an fascinating various could also be to mix scheduled jobs with IMAP connections:

The thought right here is that when new tickets are opened, or when updates are made to current ones, Jira will ship out notifications to particular electronic mail addresses and we are able to make the most of it.

As an illustration, you’ll be able to inform Jira to CC or BCC an tackle reminiscent of zato@instance.com. Now, Zato will nonetheless run a scheduled job however as a substitute of connecting with Jira immediately, that job will lookup unread emails for it inbox (“UNSEEN” per the related RFC).

Something that’s unread should be new for the reason that final iteration which signifies that we are able to course of every such electronic mail from the inbox, on this method guaranteeing that we course of solely the newest updates, dishing out with the necessity for our personal database of tickets already processed. We will extract the ticket ID or different particulars from the e-mail, lookup its particulars in Jira and the proceed as wanted.

All the main points of easy methods to work with IMAP emails are offered within the documentation however it could boil right down to this:

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyService(Service):

    def deal with(self):
        conn = self.electronic mail.imap.get('My Jira Inbox').conn

        for msg_id, msg in conn.get():

            # Course of the message right here ..
            process_message(msg.knowledge)

            # .. and mark it as seen in IMAP.
            msg.mark_seen()

The pure query is – how would the “process_message” operate extract particulars of a ticket from an electronic mail?

There are a number of methods:

  1. Every electronic mail has a topic of a hard and fast kind – “[JIRA] (ABC-123) Right here goes description”. On this case, ABC-123 is the ticket ID.
  2. Every electronic mail will comprise a abstract, such because the one beneath, which will also be parsed:
         Abstract: Right here goes description
             Key: ABC-123
             URL: https://instance.atlassian.web/browse/ABC-123
         Mission: My Mission
      Difficulty Kind: Enchancment
Impacts Variations: 1.3.17
     Surroundings: Manufacturing
        Reporter: Reporter Identify
        Assignee: Assignee Identify
  1. Lastly, every electronic mail can have an “X-Atl-Mail-Meta” header with fascinating metadata that will also be parsed and extracted:
X-Atl-Mail-Meta: user_id="123456:12d80508-dcd0-42a2-a2cd-c07f230030e5",
                 event_type="Difficulty Created",
                 tenant="https://instance.atlassian.web"

The primary choice is probably the most easy and sure probably the most handy one – merely parse out the ticket ID and name Jira with that ID on enter for all the opposite details about the ticket. The way to do it precisely is introduced within the subsequent chapter.

No matter how we parse the emails, the necessary half is that we all know that we invoke Jira solely when there are new or up to date tickets – in any other case there wouldn’t have been any new emails to course of. Furthermore, as a result of it’s our aspect that invokes Jira, we don’t expose our inside system to the general public community immediately.

Nonetheless, from the attitude of the general safety structure, electronic mail continues to be a part of the assault floor so we have to guarantee that we learn and parse emails with that in view. In different phrases, no matter whether or not it’s Jira invoking us or our studying emails from Jira, all the standard safety precautions relating to API integrations and accepting enter from exterior assets, all that also holds and must be a part of the design of the combination workflow.

Creating Jira connections

The above introduced the methods through which we are able to arrive on the step of once we invoke Jira and now we’re prepared to truly do it.

As with different sorts of connections, Jira connections are created in Zato Dashboard, as beneath. Word that you just use the e-mail tackle of a person on whose behalf you connect with Jira however the one different credential is that person’s API token beforehand generated in Jira, not the person’s password.

Invoking Jira

With a Jira connection in place, we are able to now create a Python API service. On this case, we settle for a ticket ID on enter (known as “a key” in Jira) and we return just a few particulars in regards to the ticket to our caller.

That is the sort of a service that could possibly be invoked from a service that’s triggered by a scheduled job. That’s, we might separate the duties, one service could be answerable for opening IMAP inboxes and parsing emails and the one beneath could be answerable for communication with Jira.

Because of this free coupling, we make all the things far more reusable – that the providers will be modified independently is however one half and the extra necessary aspect is that, with such separation, each of them will be reused by future providers as properly, with out tying them rigidly to this one integration alone.

# -*- coding: utf-8 -*-

# stdlib
from dataclasses import dataclass

# Zato
from zato.frequent.typing_ import cast_, dictnone
from zato.server.service import Mannequin, Service

# ###########################################################################

if 0:
    from zato.server.connection.jira_ import JiraClient

# ###########################################################################

@dataclass(init=False)
class GetTicketDetailsRequest(Mannequin):
    key: str

@dataclass(init=False)
class GetTicketDetailsResponse(Mannequin):
    assigned_to: str = ''
    progress_info: dictnone = None

# ###########################################################################

class GetTicketDetails(Service):

    class SimpleIO:
        enter  = GetTicketDetailsRequest
        output = GetTicketDetailsResponse

    def deal with(self):

        # That is our enter knowledge
        enter = self.request.enter # sort: GetTicketDetailsRequest

        # .. create a reference to our connection definition ..
        jira = self.cloud.jira['My Jira Connection']

        # .. receive a consumer to Jira ..
        with jira.conn.consumer() as consumer:

            # Solid to allow code completion
            consumer = cast_('JiraClient', consumer)

            # Get particulars of a ticket (problem) from Jira
            ticket = consumer.get_issue(enter.key)

        # Observe that ticket could also be None (e.g. invalid key), therefore this 'if' guard ..
        if ticket:

            # .. construct a shortcut reference to all of the fields within the ticket ..
            fields = ticket['fields']

            # .. construct our response object ..
            response = GetTicketDetailsResponse()
            response.assigned_to = fields['assignee']['emailAddress']
            response.progress_info = fields['progress']

            # .. and return the response to our caller.
            self.response.payload = response

# ###########################################################################

Making a REST channel and testing it

The final remaining half is a REST channel to invoke our service via. We are going to present the ticket ID (key) on enter and the service will reply with what was present in Jira for that ticket.

We at the moment are prepared for the ultimate step – we invoke the channel, which invokes the service which communicates with Jira, remodeling the response from Jira to the output that we want:

$ curl localhost:17010/jira1 -d '{"key":"ABC-123"}'
{
    "assigned_to":"zato@instance.com",
    "progress_info": {
        "progress": 10,
        "complete": 30
    }
}
$

And that is all the things for at this time – simply do not forget that this is only one method of integrating with Jira. The opposite one, utilizing WebHooks, is one thing that I’ll go into in one of many future articles.

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here