ruby-jss 2.0.0b3 → 2.0.0b5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.0b5'.freeze
31
31
 
32
32
  end # module