1
0
-1

We are about deploying Exalate as means to synchronize issues from Jira Service Management (JSM) projects to Jira Software Projects (JSW) for we do not have classical 1st level support, the number of people possibly handling incoming requests (tickets and other types) is to high and so would be the costs for the appropriate number of JSM agents. The POC for this setup was made by end of last year with the help of some of your colleagues.

In the meantime Atlassian introduced organization details as kind of attributes to organizations in JSM. We want (and need) to have to set some of those details and put their values into custom fields when filling the fields of the destination issue in the Exalate synchronization. Alas the attributes can (as far as we know and have found out) only be retrieved from the API endpoint I provided. Its hostname is not that of the instance so the usual approach for the httpClient function to just provide the URL path does not apply and work here. So we are looking for a solution, ideally one where the Exalate apps authentication can be implizitely be used (as it is done with httpClient() so far).

    CommentAdd your comment...

    2 answers

    1.  
      2
      1
      0

      // Function to fetch organization details
      function fetchOrganizationDetails(organizationId) {
        // Replace with the actual JSM API endpoint URL
        const url = "https://<your_jsm_api_hostname>/rest/servicedeskapi/organization/" + organizationId;

        // Replace with appropriate authentication method (modify based on actual API)
        const credentials = btoa(encodeURIComponent("<your_username>") + ":" + encodeURIComponent("<your_password>"));
        const headers = {
          "Authorization": "Basic " + credentials
        };

        return fetch(url, { headers })
          .then(response => response.json())
          .then(data => data); // Replace with specific data extraction logic
      }

      // Function to set custom fields in destination issue
      function setCustomFields(issue, organizationDetails) {
        // Replace with logic to map organization details to specific custom field IDs
        issue.fields["customfield_10001"] = organizationDetails.field1Value; // Replace with actual custom field ID
        issue.fields["customfield_10002"] = organizationDetails.field2Value; // Replace with actual custom field ID
        // ... add logic for other custom fields
      }

      // Example usage within Exalate sync configuration (replace with actual trigger point)
      const issue = context.destinationIssue;
      const organizationId = issue.fields.organizationId; // Replace with field containing organization ID

      fetchOrganizationDetails(organizationId)
        .then(organizationDetails => {
          setCustomFields(issue, organizationDetails);
        })
        .catch(error => {
          console.error("Error fetching organization details:", error);
        });




      Remember to replace the following:

      • <your_jsm_api_hostname> with the actual hostname of your JSM instance.
      • <your_username> and <your_password> with your Exalate app credentials (if using basic authentication).
      • "customfield_10001" and "customfield_10002" with the actual IDs of your custom fields in JSW.
      • Update the logic in fetchOrganizationDetails to extract the specific details you need from the JSM API response.
      • Update the logic in setCustomFields to map the retrieved details to the appropriate custom field IDs in JSW.

      This script provides a starting point. You'll need to adapt it based on your specific Exalate scripting language, JSM API details, and custom field configuration.

        CommentAdd your comment...
      1.  
        1
        0
        -1


        def USER = ",,,,"
        def PASS = "...."
        replica."SIC_SERVER_INFO" = (new GroovyHttpClient(httpClient))
          .http("GET", "https://url/rest/api/2/serverInfo?expand=all", null, 
          ["Authorization": "Basic ${(USER+":"+PASS).bytes.encodeBase64().toString()}".toString()])
          { response ->
            if (response.code > 200) 
              debug.error("GET https://support.idalko.com/rest/api/2/serverInfo?expand=all failed with ${response.code}: "+response.body)
            else response.body
          }

         

        This script should connect to a Jira instance given the specified user and password, then perform a GET request to retrieve server information. It will store this information in the field "SIC_SERVER_INFO" on the replica issue. If the response code indicates an error (anything over 200), it will log an error with the response code and body.





        1. Jillani Fazal

          I slightly adopted your code: 


          String CSM_API_User = "<ouruser>"
          String CSM_API_Token = "<API-Token>"
          String CSM_API_Instance = "<instance-number"
          String CSM_API_Base_URL = "https://api.atlassian.com/jsm/csm/cloudid/${CSM_API_Instance}/api/v1"
          /* ENDE interne Angaben */
          
          def getFromCSM = { csmtype, csmvalue ->
              CSM_API_URL = CSM_API_Base_URL+"/${csmtype}/${csmvalue}"
              (new GroovyHttpClient(httpClient)).http(
                  "GET", 
                  CSM_API_URL, 
                  null, 
                  ["Autorization": "Basic ${(CSM_API_User+":"+CSM_API_Token).bytes.encodeBase64().toString()}".toString()]) { response ->
                      if (response.code > 200) debug.error("GET ${CSM_API_URL} failed with ${response.code}: "+response.body)
                      else response.body
                  }
          }
          
          orga_details = getFromCSM("organization", "1")

          The resulting URL is correct, I reveice a HTTP 431 error (which is not defined in the API docs) and an empty response body (meaning no data beyond the URL in the error output).


          We made it work using generic Groovy tooling. The closure definition is:

          import groovy.json.JsonSlurper
          def getFromCSM = { csmtype, csmvalue ->
              CSM_API_URL = CSM_API_Base_URL+"/${csmtype}/${csmvalue}"
              authorization = (CSM_API_User+":"+CSM_API_Token).bytes.encodeBase64().toString()
              req = new URL(CSM_API_URL).openConnection()
              req.setRequestProperty("Authorization", "Basic " + authorization)
              req.requestMethod = 'GET'
              content = req.getInputStream().getText()
              if (req.responseCode > 200) {
                  debug.error("GET ${CSM_API_URL} failed with ${req.responseCode}: " + content)
              } else {
                  (new JsonSlurper()).parseText(content)
              }
          }




        CommentAdd your comment...