ruby-jss 1.2.4a4 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

Files changed (248) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +185 -1
  3. data/README.md +3 -1
  4. data/bin/cgrouper +1 -1
  5. data/bin/jamfHelperBackgrounder +1 -1
  6. data/bin/netseg-update +1 -1
  7. data/data/ruby-jss.conf.example +1 -1
  8. data/lib/jamf.rb +1 -1
  9. data/lib/jamf/api/abstract_classes/advanced_search.rb +1 -1
  10. data/lib/jamf/api/abstract_classes/collection_resource.rb +31 -26
  11. data/lib/jamf/api/abstract_classes/generic_reference.rb +1 -1
  12. data/lib/jamf/api/abstract_classes/json_object.rb +15 -5
  13. data/lib/jamf/api/abstract_classes/prestage.rb +2 -2
  14. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +1 -1
  15. data/lib/jamf/api/abstract_classes/resource.rb +1 -1
  16. data/lib/jamf/api/abstract_classes/singleton_resource.rb +1 -1
  17. data/lib/jamf/api/attribute_classes/ip_address.rb +1 -1
  18. data/lib/jamf/api/attribute_classes/timestamp.rb +1 -1
  19. data/lib/jamf/api/connection.rb +106 -60
  20. data/lib/jamf/api/connection/api_error.rb +1 -1
  21. data/lib/jamf/api/connection/api_error_styleguide.rb +1 -1
  22. data/lib/jamf/api/connection/token.rb +80 -13
  23. data/lib/jamf/api/json_objects/account_prefs.rb +1 -1
  24. data/lib/jamf/api/json_objects/android_details.rb +1 -1
  25. data/lib/jamf/api/json_objects/appletv_details.rb +1 -1
  26. data/lib/jamf/api/json_objects/attachment.rb +1 -1
  27. data/lib/jamf/api/json_objects/cellular_network.rb +1 -1
  28. data/lib/jamf/api/json_objects/change_log_entry.rb +1 -1
  29. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +1 -1
  30. data/lib/jamf/api/json_objects/country.rb +1 -1
  31. data/lib/jamf/api/json_objects/criterion.rb +1 -1
  32. data/lib/jamf/api/json_objects/device_enrollment_device.rb +1 -1
  33. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  34. data/lib/jamf/api/json_objects/extension_attribute_value.rb +1 -1
  35. data/lib/jamf/api/json_objects/installed_application.rb +1 -1
  36. data/lib/jamf/api/json_objects/installed_certificate.rb +1 -1
  37. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +1 -1
  38. data/lib/jamf/api/json_objects/installed_ebook.rb +1 -1
  39. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +1 -1
  40. data/lib/jamf/api/json_objects/inventory_preload_extension_attribute.rb +1 -1
  41. data/lib/jamf/api/json_objects/ios_details.rb +1 -1
  42. data/lib/jamf/api/json_objects/location.rb +1 -1
  43. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  44. data/lib/jamf/api/json_objects/md_prestage_names.rb +1 -1
  45. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +1 -1
  46. data/lib/jamf/api/json_objects/mobile_device_details.rb +1 -1
  47. data/lib/jamf/api/json_objects/mobile_device_security.rb +1 -1
  48. data/lib/jamf/api/json_objects/prestage_assignment.rb +1 -1
  49. data/lib/jamf/api/json_objects/prestage_location.rb +1 -1
  50. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +1 -1
  51. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  52. data/lib/jamf/api/json_objects/prestage_sync_status.rb +1 -1
  53. data/lib/jamf/api/json_objects/purchasing_data.rb +1 -1
  54. data/lib/jamf/api/mixins/abstract.rb +1 -1
  55. data/lib/jamf/api/mixins/bulk_deletable.rb +1 -1
  56. data/lib/jamf/api/mixins/change_log.rb +1 -1
  57. data/lib/jamf/api/mixins/extendable.rb +1 -1
  58. data/lib/jamf/api/mixins/immutable.rb +1 -1
  59. data/lib/jamf/api/mixins/locatable.rb +1 -1
  60. data/lib/jamf/api/mixins/lockable.rb +1 -1
  61. data/lib/jamf/api/mixins/referable.rb +1 -1
  62. data/lib/jamf/api/mixins/searchable.rb +1 -1
  63. data/lib/jamf/api/mixins/uncreatable.rb +1 -1
  64. data/lib/jamf/api/mixins/undeletable.rb +1 -1
  65. data/lib/jamf/api/resources/collection_resources/account.rb +1 -1
  66. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +1 -1
  67. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +1 -1
  68. data/lib/jamf/api/resources/collection_resources/building.rb +1 -1
  69. data/lib/jamf/api/resources/collection_resources/category.rb +1 -1
  70. data/lib/jamf/api/resources/collection_resources/computer.rb +1 -1
  71. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +1 -1
  72. data/lib/jamf/api/resources/collection_resources/department.rb +1 -1
  73. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +1 -1
  74. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +1 -1
  75. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +9 -2
  76. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +1 -1
  77. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +1 -1
  78. data/lib/jamf/api/resources/collection_resources/script.rb +1 -1
  79. data/lib/jamf/api/resources/collection_resources/site.rb +1 -1
  80. data/lib/jamf/api/resources/collection_resources/time_zone.rb +1 -1
  81. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +1 -1
  82. data/lib/jamf/api/resources/singleton_resources/authorization.rb +1 -1
  83. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +1 -1
  84. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +1 -1
  85. data/lib/jamf/client.rb +1 -1
  86. data/lib/jamf/client/jamf_binary.rb +1 -1
  87. data/lib/jamf/client/jamf_helper.rb +1 -1
  88. data/lib/jamf/client/management_action.rb +1 -1
  89. data/lib/jamf/compatibility.rb +1 -1
  90. data/lib/jamf/composer.rb +1 -1
  91. data/lib/jamf/configuration.rb +8 -10
  92. data/lib/jamf/exceptions.rb +6 -1
  93. data/lib/jamf/ruby_extensions.rb +2 -1
  94. data/lib/jamf/ruby_extensions/array.rb +2 -2
  95. data/lib/jamf/ruby_extensions/array/predicates.rb +1 -1
  96. data/lib/jamf/ruby_extensions/array/utils.rb +4 -4
  97. data/lib/jamf/ruby_extensions/dig.rb +52 -0
  98. data/lib/jamf/ruby_extensions/filetest.rb +1 -1
  99. data/lib/jamf/ruby_extensions/filetest/predicates.rb +1 -1
  100. data/lib/jamf/ruby_extensions/hash.rb +1 -1
  101. data/lib/jamf/ruby_extensions/hash/backports.rb +2 -2
  102. data/lib/jamf/ruby_extensions/ipaddr.rb +1 -1
  103. data/lib/jamf/ruby_extensions/ipaddr/utils.rb +1 -1
  104. data/lib/jamf/ruby_extensions/object.rb +1 -1
  105. data/lib/jamf/ruby_extensions/object/predicates.rb +1 -1
  106. data/lib/jamf/ruby_extensions/pathname.rb +1 -1
  107. data/lib/jamf/ruby_extensions/pathname/predicates.rb +1 -1
  108. data/lib/jamf/ruby_extensions/pathname/utils.rb +1 -1
  109. data/lib/jamf/ruby_extensions/string.rb +1 -1
  110. data/lib/jamf/ruby_extensions/string/backports.rb +1 -1
  111. data/lib/jamf/ruby_extensions/string/conversions.rb +1 -1
  112. data/lib/jamf/ruby_extensions/string/predicates.rb +14 -4
  113. data/lib/jamf/utility.rb +1 -1
  114. data/lib/jamf/validate.rb +1 -1
  115. data/lib/jamf/version.rb +2 -2
  116. data/lib/jpapi.rb +1 -1
  117. data/lib/jss-api.rb +1 -1
  118. data/lib/jss.rb +5 -2
  119. data/lib/jss/api_connection.rb +3 -30
  120. data/lib/jss/api_object.rb +16 -3
  121. data/lib/jss/api_object/account.rb +1 -1
  122. data/lib/jss/api_object/advanced_search.rb +1 -1
  123. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +1 -1
  124. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +1 -1
  125. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +1 -1
  126. data/lib/jss/api_object/building.rb +1 -1
  127. data/lib/jss/api_object/categorizable.rb +1 -1
  128. data/lib/jss/api_object/category.rb +1 -1
  129. data/lib/jss/api_object/computer.rb +12 -6
  130. data/lib/jss/api_object/computer/application_installs.rb +1 -1
  131. data/lib/jss/api_object/computer_invitation.rb +1 -1
  132. data/lib/jss/api_object/configuration_profile.rb +4 -2
  133. data/lib/jss/api_object/configuration_profile/mobile_device_configuration_profile.rb +1 -1
  134. data/lib/jss/api_object/configuration_profile/osx_configuration_profile.rb +1 -1
  135. data/lib/jss/api_object/creatable.rb +1 -1
  136. data/lib/jss/api_object/criteriable.rb +10 -5
  137. data/lib/jss/api_object/criteriable/criteria.rb +26 -10
  138. data/lib/jss/api_object/criteriable/criterion.rb +1 -1
  139. data/lib/jss/api_object/department.rb +1 -1
  140. data/lib/jss/api_object/directory_binding.rb +273 -0
  141. data/lib/jss/api_object/directory_binding_type.rb +90 -0
  142. data/lib/jss/api_object/directory_binding_type/active_directory.rb +502 -0
  143. data/lib/jss/api_object/directory_binding_type/admitmac.rb +525 -0
  144. data/lib/jss/api_object/directory_binding_type/centrify.rb +212 -0
  145. data/lib/jss/api_object/directory_binding_type/open_directory.rb +178 -0
  146. data/lib/jss/api_object/directory_binding_type/powerbroker_identity_services.rb +73 -0
  147. data/lib/jss/api_object/disk_encryption_configurations.rb +114 -0
  148. data/lib/jss/api_object/distribution_point.rb +96 -36
  149. data/lib/jss/api_object/dock_item.rb +137 -0
  150. data/lib/jss/api_object/ebook.rb +1 -1
  151. data/lib/jss/api_object/extendable.rb +67 -28
  152. data/lib/jss/api_object/extension_attribute.rb +1 -1
  153. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +1 -1
  154. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +1 -1
  155. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +1 -1
  156. data/lib/jss/api_object/group.rb +1 -1
  157. data/lib/jss/api_object/group/computer_group.rb +1 -1
  158. data/lib/jss/api_object/group/mobile_device_group.rb +1 -1
  159. data/lib/jss/api_object/group/user_group.rb +1 -1
  160. data/lib/jss/api_object/ibeacon.rb +1 -1
  161. data/lib/jss/api_object/ldap_server.rb +1 -1
  162. data/lib/jss/api_object/locatable.rb +1 -1
  163. data/lib/jss/api_object/mac_application.rb +1 -1
  164. data/lib/jss/api_object/management_history.rb +23 -22
  165. data/lib/jss/api_object/management_history/audit_event.rb +1 -1
  166. data/lib/jss/api_object/management_history/casper_imaging_log.rb +1 -1
  167. data/lib/jss/api_object/management_history/casper_remote_log.rb +1 -1
  168. data/lib/jss/api_object/management_history/computer_usage_log.rb +1 -1
  169. data/lib/jss/api_object/management_history/ebook.rb +1 -1
  170. data/lib/jss/api_object/management_history/hashlike.rb +1 -1
  171. data/lib/jss/api_object/management_history/mac_app_store_app.rb +1 -1
  172. data/lib/jss/api_object/management_history/mdm_command.rb +1 -1
  173. data/lib/jss/api_object/management_history/mobile_device_app.rb +1 -1
  174. data/lib/jss/api_object/management_history/policy_log.rb +1 -1
  175. data/lib/jss/api_object/management_history/screen_sharing_log.rb +1 -1
  176. data/lib/jss/api_object/management_history/user_location_change.rb +1 -1
  177. data/lib/jss/api_object/matchable.rb +1 -1
  178. data/lib/jss/api_object/mdm.rb +1 -1
  179. data/lib/jss/api_object/mobile_device.rb +29 -6
  180. data/lib/jss/api_object/mobile_device_application.rb +13 -1
  181. data/lib/jss/api_object/netboot_server.rb +1 -1
  182. data/lib/jss/api_object/network_segment.rb +153 -59
  183. data/lib/jss/api_object/package.rb +106 -41
  184. data/lib/jss/api_object/patch_policy.rb +1 -1
  185. data/lib/jss/api_object/patch_source.rb +1 -1
  186. data/lib/jss/api_object/patch_source/patch_external_source.rb +1 -1
  187. data/lib/jss/api_object/patch_source/patch_internal_source.rb +1 -1
  188. data/lib/jss/api_object/patch_title.rb +1 -1
  189. data/lib/jss/api_object/patch_title/version.rb +1 -1
  190. data/lib/jss/api_object/peripheral.rb +1 -1
  191. data/lib/jss/api_object/peripheral_type.rb +1 -1
  192. data/lib/jss/api_object/policy.rb +380 -5
  193. data/lib/jss/api_object/printer.rb +440 -0
  194. data/lib/jss/api_object/purchasable.rb +1 -1
  195. data/lib/jss/api_object/removable_macaddr.rb +1 -1
  196. data/lib/jss/api_object/restricted_software.rb +1 -1
  197. data/lib/jss/api_object/scopable.rb +1 -1
  198. data/lib/jss/api_object/scopable/scope.rb +257 -37
  199. data/lib/jss/api_object/script.rb +1 -1
  200. data/lib/jss/api_object/self_servable.rb +7 -7
  201. data/lib/jss/api_object/self_servable/icon.rb +1 -1
  202. data/lib/jss/api_object/sitable.rb +6 -2
  203. data/lib/jss/api_object/site.rb +1 -1
  204. data/lib/jss/api_object/software_update_server.rb +1 -1
  205. data/lib/jss/api_object/updatable.rb +1 -1
  206. data/lib/jss/api_object/uploadable.rb +1 -1
  207. data/lib/jss/api_object/user.rb +5 -3
  208. data/lib/jss/api_object/vppable.rb +1 -1
  209. data/lib/jss/api_object/webhook.rb +1 -1
  210. data/lib/jss/client.rb +1 -1
  211. data/lib/jss/client/jamf_binary.rb +1 -1
  212. data/lib/jss/client/jamf_helper.rb +1 -1
  213. data/lib/jss/client/management_action.rb +1 -1
  214. data/lib/jss/compatibility.rb +1 -1
  215. data/lib/jss/composer.rb +2 -2
  216. data/lib/jss/configuration.rb +1 -1
  217. data/lib/jss/db_connection.rb +1 -1
  218. data/lib/jss/exceptions.rb +1 -1
  219. data/lib/jss/ruby_extensions.rb +1 -1
  220. data/lib/jss/ruby_extensions/array.rb +1 -1
  221. data/lib/jss/ruby_extensions/filetest.rb +1 -1
  222. data/lib/jss/ruby_extensions/hash.rb +1 -1
  223. data/lib/jss/ruby_extensions/ipaddr.rb +1 -1
  224. data/lib/jss/ruby_extensions/pathname.rb +1 -1
  225. data/lib/jss/ruby_extensions/string.rb +1 -1
  226. data/lib/jss/ruby_extensions/string/backports.rb +1 -1
  227. data/lib/jss/ruby_extensions/string/conversions.rb +1 -1
  228. data/lib/jss/ruby_extensions/string/predicates.rb +14 -4
  229. data/lib/jss/ruby_extensions/time.rb +1 -1
  230. data/lib/jss/server.rb +1 -1
  231. data/lib/jss/utility.rb +9 -23
  232. data/lib/jss/validate.rb +1 -1
  233. data/lib/jss/version.rb +2 -2
  234. data/lib/jss/xml_workaround.rb +1 -1
  235. data/lib/ruby-jss.rb +1 -1
  236. data/test/bin/runtests +1 -1
  237. data/test/lib/testhelper.rb +1 -1
  238. data/test/lib/testhelper/auth.rb +1 -1
  239. data/test/lib/testhelper/patch_mgmt.rb +1 -1
  240. data/test/specs/api_connection_spec.rb +1 -1
  241. data/test/specs/patch01_source_spec.rb +1 -1
  242. data/test/specs/patch02_internal_source_spec.rb +1 -1
  243. data/test/specs/patch03_external_source_spec.rb +1 -1
  244. data/test/specs/patch04_titles_spec.rb +1 -1
  245. data/test/specs/patch05_policies_spec.rb +1 -1
  246. data/test/specs/patch06_cleanup_spec.rb +1 -1
  247. data/test/specs/policy_spec.rb +1 -1
  248. metadata +15 -4
@@ -1,4 +1,4 @@
1
- ### Copyright 2019 Pixar
1
+ ### Copyright 2020 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -1,4 +1,4 @@
1
- ### Copyright 2019 Pixar
1
+ ### Copyright 2020 Pixar
2
2
 
3
3
  ###
4
4
  ### Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -67,21 +67,70 @@ module JSS
67
67
  ### Class Methods
68
68
  #####################################
69
69
 
70
- ### All NetworkSegments in the jss as IPAddr object Ranges representing the
71
- ### Segment, e.g. with starting = 10.24.9.1 and ending = 10.24.15.254
72
- ### the range looks like:
73
- ### <IPAddr: IPv4:10.24.9.1/255.255.255.255>..#<IPAddr: IPv4:10.24.15.254/255.255.255.255>
74
- ###
75
- ### Using the #include? method on those Ranges is very useful.
76
- ###
77
- ### @param refresh[Boolean] re-read the data from the API?
78
- ###
79
- ### @param api[JSS::APIConnection] The API connection to query
80
- ###
81
- ### @return [Hash{Integer => Range}] the network segments as IPv4 address Ranges
82
- ###
70
+ # All NetworkSegments in the given API as ruby Ranges of IPAddr instances
71
+ # representing the Segment,
72
+ # e.g. with starting = 10.24.9.1 and ending = 10.24.15.254
73
+ # the range looks like:
74
+ # <IPAddr: IPv4:10.24.9.1/255.255.255.255>
75
+ # ..
76
+ # <IPAddr: IPv4:10.24.15.254/255.255.255.255>
77
+ #
78
+ # Using the #include? method on those Ranges is very useful.
79
+ #
80
+ # Note1: We don't use the IPAddr#to_range method because that works
81
+ # best for masked IPAddrs (which are ranges of IPs with widths
82
+ # determined by the mask) and Jamf Network Segments can have arbitrary
83
+ # widths.
84
+ #
85
+ # Note2: See the network_ranges_as_integers method below, which is similar
86
+ # but much faster.
87
+ #
88
+ # @param refresh[Boolean] should the data be re-queried?
89
+ #
90
+ # @param api[JSS::APIConnection] the API to query
91
+ #
92
+ # @return [Hash{Integer => Range}] the network segments as IPv4 address Ranges
93
+ # keyed by id
94
+ #
83
95
  def self.network_ranges(refresh = false, api: JSS.api)
84
- api.network_ranges refresh
96
+ @network_ranges = nil if refresh
97
+ return @network_ranges if @network_ranges
98
+
99
+ @network_ranges = {}
100
+ all(refresh, api: api).each do |ns|
101
+ @network_ranges[ns[:id]] = IPAddr.new(ns[:starting_address])..IPAddr.new(ns[:ending_address])
102
+ end
103
+ @network_ranges
104
+ end # def network_segments
105
+
106
+ # An IPv4 Address is really just a 32-bit integer, displayed as four
107
+ # 8-bit integers. e.g. '10.0.69.1' is really the integer 167789825
108
+ # The #to_i method of IPAddr objects returns that integer (or the first of
109
+ # them if the IPAddr is masked).
110
+ #
111
+ # Using ranges made of those integers is far faster than using ranges
112
+ # if IPAddr objects, so that's what this method returns.
113
+ #
114
+ # See also: the network_ranges method above
115
+ #
116
+ # @param refresh[Boolean] should the data be re-queried?
117
+ #
118
+ # @param api[JSS::APIConnection] the APIConnection to query
119
+ #
120
+ # @return [Hash{Integer => Range}] the network segments as Integer Ranges
121
+ # keyed by id
122
+ #
123
+ def self.network_ranges_as_integers(refresh = false, api: JSS.api)
124
+ @network_ranges_as_integers = nil if refresh
125
+ return @network_ranges_as_integers if @network_ranges_as_integers
126
+
127
+ @network_ranges_as_integers = {}
128
+ all(refresh, api: api).each do |ns|
129
+ first = IPAddr.new(ns[:starting_address]).to_i
130
+ last = IPAddr.new(ns[:ending_address]).to_i
131
+ @network_ranges_as_integers[ns[:id]] = first..last
132
+ end
133
+ @network_ranges_as_integers
85
134
  end # def network_segments
86
135
 
87
136
  ### An alias for {NetworkSegment.network_ranges}
@@ -195,23 +244,72 @@ module JSS
195
244
  ###
196
245
  ### @return [Array<Integer>] the ids of the NetworkSegments containing the given ip
197
246
  ###
198
- def self.network_segments_for_ip(ip, refresh = false, api: JSS.api)
199
- ok_ip = IPAddr.new(ip)
200
- matches = []
201
- network_ranges(refresh, api: api).each { |id, subnet| matches << id if subnet.include?(ok_ip) }
202
- matches
247
+ def self.network_segments_for_ip(ipaddr, refresh = false, api: JSS.api)
248
+ # get the ip as a 32bit interger
249
+ ip = IPAddr.new(ipaddr.to_s).to_i
250
+ # a hash of NetSeg ids => Range<Integer>
251
+ network_ranges_as_integers(refresh, api: api).select { |_id, range| range.include? ip }.keys
252
+ end
253
+
254
+ # Which network segment is seen as current for a given IP addr?
255
+ #
256
+ # According to the Jamf Pro Admin Guide, if an IP is in more than one network
257
+ # segment, it uses the 'smallest' (narrowest) one - the one with fewest
258
+ # IP addrs within it.
259
+ #
260
+ # If multiple ones have the same width, then it uses the one of
261
+ # those with the lowest starting address
262
+ #
263
+ # @return [Integer, nil] the id of the current net segment, or nil
264
+ #
265
+ def self.network_segment_for_ip(ipaddr, refresh: false, api: JSS.api)
266
+ # get the ip as a 32bit interger
267
+ ip = IPAddr.new(ipaddr.to_s).to_i
268
+ # a hash of NetSeg ids => Range<Integer>
269
+ ranges = network_ranges_as_integers(refresh, api: api).select { |_id, range| range.include? ip }
270
+
271
+ # we got nuttin
272
+ return nil if ranges.empty?
273
+
274
+ # if we got only one, its the one
275
+ return ranges.keys.first if ranges.size == 1
276
+
277
+ # got more than one, sort by range size/width, asc.
278
+ sorted_by_size = ranges.sort_by { |_i, r| r.size }.to_h
279
+
280
+ # the first one is the smallest/narrowest.
281
+ _smallest_range_id, smallest_range = sorted_by_size.first
282
+
283
+ smallest_range_size = smallest_range.size
284
+
285
+ # select all of them that are the same size
286
+ all_of_small_size = sorted_by_size.select { |_i, r| r.size == smallest_range_size }
287
+
288
+ # sort them by the start of each range (r.first)
289
+ # and return the lowest start (returned by min_by)
290
+ my_range_id, _my_range = all_of_small_size.min_by { |_i, r| r.first }
291
+
292
+ # and return the id
293
+ my_range_id
203
294
  end
204
295
 
205
- # @deprecated use network_segments_for_ip
206
- # Here for Backward compatibility
207
- def self.network_segment_for_ip(ip, api: JSS.api)
208
- network_segments_for_ip(ip, api: api)
296
+ # given 2 IPAddr instances, find out how 'wide' they are -
297
+ # how many IP addresses exist between them.
298
+ def self.ip_range_width(ip1, ip2)
299
+ raise ArgumentError, 'Parameters must be IPAddr objects' unless ip1.is_a?(IPAddr) && ip2.is_a?(IPAddr)
300
+
301
+ low, high = [ip1, ip2].sort
302
+ high.to_i - low.to_i
209
303
  end
210
304
 
211
- ### Find the current network segment ids for the machine running this code
212
- ###
213
- ### @return [Array<Integer>] the NetworkSegment ids for this machine right now.
214
- ###
305
+ # Find the current network segment ids for the machine running this code
306
+ #
307
+ # See my_network_segment to get the current one according to the server.
308
+ #
309
+ # @param names [Boolean] the array will contain Network Segment names, not ids
310
+ #
311
+ # @return [Array<Integer>,Array<String>] the NetworkSegment ids or names for this machine right now.
312
+ #
215
313
  def self.my_network_segments(refresh = false, names: false, api: JSS.api)
216
314
  ids = network_segments_for_ip JSS::Client.my_ip_address, refresh, api: api
217
315
  return ids unless names
@@ -220,35 +318,23 @@ module JSS
220
318
  ids.map { |id| ids_to_names[id] }
221
319
  end
222
320
 
223
- # @deprecated use my_network_segments
224
- # Here for backward compatibility
225
- def self.my_network_segment(api: JSS.api)
226
- my_network_segments api: api
227
- end
228
-
229
- # All NetworkSegments in the given API as IPAddr object Ranges representing the
230
- # Segment, e.g. with starting = 10.24.9.1 and ending = 10.24.15.254
231
- # the range looks like:
232
- # <IPAddr: IPv4:10.24.9.1/255.255.255.255>..#<IPAddr: IPv4:10.24.15.254/255.255.255.255>
321
+ # Which network segment is seen as current? According to the
322
+ # Jamf Pro Admin Guide, the 'smallest' one - the one with fewest IP
323
+ # addrs within it. If multiple ones have the same number of IPs,
324
+ # then its the one with the lowest starting address
233
325
  #
234
- # Using the #include? method on those Ranges is very useful.
326
+ # @param name [Boolean] return the name of the netsegment, not the id
235
327
  #
236
- # @param refresh[Boolean] should the data be re-queried?
237
- #
238
- # @param api[JSS::APIConnection] the API to query
239
- #
240
- # @return [Hash{Integer => Range}] the network segments as IPv4 address Ranges
241
- # keyed by id
242
- #
243
- def self.network_ranges(refresh = false, api: JSS.api)
244
- @network_ranges = nil if refresh
245
- return @network_ranges if @network_ranges
246
- @network_ranges = {}
247
- all(refresh, api: api).each do |ns|
248
- @network_ranges[ns[:id]] = IPAddr.new(ns[:starting_address])..IPAddr.new(ns[:ending_address])
249
- end
250
- @network_ranges
251
- end # def network_segments
328
+ # @return [Integer, String, nil] the id of the current net segment, or nil
329
+ def self.my_network_segment(refresh = false, name: false, api: JSS.api)
330
+ my_ip = JSS::Client.my_ip_address
331
+ return nil unless my_ip
332
+
333
+ id = network_segment_for_ip(my_ip, refresh: refresh, api: api)
334
+ return id unless name
335
+
336
+ map_all_ids_to(:name)[id]
337
+ end
252
338
 
253
339
  ### Attributes
254
340
  #####################################
@@ -419,14 +505,22 @@ module JSS
419
505
 
420
506
  ### set the distribution_point
421
507
  ###
422
- ### @param newval[String, Integer] the new dist. point by name or id, must be in the JSS
508
+ ### @param newval[String, Integer, nil] the new dist. point by name or id, must be in the JSS, or nil or blank to unset
423
509
  ###
424
510
  ### @return [void]
425
511
  ###
426
512
  def distribution_point=(newval)
427
- new = JSS::DistributionPoint.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
428
- raise JSS::MissingDataError, "No distribution_point matching '#{newval}' in the JSS" unless new
429
- @distribution_point = new[:name]
513
+ new =
514
+ if newval.to_s.empty?
515
+ JSS::BLANK
516
+ else
517
+ id = JSS::DistributionPoint.valid_id newval
518
+ raise JSS::MissingDataError, "No distribution_point matching '#{newval}' in the JSS" unless id
519
+
520
+ JSS::DistributionPoint.map_all_ids_to(:name)[id]
521
+ end
522
+
523
+ @distribution_point = new
430
524
  @need_to_update = true
431
525
  end
432
526
 
@@ -1,4 +1,4 @@
1
- # Copyright 2019 Pixar
1
+ # Copyright 2020 Pixar
2
2
 
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "Apache License")
@@ -121,9 +121,31 @@ module JSS
121
121
  # @return [Array<String>] The current file names
122
122
  #
123
123
  def self.all_filenames(api: JSS.api)
124
- pkgs_in_use = []
125
- all_ids.each { |pkg_id| pkgs_in_use << fetch(id: pkg_id, api: api).filename }
126
- pkgs_in_use.compact
124
+ all_filenames_by(:id, api: api).values
125
+ end
126
+
127
+ # A Hash of all dist-point filenames used by all JSS packages, keyed by
128
+ # package name or id
129
+ #
130
+ # Slow cuz we have to instantiate every pkg
131
+ #
132
+ # @param key[Symbol] either :id, or :name
133
+ #
134
+ # @param api[JSS::APIConnection] an API connection to use
135
+ # Defaults to the corrently active API. See {JSS::APIConnection}
136
+ #
137
+ # @return [Hash{Ingeter,String => String}] The current file names by key
138
+ #
139
+ def self.all_filenames_by(key, api: JSS.api)
140
+ raise ArgumentError, 'key must be :id or :name' unless %i[id name].include? key
141
+
142
+ files_in_use = {}
143
+ all_ids(:refresh).each do |pkg_id|
144
+ pkg = fetch id: pkg_id, api: api
145
+ files_in_use[pkg.send(key)] = pkg.filename
146
+ end
147
+
148
+ files_in_use
127
149
  end
128
150
 
129
151
  # An array of String filenames for all files DIST_POINT_PKGS_FOLDER
@@ -140,14 +162,17 @@ module JSS
140
162
  # @param api[JSS::APIConnection] an API connection to use
141
163
  # Defaults to the corrently active API. See {JSS::APIConnection}
142
164
  #
165
+ # @param dist_point [String,Integer] the name or id of the distribution
166
+ # point to use. Defaults to the Master Dist. Point
167
+ #
143
168
  # @return [Array<String>] The orphaned files
144
169
  #
145
- def self.orphaned_files(ro_pw, unmount = true, api: JSS.api)
146
- mdp = JSS::DistributionPoint.master_distribution_point api: api
147
- pkgs_dir = mdp.mount(ro_pw, :ro) + DIST_POINT_PKGS_FOLDER
148
- files_on_mdp = pkgs_dir.children.map { |f| f.basename.to_s }
149
- mdp.unmount if unmount
150
- files_on_mdp - all_filenames(api: api)
170
+ def self.orphaned_files(ro_pw, unmount = true, api: JSS.api, dist_point: nil)
171
+ dp = fetch_dist_point(dist_point, api: api)
172
+ pkgs_dir = dp.mount(ro_pw, :ro) + DIST_POINT_PKGS_FOLDER
173
+ files_on_dp = pkgs_dir.children.map { |f| f.basename.to_s }
174
+ dp.unmount if unmount
175
+ files_on_dp - all_filenames(api: api)
151
176
  end
152
177
 
153
178
  # An array of String filenames for all filenames in any
@@ -164,14 +189,18 @@ module JSS
164
189
  # @param api[JSS::APIConnection] an API connection to use
165
190
  # Defaults to the corrently active API. See {JSS::APIConnection}
166
191
  #
192
+ # @param dist_point [String,Integer] the name or id of the distribution
193
+ # point to use. Defaults to the Master Dist. Point
194
+ #
195
+ #
167
196
  # @return [Array<String>] The orphaned files
168
197
  #
169
- def self.missing_files(ro_pw, unmount = true, api: JSS.api)
170
- mdp = JSS::DistributionPoint.master_distribution_point api: api
171
- pkgs_dir = mdp.mount(ro_pw, :ro) + DIST_POINT_PKGS_FOLDER
172
- files_on_mdp = pkgs_dir.children.map { |f| f.basename.to_s }
173
- mdp.unmount if unmount
174
- all_filenames(api: api) - files_on_mdp
198
+ def self.missing_files(ro_pw, unmount = true, api: JSS.api, dist_point: nil)
199
+ dp = fetch_dist_point(dist_point, api: api)
200
+ pkgs_dir = dp.mount(ro_pw, :ro) + DIST_POINT_PKGS_FOLDER
201
+ files_on_dp = pkgs_dir.children.map { |f| f.basename.to_s }
202
+ dp.unmount if unmount
203
+ all_filenames(api: api) - files_on_dp
175
204
  end
176
205
 
177
206
  # Given a file path, and hash type, generate the checksum for an arbitrary
@@ -189,6 +218,18 @@ module JSS
189
218
  CHECKSUM_HASH_TYPES[type].file(filepath).hexdigest
190
219
  end
191
220
 
221
+ # @param dist_point [String,Integer] the name or id of the distribution
222
+ # point to use. Defaults to the Master Dist. Point
223
+ #
224
+ # @return [JSS::DistributionPoint]
225
+ def self.fetch_dist_point(dist_point, api: JSS.api)
226
+ if dist_point
227
+ JSS::DistributionPoint.fetch dist_point, api: api
228
+ else
229
+ JSS::DistributionPoint.master_distribution_point api: api
230
+ end
231
+ end
232
+
192
233
  # Attributes
193
234
  #####################################
194
235
 
@@ -324,7 +365,7 @@ module JSS
324
365
  new_val = nil if new_val == ''
325
366
  new_val ||= @name
326
367
  return nil if new_val == @filename
327
- warn 'WARNING: you must change the filename on the master Distribution Point. See JSS::Package.update_master_filename.' if @in_jss
368
+
328
369
  @filename = new_val
329
370
  @need_to_update = true
330
371
  end
@@ -590,13 +631,17 @@ module JSS
590
631
  # @param chksum [String] the constants CHECKSUM_HASH_TYPE_SHA512 or
591
632
  # CHECKSUM_HASH_TYPE_MD5. Anything else means don't calc.
592
633
  #
634
+ # @param dist_point [String,Integer] the name or id of the distribution
635
+ # point to use. Defaults to the Master Dist. Point
636
+ #
593
637
  # @return [void]
594
638
  #
595
- def upload_master_file(local_file_path, rw_pw, unmount = true, chksum: DEFAULT_CHECKSUM_HASH_TYPE )
639
+ def upload_master_file(local_file_path, rw_pw, unmount = true, chksum: DEFAULT_CHECKSUM_HASH_TYPE, dist_point: nil)
596
640
  raise JSS::NoSuchItemError, 'Please create this package in the JSS before uploading it.' unless @in_jss
597
641
 
598
- mdp = JSS::DistributionPoint.master_distribution_point api: @api
599
- destination = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
642
+ dp = self.class.fetch_dist_point(dist_point, api: @api)
643
+
644
+ destination = dp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
600
645
 
601
646
  local_path = Pathname.new local_file_path
602
647
  raise JSS::NoSuchItemError, "Local file '#{@local_file}' doesn't exist" unless local_path.exist?
@@ -637,11 +682,11 @@ module JSS
637
682
 
638
683
  if CHECKSUM_HASH_TYPES.keys.include? chksum
639
684
  @checksum_type = chksum
640
- @checksum = calculate_checksum local_file: local_path, type: chksum, unmount: false
685
+ @checksum = calculate_checksum local_file: local_path, type: chksum, unmount: false, dist_point: dist_point
641
686
  @need_to_update = true
642
687
  end
643
688
  update if @need_to_update
644
- mdp.unmount if unmount
689
+ dp.unmount if unmount
645
690
  end # upload master file
646
691
 
647
692
  # Using either a local file, or the file on the master dist. point,
@@ -658,7 +703,7 @@ module JSS
658
703
  #
659
704
  # @return [void]
660
705
  #
661
- def reset_checksum(type: nil, local_file: nil, rw_pw: nil, ro_pw: nil, unmount: true)
706
+ def reset_checksum(type: nil, local_file: nil, rw_pw: nil, ro_pw: nil, unmount: true, dist_point: nil )
662
707
  type ||= DEFAULT_CHECKSUM_HASH_TYPE
663
708
 
664
709
  new_checksum = calculate_checksum(
@@ -666,7 +711,8 @@ module JSS
666
711
  local_file: local_file,
667
712
  rw_pw: rw_pw,
668
713
  ro_pw: ro_pw,
669
- unmount: unmount
714
+ unmount: unmount,
715
+ dist_point: dist_point
670
716
  )
671
717
  return if @checksum == new_checksum
672
718
 
@@ -694,11 +740,14 @@ module JSS
694
740
  # @param unmount [Boolean] Unmount the master dist point after using it.
695
741
  # Only used if the dist point is mounted. default: true
696
742
  #
743
+ # @param dist_point [String,Integer] the name or id of the distribution
744
+ # point to use. Defaults to the Master Dist. Point
745
+ #
697
746
  # @return [String] The calculated checksum
698
747
  #
699
- def calculate_checksum(type: nil, local_file: nil, rw_pw: nil, ro_pw: nil, unmount: true )
748
+ def calculate_checksum(type: nil, local_file: nil, rw_pw: nil, ro_pw: nil, unmount: true, dist_point: nil )
700
749
  type ||= DEFAULT_CHECKSUM_HASH_TYPE
701
- mdp = JSS::DistributionPoint.master_distribution_point api: @api
750
+ dp = self.class.fetch_dist_point(dist_point, api: @api)
702
751
 
703
752
  if local_file
704
753
  file_to_calc = local_file
@@ -712,10 +761,10 @@ module JSS
712
761
  else
713
762
  raise ArgumentError, 'Either rw_pw: or ro_pw: must be provided'
714
763
  end
715
- file_to_calc = mdp.mount(dppw, mnt) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
764
+ file_to_calc = dp.mount(dppw, mnt) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
716
765
  end
717
766
  new_checksum = self.class.calculate_checksum(file_to_calc, type)
718
- mdp.unmount if unmount && mdp.mounted?
767
+ dp.unmount if unmount && dp.mounted?
719
768
  new_checksum
720
769
  end
721
770
 
@@ -734,17 +783,21 @@ module JSS
734
783
  # @param unmount [Boolean] Unmount the master dist point after using it.
735
784
  # Only used if the dist point is mounted. default: true
736
785
  #
786
+ # @param dist_point [String,Integer] the name or id of the distribution
787
+ # point to use. Defaults to the Master Dist. Point
788
+ #
737
789
  # @return [Boolean] false if there is no checksum for this pkg, otherwise,
738
790
  # does the calculated checksum match the one stored for the pkg?
739
791
  #
740
- def checksum_valid?(local_file: nil, rw_pw: nil, ro_pw: nil, unmount: true)
792
+ def checksum_valid?(local_file: nil, rw_pw: nil, ro_pw: nil, unmount: true, dist_point: nil )
741
793
  return false unless @checksum
742
794
  new_checksum = calculate_checksum(
743
795
  type: @checksum_type,
744
796
  local_file: local_file,
745
797
  rw_pw: rw_pw,
746
798
  ro_pw: ro_pw,
747
- unmount: unmount
799
+ unmount: unmount,
800
+ dist_point: dist_point
748
801
  )
749
802
  new_checksum == @checksum
750
803
  end
@@ -760,12 +813,16 @@ module JSS
760
813
  # @param rw_pw[String,Symbol] the password for the read/write account on the master Distribution Point,
761
814
  # or :prompt, or :stdin# where # is the line of stdin containing the password See {JSS::DistributionPoint#mount}
762
815
  #
816
+ # @param dist_point [String,Integer] the name or id of the distribution
817
+ # point to use. Defaults to the Master Dist. Point
818
+ #
763
819
  # @return [nil]
764
820
  #
765
- def update_master_filename(old_file_name, new_file_name, rw_pw, unmount = true)
821
+ def update_master_filename(old_file_name, new_file_name, rw_pw, unmount = true, dist_point: nil)
766
822
  raise JSS::NoSuchItemError, "#{old_file_name} does not exist in the jss." unless @in_jss
767
- mdp = JSS::DistributionPoint.master_distribution_point api: @api
768
- pkgs_dir = mdp.mount(rw_pw, :rw) + DIST_POINT_PKGS_FOLDER.to_s
823
+ dp = self.class.fetch_dist_point(dist_point, api: @api)
824
+
825
+ pkgs_dir = dp.mount(rw_pw, :rw) + DIST_POINT_PKGS_FOLDER.to_s
769
826
  old_file = pkgs_dir + old_file_name
770
827
  raise JSS::NoSuchItemError, "File not found on the master distribution point at #{DIST_POINT_PKGS_FOLDER}/#{old_file_name}." unless \
771
828
  old_file.exist?
@@ -775,7 +832,7 @@ module JSS
775
832
  new_file = pkgs_dir + (new_file_name + old_file.extname) if new_file.extname.empty?
776
833
 
777
834
  old_file.rename new_file
778
- mdp.unmount if unmount
835
+ dp.unmount if unmount
779
836
  nil
780
837
  end # update_master_filename
781
838
 
@@ -791,18 +848,21 @@ module JSS
791
848
  #
792
849
  # @param unmount[Boolean] whether or not ot unount the distribution point when finished.
793
850
  #
851
+ # @param dist_point [String,Integer] the name or id of the distribution
852
+ # point to use. Defaults to the Master Dist. Point
853
+ #
794
854
  # @return [Boolean] was the file deleted?
795
855
  #
796
- def delete_master_file(rw_pw, unmount = true)
797
- mdp = JSS::DistributionPoint.master_distribution_point api: @api
798
- file = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
856
+ def delete_master_file(rw_pw, unmount = true, dist_point: nil)
857
+ dp = self.class.fetch_dist_point(dist_point, api: @api)
858
+ file = dp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
799
859
  if file.exist?
800
860
  file.delete
801
861
  did_it = true
802
862
  else
803
863
  did_it = false
804
864
  end # if exists
805
- mdp.unmount if unmount
865
+ dp.unmount if unmount
806
866
  did_it
807
867
  end # delete master file
808
868
 
@@ -816,9 +876,13 @@ module JSS
816
876
  #
817
877
  # @param unmount[Boolean] whether or not ot unount the distribution point when finished.
818
878
  #
819
- def delete(delete_file: false, rw_pw: nil, unmount: true)
879
+ # @param dist_point [String,Integer] the name or id of the distribution
880
+ # point to use. Defaults to the Master Dist. Point
881
+ #
882
+ # @return [void]
883
+ def delete(delete_file: false, rw_pw: nil, unmount: true, dist_point: nil)
820
884
  super()
821
- delete_master_file(rw_pw, unmount) if delete_file
885
+ delete_master_file(rw_pw, unmount, dist_point: dist_point) if delete_file
822
886
  end
823
887
 
824
888
  # Install this package via the jamf binary 'install' command from the
@@ -885,7 +949,7 @@ module JSS
885
949
 
886
950
  # we'll re-add the filename below if needed.
887
951
  src_path = args[:alt_download_url].chomp "/#{@filename}"
888
-
952
+ using_http = true
889
953
  # use our appropriate dist. point for download
890
954
  else
891
955
  mdp = JSS::DistributionPoint.my_distribution_point api: @api
@@ -1021,6 +1085,7 @@ module JSS
1021
1085
 
1022
1086
  private
1023
1087
 
1088
+
1024
1089
  # Return the REST XML for this pkg, with the current values,
1025
1090
  # for saving or updating
1026
1091
  #