Class: JSS::APIConnection

Inherits:
Object show all
Defined in:
lib/jss.rb,
lib/jss/api_connection.rb

Overview

Instances of this class represent a REST connection to a JSS API.

For most cases, a single connection to a single JSS is all you need, and this is ruby-jss's default behavior.

If needed, multiple connections can be made and used sequentially or simultaneously.

Using the default connection

When ruby-jss is loaded, a not-yet-connected default instance of JSS::APIConnection is created and stored in the constant JSS::API. This connection is used as the initial 'active connection' (see below) so all methods that make API calls will use it by default. For most uses, where you're only going to be working with one connection to one JSS, the default connection is all you need.

Before using it you must call its #connect method, passing in appropriate connection details and credentials.

Example:

require 'ruby-jss'
JSS.api.connect server: 'server.address.edu', user: 'jss-api-user', pw: :prompt
# (see {JSS::APIConnection#connect} for all the connection options)

a_phone = JSS::MobileDevice.fetch id: 8743

# the mobile device was fetched through the default connection

Using Multiple Simultaneous Connections

Sometimes you need to connect simultaneously to more than one JSS. or to the same JSS with different credentials. ruby-jss allows you to create as many connections as needed, and gives you three ways to use them:

  1. Making a connection 'active', after which API calls go thru it automatically

    Example:

    a_computer = JSS::Computer.fetch id: 1234
    
    # the JSS::Computer with id 1234 is fetched from the active connection
    # and stored in the variable 'a_computer'
    

    NOTE: When ruby-jss is first loaded, the default connection (see above) is the active connection.

  2. Passing an APIConnection instance to methods that use the API

    Example:

    a_computer = JSS::Computer.fetch id: 1234, api: production_api
    
    # the JSS::Computer with id 1234 is fetched from the connection
    # stored in the variable 'production_api'. The computer is
    # then stored in the variable 'a_computer'
    
  3. Using the APIConnection instance itself to make API calls.

    Example:

    a_computer = production_api.fetch :Computer, id: 1234
    
    # the JSS::Computer with id 1234 is fetched from the connection
    # stored in the variable 'production_api'. The computer is
    # then stored in the variable 'a_computer'
    

See below for more details about the ways to use multiple connections.

NOTE: Objects retrieved or created through an APIConnection store an internal reference to that APIConnection and use that when they make other API calls, thus ensuring data consistency when using multiple connections.

Similiarly, the data caches used by APIObject list methods (e.g. JSS::Computer.all, .all_names, and so on) are stored in the APIConnection instance through which they were read, so they won't be incorrect when you use multiple connections.

Making new APIConnection instances

New connections can be created using the standard ruby 'new' method.

If you provide connection details when calling 'new', they will be passed to the #connect method immediately. Otherwise you can call #connect later.

production_api = JSS::APIConnection.new(
  name: 'prod',
  server: 'prodserver.address.org',
  user: 'produser',
  pw: :prompt
)

# the new connection is now stored in the variable 'production_api'.

Using the 'Active' Connection

While multiple connection instances can be created, only one at a time is 'the active connection' and all APIObject-based access methods in ruby-jss will use it automatically. When ruby-jss is loaded, the default connection (see above) is the active connection.

To use the active connection, just call a method on an APIObject subclass that uses the API.

For example, the various list methods:

all_computer_sns = JSS::Computer.all_serial_numbers

# the list of all computer serial numbers is read from the active
# connection and stored in all_computer_sns

Fetching an object from the API:

victim_md = JSS::MobileDevice.fetch id: 832

# the variable 'victim_md' now contains a JSS::MobileDevice queried
# through the active connection.

The currently-active connection instance is available from the `JSS.api` method.

Making a Connection Active

Only one connection is 'active' at a time and the currently active one is returned when you call `JSS.api` or its alias `JSS.active_connection`

To activate another connection just pass it to the JSS.use_api method like so:

JSS.use_api production_api
# the connection we stored in 'production_api' is now active

To re-activate to the default connection, just call

JSS.use_default_connection

Connection Names:

As seen in the example above, you can provide a 'name:' parameter (a String or a Symbol) when creating a new connection. The name can be used later to identify connection objects.

If you don't provide one, the name is ':disconnected' until you connect, and then 'user@server:port' after connecting.

The name of the default connection is always :default

To see the name of the currently active connection, just use `JSS.api.name`

JSS.use_api production_api
JSS.api.name  # => 'prod'

JSS.use_default_connection
JSS.api.name  # => :default

Creating, Storing and Activating a connection in one step

Both of the above steps (creating/storing a connection, and making it active) can be performed in one step using the `JSS.new_api_connection` method, which creates a new APIConnection, makes it the active connection, and returns it.

 production_api2 = JSS.new_api_connection(
   name: 'prod2',
   server: 'prodserver.address.org',
   user: 'produser',
   pw: :prompt
 )

JSS.api.name  # => 'prod2'

Passing an APIConnection object to API-related methods

All methods that use the API can take an 'api:' parameter which contains an APIConnection object. When provided, that APIconnection is used rather than the active connection.

For example:

prod2_computer_sns = JSS::Computer.all_serial_numbers, api: production_api2

# the list of all computer serial numbers is read from the connection in
# the variable 'production_api2' and stored in 'prod2_computer_sns'

prod2_victim_md = JSS::MobileDevice.fetch id: 832, api: production_api2

# the variable 'prod2_victim_md' now contains a JSS::MobileDevice queried
# through the connection 'production_api2'.

Using the APIConnection itself to make API calls.

Rather than passing an APIConnection into another method, you can call similar methods on the connection itself. For example, these two calls have the same result as the two examples above:

prod2_computer_sns = production_api2.all :Computer, only: :serial_numbers
prod2_victim_md = production_api2.fetch :MobileDevice, id: 832

Here are the API calls you can make directly from an APIConnection object. They behave practically identically to the same methods in the APIObject subclasses, since they just call those methods, passing themselves in as the APIConnection to use.

Low-level use of APIConnection instances.

For most cases, using APIConnection instances as mentioned above is all you'll need. However to access API resources that aren't yet implemented in other parts of ruby-jss, you can use the methods #get_rsrc, #put_rsrc, #post_rsrc, & #delete_rsrc documented below.

For even lower-level work, you can access the underlying RestClient::Resource inside the APIConnection via the connection's #cnx attribute.

APIConnection instances also have a #server attribute which contains an instance of Server q.v., representing the JSS to which it's connected.

Constant Summary collapse

RSRC_BASE =

The base API path in the jss URL

'JSSResource'.freeze
TEST_PATH =

A url path to load to see if there's an API available at a host. This just loads the API resource docs page

"#{RSRC_BASE}/accounts".freeze
TEST_CONTENT =

If the test path loads correctly from a casper server, it'll contain this text (this is what we get when we make an unauthenticated API call.)

'<p>The request requires user authentication</p>'.freeze
HTTP_PORT =

The Default port

9006
SSL_PORT =

The Jamf default SSL port, default for locally-hosted servers

8443
HTTPS_SSL_PORT =

The https default SSL port, default for Jamf Cloud servers

443
SSL_PORTS =

if either of these is specified, we'll default to SSL

[SSL_PORT, HTTPS_SSL_PORT].freeze
JAMFCLOUD_DOMAIN =

Recognize Jamf Cloud servers

'jamfcloud.com'.freeze
JAMFCLOUD_PORT =

JamfCloud connections default to 443, not 8443

HTTPS_SSL_PORT
XML_HEADER =

The top line of an XML doc for submitting data via API

'<?xml version="1.0" encoding="UTF-8" standalone="no"?>'.freeze
DFT_OPEN_TIMEOUT =

Default timeouts in seconds

60
DFT_TIMEOUT =
60
DFT_SSL_VERSION =

The Default SSL Version

'TLSv1_2'.freeze
RSRC_NOT_FOUND_MSG =
'The requested resource was not found'.freeze
EXTENDABLE_CLASSES =

These classes are extendable, and may need cache flushing for EA definitions

[JSS::Computer, JSS::MobileDevice, JSS::User].freeze
GET_FORMATS =

values for the format param of get_rsrc

%i[json xml].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ APIConnection

If name: is provided (as a String or Symbol) that will be stored as the APIConnection's name attribute.

For other available parameters, see #connect.

If they are provided, they will be used to establish the connection immediately.

If not, you must call #connect before accessing the API.



427
428
429
430
431
432
# File 'lib/jss/api_connection.rb', line 427

def initialize(args = {})
  @name = args.delete :name
  @name ||= :unknown
  @connected = false
  connect args unless args.empty?
end

Instance Attribute Details

#cnxRestClient::Resource (readonly)

Returns the underlying connection resource.

Returns:

  • (RestClient::Resource)

    the underlying connection resource



341
342
343
# File 'lib/jss/api_connection.rb', line 341

def cnx
  @cnx
end

#connectedBoolean (readonly) Also known as: connected?

Returns are we connected right now?.

Returns:

  • (Boolean)

    are we connected right now?



344
345
346
# File 'lib/jss/api_connection.rb', line 344

def connected
  @connected
end

#ext_attr_definition_cacheHash{Class: Hash{String => JSS::ExtensionAttribute}} (readonly)

This Hash caches the Extension Attribute definition objects for the three types of ext. attribs: ComputerExtensionAttribute, MobileDeviceExtensionAttribute, and UserExtensionAttribute, whenever they are fetched for parsing or validating extention attribute data.

The top-level keys are the EA classes themselves:

  • ComputerExtensionAttribute

  • MobileDeviceExtensionAttribute

  • UserExtensionAttribute

These each point to a Hash of their instances, keyed by name, e.g.

{
 "A Computer EA" => <JSS::ComputerExtensionAttribute...>,
 "A different Computer EA" => <JSS::ComputerExtensionAttribute...>,
 ...
}

Returns:



412
413
414
# File 'lib/jss/api_connection.rb', line 412

def ext_attr_definition_cache
  @ext_attr_definition_cache
end

#last_http_responseRestClient::Response (readonly)

Returns The response from the most recent API call.

Returns:

  • (RestClient::Response)

    The response from the most recent API call



363
364
365
# File 'lib/jss/api_connection.rb', line 363

def last_http_response
  @last_http_response
end

#nameString, Symbol (readonly)

connection during initialization, using the name: parameter. defaults to user@hostname:port

Returns:

  • (String, Symbol)

    an arbitrary name that can be given to this



371
372
373
# File 'lib/jss/api_connection.rb', line 371

def name
  @name
end

#object_list_cacheHash (readonly)

This Hash caches the result of the the first API query for an APIObject subclass's .all summary list, keyed by the subclass's RSRC_LIST_KEY. See the APIObject.all class method.

It also holds related data items for speedier processing:

  • The Hashes created by APIObject.map_all_ids_to(foo), keyed by “#RSRC_LIST_KEYmap#other_key”.to_sym

  • This hash also holds a cache of the rarely-used APIObject.all_objects hash, keyed by “#RSRC_LIST_KEY_objects”.to_sym

When APIObject.all, and related methods are called without an argument, and this hash has a matching value, the value is returned, rather than requerying the API. The first time a class calls .all, or whnever refresh is not false, the API is queried and the value in this hash is updated.

Returns:



391
392
393
# File 'lib/jss/api_connection.rb', line 391

def object_list_cache
  @object_list_cache
end

#portInteger (readonly)

Returns the port used for the connection.

Returns:

  • (Integer)

    the port used for the connection



357
358
359
# File 'lib/jss/api_connection.rb', line 357

def port
  @port
end

#protocolString (readonly)

Returns the protocol being used: http or https.

Returns:

  • (String)

    the protocol being used: http or https



360
361
362
# File 'lib/jss/api_connection.rb', line 360

def protocol
  @protocol
end

#rest_urlString (readonly)

Returns The base URL to to the current REST API.

Returns:

  • (String)

    The base URL to to the current REST API



366
367
368
# File 'lib/jss/api_connection.rb', line 366

def rest_url
  @rest_url
end

#serverJSS::Server (readonly)

Returns the details of the JSS to which we're connected.

Returns:

  • (JSS::Server)

    the details of the JSS to which we're connected.



348
349
350
# File 'lib/jss/api_connection.rb', line 348

def server
  @server
end

#server_hostString (readonly)

Returns the hostname of the JSS to which we're connected.

Returns:

  • (String)

    the hostname of the JSS to which we're connected.



351
352
353
# File 'lib/jss/api_connection.rb', line 351

def server_host
  @server_host
end

#server_pathString (readonly)

Returns any path in the URL below the hostname. See #connect.

Returns:



354
355
356
# File 'lib/jss/api_connection.rb', line 354

def server_path
  @server_path
end

#userString (readonly) Also known as: jss_user

Returns the username who's connected to the JSS API.

Returns:

  • (String)

    the username who's connected to the JSS API



337
338
339
# File 'lib/jss/api_connection.rb', line 337

def user
  @user
end

Instance Method Details

#all(class_name, refresh = false, only: nil) ⇒ Array

Deprecated.

please use the .all class method of the desired class

Call one of the 'all*' methods on a JSS::APIObject subclass using this APIConnection.

Parameters:

  • class_name (String, Symbol)

    The name of a JSS::APIObject subclass see JSS.api_object_class

  • refresh (Boolean) (defaults to: false)

    Should the data be re-read from the API?

  • only (String, Symbol) (defaults to: nil)

    Limit the output to subset or data. All APIObject subclasses can take :ids or :names, which calls the .all_ids and .all_names methods. Some subclasses can take other options, e.g. MobileDevice can take :udids

Returns:

  • (Array)

    The list of items for the class

Raises:

  • (ArgumentError)


715
716
717
718
719
720
721
722
723
# File 'lib/jss/api_connection.rb', line 715

def all(class_name, refresh = false, only: nil)
  the_class = JSS.api_object_class(class_name)
  list_method = only ? :"all_#{only}" : :all

  raise ArgumentError, "Unknown identifier: #{only} for #{the_class}" unless
    the_class.respond_to? list_method

  the_class.send list_method, refresh, api: self
end

#computer_application_usage(ident, start_date, end_date = nil) ⇒ Object

Deprecated.

Please use JSS::Computer.application_usage

Call Computer.application_usage q.v., passing this API connection



856
857
858
# File 'lib/jss/api_connection.rb', line 856

def computer_application_usage(ident, start_date, end_date = nil)
  JSS::Computer.application_usage ident, start_date, end_date, api: self
end

#computer_checkin_settingsObject

Deprecated.

Please use JSS::Computer.checkin_settings

Call Computer.checkin_settings q.v., passing this API connection



840
841
842
# File 'lib/jss/api_connection.rb', line 840

def computer_checkin_settings
  JSS::Computer.checkin_settings api: self
end

#computer_history(ident, subset: nil) ⇒ Object

Deprecated.

Please use JSS::Computer.management_history or its convenience methods. @see JSS::ManagementHistory

Call Computer.history q.v., passing this API connection



875
876
877
# File 'lib/jss/api_connection.rb', line 875

def computer_history(ident, subset: nil)
  JSS::Computer.history ident, subset, api: self
end

#computer_inventory_collection_settingsObject

Deprecated.

Please use JSS::Computer.inventory_collection_settings

Call Computer.inventory_collection_settings q.v., passing this API connection



848
849
850
# File 'lib/jss/api_connection.rb', line 848

def computer_inventory_collection_settings
  JSS::Computer.inventory_collection_settings api: self
end

#computer_management_data(ident, subset: nil, only: nil) ⇒ Object

Deprecated.

Please use JSS::Computer.management_data

Call Computer.management_data q.v., passing this API connection



865
866
867
# File 'lib/jss/api_connection.rb', line 865

def computer_management_data(ident, subset: nil, only: nil)
  JSS::Computer.management_data ident, subset: subset, only: only, api: self
end

#connect(args = {}) ⇒ true

Connect to the JSS Classic API.

Parameters:

  • args (Hash) (defaults to: {})

    the keyed arguments for connection.

Options Hash (args):

  • :server (String)

    the hostname of the JSS API server, required if not defined in JSS::CONFIG

  • :server_path (String)

    If your JSS is not at the root of the server, e.g. if it's at

    https://myjss.myserver.edu:8443/dev_mgmt/jssweb
    

    rather than

    https://myjss.myserver.edu:8443/
    

    then use this parameter to specify the path below the root e.g:

    server_path: 'dev_mgmt/jssweb'
    
  • :port (Integer)

    the port number to connect with, defaults to 8443

  • :use_ssl (Boolean)

    should the connection be made over SSL? Defaults to true.

  • :verify_cert (Boolean)

    should HTTPS SSL certificates be verified. Defaults to true. If your connection raises RestClient::SSLCertificateNotVerified, and you don't care about the validity of the SSL cert. just set this explicitly to false.

  • :user (String)

    a JSS user who has API privs, required if not defined in JSS::CONFIG

  • :pw (String, Symbol)

    Required, the password for that user, or :prompt, or :stdin If :prompt, the user is promted on the commandline to enter the password for the :user. If :stdin#, the password is read from a line of std in represented by the digit at #, so :stdin3 reads the passwd from the third line of standard input. defaults to line 1, if no digit is supplied. see JSS.stdin

  • :open_timeout (Integer)

    the number of seconds to wait for an initial response, defaults to 60

  • :timeout (Integer)

    the number of seconds before an API call times out, defaults to 60

Returns:

  • (true)


473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
# File 'lib/jss/api_connection.rb', line 473

def connect(args = {})
  # new connections always get new caches
  flushcache

  args[:no_port_specified] = args[:port].to_s.empty?
  args = apply_connection_defaults args

  # ensure an integer
  args[:port] &&= args[:port].to_i

  # confirm we know basics
  verify_basic_args args

  # parse our ssl situation
  verify_ssl args

  @user = args[:user]

  @rest_url = build_rest_url args

  # figure out :password from :pw
  args[:password] = acquire_password args

  # heres our connection
  @cnx = RestClient::Resource.new(@rest_url.to_s, args)

  verify_server_version

  @name = "#{@user}@#{@server_host}:#{@port}" if @name.nil? || @name == :disconnected
  @connected ? hostname : nil
end

#delete_rsrc(rsrc, xml = nil) ⇒ String

Delete a resource from the JSS

Parameters:

  • rsrc (String)

    the resource to create, the URL part after 'JSSResource/'

Returns:

  • (String)

    the xml response from the server.



633
634
635
636
637
638
639
640
641
642
643
644
645
# File 'lib/jss/api_connection.rb', line 633

def delete_rsrc(rsrc, xml = nil)
  validate_connected
  raise MissingDataError, 'Missing :rsrc' if rsrc.nil?

  # payload?
  return delete_with_payload rsrc, xml if xml

  # delete the resource
  @last_http_response = @cnx[rsrc].delete
  @last_http_response.body
rescue RestClient::ExceptionWithResponse => e
  handle_http_error e
end

#disconnectvoid

This method returns an undefined value.

With a REST connection, there isn't any real “connection” to disconnect from So to disconnect, we just unset all our credentials.



538
539
540
541
542
543
544
# File 'lib/jss/api_connection.rb', line 538

def disconnect
  @user = nil
  @rest_url = nil
  @server_host = nil
  @cnx = nil
  @connected = false
end

#exist?(class_name, identifier, refresh = false) ⇒ Boolean

Deprecated.

please use the .exist class method of the desired class

Call the 'exist?' method on a JSS::APIObject subclass using this APIConnection. See JSS::APIObject.exist?

Parameters:

  • class_name (String, Symbol)

    The name of a JSS::APIObject subclass see JSS.api_object_class

  • identifier (String, Symbol)

    the value to which the ids should be mapped

  • refresh (Boolean) (defaults to: false)

    Should the data be re-read from the API?

Returns:

  • (Boolean)

    Is there an object of this class in the JSS matching this indentifier?



782
783
784
# File 'lib/jss/api_connection.rb', line 782

def exist?(class_name, identifier, refresh = false)
  !valid_id(class_name, identifier, refresh).nil?
end

#fetch(class_name, arg) ⇒ APIObject

Deprecated.

Please use the .fetch class method of the desired class

Retrieve an object of a given class from the API See JSS::APIObject.fetch

Parameters:

Returns:

  • (APIObject)

    The ruby-instance of the object.



814
815
816
817
# File 'lib/jss/api_connection.rb', line 814

def fetch(class_name, arg)
  the_class = JSS.api_object_class(class_name)
  the_class.fetch arg, api: self
end

#flushcache(key = nil) ⇒ void

This method returns an undefined value.

Empty all cached lists from this connection then run garbage collection to clear any available memory

If an APIObject Subclass's RSRC_LIST_KEY is specified, only the caches for that class are flushed (e.g. :computers, :comptuer_groups)

NOTE if you've referenced objects in these caches, those objects won't be removed from memory, but all cached data will be recached as needed.

Parameters:

  • key (Symbol, Class) (defaults to: nil)

    Flush only the caches for the given RSRC_LIST_KEY. or the EAdef cache for the given extendable class. If nil (the default) flushes all caches



993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
# File 'lib/jss/api_connection.rb', line 993

def flushcache(key = nil)
  if EXTENDABLE_CLASSES.include? key
    @ext_attr_definition_cache[key] = {}
  elsif key
    map_key_pfx = "#{key}_map_"
    @object_list_cache.delete_if do |cache_key, _cache|
      cache_key == key || cache_key.to_s.start_with?(map_key_pfx)
    end
    @ext_attr_definition_cache
  else
    @object_list_cache = {}
    @ext_attr_definition_cache = {}
  end

  GC.start
end

#get_rsrc(rsrc, format = :json, raw_json: false) ⇒ Hash, String

Get an arbitrary JSS resource

The first argument is the resource to get (the part of the API url after the 'JSSResource/' ) The resource must be properly URL escaped beforehand. Note: URL.encode is deprecated, use CGI.escape

By default we get the data in JSON, and parse it into a ruby Hash with symbolized Hash keys.

If the second parameter is :xml then the XML version is retrieved and returned as a String.

To get the raw JSON string as it comes from the API, pass raw_json: true

Parameters:

  • rsrc (String)

    the resource to get (the part of the API url after the 'JSSResource/' )

  • format (Symbol) (defaults to: :json)

    either ;json or :xml If the second argument is :xml, the XML data is returned as a String.

  • raw_json (Boolean) (defaults to: false)

    When GETting JSON, return the raw unparsed string (the XML is always returned as a raw string)

Returns:

Raises:



571
572
573
574
575
576
577
578
579
580
581
582
583
# File 'lib/jss/api_connection.rb', line 571

def get_rsrc(rsrc, format = :json, raw_json: false)
  validate_connected
  raise JSS::InvalidDataError, 'format must be :json or :xml' unless GET_FORMATS.include? format

  begin
    @last_http_response = @cnx[rsrc].get(accept: format)
    return JSON.parse(@last_http_response.body, symbolize_names: true) if format == :json && !raw_json

    @last_http_response.body
  rescue RestClient::ExceptionWithResponse => e
    handle_http_error e
  end
end

#hostnameString Also known as: host

The server to which we are connected, or will try connecting to if none is specified with the call to #connect

Returns:

  • (String)

    the hostname of the server



687
688
689
690
691
692
# File 'lib/jss/api_connection.rb', line 687

def hostname
  return @server_host if @server_host
  srvr = JSS::CONFIG.api_server_name
  srvr ||= JSS::Client.jss_server
  srvr
end

#make(class_name, **args) ⇒ APIObject

Deprecated.

Please use the .make class method of the desired class

Make a ruby instance of a not-yet-existing APIObject of the given class See JSS::APIObject.make

Parameters:

Returns:

  • (APIObject)

    The un-created ruby-instance of the object.



830
831
832
833
834
# File 'lib/jss/api_connection.rb', line 830

def make(class_name, **args)
  the_class = JSS.api_object_class(class_name)
  args[:api] = self
  the_class.make args
end

#map_all_ids(class_name, refresh = false, to: nil) ⇒ Hash

Deprecated.

please use the .map_all_ids_to class method of the desired class

Call the 'map_all_ids_to' method on a JSS::APIObject subclass using this APIConnection.

Parameters:

  • class_name (String, Symbol)

    The name of a JSS::APIObject subclass see JSS.api_object_class

  • refresh (Boolean) (defaults to: false)

    Should the data be re-read from the API?

  • to (String, Symbol) (defaults to: nil)

    the value to which the ids should be mapped

Returns:

  • (Hash)

    The ids for the class keyed to the requested identifier



740
741
742
743
744
# File 'lib/jss/api_connection.rb', line 740

def map_all_ids(class_name, refresh = false, to: nil)
  raise "'to:' value must be provided for mapping ids." unless to
  the_class = JSS.api_object_class(class_name)
  the_class.map_all_ids_to to, refresh, api: self
end

#master_distribution_point(refresh = false) ⇒ JSS::DistributionPoint

Get the DistributionPoint instance for the master distribution point in the JSS. If there's only one in the JSS, return it even if not marked as master.

Parameters:

  • refresh (Boolean) (defaults to: false)

    re-read from the API?

Returns:

Raises:



898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
# File 'lib/jss/api_connection.rb', line 898

def master_distribution_point(refresh = false)
  @master_distribution_point = nil if refresh
  return @master_distribution_point if @master_distribution_point

  JSS::DistributionPoint.all_ids.each do |dp_id|
    dp = JSS::DistributionPoint.fetch id: dp_id, api: self
    if dp.master?
      @master_distribution_point = dp
      break
    end
  end

  return @master_distribution_point if @master_distribution_point

  # If we're here, the Cloud DP might be master, but there's no
  # access to it in the API :/
  raise JSS::NoSuchItemError, 'No Master Distribtion Point defined. It could be the Cloud Dist Point, which is not available in the classic API'
end

#match(class_name, term) ⇒ Array<Hash>

Deprecated.

Please use the .match class method of the desired class

Call Matchable#match for the given class.

See Matchable#match

Parameters:

Returns:

Raises:



797
798
799
800
801
# File 'lib/jss/api_connection.rb', line 797

def match(class_name, term)
  the_class = JSS.api_object_class(class_name)
  raise JSS::UnsupportedError, "Class #{the_class} is not matchable" unless the_class.respond_to? :match
  the_class.match term, api: self
end

#my_distribution_point(refresh = false) ⇒ JSS::DistributionPoint

Get the DistributionPoint instance for the machine running this code, based on its IP address. If none is defined for this IP address, use the result of master_distribution_point

Parameters:

  • refresh (Boolean) (defaults to: false)

    should the distribution point be re-queried?

Returns:



925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
# File 'lib/jss/api_connection.rb', line 925

def my_distribution_point(refresh = false)
  @my_distribution_point = nil if refresh
  return @my_distribution_point if @my_distribution_point

  my_net_seg_id = my_network_segments[0]

  if my_net_seg_id
    my_net_seg = JSS::NetworkSegment.fetch(id: my_net_seg_id, api: self)
    my_dp_name = my_net_seg.distribution_point
    @my_distribution_point = JSS::DistributionPoint.fetch(name: my_dp_name) if my_dp_name
  end # if my_net_seg_id

  @my_distribution_point ||= master_distribution_point refresh
  @my_distribution_point
end

#my_network_segmentsObject

Deprecated.

See Also:

  • JSS::APIConnection.{JSS{JSS::NetworkSegment{JSS::NetworkSegment.my_network_segments}


961
962
963
# File 'lib/jss/api_connection.rb', line 961

def my_network_segments
  network_segments_for_ip JSS::Client.my_ip_address
end

#network_ranges(refresh = false) ⇒ Object

Deprecated.

See Also:

  • JSS::APIConnection.{JSS{JSS::NetworkSegment{JSS::NetworkSegment.network_ranges}


945
946
947
# File 'lib/jss/api_connection.rb', line 945

def network_ranges(refresh = false)
  JSS::NetworkSegment.network_ranges refresh, api: self
end

#network_segments_for_ip(ip, refresh = false) ⇒ Object

Deprecated.

See Also:

  • JSS::APIConnection.{JSS{JSS::NetworkSegment{JSS::NetworkSegment.network_segments_for_ip}


953
954
955
# File 'lib/jss/api_connection.rb', line 953

def network_segments_for_ip(ip, refresh = false)
  JSS::NetworkSegment.network_segments_for_ip ip, refresh, api: self
end

#open_timeout=(timeout) ⇒ void

This method returns an undefined value.

Reset the open-connection timeout for the rest connection

Parameters:

  • timeout (Integer)

    the new timeout in seconds



529
530
531
# File 'lib/jss/api_connection.rb', line 529

def open_timeout=(timeout)
  @cnx.options[:open_timeout] = timeout
end

#post_rsrc(rsrc, xml = '') ⇒ String

Create a new JSS resource

Parameters:

  • rsrc (String)

    the API resource being created, the URL part after 'JSSResource/'

  • xml (String) (defaults to: '')

    the xml specifying the new object.

Returns:

  • (String)

    the xml response from the server.



614
615
616
617
618
619
620
621
622
623
624
625
# File 'lib/jss/api_connection.rb', line 614

def post_rsrc(rsrc, xml = '')
  validate_connected

  # convert CRs & to &#13;
  xml.gsub!(/\r/, '&#13;') if xml

  # send the data
  @last_http_response = @cnx[rsrc].post(xml, content_type: 'text/xml', accept: :json)
  @last_http_response.body
rescue RestClient::ExceptionWithResponse => e
  handle_http_error e
end

#pretty_print_instance_variablesArray

Remove the various cached data from the instance_variables used to create pretty-print (pp) output.

Returns:

  • (Array)

    the desired instance_variables



1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
# File 'lib/jss/api_connection.rb', line 1016

def pretty_print_instance_variables
  vars = instance_variables.sort
  vars.delete :@object_list_cache
  vars.delete :@last_http_response
  vars.delete :@network_ranges
  vars.delete :@my_distribution_point
  vars.delete :@master_distribution_point
  vars.delete :@ext_attr_definition_cache
  vars
end

#put_rsrc(rsrc, xml) ⇒ String

Update an existing JSS resource

Parameters:

  • rsrc (String)

    the API resource being changed, the URL part after 'JSSResource/'

  • xml (String)

    the xml specifying the changes.

Returns:

  • (String)

    the xml response from the server.



593
594
595
596
597
598
599
600
601
602
603
604
# File 'lib/jss/api_connection.rb', line 593

def put_rsrc(rsrc, xml)
  validate_connected

  # convert CRs & to &#13;
  xml.gsub!(/\r/, '&#13;')

  # send the data
  @last_http_response = @cnx[rsrc].put(xml, content_type: 'text/xml')
  @last_http_response.body
rescue RestClient::ExceptionWithResponse => e
  handle_http_error e
end

#send_computer_mdm_command(targets, command, passcode = nil) ⇒ Object

Deprecated.

Please use JSS::Computer.send_mdm_command or its convenience methods. @see JSS::MDM

Call Computer.send_mdm_command q.v., passing this API connection



885
886
887
888
# File 'lib/jss/api_connection.rb', line 885

def send_computer_mdm_command(targets, command, passcode = nil)
  opts = passcode ? { passcode: passcode } : {}
  JSS::Computer.send_mdm_command targets, command, opts: opts, api: self
end

#send_mobiledevice_mdm_command(targets, command, data = {}) ⇒ Object

Deprecated.

Please use JSS::MobileDevice.send_mdm_command or its convenience methods. @see JSS::MDM

Send an MDM command to one or more mobile devices managed by this JSS

see MobileDevice.send_mdm_command



973
974
975
# File 'lib/jss/api_connection.rb', line 973

def send_mobiledevice_mdm_command(targets, command, data = {})
  JSS::MobileDevice.send_mdm_command(targets, command, opts: data, api: self)
end

#timeout=(timeout) ⇒ void

This method returns an undefined value.

Reset the response timeout for the rest connection

Parameters:

  • timeout (Integer)

    the new timeout in seconds



519
520
521
# File 'lib/jss/api_connection.rb', line 519

def timeout=(timeout)
  @cnx.options[:timeout] = timeout
end

#to_sString

A useful string about this connection

Returns:



509
510
511
# File 'lib/jss/api_connection.rb', line 509

def to_s
  @connected ? "Using #{@rest_url} as user #{@user}" : 'not connected'
end

#valid_id(class_name, identifier, refresh = true) ⇒ Integer?

Deprecated.

please use the .valid_id class method of the desired class

Call the 'valid_id' method on a JSS::APIObject subclass using this APIConnection. See JSS::APIObject.valid_id

Parameters:

  • class_name (String, Symbol)

    The name of a JSS::APIObject subclass, see JSS.api_object_class

  • identifier (String, Symbol)

    the value to which the ids should be mapped

  • refresh (Boolean) (defaults to: true)

    Should the data be re-read from the API?

Returns:

  • (Integer, nil)

    the id of the matching object of the class, or nil if there isn't one



762
763
764
765
# File 'lib/jss/api_connection.rb', line 762

def valid_id(class_name, identifier, refresh = true)
  the_class = JSS.api_object_class(class_name)
  the_class.valid_id identifier, refresh, api: self
end

#valid_server?(server, port = SSL_PORT) ⇒ Boolean

Test that a given hostname & port is a JSS API server

Parameters:

  • server (String)

    The hostname to test,

  • port (Integer) (defaults to: SSL_PORT)

    The port to try connecting on

Returns:

  • (Boolean)

    does the server host a JSS API?



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
# File 'lib/jss/api_connection.rb', line 655

def valid_server?(server, port = SSL_PORT)
  # cheating by shelling out to curl, because getting open-uri, or even net/http to use
  # ssl_options like :OP_NO_SSLv2 and :OP_NO_SSLv3 will take time to figure out..
  return true if `/usr/bin/curl -s 'https://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
  return true if `/usr/bin/curl -s 'http://#{server}:#{port}/#{TEST_PATH}'`.include? TEST_CONTENT
  false

  # # try ssl first
  # # NOTE:  doesn't work if we can't disallow SSLv3 or force TLSv1
  # # See cheat above.
  # begin
  #   return true if open("https://#{server}:#{port}/#{TEST_PATH}", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read.include? TEST_CONTENT
  #
  # rescue
  #   # then regular http
  #   begin
  #     return true if open("http://#{server}:#{port}/#{TEST_PATH}").read.include? TEST_CONTENT
  #   rescue
  #     # any errors = no API
  #     return false
  #   end # begin
  # end # begin
  # # if we're here, no API
  # false
end