ruby-jss 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +95 -0
- data/THANKS.md +3 -2
- data/lib/jamf.rb +18 -17
- data/lib/jamf/api/base_classes/collection_resource.rb +613 -0
- data/lib/jamf/api/{abstract_classes → base_classes}/json_object.rb +109 -101
- data/lib/jamf/api/{abstract_classes → base_classes}/prestage.rb +55 -30
- data/lib/jamf/api/{abstract_classes → base_classes}/resource.rb +10 -6
- data/lib/jamf/api/{abstract_classes → base_classes}/singleton_resource.rb +4 -3
- data/lib/jamf/api/connection.rb +13 -9
- data/lib/jamf/api/connection/api_error.rb +8 -8
- data/lib/jamf/api/connection/token.rb +16 -15
- data/lib/jamf/api/json_objects/device_enrollment_device.rb +14 -7
- data/lib/jamf/api/json_objects/{location.rb → device_enrollment_device_sync_state.rb} +27 -41
- data/lib/jamf/api/json_objects/device_enrollment_sync_status.rb +1 -1
- data/lib/jamf/api/json_objects/{attachment.rb → locale.rb} +14 -23
- data/lib/jamf/api/json_objects/md_prestage_name.rb +1 -1
- data/lib/jamf/api/json_objects/md_prestage_names.rb +2 -2
- data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +50 -1
- data/lib/jamf/api/json_objects/prestage_assignment.rb +2 -2
- data/lib/jamf/api/json_objects/prestage_location.rb +3 -3
- data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +7 -7
- data/lib/jamf/api/json_objects/prestage_scope.rb +1 -1
- data/lib/jamf/api/{resources/collection_resources → json_objects}/time_zone.rb +9 -23
- data/lib/jamf/api/mixins/{abstract.rb → base_class.rb} +34 -16
- data/lib/jamf/api/mixins/bulk_deletable.rb +27 -6
- data/lib/jamf/api/mixins/change_log.rb +201 -51
- data/lib/jamf/api/{resources/collection_resources/computer.rb → mixins/filterable.rb} +19 -17
- data/lib/jamf/api/mixins/pageable.rb +208 -0
- data/lib/jamf/api/{json_objects/installed_application.rb → mixins/sortable.rb} +33 -33
- data/lib/jamf/api/resources/collection_resources/building.rb +16 -9
- data/lib/jamf/api/resources/collection_resources/category.rb +5 -4
- data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +12 -5
- data/lib/jamf/api/resources/collection_resources/department.rb +0 -2
- data/lib/jamf/api/resources/collection_resources/device_enrollment.rb +10 -10
- data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +11 -3
- data/lib/jamf/api/resources/collection_resources/mobile_device_prestage.rb +25 -23
- data/lib/jamf/api/resources/collection_resources/script.rb +61 -25
- data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +15 -5
- data/lib/jamf/api/resources/singleton_resources/locales.rb +155 -0
- data/lib/jamf/api/resources/singleton_resources/time_zones.rb +213 -0
- data/lib/jamf/client.rb +3 -3
- data/lib/jamf/client/management_action.rb +2 -3
- data/lib/jamf/composer.rb +2 -2
- data/lib/jamf/utility.rb +35 -7
- data/lib/jamf/validate.rb +63 -24
- data/lib/jamf/version.rb +1 -1
- data/lib/jss.rb +2 -2
- data/lib/jss/api_connection.rb +114 -406
- data/lib/jss/api_object.rb +3 -19
- data/lib/jss/api_object/categorizable.rb +1 -1
- data/lib/jss/api_object/computer.rb +13 -0
- data/lib/jss/api_object/configuration_profile.rb +61 -5
- data/lib/jss/api_object/directory_binding_type.rb +66 -60
- data/lib/jss/api_object/directory_binding_type/active_directory.rb +71 -34
- data/lib/jss/api_object/directory_binding_type/admitmac.rb +536 -467
- data/lib/jss/api_object/directory_binding_type/centrify.rb +21 -7
- data/lib/jss/api_object/directory_binding_type/open_directory.rb +4 -4
- data/lib/jss/api_object/distribution_point.rb +2 -2
- data/lib/jss/api_object/dock_item.rb +102 -96
- data/lib/jss/api_object/extendable.rb +1 -1
- data/lib/jss/api_object/group.rb +33 -2
- data/lib/jss/api_object/network_segment.rb +45 -13
- data/lib/jss/api_object/patch_source.rb +10 -9
- data/lib/jss/api_object/policy.rb +155 -25
- data/lib/jss/api_object/printer.rb +10 -4
- data/lib/jss/api_object/scopable.rb +10 -15
- data/lib/jss/api_object/scopable/scope.rb +31 -30
- data/lib/jss/api_object/script.rb +242 -352
- data/lib/jss/api_object/user.rb +1 -1
- data/lib/jss/client/management_action.rb +1 -2
- data/lib/jss/composer.rb +2 -2
- data/lib/jss/exceptions.rb +3 -0
- data/lib/jss/server.rb +15 -0
- data/lib/jss/utility.rb +213 -45
- data/lib/jss/version.rb +1 -1
- metadata +46 -64
- data/lib/jamf/api/abstract_classes/advanced_search.rb +0 -86
- data/lib/jamf/api/abstract_classes/collection_resource.rb +0 -433
- data/lib/jamf/api/abstract_classes/generic_reference.rb +0 -145
- data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +0 -126
- data/lib/jamf/api/json_objects/account_prefs.rb +0 -79
- data/lib/jamf/api/json_objects/android_details.rb +0 -139
- data/lib/jamf/api/json_objects/appletv_details.rb +0 -110
- data/lib/jamf/api/json_objects/cellular_network.rb +0 -151
- data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +0 -67
- data/lib/jamf/api/json_objects/criterion.rb +0 -152
- data/lib/jamf/api/json_objects/extension_attribute_value.rb +0 -128
- data/lib/jamf/api/json_objects/installed_certificate.rb +0 -53
- data/lib/jamf/api/json_objects/installed_configuration_profile.rb +0 -67
- data/lib/jamf/api/json_objects/installed_ebook.rb +0 -58
- data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +0 -59
- data/lib/jamf/api/json_objects/ios_details.rb +0 -244
- data/lib/jamf/api/json_objects/mobile_device_details.rb +0 -219
- data/lib/jamf/api/json_objects/mobile_device_security.rb +0 -101
- data/lib/jamf/api/json_objects/purchasing_data.rb +0 -125
- data/lib/jamf/api/mixins/locatable.rb +0 -124
- data/lib/jamf/api/mixins/referable.rb +0 -92
- data/lib/jamf/api/resources/collection_resources/account.rb +0 -163
- data/lib/jamf/api/resources/collection_resources/advanced_mobile_device_search.rb +0 -52
- data/lib/jamf/api/resources/collection_resources/advanced_user_search.rb +0 -52
- data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +0 -45
- data/lib/jamf/api/resources/collection_resources/mobile_device.rb +0 -315
- data/lib/jamf/api/resources/collection_resources/site.rb +0 -77
- data/lib/jamf/api/resources/singleton_resources/authorization.rb +0 -88
- data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +0 -139
- data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +0 -95
|
@@ -1,94 +1,91 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
# Copyright 2020 Pixar
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
5
|
+
# with the following modification; you may not use this file except in
|
|
6
|
+
# compliance with the Apache License and the following modification to it:
|
|
7
|
+
# Section 6. Trademarks. is deleted and replaced with:
|
|
8
|
+
#
|
|
9
|
+
# 6. Trademarks. This License does not grant permission to use the trade
|
|
10
|
+
# names, trademarks, service marks, or product names of the Licensor
|
|
11
|
+
# and its affiliates, except as required to comply with Section 4(c) of
|
|
12
|
+
# the License and to reproduce the content of the NOTICE file.
|
|
13
|
+
#
|
|
14
|
+
# You may obtain a copy of the Apache License at
|
|
15
|
+
#
|
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
#
|
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
# distributed under the Apache License with the above modification is
|
|
20
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
21
|
+
# KIND, either express or implied. See the Apache License for the specific
|
|
22
|
+
# language governing permissions and limitations under the Apache License.
|
|
23
|
+
#
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
#
|
|
27
27
|
module JSS
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# Module Constants
|
|
30
30
|
#####################################
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
# Module Variables
|
|
33
33
|
#####################################
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
# Module Methods
|
|
36
36
|
#####################################
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
# Classes
|
|
39
39
|
#####################################
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
###
|
|
55
|
-
### @see JSS::APIObject
|
|
56
|
-
###
|
|
41
|
+
# A Script in the JSS.
|
|
42
|
+
#
|
|
43
|
+
# As of Casper 9.4, the script contents as stored in the database are
|
|
44
|
+
# accessible via the API
|
|
45
|
+
#
|
|
46
|
+
# According to Jamf as of early 2021, it has been some years now since
|
|
47
|
+
# its been possible to store script contents on a dist. point - they
|
|
48
|
+
# are all always in the database.
|
|
49
|
+
#
|
|
50
|
+
# Use the {#run} method to run the script on the local machine.
|
|
51
|
+
#
|
|
52
|
+
# @see JSS::APIObject
|
|
53
|
+
#
|
|
57
54
|
class Script < JSS::APIObject
|
|
58
55
|
|
|
59
|
-
|
|
56
|
+
# Mix-Ins
|
|
60
57
|
#####################################
|
|
61
58
|
|
|
62
59
|
include JSS::Creatable
|
|
63
60
|
include JSS::Updatable
|
|
64
61
|
include JSS::Categorizable
|
|
65
62
|
|
|
66
|
-
|
|
63
|
+
# Class Methods
|
|
67
64
|
#####################################
|
|
68
65
|
|
|
69
|
-
|
|
66
|
+
# Class Constants
|
|
70
67
|
#####################################
|
|
71
68
|
|
|
72
|
-
|
|
69
|
+
# The base for REST resources of this class
|
|
73
70
|
RSRC_BASE = 'scripts'.freeze
|
|
74
71
|
|
|
75
|
-
|
|
72
|
+
# the hash key used for the JSON list output of all objects in the JSS
|
|
76
73
|
RSRC_LIST_KEY = :scripts
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
# The hash key used for the JSON object output.
|
|
76
|
+
# It's also used in various error messages
|
|
80
77
|
RSRC_OBJECT_KEY = :script
|
|
81
78
|
|
|
82
|
-
|
|
79
|
+
# The script storage folder on the distribution point, if used
|
|
83
80
|
DIST_POINT_SCRIPTS_FOLDER = 'Scripts'.freeze
|
|
84
81
|
|
|
85
|
-
|
|
82
|
+
# Priority to use for running the script in relation to other actions during imaging
|
|
86
83
|
PRIORITIES = ['Before', 'After', 'At Reboot'].freeze
|
|
87
84
|
|
|
88
|
-
|
|
85
|
+
# which is default?
|
|
89
86
|
DEFAULT_PRIORITY = 'After'.freeze
|
|
90
87
|
|
|
91
|
-
|
|
88
|
+
# The keys used in the @parameters Hash
|
|
92
89
|
PARAMETER_KEYS = [:parameter4, :parameter5, :parameter6, :parameter7, :parameter8, :parameter9, :parameter10, :parameter11].freeze
|
|
93
90
|
|
|
94
91
|
# the object type for this object in
|
|
@@ -103,34 +100,39 @@ module JSS
|
|
|
103
100
|
CATEGORY_DATA_TYPE = String
|
|
104
101
|
|
|
105
102
|
|
|
106
|
-
|
|
103
|
+
# Attributes
|
|
107
104
|
#####################################
|
|
108
105
|
|
|
109
|
-
|
|
106
|
+
# @return [String] the file name of the script, if stored in a dist. point
|
|
110
107
|
attr_reader :filename
|
|
111
108
|
|
|
112
|
-
|
|
109
|
+
# @return [Array<String>] the OS versions this can be installed onto. For all minor versions, the format is 10.5.x
|
|
113
110
|
attr_reader :os_requirements
|
|
114
111
|
|
|
115
|
-
|
|
112
|
+
# @return [String] either 'Before' or 'After' or "At Reboot".
|
|
116
113
|
attr_reader :priority
|
|
117
114
|
|
|
118
|
-
|
|
115
|
+
# @return [String] the info field for this script
|
|
119
116
|
attr_reader :info
|
|
120
117
|
|
|
121
|
-
|
|
118
|
+
# @return [String] the notes field for this script
|
|
122
119
|
attr_reader :notes
|
|
123
120
|
|
|
124
|
-
|
|
121
|
+
# @return [Hash] descriptions of parameters 4-11. Parameters 1-3 are predefined as target drive, computer name, and username
|
|
125
122
|
attr_reader :parameters
|
|
123
|
+
alias parameter_labels parameters
|
|
124
|
+
alias parameter_descriptions parameters
|
|
126
125
|
|
|
127
|
-
|
|
126
|
+
# @return {String] the actual code for this script, if it's stored in the database.
|
|
128
127
|
attr_reader :script_contents
|
|
129
128
|
|
|
130
|
-
|
|
129
|
+
# @return [String] the code for this script, Base64-encoded
|
|
130
|
+
attr_reader :script_contents_encoded
|
|
131
|
+
|
|
132
|
+
# Constructor
|
|
131
133
|
#####################################
|
|
132
134
|
|
|
133
|
-
|
|
135
|
+
#
|
|
134
136
|
def initialize(args = {})
|
|
135
137
|
super
|
|
136
138
|
|
|
@@ -141,19 +143,23 @@ module JSS
|
|
|
141
143
|
@parameters = @init_data[:parameters] ? @init_data[:parameters] : {}
|
|
142
144
|
@priority = @init_data[:priority] || DEFAULT_PRIORITY
|
|
143
145
|
@script_contents = @init_data[:script_contents]
|
|
146
|
+
@script_contents_encoded = @init_data[:script_contents_encoded]
|
|
147
|
+
if @script_contents && @script_contents_encoded.to_s.empty?
|
|
148
|
+
@script_contents_encoded = Base64.encode64 @script_contents
|
|
149
|
+
end
|
|
144
150
|
end # initialize
|
|
145
151
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
# Change the script filename
|
|
153
|
+
#
|
|
154
|
+
# Setting it to nil will make it match the script name
|
|
155
|
+
#
|
|
156
|
+
# @param new_val[String,Nil] the new filename
|
|
157
|
+
#
|
|
158
|
+
# @return [void]
|
|
159
|
+
#
|
|
160
|
+
# @note This method does NOT change the filename on the distribution point
|
|
161
|
+
# if that's where you store your scripts.
|
|
162
|
+
#
|
|
157
163
|
def filename=(new_val)
|
|
158
164
|
new_val = nil if new_val == ''
|
|
159
165
|
new_val = @name unless new_val
|
|
@@ -164,14 +170,14 @@ module JSS
|
|
|
164
170
|
@need_to_update = true
|
|
165
171
|
end # filename=
|
|
166
172
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
# Change the script's display name
|
|
174
|
+
#
|
|
175
|
+
# If the filename is the same as the name, the filename will be changed also
|
|
176
|
+
#
|
|
177
|
+
# @param new_val[String] the new display name
|
|
178
|
+
#
|
|
179
|
+
# @return [void]
|
|
180
|
+
#
|
|
175
181
|
def name=(new_val)
|
|
176
182
|
new_val = new_val.to_s
|
|
177
183
|
return if new_val == @name
|
|
@@ -179,39 +185,39 @@ module JSS
|
|
|
179
185
|
raise JSS::MissingDataError, "Name can't be empty" if new_val.empty?
|
|
180
186
|
raise JSS::AlreadyExistsError, "A script already exists with the name '#{new_val}'" if JSS::Script.all_names.include? new_val
|
|
181
187
|
|
|
182
|
-
|
|
188
|
+
# if the filename matches the name, change that too.
|
|
183
189
|
@filename = new_val if @filename == @name
|
|
184
190
|
@name = new_val
|
|
185
191
|
|
|
186
|
-
|
|
192
|
+
# if our REST resource is based on the name, update that too
|
|
187
193
|
@rest_rsrc = "#{RSRC_BASE}/name/#{CGI.escape @name.to_s}" if @rest_rsrc.include? '/name/'
|
|
188
194
|
@need_to_update = true
|
|
189
195
|
end # name=
|
|
190
196
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
197
|
+
# Change the os_requirements
|
|
198
|
+
#
|
|
199
|
+
# Minumum OS's can be specified as a string using the notation ">=10.6.7"
|
|
200
|
+
# See the {JSS.expand_min_os} method for details.
|
|
201
|
+
#
|
|
202
|
+
# @param new_val[String, Array<String>] the new os requirements as a comma-separted String or an Array of Strings
|
|
203
|
+
#
|
|
204
|
+
# @return [void]
|
|
205
|
+
#
|
|
206
|
+
# @example String value
|
|
207
|
+
# myscript.os_requirements "10.5, 10.5.3, 10.6.x"
|
|
208
|
+
#
|
|
209
|
+
# @example Array value
|
|
210
|
+
# ok_oses = ['10.5', '10.5.3', '10.6.x']
|
|
211
|
+
# myscript.os_requirements ok_oses
|
|
212
|
+
#
|
|
213
|
+
# @example Minimum OS
|
|
214
|
+
# myscript.os_requirements ">=10.7.5"
|
|
215
|
+
#
|
|
210
216
|
def os_requirements=(new_val)
|
|
211
|
-
|
|
217
|
+
# nil should be an empty array
|
|
212
218
|
new_val = [] if new_val.to_s.empty?
|
|
213
219
|
|
|
214
|
-
|
|
220
|
+
# if any value starts with >=, expand it
|
|
215
221
|
case new_val
|
|
216
222
|
when String
|
|
217
223
|
new_val = JSS.expand_min_os(new_val) if new_val =~ /^>=/
|
|
@@ -223,17 +229,17 @@ module JSS
|
|
|
223
229
|
raise JSS::InvalidDataError, 'os_requirements must be a String or an Array of strings'
|
|
224
230
|
end # case
|
|
225
231
|
|
|
226
|
-
|
|
232
|
+
# get the array version
|
|
227
233
|
@os_requirements = JSS.to_s_and_a(new_val)[:arrayform]
|
|
228
234
|
@need_to_update = true
|
|
229
235
|
end # os_requirements=
|
|
230
236
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
+
# Change the priority of this script
|
|
238
|
+
#
|
|
239
|
+
# @param new_val[Integer] the new priority, which must be one of {PRIORITIES}
|
|
240
|
+
#
|
|
241
|
+
# @return [void]
|
|
242
|
+
#
|
|
237
243
|
def priority=(new_val)
|
|
238
244
|
return nil if new_val == @priority
|
|
239
245
|
new_val = DEFAULT_PRIORITY if new_val.nil? || (new_val == '')
|
|
@@ -242,47 +248,47 @@ module JSS
|
|
|
242
248
|
@need_to_update = true
|
|
243
249
|
end # priority=
|
|
244
250
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
+
# Change the info field
|
|
252
|
+
#
|
|
253
|
+
# @param new_val[String] the new info
|
|
254
|
+
#
|
|
255
|
+
# @return [void]
|
|
256
|
+
#
|
|
251
257
|
def info=(new_val)
|
|
252
258
|
return nil if new_val == @info
|
|
253
|
-
|
|
259
|
+
# line breaks should be \r
|
|
254
260
|
new_val = new_val.to_s.tr("\n", "\r")
|
|
255
261
|
@info = new_val
|
|
256
262
|
@need_to_update = true
|
|
257
263
|
end # info=
|
|
258
264
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
+
# Change the notes field
|
|
266
|
+
#
|
|
267
|
+
# @param new_val[String] the new notes
|
|
268
|
+
#
|
|
269
|
+
# @return [void]
|
|
270
|
+
#
|
|
265
271
|
def notes=(new_val)
|
|
266
272
|
return nil if new_val == @notes
|
|
267
|
-
|
|
273
|
+
# line breaks should be \r
|
|
268
274
|
new_val = new_val.to_s.tr("\n", "\r")
|
|
269
275
|
@notes = new_val
|
|
270
276
|
@need_to_update = true
|
|
271
277
|
end # notes=
|
|
272
278
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
279
|
+
# Replace all the script parameters at once.
|
|
280
|
+
#
|
|
281
|
+
# This will replace the entire set with the hash provided.
|
|
282
|
+
#
|
|
283
|
+
# @param new_val[Hash] the Hash keys must exist in {PARAMETER_KEYS}
|
|
284
|
+
#
|
|
285
|
+
# @return [void]
|
|
286
|
+
#
|
|
281
287
|
def parameters=(new_val)
|
|
282
288
|
return nil if new_val == @parameters
|
|
283
289
|
new_val = {} if new_val.nil? || (new_val == '')
|
|
284
290
|
|
|
285
|
-
|
|
291
|
+
# check the values
|
|
286
292
|
raise JSS::InvalidDataError, ':parameters must be a Hash with keys :parameter4 thru :parameter11' unless \
|
|
287
293
|
new_val.is_a?(Hash) && ((new_val.keys & PARAMETER_KEYS) == new_val.keys)
|
|
288
294
|
new_val.each do |_k, v|
|
|
@@ -293,14 +299,14 @@ module JSS
|
|
|
293
299
|
@need_to_update = true
|
|
294
300
|
end # parameters=
|
|
295
301
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
302
|
+
# Change one of the stored parameters
|
|
303
|
+
#
|
|
304
|
+
# @param param_num[Integer] which param are we setting? must be 4..11
|
|
305
|
+
#
|
|
306
|
+
# @param new_val[String] the new value for the parameter
|
|
307
|
+
#
|
|
308
|
+
# @return [void]
|
|
309
|
+
#
|
|
304
310
|
def set_parameter(param_num, new_val)
|
|
305
311
|
raise JSS::NoSuchItemError, 'Parameter numbers must be from 4-11' unless (4..11).cover? param_num
|
|
306
312
|
pkey = "parameter#{param_num}".to_sym
|
|
@@ -309,21 +315,23 @@ module JSS
|
|
|
309
315
|
@parameters[pkey] = new_val
|
|
310
316
|
@need_to_update = true
|
|
311
317
|
end
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
318
|
+
alias set_parameter_label set_parameter
|
|
319
|
+
alias set_parameter_description set_parameter
|
|
320
|
+
|
|
321
|
+
# Change the executable code of this script.
|
|
322
|
+
#
|
|
323
|
+
# If the arg is a Pathname instance, or a String starting with "/"
|
|
324
|
+
# Then the arg is assumed to be a file from which to read the code.
|
|
325
|
+
#
|
|
326
|
+
# Otherwise it should be a String with the code itself, and it must start with '#!"
|
|
327
|
+
#
|
|
328
|
+
# After doing this, use {#create} or {#update} to write it to the database or
|
|
329
|
+
# use {#upload_master_file} to save it to the master dist. point.
|
|
330
|
+
#
|
|
331
|
+
# @param new_val[String,Pathname] the new script contents or a path to a file containing it.
|
|
332
|
+
#
|
|
333
|
+
# @return [void]
|
|
334
|
+
#
|
|
327
335
|
def script_contents=(new_val)
|
|
328
336
|
new_code = case new_val
|
|
329
337
|
when String
|
|
@@ -341,207 +349,89 @@ module JSS
|
|
|
341
349
|
raise JSS::InvalidDataError, "Script contents must start with '#!'" unless new_code.start_with? '#!'
|
|
342
350
|
|
|
343
351
|
@script_contents = new_code
|
|
352
|
+
@script_contents_encoded = Base64.encode64 @script_contents
|
|
344
353
|
@need_to_update = true
|
|
345
354
|
end
|
|
346
355
|
|
|
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
|
-
### @return [Boolean] was the file deleted?
|
|
381
|
-
###
|
|
382
|
-
def delete_master_file(rw_pw, unmount = true)
|
|
383
|
-
file = JSS::DistributionPoint.master_distribution_point.mount(rw_pw, :rw) + "#{DIST_POINT_SCRIPTS_FOLDER}/#{@filename}"
|
|
384
|
-
if file.exist?
|
|
385
|
-
file.delete
|
|
386
|
-
did_it = true
|
|
387
|
-
else
|
|
388
|
-
did_it = false
|
|
389
|
-
end # if exists
|
|
390
|
-
JSS::DistributionPoint.master_distribution_point.unmount if unmount
|
|
391
|
-
did_it
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
### Run this script on the current machine using the "jamf runScript" command.
|
|
395
|
-
###
|
|
396
|
-
### If the script code is available in the {#script_contents} attribute, then that
|
|
397
|
-
### code is saved to a tmp file, and executed. Otherwise, the script is assumed
|
|
398
|
-
### to be stored on the distribution point.
|
|
399
|
-
###
|
|
400
|
-
### If the dist. point has http downloads enabled, then the URL is used as the path with the
|
|
401
|
-
### 'jamf runScript' command.
|
|
402
|
-
###
|
|
403
|
-
### If http is not an option, the dist.point is mounted, and the script copied locally before running.
|
|
404
|
-
### In this case the options must include :ro_pw => 'somepass'
|
|
405
|
-
### to provide the read-only password for mounting the distribution point. If :unmount => true
|
|
406
|
-
### is provided, the dist. point will be unmounted immediately after copying
|
|
407
|
-
### the script locally. Otherwise it will remain mounted, in case there's further need of it.
|
|
408
|
-
###
|
|
409
|
-
### Any local on-disk copies of the script are removed after running.
|
|
410
|
-
###
|
|
411
|
-
### After the script runs, this method returns a two-item Array.
|
|
412
|
-
### - the first item is an Integer, the exit status of the script itself (0 means success)
|
|
413
|
-
### - the second item is a String, the output (stdout + stderr) of the jamf binary, which will include
|
|
414
|
-
### the script output.
|
|
415
|
-
### The exit status of the jamf binary process will be available as a Process::Status object
|
|
416
|
-
### in $? immediately after running.
|
|
417
|
-
###
|
|
418
|
-
### @param opts[Hash] the options for running the script
|
|
419
|
-
###
|
|
420
|
-
### @option opts :target[String,Pathname] the 'target drive', passed to the script as the first commandline option.
|
|
421
|
-
### Defaults to '/'
|
|
422
|
-
###
|
|
423
|
-
### @option opts :computer_name[String] the name of the computer, passed to the script as the second commandline
|
|
424
|
-
### option. Defaults to the name of the current machine
|
|
425
|
-
###
|
|
426
|
-
### @option opts :username[String] the username to be passed to the script as the third commandline option.
|
|
427
|
-
###
|
|
428
|
-
### @option opts :p1..:p8[String] the values to be passed as the 4th - 11th commandline options, overriding
|
|
429
|
-
### those defined with the script in the JSS
|
|
430
|
-
###
|
|
431
|
-
### @option opts :ro_pw[String] the read-only password for mounting the distribution point, if needed
|
|
432
|
-
###
|
|
433
|
-
### @option opts :unmount[Boolean} should the dist. point be unmounted when finished, if we mounted it?
|
|
434
|
-
###
|
|
435
|
-
### @option opts :verbose[Boolean] should the 'jamf runScript' command be verbose?
|
|
436
|
-
###
|
|
437
|
-
### @option opts :show_output[Boolean] should the output (stdout + stderr) of 'jamf runScript' be copied to
|
|
438
|
-
### stdout in realtime, as well as returned?
|
|
439
|
-
###
|
|
440
|
-
### @return [Array<(Integer,String)>] the exit status of the *script* and stdout+stderr of 'jamf runScript'.
|
|
441
|
-
### The exit status of the jamf binary will be available in $? immediately after running.
|
|
442
|
-
###
|
|
443
|
-
### *NOTE* In the WEB UI and API, the definable parameters are numbered 4-11, since 1, 2, & 3 are the
|
|
444
|
-
### target drive, computer name, and user name respectively. However, the jamf binary refers to them as
|
|
445
|
-
### p1-p8, and that's how they are expected as options to #run. So if :p1=> "new param" is given as an
|
|
446
|
-
### aption to #run, it will override any value that the API provided in @parameters[:parameter4]
|
|
447
|
-
###
|
|
356
|
+
# Run this script on the current machine.
|
|
357
|
+
#
|
|
358
|
+
# If the script code is available in the {#script_contents} attribute, then that
|
|
359
|
+
# code is saved to a tmp file, and executed. The tmp file is deleted immediately
|
|
360
|
+
# after running
|
|
361
|
+
#
|
|
362
|
+
# After the script runs, this method returns a two-item Array.
|
|
363
|
+
# - the first item is an Integer, the exit status of the script itself (0 means success)
|
|
364
|
+
# - the second item is a String, the output (stdout + stderr) of the script.
|
|
365
|
+
#
|
|
366
|
+
# The exit status of the jamf binary process will be available as a Process::Status object
|
|
367
|
+
# in $? immediately after running.
|
|
368
|
+
#
|
|
369
|
+
# @param opts[Hash] the options for running the script
|
|
370
|
+
#
|
|
371
|
+
# @option opts :target[String,Pathname] the 'target drive', passed to the script as the first commandline option.
|
|
372
|
+
# Defaults to '/'
|
|
373
|
+
#
|
|
374
|
+
# @option opts :computer_name[String] the name of the computer, passed to the script as the second commandline
|
|
375
|
+
# option. Defaults to the name of the current machine
|
|
376
|
+
#
|
|
377
|
+
# @option opts :username[String] the username to be passed to the script as the third commandline option.
|
|
378
|
+
# Defaults to the current console user.
|
|
379
|
+
#
|
|
380
|
+
# @option opts :p4..:p11[String] the values to be passed as the 4th - 11th commandline params
|
|
381
|
+
# Script params 1, 2, & 3 are the target:, computer_name: and username: params
|
|
382
|
+
#
|
|
383
|
+
# @option opts :show_output[Boolean] should the output (stdout + stderr) be copied to
|
|
384
|
+
# stdout in realtime, as well as returned?
|
|
385
|
+
#
|
|
386
|
+
# @return [Array<(Integer,String)>] the exit status and stdout+stderr of the script
|
|
387
|
+
#
|
|
448
388
|
def run(opts = {})
|
|
449
|
-
|
|
450
|
-
opts[:p1] ||= @parameters[:parameter4]
|
|
451
|
-
opts[:p2] ||= @parameters[:parameter5]
|
|
452
|
-
opts[:p3] ||= @parameters[:parameter6]
|
|
453
|
-
opts[:p4] ||= @parameters[:parameter7]
|
|
454
|
-
opts[:p5] ||= @parameters[:parameter8]
|
|
455
|
-
opts[:p6] ||= @parameters[:parameter9]
|
|
456
|
-
opts[:p7] ||= @parameters[:parameter10]
|
|
457
|
-
opts[:p8] ||= @parameters[:parameter11]
|
|
458
|
-
|
|
459
|
-
dp_mount_pt = nil
|
|
460
|
-
delete_exec = false
|
|
461
|
-
|
|
462
|
-
begin
|
|
463
|
-
|
|
464
|
-
# do we have the code already? if so, save it out and make it executable
|
|
465
|
-
if @script_contents && !@script_contents.empty?
|
|
466
|
-
|
|
467
|
-
script_path = JSS::Client::DOWNLOADS_FOLDER
|
|
468
|
-
|
|
469
|
-
executable = script_path + @filename
|
|
470
|
-
|
|
471
|
-
executable.jss_touch
|
|
472
|
-
executable.chmod 0o700
|
|
473
|
-
executable.jss_save @script_contents
|
|
474
|
-
delete_exec = true
|
|
475
|
-
|
|
476
|
-
# otherwise, get it from the dist. point
|
|
477
|
-
else
|
|
478
|
-
dist_point = JSS::DistributionPoint.my_distribution_point api: @api
|
|
389
|
+
raise JSS::MissingDataError, 'script_contents does not start with #!' unless @script_contents.to_s.start_with? '#!'
|
|
479
390
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
else
|
|
485
|
-
dp_mount_pt = dist_point.mount opts[:ro_pw]
|
|
486
|
-
|
|
487
|
-
script_path = (dp_mount_pt + DIST_POINT_SCRIPTS_FOLDER)
|
|
488
|
-
|
|
489
|
-
end # if http enabled
|
|
490
|
-
|
|
491
|
-
end # if @script_contents and (not @script_contents.empty?)
|
|
492
|
-
|
|
493
|
-
# build the command as an array.
|
|
494
|
-
command_arry = ['-script', @filename, '-path', script_path.to_s]
|
|
495
|
-
|
|
496
|
-
command_arry << '-target'
|
|
497
|
-
command_arry << opts[:target].to_s
|
|
498
|
-
|
|
499
|
-
command_arry << '-computerName' if opts[:computer_name]
|
|
500
|
-
command_arry << opts[:computer_name] if opts[:computer_name]
|
|
501
|
-
|
|
502
|
-
command_arry << '-username' if opts[:username]
|
|
503
|
-
command_arry << opts[:username] if opts[:username]
|
|
504
|
-
|
|
505
|
-
command_arry << '-p1' if opts[:p1]
|
|
506
|
-
command_arry << opts[:p1] if opts[:p1]
|
|
507
|
-
|
|
508
|
-
command_arry << '-p2' if opts[:p2]
|
|
509
|
-
command_arry << opts[:p2] if opts[:p2]
|
|
510
|
-
|
|
511
|
-
command_arry << '-p3' if opts[:p3]
|
|
512
|
-
command_arry << opts[:p3] if opts[:p3]
|
|
513
|
-
|
|
514
|
-
command_arry << '-p4' if opts[:p4]
|
|
515
|
-
command_arry << opts[:p4] if opts[:p4]
|
|
516
|
-
|
|
517
|
-
command_arry << '-p5' if opts[:p5]
|
|
518
|
-
command_arry << opts[:p5] if opts[:p5]
|
|
391
|
+
opts[:target] ||= '/'
|
|
392
|
+
opts[:computer_name] ||= JSS::Client.run_jamf('getComputerName')[/>(.)</, 1]
|
|
393
|
+
opts[:username] ||= JSS::Client.console_user
|
|
519
394
|
|
|
520
|
-
|
|
521
|
-
|
|
395
|
+
params = [opts[:target], opts[:computer_name], opts[:username]]
|
|
396
|
+
params << opts[:p4]
|
|
397
|
+
params << opts[:p5]
|
|
398
|
+
params << opts[:p6]
|
|
399
|
+
params << opts[:p7]
|
|
400
|
+
params << opts[:p8]
|
|
401
|
+
params << opts[:p9]
|
|
402
|
+
params << opts[:p10]
|
|
403
|
+
params << opts[:p11]
|
|
522
404
|
|
|
523
|
-
|
|
524
|
-
|
|
405
|
+
# everything must be a string
|
|
406
|
+
params.map! &:to_s
|
|
525
407
|
|
|
526
|
-
|
|
527
|
-
|
|
408
|
+
# remove nils
|
|
409
|
+
params.compact!
|
|
528
410
|
|
|
529
|
-
|
|
411
|
+
# remove empty strings
|
|
412
|
+
params.delete_if &:empty?
|
|
530
413
|
|
|
531
|
-
|
|
414
|
+
return_value = []
|
|
532
415
|
|
|
533
|
-
|
|
416
|
+
# Save and run the script from a private temp dir
|
|
417
|
+
# which will be deleted when finished
|
|
418
|
+
require 'tmpdir'
|
|
419
|
+
Dir.mktmpdir do |dir|
|
|
420
|
+
executable = Pathname.new "#{dir}/#{@name}"
|
|
421
|
+
executable.jss_touch
|
|
422
|
+
executable.chmod 0o700
|
|
423
|
+
executable.jss_save @script_contents
|
|
534
424
|
|
|
535
|
-
|
|
425
|
+
cmd = [executable.to_s]
|
|
426
|
+
cmd += params
|
|
536
427
|
|
|
537
|
-
|
|
428
|
+
stdout_and_stderr_str, status = Open3.capture2e(*cmd)
|
|
538
429
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
end # begin/ensure
|
|
430
|
+
return_value << status.exitstatus
|
|
431
|
+
return_value << stdout_and_stderr_str
|
|
432
|
+
end # Dir.mktmpdirs
|
|
543
433
|
|
|
544
|
-
|
|
434
|
+
return_value
|
|
545
435
|
end # def run
|
|
546
436
|
|
|
547
437
|
# aliases under their methods seem to confuse the YARD documenter, so I'm putting them all here.
|
|
@@ -552,13 +442,13 @@ module JSS
|
|
|
552
442
|
alias contents script_contents
|
|
553
443
|
alias contents= script_contents=
|
|
554
444
|
|
|
555
|
-
|
|
445
|
+
# Private Instance Methods
|
|
556
446
|
#####################################
|
|
557
447
|
|
|
558
448
|
private
|
|
559
449
|
|
|
560
|
-
|
|
561
|
-
|
|
450
|
+
# Return the xml for creating or updating this script in the JSS
|
|
451
|
+
#
|
|
562
452
|
def rest_xml
|
|
563
453
|
doc = REXML::Document.new
|
|
564
454
|
scpt = doc.add_element 'script'
|
|
@@ -579,7 +469,7 @@ module JSS
|
|
|
579
469
|
PARAMETER_KEYS.each { |p| pars.add_element(p.to_s).text = @parameters[p] }
|
|
580
470
|
end
|
|
581
471
|
|
|
582
|
-
scpt.add_element('script_contents_encoded').text =
|
|
472
|
+
scpt.add_element('script_contents_encoded').text = script_contents_encoded
|
|
583
473
|
|
|
584
474
|
doc.to_s
|
|
585
475
|
end # rest xml
|