depot3 3.0.15 → 3.0.20
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 +21 -1
- data/README.md +6 -6
- data/bin/d3 +3 -3
- data/bin/d3admin +257 -293
- data/lib/d3/admin/add.rb +98 -94
- data/lib/d3/admin/interactive.rb +195 -161
- data/lib/d3/admin/options.rb +424 -412
- data/lib/d3/admin/prefs.rb +73 -42
- data/lib/d3/admin/validate.rb +50 -43
- data/lib/d3/client/auth.rb +4 -2
- data/lib/d3/client/class_methods.rb +169 -119
- data/lib/d3/client/receipt.rb +2 -2
- data/lib/d3/database.rb +167 -180
- data/lib/d3/log.rb +2 -3
- data/lib/d3/package/server_actions.rb +2 -3
- data/lib/d3/package/validate.rb +63 -70
- data/lib/d3/version.rb +1 -2
- metadata +2 -2
data/lib/d3/admin/add.rb
CHANGED
@@ -24,6 +24,7 @@
|
|
24
24
|
|
25
25
|
###
|
26
26
|
module D3
|
27
|
+
|
27
28
|
module Admin
|
28
29
|
|
29
30
|
### The Admin::Add modile contains constants and methods related to
|
@@ -34,35 +35,35 @@ module D3
|
|
34
35
|
|
35
36
|
### These are the symbols representing all the possible commandline options
|
36
37
|
### used for defining new packages.
|
37
|
-
NEW_PKG_OPTIONS = %
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
38
|
+
NEW_PKG_OPTIONS = %i(
|
39
|
+
version
|
40
|
+
revision
|
41
|
+
package_name
|
42
|
+
description
|
43
|
+
filename
|
44
|
+
category
|
45
|
+
oses
|
46
|
+
cpu_type
|
47
|
+
reboot
|
48
|
+
removable
|
49
|
+
remove_first
|
50
|
+
prohibiting_processes
|
51
|
+
auto_groups
|
52
|
+
excluded_groups
|
53
|
+
pre_install
|
54
|
+
post_install
|
55
|
+
pre_remove
|
56
|
+
post_remove
|
57
|
+
expiration
|
58
|
+
expiration_paths
|
59
|
+
source_path
|
60
|
+
).freeze
|
60
61
|
|
61
62
|
### If we need to build the pkg, these options are needed
|
62
|
-
BUILD_OPTIONS = [:workspace, :package_build_type]
|
63
|
+
BUILD_OPTIONS = [:workspace, :package_build_type].freeze
|
63
64
|
|
64
65
|
### If we are building a .pkg these options are needed
|
65
|
-
PKG_OPTIONS = [:pkg_identifier, :pkg_preserve_owners]
|
66
|
+
PKG_OPTIONS = [:pkg_identifier, :pkg_preserve_owners, :signing_identity, :signing_options].freeze
|
66
67
|
|
67
68
|
### Continuously loop through displaying the add-package menu, and getting
|
68
69
|
### new values, until the user types 'x'.
|
@@ -71,39 +72,36 @@ module D3
|
|
71
72
|
###
|
72
73
|
### @return [OpenStruct] the new_package_options with validated data
|
73
74
|
###
|
74
|
-
def loop_thru_add_walkthru
|
75
|
-
|
76
|
-
inherited_line = options.inherited_from ? "with values inherited from '#{options.inherited_from}'" : "with global default values"
|
77
|
-
|
78
|
-
|
75
|
+
def loop_thru_add_walkthru(options)
|
76
|
+
inherited_line = options.inherited_from ? "with values inherited from '#{options.inherited_from}'" : 'with global default values'
|
79
77
|
|
80
78
|
choice = nil
|
81
79
|
|
82
80
|
# loop until the user types an x
|
83
|
-
while choice !=
|
81
|
+
while choice != 'x'
|
84
82
|
walkthru_menu_header = <<-END_HEADER
|
85
83
|
------------------------------------
|
86
|
-
Adding pilot d3 package '#{options.edition
|
84
|
+
Adding pilot d3 package '#{options.edition || options.basename}'
|
87
85
|
#{inherited_line}
|
88
86
|
------------------------------------
|
89
87
|
END_HEADER
|
90
88
|
menu_options = NEW_PKG_OPTIONS
|
91
|
-
if options.source_path
|
89
|
+
if options.source_path && get_package_type_from_source(options.source_path) == :root_folder
|
92
90
|
menu_options += BUILD_OPTIONS
|
93
91
|
menu_options += PKG_OPTIONS if options.package_build_type == :pkg
|
94
92
|
end
|
95
93
|
|
96
|
-
choice = D3::Admin::Interactive.get_menu_choice(
|
94
|
+
choice = D3::Admin::Interactive.get_menu_choice(walkthru_menu_header, walkthru_menu_lines(menu_options, options))
|
97
95
|
|
98
96
|
if choice == 'x'
|
99
97
|
(options, errors) = validate_all_new_package_options options
|
100
98
|
if errors.empty?
|
101
99
|
break # while
|
102
100
|
else
|
103
|
-
puts
|
101
|
+
puts '***** ERRORS *****'
|
104
102
|
puts errors.join "\n"
|
105
|
-
puts
|
106
|
-
puts
|
103
|
+
puts '*****'
|
104
|
+
puts 'Type return to continue, ^c to exit'
|
107
105
|
gets
|
108
106
|
choice = 'not x'
|
109
107
|
end # if errors empty
|
@@ -115,10 +113,9 @@ END_HEADER
|
|
115
113
|
# Here the value we're actually editing
|
116
114
|
current_opt_value = options[chosen_opt]
|
117
115
|
|
118
|
-
|
119
116
|
# if we're editing version or revision, and the current pkg or filenames are
|
120
117
|
# based on them then make a note to update the names when we get the new values
|
121
|
-
if chosen_opt == :basename
|
118
|
+
if chosen_opt == :basename || chosen_opt == :version || chosen_opt == :revision
|
122
119
|
update_edition = true
|
123
120
|
update_pkg_name = options.package_name.start_with? options.edition
|
124
121
|
update_filename = options.filename.start_with? options.edition
|
@@ -130,7 +127,7 @@ END_HEADER
|
|
130
127
|
|
131
128
|
# if editing the source or the buildtype, we might have to update the
|
132
129
|
# names as well
|
133
|
-
if chosen_opt == :source_path
|
130
|
+
if chosen_opt == :source_path || chosen_opt == :package_build_type
|
134
131
|
update_pkg_name = options.package_name =~ /\.(m?pkg|dmg)$/
|
135
132
|
update_filename = true
|
136
133
|
end
|
@@ -139,7 +136,7 @@ END_HEADER
|
|
139
136
|
options[chosen_opt] = D3::Admin::Interactive.get_value(chosen_opt, current_opt_value, nil)
|
140
137
|
|
141
138
|
# if we changed the version, reset the revision to 1 and update values as needed
|
142
|
-
if chosen_opt == :version
|
139
|
+
if chosen_opt == :version && options[chosen_opt] != current_opt_value
|
143
140
|
options[:revision] = 1
|
144
141
|
update_edition = true
|
145
142
|
update_pkg_name = options.package_name.start_with? options.edition
|
@@ -152,10 +149,10 @@ END_HEADER
|
|
152
149
|
options.filename = "#{options.edition}.#{options.package_build_type}" if update_filename
|
153
150
|
|
154
151
|
# if we edited the source path, we might need to update the names and the pkg build type
|
155
|
-
if chosen_opt == :source_path
|
152
|
+
if chosen_opt == :source_path && options.source_path.extname =~ /\.(m?pkg|dmg)$/
|
156
153
|
options.package_name.sub(/\.(m?pkg|dmg)$/, options.source_path.extname)
|
157
154
|
options.filename.sub(/\.(m?pkg|dmg)$/, options.source_path.extname)
|
158
|
-
options.package_build_type = options.source_path.extname ==
|
155
|
+
options.package_build_type = options.source_path.extname == '.dmg' ? :dmg : :pkg
|
159
156
|
end
|
160
157
|
|
161
158
|
# ditto if we edited the package_build_type
|
@@ -164,12 +161,11 @@ END_HEADER
|
|
164
161
|
options.filename.sub(/\.(m?pkg|dmg)$/, options.package_build_type.to_s)
|
165
162
|
end
|
166
163
|
|
167
|
-
end #if choice == x
|
164
|
+
end # if choice == x
|
168
165
|
end # while choice not x
|
169
166
|
|
170
167
|
# return the options
|
171
168
|
options
|
172
|
-
|
173
169
|
end # loop_thru_add_walkthru
|
174
170
|
|
175
171
|
### Regenerate the walkthru menu lines
|
@@ -181,12 +177,12 @@ END_HEADER
|
|
181
177
|
###
|
182
178
|
### @return [Array<String>] the lines of the walkthru menu
|
183
179
|
###
|
184
|
-
def walkthru_menu_lines
|
180
|
+
def walkthru_menu_lines(menu_options, current_options)
|
185
181
|
display_lines = []
|
186
182
|
|
187
183
|
menu_options.each_index do |i|
|
188
184
|
# the option symbol, like :reboot
|
189
|
-
#opt = NEW_PKG_OPTIONS[i]
|
185
|
+
# opt = NEW_PKG_OPTIONS[i]
|
190
186
|
opt = menu_options[i]
|
191
187
|
opt_def = D3::Admin::OPTIONS[opt]
|
192
188
|
label = opt_def[:label]
|
@@ -195,7 +191,7 @@ END_HEADER
|
|
195
191
|
value_display = converter ? converter.call(value) : value
|
196
192
|
display_lines[i] = "#{label}: #{value_display}"
|
197
193
|
end
|
198
|
-
|
194
|
+
display_lines
|
199
195
|
end # def walkthru_menu_lines
|
200
196
|
|
201
197
|
### Validate commandline options when adding a package without walkthru
|
@@ -210,17 +206,17 @@ END_HEADER
|
|
210
206
|
###
|
211
207
|
### @return [OpenStruct] the new_package_options with validated data
|
212
208
|
###
|
213
|
-
def add_pilot_cli
|
214
|
-
(new_package_options, errors) = validate_all_new_package_options
|
209
|
+
def add_pilot_cli(cli_options)
|
210
|
+
(new_package_options, errors) = validate_all_new_package_options(cli_options)
|
215
211
|
if errors.empty?
|
216
212
|
return new_package_options
|
217
213
|
else
|
218
|
-
puts
|
214
|
+
puts '***** ERRORS *****'
|
219
215
|
puts errors.join "\n"
|
220
|
-
puts
|
221
|
-
raise ArgumentError,
|
216
|
+
puts '*****'
|
217
|
+
raise ArgumentError, 'Errors in commandline options, see above.'
|
222
218
|
end # if errors empty
|
223
|
-
end #validate_cli_add_pilot
|
219
|
+
end # validate_cli_add_pilot
|
224
220
|
|
225
221
|
### Validate all possible options for making a new pkg.
|
226
222
|
###
|
@@ -235,11 +231,10 @@ END_HEADER
|
|
235
231
|
### @return [Array<OpenStruct, Array>] An array with two items: the possibly-validated options
|
236
232
|
### and an array of error messages, which should be empty if all options are valid.
|
237
233
|
###
|
238
|
-
def validate_all_new_package_options
|
239
|
-
|
234
|
+
def validate_all_new_package_options(options_from_user)
|
240
235
|
# what do we need to check
|
241
236
|
opts_to_check = NEW_PKG_OPTIONS
|
242
|
-
if options_from_user.source_path
|
237
|
+
if options_from_user.source_path && get_package_type_from_source(options_from_user.source_path) == :root_folder
|
243
238
|
opts_to_check += BUILD_OPTIONS
|
244
239
|
opts_to_check += PKG_OPTIONS if options_from_user.package_build_type == :pkg
|
245
240
|
end
|
@@ -273,16 +268,16 @@ END_HEADER
|
|
273
268
|
|
274
269
|
# group overlaps
|
275
270
|
begin
|
276
|
-
|
271
|
+
D3::Package::Validate.validate_non_overlapping_groups options_from_user[:auto_groups], options_from_user[:excluded_groups]
|
277
272
|
rescue JSS::InvalidDataError
|
278
|
-
|
273
|
+
errors << "Auto and Excluded group-lists can't contain groups in common."
|
279
274
|
end
|
280
275
|
|
281
276
|
# expiration path if expiration
|
282
277
|
if options_from_user[:expiration] > 0
|
283
|
-
|
278
|
+
errors << 'expiration path cannot be empty if expiration is > 0 .' unless options_from_user[:expiration_paths]
|
284
279
|
end
|
285
|
-
|
280
|
+
[options_from_user, errors]
|
286
281
|
end # validate_all_new_package_options
|
287
282
|
|
288
283
|
### Figure out the default values for all options for creating a new package
|
@@ -296,7 +291,7 @@ END_HEADER
|
|
296
291
|
dft_opts = OpenStruct.new
|
297
292
|
|
298
293
|
# first populate the opts from the defined defaults for anything that's still nil
|
299
|
-
D3::Admin::OPTIONS.each {|opt, settings| dft_opts[opt] = settings[:default]}
|
294
|
+
D3::Admin::OPTIONS.each { |opt, settings| dft_opts[opt] = settings[:default] }
|
300
295
|
|
301
296
|
dft_opts.basename = basename
|
302
297
|
|
@@ -313,7 +308,7 @@ END_HEADER
|
|
313
308
|
end # if basename
|
314
309
|
|
315
310
|
# edition if available
|
316
|
-
if dft_opts.version
|
311
|
+
if dft_opts.version && dft_opts.revision
|
317
312
|
dft_opts.edition = "#{dft_opts.basename}-#{dft_opts.version}-#{dft_opts.revision}"
|
318
313
|
else
|
319
314
|
dft_opts.edition = nil
|
@@ -330,15 +325,16 @@ END_HEADER
|
|
330
325
|
dft_opts.workspace = D3::Admin::Prefs.prefs[:workspace]
|
331
326
|
dft_opts.workspace ||= D3::Admin::DFT_WORKSPACE
|
332
327
|
|
333
|
-
|
334
328
|
# use the pkg_identifier_prefix from the prefs
|
335
329
|
pfx = D3::Admin::Prefs.prefs[:apple_pkg_id_prefix]
|
336
330
|
pfx ||= D3::Admin::DFT_PKG_ID_PREFIX
|
337
331
|
dft_opts.pkg_identifier ||= "#{pfx}.#{basename}".gsub(/\.+/, '.')
|
338
332
|
|
339
333
|
# We now have our defaults for a new pkg
|
340
|
-
|
334
|
+
dft_opts.signing_identity = D3::Admin::Prefs.prefs[:signing_identity] || ''
|
335
|
+
dft_opts.signing_options = D3::Admin::Prefs.prefs[:signing_options] || ''
|
341
336
|
|
337
|
+
dft_opts
|
342
338
|
end # populate_default_options
|
343
339
|
|
344
340
|
### Get default values from an existing d3 package, and use them to
|
@@ -352,7 +348,6 @@ END_HEADER
|
|
352
348
|
### @return [OpenStruct] an ostruct with the default values
|
353
349
|
###
|
354
350
|
def default_options_from_package(pkg, dft_opts = OpenStruct.new)
|
355
|
-
|
356
351
|
# populate the opts from the pkg, if the pkg has a value
|
357
352
|
D3::Admin::OPTIONS.keys.each do |opt|
|
358
353
|
next unless pkg.respond_to?(opt)
|
@@ -370,7 +365,7 @@ END_HEADER
|
|
370
365
|
|
371
366
|
# grab the first pkg-id if it exists
|
372
367
|
# we might use it to if making a new pkg
|
373
|
-
if pkg.apple_receipt_data
|
368
|
+
if pkg.apple_receipt_data && pkg.apple_receipt_data[0] && pkg.apple_receipt_data[0][:apple_pkg_id]
|
374
369
|
dft_opts.pkg_identifier = pkg.apple_receipt_data[0][:apple_pkg_id]
|
375
370
|
end
|
376
371
|
|
@@ -386,13 +381,13 @@ END_HEADER
|
|
386
381
|
### @return [Symbol] :dmg, :pkg, or :root_folder
|
387
382
|
###
|
388
383
|
def get_package_type_from_source (source_path)
|
389
|
-
if source_path.to_s.end_with?
|
390
|
-
|
384
|
+
if source_path.to_s.end_with? '.dmg'
|
385
|
+
:dmg
|
391
386
|
elsif source_path.to_s =~ /\.m?pkg$/
|
392
|
-
|
387
|
+
:pkg
|
393
388
|
else
|
394
|
-
|
395
|
-
end # if .source_path.to_s.end_with?
|
389
|
+
:root_folder
|
390
|
+
end # if .source_path.to_s.end_with? '.dmg'
|
396
391
|
end
|
397
392
|
|
398
393
|
### Add the new pkg to d3
|
@@ -401,16 +396,17 @@ END_HEADER
|
|
401
396
|
###
|
402
397
|
### @return [Integer] the JSS id of the new package
|
403
398
|
###
|
404
|
-
def add_new_package
|
405
|
-
|
399
|
+
def add_new_package(new_package_options)
|
406
400
|
# new_package_options should now have all the validated data we need to make a new pkg
|
407
|
-
new_pilot = D3::Package.new(
|
408
|
-
:
|
409
|
-
:
|
410
|
-
:
|
411
|
-
:
|
412
|
-
:
|
413
|
-
:
|
401
|
+
new_pilot = D3::Package.new(
|
402
|
+
id: :new,
|
403
|
+
basename: new_package_options.basename,
|
404
|
+
name: new_package_options.package_name,
|
405
|
+
version: new_package_options.version,
|
406
|
+
revision: new_package_options.revision,
|
407
|
+
filename: new_package_options.filename,
|
408
|
+
admin: ENV['USER']
|
409
|
+
)
|
414
410
|
|
415
411
|
D3::Admin::Add::NEW_PKG_OPTIONS.each do |opt|
|
416
412
|
setter = "#{opt}=".to_sym
|
@@ -420,21 +416,28 @@ END_HEADER
|
|
420
416
|
# do we need to build the pkg?
|
421
417
|
unless new_package_options.source_path.extname =~ /\.(m?pkg|dmg)$/
|
422
418
|
if new_package_options.package_build_type == :pkg
|
423
|
-
puts
|
424
|
-
|
419
|
+
puts 'Building .pkg...'
|
420
|
+
|
421
|
+
new_pkg_path = JSS::Composer.mk_pkg(
|
422
|
+
new_package_options.package_name,
|
425
423
|
new_package_options.version,
|
426
424
|
new_package_options.source_path,
|
427
|
-
:
|
428
|
-
:
|
429
|
-
:
|
425
|
+
pkg_id: new_package_options.pkg_identifier,
|
426
|
+
out_dir: new_package_options.workspace,
|
427
|
+
preserve_ownership: new_package_options.pkg_preserve_owners,
|
428
|
+
signing_identity: new_package_options.signing_identity,
|
429
|
+
signing_options: new_package_options.signing_options
|
430
|
+
)
|
430
431
|
|
431
432
|
new_package_options.source_path = new_pkg_path
|
432
433
|
|
433
434
|
elsif new_package_options.package_build_type == :dmg
|
434
|
-
puts
|
435
|
-
new_pkg_path = JSS::Composer.mk_dmg(
|
435
|
+
puts 'Building .dmg...'
|
436
|
+
new_pkg_path = JSS::Composer.mk_dmg(
|
437
|
+
new_package_options.package_name,
|
436
438
|
new_package_options.source_path,
|
437
|
-
new_package_options.workspace
|
439
|
+
new_package_options.workspace
|
440
|
+
)
|
438
441
|
|
439
442
|
new_package_options.source_path = new_pkg_path
|
440
443
|
end # if new_package_options.package_build_type
|
@@ -445,19 +448,20 @@ END_HEADER
|
|
445
448
|
|
446
449
|
new_pkg_id = new_pilot.save
|
447
450
|
|
448
|
-
puts
|
451
|
+
puts 'Indexing...'
|
449
452
|
# make the index - all d3 pkgs are indexed in the JSS
|
450
|
-
new_pilot.mk_index :
|
453
|
+
new_pilot.mk_index local_filepath: new_package_options.source_path
|
451
454
|
|
452
455
|
# upload to dist point
|
453
456
|
# if its a .pkg, the apple rcpt data is updated during the upload
|
454
|
-
puts
|
457
|
+
puts 'Uploading to the Master Distribution Point...'
|
455
458
|
new_pilot.upload_master_file new_package_options.source_path, D3::Admin::Auth.rw_credentials(:dist)[:password]
|
456
459
|
|
457
|
-
|
458
|
-
|
460
|
+
new_pkg_id
|
459
461
|
end # add_new_package
|
460
462
|
|
461
463
|
end # module Add
|
464
|
+
|
462
465
|
end # module Admin
|
466
|
+
|
463
467
|
end # module D3
|
data/lib/d3/admin/interactive.rb
CHANGED
@@ -22,9 +22,9 @@
|
|
22
22
|
###
|
23
23
|
###
|
24
24
|
|
25
|
-
|
26
25
|
###
|
27
26
|
module D3
|
27
|
+
|
28
28
|
module Admin
|
29
29
|
|
30
30
|
### This module contains methods for interacting with the user in the terminal
|
@@ -33,24 +33,24 @@ module D3
|
|
33
33
|
### These methods all return a string of user input, possibly an empty string.
|
34
34
|
###
|
35
35
|
module Interactive
|
36
|
+
|
36
37
|
require 'readline'
|
37
38
|
extend self
|
38
39
|
|
39
40
|
# Set up readline
|
40
41
|
# no spaces at the end of readline completion
|
41
|
-
Readline.completion_append_character =
|
42
|
+
Readline.completion_append_character = ''
|
42
43
|
# names may contain spaces
|
43
|
-
Readline.basic_word_break_characters =
|
44
|
+
Readline.basic_word_break_characters = ''
|
44
45
|
# this appends a / to directories as we auto-complete paths.
|
45
|
-
Readline.completion_proc =
|
46
|
-
files = Dir.glob(str +
|
47
|
-
files.map {|f|
|
46
|
+
Readline.completion_proc = proc do |str|
|
47
|
+
files = Dir.glob(str + '*')
|
48
|
+
files.map { |f| File.directory?(f) ? "#{f}/" : f }
|
48
49
|
end
|
49
50
|
|
51
|
+
UNSET = 'n'.freeze
|
50
52
|
|
51
|
-
|
52
|
-
|
53
|
-
DFT_EDITOR = "/usr/bin/nano -L"
|
53
|
+
DFT_EDITOR = '/usr/bin/nano -L'.freeze
|
54
54
|
|
55
55
|
### Display a menu of numbered choices, and return the user's choice,
|
56
56
|
### or 'x' if the user is done choosing.
|
@@ -61,41 +61,40 @@ module D3
|
|
61
61
|
###
|
62
62
|
### @return [Integer, String] The index of the chosen chosen, or 'x'
|
63
63
|
###
|
64
|
-
def get_menu_choice
|
65
|
-
|
64
|
+
def get_menu_choice(header, items)
|
66
65
|
# add a 1-based number and ) to the start of each line, like 1), and 2)...
|
67
|
-
items.each_index{|i| items[i]
|
66
|
+
items.each_index { |i| items[i] = "#{i + 1}) #{items[i]}" }
|
68
67
|
menu_count = items.count
|
69
68
|
menu_count_display = "(1-#{menu_count}, x=done, ^c=cancel)"
|
70
69
|
|
71
70
|
menu = "#{header}\n#{items.join("\n")}"
|
72
71
|
|
73
72
|
# clear the screen between displays of the menu, so its always at the top.
|
74
|
-
system
|
73
|
+
system 'clear' or system 'cls'
|
75
74
|
puts menu
|
76
|
-
choice =
|
77
|
-
while choice ==
|
75
|
+
choice = ''
|
76
|
+
while choice == ''
|
78
77
|
choice = Readline.readline("Which to change? #{menu_count_display}: ", false)
|
79
78
|
break if choice == 'x'
|
80
79
|
|
81
80
|
# they chose a number..
|
82
81
|
if choice =~ /^\d+$/
|
83
82
|
# map it to one of the editing options
|
84
|
-
choice =
|
83
|
+
choice = choice.to_i - 1
|
85
84
|
# but they might have chosen a higher number than allowws
|
86
|
-
choice =
|
85
|
+
choice = '' unless (0..(menu_count - 1)).cover? choice
|
87
86
|
else
|
88
|
-
choice =
|
87
|
+
choice = ''
|
89
88
|
end
|
90
89
|
|
91
90
|
# tell them they made a bad choice
|
92
|
-
if choice ==
|
91
|
+
if choice == ''
|
93
92
|
puts "\n******* Sorry, invalid choice.\n"
|
94
93
|
next
|
95
94
|
end
|
96
95
|
end # while choice == ""
|
97
96
|
|
98
|
-
|
97
|
+
choice
|
99
98
|
end # get_menu_choice
|
100
99
|
|
101
100
|
### Call one of the get_ methods and do the matching validity check,
|
@@ -114,10 +113,8 @@ module D3
|
|
114
113
|
### @return [Object] the validated data from the user
|
115
114
|
###
|
116
115
|
def get_value(option_or_get_method, default = nil, validate_method = nil)
|
117
|
-
|
118
116
|
# if the option_or_get_method is one of the keys in OPTIONS, then use OPTIONS[get_method][:get] if it exists
|
119
117
|
if D3::Admin::OPTIONS.keys.include?(option_or_get_method)
|
120
|
-
option_to_get = option_or_get_method
|
121
118
|
get_method = D3::Admin::OPTIONS[option_or_get_method][:get]
|
122
119
|
# if we weren't giving a validate method, get it from the OPTIONS
|
123
120
|
validate_method ||= D3::Admin::OPTIONS[option_or_get_method][:validate]
|
@@ -127,7 +124,7 @@ module D3
|
|
127
124
|
|
128
125
|
valid = :start
|
129
126
|
validated = nil
|
130
|
-
until valid === true
|
127
|
+
until valid === true # Keep the ===, trust me. Don't listen to rubocop.
|
131
128
|
puts "\nSorry: #{validated}, Try again.\n" unless valid === :start
|
132
129
|
|
133
130
|
value_input = self.send get_method, default
|
@@ -137,8 +134,8 @@ module D3
|
|
137
134
|
|
138
135
|
(valid, validated) = D3::Admin::Validate.validate(value_input, validate_method)
|
139
136
|
|
140
|
-
end #until valid === true
|
141
|
-
|
137
|
+
end # until valid === true
|
138
|
+
validated
|
142
139
|
end # get value
|
143
140
|
|
144
141
|
### Prompt for user input for an option and return the response.
|
@@ -179,8 +176,7 @@ module D3
|
|
179
176
|
###
|
180
177
|
### @return [String] The data entered by the user, possibly an empty string
|
181
178
|
###
|
182
|
-
def prompt_for_data
|
183
|
-
|
179
|
+
def prompt_for_data(desc: nil, prompt: nil, opt: nil, default: :no_default, required: true)
|
184
180
|
unset_line = nil
|
185
181
|
default_display = default
|
186
182
|
|
@@ -197,26 +193,26 @@ module D3
|
|
197
193
|
|
198
194
|
# some values are special for displaying
|
199
195
|
default_display = case default_display
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
196
|
+
when :no_default then ''
|
197
|
+
when D3::Admin::DFT_REQUIRED then '' # the '---Required---' should only be visible in the menu, not the prompt
|
198
|
+
when D3::Admin::DFT_NONE then UNSET
|
199
|
+
else default_display.to_s
|
200
|
+
end
|
205
201
|
|
206
202
|
data_entered = ''
|
207
203
|
puts "\n#{desc}" if desc
|
208
|
-
prompt ||=
|
209
|
-
hit_return = default_display.empty? ?
|
204
|
+
prompt ||= 'Please enter a value'
|
205
|
+
hit_return = default_display.empty? ? '' : " (Hit return for '#{default_display}' )"
|
210
206
|
prompt_line = "#{prompt}#{hit_return}: "
|
211
207
|
|
212
208
|
while true do
|
213
209
|
data_entered = Readline.readline(prompt_line, false)
|
214
210
|
data_entered = default_display if data_entered == ''
|
215
|
-
break unless required
|
211
|
+
break unless required && data_entered.empty?
|
216
212
|
end
|
217
213
|
# if 'n' was typed for an unsettable option, return nil
|
218
|
-
return nil if opt_def
|
219
|
-
|
214
|
+
return nil if opt_def && opt_def[:unsetable] && data_entered == UNSET
|
215
|
+
data_entered.strip
|
220
216
|
end # prompt_for_data
|
221
217
|
|
222
218
|
### Ask the user for an edition or basename
|
@@ -235,12 +231,12 @@ Enter:
|
|
235
231
|
- 'v' to view a list of all packages with the basenames and editions in d3.
|
236
232
|
END_DESC
|
237
233
|
|
238
|
-
input =
|
239
|
-
while input ==
|
240
|
-
input = prompt_for_data(desc: desc, prompt:
|
241
|
-
D3::Admin::Report.show_all_basenames_and_editions if input ==
|
234
|
+
input = 'v'
|
235
|
+
while input == 'v'
|
236
|
+
input = prompt_for_data(desc: desc, prompt: 'Edition or Basename', default: default, required: true)
|
237
|
+
D3::Admin::Report.show_all_basenames_and_editions if input == 'v'
|
242
238
|
end
|
243
|
-
|
239
|
+
input
|
244
240
|
end # get existing pkg
|
245
241
|
|
246
242
|
### Ask the user for an id or name
|
@@ -248,7 +244,7 @@ Enter:
|
|
248
244
|
###
|
249
245
|
### @return [String] the name or id entered, or nil
|
250
246
|
###
|
251
|
-
def get_jss_package_for_import
|
247
|
+
def get_jss_package_for_import(default = nil)
|
252
248
|
desc = <<-END_DESC
|
253
249
|
IMPORT JSS PACKAGE
|
254
250
|
Enter a package id or display-name for
|
@@ -257,16 +253,16 @@ Enter:
|
|
257
253
|
- 'v' to view a list of all JSS package names not in d3.
|
258
254
|
END_DESC
|
259
255
|
|
260
|
-
input =
|
261
|
-
while input ==
|
262
|
-
input = prompt_for_data(desc: desc, prompt:
|
263
|
-
D3::Admin::Report.show_pkgs_available_for_import if input ==
|
256
|
+
input = 'v'
|
257
|
+
while input == 'v'
|
258
|
+
input = prompt_for_data(desc: desc, prompt: 'JSS id or display name', default: default, required: true)
|
259
|
+
D3::Admin::Report.show_pkgs_available_for_import if input == 'v'
|
264
260
|
end
|
265
|
-
|
261
|
+
input
|
266
262
|
end # get existing pkg
|
267
263
|
|
268
264
|
### get a basename from the user
|
269
|
-
def get_basename
|
265
|
+
def get_basename(default = nil)
|
270
266
|
desc = <<-END_DESC
|
271
267
|
BASENAME
|
272
268
|
Enter a basename.
|
@@ -274,31 +270,31 @@ Enter 'v' to view a list of all basenames in d3 and
|
|
274
270
|
the newest edition for each.
|
275
271
|
END_DESC
|
276
272
|
|
277
|
-
input =
|
278
|
-
while input ==
|
279
|
-
input = prompt_for_data(desc: desc, prompt:
|
280
|
-
D3::Admin::Report.show_all_basenames_and_editions if input ==
|
273
|
+
input = 'v'
|
274
|
+
while input == 'v'
|
275
|
+
input = prompt_for_data(desc: desc, prompt: 'Basename', required: true)
|
276
|
+
D3::Admin::Report.show_all_basenames_and_editions if input == 'v'
|
281
277
|
end
|
282
|
-
|
278
|
+
input
|
283
279
|
end # get basename
|
284
280
|
|
285
281
|
### get a package name from user
|
286
|
-
def get_package_name
|
282
|
+
def get_package_name(default = nil)
|
287
283
|
desc = <<-END_DESC
|
288
284
|
JSS PACKAGE NAME
|
289
285
|
Enter a unique name for this package in d3 and Casper.
|
290
286
|
Enter 'v' to view a list of package names currently in d3.
|
291
287
|
END_DESC
|
292
|
-
input =
|
293
|
-
while input ==
|
288
|
+
input = 'v'
|
289
|
+
while input == 'v'
|
294
290
|
input = prompt_for_data(opt: :package_name, desc: desc, default: default, required: true)
|
295
|
-
D3::Admin::Report.show_existing_package_ids if input ==
|
291
|
+
D3::Admin::Report.show_existing_package_ids if input == 'v'
|
296
292
|
end
|
297
|
-
|
293
|
+
input
|
298
294
|
end # get pkg name
|
299
295
|
|
300
|
-
|
301
|
-
def get_filename
|
296
|
+
### get a package name from user
|
297
|
+
def get_filename(default = nil)
|
302
298
|
desc = <<-END_DESC
|
303
299
|
INSTALLER FILENAME
|
304
300
|
Enter a unique name for this package's installer file
|
@@ -306,12 +302,12 @@ on the master distribution point. The file will be
|
|
306
302
|
renamed to this name on the distribution point.
|
307
303
|
Enter 'v' to see a list of existing pkg filenames in the JSS
|
308
304
|
END_DESC
|
309
|
-
input =
|
310
|
-
while input ==
|
305
|
+
input = 'v'
|
306
|
+
while input == 'v'
|
311
307
|
input = prompt_for_data(opt: :filename, desc: desc, default: default, required: true)
|
312
|
-
D3::Admin::Report.show_existing_package_ids if input ==
|
308
|
+
D3::Admin::Report.show_existing_package_ids if input == 'v'
|
313
309
|
end
|
314
|
-
|
310
|
+
input
|
315
311
|
end # get pkg name
|
316
312
|
|
317
313
|
### Get a version from the user
|
@@ -319,7 +315,7 @@ Enter 'v' to see a list of existing pkg filenames in the JSS
|
|
319
315
|
### @param default[String] the value to use when the user types a return.
|
320
316
|
###
|
321
317
|
### @return [String] the value to use as the version
|
322
|
-
def get_version
|
318
|
+
def get_version(default = nil)
|
323
319
|
desc = <<-END_DESC
|
324
320
|
VERSION
|
325
321
|
Enter a version for this package.
|
@@ -335,7 +331,7 @@ All spaces will be converted to underscores.
|
|
335
331
|
###
|
336
332
|
### @return [String] the value to use as the rev
|
337
333
|
###
|
338
|
-
def get_revision
|
334
|
+
def get_revision(default = nil)
|
339
335
|
desc = <<-END_DESC
|
340
336
|
REVISION
|
341
337
|
Enter a Package revision for this package.
|
@@ -353,16 +349,15 @@ an existing version of a given basename.
|
|
353
349
|
###
|
354
350
|
### @return [String] the desired description
|
355
351
|
###
|
356
|
-
def get_description(current_desc =
|
357
|
-
|
352
|
+
def get_description(current_desc = '')
|
358
353
|
# do we have a current desc to display and possibly keep?
|
359
|
-
current_desc_review =
|
354
|
+
current_desc_review = ''
|
360
355
|
unless current_desc.to_s.empty?
|
361
356
|
current_desc_review = "\n----- Current Description -----\n#{current_desc}\n-------------------------------\n\n"
|
362
357
|
end
|
363
358
|
|
364
359
|
if prefd_editor = D3::Admin::Prefs.prefs[:editor]
|
365
|
-
prefd_editor_choice =
|
360
|
+
prefd_editor_choice = "\n - 'e' to edit using '#{prefd_editor}' "
|
366
361
|
else
|
367
362
|
prefd_editor_choice = ''
|
368
363
|
end
|
@@ -387,26 +382,26 @@ or '#{DFT_EDITOR}' if none is set.
|
|
387
382
|
|
388
383
|
# show it, get response
|
389
384
|
puts input_desc
|
390
|
-
choice = Readline.readline(
|
385
|
+
choice = Readline.readline('Your choice (hit return to keep current desc.): ', false)
|
391
386
|
|
392
387
|
# keep or empty?
|
393
388
|
return current_desc if choice.empty?
|
394
389
|
|
395
|
-
return
|
390
|
+
return '' if choice.casecmp('b').zero?
|
396
391
|
|
397
392
|
# make a tem file, save current into it
|
398
|
-
desc_tmp_file = Pathname.new Tempfile.new(
|
393
|
+
desc_tmp_file = Pathname.new Tempfile.new('d3_description_')
|
399
394
|
desc_tmp_file.jss_save current_desc
|
400
395
|
|
401
396
|
# which editor?
|
402
|
-
if choice.casecmp('e')
|
397
|
+
if choice.casecmp('e').zero?
|
403
398
|
cmd = prefd_editor
|
404
|
-
elsif choice.casecmp('v')
|
405
|
-
cmd =
|
406
|
-
elsif choice.casecmp('m')
|
407
|
-
cmd =
|
408
|
-
elsif choice.casecmp('n')
|
409
|
-
cmd =
|
399
|
+
elsif choice.casecmp('v').zero?
|
400
|
+
cmd = '/usr/bin/vim'
|
401
|
+
elsif choice.casecmp('m').zero?
|
402
|
+
cmd = '/usr/bin/emacs'
|
403
|
+
elsif choice.casecmp('n').zero?
|
404
|
+
cmd = '/usr/bin/nano -L'
|
410
405
|
else
|
411
406
|
cmd = ENV['EDITOR']
|
412
407
|
end
|
@@ -416,7 +411,7 @@ or '#{DFT_EDITOR}' if none is set.
|
|
416
411
|
|
417
412
|
result = desc_tmp_file.read.chomp
|
418
413
|
desc_tmp_file.delete
|
419
|
-
|
414
|
+
result.chomp
|
420
415
|
end # get_description
|
421
416
|
|
422
417
|
### Get the local path to the package being added to d3
|
@@ -424,7 +419,7 @@ or '#{DFT_EDITOR}' if none is set.
|
|
424
419
|
### if the source is a root-folder rather than a .pkg or .dmg
|
425
420
|
###
|
426
421
|
### @return [Pathname] the local path to the pkg source
|
427
|
-
def get_source_path
|
422
|
+
def get_source_path(default = false)
|
428
423
|
desc = <<-END_DESC
|
429
424
|
SOURCE
|
430
425
|
Enter the path to a .pkg or .dmg installer
|
@@ -433,7 +428,7 @@ END_DESC
|
|
433
428
|
|
434
429
|
# dragging in items from the finder will esacpe spaces in the path with \'s
|
435
430
|
# in the shell this is good, but ruby is interpreting the \'s, so lets remove them.
|
436
|
-
prompt_for_data(opt: :source_path, desc: desc, default: default, required: true).strip.gsub(/\\ /,
|
431
|
+
prompt_for_data(opt: :source_path, desc: desc, default: default, required: true).strip.gsub(/\\ /, ' ')
|
437
432
|
end
|
438
433
|
|
439
434
|
### If we're builting a pkg, should we build a .pkg, or a .dmg?
|
@@ -455,8 +450,8 @@ Should we build a .pkg or .dmg? ( p = pkg, d = dmg )
|
|
455
450
|
###
|
456
451
|
### @return [String] the prefix to use
|
457
452
|
###
|
458
|
-
def get_pkg_identifier
|
459
|
-
|
453
|
+
def get_pkg_identifier(default = nil)
|
454
|
+
desc = <<-END_DESC
|
460
455
|
PKG IDENTIFIER
|
461
456
|
Enter the Apple .pkg indentifier for building a .pkg.
|
462
457
|
E.g. com.mycompany.myapp
|
@@ -477,8 +472,8 @@ E.g. com.mycompany.myapp
|
|
477
472
|
###
|
478
473
|
### @return [String] the prefix to use
|
479
474
|
###
|
480
|
-
def get_pkg_identifier_prefix
|
481
|
-
|
475
|
+
def get_pkg_identifier_prefix(default = D3::Admin::DFT_PKG_ID_PREFIX)
|
476
|
+
desc = <<-END_DESC
|
482
477
|
PKG IDENTIFIER PREFIX
|
483
478
|
Enter the prefix to prepend to a basename to create an Apple .pkg indentifier.
|
484
479
|
E.g. If you enter 'com.mycompany', then when you build a .pkg with basename 'foo'
|
@@ -487,6 +482,46 @@ the default .pkg identifier will be 'com.mycompany.foo'
|
|
487
482
|
prompt_for_data(opt: :pkg_identifier_prefix, desc: desc, default: default, required: true)
|
488
483
|
end
|
489
484
|
|
485
|
+
### Get the optional Apple Developer signing ID
|
486
|
+
### .pkgs can be codesigned with a certificate from Apple
|
487
|
+
### The Developer ID Installer certificate must be
|
488
|
+
### in the login.keychain of the user operating d3admin unless
|
489
|
+
### otherwise specified in signing_options
|
490
|
+
###
|
491
|
+
### This value is saved in the admin prefs for future use.
|
492
|
+
###
|
493
|
+
### @param default[String] the default value when hitting return
|
494
|
+
###
|
495
|
+
### @return [String] The Apple Developer signing ID to use
|
496
|
+
###
|
497
|
+
def get_signing_identity(default = D3::Admin::Prefs.prefs[:signing_identity])
|
498
|
+
desc = <<-END_DESC
|
499
|
+
SIGNING IDENTITY
|
500
|
+
Enter the common name of your Apple Developer signing ID to create signed Apple .pkgs.
|
501
|
+
E.g. If you enter 'Developer ID Installer: My Company (A12BC34DE56)', then that string will be passed
|
502
|
+
as the option for pkgbuild --sign. D3 will not attempt to sign unless this option is set.'
|
503
|
+
END_DESC
|
504
|
+
prompt_for_data(opt: :signing_identity, desc: desc, default: default, required: false)
|
505
|
+
end
|
506
|
+
|
507
|
+
### Get any arguments and options to pass to pkgbuild
|
508
|
+
### A signing identity must be defined for these options to be used.
|
509
|
+
###
|
510
|
+
### This value is saved in the admin prefs for future use.
|
511
|
+
###
|
512
|
+
### @param default[String] the default value when hitting return
|
513
|
+
###
|
514
|
+
### @return [String] The string of arguments and options to pass to pkgbuild
|
515
|
+
###
|
516
|
+
def get_signing_options(default = D3::Admin::Prefs.prefs[:signing_options])
|
517
|
+
desc = <<-END_DESC
|
518
|
+
SIGNING OPTIONS
|
519
|
+
Enter optional arguments and options to pass to pkgbuild. These options are ignored unless a signing identity is defined.
|
520
|
+
E.g. --keychain '/Users/d3/Library/Keychain' --cert 'My Awesome Authority' --timestamp
|
521
|
+
END_DESC
|
522
|
+
prompt_for_data(opt: :signing_options, desc: desc, default: default, required: false)
|
523
|
+
end
|
524
|
+
|
490
525
|
### Get the desired local workspace for building pkgs
|
491
526
|
### Defaults to ENV['HOME']
|
492
527
|
###
|
@@ -494,7 +529,7 @@ the default .pkg identifier will be 'com.mycompany.foo'
|
|
494
529
|
###
|
495
530
|
### @return [Pathname] the path to the workspace
|
496
531
|
###
|
497
|
-
def get_workspace
|
532
|
+
def get_workspace(default = ENV['HOME'])
|
498
533
|
desc = <<-END_DESC
|
499
534
|
PACKAGE BUILD WORKSPACE
|
500
535
|
Enter the path to a folder where we can build packages.
|
@@ -510,7 +545,7 @@ This will be stored between uses of d3admin.
|
|
510
545
|
###
|
511
546
|
### @return [String] the users response
|
512
547
|
###
|
513
|
-
def get_pkg_preserve_owners
|
548
|
+
def get_pkg_preserve_owners(default = 'n')
|
514
549
|
desc = <<-END_DESC
|
515
550
|
PRESERVE SOURCE OWNERSHIP
|
516
551
|
When building a .pkg, the OS generally sets the ownership and permissions
|
@@ -524,7 +559,7 @@ Should we override the OS and preserve the ownership on
|
|
524
559
|
the source folder when the item is installed on the client?
|
525
560
|
Enter 'y' or 'n'
|
526
561
|
END_DESC
|
527
|
-
prompt_for_data(desc: desc, prompt:
|
562
|
+
prompt_for_data(desc: desc, prompt: 'Preserve ownership (y/n)', default: default, required: true)
|
528
563
|
end
|
529
564
|
|
530
565
|
### Get a pre-install script, either local file, JSS id, or JSS name
|
@@ -534,8 +569,8 @@ Enter 'y' or 'n'
|
|
534
569
|
### @return [Pathname, Integer, nil] The local script file, or the JSS id of the
|
535
570
|
### chosen script
|
536
571
|
###
|
537
|
-
def get_pre_install_script
|
538
|
-
get_script
|
572
|
+
def get_pre_install_script(default = nil)
|
573
|
+
get_script 'PRE-INSTALL SCRIPT', :pre_install, default
|
539
574
|
end
|
540
575
|
|
541
576
|
### Get a post-install script, either local file, JSS id, or JSS name
|
@@ -545,8 +580,8 @@ Enter 'y' or 'n'
|
|
545
580
|
### @return [Pathname, Integer, nil] The local script file, or the JSS id of the
|
546
581
|
### chosen script
|
547
582
|
###
|
548
|
-
def get_post_install_script
|
549
|
-
get_script
|
583
|
+
def get_post_install_script(default = nil)
|
584
|
+
get_script 'POST-INSTALL SCRIPT', :post_install, default
|
550
585
|
end
|
551
586
|
|
552
587
|
### Get a pre-remove script, either local file, JSS id, or JSS name
|
@@ -556,8 +591,8 @@ Enter 'y' or 'n'
|
|
556
591
|
### @return [Pathname, Integer, nil] The local script file, or the JSS id of the
|
557
592
|
### chosen script
|
558
593
|
###
|
559
|
-
def get_pre_remove_script
|
560
|
-
|
594
|
+
def get_pre_remove_script(default = nil)
|
595
|
+
get_script 'PRE-REMOVE SCRIPT', :pre_remove, default
|
561
596
|
end
|
562
597
|
|
563
598
|
### Get a post-remove script, either local file, JSS id, or JSS name
|
@@ -567,8 +602,8 @@ Enter 'y' or 'n'
|
|
567
602
|
### @return [Pathname, Integer, nil] The local script file, or the JSS id of the
|
568
603
|
### chosen script
|
569
604
|
###
|
570
|
-
def get_post_remove_script
|
571
|
-
get_script
|
605
|
+
def get_post_remove_script(default = nil)
|
606
|
+
get_script 'POST-REMOVE SCRIPT', :post_remove, default
|
572
607
|
end
|
573
608
|
|
574
609
|
### Get a script, either local file, JSS id, or JSS name
|
@@ -578,7 +613,7 @@ Enter 'y' or 'n'
|
|
578
613
|
### @return [Pathname, Integer, nil] The local script file, or the JSS id of the
|
579
614
|
### chosen script
|
580
615
|
###
|
581
|
-
def get_script
|
616
|
+
def get_script(heading, opt, default = nil)
|
582
617
|
desc = <<-END_DESC
|
583
618
|
#{heading}
|
584
619
|
Enter a path to a local file containing the script
|
@@ -586,12 +621,12 @@ or the name or id of an existing script in the JSS.
|
|
586
621
|
Enter 'v' to view a list of scripts in the JSS.
|
587
622
|
END_DESC
|
588
623
|
|
589
|
-
result =
|
590
|
-
while result ==
|
624
|
+
result = 'v'
|
625
|
+
while result == 'v'
|
591
626
|
result = prompt_for_data(opt: opt, desc: desc, default: default, required: true)
|
592
|
-
D3.less_text JSS::Script.all_names.sort_by
|
627
|
+
D3.less_text JSS::Script.all_names.sort_by(&:downcase).join("\n") if result == 'v'
|
593
628
|
end
|
594
|
-
|
629
|
+
result
|
595
630
|
end
|
596
631
|
|
597
632
|
### Prompt the admin for one or more auto-groups for this installer
|
@@ -599,7 +634,7 @@ Enter 'v' to view a list of scripts in the JSS.
|
|
599
634
|
### @param default[nil,String,Array<String>] The groups to use
|
600
635
|
###
|
601
636
|
### @return [String]
|
602
|
-
def get_auto_groups
|
637
|
+
def get_auto_groups(default = nil)
|
603
638
|
desc = <<-END_DESC
|
604
639
|
AUTO-INSTALL GROUPS
|
605
640
|
Enter a comma-separated list of JSS Computer Group names whose members should
|
@@ -613,8 +648,7 @@ Enter '#{D3::STANDARD_AUTO_GROUP}' to install on all machines.
|
|
613
648
|
### Prompt the admin for one or more auto-groups for this installer
|
614
649
|
###
|
615
650
|
### @param default[nil,String,Array<String>] The groups to
|
616
|
-
def get_excluded_groups
|
617
|
-
|
651
|
+
def get_excluded_groups(default = nil)
|
618
652
|
desc = <<-END_PROMPT
|
619
653
|
EXCLUDED GROUPS
|
620
654
|
Enter a comma-separated list of JSS Computer Group names
|
@@ -628,7 +662,7 @@ Enter 'v' to view list of computer groups.
|
|
628
662
|
###
|
629
663
|
### @return [String] whatever the admin typed
|
630
664
|
###
|
631
|
-
def get_search_target
|
665
|
+
def get_search_target(default = false)
|
632
666
|
desc = <<-END_PROMPT
|
633
667
|
SEARCH TEXT
|
634
668
|
Enter text to use in matching basenames or computer group names.
|
@@ -637,26 +671,25 @@ Matching a group name will list all packages auto-installed or
|
|
637
671
|
excluded for the group. (RegExp's OK)
|
638
672
|
Enter 'all' to list all packages in d3.
|
639
673
|
END_PROMPT
|
640
|
-
prompt_for_data(
|
674
|
+
prompt_for_data(desc: desc, prompt: "Text to match or 'all'").chomp
|
641
675
|
end # get auto
|
642
676
|
|
643
|
-
|
644
|
-
def get_status_for_filter (with_frozen = false)
|
677
|
+
def get_status_for_filter(with_frozen = false)
|
645
678
|
if with_frozen
|
646
679
|
frozen_line = "\nUse 'frozen' to limit to frozen receipts"
|
647
|
-
frozen_title =
|
680
|
+
frozen_title = 'OR FROZEN'
|
648
681
|
else
|
649
|
-
frozen_line =
|
650
|
-
frozen_title =
|
682
|
+
frozen_line = ''
|
683
|
+
frozen_title = ''
|
651
684
|
end
|
652
685
|
|
653
686
|
desc = <<-END_PROMPT
|
654
687
|
LIMIT TO STATUS#{frozen_title}
|
655
688
|
Enter a comma-separate list of statuses for limiting the list.
|
656
|
-
Valid Statuses are: #{D3::Basename::STATUSES_FOR_FILTERS.join(
|
689
|
+
Valid Statuses are: #{D3::Basename::STATUSES_FOR_FILTERS.join(', ')}#{frozen_line}
|
657
690
|
Enter 'all' to show all statuses
|
658
691
|
END_PROMPT
|
659
|
-
prompt_for_data(
|
692
|
+
prompt_for_data(desc: desc, prompt: 'Statuses', default: 'all').chomp
|
660
693
|
end
|
661
694
|
|
662
695
|
### Prompt the admin for one or more groups
|
@@ -665,15 +698,13 @@ Enter 'all' to show all statuses
|
|
665
698
|
###
|
666
699
|
### @return [String,nil]
|
667
700
|
###
|
668
|
-
def get_groups
|
669
|
-
|
670
|
-
result
|
671
|
-
|
672
|
-
|
673
|
-
D3.less_text JSS::ComputerGroup.all_names.sort_by{|s| s.downcase}.join("\n") if result == "v"
|
701
|
+
def get_groups(desc, opt, default = nil)
|
702
|
+
result = 'v'
|
703
|
+
while result == 'v'
|
704
|
+
result = prompt_for_data(opt: opt, desc: desc, default: default, required: true)
|
705
|
+
D3.less_text JSS::ComputerGroup.all_names.sort_by(&:downcase).join("\n") if result == 'v'
|
674
706
|
end
|
675
|
-
|
676
|
-
return result
|
707
|
+
result
|
677
708
|
end # get auto
|
678
709
|
|
679
710
|
### Get a list of allowed OSes for this pkg
|
@@ -683,7 +714,7 @@ Enter 'all' to show all statuses
|
|
683
714
|
###
|
684
715
|
### @return [String,nil] A comma-separated list of allowed OSes
|
685
716
|
###
|
686
|
-
def get_oses
|
717
|
+
def get_oses(default = [])
|
687
718
|
desc = <<-END_DESC
|
688
719
|
LIMIT TO OS's
|
689
720
|
Enter a comma-separated list of OS's allowed to
|
@@ -699,7 +730,7 @@ Use '>=' to set a minimum OS, e.g. '>=10.8.5'
|
|
699
730
|
###
|
700
731
|
### @return [Symbol,nil] :ppc, :intel, or nil
|
701
732
|
###
|
702
|
-
def get_cpu_type
|
733
|
+
def get_cpu_type(default = 'x86')
|
703
734
|
desc = <<-END_DESC
|
704
735
|
LIMIT TO CPU TYPE
|
705
736
|
Should this packge be limited to certain CPU types?
|
@@ -714,7 +745,7 @@ Enter 'ppc' or 'x86' or 'none' for neither.
|
|
714
745
|
###
|
715
746
|
### @return [String] the category entered by the user
|
716
747
|
###
|
717
|
-
def get_category
|
748
|
+
def get_category(default = 'n')
|
718
749
|
desc = <<-END_DESC
|
719
750
|
CATEGORY
|
720
751
|
Enter the JSS category name for this package.
|
@@ -723,10 +754,10 @@ Enter:
|
|
723
754
|
- 'n' for no category
|
724
755
|
END_DESC
|
725
756
|
|
726
|
-
result =
|
727
|
-
while result ==
|
728
|
-
result = prompt_for_data(desc: desc, prompt:
|
729
|
-
D3.less_text JSS::Category.all_names.sort_by
|
757
|
+
result = 'v'
|
758
|
+
while result == 'v'
|
759
|
+
result = prompt_for_data(desc: desc, prompt: 'Category', default: default, required: true)
|
760
|
+
D3.less_text JSS::Category.all_names.sort_by(&:downcase).join("\n") if result == 'v'
|
730
761
|
end
|
731
762
|
return nil if result == 'n'
|
732
763
|
result
|
@@ -742,7 +773,7 @@ Enter:
|
|
742
773
|
###
|
743
774
|
### @return [Regexp,nil] the pattern to match
|
744
775
|
###
|
745
|
-
def get_prohibiting_processes
|
776
|
+
def get_prohibiting_processes(default = 'n')
|
746
777
|
desc = <<-END_DESC
|
747
778
|
PROHIBITING PROCESSES
|
748
779
|
Enter a comma separated string of process name(s) as they appear in the
|
@@ -757,7 +788,7 @@ to quit GUI applications gracefully. Matching is case sensitive.
|
|
757
788
|
Enter 'n' for none.
|
758
789
|
END_DESC
|
759
790
|
|
760
|
-
result = prompt_for_data(desc: desc, prompt:
|
791
|
+
result = prompt_for_data(desc: desc, prompt: 'Prohibiting Processes', opt: :prohibiting_processes, default: default, required: true)
|
761
792
|
return nil if result == 'n'
|
762
793
|
result
|
763
794
|
end
|
@@ -768,13 +799,13 @@ Enter 'n' for none.
|
|
768
799
|
###
|
769
800
|
### @return [String] the users response
|
770
801
|
###
|
771
|
-
def get_removable
|
802
|
+
def get_removable(default = 'y')
|
772
803
|
desc = <<-END_DESC
|
773
804
|
REMOVABLE
|
774
805
|
Can this package be uninstalled?
|
775
806
|
Enter 'y' or 'n'
|
776
807
|
END_DESC
|
777
|
-
prompt_for_data(desc: desc, prompt:
|
808
|
+
prompt_for_data(desc: desc, prompt: 'Removable? (y/n)', default: default, required: true)
|
778
809
|
end
|
779
810
|
|
780
811
|
### Ask if we should ininstall older versions of this basename
|
@@ -784,14 +815,14 @@ Enter 'y' or 'n'
|
|
784
815
|
###
|
785
816
|
### @return [String] the users response
|
786
817
|
###
|
787
|
-
def get_remove_first
|
818
|
+
def get_remove_first(default = 'y')
|
788
819
|
desc = <<-END_DESC
|
789
820
|
UNINSTALL OLDER VERSIONS
|
790
821
|
Should older versions of this basename be uninstalled
|
791
822
|
(if they are removable) before attempting to install this package?
|
792
823
|
Enter 'y' or 'n'
|
793
824
|
END_DESC
|
794
|
-
prompt_for_data(desc: desc, prompt:
|
825
|
+
prompt_for_data(desc: desc, prompt: 'Remove older installs first? (y/n)', default: default, required: true)
|
795
826
|
end
|
796
827
|
|
797
828
|
### Ask if this package needs a reboot
|
@@ -800,7 +831,7 @@ Enter 'y' or 'n'
|
|
800
831
|
###
|
801
832
|
### @return [String] the users response
|
802
833
|
###
|
803
|
-
def get_reboot
|
834
|
+
def get_reboot(default = 'n')
|
804
835
|
desc = <<-END_DESC
|
805
836
|
REBOOT REQUIRED (PUPPIES!)
|
806
837
|
Does this package require a reboot after installation?
|
@@ -809,8 +840,7 @@ with 'd3 install', and the user will be notified to log
|
|
809
840
|
out as soon as possible.
|
810
841
|
Enter 'y' or 'n'
|
811
842
|
END_DESC
|
812
|
-
prompt_for_data(desc: desc, prompt:
|
813
|
-
|
843
|
+
prompt_for_data(desc: desc, prompt: 'Requires reboot? (y/n)', default: default, required: true)
|
814
844
|
end
|
815
845
|
|
816
846
|
### Get an expiration period (# of days) from the user
|
@@ -819,7 +849,7 @@ Enter 'y' or 'n'
|
|
819
849
|
###
|
820
850
|
### @return [Integer] the value to use as the expiration
|
821
851
|
###
|
822
|
-
def get_expiration
|
852
|
+
def get_expiration(default = 0)
|
823
853
|
desc = <<-END_DESC
|
824
854
|
EXPIRATION
|
825
855
|
On machines that allow package expiration,
|
@@ -828,7 +858,7 @@ number of days without being used?
|
|
828
858
|
Enter the number of days, or 0 for no expiration.
|
829
859
|
END_DESC
|
830
860
|
|
831
|
-
prompt_for_data(desc: desc, prompt:
|
861
|
+
prompt_for_data(desc: desc, prompt: 'Expiration days', default: default, required: true)
|
832
862
|
end
|
833
863
|
|
834
864
|
### Get the path to the executable(s) to monitor for expiration
|
@@ -837,7 +867,7 @@ Enter the number of days, or 0 for no expiration.
|
|
837
867
|
###
|
838
868
|
### @return [Array<Pathname>] the path(s) to the executable
|
839
869
|
###
|
840
|
-
def get_expiration_paths
|
870
|
+
def get_expiration_paths(default = 'n')
|
841
871
|
desc = <<-END_DESC
|
842
872
|
EXPIRATION PATH(S)
|
843
873
|
Enter the path(s) to the executable(s) that must be used
|
@@ -846,7 +876,7 @@ should not be escaped. E.g.
|
|
846
876
|
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome, /Applications/Firefox.app/Contents/MacOS/firefox
|
847
877
|
Enter 'n' for none
|
848
878
|
END_DESC
|
849
|
-
prompt_for_data(desc: desc, prompt:
|
879
|
+
prompt_for_data(desc: desc, prompt: 'Expiration Path(s)', default: default, required: true)
|
850
880
|
end
|
851
881
|
|
852
882
|
### when deleting a pkg, should its pre- and post- scripts be kept?
|
@@ -855,7 +885,7 @@ Enter 'n' for none
|
|
855
885
|
###
|
856
886
|
### @return [String] the users response
|
857
887
|
###
|
858
|
-
def get_keep_scripts
|
888
|
+
def get_keep_scripts(default = 'n')
|
859
889
|
desc = <<-END_DESC
|
860
890
|
KEEP ASSOCIATED SCRIPTS IN CASPER?
|
861
891
|
When deleting a package, should any associated scripts
|
@@ -865,7 +895,7 @@ NOTE: If any other d3 packages or policies are using the scripts
|
|
865
895
|
they won't be deleted. The other users of the scripts will be reported.
|
866
896
|
Enter 'y' or 'n'
|
867
897
|
END_DESC
|
868
|
-
prompt_for_data(desc: desc, prompt:
|
898
|
+
prompt_for_data(desc: desc, prompt: 'Delete Scripts? (y/n)', default: default, required: true)
|
869
899
|
end
|
870
900
|
|
871
901
|
### when deleting a pkg, should it be kept in the JSS?
|
@@ -874,14 +904,14 @@ Enter 'y' or 'n'
|
|
874
904
|
###
|
875
905
|
### @return [String] the users response
|
876
906
|
###
|
877
|
-
def get_keep_in_jss
|
907
|
+
def get_keep_in_jss(default = 'n')
|
878
908
|
desc = <<-END_DESC
|
879
909
|
KEEP THE PACKAGE IN CASPER?
|
880
910
|
When deleting a package, should it be kept as a Casper package
|
881
911
|
and only deleted from d3?
|
882
912
|
Enter 'y' or 'n'
|
883
913
|
END_DESC
|
884
|
-
prompt_for_data(desc: desc, prompt:
|
914
|
+
prompt_for_data(desc: desc, prompt: 'Keep in JSS? (y/n)', default: default, required: true)
|
885
915
|
end
|
886
916
|
|
887
917
|
### what kind of package list are we showing?
|
@@ -890,7 +920,7 @@ Enter 'y' or 'n'
|
|
890
920
|
###
|
891
921
|
### @return [String] the chosen report type
|
892
922
|
###
|
893
|
-
def get_show_type
|
923
|
+
def get_show_type(default = D3::Admin::Report::DFT_SHOW_TYPE)
|
894
924
|
desc = <<-END_DESC
|
895
925
|
SERVER PACKAGE LIST
|
896
926
|
Enter the type of list you'd like to generate about packages in d3.
|
@@ -905,25 +935,25 @@ One of:
|
|
905
935
|
auto - packages auto-installed for a given computer group
|
906
936
|
excluded - packages not available to a given computer group
|
907
937
|
END_DESC
|
908
|
-
prompt_for_data(desc: desc, prompt:
|
938
|
+
prompt_for_data(desc: desc, prompt: 'Show packages', default: default, required: true)
|
909
939
|
end
|
910
940
|
|
911
941
|
### What computer are we generating a receipt report for?
|
912
942
|
###
|
913
943
|
### @return [String] A computer name in the JSS
|
914
944
|
###
|
915
|
-
def get_computer
|
916
|
-
|
945
|
+
def get_computer(default = nil)
|
946
|
+
desc = <<-END_DESC
|
917
947
|
COMPUTER NAME
|
918
948
|
Enter the name of a computer Casper.
|
919
949
|
Enter 'v' to view a list available computer names.
|
920
950
|
END_DESC
|
921
|
-
input =
|
922
|
-
while input ==
|
923
|
-
input = prompt_for_data(desc: desc, prompt:
|
924
|
-
D3::Admin::Report.show_available_computers_for_reports if input ==
|
951
|
+
input = 'v'
|
952
|
+
while input == 'v'
|
953
|
+
input = prompt_for_data(desc: desc, prompt: 'Computer name', default: nil, required: true)
|
954
|
+
D3::Admin::Report.show_available_computers_for_reports if input == 'v'
|
925
955
|
end
|
926
|
-
|
956
|
+
input
|
927
957
|
end # get computer
|
928
958
|
|
929
959
|
### Get the config target
|
@@ -932,8 +962,8 @@ END_DESC
|
|
932
962
|
###
|
933
963
|
### @return [String] the prefix to use
|
934
964
|
###
|
935
|
-
def get_config_target
|
936
|
-
|
965
|
+
def get_config_target(default = 'all')
|
966
|
+
desc = <<-END_DESC
|
937
967
|
CONFIGURATION
|
938
968
|
Which setting would you like to configure?
|
939
969
|
jss - the JSS and credentials (stored in your keychain)
|
@@ -942,6 +972,8 @@ Which setting would you like to configure?
|
|
942
972
|
workspace - the folder in which to build .pkgs and .dmgs
|
943
973
|
editor - the shell command for editing package descriptions
|
944
974
|
pkg-id-prefix - the prefix for the .pkg identifier when building .pkgs
|
975
|
+
signing-identity - optional Developer ID Installer certificate issued by Apple
|
976
|
+
signing-options - optional string of signing options to pass to pkgbuild.
|
945
977
|
all - all of the above
|
946
978
|
display - show current configuration
|
947
979
|
|
@@ -955,7 +987,7 @@ Which setting would you like to configure?
|
|
955
987
|
###
|
956
988
|
### @return [String] the command to use
|
957
989
|
###
|
958
|
-
def get_editor
|
990
|
+
def get_editor(default = '/usr/bin/nano')
|
959
991
|
desc = <<-END_DESC
|
960
992
|
EDITOR
|
961
993
|
Enter the shell command to use during --walkthru
|
@@ -966,9 +998,11 @@ Note: if the command launches a GUI editor, make sure the
|
|
966
998
|
shell command stays running until the document is closed.
|
967
999
|
Most such editors have an option for that.
|
968
1000
|
END_DESC
|
969
|
-
prompt_for_data(
|
1001
|
+
prompt_for_data(desc: desc, default: default, prompt: 'Command', required: true)
|
970
1002
|
end
|
971
1003
|
|
972
1004
|
end # module
|
1005
|
+
|
973
1006
|
end # module Admin
|
1007
|
+
|
974
1008
|
end # module D3
|