Skip to main content
Solved

Device (Business) Service automation

  • May 30, 2025
  • 5 replies
  • 0 views

Forum|alt.badge.img

Does anyone have example code for creating/deleting device services, API or GQL?

Best answer by jchivers

Hello, 

we have a prototype of a script to create services using an existing template and to modify the name of the service and the device search filter based on supplied data. I will post the script below. This script is provided as a working sample to demonstrate what is possible, please do not raise a Support case for it! The script only works with Device Service templates. 


#!/usr/bin/env python3
import requests
import argparse
import getpass

def run_gql(url, payload, auth):
    request = requests.post(url, json=payload, verify=False, auth=auth)
    if request.status_code == 200:
        return request.json()
    else:
        raise Exception(f"GraphQL query failed to run by returning code of {request.status_code}. \n\nOriginal Query: {query}")

def query_template_by_name(template_name):
    query = """
    query harTemplateNameToId($templateName: String!) {
        harTemplates(search: {name: {eq: $templateName}}) {
            edges {
                node {
                    id
                    definition
                }
            }
            pageInfo {
                matchCount
            }
        }
    }
    """

    variables = {
        "templateName": template_name
    }

    payload = {
        'query': query,
        'variables': variables
    }
    auth = (username, password)
    try:
        result = run_gql(GQL_URL, payload, auth)
        if result['data']['harTemplates']['pageInfo']['matchCount'] > 1:
            print(f"Multiple templates with name {template_name}")
            exit(1)
        return result['data']['harTemplates']['edges'][0]['node']
    except Exception as e:
        print(f"Error caught: {e}")
        exit(1)

def query_organization_id_by_name(organization_name):
    query = """
    query orgNameToOrgId($companyName:String!) {
        organizations(search: { company: { eq: $companyName } } ) {
            edges {
                node {
                    id
                }
            }
        }
    }
    """

    variables = {
        "companyName": organization_name
    }

    payload = {
        'query': query,
        'variables': variables
    }
    auth = (username, password)
    try:
        result = run_gql(GQL_URL, payload, auth)
        return result['data']['organizations']['edges'][0]['node']['id']
    except Exception as e:
        print(f"Error caught: {e}")
        exit(1)

def create_from_har_template(template_id, definition):
    query = """
        mutation createFromHarTemplate($templateId:ID!, $definition:JSON!) {
            createFromHarTemplate(id: $templateId, definition:$definition) {
                harProviders {
                    id
                    name
                    type
                    organization {
                        company
                    }
                }
            }
        }
    """

    variables = {
        "templateId": template_id,
        "definition": definition,
    }
    payload = {
        'query': query,
        'variables': variables
    }
    auth = (username, password)
    try:
        result = run_gql(GQL_URL, payload, auth)
        return result
    except Exception as e:
        print(f"Error caught: {e}")
        exit(1)


####### main ######
parser = argparse.ArgumentParser(description='Install services from a template')
parser.add_argument('--url', help='Required argument --  URL of the SL1 GraphQL API endpoint.  Example: https://sl1platform.company.com/gql OR http://sl1platform.company.com/gql', required=True)
parser.add_argument('--user', help='Required argument --  user name for the GraphQL request.  Users will be prompted for a password at run time.', required=True)
parser.add_argument('--template', help='Required argument --  Service / HarProvider template name', required=True)
parser.add_argument('--org', help='Required argument --  SL1 Organization (Company name)', required=True)
parser.add_argument('--nameKey', help='Optional argument -- Unique name to append to services and to require in devices')
args = vars(parser.parse_args())

GQL_URL = args['url']
username = args['user']
template = args['template']
name_key = args['nameKey']
organization = args['org']
print(f"template: {template}")
print(f"nameKey: {name_key}")
print(f"org = {organization}")
password = getpass.getpass(prompt='Password: ')

organization_id = query_organization_id_by_name(organization)
har_template = query_template_by_name(template)
template_definition = har_template['definition']
template_id = har_template['id']
har_providers = template_definition['harProviders']

# loop through har providers and update organizations and filters
for har_provider in har_providers:
    har_provider['organization']['id'] = organization_id
    har_provider['contactOrganization']['id'] = organization_id
    name = har_providers[0]['name']
    new_name = name
    if name_key:
        new_name += f" - {name_key}"
        har_provider['name'] = new_name
        filterText = har_provider['filter']['filter']
        filterJson = har_provider['filter']['search']
        newFilterText = f'({filterText}) and (name contains {name_key})'
        newFilterJson = {
            "and": [
                filterJson,
                {
                    "name": {
                        "contains": name_key
                    }
                }
            ]
        }
        har_provider['filter']['filter'] = newFilterText
        har_provider['filter']['search'] = newFilterJson

# call createFromHarTemplate
result = create_from_har_template(template_id, template_definition)
print('')
print('The following services were created:')
for har_provider in result['data']['createFromHarTemplate']['harProviders']:
    print(f'    ServiceId: {har_provider["id"]}')
    print(f'        Name: {har_provider["name"]}')
    print(f'        Type: {har_provider["type"]}')
    print(f'        Organization: {har_provider["organization"]["company"]}')

 

5 replies

Forum|alt.badge.img
  • Author
  • New Contributor
  • May 30, 2025

I have an excellent leg up on this task thanks to Jonathan Chivers. I will include the code at some point.


Forum|alt.badge.img

First you need to query policies:

query harPolicyt{
  harPolicies(first:10 ) {
    edges {
      node {
        id
        name
        type
      }
    }
  }
}

----

Then use the correct policy for you with this:

    mutation CreateBSM {
        saveHarProvider(
            contactOrganization: "0",
            description: "This is for GQL testing",
            filterSearch:
          {
            userSearch:"name contains sl1"
              search: {
                name:{contains: "sl1"}}
     
          },
            name: "manual_sl2",
            organization: "0",
            policy: "cjfcxzgdx002e1byxzwlx04a2",
            type: deviceService,
            enabled: true,
            rootCauseAnalysisMode: enabledContributorsOnly,
            pollFrequency: 5
        )
        {
            name
            id
        }
    }

with variables like:

{
  "data": {
    "saveHarProvider": {
      "name": "manual_sl2",
      "id": "cm03kxj7z7zhgs5mncz8q3vp2"
    }
  }
}

 

 


  • Community Manager
  • Answer
  • June 20, 2025

Hello, 

we have a prototype of a script to create services using an existing template and to modify the name of the service and the device search filter based on supplied data. I will post the script below. This script is provided as a working sample to demonstrate what is possible, please do not raise a Support case for it! The script only works with Device Service templates. 


#!/usr/bin/env python3
import requests
import argparse
import getpass

def run_gql(url, payload, auth):
    request = requests.post(url, json=payload, verify=False, auth=auth)
    if request.status_code == 200:
        return request.json()
    else:
        raise Exception(f"GraphQL query failed to run by returning code of {request.status_code}. \n\nOriginal Query: {query}")

def query_template_by_name(template_name):
    query = """
    query harTemplateNameToId($templateName: String!) {
        harTemplates(search: {name: {eq: $templateName}}) {
            edges {
                node {
                    id
                    definition
                }
            }
            pageInfo {
                matchCount
            }
        }
    }
    """

    variables = {
        "templateName": template_name
    }

    payload = {
        'query': query,
        'variables': variables
    }
    auth = (username, password)
    try:
        result = run_gql(GQL_URL, payload, auth)
        if result['data']['harTemplates']['pageInfo']['matchCount'] > 1:
            print(f"Multiple templates with name {template_name}")
            exit(1)
        return result['data']['harTemplates']['edges'][0]['node']
    except Exception as e:
        print(f"Error caught: {e}")
        exit(1)

def query_organization_id_by_name(organization_name):
    query = """
    query orgNameToOrgId($companyName:String!) {
        organizations(search: { company: { eq: $companyName } } ) {
            edges {
                node {
                    id
                }
            }
        }
    }
    """

    variables = {
        "companyName": organization_name
    }

    payload = {
        'query': query,
        'variables': variables
    }
    auth = (username, password)
    try:
        result = run_gql(GQL_URL, payload, auth)
        return result['data']['organizations']['edges'][0]['node']['id']
    except Exception as e:
        print(f"Error caught: {e}")
        exit(1)

def create_from_har_template(template_id, definition):
    query = """
        mutation createFromHarTemplate($templateId:ID!, $definition:JSON!) {
            createFromHarTemplate(id: $templateId, definition:$definition) {
                harProviders {
                    id
                    name
                    type
                    organization {
                        company
                    }
                }
            }
        }
    """

    variables = {
        "templateId": template_id,
        "definition": definition,
    }
    payload = {
        'query': query,
        'variables': variables
    }
    auth = (username, password)
    try:
        result = run_gql(GQL_URL, payload, auth)
        return result
    except Exception as e:
        print(f"Error caught: {e}")
        exit(1)


####### main ######
parser = argparse.ArgumentParser(description='Install services from a template')
parser.add_argument('--url', help='Required argument --  URL of the SL1 GraphQL API endpoint.  Example: https://sl1platform.company.com/gql OR http://sl1platform.company.com/gql', required=True)
parser.add_argument('--user', help='Required argument --  user name for the GraphQL request.  Users will be prompted for a password at run time.', required=True)
parser.add_argument('--template', help='Required argument --  Service / HarProvider template name', required=True)
parser.add_argument('--org', help='Required argument --  SL1 Organization (Company name)', required=True)
parser.add_argument('--nameKey', help='Optional argument -- Unique name to append to services and to require in devices')
args = vars(parser.parse_args())

GQL_URL = args['url']
username = args['user']
template = args['template']
name_key = args['nameKey']
organization = args['org']
print(f"template: {template}")
print(f"nameKey: {name_key}")
print(f"org = {organization}")
password = getpass.getpass(prompt='Password: ')

organization_id = query_organization_id_by_name(organization)
har_template = query_template_by_name(template)
template_definition = har_template['definition']
template_id = har_template['id']
har_providers = template_definition['harProviders']

# loop through har providers and update organizations and filters
for har_provider in har_providers:
    har_provider['organization']['id'] = organization_id
    har_provider['contactOrganization']['id'] = organization_id
    name = har_providers[0]['name']
    new_name = name
    if name_key:
        new_name += f" - {name_key}"
        har_provider['name'] = new_name
        filterText = har_provider['filter']['filter']
        filterJson = har_provider['filter']['search']
        newFilterText = f'({filterText}) and (name contains {name_key})'
        newFilterJson = {
            "and": [
                filterJson,
                {
                    "name": {
                        "contains": name_key
                    }
                }
            ]
        }
        har_provider['filter']['filter'] = newFilterText
        har_provider['filter']['search'] = newFilterJson

# call createFromHarTemplate
result = create_from_har_template(template_id, template_definition)
print('')
print('The following services were created:')
for har_provider in result['data']['createFromHarTemplate']['harProviders']:
    print(f'    ServiceId: {har_provider["id"]}')
    print(f'        Name: {har_provider["name"]}')
    print(f'        Type: {har_provider["type"]}')
    print(f'        Organization: {har_provider["organization"]["company"]}')

 


  • Community Manager
  • June 20, 2025

To use this script you need to:

  1. Create a Device Service that has a device search filter that covers what will be common to all instances of this service, such as 'name contains 'Kirk'
  2. Run the script from a CLI 

    python bs_install_from_template.py --url https://<your cdb IP>/gql --user “<user-name>” --template “<template-name>” --org "<organization>" --nameKey "<unique-value>”

  3. The new Device Service will have unique-value appended to its name and the device search filter will become 
  4. 'name contains 'Kirk' and name contains unique-value

  • Community Manager
  • June 20, 2025

If you have a long list of Device Services to create, there is another version of this script that reads the required fields from a CSV file so you do not have to run the script once per new instance. Let me know if this is of interest to you jchivers@sciencelogic.com