Module: JSS
- Defined in:
- lib/jss.rb,
lib/jss/client.rb,
lib/jss/server.rb,
lib/jss/utility.rb,
lib/jss/version.rb,
lib/jss/composer.rb,
lib/jss/api_object.rb,
lib/jss/exceptions.rb,
lib/jss/configuration.rb,
lib/jss/db_connection.rb,
lib/jss/api_connection.rb,
lib/jss/api_object/site.rb,
lib/jss/api_object/user.rb,
lib/jss/api_object/group.rb,
lib/jss/api_object/policy.rb,
lib/jss/api_object/script.rb,
lib/jss/api_object/account.rb,
lib/jss/api_object/package.rb,
lib/jss/api_object/webhook.rb,
lib/jss/api_object/building.rb,
lib/jss/api_object/category.rb,
lib/jss/api_object/computer.rb,
lib/jss/api_object/scopable.rb,
lib/jss/api_object/creatable.rb,
lib/jss/api_object/locatable.rb,
lib/jss/api_object/matchable.rb,
lib/jss/api_object/updatable.rb,
lib/jss/api_object/department.rb,
lib/jss/api_object/extendable.rb,
lib/jss/api_object/peripheral.rb,
lib/jss/api_object/uploadable.rb,
lib/jss/api_object/criteriable.rb,
lib/jss/api_object/ldap_server.rb,
lib/jss/api_object/purchasable.rb,
lib/jss/api_object/mobile_device.rb,
lib/jss/api_object/self_servable.rb,
lib/jss/api_object/netboot_server.rb,
lib/jss/api_object/scopable/scope.rb,
lib/jss/api_object/advanced_search.rb,
lib/jss/api_object/network_segment.rb,
lib/jss/api_object/peripheral_type.rb,
lib/jss/api_object/group/user_group.rb,
lib/jss/api_object/removable_macaddr.rb,
lib/jss/api_object/distribution_point.rb,
lib/jss/api_object/computer_invitation.rb,
lib/jss/api_object/extension_attribute.rb,
lib/jss/api_object/restricted_software.rb,
lib/jss/api_object/criteriable/criteria.rb,
lib/jss/api_object/group/computer_group.rb,
lib/jss/api_object/criteriable/criterion.rb,
lib/jss/api_object/software_update_server.rb,
lib/jss/api_object/group/mobile_device_group.rb,
lib/jss/api_object/osx_configuration_profile.rb,
lib/jss/api_object/advanced_search/advanced_user_search.rb,
lib/jss/api_object/advanced_search/advanced_computer_search.rb,
lib/jss/api_object/extension_attribute/user_extension_attribute.rb,
lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb,
lib/jss/api_object/extension_attribute/computer_extension_attribute.rb,
lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb
Overview
A mix-in module providing object-updating via the JSS API.
Defined Under Namespace
Modules: Composer, Creatable, Criteriable, Extendable, FileUpload, Locatable, Matchable, Purchasable, Scopable, SelfServable, Updatable, Uploadable Classes: APIConnection, APIObject, Account, AdvancedComputerSearch, AdvancedMobileDeviceSearch, AdvancedSearch, AdvancedUserSearch, AlreadyExistsError, AuthenticationError, Building, Category, Client, Computer, ComputerExtensionAttribute, ComputerGroup, ComputerInvitation, Configuration, DBConnection, Department, DistributionPoint, ExtensionAttribute, FileServiceError, Group, InvalidConnectionError, InvalidDataError, LDAPServer, MissingDataError, MobileDevice, MobileDeviceExtensionAttribute, MobileDeviceGroup, NetBootServer, NetworkSegment, NoSuchItemError, OSXConfigurationProfile, Package, Peripheral, PeripheralType, Policy, Preferences, RemovableMacAddress, RestrictedSoftware, Script, Server, Site, SoftwareUpdateServer, TimeoutError, UnmanagedError, UnsupportedError, User, UserExtensionAttribute, UserGroup, WebHook
Constant Summary collapse
- MINIMUM_RUBY_VERSION =
The minimum Ruby version that works with this gem
'2.0.0'.freeze
- MINIMUM_SERVER_VERSION =
The minimum JSS version that works with this gem, as returned by the API in the deprecated ‘jssuser’ resource
'9.4'.freeze
- 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].freeze
- NIL_DATES =
When parsing a date/time data into a Time object, these will return nil
[0, nil, '', '0'].freeze
- VERSION =
The version of the JSS ruby gem
'0.7.0'.freeze
- 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
- @@stdin_lines =
The contents of anything piped to stdin, split into lines. See stdin
nil- @@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.
-
.os_ok?(requirement, os_to_check = nil) ⇒ Boolean
Scripts and packages can have OS limitations.
-
.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.
-
.processor_ok?(requirement, processor = nil) ⇒ Boolean
Scripts and packages can have processor limitations.
-
.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>bar</foo>
<foo>morefoo</foo>
302 303 304 305 306 307 308 309 310 |
# File 'lib/jss/utility.rb', line 302 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.
284 285 286 |
# File 'lib/jss/db_connection.rb', line 284 def self.db DB_CNX.db end |
.epoch_to_time(epoch) ⇒ Time?
Converts JSS epoch (unix epoch + milliseconds) to a Ruby Time object
270 271 272 273 |
# File 'lib/jss/utility.rb', line 270 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.
* & => &
* " => "
* < => <
* > => >
* ' => '
286 287 288 |
# File 'lib/jss/utility.rb', line 286 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.
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 95 |
# File 'lib/jss/utility.rb', line 68 def self. (min_os) 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
328 329 330 331 332 333 334 335 336 337 |
# File 'lib/jss/utility.rb', line 328 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
371 372 373 374 375 376 377 |
# File 'lib/jss/utility.rb', line 371 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 |
.os_ok?(requirement, os_to_check = nil) ⇒ Boolean
Scripts and packages can have OS limitations. This method tests a given OS, against a requirement list to see if the requirement is met.
131 132 133 134 135 136 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/utility.rb', line 131 def self.os_ok? (requirement, os_to_check = nil) return true if requirement.to_s =~ /none/i return true if requirement.to_s == 'n' requirement = JSS.to_s_and_a(requirement)[:arrayform] return true if requirement.empty? os_to_check ||= `/usr/bin/sw_vers -productVersion`.chomp # convert the requirement array into an array of regexps. # examples: # "10.8.5" becomes /^10\.8\.5$/ # "10.8" becomes /^10.8(.0)?$/ # "10.8.x" /^10\.8\.?\d*$/ req_regexps = requirement.map do |r| if r.end_with?('.x') /^#{r.chomp('.x').gsub('.','\.')}\.?\d*$/ elsif r =~ /^\d+\.\d+$/ /^#{r.gsub('.','\.')}(.0)?$/ else /^#{r.gsub('.','\.')}$/ end end req_regexps.each{|re| return true if os_to_check =~ re } return false end |
.parse_datetime(a_datetime) ⇒ Object
Deprecated - to be eventually removed in favor of the more-appropriately named JSS::parse_time
262 |
# File 'lib/jss/utility.rb', line 262 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.
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'lib/jss/utility.rb', line 408 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.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/jss/utility.rb', line 202 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.
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/jss/utility.rb', line 238 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 |
.processor_ok?(requirement, processor = nil) ⇒ Boolean
Scripts and packages can have processor limitations. This method tests a given processor, against a requirement to see if the requirement is met.
111 112 113 114 115 116 |
# File 'lib/jss/utility.rb', line 111 def self.processor_ok? (requirement, processor = nil) return true if requirement.to_s.empty? or requirement =~ /none/i processor ||= `/usr/bin/uname -p` return requirement == (processor.to_s.include?("86") ? "x86" : "ppc") end |
.prompt_for_password(message) ⇒ String
Prompt for a password in a terminal.
466 467 468 469 470 471 472 473 474 475 476 477 478 |
# File 'lib/jss/utility.rb', line 466 def self.prompt_for_password() begin $stdin.reopen '/dev/tty' unless $stdin.tty? $stderr.print "#{} " 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 the first time this method is called and the lines are stored as an Array in the module var @@stdin_lines
452 453 454 455 456 457 458 |
# File 'lib/jss/utility.rb', line 452 def self.stdin(line = 0) @@stdin_lines ||= ($stdin.tty? ? [] : $stdin.read.lines.map{|line| line.chomp("\n") }) 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?.
438 439 440 |
# File 'lib/jss/utility.rb', line 438 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.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/jss/utility.rb', line 177 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 |