Yep, I do something very similar, except that I’ve started using environment variables for the credentials (see input_method below). This function should facilitate creating your groups. Actually, it’s idempotent, so if you call it once, it’ll create the group. The second time you call it, it should just update the existing one:
import logicmonitor_sdk, argparse, os
from datetime import datetime
input_method = "envs"
if input_method == "args":
parser = argparse.ArgumentParser()
for arg,help in {
"id":"LM API Access ID",
"key": "LM API Access Key",
"company": "LM API Company",
}.items():
parser.add_argument(arg, help=help)
args = parser.parse_args()
lm_creds = {
"AccessId": args.id,
"AccessKey": args.key,
"Company": args.company
}
elif input_method == "envs":
lm_creds = {
"AccessId": os.environ['accessid'],
"AccessKey": os.environ['accesskey'],
"Company": os.environ['company']
}
else:
print(f"Invalid input method chosen: {input_method}")
quit()
configuration = logicmonitor_sdk.Configuration()
configuration.access_id = lm_creds['AccessId']
configuration.access_key = lm_creds['AccessKey']
configuration.company = lm_creds['Company']
lm = logicmonitor_sdk.LMApi(logicmonitor_sdk.ApiClient(configuration))
debug = False
info = False
def log_msg(msg, severity="INFO", end="\n"):
if (severity == "DEBUG" and debug) or (severity == "INFO" and info) or severity not in ("DEBUG", "INFO"):
print(f"{datetime.now().strftime('[%Y-%m-%d %H:%M:%S]')} {severity}: {msg}", end=end)
def create_group(name,parent,customProperties={},appliesTo=""): # shortcut function to the sdk that creates device groups with less fuss
parsedProperties = [{"name": k, "value": v} for k,v in customProperties.items()]
device_groups = []
end_found = False
offset = 0
size = 1000
while not end_found:
current = lm.get_device_group_list(size=size,offset=offset,filter=f"parentId:\"{parent}\",name:\"{name}\"").items
device_groups += current
offset += len(current)
end_found = len(current) != size
if len(device_groups) == 0:
try:
result = lm.add_device_group({"name":name, "parentId":parent, "customProperties":parsedProperties, "appliesTo":appliesTo})
log_msg(f" Created resource group {result.full_path} ({result.id})", "API SDK POST")
return result
except lm.ApiException as e:
log_msg("Exception when calling LMApi->addDeviceGroup: %s\n" % e)
else:
existing_group = device_groups[0]
mismatches = 0
log_msg(f" Group {name} exists in LM ({existing_group.id}), checking if attributes match...", "DEBUG")
existing_properties = {x.name:x.value for x in existing_group.custom_properties}
for k,v in customProperties.items(): #check each of the custom attributes we want to pass in to see if they match
if k in existing_properties.keys() and v==existing_properties.get(k,None):
log_msg(f" Property {k} matches attribute already in LM", "DEBUG")
else:
log_msg(f" Property {k} doesn't match attribute already in LM")
mismatches += 1
log_msg(f" {'='*80}", "DEBUG")
log_msg(f" {k}: {v}", "DEBUG")
log_msg(f" {k}: {existing_properties.get(k)}", "DEBUG")
log_msg(f" {'='*80}", "DEBUG")
if len(appliesTo) > 0:
if appliesTo == existing_group.applies_to:
log_msg(f" AppliesTo we want to patch in matches the AppliesTo already on the device", "DEBUG")
else:
log_msg(f" AppliesTo we want to patch in doesn't match the AppliesTo already on the device")
mismatches += 1
log_msg(f" {'='*80}", "DEBUG")
formatted_appliesTo = appliesTo.replace('\n','\n ')
log_msg(f" {formatted_appliesTo}", "DEBUG")
log_msg(f" {'='*80}", "DEBUG")
formatted_appliesTo = existing_group.applies_to.replace('\n','\n ')
log_msg(f" {formatted_appliesTo}", "DEBUG")
log_msg(f" {'='*80}", "DEBUG")
else:
log_msg(f" There is no AppliesTo that we want to patch in.", "DEBUG")
if mismatches > 0:
log_msg(f" Number of attribute mismatches: {mismatches}")
existing_group.applies_to = appliesTo
existing_properties.update(customProperties)
existing_group.custom_properties = [{"name":k,"value":v} for k,v in existing_properties.items()]
result = lm.patch_device_group_by_id(id=existing_group.id, body=existing_group) # , op_type="replace")
log_msg(f" Patched device group {existing_group.name}", "API SDK PATCH")
else:
log_msg(f" {existing_group.full_path} already exists in LM with all the correct properties, moving on...", "SUMMARY")
result = existing_group
log_msg(f" {result.id}: {result.full_path}: {result.custom_properties}", "DEBUG")
return result
Example usage:
>>> response = create_group("SDK Test",812,{"prop1":"1","prop2":"2"})
[2023-02-21 16:30:11] API SDK POST: Created resource group Customers/Longhorn Smokers/SDK Test (854)
>>> response = create_group("SDK Test",812,{"prop1":"1","prop2":"2"})
[2023-02-21 16:33:06] SUMMARY: Customers/Longhorn Smokers/SDK Test already exists in LM with all the correct properties, moving on...
>>> response = create_group("SDK Test",812,{"prop1":"1","prop2":"2"})
[2023-02-21 16:33:43] API SDK PATCH: Patched device group SDK Test
>>> debug = True
>>> info = True
>>> response = create_group("SDK Test",812,{"prop1":"1","prop2":"2"})
[2023-02-21 16:35:57] DEBUG: Group SDK Test exists in LM (854), checking if attributes match...
[2023-02-21 16:35:57] DEBUG: Property prop1 matches attribute already in LM
[2023-02-21 16:35:57] DEBUG: ================================================================================
[2023-02-21 16:35:57] DEBUG: prop1: 1
[2023-02-21 16:35:57] DEBUG: prop1: 1
[2023-02-21 16:35:57] DEBUG: ================================================================================
[2023-02-21 16:35:57] DEBUG: Property prop2 matches attribute already in LM
[2023-02-21 16:35:57] DEBUG: ================================================================================
[2023-02-21 16:35:57] DEBUG: prop2: 2
[2023-02-21 16:35:57] DEBUG: prop2: 2
[2023-02-21 16:35:57] DEBUG: ================================================================================
[2023-02-21 16:35:57] DEBUG: There is no AppliesTo that we want to patch in.
[2023-02-21 16:35:57] SUMMARY: Customers/Longhorn Smokers/SDK Test already exists in LM with all the correct properties, moving on...
[2023-02-21 16:35:57] DEBUG: 854: Customers/Longhorn Smokers/SDK Test: [{'name': 'prop2', 'value': '2'}, {'name': 'prop1', 'value': '1'}]
>>>