ruby-jss 2.0.0b3 → 2.0.0

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.
@@ -107,27 +107,18 @@ module Jamf
107
107
  def self.master_distribution_point(refresh = false, default: nil, api: nil, cnx: Jamf.cnx)
108
108
  cnx = api if api
109
109
 
110
- @master_distribution_point = nil if refresh
111
- return @master_distribution_point if @master_distribution_point
112
-
113
110
  all_ids(refresh, cnx: cnx).each do |dp_id|
114
111
  dp = fetch id: dp_id, cnx: cnx
115
- if dp.master?
116
- @master_distribution_point = dp
117
- break
118
- end
112
+ return dp if dp.master?
119
113
  end
120
114
 
121
- # If we're here, the Cloud DP might be master, but there's no
122
- # access to it in the API :/
123
- raise Jamf::NoSuchItemError, 'No Master FileShare Distribtion Point. Use the default: parameter if needed.' unless @master_distribution_point || default
124
-
125
- if @master_distribution_point
126
- @master_distribution_point
127
- elsif default == :random
128
- @master_distribution_point = fetch(id: all_ids.sample, cnx: cnx)
115
+ case default
116
+ when :random
117
+ fetch id: all_ids.sample, cnx: cnx
118
+ when nil
119
+ raise Jamf::NoSuchItemError, 'No Master FileShare Distribtion Point. Use the default: parameter if needed.'
129
120
  else
130
- @master_distribution_point = fetch(default, cnx: cnx)
121
+ fetch default, cnx: cnx
131
122
  end
132
123
  end
133
124
 
@@ -267,38 +258,9 @@ module Jamf
267
258
  # @return [String] the ssh password as a SHA256 digest
268
259
  attr_reader :ssh_password_sha256
269
260
 
270
- # As well as the standard :id, :name, and :data, you can
271
- # instantiate this class with :id => :master, in which case you'll
272
- # get the Master Distribution Point as defined in the JSS.
273
- # An error will be raised if one hasn't been defined.
274
- #
275
- # You can also do this more easily by calling JSS.master_distribution_point
276
- #
277
261
  def initialize(**args)
278
- # TODO: this looks redundant with super....
279
- args[:cnx] ||= args[:api]
280
- args[:cnx] ||= Jamf.cnx
281
-
282
- @cnx = args[:cnx]
283
-
284
- @init_data = nil
285
-
286
- # looking for master?
287
- if args[:id] == :master
288
-
289
- self.class.all_ids(cnx: @cnx).each do |id|
290
- @init_data = @cnx.c_get("#{RSRC_BASE}/id/#{id}")[RSRC_OBJECT_KEY]
291
- if @init_data[:is_master]
292
- @id = @init_data[:id]
293
- @name = @init_data[:name]
294
- break
295
- end # if data is master
296
- @init_data = nil
297
- end # each id
298
- end # if args is master
299
-
300
- super(args) if @init_data.nil?
301
-
262
+ super
263
+
302
264
  @ip_address = @init_data[:ip_address]
303
265
  @local_path = @init_data[:local_path]
304
266
  @enable_load_balancing = @init_data[:enable_load_balancing]
@@ -365,7 +327,7 @@ module Jamf
365
327
  when :ro then @read_only_password_sha256
366
328
  when :http then @http_password_sha256
367
329
  when :ssh then @ssh_password_sha256
368
- end # case
330
+ end # case
369
331
 
370
332
  return nil if sha256 == EMPTY_PW_256
371
333
 
@@ -449,7 +411,7 @@ module Jamf
449
411
  JSS.stdin line
450
412
  else
451
413
  pw
452
- end
414
+ end
453
415
 
454
416
  pwok = check_pw(access, password)
455
417
  unless pwok
@@ -466,7 +428,7 @@ module Jamf
466
428
  when 'smb' then '/sbin/mount_smbfs'
467
429
  when 'afp' then '/sbin/mount_afp'
468
430
  else raise "Can't mount distribution point #{@name}: no known connection type."
469
- end
431
+ end
470
432
 
471
433
  @mountpoint.mkpath
472
434
 
@@ -180,6 +180,7 @@ module Jamf
180
180
  info[:source_id] = info[:source_id].to_i
181
181
  end
182
182
  return data unless source_id
183
+
183
184
  data.select { |p| p[:source_id] == source_id }
184
185
  end
185
186
 
@@ -311,9 +312,11 @@ module Jamf
311
312
  # so all other lookup values have to be converted to ID before
312
313
  # the call to super
313
314
  #
314
- def self.fetch(identifier = nil, **params)
315
- # default api
316
- api = params[:api] ? params[:api] : Jamf.cnx
315
+ def self.fetch(identifier = nil, **params)
316
+ # default connection if unspecified
317
+ cnx = params.delete :cnx
318
+ cnx ||= params.delete :api # backward compatibility, deprecated
319
+ cnx ||= Jamf.cnx
317
320
 
318
321
  # source: and source_id: are considered the same, source_id: wins
319
322
  params[:source_id] ||= params[:source]
@@ -349,8 +352,8 @@ module Jamf
349
352
  cnx = api if api
350
353
 
351
354
  id = all_ids(refresh, cnx: cnx).include?(ident) ? ident : nil
352
- id ||= map_all_ids_to(:source_name_id).invert[ident]
353
- id ||= map_all_ids_to(:name).invert[ident]
355
+ id ||= map_all(:id, to: :source_name_id).invert[ident]
356
+ id ||= map_all(:id, to: :name).invert[ident]
354
357
  id
355
358
  end
356
359
 
@@ -376,7 +379,6 @@ module Jamf
376
379
  attr_reader :email_notification
377
380
  alias email_notification? email_notification
378
381
 
379
- #
380
382
  def initialize(**args)
381
383
  super
382
384
 
@@ -421,11 +423,11 @@ module Jamf
421
423
  def versions
422
424
  return @versions unless in_jss
423
425
  return @versions unless @versions.empty?
426
+
424
427
  # if we are in jss, and versions is empty, re-fetch them
425
428
  @versions = self.class.fetch(id: id).versions
426
429
  end
427
430
 
428
-
429
431
  # @return [Hash] Subset of @versions, containing those which have packages
430
432
  # assigned
431
433
  #
@@ -442,6 +444,7 @@ module Jamf
442
444
  def email_notification=(new_setting)
443
445
  return if email_notification == new_setting
444
446
  raise Jamf::InvalidDataError, 'New Setting must be boolean true or false' unless Jamf::TRUE_FALSE.include? @email_notification = new_setting
447
+
445
448
  @need_to_update = true
446
449
  end
447
450
 
@@ -454,6 +457,7 @@ module Jamf
454
457
  def web_notification=(new_setting)
455
458
  return if web_notification == new_setting
456
459
  raise Jamf::InvalidDataError, 'New Setting must be boolean true or false' unless Jamf::TRUE_FALSE.include? @web_notification = new_setting
460
+
457
461
  @need_to_update = true
458
462
  end
459
463
 
@@ -467,8 +471,8 @@ module Jamf
467
471
 
468
472
  # wrapper to fetch versions after creating
469
473
  def create
470
- response = super
471
- response
474
+ super
475
+
472
476
  end
473
477
 
474
478
  # wrapper to clear @changed_pkgs after updating
@@ -535,6 +539,7 @@ module Jamf
535
539
  pkg = velem.add_element 'package'
536
540
  # leave am empty package element to remove the pkg assignement
537
541
  next if versions[vers].package_id == :none
542
+
538
543
  pkg.add_element('id').text = versions[vers].package_id.to_s
539
544
  end # do vers
540
545
  end
@@ -557,8 +557,9 @@ module Jamf
557
557
  #
558
558
  ######################################
559
559
  def self.map_all(ident, to:, cnx: Jamf.cnx, refresh: false, cached_list: nil)
560
+ orig_ident = ident
560
561
  ident = lookup_keys[ident]
561
- raise Jamf::InvalidDataError, "No identifier :#{ident} for class #{self}" unless ident
562
+ raise Jamf::InvalidDataError, "No identifier :#{orig_ident} for class #{self}" unless ident
562
563
 
563
564
  list = cached_list || all(refresh, cnx: cnx)
564
565
  mapped = list.map do |i|
@@ -673,28 +674,85 @@ module Jamf
673
674
  # is undefined. In short - dont' use names here unless you know they are
674
675
  # unique.
675
676
  #
677
+ # NOTE: Integers passed in as strings, e.g. '12345' will be converted to
678
+ # integers and return the matching integer id if it exists.
679
+ #
680
+ # This means that if you have names that might match '12345' and you use
681
+ # valid_id '12345'
682
+ # you will get back the id 12345, if such an id exists, even if it is not
683
+ # the object with the name '12345'
684
+ #
685
+ # To explicitly look for '12345' as a name, use:
686
+ # valid_id name: '12345'
687
+ # See the ident_and_val param below.
688
+ #
676
689
  # @param identfier [String,Integer] An identifier for an object, a value for
677
- # one of the available lookup_keys
690
+ # one of the available lookup_keys. Omit this and use 'identifier: value'
691
+ # if you want to limit the search to a specific indentifier key, e.g.
692
+ # name: 'somename'
693
+ # or
694
+ # id: 76538
678
695
  #
679
696
  # @param refresh [Boolean] Should the data be re-read from the server
680
697
  #
698
+ # @param ident_and_val [Hash] Do not pass in Hash.
699
+ # This Hash internally holds the arbitrary identifier key
700
+ # and desired value when you call ".valid_id ident: 'value'", e.g.
701
+ # ".valid_id name: 'somename'" or ".valid_id udid: some_udid"
702
+ # Using explicit identifier keys like this will speed things up, since
703
+ # the method doesn't have to search through all available identifiers
704
+ # for the desired value.
705
+ #
681
706
  # @param cnx [Jamf::Connection] an API connection to use for the query.
682
707
  # Defaults to the corrently active API. See {Jamf::Connection}
683
708
  #
684
709
  # @return [Integer, nil] the id of the matching object, or nil if it doesn't exist
685
710
  #
686
- def self.valid_id(identifier, refresh = false, api: nil, cnx: Jamf.cnx)
711
+ def self.valid_id(identifier = nil, refresh = false, api: nil, cnx: Jamf.cnx, **ident_and_val)
687
712
  cnx = api if api
688
713
 
689
- # refresh if needed
714
+ # refresh the cache if needed
690
715
  all(refresh, cnx: cnx) if refresh
691
716
 
692
- # it its a valid id, return it
717
+ # Were we given an explict identifier key, like name: or id:?
718
+ # If so, just look for that.
719
+ unless ident_and_val.empty?
720
+ # only the first k/v pair of the ident_and_val hash is used
721
+ key = ident_and_val.keys.first
722
+ val = ident_and_val[key]
723
+
724
+ # if we are explicitly looking for an id, ensure we use an integer
725
+ # even if we were given an integer in a string.
726
+ if key == :id
727
+ val = val.to_i if val.is_a?(String) && val.j_integer?
728
+ return all_ids(cnx: cnx).include?(val) ? val : nil
729
+ end
730
+
731
+ # map the identifiers to ids, and return the id if there's
732
+ # a case-insensitive matching identifire
733
+ map_all(key, to: :id).each do |ident_val, id|
734
+ return id if ident_val.to_s.casecmp? val.to_s
735
+ end
736
+ nil
737
+ end
738
+
739
+ # If we are here, we need to seach all available identifier keys
740
+ # Start by looking for it as an id.
741
+
742
+ # it its a valid integer id, return it
693
743
  return identifier if all_ids(cnx: cnx).include? identifier
694
744
 
745
+ # if its a valid integer-in-a-string id, return it
746
+ if identifier.is_a?(String) && identifier.j_integer?
747
+ int_id = identifier.to_i
748
+ return int_id if all_ids(cnx: cnx).include? int_id
749
+ end
750
+
751
+ # Now go through all the other identifier keys
695
752
  keys_to_check = lookup_keys(no_aliases: true)
696
753
  keys_to_check.delete :id # we've already checked :id
697
754
 
755
+ # loop thru looking for a match
698
756
  keys_to_check.each do |key|
699
757
  mapped_ids = map_all_ids_to key, cnx: cnx
700
758
  matches = mapped_ids.select { |_id, ident| ident.casecmp? identifier }
@@ -905,7 +963,7 @@ module Jamf
905
963
 
906
964
  # which connection?
907
965
  cnx = args.delete :cnx
908
- cnx ||= args.delete :api
966
+ cnx ||= args.delete :api # backward compatibility, deprecated
909
967
  cnx ||= Jamf.cnx
910
968
 
911
969
  # refresh the .all list if needed
@@ -1073,7 +1131,7 @@ module Jamf
1073
1131
  # @param cnx [Jamf::Connection] the connection thru which to make this
1074
1132
  # object. Defaults to the deault API connection in Jamf.cnx
1075
1133
  #
1076
- # @param args[Hash] The data for creating an object, such as name:
1134
+ # @param args [Hash] The data for creating an object, such as name:
1077
1135
  # See {APIObject#initialize}
1078
1136
  #
1079
1137
  # @return [APIObject] The un-created ruby-instance of a JSS object
@@ -1084,8 +1142,9 @@ module Jamf
1084
1142
  raise Jamf::UnsupportedError, "Creating #{self.class::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows."
1085
1143
  end
1086
1144
  raise ArgumentError, "Use '#{self.class}.fetch id: xx' to retrieve existing JSS objects" if args[:id]
1087
-
1088
- args[:api] ||= Jamf.cnx
1145
+
1146
+ args[:cnx] ||= args[:api] # deprecated
1147
+ args[:cnx] ||= Jamf.cnx
1089
1148
  args[:id] = :new
1090
1149
  new(**args)
1091
1150
  end
@@ -128,8 +128,9 @@ module Jamf
128
128
 
129
129
  # Fetch either an internal or external patch source
130
130
  #
131
- # BUG: there's an API bug: fetching a non-existent
132
- # which is why we rescue internal server errors.
131
+ # BUG: there's an API bug when fetching a non-existent patch source
132
+ # which is why we rescue 500 internal server errors and report them
133
+ # as 'no matching patch source'
133
134
  #
134
135
  # @see APIObject.fetch
135
136
  #
@@ -162,7 +163,7 @@ module Jamf
162
163
  # @see APIObject.make
163
164
  #
164
165
  def self.create(**args)
165
- case self.name
166
+ case name
166
167
  when 'Jamf::PatchSource'
167
168
  Jamf::PatchExternalSource.make args
168
169
  when 'Jamf::PatchExternalSource'
@@ -184,7 +185,7 @@ module Jamf
184
185
  def self.delete(victims, api: nil, cnx: Jamf.cnx)
185
186
  cnx = api if api
186
187
 
187
- case self.name
188
+ case name
188
189
  when 'Jamf::PatchSource'
189
190
  Jamf::PatchExternalSource victims, cnx: cnx
190
191
  when 'Jamf::PatchExternalSource'
@@ -292,6 +293,7 @@ module Jamf
292
293
 
293
294
  return :internel if Jamf::PatchInternalSource.valid_id ident, refresh, cnx: cnx
294
295
  return :external if Jamf::PatchExternalSource.valid_id ident, refresh, cnx: cnx
296
+
295
297
  nil
296
298
  end
297
299
 
@@ -324,7 +326,10 @@ module Jamf
324
326
 
325
327
  # Init
326
328
  def initialize(**args)
327
- raise Jamf::UnsupportedError, 'PatchSource is an abstract metaclass. Please use PatchInternalSource or PatchExternalSource' if self.class == Jamf::PatchSource
329
+ if instance_of?(Jamf::PatchSource)
330
+ raise Jamf::UnsupportedError,
331
+ 'PatchSource is an abstract metaclass. Please use PatchInternalSource or PatchExternalSource'
332
+ end
328
333
 
329
334
  super
330
335
 
@@ -106,7 +106,7 @@ module Jamf
106
106
  # If you provide connection details when calling 'new', they will be passed
107
107
  # to the {#connect} method immediately. Otherwise you can call {#connect} later.
108
108
  #
109
- # production_api = Jamf::Connection.new(
109
+ # production_server = Jamf::Connection.new(
110
110
  # 'https://produser@prodserver.address.org:8443/'
111
111
  # name: 'prod',
112
112
  # pw: :prompt
@@ -24,6 +24,7 @@
24
24
  #
25
25
 
26
26
  module Jamf
27
+
27
28
  # A Collection Resource in Jamf Pro
28
29
  #
29
30
  # See {Jamf::Resource} for general info about API resources.
@@ -60,6 +61,7 @@ module Jamf
60
61
  # @abstract
61
62
  ######################################
62
63
  module CollectionResource
64
+
63
65
  include Jamf::JPAPIResource
64
66
 
65
67
  # when this module is included, also extend our Class Methods
@@ -71,6 +73,7 @@ module Jamf
71
73
  # Class Methods
72
74
  #####################################
73
75
  module ClassMethods
76
+
74
77
  # 'include' all of these, so their methods become defined in this
75
78
  # module, and will become Class Methods when this module
76
79
  # is extended.
@@ -128,7 +131,6 @@ module Jamf
128
131
  @patch_path ||= defined?(self::PATCH_PATH) ? self::PATCH_PATH : self::LIST_PATH
129
132
  end
130
133
 
131
-
132
134
  # The path for POSTing to create a single object in the collection.
133
135
  #
134
136
  # Classes including CollectionResource really need to define POST_PATH if it
@@ -256,7 +258,6 @@ module Jamf
256
258
  #
257
259
  ######################################
258
260
  def all(sort: nil, filter: nil, instantiate: false, cnx: Jamf.cnx, refresh: nil)
259
-
260
261
  # if we are here, we need to query for all items, possibly filtered and
261
262
  # sorted
262
263
  sort = Jamf::Sortable.parse_url_sort_param(sort)
@@ -287,7 +288,6 @@ module Jamf
287
288
  # arbitrary pages from the collection.
288
289
  #
289
290
  def pager(page_size: Jamf::Pager::DEFAULT_PAGE_SIZE, sort: nil, filter: nil, instantiate: false, cnx: Jamf.cnx)
290
-
291
291
  sort = Jamf::Sortable.parse_url_sort_param(sort)
292
292
  filter = filterable? ? Jamf::Filterable.parse_url_filter_param(filter) : nil
293
293
 
@@ -325,7 +325,6 @@ module Jamf
325
325
 
326
326
  raise Jamf::NoSuchItemError, "No attribute :#{to} for class #{self}" unless self::OAPI_PROPERTIES.key? to
327
327
 
328
-
329
328
  list = cached_list || all(cnx: cnx)
330
329
  to_class = self::OAPI_PROPERTIES[to][:class]
331
330
  to_multi = self::OAPI_PROPERTIES[to][:multi]
@@ -362,7 +361,7 @@ module Jamf
362
361
  # raw_data some_value
363
362
  #
364
363
  # If some_value is an integer or a string containing an integer, it
365
- # is assumed to be an :id otherwise all the available identifers
364
+ # is assumed to be an :id, otherwise all the available identifers
366
365
  # are searched, in the order you see them when you call <class>.identifiers
367
366
  #
368
367
  # If no matching object is found, nil is returned.
@@ -382,8 +381,6 @@ module Jamf
382
381
  #
383
382
  ######################################
384
383
  def raw_data(searchterm = nil, ident: nil, value: nil, cnx: Jamf.cnx)
385
-
386
-
387
384
  # given a value with no ident key
388
385
  return raw_data_by_searchterm_only(searchterm, cnx: cnx) if searchterm
389
386
 
@@ -491,15 +488,13 @@ module Jamf
491
488
  #
492
489
  # @return [Boolean]
493
490
  ######################################
494
- def creatable?
491
+ def creatable?
495
492
  true
496
493
  end
497
494
 
498
495
  # Make a new thing to be added to the API
499
496
  ######################################
500
497
  def create(**params)
501
-
502
-
503
498
  # no such animal when .creating
504
499
  params.delete :id
505
500
 
@@ -582,7 +577,7 @@ module Jamf
582
577
  def delete(*ids, cnx: Jamf.cnx)
583
578
  raise Jamf::UnsupportedError, "Deleting #{self} objects is not currently supported" unless deletable?
584
579
 
585
- return bulk_delete(ids, cnx: Jamf.cnx) if self.bulk_deletable?
580
+ return bulk_delete(ids, cnx: Jamf.cnx) if bulk_deletable?
586
581
 
587
582
  errs = []
588
583
  ids.each do |id_to_delete|
@@ -650,7 +645,6 @@ module Jamf
650
645
  raise NoMethodError, "no method '#{list_method_name}': '#{attr_name}' is not an indentifier for #{self}"
651
646
  end
652
647
  end
653
-
654
648
  end # create_identifier_list_method
655
649
  private :create_identifier_list_method
656
650
 
@@ -758,5 +752,7 @@ module Jamf
758
752
  raise Jamf::MissingDataError, "Attribute '#{attr_name}' cannot be nil, must be a #{attr_def[:class]}"
759
753
  end
760
754
  end
755
+
761
756
  end # class CollectionResource
757
+
762
758
  end # module JAMF
data/lib/jamf/version.rb CHANGED
@@ -27,6 +27,6 @@
27
27
  module Jamf
28
28
 
29
29
  ### The version of ruby-jss
30
- VERSION = '2.0.0b3'.freeze
30
+ VERSION = '2.0.0'.freeze
31
31
 
32
32
  end # module