API and POST command

pat_best
Contributor III

I am trying to import a computer using the mac or serial number into the JSS using the api. I am not understanding the syntax for this. I have an xml file with both pieces of information in it ready to be imported. I understand the command will look something like "https://myjss:8443/JSSResource/computers/" after that I am unsure of what to put in for a path. I know it should end with /path/to/xmlfile -X POST. The big picture is that I will be receiving new imacs and would like to take an excel inventory of the mac addresses and serial numbers, export it to xml and import the entries into the JSS so I can group computers and scope policies before the computers arrive. I am fine with needing to add more information to the xml file such as platform, os version and so on if it helps with the pre-deployment. I could try to do prestage imaging to simply install the apps I want, but I was hoping to be able to front load computer groups and policy scoping. I am using JSS 9.61 and am ordering new iMacs from Apple. I may also be contacting JAMF as I am up against a time crunch on this. Thanks for any help!!

2 ACCEPTED SOLUTIONS

mm2270
Legendary Contributor III

@pat.best - I've seen this issue and I worked around it by opening the csv file in TextWrangler and re-saving it. Not sure why but Excel saves csv files in a way that a script won't see the line breaks. Opening and saving it out of another application like TextWrangler solved this for me when I ran into the same problem once.

View solution in original post

GaToRAiD
Contributor II

@mm2270 the reason the file does not work is because the csv is saved in "Classic Mac" (CR) format, you need to make sure it is saved in the following formats:

1) Unix (LF)

View solution in original post

17 REPLIES 17

mm2270
Legendary Contributor III

What you're looking for is the -T flag before the xml file path I believe.
IOW, the syntax would look something like the following:

curl -sfku apiusername:apipassword https://myjss.com:8443/JSSResource/computers -T /path/to/xmlfile.xml -X POST

Also, I'm not sure, but you may need to also specify something else besides just /computers, like /id, /name, /udid, /serialnumber, etc. But I may be wrong because you're using the xml file for that information. Haven't specifically created new computer records via the API, so I'm not clear on that. I guess experiment.

BTW, the -f flag in the curl command, while not strictly required, is something I recommend. Curl normally considers any response from the server to be a successful exit status. So even if the JSS refuses the POST command because of a bad username/password or malformed syntax or a bad xml file, curl will happily think it worked, as long as it got some kind of response back from the server. Throwing in -f asks curl to specifically get an exit status. If its not 0, it didn't work. So you can use that in your scripts to confirm the upload actually worked, like:

if [ "$?" != "0" ]; then
    echo "Failed"
else
    echo "Worked!"
fi

Hope that helps.

EDIT: Forgot to mention to check out your JSS' built in help for more information, in case you haven't already:
https://yourjss.com:8443/api

pat_best
Contributor III

@mm2270 that looks great. I had not thought to use the -f flag, that will be very helpful. The api states "You can POST using the resource URLs with parameters of {name}, {udid}, {serial number}, or {macaddress}" and I would like to use those but that is where my question lies should it look like:

curl -sfku apiusername:apipassword https://myjss.com:8443/JSSResource/computers -T /path/to/xmlfile.xml -X POST

or more like:

curl -sfku apiusername:apipassword https://myjss.com:8443/JSSResource/computers/macaddress -T /path/to/xmlfile.xml -X POST

BrysonTyrrell
Contributor II

Hi Pat,

If you're creating a new resource you should use the "/id/0" endpoint as a best practice:

https://myjss.com:8443/JSSResource/computers/id/0

'/id/0' for any resource that supports POSTing will create a new object. It is usually your best bet to avoid 409 conflicts or other errors (which will arise if you attempt to POST a copy of a record that contains a unique identifier - like a UUID - that is already in user).

If you were performing GET, PUT or DELETE operations the other identifiers should work just fine. The syntax for using those would look like this:

https://myjss.com:8443/JSSResource/computers/udid/<udid>
https://myjss.com:8443/JSSResource/computers/serialnumber/<serial number>
https://myjss.com:8443/JSSResource/computers/macaddress/<mac address>

pat_best
Contributor III

thanks @brysontyrrell, that is huge to know that adding the id/0 at the end takes the next available id number.

I am trying to read a .csv file and have found two commands that get me started but in both cases they only show me the last line and a line count of one regardless of the actual line count in the file.

echo "$data" | wc -l | awk '{print $NF}'

with data='cat $file' and $file being the path to the .csv

and

awk -F, 'END {printf "%s
", NR}' $file

with $file being the path to the .csv

what I am trying to do is parse through a csv and get a total row count and to be able to read the file line by line to pull data from the individual rows. I can set an index to cycle through the csv row by row but I seem to be unable to write a command to get the total row count or read more than the last row. I will post the whole script below

pat_best
Contributor III

This script is supposed to read a .csv file and sort the data into an xml file to be POST'ed into the API. I have hijacked this script and edited it as far as I can with help from the wonderful people at JAMF. (they got me going on the csv idea and had the original script designed for user import in this fashion.) I am open to any ideas people have about this.

#!/bin/bash

########################################################################################################
#
# Copyright (c) 2014, JAMF Software, LLC.  All rights reserved.
#
#       Redistribution and use in source and binary forms, with or without
#       modification, are permitted provided that the following conditions are met:
#               * Redistributions of source code must retain the above copyright
#                 notice, this list of conditions and the following disclaimer.
#               * Redistributions in binary form must reproduce the above copyright
#                 notice, this list of conditions and the following disclaimer in the
#                 documentation and/or other materials provided with the distribution.
#               * Neither the name of the JAMF Software, LLC nor the
#                 names of its contributors may be used to endorse or promote products
#                 derived from this software without specific prior written permission.
#
#       THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
#       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#       DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
#       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
####################################################################################################
#
# DESCRIPTION
#
#   This script reads a CSV of computer data and imports them to the JSS.
#   The format must be asset number in the first column, serial number in the second, mac address in the third, and computer name last
#
####################################################################################################
#
# HISTORY
#
#   -Created by Sam Fortuna, JAMF Software, LLC, on June 18th, 2014
#   -Updated by Sam Fortuna, JAMF Software, LLC, on August 5th, 2014
#       -Improved error handling
#       -Returns a list of failed submissions
#   -Updated by Bram Cohen, JAMF Software, LLC, on September 10th, 2014
#       -Added ID check of ID #'s to start the posting
#   -Edited by Pat Best  Jan 27th, 2015
#              -to change it from user creation to computer creation
#              - removed the ID check portion
#
####################################################################################################

#Variables
file="file/path/testcsv.csv"                  #Path to the CSV
server="myjss"                        #Server name
username="user"                           #JSS username with API privileges
password="password"                           #Password for the JSS account

#Option to read in the path from Terminal
if [[ "$file" == "" ]]; then
    echo "Please enter the path to the CSV"
    read file
fi

#Verify we can read the file
data=`cat $file`
if [[ "$data" == "" ]]; then
    echo "Unable to read the file path specified"
    echo "Ensure there are no spaces and that the path is correct"
    exit 1
fi

#Find how many computers to import
computerqty=`awk -F, 'END {printf "%s
", NR}' $file`

#Set a counter for the loop
counter="0"

duplicates=[]

id=$((id+1))

#Loop through the CSV and submit data to the API
while [ $counter -lt $computerqty ]
do
    counter=$[$counter+1]
    line=`echo "$data" | head -n $counter | tail -n 1`
    asset=`echo "$line" | awk -F , '{print $1}'`
    serialnumber=`echo "$line" | awk -F , '{print $2}'`
    macaddy=`echo "$line" | awk -F , '{print $3}'`
    name=`echo "$line" | awk -F , '{print $4}'`


    echo "Attempting to create computer - $asset : $serialnumber : $macaddy"

    #Construct the XML
    apiData="<computer><general><name>${name}</name><mac_address>${macaddy}</mac_address><serial_number>${serialnumber}</serial_number><platform>Mac</platform><asset_tag>${asset}</asset_tag></general><hardware><os_name>Mac OS X</os_name><os_version>10.9</os_version></hardware></computer>"
    output=`curl -sS -k -i -u admin:password -X POST -H "Content-Type: text/xml" -d "<?xml version="1.0" encoding="ISO-8859-1"?>$apiData https://$server:8443/JSSResource/computers/id/0 -d `

    #Error Checking
    error=""
    error=`echo $output | grep "Conflict"`
    if [[ $error != "" ]]; then
        duplicates+=($serialnumber)
    fi
    #Increment the ID variable for the next user
    id=$((id+1))
done

echo "The following computers could not be created:"
printf -- '%s
' "${duplicates[@]}"

exit 0

Thanks for any help you have to offer!!

Pat

mm2270
Legendary Contributor III

@pat.best - I've seen this issue and I worked around it by opening the csv file in TextWrangler and re-saving it. Not sure why but Excel saves csv files in a way that a script won't see the line breaks. Opening and saving it out of another application like TextWrangler solved this for me when I ran into the same problem once.

GaToRAiD
Contributor II

@mm2270 the reason the file does not work is because the csv is saved in "Classic Mac" (CR) format, you need to make sure it is saved in the following formats:

1) Unix (LF)

pat_best
Contributor III

@mm2270 and @GaToRAiD that was it! I have not run into this before. Both commands now work as expected thank you both!

pat_best
Contributor III

I had a missing " mark in the old one, here is the working completed form:

#!/bin/bash

########################################################################################################
#
# Copyright (c) 2014, JAMF Software, LLC.  All rights reserved.
#
#       Redistribution and use in source and binary forms, with or without
#       modification, are permitted provided that the following conditions are met:
#               * Redistributions of source code must retain the above copyright
#                 notice, this list of conditions and the following disclaimer.
#               * Redistributions in binary form must reproduce the above copyright
#                 notice, this list of conditions and the following disclaimer in the
#                 documentation and/or other materials provided with the distribution.
#               * Neither the name of the JAMF Software, LLC nor the
#                 names of its contributors may be used to endorse or promote products
#                 derived from this software without specific prior written permission.
#
#       THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
#       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#       DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
#       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
####################################################################################################
#
# DESCRIPTION
#
#   This script reads a CSV of computer data and imports them to the JSS.
#   The format must be asset number in the first column, serial number in the second, mac address in the third, and computer name last
#
####################################################################################################
#
# HISTORY
#
#   -Created by Sam Fortuna, JAMF Software, LLC, on June 18th, 2014
#   -Updated by Sam Fortuna, JAMF Software, LLC, on August 5th, 2014
#       -Improved error handling
#       -Returns a list of failed submissions
#   -Updated by Bram Cohen, JAMF Software, LLC, on September 10th, 2014
#       -Added ID check of ID #'s to start the posting 
#    -Edited by Pat Best  Jan 27th, 2015
#              -to change it from user creation to computer creation
#              - removed the ID check portion
#
#
####################################################################################################

#Variables
file="/path/to/file/computer.csv"                 #Path to the CSV

#Option to read in the path from Terminal
if [[ "$file" == "" ]]; then
    echo "Please enter the path to the CSV"
    read file
fi

#Verify we can read the file
data=`cat $file`
if [[ "$data" == "" ]]; then
    echo "Unable to read the file path specified"
    echo "Ensure there are no spaces and that the path is correct"
    exit 1
fi

#Find how many computers to import
computerqty=`awk -F, 'END {printf "%s
", NR}' $file`

#Set a counter for the loop
counter="0"

duplicates=[]

id=$((id+1))

#Loop through the CSV and submit data to the API
while [ $counter -lt $computerqty ]
do
    counter=$[$counter+1]
    line=`echo "$data" | head -n $counter | tail -n 1`
    asset=`echo "$line" | awk -F , '{print $1}'`
    serialnumber=`echo "$line" | awk -F , '{print $2}'`
    macaddy=`echo "$line" | awk -F , '{print $3}'`
    name=`echo "$line" | awk -F , '{print $4}'`


    echo "Attempting to create computer - $asset : $serialnumber : $macaddy"

    #Construct the XML
    apiData="<computer><general><name>${name}</name><mac_address>${macaddy}</mac_address><serial_number>${serialnumber}</serial_number><platform>Mac</platform><asset_tag>${asset}</asset_tag></general><hardware><os_name>Mac OS X</os_name><os_version>10.9</os_version></hardware></computer>"
    output=`curl -sS -k -i -u apiusername: apipassword -X POST -H "Content-Type: text/xml" -d "<?xml version="1.0" encoding="ISO-8859-1"?>$apiData" https://myjss:8443/JSSResource/computers/id/0`

    #Error Checking
    error=""
    error=`echo $output | grep "Conflict"`
    if [[ $error != "" ]]; then
        duplicates+=($serialnumber)
    fi
    #Increment the ID variable for the next user
    id=$((id+1))
done

echo "The following computers could not be created:"
printf -- '%s
' "${duplicates[@]}"

exit 0

on a side note, I did not write anything in there to remove a header row from the .csv so please be mindful of that if you decide to use this script. Thanks!

chelm
New Contributor III

I know this thread is more than a year old, so I'm sorry if posting to it bothers anyone. The script and method are great but I'm wondering if there is a way to add a computer to a specific site? Our implementation has many sites but the root site is not accessible to everyone, so they cannot add computers with the API using this script because it is trying to put the computer in the root site.

Any advice is greatly appreciated.

Edit:

Someone here just sent me a solution I thought I would share that simply adding this to the string will solve the problem:
<site><id>sitenum</id><name>sitename</name></site>

stevewood
Honored Contributor II
Honored Contributor II

@chelm you actually only need the Site ID.

chelm
New Contributor III

Awesome. Thank you!

chelm
New Contributor III

When our machines enroll they are creating new records instead of updating the record that is pre-populated. Anyone have any tips?

mm2270
Legendary Contributor III

@chelm I'm pretty sure the above script in this thread is for importing machines into the JSS that have not been previously enrolled or have preconfigured records. You can't use this, as is at least, for importing computers to the JSS to match up with existing records. There are ways you can do that with a script, but it would need to be a different script, not this one.

chelm
New Contributor III

@mm2270 -- I'm sorry if I didn't explain my question well. I wrote an application in C# (our departmental admin uses a PC) for importing newly received (box never opened) computers. The idea was to pre-populate the object with the information that can be scanned off the box.

The first couple machines we tested on created the computer, but when the machine was built and enrolled it created a duplicate record. At first we thought it was because we were not entering the UDID. Then we realized that it wasn't populating the serial and MAC address correctly. I fixed this and now it doesn't duplicate the computer.

This does make me wonder what exactly is keyed on when a computer is enrolled. Is it the MAC address or the serial number, or do both have to exist?

pat_best
Contributor III

@chelm I am pretty sure you need the mac address and serial number when using the POST command in order to get newly enrolled computers to populate the rest of the data. This cannot be done from the outside of the brown box from Apple. I thought I read somewhere that you can have apple send you a sheet with this information on it if you order from Apple directly. It has been a while since I used this setup so I am a little fuzzy, hope this helps!

hinrichd
New Contributor III

i did some testing for our dep workflow with prepopulating computer name, uuid, mac address and serial number and i did not get duplicates after enrollment. The reason why i have test this workflow was to check if i can prepopulate/set the computer name bevor dep/prestage enrollments. I thought the client would match the computer name from the jss. I realized that the computer is renamed druing dep enrollment to the Mac Model or sometimes to DEPSERIAL. Does anybody have a solution to match the prepopulated jss computername to the dep client during enrollment?