/Users/Shared. This is to address failing mount points on macOS Big Sur.
$to safe characters in URLs to allow hidden shares (#169).
urllib3dependency version bumped to mitigate vulnerability.
JCDSDistribution Point type. This distribution point type takes no configuration parameters except the
JCDStype retrieves information about your jamfcloud instance and uploads packages directly instead of the
/dbfileuploadendpoint which should improve speed and reliability.
NSURLSessionAdapterto perform native API HTTP transfers on macOS. This was to work around the TLS1.2 issue and is largely superseded by the default Requests Adapter.
JCDSdistribution point type to get files via the legacy
JCDSdistribution point type has a multi-threaded implementation as well as a single threaded one.
AWSrepo type, which will establish a direct connection to Amazon S3 via the boto library.
remove_packagemethods to the
Content-Typeof the response from the API to determine how it should decode the response. This was necessary to support the new UAPI/JAMF Pro API.
OSXConfigurationProfileto make creating new instances easier.
RequestsAdapter, because we are now using requests directly.
TLSAdapter, because we do not have the TLS1.2 problem.
LDAPServerincorrectly tried to use PUT to create new objects because the implementation of the
idproperty was incorrect.
RequestsAdapterto wrap curl in requests' API. This is primarily to deal with the fact that Apple's shipped OpenSSL is extremely out of date (requests uses pyopenssl, which uses the out-of-date OpenSSL). Since current recommendations from Jamf are to run the Casper server using only TLS1.2, this puts us in a bind. So, by default, python-jss will now use curl for networking. Developers seeking the advantages of using requests can replace the networking adapter they want to use (see
JSSObjectand all of its subclasses can now be used as a context manager (the python
withstatement). All this does is automatically tries to save the object automatically on the way out of the with context.
Container.__contains__magic method, which allows you to do things like
if some_pkg in some_policy:. Please note, this will find any reference to that object contained within. This may not be what you want, for example, if a computer is in a group's exclusions list but you want to know if it's in the inclusion list. Thankfully, there's a method for that (
JSSObjectmagic methods for equality and hash. This means you can test whether two
Computerobjects are the same, for example. You can also now use the objects as keys in a dictionary, or other mapping.
True) to compress pickle output. A lot.
JSSObjects. For example, you can now do
computer.configuration_profiles.size.textto reach all the way down the tree to that value.
JSSObjects have a
tree()method which will return a nicely indented representation of the tag structure of the object. Use it like this:
matchsearch detection for object types that support it. Now you can do
j.Computer("match=MacBook*"). Match searches will always return a QuerySet.
JSS.version()method now returns the server's version (using the jssuser endpoint.
DistributionPointscollection class iterable, so if you do need to operate on individual DPs within, you don't need to fool around with the private collection. (See JSSImporter for an example).
Script.add_script()to handle XML escaping and adding a script payload to a
suppress_warningspreference out of
JSSand into the requests adapter. The
JSSinitialization will accept that keyword argument to ease the (sudden) deprecation, but it just won't do anything. Use the
RequestsAdapter.suppress_warnings()method if you need it.
JSSobject will now default to using the
CurlAdapterfor networking. Use
JSS.mount_networking_adapter()to replace it with the
RequestsAdapterand gain things like sessions.
subsetpositional argument). Whether the JSS is considered to work with subsetting is recorded as a new attribute on the class (
jss.Computer.allowed_kwargs = Truefor example). This, again, makes it easier to maintain as JAMF adds or removes query features. The search methods docstrings all reflect the level of (considered) support.
JSSObjectListis now called a
QuerySet, inspired by Django. The old behavior was that the contents were just id/name for each contained object, until you used the "retrieve" method. Now all objects contained within are full JSSObjects.
strtoo casually. Throughout, class'
reprhas been rewritten to provide a very basic marker of the type, and
strhas been written to provide the pretty-printing of XML functionality that it had previously. In practice, this means that in the interpreter, developers will have to
print xinstead of just entering
xto see what they have. However, it also means that simply doing
xgives easier to read information for QuerySets of items without dumping their entire contents to screen (e.g.
j.Computer()results in thousands of lines vomited into your terminal).
Containerand all of its subclasses (most types of data from the JSS) now use lazy-loading to defer sending a GET method until you actually need the data.
Elementobjects added to a
JSSObjectwill get converted to the
PrettyElementtype to enable dot access and pretty printing.
JSSObjectListhas been renamed to QuerySet and now inherits from it. While it is unlikely that any client code directly references this class, it is worth checking for in your code. It will be remmoved entirely in a future release. Please update code to use the QuerySet API and signature.
jss_migratedpreference has been removed. This is no longer an issue with current and future JSS versions.
JSSObjectList.retrieve()has been removed as it's no longer needed.
from_pickle(). This code is just cruft; it's just about the same amount of work to pickle it on your own.
JSSObjectFactorywas removed as it is no longer needed. Client code should use
getattrif it needs to dynamically choose which class to use.
JSSDeviceObjectwas removed as it was no longer needed. It only added a
serial_numbermethod to two subclasses,
MobileDevice. You can access these through
.access to subelements, all properties doing the same thing have been removed. The vast majority of these were in
a_policy.computersis now accessed through
JSS.passwordproper properties, that will set the attached network adapter appropriately.
Policy.add_package. Now you can specify that you want to "Cache", "Install Cached", or "Install". Uses "Install" by default. (#48)
CommandFlushobject (new endpoint in JSS API).
LogFlushobject (new endpoint in JSS API).
VPPAssignmentobject (untested at this time).
VPPInvitationobject (untested at this time).
JSSObject.to_filemethods to JSSObject.
Policy. (#50 Thanks @jlrgraham)
subsetparam). As I have limited development time for this project, these endpoints have stub objects added, but no
JSShelper method, testing, or easy import with
import jss. The TODO list has an item to add an ability to handle an arbitrary number of keyword arguments to a a GET request to support these new endpoints. Until then, the following objects serve as placeholders:
ComputerApplicationobject (untested at this time).
ComputerHardwareSoftwareReportobject (untested at this time).
ComputerHistoryobject (untested at this time).
JSSObjectList.retrieve_allnow returns a
JSSObjectListinstead of a list. This is to support being able to pickle/unpickle the contained objects all at once.
JSSObject.from_stringencodes input to utf-8 now. ElementTree.fromstring doesn't accept unicode, so anything outside of ascii throws an exception. (#44 Thanks @systemheld!)
distribution_point.pyto satisfy Requests' requirement for string-type headers (#55 thanks @ftiff!)
JSSListData, making the retrieval of individual
JSSObjectListelements more flexible.
JSSListDataso you can now better interact with them.
suppress_warningskey to the preference domain and
DistributionPoints.copy. This allows you to provide some feedback for long copying operations. In the future, if desired, more may be added to long-running methods like
JSSObjectFactoryif you're into doing some lower-level object searching and creation.
JSSObject.savemethod. It was very convoluted. Now it reads better, is more error resistant, and should work exactly the same. Specifically, it assumes that if your JSSObject has no ID, then it is a new object (because only the JSS can assign one) and thus needs to PUT. If it does have an ID, then it POSTs it. Potentially this could be an issue where if you retrieved an object, and then wanted to completely replace it with different data, and then tried to save, it would then be missing the ID and would PUT, creating a new object (or fail because of the name conflict); I don't see that as a real issue though.
JSSObject.searchsince it implements a deprecated Element method that wasn't being used anywhere.
Policy.save. It's likely this was broader than just Packages and Policies, but python-jss hadn't implemented or tested other objects.
JSSObject.pretty_findas it's no longer needed.
data_keysto generate the structure. It allows for setting default values.
_newmethods accept any of the
data_keysas keyword args to be set during creation.
JSSObject._newto discourage client use.
JSSObject.set_boolimproved to not have broken string behavior.
jss_connection.Computer(None, "basic") for extended list information orjss_connection.Computer("computer-name", "general&purchasing")
orjss_connection.Computer("computer-name", ["general", "purchasing"])
for subsection retrieval. This should allow you to speed up bigretrieve_all` runs significantly.
JSSObject.pretty_find. Pretty prints sub-elements of a JSSObject for use in interactive exploration of the JSS.
JSSPrefsand the com.github.sheagcraig.python-jss preference domain. If not specified in the preferences, it will assume
JSSGroupObjectand subclasses for
is_smart. Now you can have a regular boolean property and setter for groups.
JSSGroupObject. This allows you to test whether a Computer or MobileDevice object is a member of a group.
__repr__now displays simply
*data*instead of the full binary data for things like icons and app binaries.
JSSobject's get method.
JSSobject's get method, since apparently requests doesn't do this for us.
JSSGroupObject.set_is_smart. (Replaced with
jss.ComputerGroups that are made with the
newmethod now include the
computerssubelement. Strangely, even smart groups include a computers tag. If previously populated with computer objects, it will retain them!
install_requiresto specify dependencies:
JSS.base_url(Get and Set) and
JSS._url(Read only) are now proper properties.
jss.JSS.ssl_verifyis now a computed property and will properly update the requests session if changed after instantiation.
Casperclass did not use the requests session on the JSS object passed to it.
Package.newnow sets the
MobileDeviceGroupnow correctly inherits from
jss.exceptions.JSSError, and all exceptions now subclass it.
jss.toolsfor misc. tools. (Right now, shorthand os detection functions).
Policy.add_object_to_exclusions. Thanks to @MScottBlake
~/.com.github.sheagcraig.python-jss.plistand should be a non-binary plist.
is_mountedmethod for dynamic mount point reconfiguration.
AttributeErrorwith pre-existing computer groups. (#34)
is_mountedmethod. (sheagcraig/JSSImporter#35). Thanks for the heads up @rtrouton!
PROTOCOL_TLSv1. Removes need for manually editing each requests release.
search_users()searches for users.
search_groups()searches for groups.
is_user_in_group()tests for group membership by user.
is_mountedmethod now looks for mounted shares by server, and updates mount point dynamically if it is different than configured. This prevents issues when multiple shares have the same name, or when Casper Admin is open and has mounted them already, with different-than-expected share names. Thanks @eahrold!
__repr__corrected to make use of
umountnow has a
forcedargument which defaults to
mount_point, due to the dynamic handling above, is no longer made by concatenating the repo name or "JSS" and share name. Thanks @eahrold!
jss.Siteso it will properly add itself to other objects. Thanks @MScottBlake. (#29)
jss.distribution_points.JDS.delete_with_casperAdminSave(). The latter is the method used by the Casper Admin app, and is included mostly for reference.
jss_migratedis handled correctly. (sheagcraig/JSSImporter#19)
distribution_points.DistributionPointdid not have
distribution_pointsto be ints.
jss.JSSobjects to disable urllib3 warnings. Use at your own risk. (sheagcraig/jss-autopkg-addon#18)
repo_prefsparameter to the
JSS, we shouldn't attempt
DistributionPoints.retrieve_all(). Reordered slightly to avoid problems. (#21)
JSSObject.save()has been reworked to safely handle all permutations of PUT and POST abilities on objects. For example,
ComputerInvitationscan only POST, not PUT, and did not work correctly.
JSSobjects will now have a
JSS.distribution_pointseven if no repos are configured. This makes it easier to add in after the fact.
JSSObject.save()now has better error reporting.
savemethod on Policies and Packages until they fix it. Please let me know if you come across others.
I did a quick update to include an egg installer on pypi.org. This was needed to support the jss-autopkg-addon installer.
domainwere incorrectly pulled from preferences. This has been corrected. Thanks @eahrold. (sheagcraig/jss-autopkg-addon#11)
name. This is now properly set as optional. If left out, a generic name with an incremented numeric suffix will be used.
casper. This class pulls the information returned from POSTing to the undocumented casper.jxml. At some point I would like this to allow for automatic configuration of all repository information (provided an authentication by a privileged user). However, due to its undocumented nature, I don't want to rely on it until I can get some confirmation from JAMF that this is 'OK'.
DistributionPointsnow have helper methods to add and remove a
repos. (Previously, it would try to match all DP's from .distributionpoints to a config option).
passwordwill still get the rest of the information from the server.
FileUploadsis squared away.
FileUploadswere sent using a non-session request because I couldn't get it working with a session. I got it working with a session.
FileUploadsnon-session request lacked the verify parameter, thus, even if SSL verification was turned off in the JSS object, it still tried to verify SSL.
FileUpload. Previous behavior was to give resource the full upload path as a name. Switched to just os.path.basename()
DistributionPoints.exists()for testing for the existence of a script/pkg across all distribution points.
DistributionPointsto handle copying packages and scripts across all configured repositories.
JDSRepository. (Only AFP and SMB implemented currently-HTTP(S) and JDS coming soon.)
repospreference key in com.github.sheagcraig.python-jss.plist. See README.
__version__property to module. Use for version checking if needed.
JSSObject.save()logic to try to update first. Trying to create a new object first with existing objects results in a name conflict exception, which you then have to catch. But when you DO have a name conflict, you really would like to know. This saves the need to wrap save calls in a try/except for updating existing objects. E.g. batch_scope verb of jss_helper.
JSS._error_handler()now adds a
status_codeattribute to exceptions.
JSSObject.save()was confusing. If you created a new object with
JSSObject()that conflicted with an existing object on the JSS, the save would fail with a
JSSPutError. Now we check for conflicts and instead return a
JSSPostErrorwith a more helpful error message.
jss_passwordin the README. Now the code and README agree:
jss_passis the correct key.
JSSObject.save()to represent its added responsibilities (it can now post new objects as well)
policy = Policy(jss_instance, "Install Adventure") policy.save()
jss_helpernow has a promotion feature... Except see CHANGES below.
XMLEditor.add_object_to_list()now returns the element added.
JSSObject.update()now accepts a template as a parameter (defaults to None) to replace instance's data from a template.
JSSObject.update()did not properly update instance's data.
jss_helperto its own project, here: https://github.com/sheagcraig/jss_helper
TemplateFromStringclasses for using external template files and strings.