Class: Jamf::Scopable::Scope

Inherits:
Object
  • Object
show all
Defined in:
lib/jamf/api/classic/api_objects/scopable/scope.rb

Overview

This class represents a Scope in the JSS, as can be applied to Scopable objects like Policies, Profiles, etc. Instances of this class are generally used as the value of the @scope attribute of those objects.

Scope data comes from the API as a hash within the overall object data. The main keys of the hash define the included targets of the scope. A sub-hash defines limitations on those inclusions, and another sub-hash defines explicit exclusions.

This class provides methods for adding, removing, or fully replacing the various items in scope’s realms: targets, limitations, and exclusions.

This class also provides a way to see if a machine will be included in this scope.

IMPORTANT - Users & User Groups in Targets and Exclusions:

The classic API has bugs regarding the use of Users, UserGroups, LDAP/Local Users, & LDAP User Groups in scopes. Here’s a discussion of those bugs and how ruby-jss handles them.

Targets/Inclusions

- 'Users' in the Scope UI can only be Jamf::Users - No LDAP
  - BUG: They do not appear in API data (XML or JSON) and are
    NOT SUPPORTED in ruby-jss.
  - You must use the Web UI to work with them in a Scope.
- 'User Groups' in the Scope UI can only be Jamf::UserGroups - No LDAP
  - BUG: They do not appear in API data (XML or JSON) and are
    NOT SUPPORTED in ruby-jss.
  - You must use the Web UI to work with them in a Scope.

Limitations

- 'LDAP/Local Users' can be any string
  - The Web UI accepts any string, even if no matching Local or LDAP user.
  - The data shows up in API data in scope=>limitations=>users
    by name only (the string provided), no IDs
- 'LDAP User Groups' can only be LDAP groups that actually exist
  - The Web UI won't let you add a group that doesn't exist in ldap
  - The data shows up in API data in scope=>limitations=>user_groups
    by name and LDAP ID (which may be empty)
  - The data ALSO shows up in API data in scope=>limit_to_users=>user_groups
    by name only, no LDAP IDs. ruby-jss ignores this and looks at
    scope=>limitations=>user_groups

Exclusions, combines the behavior of Inclusions & Limitations

- 'Users' in the Scope UI can only be Jamf::Users - No LDAP
  - BUG: They do not appear in API data (XML or JSON) and are
    NOT SUPPORTED in ruby-jss.
  - You must use the Web UI to work with them in a Scope.
- 'User Groups' in the Scope UI can only be Jamf::UserGroups - No LDAP
  - BUG: They do not appear in API data (XML or JSON) and are
    NOT SUPPORTED in ruby-jss.
  - You must use the Web UI to work with them in a Scope.
- 'LDAP/Local Users' can be any string
  - The Web UI accepts any string, even if no matching Local or LDAP user.
  - The data shows up in API data in scope=>exclusions=>users
    by name only (the string provided), no IDs
- 'LDAP User Groups' can only be LDAP groups that actually exist
  - The Web UI won't let you add a group that doesn't exist in ldap
  - The data shows up in API data in scope=>exclusions=>user_groups
    by name and LDAP ID (which may be empty)

How ruby-jss handles this:

 - Methods #set_targets and #add_target will not accept the keys
   :user, :users, :user_group, :user_groups.

 - Method #remove_target will ignore them.

 - Methods #set_limitations, #add_limitation & #remove_limitation will accept:
   - :user, :ldap_user, or :jamf_ldap_user (and their plurals) for working
     with 'LDAP/Local Users'. When setting or adding, the provided
     string(s) must exist as either a Jamf::User or an LDAP user
   - :user_group or :ldap_user_group (and their plurals) for working with
     'LDAP User Groups'. When setting or adding, the provided string
     must exist as a group in LDAP.

 - Methods #set_exclusions, #add_exclusion & #remove_exclusion will accept:
   - :user, :ldap_user, or :jamf_ldap_user (and their plurals) for working
     with 'LDAP/Local Users'. When setting or adding, the provided string(s)
     must exist as either a Jamf::User or an LDAP user.
   - :user_group or :ldap_user_group (and their plurals) for working with
     'LDAP User Groups''. When setting or adding, the provided string
     must exist as a group in LDAP.

Internally in the Scope instance:

- The limitations and exclusions that match the WebUI's 'LDAP/Local Users'
  are in @limitations[:jamf_ldap_users]  and @exclusions[:jamf_ldap_users]

- The  limitations and exclusions that match the WebUI's 'LDAP User Groups'
  are in @limitations[:ldap_user_groups]  and @exclusions[:ldap_user_groups]

See Also:

Constant Summary collapse

SCOPING_CLASSES =

These are the classes that Scopes can use for defining a scope, keyed by appropriate symbols. NOTE: All the user and group ones don’t actually refer to Jamf::User or Jamf::UserGroup. See IMPORTANT discussion above.

{
  computers: Jamf::Computer,
  computer: Jamf::Computer,
  computer_groups: Jamf::ComputerGroup,
  computer_group: Jamf::ComputerGroup,
  mobile_devices: Jamf::MobileDevice,
  mobile_device: Jamf::MobileDevice,
  mobile_device_groups: Jamf::MobileDeviceGroup,
  mobile_device_group: Jamf::MobileDeviceGroup,
  buildings: Jamf::Building,
  building: Jamf::Building,
  departments: Jamf::Department,
  department: Jamf::Department,
  network_segments: Jamf::NetworkSegment,
  network_segment: Jamf::NetworkSegment,
  ibeacon: Jamf::IBeacon,
  ibeacons: Jamf::IBeacon,
  user: nil,
  users: nil,
  ldap_user: nil,
  ldap_users: nil,
  jamf_ldap_user: nil,
  jamf_ldap_users: nil,
  user_group: nil,
  user_groups: nil,
  ldap_user_group: nil,
  ldap_user_groups: nil
}.freeze
LDAP_JAMF_USER_KEYS =

These keys always mean :jamf_ldap_users

%i[
  user
  users
  ldap_user
  ldap_users
  jamf_ldap_user
  jamf_ldap_users
].freeze
LDAP_GROUP_KEYS =

These keys always mean :ldap_user_groups

%i[
  user_group
  user_groups
  ldap_user_group
  ldap_user_groups
].freeze
TARGETS_AND_GROUPS =

This hash maps the availble Scope Target keys from SCOPING_CLASSES to their corresponding target group keys from SCOPING_CLASSES.

{ computers: :computer_groups, mobile_devices: :mobile_device_groups }.freeze
ESS =

added to the ends of singular key names if needed, e.g. computer_group => computer_groups

's'.freeze
INCLUSIONS =

These can be part of the base inclusion list of the scope, along with the appropriate target and target group keys

%i[buildings departments].freeze
LIMITATIONS =

These can limit the inclusion list These are the keys that come from the API the :users key from the API is what we call :jamf_ldap_users and the :user_groups key from the API we call :ldap_user_groups See the IMPORTANT discussion above.

%i[
  ibeacons
  network_segments
  jamf_ldap_users
  ldap_user_groups
].freeze
EXCLUSIONS =

any of them can be excluded

INCLUSIONS + LIMITATIONS
DEFAULT_SCOPE =

Here’s a default scope as it might come from the API.

{
  all_computers: true,
  all_mobile_devices: true,
  limitations: {},
  exclusions: {}
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target_key, raw_scope = nil) ⇒ Scope

If raw_scope is empty, a default scope, scoped to all targets, is created, and can be modified as needed.

Parameters:

  • target_key (Symbol)

    the kind of thing we’re scoping, one of TARGETS_AND_GROUPS

  • raw_scope (Hash) (defaults to: nil)

    the JSON :scope data from an API query that is scopable, e.g. a Policy.



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 303

def initialize(target_key, raw_scope = nil)
  raw_scope ||= DEFAULT_SCOPE.dup
  unless TARGETS_AND_GROUPS.key?(target_key)
    raise Jamf::InvalidDataError, "The target class of a Scope must be one of the symbols :#{TARGETS_AND_GROUPS.keys.join(', :')}"
  end

  @target_key = target_key
  @target_class = SCOPING_CLASSES[@target_key]
  @group_key = TARGETS_AND_GROUPS[@target_key]
  @group_class = SCOPING_CLASSES[@group_key]

  @target_keys = [@target_key, @group_key] + INCLUSIONS
  @exclusion_keys = [@target_key, @group_key] + EXCLUSIONS

  @all_key = "all_#{target_key}".to_sym
  @all_targets = raw_scope[@all_key]

  # Everything gets mapped from an Array of Hashes to
  # an Array of ids
  @targets = {}
  @target_keys.each do |k|
    raw_scope[k] ||= []
    @targets[k] = raw_scope[k].compact.map { |n| n[:id].to_i }
    @targets[:direct_targets] = @targets[k] if k == @target_key
    @targets[:group_targets] = @targets[k] if k == @group_key
  end # @target_keys.each do |k|

  # the  :users key from the API is what we call :jamf_ldap_users
  # and the :user_groups key from the API we call :ldap_user_groups
  # See the IMPORTANT discussion above.
  @limitations = {}
  if raw_scope[:limitations]

    LIMITATIONS.each do |k|
      # :jamf_ldap_users comes from :users in the API data
      if k == :jamf_ldap_users
        api_data = raw_scope[:limitations][:users]
        api_data ||= []
        @limitations[k] = api_data.compact.map { |n| n[:name].to_s }

      # :ldap_user_groups comes from :user_groups in the API data
      elsif k == :ldap_user_groups
        api_data = raw_scope[:limitations][:user_groups]
        api_data ||= []
        @limitations[k] = api_data.compact.map { |n| n[:name].to_s }

      # others handled normally.
      else
        api_data = raw_scope[:limitations][k]
        api_data ||= []
        @limitations[k] = api_data.compact.map { |n| n[:id].to_i }
      end
    end # LIMITATIONS.each do |k|
  end # if raw_scope[:limitations]

  # the  :users key from the API is what we call :jamf_ldap_users
  # and the :user_groups key from the API we call :ldap_user_groups
  # See the IMPORTANT discussion above.
  @exclusions = {}
  if raw_scope[:exclusions]

    @exclusion_keys.each do |k|
      # :jamf_ldap_users comes from :users in the API data
      if k == :jamf_ldap_users
        api_data = raw_scope[:exclusions][:users]
        api_data ||= []
        @exclusions[k] = api_data.compact.map { |n| n[:name].to_s }

      # :ldap_user_groups comes from :user_groups in the API data
      elsif k == :ldap_user_groups
        api_data = raw_scope[:exclusions][:user_groups]
        api_data ||= []
        @exclusions[k] = api_data.compact.map { |n| n[:name].to_s }

      # others handled normally.
      else
        api_data = raw_scope[:exclusions][k]
        api_data ||= []
        @exclusions[k] = api_data.compact.map { |n| n[:id].to_i }
        @exclusions[:direct_exclusions] = @exclusions[k] if k == @target_key
        @exclusions[:group_exclusions] = @exclusions[k] if k == @group_key
      end # if ...elsif... else
    end # @exclusion_keys.each
  end # if raw_scope[:exclusions]

  @container = nil
end

Instance Attribute Details

#all_targetsBoolean Also known as: all_targets?

Does this scope cover all targets?

If this is true, the @targets Hash is ignored, and all targets in the JSS form the base scope.

Returns:

  • (Boolean)


247
248
249
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 247

def all_targets
  @all_targets
end

#containerJamf::APIObject subclass

A reference to the object that contains this Scope

For telling it when a change is made and an update needed and for accessing its api connection

Returns:



228
229
230
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 228

def container
  @container
end

#exclusionsHash{Symbol: Array<Integer, String>} (readonly)

The items in these arrays are the exclusions applied to targets in the @targets .

The arrays of ids are:

  • :computers or :mobile_devices (which are directly excluded)

  • :direct_exclusions - a synonym for :mobile_devices or :computers

  • :computer_groups or :mobile_device_groups (which exclude all of their memebers)

  • :group_exclusions - a synonym for :computer_groups or :mobile_device_groups

  • :departments

  • :buildings

  • :network_segments

  • :users

  • :user_groups

Returns:



291
292
293
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 291

def exclusions
  @exclusions
end

#group_classObject (readonly)

what type of target group is this scope for? ComputerGroups or MobileDeviceGroups?



238
239
240
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 238

def group_class
  @group_class
end

#limitationsHash{Symbol: Array<Integer, String>} (readonly)

The items in these arrays are the limitations applied to targets in the @targets .

The arrays of ids are:

  • :network_segments

  • :jamf_ldap_users

  • :user_groups

Returns:



275
276
277
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 275

def limitations
  @limitations
end

#target_classObject (readonly)

what type of target is this scope for? Computers or MobileDevices?



235
236
237
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 235

def target_class
  @target_class
end

#targetsHash{Symbol: Array<Integer>} (readonly) Also known as: inclusions

The items which form the base scope of included targets

This is the group of targets to which the limitations and exclusions apply. they keys are:

  • :computers or :mobile_devices (which are directly targeted)

  • :direct_targets - a synonym for :mobile_devices or :computers

  • :computer_groups or :mobile_device_groups (which target all of their memebers)

  • :group_targets - a synonym for :computer_groups or :mobile_device_groups

  • :departments

  • :buildings

and the values are Arrays of names of those things.

Returns:



263
264
265
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 263

def targets
  @targets
end

#unable_to_verify_ldap_entriesBoolean

Returns should we expect a potential 409 Conflict if we can’t connect to LDAP servers for verification?.

Returns:

  • (Boolean)

    should we expect a potential 409 Conflict if we can’t connect to LDAP servers for verification?



232
233
234
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 232

def unable_to_verify_ldap_entries
  @unable_to_verify_ldap_entries
end

Instance Method Details

#add_exclusion(key, item) ⇒ void

This method returns an undefined value.

Add a single item for exclusions of this scope.

The item name will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.

Examples:

add_exclusion(:network_segments, "foo")

Parameters:

  • key (Symbol)

    the type of item being added to the exclusions, :computer, :building, etc…

  • item (String, integer)

    a valid identifier of the item being added

Raises:



681
682
683
684
685
686
687
688
689
690
691
692
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 681

def add_exclusion(key, item)
  key = pluralize_key(key)
  item_id = validate_item(:exclusion, key, item)
  return if @exclusions[key]&.include?(item_id)

  raise Jamf::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @targets[key]&.include?(item)

  raise Jamf::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key]&.include?(item)

  @exclusions[key] << item_id
  @container&.should_update
end

#add_limitation(key, item) ⇒ void

TODO:

handle ldap user/group lookups

This method returns an undefined value.

Add a single item for limiting this scope.

The item name will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.

Examples:

add_limitation(:network_segments, "foo")

Parameters:

  • key (Symbol)

    the type of item being added, :computer, :building, etc…

  • item (String, integer)

    a valid identifier of the item being added



592
593
594
595
596
597
598
599
600
601
602
603
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 592

def add_limitation(key, item)
  key = pluralize_key(key)
  item_id = validate_item(:limitation, key, item)
  return nil if @limitations[key]&.include?(item_id)

  if @exclusions[key]&.include?(item_id)
    raise Jamf::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
  end

  @limitations[key] << item_id
  @container&.should_update
end

#add_target(key, item = nil) ⇒ void Also known as: add_inclusion

This method returns an undefined value.

Add a single item as a target in this scope.

The item name will be checked for existence in the JSS, and an exception

raised if the item doesn't exist.

Examples:

add_target(:computers, "mantis")
add_target(:computer_groups, 2342)

Parameters:

  • key (Symbol)

    the key from #SCOPING_CLASSES for the kind of item being added, :computer, :building, etc… Use :all to scope to all targets (the same as calling #set_all_targets)

  • item (String, integer) (defaults to: nil)

    a valid identifier of the item being added



497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 497

def add_target(key, item = nil)
  if key == :all
    set_all_targets
    return
  end

  key = pluralize_key(key)
  item_id = validate_item(:target, key, item)
  return if @targets[key]&.include?(item_id)

  if @exclusions[key]&.include?(item_id)
    raise Jamf::AlreadyExistsError,
          "Can't set #{key} target to '#{item}' because it's already an explicit exclusion."
  end

  @targets[key] << item_id
  @all_targets = false
  @container&.should_update
end

#in_scope?(machine) ⇒ Boolean

is a given machine is in this scope?

For a parameter you may pass either an instantiated Jamf::MobileDevice or Jamf::Computer, or an identifier for one. If an identifier is passed, it is not instantiated, but an API request is made for just the required subsets of data, thus speeding things up a bit when calling this method many times.

WARNING: For scopes that include Jamf Users and Jamf User Groups as targets or exclusions, this method may return an incorrect value. See the discussion in the documentation for the Scopable::Scope class under ‘IMPORTANT - Users & User Groups in Targets and Exclusions’

NOTE: currently in-range iBeacons are transient, and are not reported to the JSS as inventory data. As such they are ignored in this result. If a scope contains iBeacon limitations or exclusions, it is up to the user to be aware of that when evaluating the meaning of this result.

Parameters:

Returns:

  • (Boolean)


839
840
841
842
843
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 839

def in_scope?(machine)
  machine_data = fetch_machine_data machine

  a_target?(machine_data) && within_limitations?(machine_data) && !excluded?(machine_data)
end

#pretty_print_instance_variablesArray

Remove the init_data and api object from the instance_variables used to create pretty-print (pp) output.

Returns:

  • (Array)

    the desired instance_variables



785
786
787
788
789
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 785

def pretty_print_instance_variables
  vars = instance_variables.sort
  vars.delete :@container
  vars
end

#remove_exclusion(key, item) ⇒ void

This method returns an undefined value.

Remove a single item for exclusions of this scope

Examples:

remove_exclusion(:network_segments, "foo")

Parameters:

  • key (Symbol)

    the type of item being removed from the excludions, :computer, :building, etc…

  • item (String, integer)

    a valid identifier of the item being removed



705
706
707
708
709
710
711
712
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 705

def remove_exclusion(key, item)
  key = pluralize_key(key)
  item_id = validate_item :exclusion, key, item, error_if_not_found: false
  return unless @exclusions[key]&.include?(item_id)

  @exclusions[key].delete item_id
  @container&.should_update
end

#remove_limitation(key, item) ⇒ void

TODO:

handle ldap user/group lookups

This method returns an undefined value.

Remove a single item for limiting this scope.

Examples:

remove_limitation(:network_segments, "foo")

Parameters:

  • key (Symbol)

    the type of item being removed, :computer, :building, etc…

  • item (String, integer)

    a valid identifier of the item being removed



618
619
620
621
622
623
624
625
626
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 618

def remove_limitation(key, item)
  key = pluralize_key(key)
  item_id = validate_item :limitation, key, item, error_if_not_found: false
  return unless item_id
  return unless @limitations[key]&.include?(item_id)

  @limitations[key].delete item_id
  @container&.should_update
end

#remove_target(key, item) ⇒ void Also known as: remove_inclusion

This method returns an undefined value.

Remove a single item as a target for this scope.

Examples:

remove_target(:computer, "mantis")

Parameters:

  • key (Symbol)

    the key from #SCOPING_CLASSES for the kind of item being removed, :computer, :building, etc…

  • item (String, integer)

    a valid identifier of the item being removed



529
530
531
532
533
534
535
536
537
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 529

def remove_target(key, item)
  key = pluralize_key(key)
  item_id = validate_item :target, key, item, error_if_not_found: false
  return unless item_id
  return unless @targets[key]&.include?(item_id)

  @targets[key].delete item_id
  @container&.should_update
end

#scope_xmlREXML::Element

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return a REXML Element containing the current state of the Scope for adding into the XML of the container.

Returns:

  • (REXML::Element)


720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 720

def scope_xml
  scope = REXML::Element.new 'scope'
  scope.add_element(@all_key.to_s).text = @all_targets

  @target_keys.each do |klass|
    list = @targets[klass]
    list.compact!
    list.delete 0
    list_as_hashes = list.map { |i| { id: i } }
    scope << SCOPING_CLASSES[klass].xml_list(list_as_hashes, :id)
  end

  limitations = scope.add_element('limitations')
  @limitations.each do |klass, list|
    list.compact!
    list.delete 0
    if klass == :jamf_ldap_users
      users_xml = limitations.add_element 'users'
      list.each do |name|
        user_xml = users_xml.add_element 'user'
        user_xml.add_element('name').text = name
      end
    elsif klass == :ldap_user_groups
      user_groups_xml = limitations.add_element 'user_groups'
      list.each do |name|
        user_group_xml = user_groups_xml.add_element 'user_group'
        user_group_xml.add_element('name').text = name
      end
    else
      list_as_hashes = list.map { |i| { id: i } }
      limitations << SCOPING_CLASSES[klass].xml_list(list_as_hashes, :id)
    end
  end

  exclusions = scope.add_element('exclusions')
  @exclusion_keys.each do |klass|
    list = @exclusions[klass]
    list.compact!
    list.delete 0
    if klass == :jamf_ldap_users
      users_xml = exclusions.add_element 'users'
      list.each do |name|
        user_xml = users_xml.add_element 'user'
        user_xml.add_element('name').text = name
      end
    elsif klass == :ldap_user_groups
      user_groups_xml = exclusions.add_element 'user_groups'
      list.each do |name|
        user_group_xml = user_groups_xml.add_element 'user_group'
        user_group_xml.add_element('name').text = name
      end
    else
      list_as_hashes = list.map { |i| { id: i } }
      exclusions << SCOPING_CLASSES[klass].xml_list(list_as_hashes, :id)
    end
  end
  scope
end

#scoped_machinesHash{Integer => String}

Return a hash of id => name for all machines in the target class that are within this scope.

WARNING: This must instantiate all machines in the target class. It will still be slow, at least the first time for each target class. On the upside, the instantiated machines will be cached, so generating this list for other scopes with the same target class will be much much faster. In tests, 1600 Computers took about 7 minutes the first time, but less than 1 second after caching.

See also the warning for #in_scope?

Returns:



807
808
809
810
811
812
813
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 807

def scoped_machines
  scoped_machines = {}
  @target_class.all_objects(:refresh, cnx: container.cnx).each do |machine|
    scoped_machines[machine.id] = machine.name if in_scope? machine
  end
  scoped_machines
end

#set_all_targets(clear = false) ⇒ void Also known as: include_all

This method returns an undefined value.

Set the scope’s inclusions to all targets.

By default, the limitations and exclusions remain. If a non-false parameter is provided, they will be removed also.

Parameters:

  • clear (Boolean) (defaults to: false)

    Should the limitations and exclusions be removed also?



400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 400

def set_all_targets(clear = false)
  @targets = {}
  @target_keys.each { |k| @targets[k] = [] }
  @all_targets = true
  if clear
    @limitations = {}
    LIMITATIONS.each { |k| @limitations[k] = [] }

    @exclusions = {}
    @exclusion_keys.each { |k| @exclusions[k] = [] }
  end
  @container&.should_update
end

#set_exclusion(key, list) ⇒ void

This method returns an undefined value.

Replace an exclusion list for this scope

The list must be an Array of names of items of the Class being excluded from the scope Each will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.

Examples:

set_exclusion(:network_segments, ['foo','bar'])

Parameters:

  • key (Symbol)

    the type of item being excluded, :computer, :building, etc…

  • list (Array)

    the identifiers of the items being set

Raises:



642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 642

def set_exclusion(key, list)
  key = pluralize_key(key)
  raise Jamf::InvalidDataError, "List must be an Array of #{key} identifiers, it may be empty." unless list.is_a? Array

  # check the idents
  list.map! do |ident|
    item_id = validate_item(:exclusion, key, ident)
    case key
    when *@target_keys
      if @targets[key] && @exclusions[key].include?(item_id)
        raise Jamf::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already explicitly included."
      end
    when *LIMITATIONS
      if @limitations[key] && @exclusions[key].include?(item_id)
        raise Jamf::AlreadyExistsError, "Can't exclude #{key} '#{ident}' because it's already an explicit limitation."
      end
    end
    item_id
  end # each

  return nil if list.sort == @exclusions[key].sort

  @exclusions[key] = list
  @container&.should_update
end

#set_limitation(key, list) ⇒ void Also known as: set_limitations

TODO:

handle ldap user group lookups

This method returns an undefined value.

Replace a limitation list for this scope.

The list must be an Array of names of items of the Class represented by the key. Each will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.

Examples:

set_limitation(:network_segments, ['foo',231])

Parameters:

  • key (Symbol)

    the type of items being set as limitations, :network_segments, :users, etc…

  • list (Array)

    the identifiers of the items being set as limitations

Raises:



556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 556

def set_limitation(key, list)
  key = pluralize_key(key)
  raise Jamf::InvalidDataError, "List must be an Array of #{key} identifiers, it may be empty." unless list.is_a? Array

  # check the idents
  list.map! do |ident|
    item_id = validate_item(:limitation, key, ident)
    if @exclusions[key]&.include?(item_id)
      raise Jamf::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion."
    end

    item_id
  end # each

  return nil if list.sort == @limitations[key].sort

  @limitations[key] = list
  @container&.should_update
end

#set_targets(key, list = nil) ⇒ void Also known as: set_target, set_inclusion, set_inclusions

This method returns an undefined value.

Replace a list of item names for as targets in this scope.

The list must be an Array of names of items of the Class represented by the key. Each will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.

being included, :computer, :building, etc… Use :all to scope to all targets (the same as calling #set_all_targets)

Examples:

set_targets(:computers, ['kimchi','mantis'])

Parameters:

  • key (Symbol)

    the key from #SCOPING_CLASSES for the kind of items

  • list (Array) (defaults to: nil)

    identifiers of the items being added

Raises:



433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 433

def set_targets(key, list = nil)
  if key == :all
    set_all_targets
    return
  end

  key = pluralize_key(key)
  raise Jamf::InvalidDataError, "List must be an Array of #{key} identifiers, it may be empty." unless list.is_a? Array

  # check the idents
  list.map! do |ident|
    item_id = validate_item(:target, key, ident)

    if @exclusions[key]&.include?(item_id)
      raise Jamf::AlreadyExistsError, \
            "Can't set #{key} target to '#{ident}' because it's already an explicit exclusion."
    end

    item_id
  end # each

  return nil if list.sort == @targets[key].sort

  @targets[key] = list
  @all_targets = false
  @container&.should_update
end

#to_sObject



846
847
848
# File 'lib/jamf/api/classic/api_objects/scopable/scope.rb', line 846

def to_s
  "Scope for #{container.class} id #{container.id}"
end