OS version:RHEL 8
Hello Python Experts:
I need your help to add a server via REST API by using variables for the keys and values.
In general it works but I need some help to get the right syntax for the key and value definitions by using variables.
I need the right code to post key and value which are defined by a variable:
'tag_<VARIABLE1>': '<VARIABLE1>', # how is the right syntax to use the variable at the "json={" part?
And another question from my site: is there a more dynamical way to add attributes instead of such a rigid list, especially for the labels which are dynamic?
Has somebody a solution?
Thanks a lot!
Greetings JP
here is my code example:
session = requests.session()
session.headers['Authorization'] = f"Bearer {USERNAME} {PASSWORD}"
session.headers['Accept'] = 'application/json'
SITE = "XXX"
SERVER_ALIAS = "ALIAS"
SERVER_IP = "127.0.0.1"
ENVIRONMENT = "Test"
VARIABLE1 = "1XXXXX"
VARIABLE2 = "'tag_" + VARIABLE1 + "': '" + VARIABLE1 + "'"
resp = session.post(
f"{API_URL}/domain-types/host_config/collections/all",
headers={
"Content-Type": 'application/json',
json={
'folder':'/test/test',
'host_name': '%s' % HOSTNAME,
'attributes': {
"site": '%s' % SITE,
'alias': '%s' % SERVER_ALIAS,
'ipaddress': '%s' % SERVER_IP,
'tag_address_family': 'ip-v4-only',
# ---------> upper part by using the variables are ok if the variable is a value < ---------------------
#..... Problem.......
'tag_<VARIABLE1>': '<VARIABLE1>', # how is the right syntax to use the variable?
#f"{VARIABLE2}," # not working ==> how is the right syntax to use the variable?
#'%s' % VARIABLE2, # not working ==> how is the right syntax to use the variable?
#'' '%s' % VARIABLE2, # not working ==> how is the right syntax to use the variable?
#..........
"tag_environment": '%s' % ENVIRONMENT
if resp.status_code == 200:
pprint.pprint(resp.json())
elif resp.status_code == 204:
print("Done")
else:
raise RuntimeError(pprint.pformat(resp.json()))
f'tag_{VARIABLE1}': f'{VARIABLE1}',
https://docs.python.org/3/reference/lexical_analysis.html#f-strings
The title of this topic is misleading because you are talking about the REST API not the Web API.
Command reference for the HTTP-API versus
Configuration via the Checkmk REST API
As addition to @mimimi i would also recommend not to build the JSON manually.
It is saver to use the json.dumps()
I rewrote your example a little bit and it is working without problem.
#!/usr/bin/env python3
import requests
import json
USERNAME = "omdadmin"
PASSWORD = "omd"
HOSTNAME = "TEST"
session = requests.session()
session.headers["Authorization"] = f"Bearer {USERNAME} {PASSWORD}"
session.headers["Accept"] = "application/json"
SITE = "home"
SERVER_ALIAS = "ALIAS"
SERVER_IP = "127.0.0.1"
ENVIRONMENT = "Test"
API_URL = "http://<servername>/<sitename>/check_mk/api/v0"
VARIABLE1 = "demo"
DATA = {
"folder": "/test",
"host_name": "%s" % HOSTNAME,
"attributes": {
"site": "%s" % SITE,
"alias": "%s" % SERVER_ALIAS,
"ipaddress": "%s" % SERVER_IP,
"tag_address_family": "ip-v4-only",
"tag_%s" % VARIABLE1: "%s" % VARIABLE1,
print(json.dumps(DATA))
resp = session.post(
f"{API_URL}/domain-types/host_config/collections/all",
headers={
"Content-Type": "application/json",
data=json.dumps(DATA),
if resp.status_code == 200:
print(resp.json())
elif resp.status_code == 204:
print("Done")
else:
raise RuntimeError(print(resp.json()))
f"{API_URL}/domain-types/host_config/collections/all",
headers={
"Content-Type": "application/json",
data=json.dumps(DATA),
It is also possible to drop the json.dumps()
line and directly use the json=
parameter to the post()
function:
resp = session.post(
f"{API_URL}/domain-types/host_config/collections/all",
headers={
"Content-Type": "application/json",
json=DATA,
Despite the parameter’s name, it does not expect a JSON string (like data=
does) but an ordinary (Python) dictionary. See also How to POST JSON data with Python Requests? - Stack Overflow
Hello Dirk
Thanks I will try it.
But currentliy I’m struggeling with the implementation of a variable: “ICTO_IMPORT_STRING_4” as whole line:
# the variable ICTO_IMPORT_STRING_4 has such definition, defined dyn. at a previous step.
ICTO_IMPORT_STRING_4 = "'tag_cmdb_icto_number_icto_777': 'icto_777','tag_cmdb_icto_number_icto_99': 'icto_99','tag_cmdb_icto_number_icto_0': 'icto_0',"
'labels': {
'tag_application_priority': '%s' % CMDB_APPLICATION_PRIORITY,
'tag_cluster_function': '%s' % CLUSTER_AND_CLUSTER_NODE,
# '' '%s' % ICTO_IMPORT_STRING_4,
f"{ICTO_IMPORT_STRING_4}",
'tag_department': '%s' % DEPARTMENT,
'tag_test': '%s' % XXXXX
The problem is now that the output is in " which is not ok:
'labels': {"'tag_cmdb_icto_number_icto_777': 'icto_777','tag_cmdb_icto_number_icto_99': 'icto_99','tag_cmdb_icto_number_icto_0': 'icto_0',tag_department": 'IPI',
'tag_application_priority': 'priority_0',
'tag_cluster_function': 'cluster_no',
ICTO part an department part is not ok with the "
Further the Checkmk API accepted the input but the labels icto and department are not shown.
Has somebody a solution for it?
Please let me know.
Thanks!
Regrads
import ast
# the variable ICTO_IMPORT_STRING_4 has such definition, defined dyn. at a previous step.
ICTO_IMPORT_STRING_4 = "'tag_cmdb_icto_number_icto_777': 'icto_777','tag_cmdb_icto_number_icto_99': 'icto_99','tag_cmdb_icto_number_icto_0': 'icto_0',"
# convert string into real dict:
import_string_as_dict = ast.literal_eval("{" + ICTO_IMPORT_STRING_4 + "}") # (1)
"labels": {
'tag_application_priority': '%s' % CMDB_APPLICATION_PRIORITY,
'tag_cluster_function': '%s' % CLUSTER_AND_CLUSTER_NODE,
'tag_department': '%s' % DEPARTMENT,
'tag_test': '%s' % XXXXX,
**import_string_as_dict # (2)
The line marked with (1) converts the string ICTO_IMPORT_STRING_4
into a real Python dictionary. To achieve this, it first surrounds the string with curlies {…}
and then applies ast.literal_eval()
to that string. For this to work you need to import the ast
module.
The line marked with (2) flattens the dictionary into key/value pairs and adds them to the "labels"
dictionary.
Hello Dirk
How is it possible to use the import:**import_string_as_dict # (2)
more than once?
at the label definition
at the main attributes of the host definition
It is not possible to use it twice in my environment.
Thank
Regards
The goal is better flexability:
IMPORT_STRING_AS_DICT_1 = ast.literal_eval("{" + ICTO_IMPORT_STRING_4 + "}") # (1)
json={
'folder': '/api_test',
'host_name': '%s' % FQDN,
'attributes': {
'tag_environment': '%s' % ENVIRONMENT,
'labels': {
'tag_environment': '%s' % ENVIRONMENT,
**IMPORT_STRING_AS_DICT_1 # (2)
**IMPORT_STRING_AS_DICT_1 # (2) ==> This is not working
But this doesn’t work, but why?
Hello Dirk and Andreas
I find out what the mistake was in my environment, the variable IMPORT_STRING_DICT_1 was filled with tag-values which aren’t in my system. I replaced it and now it works like expected.
Here is my short example how my solution (with your help) works for me:
#!/usr/bin/env python3
import requests
import json
import subprocess
import ast
USERNAME = "USER"
PASSWORD = "PWD"
HOSTNAME = "TEST"
HOST_NAME = "localhost"
FOLDER = "/api_test"
session = requests.session()
session.headers["Authorization"] = f"Bearer {USERNAME} {PASSWORD}"
session.headers["Accept"] = "application/json"
SITE_NAME = subprocess.getoutput('whoami')
SERVER_ALIAS = "ALIAS"
SERVER_IP = "127.0.0.1"
API_URL = f"https://{HOST_NAME}/{SITE_NAME}/check_mk/api/1.0"
CMDB_APPLICATION_1 = "sap_ca"
CMDB_APPLICATION_PRIORITY = "prio_0"
ICTO_IMPORT_STRING_4 = "'tag_cmdb_icto_number_icto_903': 'icto_903', 'tag_cmdb_icto_number_icto_992': 'icto_992', 'tag_cmdb_icto_number_icto_225': 'icto_225'"
IMPORT_STRING_AS_DICT = ast.literal_eval("{" + ICTO_IMPORT_STRING_4 + "}") # (1)
DATA = {
'folder': '%s' % FOLDER,
"host_name": "%s" % HOSTNAME,
"attributes": {
"site": "%s" % SITE_NAME,
"alias": "%s" % SERVER_ALIAS,
"ipaddress": "%s" % SERVER_IP,
"tag_address_family": "ip-v4-only",
'labels': {
'tag_application_priority': '%s' % CMDB_APPLICATION_PRIORITY,
**IMPORT_STRING_AS_DICT # (2)
'tag_cmdb_appl_1_%s' % CMDB_APPLICATION_1: '%s' % CMDB_APPLICATION_1,
**IMPORT_STRING_AS_DICT # (2)
print(json.dumps(DATA))
resp = session.post(
f"{API_URL}/domain-types/host_config/collections/all",
headers={
"Content-Type": "application/json",
data=json.dumps(DATA),
if resp.status_code == 200:
print(resp.json())
elif resp.status_code == 204:
print("Done")
else:
raise RuntimeError(print(resp.json()))
Thank you so much!
Kind regards