Delete users from multiple classes script review request

m_donovan
Contributor III

So long story short I am learning scripting through doing as a lot of us are. I posted this script as a response to another users earlier discussion. Although it works in my environment I feel like there are more efficient ways to get it done. I have tried to include a good deal of commenting to both shore up my understanding as well as explain how I think it works. Any input and/or suggestions would help me better understand the many ways to accomplish tasks via scripting.

#!/bin/bash

## Remove_a_user_from_multiple_classes.sh
## Author:  Mike Donovan (mike.donovan@killeenisd.org)
## Created: 30 June 2017

##########################################################################################
#
#   This script was built with heavy reliance on other scripts from Mike Morales
#   as well as others. 
#
#   Although it works in my environment it may not work in yours. DO NOT RUN in your
#   production environment until you have thoroughly tested it and feel confident 
#   about its use.
#
#   You will need a CSV file with a single column of JSS user ID's with no header.
#   There should be no spaces in the name of the CSV file and it is best if it is 
#   located on the desktop.
#
##########################################################################################

##########################################################################################
#       USER DEFINABLE VARIABLES INPUT YOUR ENVIRONMENTS VALUES
##########################################################################################
apiuser="yourapiuser"
apipass="yourapipass"
## Set the JSS URL !! NO TRAILING SLASH !!
jssurl="https://your_org.com:8443"
##########################################################################################
#       USER DEFINABLE VARIABLES INPUT YOUR ENVIRONMENTS VALUES
##########################################################################################

##########################################################################################
#       FUNCTION TO REMOVE A SPECIFIED STUDENT ID FROM ALL CLASSES DO NOT EDIT
##########################################################################################
removeFromClass(){

    removeID=$1 ## Variable passed in with function call

    ## Verify API user credentials are present
    if [[ "$apiuser" != "" ]] && [[ "$apipass" != "" ]]; then

        #Get a list of all class ID's
        classIDList=$(curl -H "Accept: text/xml" -sfku "${apiuser}:${apipass}" "${jssurl}/JSSResource/classes" -X GET 2>/dev/null | xmllint --format - | grep -B1 "<name>" | awk -F'>|<' '/<id>/{print $3}')

        #store the list of ID's in an array
        declare -a arrayOfIDList=($classIDList)

        #iterate through the array of ID's checking each ID for the presence of the remove ID.
        for idInList in "${arrayOfIDList[@]}"; do

            ## Get the contents of the Student ID tags this should skip any class that does not have individually added students check to see if the remove ID is present
            classData=$(curl -H "Accept: text/xml" -sfku "${apiuser}:${apipass}" "${jssurl}/JSSResource/classes/id/${idInList}" -X GET | xmllint --format - | awk '/<student_ids>/,/</student_ids>/' | grep "$removeID")

            # If the remove ID was present 
            if [ ! -z "$classData" ];then
                echo "Class $idInList contains $removeID"
                # Get entire contents of the identified classes XML from the JSS and export to a file in the tmp directory
                curl -H "Accept: text/xml" -sfku "${apiuser}:${apipass}" "${jssurl}/JSSResource/classes/id/${idInList}" -X GET | xmllint --format - > "/private/tmp/${idInList}.xml"
                ## Create the start of the update XML file
                echo "<class>" > "/tmp/${idInList}mod.xml"
                # Pull out only the information between the <student_ids> tags then remove any line containing the remove ID finally append to the mod file.
                sed -n '/<student_ids>/,/</student_ids>/p' "/tmp/${idInList}.xml" | awk "!/$removeID/" >> "/tmp/${idInList}mod.xml"
                # Append a closing </class> tag to the end of the mod file
                echo "</class>" >> "/tmp/${idInList}mod.xml"

                ## Upload the mod file to the JSS. The use of PUT will update the existing record for the class with the specified ID.
                curl -sku "${apiuser}:${apipass}" "${jssurl}/JSSResource/classes/id/${idInList}" -T "/tmp/${idInList}mod.xml" -X PUT 2>&1 > /dev/null

                ## Check to see if we got a 0 exit status from the PUT command
                if [ $? == 0 ]; then
                    #if all is well
                    echo "Class "$idInList" was modified."
                else
                    # if something went wrong with upload
                    echo "Class Modification failed"
                    ## Clean up the xml file
                    #rm -f "/tmp/${idInList}mod.xml" ### may want to keep this file for troubleshooting###
                    exit 1
                fi
                    ## everything checks out  
                    ## Clean up the xml file
                    rm -f "/tmp/${idInList}mod.xml"

            fi
        done

    fi
}
##########################################################################################
#       FUNCTION TO REMOVE A SPECIFIED STUDENT ID FROM ALL CLASSES
##########################################################################################

##########################################################################################
#       MAIN SCRIPT EXECUTION DO NOT EDIT
##########################################################################################

##################Select input file 
file=$(/usr/bin/osascript << EOF
POSIX path of (choose file with prompt "Select the CSV file that contains the user ID's")
EOF)
if [ "$file" == "false" ]; then
    echo "User exited."
    exit 0
elif [ -z "$file" ]; then
    echo "File is empty"
    # No file was selected
    osascript -e 'Tell application "System Events" to display alert "You must select a file. Exiting script now..." as warning'
    exit 1 # exit with an error status
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

#Get a count of items in the file
numberOfItems=$(awk -F, 'END {printf "%s
", NR}' $file)
echo "Number of items: " $numberOfItems
#Set a counter for the loop
itemCounter="0"

#Iterate through the file one line at a time
while [ $itemCounter -lt $numberOfItems ]; do

    itemCounter=$[$itemCounter+1]
    line=$(echo "$data" | head -n $itemCounter | tail -n 1)
    stuID=$(echo "$line" | awk -F , '{print}' | tr -d '
') # "tr -d '
'" Removes trailing carriage return

    removeFromClass $stuID # Call function and pass it the student ID read from the CSV file

done

##########################################################################################
#       MAIN SCRIPT EXECUTION DO NOT EDIT
##########################################################################################

exit 0 # We get here if everything worked as expected
0 REPLIES 0