-
Couldn't load subscription status.
- Fork 17
Working with Raw Data
The API class interacts with Jamf using the get, post, put, and delete methods. You can work with the raw data using these methods. To see all of the data endpoints, go to the following URL on your server. https://example.com:8443/api
To get started using the raw data, start a python REPL.
python3Import pprint and jamf and access the api object.
from pprint import pprint
import jamf
api = jamf.API()The api object is a singleton. So if you call jamf.API() over and over and it will always return the same object. The reason behind this is so that you can access the api and the cached data from any file. The downside of this is that you can not talk to multiple Jamf servers.
The API get method downloads the associated data from the Jamf Pro server. If you store it in a variable, it does not update itself. If you make changes on the server, you’ll need to run the API get method again to get the updated data.
Get any information from your Jamf Pro server using the classic API endpoints. This includes nested dictionaries.
pprint(api.get('accounts'))
pprint(api.get('buildings'))
pprint(api.get('categories'))
pprint(api.get('computergroups'))
pprint(api.get('computers'))
pprint(api.get('departments'))
pprint(api.get('licensedsoftware'))
pprint(api.get('networksegments'))
pprint(api.get('osxconfigurationprofiles'))
pprint(api.get('packages'))
pprint(api.get('patches'))
pprint(api.get('policies'))
pprint(api.get('scripts'))Get all categories and work with the nested dictionaries
categories = api.get('categories')['categories']['category']
category_names = [x['name'] for x in categories]
print(f"first category: {category_names[0]}")
pprint(category_names)This example demonstrates using an id in the get request:
computers = api.get('computers')['computers']['computer']
pprint(computers[0])
pprint(api.get(f"computermanagement/id/{computers[0]['id']}"))
pprint(api.get(f"computermanagement/id/{computers[0]['id']}/subset/general"))Getting computer groups and filtering using list comprehension filtering.
computergroups = api.get('computergroups')['computer_groups']['computer_group']
smartcomputergroups = [i for i in computergroups if i['is_smart'] == 'true']
pprint(smartcomputergroups)
staticcomputergroups = [i for i in computergroups if i['is_smart'] != 'true']
pprint(staticcomputergroups)
computergroupids = [i['id'] for i in computergroups]
pprint(computergroupids)When creating a new data, in this case a static computer group, the id in the url ("1") is ignored and the next available id is used. The name in the url ("ignored") is also ignored and the name in the data ("realname") is what is actually used with the static computer group.
import json
api.post("computergroups/id/1",json.loads( '{"computer_group": {"name": "test", "is_smart": "false", "site": {"id": "-1", "name": "None"}, "criteria": {"size": "0"}, "computers": {"size": "0"}}}' ))
api.post("computergroups/name/ignored",json.loads( '{"computer_group": {"name": "realname", "is_smart": "false", "site": {"id": "-1", "name": "None"}, "criteria": {"size": "0"}, "computers": {"size": "0"}}}' ))The following code changes the group "realname" created in the example above to "new name".
import json
api.put("computergroups/name/realname",json.loads( '{"computer_group": {"name": "new name", "is_smart": "false", "site": {"id": "-1", "name": "None"}, "criteria": {"size": "0"}, "computers": {"size": "0"}}}' ))computergroups = api.get('computergroups')['computer_groups']['computer_group']
newgroup = [i for i in computergroups if i['name'] == 'new name']And this is how to change the computer group name using the id.
api.put(f"computergroups/id/{newgroup[0]['id']}",json.loads( '{"computer_group": {"name": "newer name", "is_smart": "false", "site": {"id": "-1", "name": "None"}, "criteria": {"size": "0"}, "computers": {"size": "0"}}}' ))The following example deletes the two groups we just created above:
api.delete("computergroups/name/test")
api.delete(f"computergroups/id/{newgroup[0]['id']}")This is where the real power of python-jamf comes in.
The following example searches all policies for the custom trigger "update_later" and replaces it with "update_now".
#!/usr/bin/env python3
import jamf
api = jamf.API()
all_policies = api.get('policies')['policies']['policy']
for policy_hook in all_policies:
policy = api.get(f"policies/id/{policy_hook['id']}")
name = policy['policy']['general']['name']
custom_trigger = policy['policy']['general']['trigger_other']
print(f"Working on {name}")
if (custom_trigger == "update_later"):
policy['policy']['general']['trigger_other'] = "update_now"
api.put(f"policies/id/{policy_hook['id']}", policy)
print(f"Changed custom trigger from {custom_trigger} to update_now")The next example prints out the code you'd need to enter into a python3 interpreter to set the custom_triggers. Save the output of this script to a file, then edit the file with the custom triggers you want for each item. Delete the items you don't want to change.
#!/usr/bin/env python3
import jamf
api = jamf.API()
all_policies = api.get('policies')['policies']['policy']
print("""#!/usr/bin/env python3
import jamf
api = jamf.API()
""")
for policy_hook in all_policies:
policy = api.get(f"policies/id/{policy_hook['id']}")
custom_trigger = policy['policy']['general']['trigger_other']
print(f"print(f\"Working on {policy['policy']['general']['name']}\")\n"
f"policy = api.get(\"policies/id/{policy_hook['id']}\")\n"
f"policy['policy']['general']['trigger_other'] = "
f"\"{policy['policy']['general']['trigger_other']}\"\n"
f"api.put(\"policies/id/{policy_hook['id']}\", policy)\n\n")Save the script named "custom_triggers_1.py" with the following commands:
./custom_triggers_1.py > custom_triggers_2.py
chmod 755 custom_triggers_2.pyThen edit "custom_triggers_2.py" with the custom triggers you want (and remove what you don't want to modify).
Then run "custom_triggers_2.py" script to make modifications.