ruby-jss 0.9.2 → 0.10.0a1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-jss might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGES.md +13 -1
- data/README.md +7 -7
- data/bin/cgrouper +6 -6
- data/bin/netseg-update +1 -1
- data/lib/jss.rb +1 -0
- data/lib/jss/api_connection.rb +428 -44
- data/lib/jss/api_object.rb +119 -68
- data/lib/jss/api_object/account.rb +12 -12
- data/lib/jss/api_object/advanced_search.rb +12 -12
- data/lib/jss/api_object/categorizable.rb +4 -4
- data/lib/jss/api_object/category.rb +2 -2
- data/lib/jss/api_object/computer.rb +111 -58
- data/lib/jss/api_object/computer_invitation.rb +2 -2
- data/lib/jss/api_object/creatable.rb +19 -8
- data/lib/jss/api_object/criteriable/criteria.rb +8 -8
- data/lib/jss/api_object/distribution_point.rb +14 -48
- data/lib/jss/api_object/extension_attribute.rb +14 -11
- data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +18 -18
- data/lib/jss/api_object/group.rb +7 -7
- data/lib/jss/api_object/ldap_server.rb +51 -60
- data/lib/jss/api_object/locatable.rb +2 -2
- data/lib/jss/api_object/matchable.rb +8 -9
- data/lib/jss/api_object/mobile_device.rb +61 -59
- data/lib/jss/api_object/mobile_device_application.rb +3 -3
- data/lib/jss/api_object/network_segment.rb +24 -19
- data/lib/jss/api_object/package.rb +6 -6
- data/lib/jss/api_object/peripheral.rb +5 -5
- data/lib/jss/api_object/policy.rb +5 -5
- data/lib/jss/api_object/restricted_software.rb +4 -4
- data/lib/jss/api_object/scopable/scope.rb +3 -3
- data/lib/jss/api_object/script.rb +1 -1
- data/lib/jss/api_object/self_servable.rb +3 -3
- data/lib/jss/api_object/self_servable/icon.rb +7 -2
- data/lib/jss/api_object/updatable.rb +2 -2
- data/lib/jss/api_object/uploadable.rb +1 -1
- data/lib/jss/api_object/user.rb +2 -2
- data/lib/jss/composer.rb +37 -10
- data/lib/jss/ruby_extensions/string.rb +51 -42
- data/lib/jss/server.rb +27 -6
- data/lib/jss/utility.rb +44 -0
- data/lib/jss/validate.rb +85 -0
- data/lib/jss/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3796577e296c595860954645bc0a2596f14245ff
|
4
|
+
data.tar.gz: 1ef961ef3629054e53f04415999bb02525c6973a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 449baa374a0229a15335eb9d96e5815fac87537176d7d9abad9cc9e3be39538b11cc575ff2a6651ba5e820e6f9724339fb2e32720f4fa48b431440cc3e32c873
|
7
|
+
data.tar.gz: 9c1f058392f666a6bc812beadb9d36891ab6e49df7f4c47e3ecce7faa896e35108ed2a97c32bfdffa5da367f88ff7832f94c01f4ca59bfc4152f0e6b5345f3d0
|
data/CHANGES.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
# Change History
|
2
2
|
|
3
|
-
## v0.9.
|
3
|
+
## v0.9.3 2017-08-08
|
4
|
+
|
5
|
+
- Add: JSS::Computer instance now allow you to modify mac_address, alt_mac_address, udid, and serial_number.
|
6
|
+
Note: even tho the WebUI doesn't allow editing of the serial_number, the API does and doing so can be useful
|
7
|
+
for dealing with duplicate SN's when a new logic board with a new udid creates a new computer entry.
|
8
|
+
- Add: JSS::Validate module, to consoliday generic data-validation methods. Methods will be moved to it from
|
9
|
+
other places over time.
|
10
|
+
|
11
|
+
## v0.9.2 2017-07-25
|
12
|
+
|
13
|
+
- Fix: parsing of JSS versions > 9.99
|
14
|
+
|
15
|
+
## v0.9.0 2017-07-17
|
4
16
|
|
5
17
|
- Add: JSS::MobileDevice.all_apple_tvs class method
|
6
18
|
- Add: JSS::MobileDevice.management_history method, and related methods in instances
|
data/README.md
CHANGED
@@ -99,11 +99,11 @@ ns.save
|
|
99
99
|
Before you can work with JSS Objects via the API, you have to connect to it.
|
100
100
|
|
101
101
|
The constant {JSS::API} contains the connection to the API (a singleton instance of {JSS::APIConnection}). When the JSS Module is first loaded, it isn't
|
102
|
-
connected. To remedy that, use JSS.
|
102
|
+
connected. To remedy that, use JSS.api.connect, passing it values for the connection. In this example, those values are stored
|
103
103
|
in the local variables jss_user, jss_user_pw, and jss_server_hostname, and others are left as default.
|
104
104
|
|
105
105
|
```ruby
|
106
|
-
JSS.
|
106
|
+
JSS.api.connect user: jss_user, pw: jss_user_pw, server: jss_server_hostname
|
107
107
|
```
|
108
108
|
|
109
109
|
Make sure the user has privileges in the JSS to do things with desired Objects.
|
@@ -301,7 +301,7 @@ Other useful classes:
|
|
301
301
|
|
302
302
|
The {JSS::Configuration} singleton class is used to read, write, and use site-specific defaults for the JSS module. When the Module is required, the single instance of {JSS::Configuration} is created and stored in the constant {JSS::CONFIG}. At that time the system-wide file /etc/jss_gem.conf is examined if it exists, and the items in it are loaded into the attributes of {JSS::CONFIG}. The user-specific file ~/.jss_gem.conf then is examined if it exists, and any items defined there will override those values from the system-wide file.
|
303
303
|
|
304
|
-
The values defined in those files are used as defaults throughout the module. Currently, those values are only related to establishing the API connection. For example, if a server name is defined, then a :server does not have to be specified when calling {JSS::API#connect}. Values provided explicitly when calling JSS.
|
304
|
+
The values defined in those files are used as defaults throughout the module. Currently, those values are only related to establishing the API connection. For example, if a server name is defined, then a :server does not have to be specified when calling {JSS::API#connect}. Values provided explicitly when calling JSS.api.connect will override the config values.
|
305
305
|
|
306
306
|
While the {JSS::Configuration} class provides methods for changing the values, saving the files, and re-reading them, or reading an arbitrary file, the files are text files with a simple format, and can be created by any means desired. The file format is one attribute per line, thus:
|
307
307
|
|
@@ -326,11 +326,11 @@ api_username: readonly-api-user
|
|
326
326
|
api_verify_cert: false
|
327
327
|
```
|
328
328
|
|
329
|
-
and then any calls to JSS.
|
329
|
+
and then any calls to JSS.api.connect will assume that server and username, and won't complain about the self-signed certificate.
|
330
330
|
|
331
331
|
### Passwords
|
332
332
|
|
333
|
-
The config files don't store passwords and the {JSS::Configuration} instance doesn't work with them. You'll have to use your own methods for acquiring the password for the JSS.
|
333
|
+
The config files don't store passwords and the {JSS::Configuration} instance doesn't work with them. You'll have to use your own methods for acquiring the password for the JSS.api.connect call.
|
334
334
|
|
335
335
|
The {JSS::API#connect} method also accepts the symbols :stdin# and :prompt as values for the :pw argument, which will cause it to read the password from a line of stdin, or prompt for it in the shell.
|
336
336
|
|
@@ -340,7 +340,7 @@ Here's an example of how to use a password stored in a file:
|
|
340
340
|
|
341
341
|
```ruby
|
342
342
|
password = File.read "/path/to/secure/password/file" # read the password from a file
|
343
|
-
JSS.
|
343
|
+
JSS.api.connect pw: password # other arguments used from the config settings
|
344
344
|
```
|
345
345
|
|
346
346
|
And here's an example of how to read a password from a web server and use it.
|
@@ -348,7 +348,7 @@ And here's an example of how to read a password from a web server and use it.
|
|
348
348
|
```ruby
|
349
349
|
require 'open-uri'
|
350
350
|
password = open('https://server.org.org/path/to/password').read
|
351
|
-
JSS.
|
351
|
+
JSS.api.connect pw: password # other arguments used from the config settings
|
352
352
|
```
|
353
353
|
|
354
354
|
## BEYOND THE API
|
data/bin/cgrouper
CHANGED
@@ -2,21 +2,21 @@
|
|
2
2
|
|
3
3
|
### Copyright 2017 Pixar
|
4
4
|
|
5
|
-
###
|
5
|
+
###
|
6
6
|
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
7
7
|
### with the following modification; you may not use this file except in
|
8
8
|
### compliance with the Apache License and the following modification to it:
|
9
9
|
### Section 6. Trademarks. is deleted and replaced with:
|
10
|
-
###
|
10
|
+
###
|
11
11
|
### 6. Trademarks. This License does not grant permission to use the trade
|
12
12
|
### names, trademarks, service marks, or product names of the Licensor
|
13
13
|
### and its affiliates, except as required to comply with Section 4(c) of
|
14
14
|
### the License and to reproduce the content of the NOTICE file.
|
15
|
-
###
|
15
|
+
###
|
16
16
|
### You may obtain a copy of the Apache License at
|
17
|
-
###
|
17
|
+
###
|
18
18
|
### http://www.apache.org/licenses/LICENSE-2.0
|
19
|
-
###
|
19
|
+
###
|
20
20
|
### Unless required by applicable law or agreed to in writing, software
|
21
21
|
### distributed under the Apache License with the above modification is
|
22
22
|
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
@@ -191,7 +191,7 @@ class App
|
|
191
191
|
raise JSS::MissingDataError, "No JSS Username provided or found in the JSS gem config." unless @options.user
|
192
192
|
raise JSS::MissingDataError, "No JSS Server provided or found in the JSS gem config." unless @options.server
|
193
193
|
|
194
|
-
JSS.
|
194
|
+
JSS.api.connect( :server => @options.server,
|
195
195
|
:port => @options.port,
|
196
196
|
:verify_cert => @options.verify_cert,
|
197
197
|
:user => @options.user,
|
data/bin/netseg-update
CHANGED
data/lib/jss.rb
CHANGED
data/lib/jss/api_connection.rb
CHANGED
@@ -37,49 +37,93 @@ module JSS
|
|
37
37
|
# Classes
|
38
38
|
#####################################
|
39
39
|
|
40
|
-
# Instances of this class represent
|
40
|
+
# Instances of this class represent a REST connection to a JSS API.
|
41
41
|
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# that API, including login credentials, URLs, and so on.
|
42
|
+
# For most cases, a single connection to a single JSS is all you need, and
|
43
|
+
# this is ruby-jss's default behavior.
|
45
44
|
#
|
46
|
-
#
|
45
|
+
# If needed, multiple connections can be made and used sequentially or
|
46
|
+
# simultaneously.
|
47
|
+
#
|
48
|
+
# == Using the default connection
|
47
49
|
#
|
48
50
|
# When ruby-jss is loaded, a not-yet-connected default instance of
|
49
|
-
# JSS::APIConnection is created
|
51
|
+
# JSS::APIConnection is created and stored in the constant JSS::API.
|
52
|
+
# This connection is used as the initial 'active connection' (see below)
|
53
|
+
# so all methods that make API calls will use it by default. For most uses,
|
54
|
+
# where you're only going to be working with one connection to one JSS, the
|
55
|
+
# default connection is all you need.
|
56
|
+
#
|
50
57
|
# Before using it you must call its {#connect} method, passing in appropriate
|
51
58
|
# connection details and credentials.
|
52
59
|
#
|
53
|
-
#
|
60
|
+
# Example:
|
54
61
|
#
|
55
|
-
#
|
56
|
-
#
|
62
|
+
# require 'ruby-jss'
|
63
|
+
# JSS.api.connect server: 'server.address.edu', user: 'jss-api-user', pw: :prompt
|
64
|
+
# # (see {JSS::APIConnection#connect} for all the connection options)
|
57
65
|
#
|
58
|
-
#
|
66
|
+
# a_phone = JSS::MobileDevice.fetch id: 8743
|
59
67
|
#
|
60
|
-
#
|
61
|
-
# using the default connection is preferred. You can call its {#connect}
|
62
|
-
# method at any time to change servers or connection credentials.
|
68
|
+
# # the mobile device was fetched through the default connection
|
63
69
|
#
|
64
|
-
# == Multiple
|
70
|
+
# == Using Multiple Simultaneous Connections
|
65
71
|
#
|
66
72
|
# Sometimes you need to connect simultaneously to more than one JSS.
|
67
|
-
# or to the same JSS with different credentials.
|
73
|
+
# or to the same JSS with different credentials. ruby-jss allows you to
|
74
|
+
# create as many connections as needed, and gives you three ways to use them:
|
68
75
|
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
# (See below for how to switch between different connections)
|
76
|
+
# 1. Making a connection 'active', after which API calls go thru it
|
77
|
+
# automatically
|
72
78
|
#
|
73
|
-
#
|
74
|
-
#
|
79
|
+
# Example:
|
80
|
+
#
|
81
|
+
# a_computer = JSS::Computer.fetch id: 1234
|
82
|
+
#
|
83
|
+
# # the JSS::Computer with id 1234 is fetched from the active connection
|
84
|
+
# # and stored in the variable 'a_computer'
|
85
|
+
#
|
86
|
+
# NOTE: When ruby-jss is first loaded, the default connection (see above)
|
87
|
+
# is the active connection.
|
88
|
+
#
|
89
|
+
# 2. Passing an APIConnection instance to methods that use the API
|
90
|
+
#
|
91
|
+
# Example:
|
92
|
+
#
|
93
|
+
# a_computer = JSS::Computer.fetch id: 1234, api: production_api
|
94
|
+
#
|
95
|
+
# # the JSS::Computer with id 1234 is fetched from the connection
|
96
|
+
# # stored in the variable 'production_api'. The computer is
|
97
|
+
# # then stored in the variable 'a_computer'
|
98
|
+
#
|
99
|
+
# 3. Using the APIConnection instance itself to make API calls.
|
100
|
+
#
|
101
|
+
# Example:
|
102
|
+
#
|
103
|
+
# a_computer = production_api.fetch :Computer, id: 1234
|
104
|
+
#
|
105
|
+
# # the JSS::Computer with id 1234 is fetched from the connection
|
106
|
+
# # stored in the variable 'production_api'. The computer is
|
107
|
+
# # then stored in the variable 'a_computer'
|
108
|
+
#
|
109
|
+
# See below for more details about the ways to use multiple connections.
|
110
|
+
#
|
111
|
+
# NOTE:
|
112
|
+
# Objects retrieved or created through an APIConnection store an internal
|
113
|
+
# reference to that APIConnection and use that when they make other API
|
114
|
+
# calls, thus ensuring data consistency when using multiple connections.
|
115
|
+
#
|
116
|
+
# Similiarly, the data caches used by APIObject list methods (e.g.
|
117
|
+
# JSS::Computer.all, .all_names, and so on) are stored in the APIConnection
|
118
|
+
# instance through which they were read, so they won't be incorrect when
|
119
|
+
# you use multiple connections.
|
75
120
|
#
|
76
|
-
# == Making new
|
121
|
+
# == Making new APIConnection instances
|
77
122
|
#
|
78
|
-
# New connections can be created
|
79
|
-
# the standard ruby 'new' method.
|
123
|
+
# New connections can be created using the standard ruby 'new' method.
|
80
124
|
#
|
81
125
|
# If you provide connection details when calling 'new', they will be passed
|
82
|
-
# to the #connect method immediately.
|
126
|
+
# to the {#connect} method immediately. Otherwise you can call {#connect} later.
|
83
127
|
#
|
84
128
|
# production_api = JSS::APIConnection.new(
|
85
129
|
# name: 'prod',
|
@@ -90,28 +134,46 @@ module JSS
|
|
90
134
|
#
|
91
135
|
# # the new connection is now stored in the variable 'production_api'.
|
92
136
|
#
|
93
|
-
# ==
|
137
|
+
# == Using the 'Active' Connection
|
94
138
|
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
139
|
+
# While multiple connection instances can be created, only one at a time is
|
140
|
+
# 'the active connection' and all APIObject-based access methods in ruby-jss
|
141
|
+
# will use it automatically. When ruby-jss is loaded, the default connection
|
142
|
+
# (see above) is the active connection.
|
143
|
+
#
|
144
|
+
# To use the active connection, just call a method on an APIObject subclass
|
145
|
+
# that uses the API.
|
146
|
+
#
|
147
|
+
# For example, the various list methods:
|
148
|
+
#
|
149
|
+
# all_computer_sns = JSS::Computer.all_serial_numbers
|
150
|
+
#
|
151
|
+
# # the list of all computer serial numbers is read from the active
|
152
|
+
# # connection and stored in all_computer_sns
|
153
|
+
#
|
154
|
+
# Fetching an object from the API:
|
155
|
+
#
|
156
|
+
# victim_md = JSS::MobileDevice.fetch id: 832
|
157
|
+
#
|
158
|
+
# # the variable 'victim_md' now contains a JSS::MobileDevice queried
|
159
|
+
# # through the active connection.
|
160
|
+
#
|
161
|
+
# The currently-active connection instance is available from the
|
162
|
+
# `JSS.api` method.
|
163
|
+
#
|
164
|
+
# === Making a Connection Active
|
165
|
+
#
|
166
|
+
# Only one connection is 'active' at a time and the currently active one is
|
167
|
+
# returned when you call `JSS.api` or its alias `JSS.active_connection`
|
98
168
|
#
|
99
169
|
# To activate another connection just pass it to the JSS.use_api method like so:
|
170
|
+
#
|
100
171
|
# JSS.use_api production_api
|
101
172
|
# # the connection we stored in 'production_api' is now active
|
102
173
|
#
|
103
174
|
# To re-activate to the default connection, just call
|
104
175
|
# JSS.use_default_connection
|
105
176
|
#
|
106
|
-
# NOTE:
|
107
|
-
# The APIObject list methods (e.g. JSS::Computer.all) cache the list
|
108
|
-
# data from the API the first time they are used, and after that when
|
109
|
-
# their 'refresh' option is true.
|
110
|
-
#
|
111
|
-
# Those caches are stored in the APIConnection instance through-
|
112
|
-
# which they were read, so they won't be incorrect when you switch
|
113
|
-
# connections.
|
114
|
-
#
|
115
177
|
# == Connection Names:
|
116
178
|
#
|
117
179
|
# As seen in the example above, you can provide a 'name:' parameter
|
@@ -147,9 +209,61 @@ module JSS
|
|
147
209
|
#
|
148
210
|
# JSS.api.name # => 'prod2'
|
149
211
|
#
|
212
|
+
# == Passing an APIConnection object to API-related methods
|
213
|
+
#
|
214
|
+
# All methods that use the API can take an 'api:' parameter which
|
215
|
+
# contains an APIConnection object. When provided, that APIconnection is
|
216
|
+
# used rather than the active connection.
|
217
|
+
#
|
218
|
+
# For example:
|
219
|
+
#
|
220
|
+
# prod2_computer_sns = JSS::Computer.all_serial_numbers, api: production_api2
|
221
|
+
#
|
222
|
+
# # the list of all computer serial numbers is read from the connection in
|
223
|
+
# # the variable 'production_api2' and stored in 'prod2_computer_sns'
|
224
|
+
#
|
225
|
+
# prod2_victim_md = JSS::MobileDevice.fetch id: 832, api: production_api2
|
226
|
+
#
|
227
|
+
# # the variable 'prod2_victim_md' now contains a JSS::MobileDevice queried
|
228
|
+
# # through the connection 'production_api2'.
|
229
|
+
#
|
230
|
+
# == Using the APIConnection itself to make API calls.
|
231
|
+
#
|
232
|
+
# Rather than passing an APIConnection into another method, you can call
|
233
|
+
# similar methods on the connection itself. For example, these two calls
|
234
|
+
# have the same result as the two examples above:
|
235
|
+
#
|
236
|
+
# prod2_computer_sns = production_api2.all :Computer, only: :serial_numbers
|
237
|
+
# prod2_victim_md = production_api2.fetch :MobileDevice, id: 832
|
238
|
+
#
|
239
|
+
# Here are the API calls you can make directly from an APIConnection object.
|
240
|
+
# Most of them behave identically to the same methods in the APIObject classes
|
241
|
+
#
|
242
|
+
# - {#all} The 'list' methods of the various APIObject classes. Use the 'only:'
|
243
|
+
# parameter to specify one of the sub-list-methods, like #all_ids or
|
244
|
+
# #all_laptops
|
245
|
+
# - {#map_all_ids} the equivalent of #map_all_ids_to in the APIObject classes
|
246
|
+
# - {#valid_id} given a class and an identifier (like macaddress or udid)
|
247
|
+
# return a valid id or nil
|
248
|
+
# - {#exist?} given a class and an identifier (like macaddress or udid) does
|
249
|
+
# the identifier exist for the class in the JSS
|
250
|
+
# - {#match} list items in the JSS matching a query
|
251
|
+
# (if the object is {Matchable})
|
252
|
+
# - {#fetch} retrieve an object from the JSS
|
253
|
+
# - {#make} instantiate an object to be created in the JSS
|
254
|
+
# - {#send_computer_mdm_command} same as {Computer.send_mdm_command}
|
255
|
+
# - {#computer_checkin_settings} same as {Computer.checkin_settings}
|
256
|
+
# - {#computer_inventory_collection_settings} same as {Computer.inventory_collection_settings}
|
257
|
+
# - {#send_mobiledevice_mdm_command} same as {MobileDevice.send_mdm_command}
|
258
|
+
# - {#master_distribution_point} same as {DistributionPoint.master_distribution_point}
|
259
|
+
# - {#my_distribution_point} same as {DistributionPoint.my_distribution_point}
|
260
|
+
# - {#network_ranges} same as {NetworkSegment.network_ranges}
|
261
|
+
# - {#network_segments_for_ip} same as {NetworkSegment.segments_for_ip}
|
262
|
+
# - {#my_network_segments} same as {NetworkSegment.my_network_segments}
|
263
|
+
#
|
150
264
|
# == Low-level use of APIConnection instances.
|
151
265
|
#
|
152
|
-
# For most
|
266
|
+
# For most cases, using APIConnection instances as mentioned above
|
153
267
|
# is all you'll need. However to access API resources that aren't yet
|
154
268
|
# implemented in other parts of ruby-jss, you can use the methods
|
155
269
|
# {#get_rsrc}, {#put_rsrc}, {#post_rsrc}, & {#delete_rsrc}
|
@@ -378,7 +492,7 @@ module JSS
|
|
378
492
|
#
|
379
493
|
def get_rsrc(rsrc, format = :json)
|
380
494
|
# puts object_id
|
381
|
-
raise JSS::InvalidConnectionError, 'Not Connected. Use
|
495
|
+
raise JSS::InvalidConnectionError, 'Not Connected. Use .connect first.' unless @connected
|
382
496
|
rsrc = URI.encode rsrc
|
383
497
|
@last_http_response = @cnx[rsrc].get(accept: format)
|
384
498
|
return JSON.parse(@last_http_response, symbolize_names: true) if format == :json
|
@@ -393,7 +507,7 @@ module JSS
|
|
393
507
|
# @return [String] the xml response from the server.
|
394
508
|
#
|
395
509
|
def put_rsrc(rsrc, xml)
|
396
|
-
raise JSS::InvalidConnectionError, 'Not Connected. Use
|
510
|
+
raise JSS::InvalidConnectionError, 'Not Connected. Use .connect first.' unless @connected
|
397
511
|
|
398
512
|
# convert CRs & to
|
399
513
|
xml.gsub!(/\r/, ' ')
|
@@ -413,7 +527,7 @@ module JSS
|
|
413
527
|
# @return [String] the xml response from the server.
|
414
528
|
#
|
415
529
|
def post_rsrc(rsrc, xml = '')
|
416
|
-
raise JSS::InvalidConnectionError, 'Not Connected. Use
|
530
|
+
raise JSS::InvalidConnectionError, 'Not Connected. Use .connect first.' unless @connected
|
417
531
|
|
418
532
|
# convert CRs & to
|
419
533
|
xml.gsub!(/\r/, ' ') if xml
|
@@ -431,7 +545,7 @@ module JSS
|
|
431
545
|
# @return [String] the xml response from the server.
|
432
546
|
#
|
433
547
|
def delete_rsrc(rsrc, xml = nil)
|
434
|
-
raise JSS::InvalidConnectionError, 'Not Connected. Use
|
548
|
+
raise JSS::InvalidConnectionError, 'Not Connected. Use .connect first.' unless @connected
|
435
549
|
raise MissingDataError, 'Missing :rsrc' if rsrc.nil?
|
436
550
|
|
437
551
|
# payload?
|
@@ -492,6 +606,274 @@ module JSS
|
|
492
606
|
alias connected? connected
|
493
607
|
alias host hostname
|
494
608
|
|
609
|
+
|
610
|
+
#################
|
611
|
+
|
612
|
+
# Call one of the 'all*' methods on a JSS::APIObject subclass
|
613
|
+
# using this APIConnection.
|
614
|
+
#
|
615
|
+
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
616
|
+
# see {JSS.api_object_class}
|
617
|
+
#
|
618
|
+
# @param refresh[Boolean] Should the data be re-read from the API?
|
619
|
+
#
|
620
|
+
# @param only[String,Symbol] Limit the output to subset or data. All
|
621
|
+
# APIObject subclasses can take :ids or :names, which calls the .all_ids
|
622
|
+
# and .all_names methods. Some subclasses can take other options, e.g.
|
623
|
+
# MobileDevice can take :udids
|
624
|
+
#
|
625
|
+
# @return [Array] The list of items for the class
|
626
|
+
#
|
627
|
+
def all(class_name, refresh = false, only: nil )
|
628
|
+
the_class = JSS.api_object_class(class_name)
|
629
|
+
list_method = only ? :"all_#{only}" : :all
|
630
|
+
|
631
|
+
raise ArgumentError, "Unknown identifier: #{only} for #{the_class}" unless
|
632
|
+
the_class.respond_to? list_method
|
633
|
+
|
634
|
+
the_class.send list_method, refresh, api: self
|
635
|
+
end
|
636
|
+
|
637
|
+
# Call the 'map_all_ids_to' method on a JSS::APIObject subclass
|
638
|
+
# using this APIConnection.
|
639
|
+
#
|
640
|
+
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
641
|
+
# see {JSS.api_object_class}
|
642
|
+
#
|
643
|
+
# @param refresh[Boolean] Should the data be re-read from the API?
|
644
|
+
#
|
645
|
+
# @param to[String,Symbol] the value to which the ids should be mapped
|
646
|
+
#
|
647
|
+
# @return [Hash] The ids for the class keyed to the requested identifier
|
648
|
+
#
|
649
|
+
def map_all_ids(class_name, refresh = false, to: nil)
|
650
|
+
raise "'to:' value must be provided for mapping ids." unless to
|
651
|
+
the_class = JSS.api_object_class(class_name)
|
652
|
+
the_class.map_all_ids_to to, api: self
|
653
|
+
end
|
654
|
+
|
655
|
+
# Call the 'valid_id' method on a JSS::APIObject subclass
|
656
|
+
# using this APIConnection. See {JSS::APIObject.valid_id}
|
657
|
+
#
|
658
|
+
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass,
|
659
|
+
# see {JSS.api_object_class}
|
660
|
+
#
|
661
|
+
# @param identifier[String,Symbol] the value to which the ids should be mapped
|
662
|
+
#
|
663
|
+
# @param refresh[Boolean] Should the data be re-read from the API?
|
664
|
+
#
|
665
|
+
# @return [Integer, nil] the id of the matching object of the class,
|
666
|
+
# or nil if there isn't one
|
667
|
+
#
|
668
|
+
def valid_id(class_name, identifier, refresh = true)
|
669
|
+
the_class = JSS.api_object_class(class_name)
|
670
|
+
the_class.valid_id identifier, refresh, api: self
|
671
|
+
end
|
672
|
+
|
673
|
+
# Call the 'exist?' method on a JSS::APIObject subclass
|
674
|
+
# using this APIConnection. See {JSS::APIObject.exist?}
|
675
|
+
#
|
676
|
+
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
677
|
+
# see {JSS.api_object_class}
|
678
|
+
#
|
679
|
+
# @param identifier[String,Symbol] the value to which the ids should be mapped
|
680
|
+
#
|
681
|
+
# @param refresh[Boolean] Should the data be re-read from the API?
|
682
|
+
#
|
683
|
+
# @return [Boolean] Is there an object of this class in the JSS matching
|
684
|
+
# this indentifier?
|
685
|
+
#
|
686
|
+
def exist?(class_name, identifier, refresh = false)
|
687
|
+
!valid_id(class_name, identifier, refresh).nil?
|
688
|
+
end
|
689
|
+
|
690
|
+
# Call {Matchable.match} for the given class.
|
691
|
+
#
|
692
|
+
# See {Matchable.match}
|
693
|
+
#
|
694
|
+
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
695
|
+
# see {JSS.api_object_class}
|
696
|
+
#
|
697
|
+
# @return (see Matchable.match)
|
698
|
+
#
|
699
|
+
def match(class_name, term)
|
700
|
+
the_class = JSS.api_object_class(class_name)
|
701
|
+
raise JSS::UnsupportedError, "Class #{the_class} is not matchable" unless the_class.respond_to? :match
|
702
|
+
the_class.match term, api: self
|
703
|
+
end
|
704
|
+
|
705
|
+
# Retrieve an object of a given class from the API
|
706
|
+
# See {APIObject.fetch}
|
707
|
+
#
|
708
|
+
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
709
|
+
# see {JSS.api_object_class}
|
710
|
+
#
|
711
|
+
# @return [APIObject] The ruby-instance of the object.
|
712
|
+
#
|
713
|
+
def fetch(class_name, arg)
|
714
|
+
the_class = JSS.api_object_class(class_name)
|
715
|
+
the_class.fetch arg, api: self
|
716
|
+
end
|
717
|
+
|
718
|
+
# Make a ruby instance of a not-yet-existing APIObject
|
719
|
+
# of the given class
|
720
|
+
# See {APIObject.make}
|
721
|
+
#
|
722
|
+
# @param class_name[String,Symbol] The name of a JSS::APIObject subclass
|
723
|
+
# see {JSS.api_object_class}
|
724
|
+
#
|
725
|
+
# @return [APIObject] The un-created ruby-instance of the object.
|
726
|
+
#
|
727
|
+
def make(class_name, **args)
|
728
|
+
the_class = JSS.api_object_class(class_name)
|
729
|
+
args[:api] = self
|
730
|
+
the_class.make args
|
731
|
+
end
|
732
|
+
|
733
|
+
# Call {JSS::Computer.checkin_settings} passing this API
|
734
|
+
# connection
|
735
|
+
#
|
736
|
+
# @return (see JSS::Computer.checkin_settings)
|
737
|
+
#
|
738
|
+
def computer_checkin_settings
|
739
|
+
JSS::Computer.checkin_settings api: self
|
740
|
+
end
|
741
|
+
|
742
|
+
|
743
|
+
# Call {JSS::Computer.inventory_collection_settings} passing this API
|
744
|
+
# connection
|
745
|
+
#
|
746
|
+
# @return (see JSS::Computer.checkin_settings)
|
747
|
+
#
|
748
|
+
def computer_inventory_collection_settings
|
749
|
+
JSS::Computer.inventory_collection_settings api: self
|
750
|
+
end
|
751
|
+
|
752
|
+
# Get the DistributionPoint instance for the master
|
753
|
+
# distribution point in the JSS. If there's only one
|
754
|
+
# in the JSS, return it even if not marked as master.
|
755
|
+
#
|
756
|
+
# @param refresh[Boolean] re-read from the API?
|
757
|
+
#
|
758
|
+
# @return [JSS::DistributionPoint]
|
759
|
+
#
|
760
|
+
def master_distribution_point(refresh = false)
|
761
|
+
@master_distribution_point = nil if refresh
|
762
|
+
return @master_distribution_point if @master_distribution_point
|
763
|
+
|
764
|
+
all_dps = JSS::DistributionPoint.all refresh, api: self
|
765
|
+
|
766
|
+
@master_distribution_point =
|
767
|
+
case all_dps.size
|
768
|
+
when 0
|
769
|
+
raise JSS::NoSuchItemError, "No distribution points defined"
|
770
|
+
when 1
|
771
|
+
JSS::DistributionPoint.fetch id: all_dps.first[:id], api: self
|
772
|
+
else
|
773
|
+
JSS::DistributionPoint.fetch id: :master, api: self
|
774
|
+
end
|
775
|
+
end
|
776
|
+
|
777
|
+
# Get the DistributionPoint instance for the machine running
|
778
|
+
# this code, based on its IP address. If none is defined for this IP address,
|
779
|
+
# use the result of master_distribution_point
|
780
|
+
#
|
781
|
+
# @param refresh[Boolean] should the distribution point be re-queried?
|
782
|
+
#
|
783
|
+
# @return [JSS::DistributionPoint]
|
784
|
+
#
|
785
|
+
def my_distribution_point(refresh = false)
|
786
|
+
@my_distribution_point = nil if refresh
|
787
|
+
return @my_distribution_point if @my_distribution_point
|
788
|
+
|
789
|
+
my_net_seg = my_network_segments[0]
|
790
|
+
@my_distribution_point = JSS::NetworkSegment.fetch(id: my_net_seg, api: self).distribution_point if my_net_seg
|
791
|
+
@my_distribution_point ||= master_distribution_point refresh
|
792
|
+
@my_distribution_point
|
793
|
+
end
|
794
|
+
|
795
|
+
# All NetworkSegments in this jss as IPAddr object Ranges representing the
|
796
|
+
# Segment, e.g. with starting = 10.24.9.1 and ending = 10.24.15.254
|
797
|
+
# the range looks like:
|
798
|
+
# <IPAddr: IPv4:10.24.9.1/255.255.255.255>..#<IPAddr: IPv4:10.24.15.254/255.255.255.255>
|
799
|
+
#
|
800
|
+
# Using the #include? method on those Ranges is very useful.
|
801
|
+
#
|
802
|
+
# @param refresh[Boolean] should the data be re-queried?
|
803
|
+
#
|
804
|
+
# @return [Hash{Integer => Range}] the network segments as IPv4 address Ranges
|
805
|
+
#
|
806
|
+
def network_ranges(refresh = false)
|
807
|
+
@network_ranges = nil if refresh
|
808
|
+
return @network_ranges if @network_ranges
|
809
|
+
@network_ranges = {}
|
810
|
+
JSS::NetworkSegment.all(refresh, api: self).each do |ns|
|
811
|
+
@network_ranges[ns[:id]] = IPAddr.new(ns[:starting_address])..IPAddr.new(ns[:ending_address])
|
812
|
+
end
|
813
|
+
@network_ranges
|
814
|
+
end # def network_segments
|
815
|
+
|
816
|
+
# Find the ids of the network segments that contain a given IP address.
|
817
|
+
#
|
818
|
+
# Even tho IPAddr.include? will take a String or an IPAddr
|
819
|
+
# I convert the ip to an IPAddr so that an exception will be raised if
|
820
|
+
# the ip isn't a valid ip.
|
821
|
+
#
|
822
|
+
# @param ip[String, IPAddr] the IP address to locate
|
823
|
+
#
|
824
|
+
# @param refresh[Boolean] should the data be re-queried?
|
825
|
+
#
|
826
|
+
# @return [Array<Integer>] the ids of the NetworkSegments containing the given ip
|
827
|
+
#
|
828
|
+
def network_segments_for_ip(ip, refresh = false)
|
829
|
+
ok_ip = IPAddr.new(ip)
|
830
|
+
matches = []
|
831
|
+
network_ranges.each { |id, subnet| matches << id if subnet.include?(ok_ip) }
|
832
|
+
matches
|
833
|
+
end
|
834
|
+
|
835
|
+
# Find the current network segment ids for the machine running this code
|
836
|
+
#
|
837
|
+
# @return [Array<Integer>] the NetworkSegment ids for this machine right now.
|
838
|
+
#
|
839
|
+
def my_network_segments
|
840
|
+
network_segments_for_ip JSS::Client.my_ip_address
|
841
|
+
end
|
842
|
+
|
843
|
+
# Send an MDM command to one or more computers managed by
|
844
|
+
# this JSS
|
845
|
+
#
|
846
|
+
# see {JSS::Computer.send_mdm_command}
|
847
|
+
#
|
848
|
+
def send_computer_mdm_command(targets, command, passcode = nil)
|
849
|
+
JSS::Computer.send_mdm_command(targets, command, passcode, api: self)
|
850
|
+
end
|
851
|
+
|
852
|
+
# Send an MDM command to one or more mobile devices managed by
|
853
|
+
# this JSS
|
854
|
+
#
|
855
|
+
# see {JSS::MobileDevice.send_mdm_command}
|
856
|
+
#
|
857
|
+
def send_mobiledevice_mdm_command(targets, command, data = nil)
|
858
|
+
JSS::MobileDevice.send_mdm_command(targets, command, data, api: self)
|
859
|
+
end
|
860
|
+
|
861
|
+
# Remove the various cached data
|
862
|
+
# from the instance_variables used to create
|
863
|
+
# pretty-print (pp) output.
|
864
|
+
#
|
865
|
+
# @return [Array] the desired instance_variables
|
866
|
+
#
|
867
|
+
def pretty_print_instance_variables
|
868
|
+
vars = instance_variables.sort
|
869
|
+
vars.delete :@object_list_cache
|
870
|
+
vars.delete :@last_http_response
|
871
|
+
vars.delete :@network_ranges
|
872
|
+
vars.delete :@my_distribution_point
|
873
|
+
vars.delete :@master_distribution_point
|
874
|
+
vars
|
875
|
+
end
|
876
|
+
|
495
877
|
# Private Insance Methods
|
496
878
|
####################################
|
497
879
|
private
|
@@ -596,9 +978,9 @@ module JSS
|
|
596
978
|
# keep this basic level of info available for basic authentication
|
597
979
|
# and JSS version checking.
|
598
980
|
begin
|
599
|
-
@server = JSS::Server.new get_rsrc('jssuser')[:user]
|
981
|
+
@server = JSS::Server.new get_rsrc('jssuser')[:user], self
|
600
982
|
rescue RestClient::Unauthorized, RestClient::Request::Unauthorized
|
601
|
-
raise JSS::AuthenticationError, "Incorrect JSS username or password for '#{
|
983
|
+
raise JSS::AuthenticationError, "Incorrect JSS username or password for '#{@jss_user}@#{@server_host}:#{@port}'."
|
602
984
|
end
|
603
985
|
|
604
986
|
min_vers = JSS.parse_jss_version(JSS::MINIMUM_SERVER_VERSION)[:version]
|
@@ -757,12 +1139,14 @@ module JSS
|
|
757
1139
|
class << self
|
758
1140
|
alias api_connection api
|
759
1141
|
alias connection api
|
1142
|
+
alias active_connection api
|
760
1143
|
|
761
1144
|
alias new_connection new_api_connection
|
762
1145
|
alias new_api new_api_connection
|
763
1146
|
|
764
1147
|
alias use_api use_api_connection
|
765
1148
|
alias use_connection use_api_connection
|
1149
|
+
alias activate_connection use_api_connection
|
766
1150
|
end
|
767
1151
|
|
768
1152
|
# create the default connection
|