@georgecm12 I did not go as far as searching for specific information, I simply used the API to update lease expiration data for all of my machines. I was able to take a CSV file that had the serial number and lease expiration information in it and run it against the API. In turn, all of my machines have lease data now. The discussion we had about this on JAMF Nation is here:
JSS API PUT
You could adjust the script I used, or the other posted there by @luispalumbo to accomplish some of what you want. If you created a CSV file that held the serial numbers, lease data and PO information, you could update all of your systems, or just the ones that you have info for. Writing these values to a machine that already has these values does no harm that I can tell.
That works, Steve. Looks like newer versions of the API default to JSON output, not XML. As a result, the script as you wrote it doesn't work anymore, but you can send a header that tells the server to send XML instead.
Would be great if you could do this via an inventory action. I did see a feature request that appears to be alive. It says under review. I just want to be able to find a bunch of machines and then mass update information about purchased vs leased as well as lease start and expiration dates.
The request is here : https://jamfnation.jamfsoftware.com/featureRequest.html?id=545
@stevewood Are you still using your script and API thing ? Works well ? Looks harder than it needs to be.
@rcorbin yep, that's the method I use. Of course I only have to run it once every few months when I have new leases to put into the JSS. The process isn't really that complicated if you ask me. Gather the lease data into a CSV file, run the script, and you're done.
I recently had to do this as well - wrote some python to make it happen. You'll need the following things on your machine:
- Python 3 - you could edit the script to run in python 2, I'm sure.
- The following python modules: sys, csv, datetime, requests, argparse
- A csv with at least the following columns: Serial_num, End_date. End_date should be in the format M/D/Year, like 08/22/2017. You can change the date format in the init section if you like. Other columns won't cause problems.
- A 'jamfconfig.py' file that provides a username as "user", a password as "password", and a hostname as "url". I use the python module 'keyring' to store user/pass info in the OS X keychain, but you could keep them directly in the jamfconfig.py file if you like. You could also just set them directly in the script, if you're truly wild.
You should be able to just run the script with 'python <script-name> <csv-name>'.
Here's the python:
#!/usr/bin/env python
import sys
import csv
from datetime import datetime
import requests
import argparse
import jamfconfig
parser = argparse.ArgumentParser()
parser.add_argument("leaseList", help="CSV of leased machines")
args = parser.parse_args()
epoch = datetime(1970, 1, 1)
def dictify_csv(csvFile):
'''Import the csv from commandline, turn that into a list of dicts (one per machine).'''
reader = csv.DictReader(open(csvFile, 'r'))
dict_list = []
for row in reader:
dict_list.append(row)
return dict_list
class computer:
def __init__(self, computerDict):
self.serial = computerDict['Serial_num']
if self.serial[0] == "S":
self.serial = self.serial[1:]
self.lease_expires = datetime.strptime(computerDict['End_date'], '%m/%d/%Y')
self.lease_expires_epoch = (self.lease_expires - epoch).total_seconds()
def update_purchase_data(self):
url = jamfconfig.url + '/JSSResource/computers/udid/' + self.udid
payload = ("<computer><purchasing><is_purchased>false</is_purchased><is_leased>true</is_leased><lease_expires_epoch>" + str(int(self.lease_expires_epoch * 1000)) + "</lease_expires_epoch></purchasing></computer>")
b = requests.put(url, auth=(jamfconfig.user, jamfconfig.password), headers={'Accept': 'application/json'}, data=payload, verify=False)
if b.status_code == 201:
print(" Added lease expiration date for " + self.serial)
else:
print("[***] UNABLE TO ADD DATA")
def exists_in_jamf(self):
url = jamfconfig.url + '/JSSResource/computers/match/' + self.serial
b = requests.get(url, auth=(jamfconfig.user, jamfconfig.password), headers={'Accept': 'application/json'}, verify=False)
record = b.json()
if len(record['computers']) == 0:
print(machine.serial + " doesn't exist in jss")
return False
if len(record['computers']) >= 1:
for i in record['computers']:
self.udid = i['udid']
print(self.serial + " exists in jss. Adding leasing data.")
return True
try:
for line in dictify_csv(args.leaseList):
machine = computer(line)
if machine.exists_in_jamf():
machine.update_purchase_data()
except KeyboardInterrupt:
sys.exit()
A note about json/xml - I was originally trying to update the records by sending json, but was always getting a 415 (unsupported media?). Uploading as XML resolved.
Good luck!