Example Creating OSLC Links with Python
We have noticed some OSLC Connect users with IBM ELM want to bulk import some OSLC Links. If you are using Global Configuration, the Links are only stored in Jira, and you can rapidly import links using the Jira API.
Note that when using this technique, OSLC Connect does not validate your links, targets, or GC context. The validity of the links created will be up to the script creator and executor.
We are starting with a simple Excel spreadsheet. This has a Jira Key, a Link Type, and Target Resource(s). The target resources are the URIs for the DNG Requirements.
We are then using a basic Python script that will read the Excel file (using Pandas), Use REST APIs with Jira (using requests), and then inspecting and creating Json content for the body of our requests.
We have documented the script so users can learn and update it.
# Simple demonstration of reading an excel file to create some OSLC links in Jira
#
# Format of the XLS file is
#
# Jira Key, Relationship Type, Target URL (in this case DNG)
#
# Basic flow is to
# 1) Read XLS
# 2) Iterate across Rows (do any parsing)
# 3) Check to see if a link already exists
# 5) Add remote link if needed
#
# Note, we are not checking the validity of the end-points or the proper formating of
# the relationship type, or extracting the remote title.
#
# Note, optimizations can be done, but this is a demonstrator not intended for performance optimizations
# imports
import pandas as pd
import os
from dotenv import load_dotenv
import requests
from requests.auth import HTTPBasicAuth
import json
def checkForLinkExisting (
JiraKey : str,
LinkType : str,
LinkTarget : str,
) -> bool :
# Check to see if a link exists already
# Get the remote links on the artifact
# Inspect if the link already exists
url = f"{jiraRoot}/rest/api/latest/issue/{JiraKey}/remotelink"
existingLinks = requests.get(url, auth=basic, verify=False)
if existingLinks.status_code == 200 :
linksObj = existingLinks.json()
for link in linksObj :
if link['application']['type'] == 'com.sodius.oslc.app.jira' :
if link['relationship'] == LinkType :
if link['object']['url'] == LinkTarget :
# link already exists, return true
return True
# no link found, return false
return False
def addLink (
JiraKey : str,
LinkType : str,
LinkTarget : str,
LinkTitle : str = "Generated Title",
) -> bool :
url = f"{jiraRoot}/rest/api/latest/issue/{JiraKey}/remotelink"
headers = {'Content-Type': 'application/json'}
# Now build the Json structure https://developer.atlassian.com/server/jira/platform/jira-rest-api-for-remote-issue-links/
# With OSLC specific configuration https://docs.sodiuswillert.com/oslc-connect/latest/understanding-oslc-connect-for-jira-link-storage
# {
# "application": {
# "type": "com.sodius.oslc.app.jira",
# "name": "Collaboration Link"
# },
# "relationship": LinkType,
# "object": {
# "url": LinkTarget,
# "title": "Generated Link",
# }
# }
body = json.dumps( {'application': { 'type' : 'com.sodius.oslc.app.jira' , 'name' : 'Collaboration Link' },
'relationship' : LinkType ,
"object" : { 'url' : LinkTarget, 'title' : LinkTitle} } )
addLink = requests.post(url, auth=basic, headers=headers, verify=False, data=body)
if addLink.status_code==201 :
return True
else :
return False
# Load our user password information from file
load_dotenv()
basic = HTTPBasicAuth(os.getenv('JIRA_USER_ID'), os.getenv('JIRA_USER_PASSWORD') )
jiraRoot = 'https://phoenix-jira.sodiuswillert.cloud'
links_df = pd.read_excel('example.xlsx')
# Interate across our rows in our Excel file (now in a data frame)
for i in range(0, len(links_df)):
# Need to split the link Target
row = links_df.iloc[i]
jiraKey = row['Jira Key']
linkType = row['Link Type']
# Getting the targets of the links. Assuming multiple and removing the Query parameters
targets = [text.strip().split('?')[0] for text in row['Target Resource'].split(",")]
for target in targets:
linkExists = checkForLinkExisting( jiraKey, linkType, target )
if not linkExists:
print(f'Creating Link on {jiraKey} to {str(target)}')
addLink( jiraKey, linkType, target )
else:
print(f'Skipping Link (already there) on {jiraKey} to {str(target)}')
All scripts are provided as is. Users are responsible for testing and validating the behavior. The purpose is an example of what is possible. Enhancements or customizations can be requested and performed under a Statement of Work.