ruby-jss 1.3.2 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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