nv-client 1.66.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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in nventory-client.gemspec
4
+ gemspec
data/README ADDED
@@ -0,0 +1,5 @@
1
+ version 1.66.0 of the nVentory ruby client.
2
+
3
+ You'll need to create an /etc/nventory.conf or $HOME/.nventory.conf with at least the following parameter:
4
+
5
+ server = http://nventory.myserver.com
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/nv ADDED
@@ -0,0 +1,709 @@
1
+ #!/usr/bin/env ruby
2
+ ##############################################################################
3
+ # A client to query a nVentory server
4
+ ##############################################################################
5
+
6
+ require 'optparse'
7
+ require 'nventory'
8
+
9
+ # Ensure we have a sane path, particularly since we might be run from
10
+ # cron in registration mode.
11
+ ENV['PATH'] = '/bin:/usr/bin:/sbin:/usr/sbin'
12
+
13
+ #
14
+ # Process command line options
15
+ #
16
+
17
+ $objecttype = 'nodes'
18
+ $get = nil
19
+ $exactget = nil
20
+ $regexget = nil
21
+ $and = nil
22
+ $exclude = nil
23
+ $name = nil
24
+ $allfields = nil
25
+ $fields = nil
26
+ $set = nil
27
+ $yes = false
28
+ $getfieldnames = false
29
+ $getallvalues = nil
30
+ $nodegroup = nil
31
+ $nodegroupexpanded = nil
32
+ $createnodegroup = nil
33
+ $addnodegroupnodeassignments = nil
34
+ $addtonodegroup = nil
35
+ $removefromnodegroup = nil
36
+ $addnodegrouptonodegroup = nil
37
+ $addcomment = nil
38
+ $removenodegroupfromnodegroup = nil
39
+ $createtag = nil
40
+ $addtagtonodegroup = nil
41
+ $removetagfromnodegroup = nil
42
+ $register = false
43
+ $username = ENV['LOGNAME']
44
+ $delete = nil
45
+ $showtags = nil
46
+ $withaliases = nil
47
+ $debug = nil
48
+ $dryrun = nil
49
+ $server = nil
50
+
51
+ def singularize(string)
52
+ if string =~ /(.*s)es$/
53
+ singular = $1
54
+ elsif string =~ /(.*)s$/
55
+ singular = $1;
56
+ else
57
+ singular = string
58
+ end
59
+ return singular;
60
+ end
61
+
62
+ def opt_hash_parse(opt)
63
+ opthash = {}
64
+ current_field = nil
65
+ opt.split(',').each do |entry|
66
+ if (entry =~ /(.+)=(.+)/)
67
+ current_field = $1
68
+ opthash[current_field] = [$2]
69
+ else
70
+ if current_field
71
+ opthash[current_field] << entry
72
+ else
73
+ abort "Failed to parse '#{opt}' as a series of name=value[,value] pairs"
74
+ end
75
+ end
76
+ end
77
+ opthash
78
+ end
79
+
80
+ opts = OptionParser.new
81
+ opts.banner = 'Usage: nv [options]'
82
+ opts.on('--objecttype object',
83
+ 'The type of object to get/set. Defaults to nodes.') do |opt|
84
+ $objecttype = opt
85
+ end
86
+ opts.on('--get [field=value1,value2][,field2=value1[,value2]]') do |opt|
87
+ if opt.nil?
88
+ $get = {}
89
+ else
90
+ $get = opt_hash_parse(opt)
91
+ end
92
+ end
93
+ opts.on('--showtags', 'Lists all tags the node(s) belongs to') do |opt|
94
+ $showtags = opt
95
+ end
96
+ opts.on('--delete', 'Delete the object(s) returned') do |opt|
97
+ $delete = opt
98
+ end
99
+ opts.on('--exactget [field=value1,value2]',
100
+ 'Select objects for display or updating. get does a substring',
101
+ 'match, exactget does an exact match. Multiple fields and values ',
102
+ 'can be specified seperated by commas.') do |opt|
103
+ if opt.nil?
104
+ $exactget = {}
105
+ else
106
+ $exactget = opt_hash_parse(opt)
107
+ end
108
+ end
109
+ opts.on('--regexget [field=value1,value2]',
110
+ 'Select objects for display or updating. get does a substring',
111
+ 'match, regexget does an regexp match. Multiple fields and values ',
112
+ 'can be specified seperated by commas.') do |opt|
113
+ if opt.nil?
114
+ $regexget = {}
115
+ else
116
+ $regexget = opt_hash_parse(opt)
117
+ end
118
+ end
119
+ opts.on('--exclude [field=value1,value2]',
120
+ 'Select objects for display or updating. get does a substring',
121
+ 'match, exclude does an regexp match. Multiple fields and values ',
122
+ 'can be specified seperated by commas.') do |opt|
123
+ if opt.nil?
124
+ $exclude = {}
125
+ else
126
+ $exclude = opt_hash_parse(opt)
127
+ end
128
+ end
129
+ opts.on('--and [field=value1,value2]',
130
+ 'when doing get, search AND values on same field',
131
+ 'can be specified seperated by commas.') do |opt|
132
+ if opt.nil?
133
+ $and = {}
134
+ else
135
+ $and = opt_hash_parse(opt)
136
+ end
137
+ end
138
+ opts.on('--name value[,value2]', Array,
139
+ 'Shortcut for --get name=value') do |opt|
140
+ $name = opt
141
+ end
142
+ opts.on('--addcomment "add your comment here"', Array) do |opt|
143
+ $addcomment = opt
144
+ end
145
+ opts.on('--allfields [excludefield1[,excludefield2]]', Array,
146
+ 'Display all fields for selected objects.',
147
+ 'One or more fields may be specified to be excluded from the',
148
+ 'query, seperate multiple fields with commas.') do |opt|
149
+ if opt.nil?
150
+ $allfields = []
151
+ else
152
+ $allfields = opt
153
+ end
154
+ end
155
+ opts.on('--fields field1[,field2]', Array,
156
+ 'Display the specified fields for selected objects.',
157
+ 'One or more fields may be specified, either by specifying this',
158
+ 'option multiple times or by seperating the field names with',
159
+ 'commas.') do |opt|
160
+ if opt.nil?
161
+ $fields = []
162
+ else
163
+ $fields = opt
164
+ end
165
+ end
166
+ opts.on('--set field=value1[,value2][,field2=value1[,value2]]',
167
+ 'Update fields in objects selected via get/exactget/regexget/exclude, Multiple ',
168
+ 'fields and values can be specified seperated by commas.') do |opt|
169
+ $set = opt_hash_parse(opt)
170
+ end
171
+ opts.on('--yes',
172
+ 'Don\'t prompt for set confirmation') do |opt|
173
+ $yes = true
174
+ end
175
+ opts.on('--getfieldnames',
176
+ 'Shows get/set fields supported by server') do |opt|
177
+ $getfieldnames = true
178
+ end
179
+ opts.on('--getallvalues field1[,field2]', Array,
180
+ 'Display all values stored in the database for the specified fields') do |opt|
181
+ $getallvalues = opt
182
+ end
183
+ opts.on('--nodegroup nodegroup', '--ng nodegroup',
184
+ 'Display the members of the given node group, member groups are',
185
+ 'displayed as groups and are not expanded') do |opt|
186
+ $nodegroup = opt
187
+ end
188
+ opts.on('--nodegroupexpanded nodegroup[,nodegroup2]', '--nge nodegroup', '--get_nodegroup_nodes nodegroup', '--get_ngn nodegroup', Array,
189
+ 'Display the members of the given node groups, member groups are',
190
+ 'expanded') do |opt|
191
+ $nodegroupexpanded = opt
192
+ end
193
+ opts.on('--createnodegroup nodegroup1[,nodegroup2]', Array,
194
+ 'Create one or more node groups') do |opt|
195
+ $createnodegroup = opt
196
+ end
197
+ opts.on('--addnodegroupnodeassignments nodegroup1[,nodegroup2]', Array,
198
+ 'Assign nodes selected via get/exactget/regexget/exclude to one or more node groups') do |opt|
199
+ $addnodegroupnodeassignments = opt
200
+ end
201
+ opts.on('--addtonodegroup nodegroup1[,nodegroup2]', Array,
202
+ 'Add nodes selected via get/exactget/regexget/exclude to one or more node groups') do |opt|
203
+ $addtonodegroup = opt
204
+ end
205
+ opts.on('--removefromnodegroup nodegroup1[,nodegroup2]', Array,
206
+ 'Remove nodes selected via get/exactget/regexget/exclude from one or more node groups') do |opt|
207
+ $removefromnodegroup = opt
208
+ end
209
+ opts.on('--addnodegrouptonodegroup child_group,parent_group', Array,
210
+ 'Takes two node group names seperated by a comma, adds the first',
211
+ 'node group to the second') do |opt|
212
+ $addnodegrouptonodegroup = [opt[0],opt[1]]
213
+ end
214
+ opts.on('--removenodegroupfromnodegroup child_group,parent_group', Array,
215
+ 'Takes two node group names seperated by a comma, removes the first',
216
+ 'node group from the second') do |opt|
217
+ $removenodegroupfromnodegroup = [opt[0],opt[1]]
218
+ end
219
+ opts.on('--createtag tagname1[,tagname2]', Array,
220
+ 'Create one or more tags by name') do |opt|
221
+ $createtag= opt
222
+ end
223
+ opts.on('--addtagtonodegroup tag,node_group', Array,
224
+ 'adds a tag to a node_group') do |opt|
225
+ $addtagtonodegroup = [opt[0],opt[1]]
226
+ end
227
+ opts.on('--removetagfromnodegroup tag,node_group', Array,
228
+ 'removes a tag from a node_group') do |opt|
229
+ $removetagfromnodegroup = [opt[0],opt[1]]
230
+ end
231
+ opts.on('--register',
232
+ 'Gather as much information as possible about the local machine',
233
+ 'and register that information into the nVentory database.') do |opt|
234
+ $register = true
235
+ end
236
+ opts.on('--username value', String,
237
+ 'Username to use when authenticating to the server. If not',
238
+ 'specified defaults to the current user.') do |opt|
239
+ $username = opt
240
+ end
241
+ opts.on('--server value', String, 'Specify alternate server to query.') do |opt|
242
+ $server = opt
243
+ end
244
+ opts.on('--debug') do |opt|
245
+ $debug = opt
246
+ end
247
+ opts.on('--withaliases') do |opt|
248
+ $withaliases = opt
249
+ end
250
+ opts.on('--dry-run') do |opt|
251
+ $dryrun = opt
252
+ end
253
+ opts.separator ''
254
+ opts.separator('All options can be shortened to anything that\'s unique.')
255
+ opts.on_tail('--help') do
256
+ puts opts
257
+ exit
258
+ end
259
+
260
+ opts.parse(ARGV)
261
+
262
+ (puts opts; exit) unless $get || $exactget || $regexget || $name || $getfieldnames || $getallvalues || $register || $nodegroup || $nodegroupexpanded || $createnodegroup || $addnodegrouptonodegroup || $removenodegroupfromnodegroup || $addtagtonodegroup || $createtag || $removetagfromnodegroup
263
+ # These options are mutually exclusive
264
+ (puts opts; exit) if $allfields && $fields
265
+ (puts opts; exit) if $getfieldnames && ($get || $exactget || $regexget || $name)
266
+ (puts opts; exit) if $getallvalues && ($get || $exactget || $regexget || $name)
267
+ # FIXME: Should support searches on node group membership and other characteristics
268
+ (puts opts; exit) if ($nodegroup || $nodegroupexpanded) && ($get || $exactget || $regexget || $exclude || $name || $and)
269
+ (puts opts; exit) if $register && ($get || $exactget || $regexget || $exclude || $name || $getfieldnames || $getallvalues || $nodegroup || $nodegroupexpanded || $createnodegroup || $addnodegrouptonodegroup || $removenodegroupfromnodegroup || $and || $createtag || $addtagtonodegroup || $removetagfromnodegroup)
270
+ (puts opts; exit) if ($addtonodegroup || $addnodegroupnodeassignments || $removefromnodegroup || $addtagtonodegroup || $removetagfromnodegroup) && $objecttype != 'nodes'
271
+ (puts '--showtags can only be used if objecttype = nodes'; exit) if $showtags && ($objecttype !~ /^(nodes|node_groups)$/)
272
+
273
+ if $name
274
+ $get = {} if !$get
275
+ $get['name'] = $name
276
+ end
277
+
278
+ SEARCH_SHORTCUTS = {
279
+ 'hw' => 'hardware_profile[name]',
280
+ 'hwmanuf' => 'hardware_profile[manufacturer]',
281
+ 'hwmodel' => 'hardware_profile[model]',
282
+ 'ip' => 'ip_addresses',
283
+ 'ips' => 'ip_addresses',
284
+ 'mac' => 'network_interfaces[hardware_address]',
285
+ 'macs' => 'network_interfaces[hardware_address]',
286
+ 'nic' => 'network_interfaces',
287
+ 'nics' => 'network_interfaces',
288
+ 'node_group' => 'node_group[name]',
289
+ 'node_groups' => 'node_group[name]',
290
+ 'os' => 'operating_system[name]',
291
+ 'osvendor' => 'operating_system[vendor]',
292
+ 'osvariant' => 'operating_system[variant]',
293
+ 'osver' => 'operating_system[version_number]',
294
+ 'osversion' => 'operating_system[version_number]',
295
+ 'osarch' => 'operating_system[architecture]',
296
+ 'serial' => 'serial_number',
297
+ 'status' => 'status[name]',
298
+ }
299
+
300
+ # Convert any shortcut names to their full names
301
+ if $get
302
+ $get.each_pair do |key,value|
303
+ if SEARCH_SHORTCUTS.has_key?(key)
304
+ $get[SEARCH_SHORTCUTS[key]] = value
305
+ $get.delete(key)
306
+ end
307
+ end
308
+ end
309
+ if $exactget
310
+ $exactget.each_pair do |key,value|
311
+ if SEARCH_SHORTCUTS.has_key?(key)
312
+ $exactget[SEARCH_SHORTCUTS[key]] = value
313
+ $exactget.delete(key)
314
+ end
315
+ end
316
+ end
317
+ if $regexget
318
+ $regexget.each_pair do |key,value|
319
+ if SEARCH_SHORTCUTS.has_key?(key)
320
+ $regexget[SEARCH_SHORTCUTS[key]] = value
321
+ $regexget.delete(key)
322
+ end
323
+ end
324
+ end
325
+ if $exclude
326
+ $exclude.each_pair do |key,value|
327
+ if SEARCH_SHORTCUTS.has_key?(key)
328
+ $exclude[SEARCH_SHORTCUTS[key]] = value
329
+ $exclude.delete(key)
330
+ end
331
+ end
332
+ end
333
+ if $and
334
+ $and.each_pair do |key,value|
335
+ if SEARCH_SHORTCUTS.has_key?(key)
336
+ $and[SEARCH_SHORTCUTS[key]] = value
337
+ $and.delete(key)
338
+ end
339
+ end
340
+ end
341
+ if $set
342
+ $set.each_pair do |key,value|
343
+ if SEARCH_SHORTCUTS.has_key?(key)
344
+ $set[SEARCH_SHORTCUTS[key]] = value
345
+ $set.delete(key)
346
+ end
347
+ end
348
+ end
349
+ if $allfields
350
+ # The ideal behavior here is probably debatable. For now I'm _adding_
351
+ # the expanded value to the list of exclusions, so both the shortcut
352
+ # string and the expanded value are excluded. That allows the user to
353
+ # specify 'os' on the command line and get the probably expected behavior
354
+ # of excluding everything containing 'os' even though 'os' expands to
355
+ # something specific, but also allows them to specify 'hwmanuf' and have
356
+ # it exclude the expanded version of that.
357
+ # Perhaps we should do something like get and exactget?
358
+ $allfields.each do |key|
359
+ if SEARCH_SHORTCUTS.has_key?(key)
360
+ # Replace shortcut with expansion
361
+ #$allfields[$allfields.index(key)] = SEARCH_SHORTCUTS[key]
362
+ # Add expansion
363
+ $allfields << SEARCH_SHORTCUTS[key]
364
+ end
365
+ end
366
+ end
367
+ if $fields
368
+ $fields.each do |key|
369
+ if SEARCH_SHORTCUTS.has_key?(key)
370
+ $fields[$fields.index(key)] = SEARCH_SHORTCUTS[key]
371
+ end
372
+ end
373
+ end
374
+
375
+ #
376
+ # Perform requested actions
377
+ #
378
+
379
+ nvclient = NVentory::Client.new($debug, $dryrun, nil, $server)
380
+
381
+ # First handle the standalone actions where we perform a single
382
+ # operation and exit.
383
+
384
+ if $getfieldnames
385
+ field_names = nvclient.get_field_names($objecttype)
386
+ field_names.each do |field_name_entry|
387
+ field_name = field_name_entry.split(' ')
388
+ shortcut = nil
389
+ shortcut_field_name = nil
390
+ SEARCH_SHORTCUTS.each_pair do |shortcut, shortcut_field_name|
391
+ if field_name == shortcut_field_name
392
+ field_name_entry << " (#{shortcut})"
393
+ end
394
+ end
395
+ puts field_name_entry
396
+ end
397
+ exit
398
+ end
399
+ if $register
400
+ nvclient.register
401
+ exit
402
+ end
403
+ if $nodegroup
404
+ getdata = {}
405
+ getdata[:objecttype] = 'node_groups'
406
+ getdata[:exactget] = {'name' => [$nodegroup]}
407
+ getdata[:includes] = ['child_groups', 'nodes']
408
+ results = nvclient.get_objects(getdata)
409
+ matches = results.keys.grep(/\b#{$nodegroup}\b/i)
410
+ matches.size == 1 ? ( $nodegroup = matches.first ) : return
411
+ puts "Child groups:"
412
+ results[$nodegroup]['child_groups'].sort{|a,b| a['name'] <=> b['name']}.each do |child_group|
413
+ puts " #{child_group['name']}"
414
+ end
415
+ puts "===================="
416
+ puts "Real Nodes:"
417
+ if results[$nodegroup]['real_nodes_names']
418
+ results[$nodegroup]['real_nodes_names'].split(",").sort{|a,b| a <=> b}.each do |node|
419
+ puts " #{node}"
420
+ end
421
+ end
422
+ puts "===================="
423
+ puts "Virtual Nodes:"
424
+ if results[$nodegroup]['virtual_nodes_names']
425
+ results[$nodegroup]['virtual_nodes_names'].split(",").sort{|a,b| a <=> b}.each do |node|
426
+ puts " #{node}"
427
+ end
428
+ end
429
+ end
430
+ if $createnodegroup
431
+ $createnodegroup.each do |newgroup|
432
+ nvclient.set_objects('node_groups', nil, {'name' => newgroup}, $username)
433
+ end
434
+ exit
435
+ end
436
+ if $addnodegrouptonodegroup
437
+ getdata = {}
438
+ getdata[:objecttype] = 'node_groups'
439
+ getdata[:exactget] = {'name' => [$addnodegrouptonodegroup[0]]}
440
+ child_results = nvclient.get_objects(getdata)
441
+ abort "Child group '#{$addnodegrouptonodegroup[0]}' not found for 'addnodegrouptonodegroup'\n" if (child_results.length != 1)
442
+ getdata = {}
443
+ getdata[:objecttype] = 'node_groups'
444
+ getdata[:exactget] = {'name' => [$addnodegrouptonodegroup[1]]}
445
+ getdata[:includes] = ['child_groups']
446
+ parent_results = nvclient.get_objects(getdata)
447
+ abort "Parent group '#{$addnodegrouptonodegroup[1]}' not found for 'addnodegrouptonodegroup'\n" if (parent_results.length != 1)
448
+ nvclient.add_nodegroups_to_nodegroups(child_results, parent_results, $username)
449
+ exit
450
+ end
451
+ if $removenodegroupfromnodegroup
452
+ getdata = {}
453
+ getdata[:objecttype] = 'node_groups'
454
+ getdata[:exactget] = {'name' => [$removenodegroupfromnodegroup[0]]}
455
+ child_results = nvclient.get_objects(getdata)
456
+ abort "Child group '#{$removenodegroupfromnodegroup[0]}' not found for 'removenodegroupfromnodegroup'\n" if (child_results.length != 1)
457
+ getdata = {}
458
+ getdata[:objecttype] = 'node_groups'
459
+ getdata[:exactget] = {'name' => [$removenodegroupfromnodegroup[1]]}
460
+ getdata[:includes] = ['child_groups']
461
+ parent_results = nvclient.get_objects(getdata)
462
+ abort "Parent group '#{$removenodegroupfromnodegroup[1]}' not found for 'removenodegroupfromnodegroup'\n" if (parent_results.length != 1)
463
+ nvclient.remove_nodegroups_from_nodegroups(child_results, parent_results, $username)
464
+ exit
465
+ end
466
+
467
+ if $createtag
468
+ $createtag.each do |tag|
469
+ nvclient.set_objects('tags', nil, {'name' => tag}, $username)
470
+ end
471
+ exit
472
+ end
473
+ if $addtagtonodegroup
474
+ getdata = {}
475
+ getdata[:objecttype] = 'node_groups'
476
+ getdata[:exactget] = {'name' => [$addtagtonodegroup[1]]}
477
+ ng_results = nvclient.get_objects(getdata)
478
+ abort "Node group '#{$addtagtonodegroup[1]}' not found for 'addtagtonodegroup'\n" if (ng_results.length != 1)
479
+ nvclient.add_tag_to_node_group(ng_results, $addtagtonodegroup[0], $username)
480
+ exit
481
+ end
482
+ if $removetagfromnodegroup
483
+ getdata = {}
484
+ getdata[:objecttype] = 'node_groups'
485
+ getdata[:exactget] = {'name' => [$removetagfromnodegroup[1]]}
486
+ ng_results = nvclient.get_objects(getdata)
487
+ abort "Node group '#{$removetagfromnodegroup[1]}' not found for 'removetagfromnodegroup'\n" if (ng_results.length != 1)
488
+ nvclient.remove_tag_from_node_group(ng_results, $removetagfromnodegroup[0], $username)
489
+ exit
490
+ end
491
+
492
+ # Now handle the general case where we fetch a list of objects and then
493
+ # perform operations on them.
494
+
495
+ # If the user has requested data which lies outside the base object model
496
+ # then we need to tell the server to include that data in the results it
497
+ # sends us.
498
+ # For example, in a 'nodes' search the user requests the
499
+ # 'hardware_profile[name]' field then we need to request that
500
+ # 'hardware_profile' data be included in the results.
501
+ includes = nil
502
+ if $fields
503
+ includes_hash = {}
504
+ $fields.each do |field|
505
+ if field =~ /([^\[]+)\[.+\]/
506
+ includes_hash[$1] = true
507
+ end
508
+ end
509
+ includes = includes_hash.keys.sort
510
+ elsif $allfields
511
+ includes_hash = {}
512
+ field_names = nvclient.get_field_names($objecttype)
513
+ field_names.each do |field_name_entry|
514
+ field_name, rest = field_name_entry.split(' ')
515
+ if field_name =~ /([^\[]+)\[.+\]/
516
+ includes_hash[$1] = true
517
+ end
518
+ end
519
+ includes = includes_hash.keys.sort
520
+ end
521
+
522
+ results = nil
523
+ names = nil
524
+ if $get || $exactget || $regexget
525
+ $get['enable_aliases'] = 1 if $withaliases
526
+ getdata = {}
527
+ getdata[:objecttype] = $objecttype
528
+ getdata[:get] = $get
529
+ getdata[:exactget] = $exactget
530
+ getdata[:regexget] = $regexget
531
+ getdata[:exclude] = $exclude
532
+ getdata[:and] = $and
533
+ if $showtags
534
+ includes ||= []
535
+ includes.delete('node_groups') if includes.include?('node_groups')
536
+ $fields ||= []
537
+ if $objecttype == 'nodes'
538
+ $fields << 'node_groups[name]' unless $fields.include?('node_groups[name]')
539
+ $fields << 'node_groups[tags][name]' unless $fields.include?('node_groups[tags][name]')
540
+ includes << 'node_groups[tags]' unless includes.include?('node_groups[tags]')
541
+ elsif $objecttype == 'node_groups'
542
+ $fields << 'tags[name]' unless $fields.include?('tags[name]')
543
+ includes << 'tags' unless includes.include?('tags')
544
+ end
545
+ end # if $showtags
546
+ getdata[:includes] = includes
547
+ results = nvclient.get_objects(getdata)
548
+ if $delete
549
+ puts "Deleting objects"
550
+ nvclient.delete_objects($objecttype, results, $username)
551
+ else
552
+ names = results.keys.sort
553
+ end
554
+ end
555
+
556
+ if $addcomment
557
+ objtype = singularize($objecttype)
558
+ results.keys.each do |key|
559
+ nvclient.set_objects('comments', nil,
560
+ { 'comment' => $addcomment,
561
+ 'commentable_id' => results[key]['id'],
562
+ 'commentable_type' => objtype.capitalize,
563
+ },
564
+ $username);
565
+ end
566
+ end
567
+
568
+ if $nodegroupexpanded
569
+ names_hash = {}
570
+ $nodegroupexpanded.each do |nge|
571
+ nvclient.get_expanded_nodegroup(nge).each { |name| names_hash[name] = true }
572
+ end
573
+ names = names_hash.keys.sort
574
+ if $allfields || $fields || $getallvalues
575
+ getdata = {}
576
+ getdata[:objecttype] = 'nodes'
577
+ getdata[:exactget] = {'name' => names}
578
+ getdata[:includes] = includes
579
+ results = nvclient.get_objects(getdata)
580
+ end
581
+ end
582
+
583
+ if names && !$delete
584
+ if names.length == 0
585
+ puts "No matching objects"
586
+ exit
587
+ end
588
+ end
589
+
590
+ # The results hash is a complex data structure. This function
591
+ # does its best to render that in a human readable format.
592
+ def fieldprint(fields, value)
593
+ # fields=['name'] => 'name'
594
+ # fields=['status', 'name'] => 'status[name]'
595
+ fieldname = ''
596
+ if fields.length > 0
597
+ fieldname << fields[0]
598
+ if fields.length > 1
599
+ fields[1..-1].each { |f| fieldname << "[#{f}]"}
600
+ end
601
+ end
602
+
603
+ if value.kind_of?(Hash)
604
+ value.each_pair do |subfield, subvalue|
605
+ fieldprint([fields, subfield].flatten, subvalue)
606
+ end
607
+ elsif value.kind_of?(Array)
608
+ value.each do |entry|
609
+ fieldprint(fields, entry)
610
+ end
611
+ elsif ($allfields && !$allfields.any?{|all| fieldname.include?(all)}) || ($fields && $fields.any?{|field| fieldname.include?(field)})
612
+ puts "#{fieldname}: #{value}"
613
+ end
614
+ end
615
+
616
+ if names && !$getallvalues && !$set && !$addtonodegroup && !$addnodegroupnodeassignments && !$removefromnodegroup && !$delete
617
+ names.each do |name|
618
+ puts name
619
+ if $allfields || $fields
620
+ fieldprint([], results[name])
621
+ puts
622
+ end
623
+ end
624
+ end
625
+
626
+ if $getallvalues
627
+ allvalues = {}
628
+
629
+ # FIXME: This is a terribly inefficient implementation
630
+ # A proper implementation would require something on the
631
+ # server side to pull this out of the database efficiently
632
+ names.each do |name|
633
+ results[name].each_pair do |field,value|
634
+ if $getallvalues.include?(field)
635
+ if !allvalues.has_key?(field)
636
+ allvalues[field] = {}
637
+ end
638
+ allvalues[field][value] = true
639
+ end
640
+ end
641
+ end
642
+
643
+ $getallvalues.each do |field|
644
+ puts "#{field}:"
645
+ allvalues.each_pair do |field,valuehash|
646
+ valuehash.keys.sort do |value|
647
+ puts " #{value}"
648
+ end
649
+ end
650
+ puts
651
+ end
652
+ end
653
+
654
+ if $set
655
+ if !$yes
656
+ number_of_matching_entries = names.length
657
+ entrystring = 'entry'
658
+ entrystring = 'entries' if (number_of_matching_entries > 1)
659
+ print "This will update #{number_of_matching_entries} #{entrystring}, continue? [y/N]: "
660
+
661
+ input = $stdin.gets
662
+ if input !~ /^y/i
663
+ puts "Canceled"
664
+ exit
665
+ end
666
+ end
667
+
668
+ nvclient.set_objects($objecttype, results, $set, $username)
669
+ end
670
+
671
+ if $addtonodegroup or $addnodegroupnodeassignments
672
+ getdata = {}
673
+ getdata[:objecttype] = 'node_groups'
674
+ ngnames = $addtonodegroup || $addnodegroupnodeassignments
675
+ getdata[:exactget] = {'name' => ngnames}
676
+ if $addtonodegroup
677
+ getdata[:includes] = ['nodes']
678
+ end
679
+
680
+ nodegroup_results = nvclient.get_objects(getdata)
681
+ if (nodegroup_results.length != ngnames.length)
682
+ warn "Not all requested node groups for 'addtonodegroup' were found:"
683
+ warn "Requested: #{$addtonodegroup.join(',')}"
684
+ warn "Found: #{nodegroup_results.keys.join(',')}"
685
+ abort
686
+ end
687
+
688
+ if $addtonodegroup
689
+ nvclient.add_nodes_to_nodegroups(results, nodegroup_results, $username);
690
+ elsif $addnodegroupnodeassignments
691
+ nvclient.add_node_group_node_assignments(results, nodegroup_results, $username);
692
+ end
693
+ end
694
+
695
+ if $removefromnodegroup
696
+ getdata = {}
697
+ getdata[:objecttype] = 'node_groups'
698
+ getdata[:exactget] = {'name' => $removefromnodegroup}
699
+ getdata[:includes] = ['nodes']
700
+ nodegroup_results = nvclient.get_objects(getdata)
701
+ if (nodegroup_results.length != $removefromnodegroup.length)
702
+ warn "Not all requested node groups for 'removefromnodegroup' were found:"
703
+ warn "Requested: #{$removefromnodegroup.join(',')}"
704
+ warn "Found: #{nodegroup_results.keys.join(',')}"
705
+ abort
706
+ end
707
+ nvclient.remove_nodes_from_nodegroups(results, nodegroup_results, $username);
708
+ end
709
+