ruby-jss 1.3.2 → 1.5.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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +122 -0
  3. data/lib/jamf.rb +18 -16
  4. data/lib/jamf/api/base_classes/collection_resource.rb +613 -0
  5. data/lib/jamf/api/{abstract_classes → base_classes}/json_object.rb +109 -101
  6. data/lib/jamf/api/{abstract_classes → base_classes}/prestage.rb +55 -30
  7. data/lib/jamf/api/{abstract_classes → base_classes}/resource.rb +10 -6
  8. data/lib/jamf/api/{abstract_classes → base_classes}/singleton_resource.rb +4 -3
  9. data/lib/jamf/api/connection.rb +13 -9
  10. data/lib/jamf/api/connection/api_error.rb +8 -8
  11. data/lib/jamf/api/connection/token.rb +36 -15
  12. data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
  13. data/lib/jamf/api/json_objects/{location.rb → device_enrollment_device_sync_state.rb} +27 -41
  14. data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
  15. data/lib/jamf/api/json_objects/{attachment.rb → locale.rb} +14 -23
  16. data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
  17. data/lib/jamf/api/json_objects/md_prestage_names.rb +2 -2
  18. data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
  19. data/lib/jamf/api/json_objects/prestage_assignment.rb +2 -2
  20. data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
  21. data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
  22. data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
  23. data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
  24. data/lib/jamf/api/mixins/{abstract.rb → base_class.rb} +34 -16
  25. data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
  26. data/lib/jamf/api/mixins/change_log.rb +201 -51
  27. data/lib/jamf/api/{resources/collection_resources/computer.rb → mixins/filterable.rb} +19 -17
  28. data/lib/jamf/api/mixins/pageable.rb +208 -0
  29. data/lib/jamf/api/{json_objects/installed_application.rb → mixins/sortable.rb} +33 -33
  30. data/lib/jamf/api/resources/collection_resources/building.rb +16 -9
  31. data/lib/jamf/api/resources/collection_resources/category.rb +5 -4
  32. data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +12 -5
  33. data/lib/jamf/api/resources/collection_resources/department.rb +1 -3
  34. data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +13 -13
  35. data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
  36. data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +25 -23
  37. data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
  38. data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
  39. data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
  40. data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
  41. data/lib/jamf/validate.rb +63 -24
  42. data/lib/jamf/version.rb +1 -1
  43. data/lib/jss.rb +2 -1
  44. data/lib/jss/api_connection.rb +113 -406
  45. data/lib/jss/api_object.rb +10 -20
  46. data/lib/jss/api_object/advanced_search.rb +27 -26
  47. data/lib/jss/api_object/app_store_country_codes.rb +298 -0
  48. data/lib/jss/api_object/categorizable.rb +1 -1
  49. data/lib/jss/api_object/computer.rb +13 -0
  50. data/lib/jss/api_object/configuration_profile.rb +60 -4
  51. data/lib/jss/api_object/directory_binding_type.rb +66 -60
  52. data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
  53. data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
  54. data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
  55. data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
  56. data/lib/jss/api_object/distribution_point.rb +2 -2
  57. data/lib/jss/api_object/dock_item.rb +102 -96
  58. data/lib/jss/api_object/ebook.rb +1 -2
  59. data/lib/jss/api_object/extendable.rb +1 -1
  60. data/lib/jss/api_object/extension_attribute.rb +4 -3
  61. data/lib/jss/api_object/group.rb +33 -2
  62. data/lib/jss/api_object/mac_application.rb +107 -8
  63. data/lib/jss/api_object/network_segment.rb +43 -12
  64. data/lib/jss/api_object/package.rb +1 -1
  65. data/lib/jss/api_object/patch_source.rb +10 -9
  66. data/lib/jss/api_object/policy.rb +217 -28
  67. data/lib/jss/api_object/printer.rb +10 -4
  68. data/lib/jss/api_object/scopable.rb +10 -15
  69. data/lib/jss/api_object/scopable/scope.rb +389 -73
  70. data/lib/jss/api_object/self_servable.rb +17 -9
  71. data/lib/jss/api_object/uploadable.rb +1 -1
  72. data/lib/jss/api_object/user.rb +42 -1
  73. data/lib/jss/api_object/vpp_account.rb +209 -0
  74. data/lib/jss/api_object/vppable.rb +169 -13
  75. data/lib/jss/exceptions.rb +3 -0
  76. data/lib/jss/server.rb +15 -0
  77. data/lib/jss/utility.rb +142 -37
  78. data/lib/jss/validate.rb +53 -10
  79. data/lib/jss/version.rb +1 -1
  80. metadata +45 -61
  81. data/lib/jamf/api/abstract_classes/advanced_search.rb +0 -86
  82. data/lib/jamf/api/abstract_classes/collection_resource.rb +0 -433
  83. data/lib/jamf/api/abstract_classes/generic_reference.rb +0 -145
  84. data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +0 -126
  85. data/lib/jamf/api/json_objects/account_prefs.rb +0 -79
  86. data/lib/jamf/api/json_objects/android_details.rb +0 -139
  87. data/lib/jamf/api/json_objects/appletv_details.rb +0 -110
  88. data/lib/jamf/api/json_objects/cellular_network.rb +0 -151
  89. data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +0 -67
  90. data/lib/jamf/api/json_objects/criterion.rb +0 -152
  91. data/lib/jamf/api/json_objects/extension_attribute_value.rb +0 -128
  92. data/lib/jamf/api/json_objects/installed_certificate.rb +0 -53
  93. data/lib/jamf/api/json_objects/installed_configuration_profile.rb +0 -67
  94. data/lib/jamf/api/json_objects/installed_ebook.rb +0 -58
  95. data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +0 -59
  96. data/lib/jamf/api/json_objects/ios_details.rb +0 -244
  97. data/lib/jamf/api/json_objects/mobile_device_details.rb +0 -219
  98. data/lib/jamf/api/json_objects/mobile_device_security.rb +0 -101
  99. data/lib/jamf/api/json_objects/purchasing_data.rb +0 -125
  100. data/lib/jamf/api/mixins/locatable.rb +0 -124
  101. data/lib/jamf/api/mixins/referable.rb +0 -92
  102. data/lib/jamf/api/resources/collection_resources/account.rb +0 -163
  103. data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +0 -52
  104. data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +0 -52
  105. data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +0 -45
  106. data/lib/jamf/api/resources/collection_resources/mobile_device.rb +0 -315
  107. data/lib/jamf/api/resources/collection_resources/site.rb +0 -77
  108. data/lib/jamf/api/resources/singleton_resources/authorization.rb +0 -88
  109. data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +0 -139
  110. data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +0 -95
@@ -459,9 +459,17 @@ module JSS
459
459
  ### @return [void]
460
460
  ###
461
461
  def building=(newval)
462
- new = JSS::Building.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
463
- raise JSS::MissingDataError, "No building matching '#{newval}'" unless new
464
- @building = new[:name]
462
+ new =
463
+ if newval.to_s.empty?
464
+ JSS::BLANK
465
+ else
466
+ id = JSS::Building.valid_id newval
467
+ raise JSS::MissingDataError, "No building matching '#{newval}'" unless id
468
+
469
+ JSS::Building.map_all_ids_to(:name)[id]
470
+ end
471
+
472
+ @building = new
465
473
  @need_to_update = true
466
474
  end
467
475
 
@@ -484,9 +492,16 @@ module JSS
484
492
  ### @return [void]
485
493
  ###
486
494
  def department=(newval)
487
- new = JSS::Department.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
488
- raise JSS::MissingDataError, "No department matching '#{newval}' in the JSS" unless new
489
- @department = new[:name]
495
+ new =
496
+ if newval.to_s.empty?
497
+ JSS::BLANK
498
+ else
499
+ id = JSS::Department.valid_id newval
500
+ raise JSS::MissingDataError , "No department matching '#{newval}' in the JSS" unless id
501
+
502
+ JSS::Department.map_all_ids_to(:name)[id]
503
+ end
504
+ @department = new
490
505
  @need_to_update = true
491
506
  end
492
507
 
@@ -531,9 +546,17 @@ module JSS
531
546
  ### @return [void]
532
547
  ###
533
548
  def netboot_server=(newval)
534
- new = JSS::NetbootServer.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
535
- raise JSS::MissingDataError, "No netboot_server matching '#{newval}' in the JSS" unless new
536
- @netboot_server = new[:name]
549
+ new =
550
+ if newval.to_s.empty?
551
+ JSS::BLANK
552
+ else
553
+ id = JSS::NetBootServer.valid_id newval
554
+ raise JSS::MissingDataError, "No netboot_server matching '#{newval}' in the JSS" unless id
555
+
556
+ JSS::NetbootServer.map_all_ids_to(:name)[id]
557
+ end
558
+
559
+ @netboot_server = new
537
560
  @need_to_update = true
538
561
  end
539
562
 
@@ -544,9 +567,17 @@ module JSS
544
567
  ### @return [void]
545
568
  ###
546
569
  def swu_server=(newval)
547
- new = JSS::SoftwareUpdateServer.all.select { |b| (b[:id] == newval) || (b[:name] == newval) }[0]
548
- raise JSS::MissingDataError, "No swu_server matching '#{newval}' in the JSS" unless new
549
- @swu_server = new[:name]
570
+ new =
571
+ if newval.to_s.empty?
572
+ JSS::BLANK
573
+ else
574
+ id = JSS::SoftwareUpdateServer.valid_id newval
575
+ raise JSS::MissingDataError, "No swu_server matching '#{newval}' in the JSS" unless id
576
+
577
+ JSS::SoftwareUpdateServer.map_all_ids_to(:name)[id]
578
+ end
579
+
580
+ @swu_server = new
550
581
  @need_to_update = true
551
582
  end
552
583
 
@@ -65,7 +65,7 @@ module JSS
65
65
  DIST_POINT_PKGS_FOLDER = 'Packages'.freeze
66
66
 
67
67
  # The possible values for cpu_type (required_processor) in a JSS package
68
- CPU_TYPES = %w[None Intel/x86 ppc].freeze
68
+ CPU_TYPES = %w[None x86 ppc].freeze
69
69
 
70
70
  # the possible priorities
71
71
  PRIORITIES = (1..20)
@@ -120,30 +120,31 @@ module JSS
120
120
 
121
121
  # Fetch either an internal or external patch source
122
122
  #
123
- # BUG: there's an API bug: fetching a non-existent ids
123
+ # BUG: there's an API bug: fetching a non-existent
124
124
  # which is why we rescue internal server errors.
125
125
  #
126
126
  # @see APIObject.fetch
127
127
  #
128
- def self.fetch(arg, api: JSS.api)
128
+ def self.fetch(searchterm = nil, **args)
129
129
  if self == JSS::PatchSource
130
130
  begin
131
- fetched = JSS::PatchInternalSource.fetch arg, api: api
132
- rescue RestClient::ResourceNotFound, RestClient::InternalServerError, JSS::NoSuchItemError
131
+ fetched = JSS::PatchInternalSource.fetch searchterm, **args
132
+ rescue
133
133
  fetched = nil
134
134
  end
135
135
  unless fetched
136
136
  begin
137
- fetched = JSS::PatchExternalSource.fetch arg, api: api
138
- rescue RestClient::ResourceNotFound, RestClient::InternalServerError, JSS::NoSuchItemError
137
+ fetched = JSS::PatchExternalSource.fetch searchterm, **args
138
+ rescue
139
139
  raise JSS::NoSuchItemError, 'No matching PatchSource found'
140
140
  end
141
141
  end
142
142
  return fetched
143
143
  end # if self == JSS::PatchSource
144
+
144
145
  begin
145
- super
146
- rescue RestClient::ResourceNotFound, RestClient::InternalServerError, JSS::NoSuchItemError
146
+ super searchterm, **args
147
+ rescue JSS::NoSuchItemError
147
148
  raise JSS::NoSuchItemError, "No matching #{self::RSRC_OBJECT_KEY} found"
148
149
  end
149
150
  end
@@ -211,7 +212,7 @@ module JSS
211
212
  begin
212
213
  # TODO: remove this and adjust parsing when jamf fixes the JSON
213
214
  raw = JSS::XMLWorkaround.data_via_xml(rsrc, AVAILABLE_TITLES_DATA_MAP, api)
214
- rescue RestClient::ResourceNotFound
215
+ rescue JSS::NoSuchItemError
215
216
  return []
216
217
  end
217
218
 
@@ -148,6 +148,12 @@ module JSS
148
148
  monthly: 'Once every month'
149
149
  }.freeze
150
150
 
151
+ RETRY_EVENTS = {
152
+ none: 'none',
153
+ checkin: 'check-in',
154
+ trigger: 'trigger'
155
+ }.freeze
156
+
151
157
  RESTART_WHEN = {
152
158
  if_pkg_requires: 'Restart if a package or update requires it',
153
159
  now: 'Restart immediately',
@@ -257,14 +263,14 @@ module JSS
257
263
  }.freeze
258
264
 
259
265
  LOG_FLUSH_INTERVAL_PERIODS = {
260
- day: 'Day',
261
- days: 'Day',
262
- week: 'Week',
263
- weeks: 'Week',
264
- month: 'Month',
265
- months: 'Month',
266
- year: 'Year',
267
- years: 'Year'
266
+ day: 'Days',
267
+ days: 'Days',
268
+ week: 'Weeks',
269
+ weeks: 'Weeks',
270
+ month: 'Months',
271
+ months: 'Months',
272
+ year: 'Years',
273
+ years: 'Years'
268
274
  }.freeze
269
275
 
270
276
  # the object type for this object in
@@ -281,6 +287,83 @@ module JSS
281
287
  # How is the category stored in the API data?
282
288
  CATEGORY_DATA_TYPE = Hash
283
289
 
290
+ # Class Methods
291
+ ######################
292
+
293
+ # Flush logs for a given policy older than some number of days, weeks,
294
+ # months or years, possibly limited to one or more computers.
295
+ #
296
+ # With no parameters, flushes all logs for the policy for all computers.
297
+ #
298
+ # NOTE: Currently the API doesn't have a way to flush only failed policies.
299
+ #
300
+ # WARNING: Log flushing can take a long time, and the API call doesnt return
301
+ # until its finished. The connection timeout will be temporarily raised to
302
+ # 30 minutes, unless it's already higher.
303
+ #
304
+ # @param policy[Integer,String] The id or name of the policy to flush
305
+ #
306
+ # @param older_than[Integer] 0, 1, 2, 3, or 6
307
+ #
308
+ # @param period[Symbol] :days, :weeks, :months, or :years
309
+ #
310
+ # @param computers[Array<Integer,String>] Identifiers of the target computers
311
+ # either ids, names, SNs, macaddrs, or UDIDs. If omitted, flushes logs for
312
+ # all computers
313
+ #
314
+ # @param api [JSS::APIConnection] the API connection to use.
315
+ #
316
+ # @return [void]
317
+ #
318
+ def self.flush_logs(policy, older_than: 0, period: :days, computers: [], api: JSS.api)
319
+ orig_timeout = api.cnx.options.timeout
320
+ pol_id = valid_id policy
321
+ raise JSS::NoSuchItemError, "No Policy identified by '#{policy}'." unless pol_id
322
+
323
+ older_than = LOG_FLUSH_INTERVAL_INTEGERS[older_than]
324
+ raise JSS::InvalidDataError, "older_than must be one of these integers: #{LOG_FLUSH_INTERVAL_INTEGERS.keys.join ', '}" unless older_than
325
+
326
+ period = LOG_FLUSH_INTERVAL_PERIODS[period]
327
+ raise JSS::InvalidDataError, "period must be one of these symbols: :#{LOG_FLUSH_INTERVAL_PERIODS.keys.join ', :'}" unless period
328
+
329
+ computers = [computers] unless computers.is_a? Array
330
+
331
+ # log flushes can be really slow
332
+ api.timeout = 1800 unless orig_timeout && orig_timeout > 1800
333
+
334
+ return api.delete_rsrc "#{LOG_FLUSH_RSRC}/policy/id/#{pol_id}/interval/#{older_than}+#{period}" if computers.empty?
335
+
336
+ flush_logs_for_specific_computers pol_id, older_than, period, computers, api
337
+ ensure
338
+ api.timeout = orig_timeout
339
+ end
340
+
341
+ # use an XML body in a DELETE request to flush logs for
342
+ # a list of computers - used by the flush_logs class method
343
+ def self.flush_logs_for_specific_computers(pol_id, older_than, period, computers, api)
344
+ # build the xml body for a DELETE request
345
+ xml_doc = REXML::Document.new JSS::APIConnection::XML_HEADER
346
+ lf = xml_doc.add_element 'logflush'
347
+ lf.add_element('log').text = 'policy'
348
+ lf.add_element('log_id').text = pol_id.to_s
349
+ lf.add_element('interval').text = "#{older_than} #{period}"
350
+ comps_elem = lf.add_element 'computers'
351
+ computers.each do |c|
352
+ id = JSS::Computer.valid_id c
353
+ next unless id
354
+
355
+ ce = comps_elem.add_element 'computer'
356
+ ce.add_element('id').text = id.to_s
357
+ end
358
+
359
+ # Do a DELETE request with a body.
360
+ api.cnx.delete(LOG_FLUSH_RSRC) do |req|
361
+ req.headers[JSS::APIConnection::HTTP_CONTENT_TYPE_HEADER] = JSS::APIConnection::MIME_XML
362
+ req.body = xml_doc.to_s
363
+ end
364
+ end
365
+ private_class_method :flush_logs_for_specific_computers
366
+
284
367
  # Attributes
285
368
  ######################
286
369
 
@@ -613,7 +696,6 @@ module JSS
613
696
 
614
697
  if @in_jss
615
698
  gen = @init_data[:general]
616
- @frequency = gen[:frequency]
617
699
  @target_drive = gen[:target_drive]
618
700
  @offline = gen[:offline]
619
701
  @enabled = gen[:enabled]
@@ -629,6 +711,10 @@ module JSS
629
711
  trigger_enrollment_complete: gen[:trigger_enrollment_complete],
630
712
  trigger_other: gen[:trigger_other]
631
713
  }
714
+ @frequency = gen[:frequency]
715
+ @retry_event = gen[:retry_event]
716
+ @retry_attempts = gen[:retry_attempts]
717
+ @notify_failed_retries = gen[:notify_on_each_failed_retry]
632
718
 
633
719
  dtl = gen[:date_time_limitations]
634
720
 
@@ -745,8 +831,93 @@ module JSS
745
831
  # @return [void]
746
832
  #
747
833
  def frequency=(freq)
748
- raise JSS::InvalidDataError, "New frequency must be one of :#{FREQUENCIES.keys.join ', :'}" unless FREQUENCIES.key?(freq)
749
- @frequency = FREQUENCIES[freq]
834
+ raise JSS::InvalidDataError, "New frequency must be one of :#{FREQUENCIES.keys.join ', :'}" unless FREQUENCIES.key?(freq) || FREQUENCIES.value?(freq)
835
+
836
+ freq = freq.is_a?(Symbol) ? FREQUENCIES[freq] : freq
837
+ return if freq == @frequency
838
+
839
+ @frequency = freq
840
+ @need_to_update = true
841
+ end
842
+
843
+ # @return [String] The event that causes a policy retry
844
+ def retry_event
845
+ return RETRY_EVENTS[:none] unless FREQUENCIES[:once_per_computer] == @frequency
846
+
847
+ @retry_event
848
+ end
849
+
850
+ # Set the event that causes a retry if the policy fails.
851
+ # One of the ways to turn off policy retry is to set this to :none
852
+ # The other is to set the retry_attempts to 0
853
+ #
854
+ # @param [Symbol, String] A key or value from RETRY_EVENTS
855
+ # @return [void]
856
+ #
857
+ def retry_event=(evt)
858
+ validate_retry_opt
859
+ raise JSS::InvalidDataError, "Retry event must be one of :#{RETRY_EVENTS.keys.join ', :'}" unless RETRY_EVENTS.key?(evt) || RETRY_EVENTS.value?(evt)
860
+
861
+ evt = evt.is_a?(Symbol) ? RETRY_EVENTS[evt] : evt
862
+ return if evt == @retry_event
863
+
864
+ # if the event is not 'none' and attempts is <= 0,
865
+ # set events to 1, or the API won't accept it
866
+ unless evt == RETRY_EVENTS[:none]
867
+ @retry_attempts = 1 unless @retry_attempts.positive?
868
+ end
869
+
870
+ @retry_event = evt
871
+ @need_to_update = true
872
+ end
873
+
874
+ # @return [Integer] How many times wil the policy be retried if it fails.
875
+ # -1 means no retries, otherwise, an integer from 1 to 10
876
+ def retry_attempts
877
+ return 0 unless FREQUENCIES[:once_per_computer] == @frequency
878
+
879
+ @retry_attempts
880
+ end
881
+
882
+ # Set the number of times to retry if the policy fails.
883
+ # One of the ways to turn off policy retry is to set this to 0 or -1
884
+ # The other is to set retry_event to :none
885
+ #
886
+ # @param [Integer] From -1 to 10
887
+ # @return [void]
888
+ #
889
+ def retry_attempts=(int)
890
+ validate_retry_opt
891
+ raise JSS::InvalidDataError, 'Retry attempts must be an integer from 0-10' unless int.is_a?(Integer) && (-1..10).include?(int)
892
+
893
+ # if zero or -1, turn off retries
894
+ if int <= 0
895
+ @retry_event = RETRY_EVENTS[:none]
896
+ int = -1
897
+ end
898
+ return if @retry_attempts == int
899
+
900
+ @retry_attempts = int
901
+ @need_to_update = true
902
+ end
903
+
904
+ # @return [Boolean] Should admins be notified of failed retry attempts
905
+ def notify_failed_retries?
906
+ return false unless FREQUENCIES[:once_per_computer] == @frequency
907
+
908
+ @notify_failed_retries
909
+ end
910
+ alias notify_failed_retries notify_failed_retries?
911
+ alias notify_on_each_failed_retry notify_failed_retries?
912
+
913
+ # @param bool[Boolean] Should admins be notified of failed retry attempts
914
+ # @return [void]
915
+ def notify_failed_retries=(bool)
916
+ validate_retry_opt
917
+ bool = JSS::Validate.boolean bool
918
+ return if @notify_failed_retries == bool
919
+
920
+ @notify_failed_retries = bool
750
921
  @need_to_update = true
751
922
  end
752
923
 
@@ -1621,34 +1792,37 @@ module JSS
1621
1792
  end
1622
1793
  alias execute run
1623
1794
 
1624
- # Flush all policy logs for this policy older than
1625
- # some number of days, weeks, months or years.
1795
+ # Flush logs for this policy older than
1796
+ # some number of days, weeks, months or years, possibly limited to
1797
+ # one or more computers
1798
+ #
1799
+ # With no parameters, flushes all logs for all computers
1626
1800
  #
1627
- # With no parameters, flushes all logs
1801
+ # NOTE: Currently the API doesn't have a way to flush only failed policies.
1628
1802
  #
1629
- # NOTE: Currently the API doesn't have a way to
1630
- # flush only failed policies.
1803
+ # WARNING: Log flushing can take a long time, and the API call doesnt return
1804
+ # until its finished. The connection timeout will be temporarily raised to
1805
+ # 30 minutes, unless it's already higher.
1631
1806
  #
1632
1807
  # @param older_than[Integer] 0, 1, 2, 3, or 6
1633
1808
  #
1634
1809
  # @param period[Symbol] :days, :weeks, :months, or :years
1635
1810
  #
1811
+ # @param computers[Array<Integer,String>] Identifiers of the target computers
1812
+ # either ids, names, SNs, macaddrs, or UDIDs
1813
+ #
1636
1814
  # @return [void]
1637
1815
  #
1638
- def flush_logs(older_than: 0, period: :days)
1816
+ def flush_logs(older_than: 0, period: :days, computers: [])
1639
1817
  raise JSS::NoSuchItemError, "Policy doesn't exist in the JSS. Use #create first." unless @in_jss
1640
1818
 
1641
- unless LOG_FLUSH_INTERVAL_INTEGERS.key?(older_than)
1642
- raise JSS::InvalidDataError, "older_than must be one of these integers: #{LOG_FLUSH_INTERVAL_INTEGERS.keys.join ', '}"
1643
- end
1644
-
1645
- unless LOG_FLUSH_INTERVAL_PERIODS.key?(period)
1646
- raise JSS::InvalidDataError, "period must be one of these symbols: :#{LOG_FLUSH_INTERVAL_PERIODS.keys.join ', :'}"
1647
- end
1648
-
1649
- interval = "#{LOG_FLUSH_INTERVAL_INTEGERS[older_than]}+#{LOG_FLUSH_INTERVAL_PERIODS[period]}"
1650
-
1651
- @api.delete_rsrc "#{LOG_FLUSH_RSRC}/policy/id/#{@id}/interval/#{interval}"
1819
+ JSS::Policy.flush_logs(
1820
+ @id,
1821
+ older_than: older_than,
1822
+ period: period,
1823
+ computers: computers,
1824
+ api: @api
1825
+ )
1652
1826
  end
1653
1827
 
1654
1828
  # Private Instance Methods
@@ -1656,6 +1830,17 @@ module JSS
1656
1830
 
1657
1831
  private
1658
1832
 
1833
+ # raise an error if a trying to set retry options when
1834
+ # frequency is not 'once per comptuer'
1835
+ #
1836
+ # @return [void]
1837
+ #
1838
+ def validate_retry_opt
1839
+ return if FREQUENCIES[:once_per_computer] == @frequency
1840
+
1841
+ raise JSS::UnsupportedError, 'Policy retry is only available when frequency is set to :once_per_computer'
1842
+ end
1843
+
1659
1844
  # raise an error if a package being added isn't valid
1660
1845
  #
1661
1846
  # @see #add_package
@@ -1786,6 +1971,10 @@ module JSS
1786
1971
  general.add_element('name').text = @name
1787
1972
  general.add_element('enabled').text = @enabled
1788
1973
  general.add_element('frequency').text = @frequency
1974
+ general.add_element('retry_event').text = @retry_event
1975
+ general.add_element('retry_attempts').text = @retry_attempts.to_s
1976
+ general.add_element('notify_on_each_failed_retry').text = @notify_failed_retries.to_s
1977
+
1789
1978
  general.add_element('target_drive').text = @target_drive
1790
1979
  general.add_element('offline').text = @offline
1791
1980