ruby-jss 0.6.3

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.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/CHANGES.md +112 -0
  4. data/LICENSE.txt +174 -0
  5. data/README.md +426 -0
  6. data/THANKS.md +6 -0
  7. data/bin/cgrouper +485 -0
  8. data/bin/subnet-update +400 -0
  9. data/lib/jss-api.rb +2 -0
  10. data/lib/jss.rb +190 -0
  11. data/lib/jss/api_connection.rb +410 -0
  12. data/lib/jss/api_object.rb +616 -0
  13. data/lib/jss/api_object/advanced_search.rb +389 -0
  14. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
  15. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
  16. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
  17. data/lib/jss/api_object/building.rb +92 -0
  18. data/lib/jss/api_object/category.rb +147 -0
  19. data/lib/jss/api_object/computer.rb +852 -0
  20. data/lib/jss/api_object/creatable.rb +98 -0
  21. data/lib/jss/api_object/criteriable.rb +189 -0
  22. data/lib/jss/api_object/criteriable/criteria.rb +231 -0
  23. data/lib/jss/api_object/criteriable/criterion.rb +228 -0
  24. data/lib/jss/api_object/department.rb +93 -0
  25. data/lib/jss/api_object/distribution_point.rb +560 -0
  26. data/lib/jss/api_object/extendable.rb +221 -0
  27. data/lib/jss/api_object/extension_attribute.rb +466 -0
  28. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
  29. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
  30. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
  31. data/lib/jss/api_object/group.rb +380 -0
  32. data/lib/jss/api_object/group/computer_group.rb +124 -0
  33. data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
  34. data/lib/jss/api_object/group/user_group.rb +139 -0
  35. data/lib/jss/api_object/ldap_server.rb +535 -0
  36. data/lib/jss/api_object/locatable.rb +286 -0
  37. data/lib/jss/api_object/matchable.rb +97 -0
  38. data/lib/jss/api_object/mobile_device.rb +556 -0
  39. data/lib/jss/api_object/netboot_server.rb +148 -0
  40. data/lib/jss/api_object/network_segment.rb +414 -0
  41. data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
  42. data/lib/jss/api_object/package.rb +839 -0
  43. data/lib/jss/api_object/peripheral.rb +335 -0
  44. data/lib/jss/api_object/peripheral_type.rb +295 -0
  45. data/lib/jss/api_object/policy.rb +898 -0
  46. data/lib/jss/api_object/purchasable.rb +316 -0
  47. data/lib/jss/api_object/removable_macaddr.rb +98 -0
  48. data/lib/jss/api_object/scopable.rb +136 -0
  49. data/lib/jss/api_object/scopable/scope.rb +621 -0
  50. data/lib/jss/api_object/script.rb +631 -0
  51. data/lib/jss/api_object/self_servable.rb +356 -0
  52. data/lib/jss/api_object/site.rb +93 -0
  53. data/lib/jss/api_object/software_update_server.rb +109 -0
  54. data/lib/jss/api_object/updatable.rb +117 -0
  55. data/lib/jss/api_object/uploadable.rb +138 -0
  56. data/lib/jss/api_object/user.rb +272 -0
  57. data/lib/jss/client.rb +504 -0
  58. data/lib/jss/compatibility.rb +66 -0
  59. data/lib/jss/composer.rb +185 -0
  60. data/lib/jss/configuration.rb +306 -0
  61. data/lib/jss/db_connection.rb +298 -0
  62. data/lib/jss/exceptions.rb +95 -0
  63. data/lib/jss/ruby_extensions.rb +35 -0
  64. data/lib/jss/ruby_extensions/filetest.rb +43 -0
  65. data/lib/jss/ruby_extensions/hash.rb +79 -0
  66. data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
  67. data/lib/jss/ruby_extensions/pathname.rb +77 -0
  68. data/lib/jss/ruby_extensions/string.rb +59 -0
  69. data/lib/jss/ruby_extensions/time.rb +63 -0
  70. data/lib/jss/server.rb +108 -0
  71. data/lib/jss/utility.rb +478 -0
  72. data/lib/jss/version.rb +31 -0
  73. metadata +187 -0
@@ -0,0 +1,6 @@
1
+ # With Thanks To...
2
+
3
+ * Pixar Systems Management
4
+ * The Pixar Mac Team
5
+ * JAMF Folks
6
+ * Alex
@@ -0,0 +1,485 @@
1
+ #!/usr/bin/ruby
2
+
3
+ ### Copyright 2016 Pixar
4
+ ###
5
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
6
+ ### with the following modification; you may not use this file except in
7
+ ### compliance with the Apache License and the following modification to it:
8
+ ### Section 6. Trademarks. is deleted and replaced with:
9
+ ###
10
+ ### 6. Trademarks. This License does not grant permission to use the trade
11
+ ### names, trademarks, service marks, or product names of the Licensor
12
+ ### and its affiliates, except as required to comply with Section 4(c) of
13
+ ### the License and to reproduce the content of the NOTICE file.
14
+ ###
15
+ ### You may obtain a copy of the Apache License at
16
+ ###
17
+ ### http://www.apache.org/licenses/LICENSE-2.0
18
+ ###
19
+ ### Unless required by applicable law or agreed to in writing, software
20
+ ### distributed under the Apache License with the above modification is
21
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22
+ ### KIND, either express or implied. See the Apache License for the specific
23
+ ### language governing permissions and limitations under the Apache License.
24
+
25
+
26
+ # Create or change the membership of a computer group in the JSS
27
+
28
+
29
+ # Load in the JSS library
30
+ require 'jss-api'
31
+
32
+ # Load other libs
33
+ require 'getoptlong'
34
+ require 'ostruct'
35
+
36
+ class App
37
+
38
+ #####################################
39
+ ###
40
+ ### Constants
41
+ ###
42
+ USAGE = "Usage: #{File.basename($0)} [-LsmcdlarRC] [--help] [-n newname]
43
+ [-S server] [-U user] [-T timeout] [-V] [--debug]
44
+ group [-f /file/path ] [computer [computer ...]]"
45
+
46
+ ACTIONS_NEEDING_GROUP = [ :create_group, :rename_group, :delete_group, :add_members, :remove_members, :remove_all, :list_members]
47
+
48
+ ACTIONS_FOR_STATIC_GROUPS_ONLY = [:create_group, :add_members, :remove_members, :remove_all]
49
+
50
+ #####################################
51
+ ### Attributes
52
+
53
+ attr_reader :debug
54
+
55
+ #####################################
56
+ ###
57
+ ### set up
58
+ ###
59
+ def initialize(args)
60
+
61
+ @debug = false
62
+
63
+ # define the options
64
+ cli_opts = GetoptLong.new(
65
+ [ '--help', '-h', '-H', GetoptLong::NO_ARGUMENT ],
66
+ [ '--list-groups', '-L', GetoptLong::NO_ARGUMENT ],
67
+ [ '--list-static', '-s', GetoptLong::NO_ARGUMENT ],
68
+ [ '--list-smart', '-m', GetoptLong::NO_ARGUMENT ],
69
+ [ '--create-group', '--create', '-c', GetoptLong::NO_ARGUMENT ],
70
+ [ '--rename-group', '--rename', '-n', GetoptLong::REQUIRED_ARGUMENT ],
71
+ [ '--delete-group', '--delete', '-d', GetoptLong::NO_ARGUMENT ],
72
+ [ '--list-members', '--list-computers', '-l', GetoptLong::NO_ARGUMENT ],
73
+ [ '--add-members', '--add', '-a', GetoptLong::NO_ARGUMENT ],
74
+ [ '--remove-members', '--remove', '-r', GetoptLong::NO_ARGUMENT ],
75
+ [ '--remove-all-members', '-R', GetoptLong::NO_ARGUMENT ],
76
+ [ '--file', '-f', GetoptLong::REQUIRED_ARGUMENT ],
77
+ [ '--server', '-S', GetoptLong::OPTIONAL_ARGUMENT],
78
+ [ '--port', '-P', GetoptLong::OPTIONAL_ARGUMENT],
79
+ [ '--user', '-U', GetoptLong::OPTIONAL_ARGUMENT],
80
+ [ '--no-verify-cert', '-V', GetoptLong::NO_ARGUMENT],
81
+ [ '--timeout', '-T', GetoptLong::OPTIONAL_ARGUMENT],
82
+ [ '--no-confirm', '-C', GetoptLong::NO_ARGUMENT],
83
+ [ '--debug', GetoptLong::NO_ARGUMENT]
84
+ )
85
+
86
+ # here's where we hold cmdline args and other user options
87
+ @options = OpenStruct.new
88
+
89
+ # set defaults
90
+ @options.action = :none
91
+
92
+ # if stdin is not a tty, then we must assume
93
+ # we're being passed a password
94
+ @options.getpass = $stdin.tty? ? :prompt : :stdin
95
+
96
+ # parse the options
97
+ cli_opts.each do |opt, arg|
98
+ case opt
99
+ when '--help'
100
+ show_help
101
+
102
+ when '--list-groups'
103
+ @options.action = :list_groups
104
+
105
+ when '--list-static'
106
+ @options.action = :list_static
107
+
108
+ when '--list-smart'
109
+ @options.action = :list_smart
110
+
111
+ when '--list-members'
112
+ @options.action = :list_members
113
+
114
+ when '--create-group'
115
+ @options.action = :create_group
116
+
117
+ when '--rename-group'
118
+ @options.action = :rename_group
119
+ @options.new_name = arg
120
+
121
+ when '--delete-group'
122
+ @options.action = :delete_group
123
+
124
+ when '--add-members'
125
+ @options.action = :add_members
126
+
127
+ when '--remove-members'
128
+ @options.action = :remove_members
129
+
130
+ when '--remove-all-members'
131
+ @options.action = :remove_all
132
+
133
+ when '--file'
134
+ @options.input_file = Pathname.new arg
135
+
136
+ when '--server'
137
+ @options.server = arg
138
+
139
+ when '--port'
140
+ @options.port = arg
141
+
142
+ when '--user'
143
+ @options.user = arg
144
+
145
+ when '--no-verify-cert'
146
+ @options.verify_cert = false
147
+
148
+ when '--timeout'
149
+ @options.timeout = arg
150
+
151
+ when '--no-confirm'
152
+ @options.no_confirm = true
153
+
154
+ when '--debug'
155
+ @debug = true
156
+
157
+ end # case
158
+ end # opts.each
159
+
160
+ @options.group = ARGV.shift
161
+
162
+ # if we were given a file of computer names, read it in
163
+ @options.computers = @options.input_file ? get_computers_from_file : []
164
+
165
+ # and add any computers on the commandline
166
+ @options.computers += ARGV
167
+
168
+ # will we say anything when finished?
169
+ @done_msg = nil
170
+
171
+ end # init
172
+
173
+
174
+
175
+ #####################################
176
+ ###
177
+ ### Do It
178
+ ###
179
+ def run
180
+
181
+ if @options.action == :none
182
+ puts USAGE
183
+ return
184
+ end
185
+
186
+ # use any config settings defined....
187
+ @options.user ||= JSS::CONFIG.api_username
188
+ @options.server ||= JSS::CONFIG.api_server_name
189
+
190
+ raise JSS::MissingDataError, "No JSS Username provided or found in the JSS gem config." unless @options.user
191
+ raise JSS::MissingDataError, "No JSS Server provided or found in the JSS gem config." unless @options.server
192
+
193
+ JSS::API.connect( :server => @options.server,
194
+ :port => @options.port,
195
+ :verify_cert => @options.verify_cert,
196
+ :user => @options.user,
197
+ :pw => @options.getpass,
198
+ :stdin_line => 1,
199
+ :timeout => @options.timeout
200
+ )
201
+
202
+
203
+ if ACTIONS_NEEDING_GROUP.include? @options.action
204
+
205
+ raise JSS::MissingDataError, "Please specify a group name" unless @options.group
206
+
207
+ # get the group from the API
208
+ if @options.action == :create_group
209
+ @group = JSS::ComputerGroup.new :id => :new, :name => @options.group, :type => :static
210
+ else
211
+ @group = JSS::ComputerGroup.new :name => @options.group
212
+ end
213
+
214
+ end # if ACTIONS_NEEDING_GROUP
215
+
216
+ # smart groups can't have some things done to them
217
+ raise InvalidTypeError, "You can't do that to a smart group. Use the JSS WebApp if needed." if ACTIONS_FOR_STATIC_GROUPS_ONLY.include? @options.action and @group.smart?
218
+
219
+
220
+ case @options.action
221
+
222
+ when :list_groups
223
+ list_groups
224
+
225
+ when :list_static
226
+ list_groups :static
227
+
228
+ when :list_smart
229
+ list_groups :smart
230
+
231
+ when :list_members
232
+ list_members
233
+
234
+ when :create_group
235
+ create_group
236
+
237
+ when :rename_group
238
+ rename_group
239
+
240
+ when :delete_group
241
+ delete_group
242
+
243
+ when :add_members
244
+ add_members
245
+
246
+ when :remove_members
247
+ remove_members
248
+
249
+ when :remove_all
250
+ remove_all
251
+
252
+ end # case @options.action
253
+
254
+ puts "Done! #{@done_msg}" if @done_msg
255
+
256
+ end # run
257
+
258
+
259
+ #####################################
260
+ ###
261
+ ### Show Help
262
+ ###
263
+ def show_help
264
+ puts <<-FULLHELP
265
+ A tool for working with computer groups in the JSS.
266
+
267
+ #{USAGE}
268
+
269
+ Options:
270
+ -L, --list-groups - list all computer groups in the JSS
271
+ -s, --list-static - list all static computer groups in the JSS
272
+ -m, --list-smart - list all smart computer groups in the JSS
273
+ -c, --create-group - create a new static computer group in the JSS
274
+ -n, --rename newname - rename the specified computer group to newname
275
+ -d, --delete - delete the specified computer group (static groups only)
276
+ -l, --list-members - list all the computers in the group specified
277
+ -a, --add-members - add the specified computer(s) to the specified group
278
+ -r, --remove-members - remove the specified computer(s) from the specified group
279
+ -R, --remove-all - remove all computers from the specified group
280
+ -f, --file /path/... - read computer names/ids from the file at /path/...
281
+ -S, --server srvr - specify the JSS API server name
282
+ -P, --port portnum - specify the JSS API port
283
+ -U, --user username - specify the JSS API user
284
+ -V, --no-verify-cert - Allow self-signed, unverified SSL certificate
285
+ -T, --timeout secs - specify the JSS API timeout
286
+ -C - don't ask for confirmation before acting
287
+ --debug - show the ruby backtrace when errors occur
288
+ -H, --help - show this help
289
+
290
+ Notes:
291
+
292
+ - If no API settings are provided, they will be read from /etc/jss_gem.conf
293
+ and ~/.jss_gem.conf. See the JSS Gem docs for details.
294
+
295
+ - The password for the connection will be read from STDIN or prompted if needed
296
+
297
+ - Computers can be specified by name or JSS id number. If a name exists
298
+ more than once in the JSS, the machine is skipped. Use IDs to avoid this.
299
+
300
+ - Only static groups can be modified. Use the JSS WebUI for editing smart groups
301
+
302
+ - If a file is used to specify computers, they are combined with any
303
+ specified on the commandline.
304
+
305
+ - Files of computers must be whitespace-separated
306
+ (spaces, tabs, & returns in any number or combination)
307
+
308
+ FULLHELP
309
+ return
310
+ end
311
+
312
+ #####################################
313
+ ###
314
+ ### Spit out a list of all computer groups
315
+ ###
316
+ def list_groups(show = :all)
317
+ case show
318
+ when :all
319
+ label = "All"
320
+ groups_to_show = JSS::ComputerGroup.all
321
+ when :static
322
+ label = "Static"
323
+ groups_to_show = JSS::ComputerGroup.all_static
324
+ when :smart
325
+ label = "Smart"
326
+ groups_to_show = JSS::ComputerGroup.all_smart
327
+ end #case
328
+
329
+ puts "# #{label} computer groups in the JSS"
330
+ puts "#---------------------------------------------"
331
+
332
+ groups_to_show.sort{|a,b| a[:name].downcase <=> b[:name].downcase}.each do |grp|
333
+ puts grp[:name]
334
+ end
335
+ end
336
+
337
+ #####################################
338
+ ###
339
+ ### Spit out a list of all computers in a group
340
+ ###
341
+ def list_members
342
+ puts "# All members of JSS #{@group.smart? ? 'smart' : 'static'} computer group '#{@options.group}'"
343
+ puts "#--- name (id) ---------------------------------"
344
+
345
+ # put them into a tmp array, so that
346
+ # we can sort by computer name, remembering that
347
+ # there can be duplicate names.
348
+ list = []
349
+ @group.members.each{|mem| list << "#{mem[:name]} (#{mem[:id]})" }
350
+ puts list.sort #.join("\n")
351
+ end
352
+
353
+
354
+ #####################################
355
+ ###
356
+ ### Create a new group
357
+ ###
358
+ def create_group
359
+
360
+ return unless confirm "create a new static group named '#{@options.group}'"
361
+ @group.create
362
+
363
+ unless @options.computers.empty?
364
+ add_members
365
+ end
366
+
367
+ end
368
+
369
+ #####################################
370
+ ###
371
+ ### rename a group
372
+ ###
373
+ def rename_group
374
+ return unless confirm "rename group '#{@group.name}' to '#{@options.new_name}'"
375
+ @group.name = @options.new_name
376
+ @group.update
377
+ end
378
+
379
+
380
+ #####################################
381
+ ###
382
+ ### delete a group
383
+ ###
384
+ def delete_group
385
+ return unless confirm "DELETE group '#{@group.name}'"
386
+ @group.delete
387
+ end
388
+
389
+
390
+ #####################################
391
+ ###
392
+ ### add members to a group
393
+ ###
394
+ def add_members
395
+ raise JSS::MissingDataError, "No computer names provided" if @options.computers.empty?
396
+ raise JSS::UnsupportedError, "Smart group members can't be changed." if @group.smart?
397
+ return unless @options.action == :create_group or confirm "add computers to group '#{@group.name}'"
398
+
399
+ @options.computers.each do |c|
400
+ begin
401
+ @group.add_member c
402
+ rescue JSS::NoSuchItemError
403
+ puts "#{$!} - skipping"
404
+ end # begin
405
+ end # each
406
+
407
+ @group.update
408
+ end
409
+
410
+ #####################################
411
+ ###
412
+ ### remove members from a group
413
+ ###
414
+ def remove_members
415
+ raise JSS::MissingDataError, "No computer names provided" if @options.computers.empty?
416
+ raise JSS::UnsupportedError, "Smart group members can't be changed." if @group.smart?
417
+ return unless confirm "remove computers from group '#{@group.name}'"
418
+ @options.computers.each do |c|
419
+ begin
420
+ @group.remove_member c
421
+ rescue JSS::NoSuchItemError
422
+ puts "#{$!} - skipping"
423
+ end
424
+ end
425
+ @group.update
426
+ end
427
+
428
+ #####################################
429
+ ###
430
+ ### remove all members from a group
431
+ ###
432
+ def remove_all
433
+ raise JSS::UnsupportedError, "Smart group members can't be changed." if @group.smart?
434
+ return unless confirm "remove ALL computers from group '#{@group.name}'"
435
+ @group.clear
436
+ @group.update
437
+ end
438
+
439
+
440
+ #####################################
441
+ ###
442
+ ### Read computer names from a file
443
+ ### Generally the names should be one per line, but
444
+ ### they can be separated by any whitespace.
445
+ ### Returns an array of computer names from the file.
446
+ ###
447
+ def get_computers_from_file
448
+ raise JSS::NoSuchItemError "File #{@options.input_file} isn't a file or isn't readable." unless \
449
+ @options.input_file.file? and @options.input_file.readable?
450
+ @options.input_file.read.split(/\s+/)
451
+ end
452
+
453
+ #####################################
454
+ ###
455
+ ### Get confirmation before doing something
456
+ ### Returns true or false
457
+ ###
458
+ def confirm (action)
459
+ return true if @options.no_confirm
460
+
461
+ print "Really #{action}? (y/n): "
462
+ $stdin.reopen '/dev/tty'
463
+ reply = $stdin.gets.strip
464
+ return true if reply =~ /^y/i
465
+ return false
466
+
467
+ end # confirm
468
+
469
+
470
+ end # class App
471
+
472
+ #######################################
473
+ begin
474
+ app = App.new(ARGV)
475
+ app.run
476
+
477
+ rescue
478
+ # handle exceptions not handled elsewhere
479
+ puts "An error occurred: #{$!}"
480
+ puts "Backtrace:" if app.debug
481
+ puts $@ if app.debug
482
+
483
+ ensure
484
+
485
+ end