Learning GraphQL is easiest when using GraphiQL directly in LeanIX as explained e.g. in GraphQL Basics and GraphQL Advanced. For daily use, you often need to embed the calls into a scripting language like Python. GraphQL with Python gives you some ideas on how to set things up.
This page walks you through a concrete use case often seen both in initial setups and bulk updates - to handle application run and management costs which are represented in LeanIX as an attribute on the relation between Application and IT Component.
1. Initial Import
Suppose we have an import XLS with the following structure
Application name | IT Component name | Annual costs |
---|---|---|
App1 | ITC1 | 125 |
App1 | ITC2 | 250 |
App2 | ITC1 | 500 |
App2 | ITC2 | 1000 |
The following script then creates the Fact Sheets and the relations. Note that none of the used Fact Sheets must exist before.
import json
import requests
import pandas as pd
# Insert your token and domain (e.g. app.leanix.net)
api_token = '<API Token>'
auth_url = 'https://<domain>/services/mtm/v1/oauth2/token'
request_url = 'https://<domain>/services/pathfinder/v1/graphql'
# Get the bearer token - see https://dev.leanix.net/v4.0/docs/authentication
response = requests.post(auth_url, auth=('apitoken', api_token), data={'grant_type': 'client_credentials'})
response.raise_for_status()
access_token = response.json()['access_token']
auth_header = 'Bearer ' + access_token
header = {'Authorization': auth_header}
# General function to call GraphQL given a query
def call(query):
data = {"query" : query}
json_data = json.dumps(data)
response = requests.post(url=request_url, headers=header, data=json_data)
response.raise_for_status()
return response.json()
# Function to create an application via GraphQL
def createApplication(name):
query = """
mutation {
createFactSheet(input: {name: "%s", type: Application}) {
factSheet {
id
}
}
}
""" % (name)
print "Create Application " + name
response = call(query)
return response['data']['createFactSheet']['factSheet']['id']
# Function to create an IT Component via GraphQL
def createITComponent(name):
query = """
mutation {
createFactSheet(input: {name: "%s", type: ITComponent}) {
factSheet {
id
}
}
}
""" % (name)
print "Create IT Component " + name
response = call(query)
return response['data']['createFactSheet']['factSheet']['id']
# Function to create a relation between Application and IT Component with the costs attribute
def createRelationWithCosts(app, itc, costs) :
query = """
mutation {
updateFactSheet(id: "%s", patches:
[{op: add,
path: "/relITComponentToApplication/new_1",
value: "{\\\"factSheetId\\\": \\\"%s\\\",\\\"costTotalAnnual\\\": %s}"}]) {
factSheet {
id
}
}
}
""" % (itc, app, costs)
print "Create relation with costs: " + itc + "->" + app + " = " + str(costs)
call(query)
# Start of the main logic
# 1. Read the input as a CSV
df = pd.read_csv('example.csv')
# 2. Make sure to create all applications, and save the created ids
apps = {}
for appName in df.loc[:, "app"].unique():
apps[appName] = createApplication(appName)
# 3. Make sure to create all IT Components, and save the created ids
itcs = {}
for itcName in df.loc[:, "itc"].unique():
itcs[itcName] = createITComponent(itcName)
# 4. Create the relations based on the saved ids
for index, row in df.iterrows():
createRelationWithCosts(apps[row['app']], itcs[row['itc']], row['costs'])
2. Export to XLS
To export the costs from LeanIX XLS, use a simple GraphQL script, e.g. in GraphiQL.
{
allFactSheets(factSheetType: Application) {
edges {
node {
... on Application {
name
relApplicationToITComponent {
edges {
node {
factSheet {
name
}
costTotalAnnual
}
}
}
}
}
}
}
}
This will give you a result like the following:
{
"data":{
"allFactSheets":{
"edges":[
{
"node":{
"name":"App1",
"relApplicationToITComponent":{
"edges":[
{
"node":{
"factSheet":{
"name":"ITC1"
},
"costTotalAnnual":125
}
},
{
"node":{
"factSheet":{
"name":"ITC2"
},
"costTotalAnnual":250
}
}
]
}
}
},
{
"node":{
"name":"App2",
"relApplicationToITComponent":{
"edges":[
{
"node":{
"factSheet":{
"name":"ITC1"
},
"costTotalAnnual":500
}
},
{
"node":{
"factSheet":{
"name":"ITC2"
},
"costTotalAnnual":1000
}
}
]
}
}
}
]
}
}
}
Now, just copying the result to an online tool like https://konklone.io/json/, or using your company's preferred JSON to XLS / CSV converter will give you a nice spreadsheet.
3. Update
The scenario under 1. is great if you have no data in your workspace. Another typical case is to update existing values. We will assume that you have an input like the following:
Application ID | IT Component ID | Costs |
---|---|---|
ad6850af-37e8-4f5b-8256-446edda7bdbe | 0e674e57-bff8-48a8-b144-26a434e8e415 | 125 |
ad6850af-37e8-4f5b-8256-446edda7bdbe | a135099c-ad61-4871-aa1a-3f6404b3d575 | 250 |
ab2438f5-8295-456e-b0e2-622b07e62352 | 0e674e57-bff8-48a8-b144-26a434e8e415 | 500 |
ab2438f5-8295-456e-b0e2-622b07e62352 | a135099c-ad61-4871-aa1a-3f6404b3d575 | 1000 |
The LeanIX IDs could either be obtained by XLS export (see https://docs.leanix.net/docs/import-export-fact-sheet-data) or just by another GraphQL call.
Now, the script is similar to before. We need to fetch all Applications to get the correct relation ID, and will then just execute a GraphQL mutation per row.
import json
import requests
import pandas as pd
# Insert your token and domain (e.g. app.leanix.net)
api_token = '<API Token>'
auth_url = 'https://<domain>/services/mtm/v1/oauth2/token'
request_url = 'https://<domain>/services/pathfinder/v1/graphql'
# Get the bearer token - see https://dev.leanix.net/v4.0/docs/authentication
response = requests.post(auth_url, auth=('apitoken', api_token),
data={'grant_type': 'client_credentials'})
response.raise_for_status()
access_token = response.json()['access_token']
auth_header = 'Bearer ' + access_token
header = {'Authorization': auth_header}
# General function to call GraphQL given a query
def call(query):
data = {"query" : query}
json_data = json.dumps(data)
response = requests.post(url=request_url, headers=header, data=json_data)
response.raise_for_status()
return response.json()
# Read all existing Application - IT Component relations
def getRelations():
query = """
{
allFactSheets(factSheetType: Application) {
edges {
node {
id
... on Application {
relApplicationToITComponent {
edges {
node {
id
factSheet {
id
}
}
}
}
}
}
}
}
}
"""
response = call(query)
apps = {}
for appNode in response['data']['allFactSheets']['edges']:
appId = appNode['node']['id']
apps[appId] = {}
for relationNode in appNode['node']['relApplicationToITComponent']['edges']:
relationId = relationNode['node']['id']
itcId = relationNode['node']['factSheet']['id']
apps[appId][itcId] = relationId
return apps
# Update the costs attribute on the existing relation
def updateCosts(app, itc, rel, costs) :
query = """
mutation {
updateFactSheet(id: "%s",
patches: [{op: replace,
path: "/relApplicationToITComponent/%s",
value: "{\\\"factSheetId\\\": \\\"%s\\\",\\\"costTotalAnnual\\\": %s}"}]) {
factSheet {
id
}
}
}
""" % (app, rel, itc, costs)
print "Update costs: " + app + "->" + itc + " = " + str(costs)
response = call(query)
print response
# Start of the main program
# 1. Read the input
df = pd.read_csv('exampleUpdate.csv')
# 2. Get the existing relations from LeanIX
apps = getRelations()
# 3. Update the cost attribute for each row
for index, row in df.iterrows():
updateCosts(row['app'], row['itc'], apps[row['app']][row['itc']], row['costs'])