Module: JSS
- Defined in:
- lib/jss-api.rb,
lib/jss-api/client.rb,
lib/jss-api/server.rb,
lib/jss-api/utility.rb,
lib/jss-api/version.rb,
lib/jss-api/composer.rb,
lib/jss-api/api_object.rb,
lib/jss-api/exceptions.rb,
lib/jss-api/configuration.rb,
lib/jss-api/db_connection.rb,
lib/jss-api/api_connection.rb,
lib/jss-api/api_object/site.rb,
lib/jss-api/api_object/user.rb,
lib/jss-api/api_object/group.rb,
lib/jss-api/api_object/policy.rb,
lib/jss-api/api_object/script.rb,
lib/jss-api/api_object/package.rb,
lib/jss-api/api_object/building.rb,
lib/jss-api/api_object/category.rb,
lib/jss-api/api_object/computer.rb,
lib/jss-api/api_object/scopable.rb,
lib/jss-api/api_object/creatable.rb,
lib/jss-api/api_object/locatable.rb,
lib/jss-api/api_object/matchable.rb,
lib/jss-api/api_object/updatable.rb,
lib/jss-api/api_object/department.rb,
lib/jss-api/api_object/extendable.rb,
lib/jss-api/api_object/peripheral.rb,
lib/jss-api/api_object/uploadable.rb,
lib/jss-api/api_object/criteriable.rb,
lib/jss-api/api_object/ldap_server.rb,
lib/jss-api/api_object/purchasable.rb,
lib/jss-api/api_object/mobile_device.rb,
lib/jss-api/api_object/self_servable.rb,
lib/jss-api/api_object/netboot_server.rb,
lib/jss-api/api_object/scopable/scope.rb,
lib/jss-api/api_object/advanced_search.rb,
lib/jss-api/api_object/network_segment.rb,
lib/jss-api/api_object/peripheral_type.rb,
lib/jss-api/api_object/group/user_group.rb,
lib/jss-api/api_object/removable_macaddr.rb,
lib/jss-api/api_object/distribution_point.rb,
lib/jss-api/api_object/extension_attribute.rb,
lib/jss-api/api_object/criteriable/criteria.rb,
lib/jss-api/api_object/group/computer_group.rb,
lib/jss-api/api_object/criteriable/criterion.rb,
lib/jss-api/api_object/software_update_server.rb,
lib/jss-api/api_object/group/mobile_device_group.rb,
lib/jss-api/api_object/osx_configuration_profile.rb,
lib/jss-api/api_object/advanced_search/advanced_user_search.rb,
lib/jss-api/api_object/advanced_search/advanced_computer_search.rb,
lib/jss-api/api_object/extension_attribute/user_extension_attribute.rb,
lib/jss-api/api_object/advanced_search/advanced_mobile_device_search.rb,
lib/jss-api/api_object/extension_attribute/computer_extension_attribute.rb,
lib/jss-api/api_object/extension_attribute/mobile_device_extension_attribute.rb
Overview
JSS, A Ruby module for interacting with the JAMF Software Server via it’s REST API.
Defined Under Namespace
Modules: Composer, Creatable, Criteriable, Extendable, FileUpload, Locatable, Matchable, Purchasable, Scopable, SelfServable, Updatable, Uploadable Classes: APIConnection, APIObject, AdvancedComputerSearch, AdvancedMobileDeviceSearch, AdvancedSearch, AdvancedUserSearch, AlreadyExistsError, AuthenticationError, Building, Category, Client, Computer, ComputerExtensionAttribute, ComputerGroup, Configuration, DBConnection, Department, DistributionPoint, ExtensionAttribute, FileServiceError, Group, InvalidConnectionError, InvalidDataError, LDAPServer, MissingDataError, MobileDevice, MobileDeviceExtensionAttribute, MobileDeviceGroup, NetBootServer, NetworkSegment, NoSuchItemError, OSXConfigurationProfile, Package, Peripheral, PeripheralType, Policy, Preferences, RemovableMacAddress, Script, Server, Site, SoftwareUpdateServer, TimeoutError, UnmanagedError, UnsupportedError, User, UserExtensionAttribute, UserGroup
Constant Summary collapse
- MINIMUM_SERVER_VERSION =
The minimum JSS version that works with this gem, as returned by the API in the deprecated ‘jssuser’ resource
"9.4"- TIME_ZONE_OFFSET =
The current local UTC offset as a fraction of a day (Time.now.utc_offset is the offset in seconds, 60*60*24 is the seconds in a day)
Rational(Time.now.utc_offset, 60*60*24)
- TRUE_FALSE =
These are handy for testing values without making new arrays, strings, etc every time.
[true, false]
- NIL_DATES =
When parsing a date/time data into a Time object, these will return nil
[0, nil, '', '0']
- STDIN_LINES =
The contents of anything piped to stdin, split into lines. See stdin
$stdin.tty? ? [] : $stdin.read.lines.map{|line| line.chomp("\n") }
- VERSION =
The version of the JSS ruby gem
"0.6.1"- CONFIG =
The single instance of Configuration
JSS::Configuration.instance
- DB_CNX =
The single instance of the DBConnection
DBConnection.instance
- API =
The single instance of the APIConnection
APIConnection.instance
- @@master_distribution_point =
the master dist. point, see JSS.master_distribution_point
nil- @@my_distribution_point =
the dist point for this machine right now
nil
Class Method Summary collapse
-
.array_to_rexml_array(element, list) ⇒ Array<REXML::Element>
Given an element name and an array of content, generate an Array of REXML::Element objects with that name, and matching content.
-
.db ⇒ Mysql
The mysql database available through the DBConnection.instance.
-
.epoch_to_time(epoch) ⇒ Time?
Converts JSS epoch (unix epoch + milliseconds) to a Ruby Time object.
-
.escape_xml(string) ⇒ String
Given a string of xml element text, escape any characters that would make XML unhappy.
-
.expand_min_os(min_os) ⇒ Array
Converts an OS Version into an Array of higher OS versions.
-
.hash_to_rexml_array(hash) ⇒ Array<REXML::Element>
Given a simple Hash, convert it to an array of REXML Elements such that each key becomes an element, and its value becomes the text content of that element.
-
.item_list_to_rexml_list(list_element, item_element, item_list, content = :name) ⇒ REXML::Element
Given an Array of Hashes with :id and/or :name keys, return a single REXML element with a sub-element for each item, each of which contains a :name or :id element.
-
.parse_datetime(a_datetime) ⇒ Object
Deprecated - to be eventually removed in favor of the more-appropriately named JSS::parse_time.
-
.parse_jss_version(version) ⇒ Hash{Symbol => String, Gem::Version}
Parse a JSS Version number into something comparable.
-
.parse_plist(plist) ⇒ Object
Parse a plist into a Ruby data structure.
-
.parse_time(a_datetime) ⇒ Time?
Converts anything that responds to #to_s to a Time, or nil.
-
.prompt_for_password(message) ⇒ String
Prompt for a password in a terminal.
-
.stdin(line = 0) ⇒ String?
Retrive one or all lines from whatever was piped to standard input.
-
.superuser? ⇒ Boolean
Is this code running as root?.
-
.to_s_and_a(somedata) ⇒ Hash{:stringform => String, :arrayform => Array}
Given a list of data as a comma-separated string, or an Array of strings, return a Hash with both versions.
Class Method Details
.array_to_rexml_array(element, list) ⇒ Array<REXML::Element>
Given an element name and an array of content, generate an Array of REXML::Element objects with that name, and matching content. The array of REXML elements would render thus:
<foo></foo>
<foo>morefoo</foo>
237 238 239 240 241 242 243 244 245 |
# File 'lib/jss-api/utility.rb', line 237 def self.array_to_rexml_array(element,list) raise JSS::InvalidDataError, "Arg. must be an Array." unless list.kind_of? Array element = element.to_s list.map do |v| e = REXML::Element.new(element) e.text = v e end end |
.db ⇒ Mysql
Returns The mysql database available through the DBConnection.instance.
292 293 294 |
# File 'lib/jss-api/db_connection.rb', line 292 def self.db DB_CNX.db end |
.epoch_to_time(epoch) ⇒ Time?
Converts JSS epoch (unix epoch + milliseconds) to a Ruby Time object
205 206 207 208 |
# File 'lib/jss-api/utility.rb', line 205 def self.epoch_to_time(epoch) return nil if NIL_DATES.include? epoch Time.at(epoch.to_i / 1000.0) end |
.escape_xml(string) ⇒ String
Given a string of xml element text, escape any characters that would make XML unhappy.
* & => &
* " => "
* < => <
* > => >
* ' => '
221 222 223 |
# File 'lib/jss-api/utility.rb', line 221 def self.escape_xml(string) string.gsub(/&/, '&').gsub(/\"/, '"').gsub(/>/, '>').gsub(/</, '<').gsub(/'/, ''') end |
.expand_min_os(min_os) ⇒ Array
Converts an OS Version into an Array of higher OS versions.
It’s unlikely that this library will still be in use as-is by the release of OS X 10.19.15. Hopefully well before then JAMF will implement a “minimum OS” in the JSS itself.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/jss-api/utility.rb', line 67 def self. (min_os) min_os.delete! ">=" ### split the version into major, minor and maintenance release numbers (maj,min,maint) = min_os.split(".") maint = "x" if maint.nil? or maint == "0" ### if the maint release number is an "x" just start the list of OK OS's with it if maint == "x" ok_oses = [maj + "." + min.to_s + ".x"] ### otherwise, start with it and explicitly add all maint releases up to 15 ### (and hope apple doesn't do more than 15 maint releases for an OS) else ok_oses = [] (maint.to_i..15).each do |m| ok_oses << maj + "." + min +"." + m.to_s end # each m end ### now account for all OS X versions starting with 10. ### up to at least 10.19.x ((min.to_i + 1)..19).each do |v| ok_oses << maj + "." + v.to_s + ".x" end # each v return ok_oses end |
.hash_to_rexml_array(hash) ⇒ Array<REXML::Element>
Given a simple Hash, convert it to an array of REXML Elements such that each key becomes an element, and its value becomes the text content of that element
263 264 265 266 267 268 269 270 271 272 |
# File 'lib/jss-api/utility.rb', line 263 def self.hash_to_rexml_array(hash) raise InvalidDataError, "Arg. must be a Hash." unless hash.kind_of? Hash ary = [] hash.each_pair do |k,v| el = REXML::Element.new k.to_s el.text = v ary << el end ary end |
.item_list_to_rexml_list(list_element, item_element, item_list, content = :name) ⇒ REXML::Element
Given an Array of Hashes with :id and/or :name keys, return a single REXML element with a sub-element for each item, each of which contains a :name or :id element.
e.g. :computers
e.g. :computer
306 307 308 309 310 311 312 |
# File 'lib/jss-api/utility.rb', line 306 def self.item_list_to_rexml_list(list_element, item_element , item_list, content = :name) xml_list = REXML::Element.new list_element.to_s item_list.each do |i| xml_list.add_element(item_element.to_s).add_element(content.to_s).text = i[content] end xml_list end |
.parse_datetime(a_datetime) ⇒ Object
Deprecated - to be eventually removed in favor of the more-appropriately named JSS::parse_time
197 |
# File 'lib/jss-api/utility.rb', line 197 def self.parse_datetime(a_datetime) ; self.parse_time(a_datetime) ; end |
.parse_jss_version(version) ⇒ Hash{Symbol => String, Gem::Version}
Parse a JSS Version number into something comparable
Unfortunately, the JSS version numbering is inconsistant and improper at the moment. Version 9.32 should be version 9.3.2, so that it will be recognizable as being less than 9.4
To work around this until JAMF standardizes version numbering, we will assume any digits before the first dot is the major version and the first digit after the first dot is the minor version and anything else, including other dots, is the revision
If that revision starts with a dot, it is removed. so 9.32 becomes major-9, minor-3, rev-2 and 9.32.3764 becomes major-9, minor-3, rev-2.3764 and 9.3.2.3764 becomes major-9, minor-3, rev-2.3764
This method of parsing will break if the minor revision ever gets above 9.
Returns a hash with these keys:
-
:major => the major version, Integer
-
:minor => the minor version, Integor
-
:revision => the revision, String
-
:version => a Gem::Version object built from the above keys, which is easily compared to others.
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/jss-api/utility.rb', line 343 def self.parse_jss_version(version) spl = version.split('.') case spl.count when 1 major = spl[0].to_i minor = 0 revision = '0' when 2 major = spl[0].to_i minor = spl[1][0,1].to_i revision = spl[1][1..-1] revision = '0' if revision.empty? else major = spl[0].to_i minor = spl[1][0,1].to_i revision = spl[1..-1].join('.')[1..-1] revision = revision[1..-1] if revision.start_with? '.' end ###revision = revision[1..-1] if revision.start_with? '.' { :major => major, :minor => minor, :revision => revision, :version => Gem::Version.new("#{major}.#{minor}.#{revision}") } end |
.parse_plist(plist) ⇒ Object
Parse a plist into a Ruby data structure. This enhances Plist::parse_xml taking file paths, as well as XML Strings and reading the files regardless of binary/XML format.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/jss-api/utility.rb', line 137 def self.parse_plist (plist) # did we get a string of xml, or a string pathname? case plist when String if plist.include? "</plist>" return Plist.parse_xml plist else plist = Pathname.new plist end when Pathname true else raise ArgumentError, "Argument must be a path (as a Pathname or String) or a String of XML" end # case plist # if we're here, its a Pathname raise JSS::MissingDataError, "No such file: #{plist}" unless plist.file? return Plist.parse_xml `/usr/libexec/PlistBuddy -x -c print #{Shellwords.escape(plist.to_s)}` end |
.parse_time(a_datetime) ⇒ Time?
Converts anything that responds to #to_s to a Time, or nil
Return nil if the item is nil, 0 or an empty String.
Otherwise the item converted to a string, and parsed with DateTime.parse. It is then examined to see if it has a UTC offset. If not, the local offset is applied, then the DateTime is converted to a Time.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/jss-api/utility.rb', line 173 def self.parse_time(a_datetime) return nil if NIL_DATES.include? a_datetime the_dt = DateTime.parse(a_datetime.to_s) ### The microseconds in DateTimes are stored as a fraction of a day. ### Convert them to an integer of microseconds usec = (the_dt.sec_fraction * 60 * 60 * 24 * (10**6)).to_i ### if the UTC offset of the datetime is zero, make a new one with the correct local offset ### (which might also be zero if we happen to be in GMT) if the_dt.offset == 0 the_dt = DateTime.new(the_dt.year, the_dt.month, the_dt.day, the_dt.hour, the_dt.min, the_dt.sec, JSS::TIME_ZONE_OFFSET) end # now convert it to a Time and return it Time.at the_dt.strftime('%s').to_i, usec end |
.prompt_for_password(message) ⇒ String
Prompt for a password in a terminal.
401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/jss-api/utility.rb', line 401 def self.prompt_for_password() begin $stdin.reopen '/dev/tty' unless $stdin.tty? $stderr.print "#{message} " system "/bin/stty -echo" pw = $stdin.gets.chomp("\n") puts ensure system "/bin/stty echo" end # begin return pw end |
.stdin(line = 0) ⇒ String?
Retrive one or all lines from whatever was piped to standard input.
Standard input is read completely when the module loads and the lines are stored as an Array in the constant STDIN_LINES
387 388 389 390 391 392 393 |
# File 'lib/jss-api/utility.rb', line 387 def self.stdin(line = 0) return STDIN_LINES.join("\n") if line <= 0 idx = line - 1 return STDIN_LINES[idx] end |
.superuser? ⇒ Boolean
Returns is this code running as root?.
373 374 375 |
# File 'lib/jss-api/utility.rb', line 373 def self.superuser? Process.euid == 0 end |
.to_s_and_a(somedata) ⇒ Hash{:stringform => String, :arrayform => Array}
Given a list of data as a comma-separated string, or an Array of strings, return a Hash with both versions.
Some parts of the JSS require lists as comma-separated strings, while often those data are easier work with as arrays. This method is a handy way to get either form when given either form.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/jss-api/utility.rb', line 112 def self.to_s_and_a (somedata) case somedata when nil valstr = "" valarr = [] when String valstr = somedata valarr = somedata.split(/,\s*/) when Array valstr = somedata.join ", " valarr = somedata else raise JSS::InvalidDataError, "Input must be a comma-separated String or an Array of Strings" end # case return {:stringform => valstr, :arrayform => valarr} end |