@@ -565,6 +565,62 @@ def get_snipe_user_id(username):
565565 except :
566566 return "NotFound"
567567
568+ def get_snipe_locations (previous = []):
569+ locations_url = f"{ snipe_base } /api/v1/locations"
570+ payload = {"limit" : 100 , "offset" : len (previous )}
571+ logging .debug ("The payload for the snipe locations GET is {}" .format (payload ))
572+ response = session .get (
573+ locations_url ,
574+ headers = snipeheaders ,
575+ params = payload ,
576+ verify = user_args .do_not_verify_ssl ,
577+ hooks = {"response" : request_handler },
578+ )
579+ response_json = response .json ()
580+ current = response_json ["rows" ]
581+ if previous :
582+ current = previous + current
583+ if response_json ["total" ] > len (current ):
584+ logging .debug (
585+ "We have more than 100 locations, get the next page - total: {} current: {}" .format (
586+ response_json ["total" ], len (current )
587+ )
588+ )
589+ return get_snipe_locations (current )
590+ else :
591+ return current
592+
593+
594+ def get_snipe_location_id (location_name ):
595+ if location_name == "" :
596+ return "NotFound"
597+ location_name = location_name .lower ()
598+ for location in snipe_locations :
599+ for value in location .values ():
600+ if str (value ).lower () == location_name :
601+ id = location ["id" ]
602+ return id
603+ logging .debug (
604+ "No matches in snipe_locations for {}, querying the API for the next closest match" .format (
605+ location_name
606+ )
607+ )
608+ location_id_url = "{}/api/v1/locations" .format (snipe_base )
609+ payload = {"search" : location_name , "limit" : 1 , "sort" : "name" , "order" : "asc" }
610+ logging .debug ("The payload for the snipe location search is: {}" .format (payload ))
611+ response = session .get (
612+ location_id_url ,
613+ headers = snipeheaders ,
614+ params = payload ,
615+ verify = user_args .do_not_verify_ssl ,
616+ hooks = {"response" : request_handler },
617+ )
618+ try :
619+ return response .json ()["rows" ][0 ]["id" ]
620+ except :
621+ return "NotFound"
622+
623+
568624# Function that creates a new Snipe Model - not an asset - with a JSON payload
569625def create_snipe_model (payload ):
570626 api_url = '{}/api/v1/models' .format (snipe_base )
@@ -644,7 +700,28 @@ def checkin_snipe_asset(asset_id):
644700 return response
645701
646702# Function that checks out an asset in snipe
647- def checkout_snipe_asset (user , asset_id , checked_out_user = None ):
703+ def checkout_snipe_asset (location , asset_id , checked_out_user = None ):
704+ jamfsplit = config ["user-mapping" ]["jamf_api_field" ].split ()
705+ checked_out = None
706+
707+ user = None
708+ building = None
709+ for field in jamfsplit :
710+ if field in location :
711+ if field == "username" :
712+ user = location [field ]
713+ elif field == "building" :
714+ building = location [field ]
715+
716+ if user :
717+ checked_out = checkout_snipe_asset_to_user (user , asset_id , checked_out_user )
718+
719+ if not checked_out and building :
720+ checked_out = checkout_snipe_asset_to_location (building , asset_id , checked_out_user )
721+
722+ return checked_out
723+
724+ def checkout_snipe_asset_to_user (user , asset_id , checked_out_user = None ):
648725 logging .debug ('Asset {} is being checked out to {}' .format (user , asset_id ))
649726 user_id = get_snipe_user_id (user )
650727 if user_id == 'NotFound' :
@@ -677,6 +754,37 @@ def checkout_snipe_asset(user, asset_id, checked_out_user=None):
677754 logging .error ('Asset checkout failed for asset {} with error {}' .format (asset_id ,response .text ))
678755 return response
679756
757+
758+ def checkout_snipe_asset_to_location (location , asset_id , checked_out_user = None ):
759+ location_id = get_snipe_location_id (location )
760+ api_url = "{}/api/v1/hardware/{}/checkout" .format (snipe_base , asset_id )
761+ logging .info ("Checking out {} to check it out to {}" .format (asset_id , location ))
762+ payload = {
763+ "checkout_to_type" : "location" ,
764+ "assigned_location" : location_id ,
765+ "note" : "Assignment made automatically, via script from Jamf." ,
766+ }
767+ logging .debug ("The payload for the snipe checkin is: {}" .format (payload ))
768+ response = session .post (
769+ api_url ,
770+ headers = snipeheaders ,
771+ json = payload ,
772+ verify = user_args .do_not_verify_ssl ,
773+ hooks = {"response" : request_handler },
774+ )
775+ logging .debug ("The response from Snipe IT is: {}" .format (response .json ()))
776+ if response .status_code == 200 :
777+ logging .debug ("Got back status code: 200 - {}" .format (response .content ))
778+ return "CheckedOut"
779+ else :
780+ logging .error (
781+ "Asset checkout failed for asset {} with error {}" .format (
782+ asset_id , response .text
783+ )
784+ )
785+ return response
786+
787+
680788### Run Testing ###
681789# Report if we're verifying SSL or not.
682790logging .info ("SSL Verification is set to: {}" .format (user_args .do_not_verify_ssl ))
@@ -749,6 +857,7 @@ jamf_types = {
749857
750858if user_args .users or user_args .users_force or user_args .users_inverse :
751859 snipe_users = get_snipe_users ()
860+ snipe_locations = get_snipe_locations ()
752861
753862TotalNumber = 0
754863if user_args .computers :
@@ -892,8 +1001,8 @@ for jamf_type in jamf_types:
8921001 if jamfsplit [1 ] not in jamf [jamfsplit [0 ]]:
8931002 logging .info ("Couldn't find {} for this device in {}, not checking it out." .format (jamfsplit [1 ], jamfsplit [0 ]))
8941003 continue
895- logging .info ('Checking out new item {} to user {}' .format (jamf ['general' ]['name' ], jamf ['{}' .format (jamfsplit [0 ])][ '{}' . format ( jamfsplit [ 1 ])] ))
896- checkout_snipe_asset (jamf ['{}' .format (jamfsplit [0 ])][ '{}' . format ( jamfsplit [ 1 ])] ,new_snipe_asset [1 ].json ()['payload' ]['id' ], "NewAsset" )
1004+ logging .info ('Checking out new item {} to user {}' .format (jamf ['general' ]['name' ], jamf ['{}' .format (jamfsplit [0 ])]))
1005+ checkout_snipe_asset (jamf ['{}' .format (jamfsplit [0 ])],new_snipe_asset [1 ].json ()['payload' ]['id' ], "NewAsset" )
8971006 # Log an error if there's an issue, or more than once match.
8981007 elif snipe == 'MultiMatch' :
8991008 logging .warning ("WARN: You need to resolve multiple assets with the same serial number in your inventory. If you can't find them in your inventory, you might need to purge your deleted records. You can find that in the Snipe Admin settings. Skipping serial number {} for now." .format (jamf ['general' ]['serial_number' ]))
@@ -967,7 +1076,7 @@ for jamf_type in jamf_types:
9671076 if jamfsplit [1 ] not in jamf [jamfsplit [0 ]]:
9681077 logging .info ("Couldn't find {} for this device in {}, not checking it out." .format (jamfsplit [1 ], jamfsplit [0 ]))
9691078 continue
970- checkout_snipe_asset (jamf ['{}' .format (jamfsplit [0 ])][ '{}' . format ( jamfsplit [ 1 ])] , snipe_id , snipe ['rows' ][0 ]['assigned_to' ])
1079+ checkout_snipe_asset (jamf ['{}' .format (jamfsplit [0 ])], snipe_id , snipe ['rows' ][0 ]['assigned_to' ])
9711080 else :
9721081 logging .info ("Can't checkout {} since the status isn't set to deployable" .format (jamf ['general' ]['name' ]))
9731082
0 commit comments