Class: JSS::APIConnection
- Defined in:
- lib/jss/api_connection.rb,
lib/jss.rb
Overview
Instances of this class represent an API connection to the JSS.
JSS::APIConnection objects are REST connections to JSS APIs and contain (once connected) all the data needed for communication with that API, including login credentials, URLs, and so on.
The default connection
When ruby-jss is loaded, a not-yet-connected default instance of JSS::APIConnection is created, activated, and stored internally. Before using it you must call its #connect method, passing in appropriate connection details and credentials.
Here’s how to use the default connection:
require 'ruby-jss'
JSS.api.connect server: 'server.address.edu', user: 'jss-api-user', pw: :prompt
(see #connect for all the connection options)
If you’re only going to be connecting to one server, or one at a time, using the default connection is preferred. You can call its #connect method at any time to change servers or connection credentials.
Multiple connections & the currently active connection
Sometimes you need to connect simultaneously to more than one JSS. or to the same JSS with different credentials.
While multiple connection instances can be created, only one is active at a time and all API access happens through the currently active connection. (See below for how to switch between different connections)
The currently-active connection instance is available from the ‘JSS.api` method.
Making new connection instances
New connections can be created and stored in a variable using the standard ruby ‘new’ method.
If you provide connection details when calling ‘new’, they will be passed to the #connect method immediately.
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'.
Switching between multiple connections
Only one connection is active at a time and the currently active one is returned when you call ‘JSS.api` or its aliases `JSS.api_connection` or `JSS.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
NOTE: The APIObject list methods (e.g. JSS::Computer.all) cache the list data from the API the first time they are used, and after that when their ‘refresh’ option is true.
Those caches are stored in the APIConnection instance through- which they were read, so they won’t be incorrect when you switch connections.
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'
Low-level use of APIConnection instances.
For most uses, creating, activating, and connecting APIConnection instances 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 SSL port
8443
- 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 As of Casper 9.61 we can’t use SSL, must use TLS, since SSLv3 was susceptible to poodles. NOTE - this requires rest-client v 1.7.0 or higher which requires mime-types 2.0 or higher, which requires ruby 1.9.2 or higher! That means that support for ruby 1.8.7 stops with Casper 9.6
'TLSv1'.freeze
Instance Attribute Summary collapse
-
#cnx ⇒ RestClient::Resource
readonly
The underlying connection resource.
-
#connected ⇒ Boolean
(also: #connected?)
readonly
Are we connected right now?.
-
#jss_user ⇒ String
readonly
The username who’s connected to the JSS API.
-
#last_http_response ⇒ RestClient::Response
readonly
The response from the most recent API call.
-
#name ⇒ String, Symbol
readonly
connection during initialization, using the name: parameter.
-
#object_list_cache ⇒ Hash
readonly
This Hash holds the most recent API query for a list of all items in any APIObject subclass, keyed by the subclass’s RSRC_LIST_KEY.
-
#port ⇒ Integer
readonly
The port used for the connection.
-
#protocol ⇒ String
readonly
The protocol being used: http or https.
-
#rest_url ⇒ String
readonly
The base URL to to the current REST API.
-
#server ⇒ JSS::Server
readonly
The details of the JSS to which we’re connected.
-
#server_host ⇒ String
readonly
The hostname of the JSS to which we’re connected.
Instance Method Summary collapse
-
#connect(args = {}) ⇒ true
Connect to the JSS API.
-
#delete_rsrc(rsrc, xml = nil) ⇒ String
Delete a resource from the JSS.
-
#disconnect ⇒ void
With a REST connection, there isn’t any real “connection” to disconnect from So to disconnect, we just unset all our credentials.
-
#get_rsrc(rsrc, format = :json) ⇒ Hash, String
Get an arbitrary JSS resource.
-
#hostname ⇒ String
(also: #host)
The server to which we are connected, or will try connecting to if none is specified with the call to #connect.
-
#initialize(args = {}) ⇒ APIConnection
constructor
If name: is provided (as a String or Symbol) that will be stored as the APIConnection’s name attribute.
-
#open_timeout=(timeout) ⇒ void
Reset the open-connection timeout for the rest connection.
-
#post_rsrc(rsrc, xml = '') ⇒ String
Create a new JSS resource.
-
#put_rsrc(rsrc, xml) ⇒ String
Change an existing JSS resource.
-
#timeout=(timeout) ⇒ void
Reset the response timeout for the rest connection.
-
#to_s ⇒ String
A useful string about this connection.
-
#valid_server?(server, port = SSL_PORT) ⇒ Boolean
Test that a given hostname & port is a JSS API server.
Constructor Details
#initialize(args = {}) ⇒ APIConnection
260 261 262 263 264 265 266 |
# File 'lib/jss/api_connection.rb', line 260 def initialize(args = {}) @name = args.delete :name @name ||= :disconnected @connected = false @object_list_cache = {} connect args unless args.empty? end |
Instance Attribute Details
#cnx ⇒ RestClient::Resource (readonly)
Returns the underlying connection resource.
208 209 210 |
# File 'lib/jss/api_connection.rb', line 208 def cnx @cnx end |
#connected ⇒ Boolean (readonly) Also known as: connected?
Returns are we connected right now?.
211 212 213 |
# File 'lib/jss/api_connection.rb', line 211 def connected @connected end |
#jss_user ⇒ String (readonly)
Returns the username who’s connected to the JSS API.
205 206 207 |
# File 'lib/jss/api_connection.rb', line 205 def jss_user @jss_user end |
#last_http_response ⇒ RestClient::Response (readonly)
Returns The response from the most recent API call.
226 227 228 |
# File 'lib/jss/api_connection.rb', line 226 def last_http_response @last_http_response end |
#name ⇒ String, Symbol (readonly)
connection during initialization, using the name: parameter. defaults to user@hostname:port
234 235 236 |
# File 'lib/jss/api_connection.rb', line 234 def name @name end |
#object_list_cache ⇒ Hash (readonly)
This Hash holds the most recent API query for a list of all items in any APIObject subclass, keyed by the subclass’s RSRC_LIST_KEY. See the APIObject.all class method.
When the APIObject.all method is 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.
245 246 247 |
# File 'lib/jss/api_connection.rb', line 245 def object_list_cache @object_list_cache end |
#port ⇒ Integer (readonly)
Returns the port used for the connection.
220 221 222 |
# File 'lib/jss/api_connection.rb', line 220 def port @port end |
#protocol ⇒ String (readonly)
Returns the protocol being used: http or https.
223 224 225 |
# File 'lib/jss/api_connection.rb', line 223 def protocol @protocol end |
#rest_url ⇒ String (readonly)
Returns The base URL to to the current REST API.
229 230 231 |
# File 'lib/jss/api_connection.rb', line 229 def rest_url @rest_url end |
#server ⇒ JSS::Server (readonly)
Returns the details of the JSS to which we’re connected.
214 215 216 |
# File 'lib/jss/api_connection.rb', line 214 def server @server end |
#server_host ⇒ String (readonly)
Returns the hostname of the JSS to which we’re connected.
217 218 219 |
# File 'lib/jss/api_connection.rb', line 217 def server_host @server_host end |
Instance Method Details
#connect(args = {}) ⇒ true
Connect to the JSS API.
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/jss/api_connection.rb', line 299 def connect(args = {}) args = apply_connection_defaults args verify_basic_args args @jss_user = args[:user] @rest_url = build_rest_url args # figure out :verify_ssl from :verify_cert args[:verify_ssl] = verify_ssl 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 = "#{@jss_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
433 434 435 436 437 438 439 440 441 442 |
# File 'lib/jss/api_connection.rb', line 433 def delete_rsrc(rsrc, xml = nil) raise JSS::InvalidConnectionError, 'Not Connected. Use JSS.api_connection.connect first.' unless @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 end |
#disconnect ⇒ void
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.
354 355 356 357 358 359 360 |
# File 'lib/jss/api_connection.rb', line 354 def disconnect @jss_user = nil @rest_url = nil @server_host = nil @cnx = nil @connected = false end |
#get_rsrc(rsrc, format = :json) ⇒ Hash, String
Get an arbitrary JSS resource
The first argument is the resource to get (the part of the API url after the ‘JSSResource/’ )
By default we get the data in JSON, and parse it into a ruby data structure (arrays, hashes, strings, etc) with symbolized Hash keys.
379 380 381 382 383 384 385 |
# File 'lib/jss/api_connection.rb', line 379 def get_rsrc(rsrc, format = :json) # puts object_id raise JSS::InvalidConnectionError, 'Not Connected. Use JSS.api.connect first.' unless @connected rsrc = URI.encode rsrc @last_http_response = @cnx[rsrc].get(accept: format) return JSON.parse(@last_http_response, symbolize_names: true) if format == :json end |
#hostname ⇒ String 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
484 485 486 487 488 489 |
# File 'lib/jss/api_connection.rb', line 484 def hostname return @server_host if @server_host srvr = JSS::CONFIG.api_server_name srvr ||= JSS::Client.jss_server srvr end |
#open_timeout=(timeout) ⇒ void
This method returns an undefined value.
Reset the open-connection timeout for the rest connection
345 346 347 |
# File 'lib/jss/api_connection.rb', line 345 def open_timeout=(timeout) @cnx.[:open_timeout] = timeout end |
#post_rsrc(rsrc, xml = '') ⇒ String
Create a new JSS resource
415 416 417 418 419 420 421 422 423 424 425 |
# File 'lib/jss/api_connection.rb', line 415 def post_rsrc(rsrc, xml = '') raise JSS::InvalidConnectionError, 'Not Connected. Use JSS.api_connection.connect first.' unless @connected # convert CRs & to xml.gsub!(/\r/, ' ') if xml # send the data @last_http_response = @cnx[rsrc].post xml, content_type: 'text/xml', accept: :json rescue RestClient::Conflict => exception raise_conflict_error(exception) end |
#put_rsrc(rsrc, xml) ⇒ String
Change an existing JSS resource
395 396 397 398 399 400 401 402 403 404 405 |
# File 'lib/jss/api_connection.rb', line 395 def put_rsrc(rsrc, xml) raise JSS::InvalidConnectionError, 'Not Connected. Use JSS.api_connection.connect first.' unless @connected # convert CRs & to xml.gsub!(/\r/, ' ') # send the data @last_http_response = @cnx[rsrc].put(xml, content_type: 'text/xml') rescue RestClient::Conflict => exception raise_conflict_error(exception) end |
#timeout=(timeout) ⇒ void
This method returns an undefined value.
Reset the response timeout for the rest connection
335 336 337 |
# File 'lib/jss/api_connection.rb', line 335 def timeout=(timeout) @cnx.[:timeout] = timeout end |
#to_s ⇒ String
A useful string about this connection
325 326 327 |
# File 'lib/jss/api_connection.rb', line 325 def to_s @connected ? "Using #{@rest_url} as user #{@jss_user}" : 'not connected' end |
#valid_server?(server, port = SSL_PORT) ⇒ Boolean
Test that a given hostname & port is a JSS API server
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 |
# File 'lib/jss/api_connection.rb', line 452 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 |