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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e483eb6fd0aae3cf4d824414f9cf8c1e7d78bec
4
- data.tar.gz: 2dc642d46f5adc58ca5b6c980492ba71e8b3d93e
3
+ metadata.gz: d3d60e7335e71cc42cfc47dc4e475f0a4b5237de
4
+ data.tar.gz: 85731430c8d7fbdc501a8ab72ef2dc68b7936594
5
5
  SHA512:
6
- metadata.gz: a7b6a499e95d949397c4091b1314a7321c84054cf69d7ee60eda10a02feef3740dd5e02038fb99cf5e5c5b938924b410f1323ec02d29071963019ddac924ae2a
7
- data.tar.gz: c98a7abc85aded9092ad66cb7657deba7b18bf665e4b182eaa88e99fa47919a1d7123d0e08d9a0bed109ebec492bfafdb88ed948617066fb2022faa27a0f6d55
6
+ metadata.gz: 7d8c26bddb9d57ead819dce286f3f2977fd96054a221cdd10e7f0b7ca21b1050c23f3a98bcc841b2146eb25daa02f8f6b017605d6ffe6959dcc1eabd4007aece
7
+ data.tar.gz: 9792ad3083342ab81257eace8ab0f0d9413fcbb94152a3e19ef62ee5f987c15ac76bb60c3d361de642e98e5edb8a0e663ce9bb92534844578207bde3621aa034
data/CHANGES.md CHANGED
@@ -1,6 +1,26 @@
1
1
  # Change History
2
2
 
3
- ## v3.0.14 - 2017-02-28
3
+ ## v3.0.20 - 2018-06-27
4
+ - Added: validate that a pkg is available via cloud before trying to install it that way
5
+ - Change: better backtrace logging
6
+ - Change: better error reporting when client passwd retrieval fails
7
+ - Fix: bug preventing puppies to install from the puppy queue
8
+
9
+ ## v3.0.19 - 2018-03-31
10
+ - Added: signing identity and signing prefs to d3admin add, when building .pkgs
11
+ - Added: A default description editer (e.g. vi, emacs, pico) can be saved in admin prefs
12
+ - Fix: return nil when asked for current foreground application on client, and there is none.
13
+
14
+ ## v3.0.18 - 2017-12-01
15
+ - Change: D3::Client.install: freeze prev. installed rcpts when 'freeze on install' requested.
16
+
17
+ ## v3.0.17 - 2017-07-14
18
+ - Fix: D3::Package.upload_master_file, call #update after #super
19
+
20
+ ## v3.0.16 - 2017-04-10
21
+ - Update: Max DB schema version bumped for 9.98 and 9.99
22
+
23
+ ## v3.0.15 - 2017-02-28
4
24
  - Bugfix: now correctly finds the most recent timestamp for an expiration path coming to the foreground
5
25
 
6
26
  ## v3.0.14 - 2016-12-08
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # d3 - Command line package and patch management for Casper
2
2
 
3
- d3 is a package deployment and patch management system for OS X that enhances the
4
- [Casper Suite](http://www.jamfsoftware.com/products/casper-suite/), an enterprise-level management system for Apple devices from [JAMF Software](http://www.jamfsoftware.com/). It was created by [Pixar Animation Studios](http://www.pixar.com/).
3
+ d3 (a.k.a. depot3) is a package deployment and patch management system for OS X that enhances
4
+ [Jamf Pro](https://www.jamf.com/products/jamf-pro/), an enterprise-level management system for Apple devices from [JAMF Software](http://www.jamf.com/). It was created by [Pixar Animation Studios](http://www.pixar.com/).
5
5
 
6
6
 
7
- d3 adds these capabilities and more to Casper's package handling:
7
+ d3 adds these capabilities and more to Jamf Pro's package handling:
8
8
 
9
9
  * Automatic software updates on clients when new versions are released on the server
10
10
  * Pre-release piloting of new packages
@@ -14,7 +14,7 @@ d3 adds these capabilities and more to Casper's package handling:
14
14
  * Both the client and admin tools are command-line only and fully scriptable
15
15
  * Admin command-line options allow integration with developer workflows and package-retrieval tools
16
16
 
17
- d3 is written in Ruby and available as a rubygem called ['depot3'](https://rubygems.org/gems/depot3). It interfaces with Casper via its REST API using [ruby-jss](https://github.com/PixarAnimationStudios/ruby-jss), a ruby module that provides simple and powerful access to the API. It also uses Casper's backend MySQL database directly to provide enhanced features.
17
+ d3 is written in Ruby and available as a rubygem called ['depot3'](https://rubygems.org/gems/depot3). It interfaces with Jamf Pro via its REST API using [ruby-jss](https://github.com/PixarAnimationStudios/ruby-jss), a ruby module that provides simple and powerful access to the API. It also uses Jamf Pro's backend MySQL database directly to provide enhanced features.
18
18
 
19
19
  ## DOCUMENTATION
20
20
 
@@ -22,7 +22,7 @@ Full user/administrator documentation is available at the [GitHub project's wiki
22
22
 
23
23
  The developer documentation for the D3 ruby module is at [http://www.rubydoc.info/gems/depot3](http://www.rubydoc.info/gems/depot3).
24
24
 
25
- Also check out [ruby-jss](https://github.com/PixarAnimationStudios/ruby-jss), which is used by d3, but is useful for working with the Casper REST API in any project.
25
+ Also check out [ruby-jss](https://github.com/PixarAnimationStudios/ruby-jss), which is used by d3, but is useful for working with the Jamf Pro REST API in any project.
26
26
 
27
27
 
28
28
  ## CONTACT
@@ -33,7 +33,7 @@ Also check out [ruby-jss](https://github.com/PixarAnimationStudios/ruby-jss), wh
33
33
 
34
34
  ## LICENSE
35
35
 
36
- Copyright 2016 Pixar
36
+ Copyright 2017 Pixar
37
37
 
38
38
  Licensed under the Apache License, Version 2.0 (the "Apache License")
39
39
  with the following modification; you may not use d3 except in
data/bin/d3 CHANGED
@@ -332,10 +332,10 @@ begin
332
332
  app = App.new(ARGV)
333
333
  app.run
334
334
 
335
- rescue
335
+ rescue => e
336
336
  # handle exceptions not handled elsewhere
337
- D3.log "An error occurred: #{$!.class}: #{$!}", :fatal
338
- D3.log_backtrace
337
+ D3.log "An error occurred: #{e.class}: #{e}", :fatal
338
+ D3.log_backtrace e
339
339
  exit 1
340
340
  ensure
341
341
  if JSS::API.connected?
@@ -44,8 +44,6 @@
44
44
  # Load libraries
45
45
  require 'd3'
46
46
 
47
-
48
-
49
47
  ######################
50
48
  # The Script Object
51
49
  ######################
@@ -53,19 +51,16 @@ class App
53
51
 
54
52
  ### Setup
55
53
  def initialize
56
-
57
54
  ### parse the commandline
58
55
  parse_commandline
59
56
 
60
57
  # can't be run as root other than help, search or report - no keychain, among other things
61
- raise "d3admin can't make server changes as root" if JSS.superuser? and (not @action =~ /^[hsr]/)
62
-
63
- end #initialize
58
+ raise "d3admin can't make server changes as root" if JSS.superuser? && (!@action =~ /^[hsr]/)
59
+ end # initialize
64
60
 
65
61
  ### Run
66
62
  def run
67
-
68
- if @action == "help"
63
+ if @action == 'help'
69
64
  show_help @options.helptype
70
65
  return
71
66
  end
@@ -73,7 +68,7 @@ class App
73
68
  # run config if it hasn't ever run
74
69
  unless D3::Admin::Prefs.prefs[:last_config] || JSS.superuser?
75
70
  puts
76
- puts "******** INITIAL D3ADMIN CONFIGURATION ********"
71
+ puts '******** INITIAL D3ADMIN CONFIGURATION ********'
77
72
  puts
78
73
  config
79
74
  # but dont run it again if that's the action chosen
@@ -84,12 +79,12 @@ class App
84
79
  @admin = @options.admin || ENV['USER']
85
80
 
86
81
  # admin can't be a badmin
87
- if D3.badmins.include? @admin and D3::Admin::ACTIONS_NEEDING_ADMIN.include? @action
82
+ if (D3.badmins.include? @admin) && (D3::Admin::ACTIONS_NEEDING_ADMIN.include? @action)
88
83
  raise D3::PermissionError, "d3admin cannot do '#{@action}' as #{@admin}."
89
84
  end
90
85
 
91
86
  # config before connecting
92
- if @action =~ /^c/ and !JSS.superuser?
87
+ if @action =~ /^c/ && !JSS.superuser?
93
88
  config
94
89
  return
95
90
  end
@@ -103,43 +98,40 @@ class App
103
98
 
104
99
  case @action
105
100
 
106
- when /^a/ then
107
- add_pilot_package
101
+ when /^a/ then
102
+ add_pilot_package
108
103
 
109
- when /^e/ then
110
- edit_package
104
+ when /^e/ then
105
+ edit_package
111
106
 
112
- when /^l/ then
113
- make_package_live
107
+ when /^l/ then
108
+ make_package_live
114
109
 
115
- when /^d/ then
116
- delete_package
110
+ when /^d/ then
111
+ delete_package
117
112
 
118
- when /^i/ then
119
- show_package_info
113
+ when /^i/ then
114
+ show_package_info
120
115
 
121
- when /^s/ then
122
- search
116
+ when /^s/ then
117
+ search
123
118
 
124
- when /^r/ then
125
- show_report
119
+ when /^r/ then
120
+ show_report
126
121
 
127
- else
128
- raise ArgumentError, "#{D3::Admin::Help::USAGE}\nUnknown action, must be one of #{D3::Admin::ACTIONS.join(', ')}"
122
+ else
123
+ raise ArgumentError, "#{D3::Admin::Help::USAGE}\nUnknown action, must be one of #{D3::Admin::ACTIONS.join(', ')}"
129
124
 
130
125
  end # case
131
-
132
-
133
- end #run
126
+ end # run
134
127
 
135
128
  ### Parse the command line
136
129
  ###
137
130
  ### @return [void]
138
131
  ###
139
132
  def parse_commandline
140
-
141
133
  # Debugging file? if so, always set debug.
142
- ARGV << "--debug" if D3::DEBUG_FILE.exist?
134
+ ARGV << '--debug' if D3::DEBUG_FILE.exist?
143
135
 
144
136
  # this holds everything that comes from the commandline
145
137
  # or from prompting the user
@@ -153,145 +145,144 @@ class App
153
145
  @options.status = []
154
146
 
155
147
  ### see Admin::CLIOpts
156
- opt_arry = D3::Admin::OPTIONS.values.map{|o| o[:cli] }
157
- opts = GetoptLong.new *opt_arry
148
+ opt_arry = D3::Admin::OPTIONS.values.map { |o| o[:cli] }
149
+ opts = GetoptLong.new(*opt_arry)
158
150
 
159
151
  opts.each do |opt, arg|
160
152
  case opt
161
153
 
162
- #general
163
- when '--help'
164
- @action = "help"
165
- @options.helptype = :help
166
- return
167
- when '--extended-help'
168
- @action = "help"
169
- @options.helptype = :extended_help
170
- return
171
- when '--debug'
172
- D3::Admin.debug = true
173
-
174
- when '--d3-version'
175
- @action = "help"
176
- @options.helptype = :show_d3_version
177
- return
178
-
179
- when '--walkthru'
180
- @options.walkthru = true
181
- when '--auto-confirm'
182
- @options.auto_confirm = true
183
-
184
- when '--admin'
185
- @options.admin = arg
186
-
187
- # search and report
188
- when '--status'
189
- @options.status += arg.split(/,\s*/)
190
- when '--queue'
191
- @options.report_q = true
192
- when '--frozen'
193
- @options.report_frozen = true
194
- when '--computers'
195
- @options.report_computers = true
196
- when '--groups'
197
- @options.search_groups = true
198
- # add/edit
199
- when '--import'
200
- @options.import = true
201
- @options.import_from = arg.empty? ? nil : arg
202
- when '--no-inherit'
203
- @options.no_inherit = true
204
- when '--basename'
205
- @options.basename = arg
206
- when '--version'
207
- @options.version = arg
208
- when '--revision'
209
- @options.revision = arg
210
- when '--description'
211
- @options.description = arg
212
- when '--package-name'
213
- @options.package_name = arg
214
- when '--filename'
215
- @options.filename = arg
216
- when '--edition'
217
- @options.edition = arg
218
- when '--source-path'
219
- @options.source_path = arg
220
- when '--dmg'
221
- @options.package_build_type = 'd'
222
- when '--preserve-owners'
223
- @options.pkg_preserve_owners = 'y'
224
- when '--pkg-id'
225
- @options.pkg_identifier = arg
226
- when '--workspace'
227
- @options.workspace = arg
228
- when '--pre-install'
229
- @options.pre_install = arg
230
- when '--post-install'
231
- @options.post_install = arg
232
- when '--pre-remove'
233
- @options.pre_remove = arg
234
- when '--post-remove'
235
- @options.post_remove = arg
236
- when '--auto-groups'
237
- @options.auto_groups = arg
238
- when '--excluded-groups'
239
- @options.excluded_groups = arg
240
- when '--prohibiting-processes'
241
- @options.prohibiting_processes = arg
242
- when '--cpu_type'
243
- @options.cpu_type = arg
244
- when '--category'
245
- @options.category = arg
246
-
247
- when '--reboot'
248
- # dft is no, so if arg is empty or /^n(o)$/i, it should be nil,
249
- # otherwise must be /^y(es)$/i
250
- if arg.empty? or arg =~ /^no?$/i
251
- @options.reboot = "n"
252
- elsif arg =~ /^y(es)?$/i
253
- @options.reboot = "y"
254
- else
255
- raise ArgumentError, "--reboot must be 'y' or 'n'"
256
- end
154
+ # General
155
+ when '--help'
156
+ @action = 'help'
157
+ @options.helptype = :help
158
+ break
159
+ when '--extended-help'
160
+ @action = 'help'
161
+ @options.helptype = :extended_help
162
+ break
163
+ when '--debug'
164
+ D3::Admin.debug = true
165
+ when '--d3-version'
166
+ @action = 'help'
167
+ @options.helptype = :show_d3_version
168
+ break
169
+ when '--walkthru'
170
+ @options.walkthru = true
171
+ when '--auto-confirm'
172
+ @options.auto_confirm = true
173
+ when '--admin'
174
+ @options.admin = arg
175
+
176
+ # Search and Report
177
+ when '--status'
178
+ @options.status += arg.split(/,\s*/)
179
+ when '--queue'
180
+ @options.report_q = true
181
+ when '--frozen'
182
+ @options.report_frozen = true
183
+ when '--computers'
184
+ @options.report_computers = true
185
+ when '--groups'
186
+ @options.search_groups = true
187
+
188
+ # Add/Edit
189
+ when '--import'
190
+ @options.import = true
191
+ @options.import_from = arg.empty? ? nil : arg
192
+ when '--no-inherit'
193
+ @options.no_inherit = true
194
+ when '--basename'
195
+ @options.basename = arg
196
+ when '--version'
197
+ @options.version = arg
198
+ when '--revision'
199
+ @options.revision = arg
200
+ when '--description'
201
+ @options.description = arg
202
+ when '--package-name'
203
+ @options.package_name = arg
204
+ when '--filename'
205
+ @options.filename = arg
206
+ when '--edition'
207
+ @options.edition = arg
208
+ when '--source-path'
209
+ @options.source_path = arg
210
+ when '--dmg'
211
+ @options.package_build_type = 'd'
212
+ when '--preserve-owners'
213
+ @options.pkg_preserve_owners = 'y'
214
+ when '--pkg-id'
215
+ @options.pkg_identifier = arg
216
+ when '--workspace'
217
+ @options.workspace = arg
218
+ when '--pre-install'
219
+ @options.pre_install = arg
220
+ when '--post-install'
221
+ @options.post_install = arg
222
+ when '--pre-remove'
223
+ @options.pre_remove = arg
224
+ when '--post-remove'
225
+ @options.post_remove = arg
226
+ when '--auto-groups'
227
+ @options.auto_groups = arg
228
+ when '--excluded-groups'
229
+ @options.excluded_groups = arg
230
+ when '--prohibiting-processes'
231
+ @options.prohibiting_processes = arg
232
+ when '--cpu_type'
233
+ @options.cpu_type = arg
234
+ when '--category'
235
+ @options.category = arg
236
+
237
+ when '--reboot'
238
+ # dft is no, so if arg is empty or /^n(o)$/i, it should be nil,
239
+ # otherwise must be /^y(es)$/i
240
+ if arg.empty? || arg =~ /^no?$/i
241
+ @options.reboot = 'n'
242
+ elsif arg =~ /^y(es)?$/i
243
+ @options.reboot = 'y'
244
+ else
245
+ raise ArgumentError, "--reboot must be 'y' or 'n'"
246
+ end
257
247
 
258
- when '--remove-first'
259
- # dft is no, so if arg is empty or /^n(o)$/i, it should be nil,
260
- # otherwise must be /^y(es)$/i
261
- if arg.empty? or arg =~ /^no?$/i
262
- @options.remove_first = "n"
263
- elsif arg =~ /^y(es)?$/i
264
- @options.remove_first = "y"
265
- else
266
- raise ArgumentError, "--remove-first must be 'y' or 'n'"
267
- end
248
+ when '--remove-first'
249
+ # dft is no, so if arg is empty or /^n(o)$/i, it should be nil,
250
+ # otherwise must be /^y(es)$/i
251
+ if arg.empty? || arg =~ /^no?$/i
252
+ @options.remove_first = 'n'
253
+ elsif arg =~ /^y(es)?$/i
254
+ @options.remove_first = 'y'
255
+ else
256
+ raise ArgumentError, "--remove-first must be 'y' or 'n'"
257
+ end
268
258
 
269
- when '--removable'
270
- # dft is yes, so if arg is empty or /^y(es)$/i, it should be nil,
271
- # otherwise must be /^n(o)$/i
272
- if arg.empty? or arg =~ /^y(es)?$/i
273
- @options.removable = "y"
274
- elsif arg =~ /^no?$/i
275
- @options.removable = "n"
276
- else
277
- raise ArgumentError, "--removable must be 'y' or 'n'"
278
- end
259
+ when '--removable'
260
+ # dft is yes, so if arg is empty or /^y(es)$/i, it should be nil,
261
+ # otherwise must be /^n(o)$/i
262
+ if arg.empty? || arg =~ /^y(es)?$/i
263
+ @options.removable = 'y'
264
+ elsif arg =~ /^no?$/i
265
+ @options.removable = 'n'
266
+ else
267
+ raise ArgumentError, "--removable must be 'y' or 'n'"
268
+ end
279
269
 
280
- when '--oses'
281
- @options.oses = arg
282
- when '--expiration'
283
- @options.expiration = arg
284
- when '--expiration-path', '--expiration_paths'
285
- @options.expiration_paths = arg
270
+ when '--oses'
271
+ @options.oses = arg
272
+ when '--expiration'
273
+ @options.expiration = arg
274
+ when '--expiration-path', '--expiration_paths'
275
+ @options.expiration_paths = arg
286
276
 
287
- # delete
288
- when '--keep-scripts'
289
- @options.keep_scripts = 'y'
290
- when '--keep-in-jss'
291
- @options.keep_in_jss = 'y'
277
+ # Delete
278
+ when '--keep-scripts'
279
+ @options.keep_scripts = 'y'
280
+ when '--keep-in-jss'
281
+ @options.keep_in_jss = 'y'
292
282
 
293
283
  end # case
294
284
  end # opts.each
285
+ return if @action == 'help'
295
286
 
296
287
  # the action is always the first thing in ARGV
297
288
  # after the options have been removed
@@ -302,40 +293,39 @@ class App
302
293
  end
303
294
 
304
295
  # one or more letters is all we need to specify the action...
305
- @action = D3::Admin::ACTIONS.select{|a| a.start_with? action_arg}.first
296
+ @action = D3::Admin::ACTIONS.select { |a| a.start_with? action_arg }.first
306
297
 
307
- unless @action and D3::Admin::ACTIONS.include? @action
298
+ unless @action && (D3::Admin::ACTIONS.include? @action)
308
299
  raise ArgumentError, "#{D3::Admin::Help::USAGE}\nAction, must be one of #{D3::Admin::ACTIONS.join(', ')}"
309
300
  end
310
301
 
311
302
  # anything remaining in ARGV is one or more targets
312
303
  # to work on.
313
304
  @targets = ARGV
314
-
315
305
  end # parse_commandline
316
306
 
317
307
  ### Show the help message
318
308
  ###
319
309
  ### @return [void]
320
310
  ###
321
- def show_help (type)
311
+ def show_help(type)
322
312
  text = case type
323
313
  when :help
324
- D3::Admin::Help.help_text
314
+ D3::Admin::Help.help_text
325
315
  when :extended_help
326
316
  D3::Admin::Help.extended_help_text
327
317
  when :show_d3_version
328
318
  d3_version_text
329
319
  end
330
320
  D3.less_text text
331
- return true
332
- end #show help
321
+ true
322
+ end # show help
333
323
 
334
324
  ### the d3 version text to spew
335
325
  ###
336
326
  ### @return [String] the text
337
327
  def d3_version_text
338
- <<-ENDVERS
328
+ <<-ENDVERS
339
329
  D3 module version: #{D3::VERSION}
340
330
  JSS module version: #{JSS::VERSION}
341
331
  ENDVERS
@@ -344,22 +334,20 @@ ENDVERS
344
334
  ### Add a new pilot package from an existing
345
335
  ### JSS package
346
336
  def import_pilot_pkg_from_jss
347
-
348
337
  if @options.walkthru
349
338
  @options.import_from = D3::Admin::Interactive.get_value :import unless @options.import_from
350
339
  @options.version = D3::Admin::Interactive.get_value :version
351
340
  @options.revision = D3::Admin::Interactive.get_value :revision
352
341
  else
353
- raise JSS::MissingDataError, "A version must be provided with --version" unless @options.version
354
- raise JSS::MissingDataError, "A revision must be provided with --revision" unless @options.revision
342
+ raise JSS::MissingDataError, 'A version must be provided with --version' unless @options.version
343
+ raise JSS::MissingDataError, 'A revision must be provided with --revision' unless @options.revision
355
344
  end # if walk thru
356
345
 
357
- imported_pkg = D3::Package.import( @options.import_from,
358
- basename: @options.basename,
359
- version: @options.version,
360
- revision: @options.revision,
361
- dist_pw: D3::Admin::Auth.rw_credentials(:dist)[:password]
362
- )
346
+ imported_pkg = D3::Package.import(@options.import_from,
347
+ basename: @options.basename,
348
+ version: @options.version,
349
+ revision: @options.revision,
350
+ dist_pw: D3::Admin::Auth.rw_credentials(:dist)[:password])
363
351
  imported_pkg.admin = @admin
364
352
  edit_package imported_pkg
365
353
  end
@@ -376,13 +364,12 @@ ENDVERS
376
364
  ### @return [void]
377
365
  ###
378
366
  def add_pilot_package
379
-
380
367
  ## we must have a basename before going farther
381
368
  @options.basename = @targets.first
382
369
  if @options.walkthru
383
370
  @options.basename ||= D3::Admin::Interactive.get_basename
384
371
  else
385
- raise ArgumentError, "A basename must be provided as a target. Use -H for help" unless @options.basename
372
+ raise ArgumentError, 'A basename must be provided as a target. Use -H for help' unless @options.basename
386
373
  end
387
374
 
388
375
  if @options.import
@@ -390,7 +377,7 @@ ENDVERS
390
377
  return
391
378
  end
392
379
 
393
- puts "Adding a new pilot package to d3..."
380
+ puts 'Adding a new pilot package to d3...'
394
381
 
395
382
  # this holds the validated data used for making the new pkg
396
383
  new_package_options = OpenStruct.new
@@ -408,7 +395,7 @@ ENDVERS
408
395
 
409
396
  # if we were given a new version but not a new revision,
410
397
  # set the new revision to 1
411
- if @options[:version] and @options[:version] != default_options[:version]
398
+ if @options[:version] && @options[:version] != default_options[:version]
412
399
  @options[:revision] ||= 1
413
400
  @options[:edition] ||= "#{@options.basename}-#{@options[:version]}-#{@options[:revision]}"
414
401
  @options.package_name ||= @options[:edition]
@@ -419,7 +406,6 @@ ENDVERS
419
406
  # for any options that weren't given on the commandline, use the defaults
420
407
  default_options.each_pair { |opt, val| @options[opt] ||= val }
421
408
 
422
-
423
409
  new_package_options = D3::Admin::Add.add_pilot_cli(@options)
424
410
 
425
411
  ##########################
@@ -436,7 +422,7 @@ ENDVERS
436
422
  opts_to_confirm += D3::Admin::Add::BUILD_OPTIONS if new_package_options.package_build_type
437
423
  opts_to_confirm += D3::Admin::Add::PKG_OPTIONS if new_package_options.package_build_type == :pkg
438
424
 
439
- #D3::Admin::Add::NEW_PKG_OPTIONS.each do |opt|
425
+ # D3::Admin::Add::NEW_PKG_OPTIONS.each do |opt|
440
426
  opts_to_confirm.each do |opt|
441
427
  lbl = D3::Admin::OPTIONS[opt][:label]
442
428
  if D3::Admin::OPTIONS[opt][:display_conversion]
@@ -444,11 +430,11 @@ ENDVERS
444
430
  else
445
431
  disp = new_package_options[opt]
446
432
  end
447
- lines << "#{lbl}: #{disp}"
433
+ lines << "#{lbl}: #{disp}"
448
434
  end
449
435
  settings_conf_disp = "\n******* New d3 Package Settings *******\n"
450
- settings_conf_disp += "Edition: #{ new_package_options.edition}\n"
451
- settings_conf_disp += "Basename: #{ new_package_options.basename}\n"
436
+ settings_conf_disp += "Edition: #{new_package_options.edition}\n"
437
+ settings_conf_disp += "Basename: #{new_package_options.basename}\n"
452
438
  settings_conf_disp += lines.join "\n"
453
439
  settings_conf_disp += "\n"
454
440
  puts settings_conf_disp
@@ -459,10 +445,9 @@ ENDVERS
459
445
 
460
446
  D3::Admin::Add.add_new_package new_package_options
461
447
 
462
- puts "Done!"
448
+ puts 'Done!'
463
449
  puts "To pilot it, run 'sudo d3 install #{new_package_options.edition}' on a test machine."
464
450
  puts "To make it live, run 'd3admin live #{new_package_options.edition}' on your machine."
465
-
466
451
  end # add pilot
467
452
 
468
453
  ### Make a package live.
@@ -470,11 +455,10 @@ ENDVERS
470
455
  ### @return [void]
471
456
  ###
472
457
  def make_package_live
473
-
474
458
  pkg_id = get_pkg_from_cli_or_prompt
475
459
 
476
460
  if pkg_id.nil?
477
- puts "No edition given to make live or no matching package found"
461
+ puts 'No edition given to make live or no matching package found'
478
462
  return
479
463
  end
480
464
  pkg = D3::Package.new id: pkg_id
@@ -485,33 +469,33 @@ ENDVERS
485
469
  end
486
470
 
487
471
  # is this a rollback?
488
- rollback_warning = ""
489
- if pkg.skipped? or pkg.deprecated?
472
+ rollback_warning = ''
473
+ if pkg.skipped? || pkg.deprecated?
490
474
  rollback_warning = "\n\nWARNING: You're rolling back to an older edition!\n"
491
475
  rollback_warning += "ALL non-frozen installs of '#{pkg.basename}' will be downgraded to this edition! \n"
492
476
  end
493
477
 
494
478
  # is the prev. live pkg in use in any policies?
495
- policy_warning = ""
479
+ policy_warning = ''
496
480
  pkg_id_being_deprecated = D3::Package.basenames_to_live_ids[pkg.basename]
497
481
  if pkg_id_being_deprecated
498
482
  outgoing_pkg = D3::Package.new(id: pkg_id_being_deprecated)
499
- pols_used_by_old_pkg = outgoing_pkg.policy_ids
483
+ pols_used_by_old_pkg = outgoing_pkg.policy_ids
500
484
  unless pols_used_by_old_pkg.empty?
501
- names = pols_used_by_old_pkg.map{|pid| JSS::Policy.map_all_ids_to(:name)[pid]}.join(', ')
485
+ names = pols_used_by_old_pkg.map { |pid| JSS::Policy.map_all_ids_to(:name)[pid] }.join(', ')
502
486
  policy_warning = "\n\nWARNING: the current live package is in use by these Casper Policies:\n"
503
487
  policy_warning += " #{names}\n"
504
- policy_warning += "You might want to update them to use the new live package."
488
+ policy_warning += 'You might want to update them to use the new live package.'
505
489
  end # unless empty
506
490
  end # if pkg_id_being_deprecated
507
491
 
508
- confirm "Make #{pkg.edition} live for basename '#{pkg.basename}'#{rollback_warning}#{policy_warning}" , ""
492
+ confirm "Make #{pkg.edition} live for basename '#{pkg.basename}'#{rollback_warning}#{policy_warning}", ''
509
493
 
510
494
  pkg.make_live @admin
511
495
 
512
- puts "Done!"
496
+ puts 'Done!'
513
497
  puts "New installs of basename '#{pkg.basename}' will get #{pkg.version}-#{pkg.revision}"
514
- puts "Existing installs will be updated at the next d3 sync."
498
+ puts 'Existing installs will be updated at the next d3 sync.'
515
499
  end
516
500
 
517
501
  ### Edit an existing or importing package
@@ -521,23 +505,20 @@ ENDVERS
521
505
  ###
522
506
  ### @return [void]
523
507
  ###
524
- def edit_package (pkg=nil)
525
-
508
+ def edit_package(pkg = nil)
526
509
  unless pkg
527
510
  pkg_id = get_pkg_from_cli_or_prompt
528
511
  pkg = pkg_id ? D3::Package.new(id: pkg_id) : nil
529
512
  end
530
513
  if pkg.nil?
531
- puts "No targets given to edit or no matching package found"
514
+ puts 'No targets given to edit or no matching package found'
532
515
  return
533
516
  end
534
517
 
535
-
536
518
  if @options.walkthru
537
519
  changes_to_make = D3::Admin::Edit.loop_thru_editing_walkthru pkg
538
520
  else
539
-
540
- changes_to_make = D3::Admin::Edit.validate_cli_edits (@options)
521
+ changes_to_make = D3::Admin::Edit.validate_cli_edits(@options)
541
522
  end # if @options.walkthru
542
523
 
543
524
  # Confirm the edition is still good if vers or rev changed
@@ -546,20 +527,19 @@ ENDVERS
546
527
  # Confirm the auto and excl groups don't conflict with each other
547
528
  D3::Admin::Edit.check_for_new_group_overlaps pkg, changes_to_make
548
529
 
549
-
550
530
  # exit if no changes on edit
551
- if changes_to_make.empty? and not @options.import
552
- puts "No changes to make!"
553
- return
531
+ if changes_to_make.empty? && !@options.import
532
+ puts 'No changes to make!'
533
+ return
554
534
  end
555
535
 
556
536
  # confirm
557
537
  if @options.import
558
538
  confirm_heading = "Import #{pkg.edition}, JSS id #{pkg.id}, into d3"
559
- conf_deets = "with these non-default settings..."
539
+ conf_deets = 'with these non-default settings...'
560
540
  else
561
541
  confirm_heading = "Make changes to #{pkg.edition}, JSS id #{pkg.id}"
562
- conf_deets = "Here are the changes..."
542
+ conf_deets = 'Here are the changes...'
563
543
  end
564
544
 
565
545
  D3::Admin::Edit::EDITING_OPTIONS.each do |opt|
@@ -583,8 +563,7 @@ ENDVERS
583
563
  # make the changes
584
564
  D3::Admin::Edit.process_edits pkg, changes_to_make
585
565
 
586
- puts @options.import ? "Done: the package has been imported to d3." : "Done! Your changes have been saved."
587
-
566
+ puts @options.import ? 'Done: the package has been imported to d3.' : 'Done! Your changes have been saved.'
588
567
  end # edit_pkg
589
568
 
590
569
  ### delete a pkg, optionallay archiving it
@@ -592,41 +571,39 @@ ENDVERS
592
571
  ### @return [void]
593
572
  ###
594
573
  def delete_package
595
-
596
574
  pkg_id = get_pkg_from_cli_or_prompt
597
575
 
598
576
  if pkg_id.nil?
599
- puts "No targets given to delete or no matching package found"
577
+ puts 'No targets given to delete or no matching package found'
600
578
  return
601
579
  end
602
580
 
603
581
  # check to see if the pkg is missing
604
- if D3::Package.package_data[pkg_id][:status] == :missing || (not JSS::Package.all_ids.include? pkg_id)
582
+ if D3::Package.package_data[pkg_id][:status] == :missing || (!JSS::Package.all_ids.include? pkg_id)
605
583
  delete_missing_package pkg_id
606
584
  return
607
585
  else
608
586
  pkg = D3::Package.new id: pkg_id
609
587
  end
610
588
 
611
- got_scripts = (not pkg.script_ids.values.empty?)
589
+ got_scripts = !pkg.script_ids.values.empty?
612
590
 
613
591
  if got_scripts
614
592
 
615
593
  if @options.walkthru
616
- @options.keep_scripts = D3::Admin::Interactive.get_value(:get_keep_scripts, default = 'n', check_method = :validate_yes_no)
594
+ @options.keep_scripts = D3::Admin::Interactive.get_value(:get_keep_scripts, default = 'n', check_method = :validate_yes_no)
617
595
 
618
596
  @options.keep_in_jss = D3::Admin::Interactive.get_value(:get_keep_in_jss, default = 'n', check_method = :validate_yes_no)
619
597
  end # if @options.walkthru
620
598
 
621
-
622
599
  if @options.keep_scripts
623
- deets = " - Keeping pre- or post- scripts in the JSS"
600
+ deets = ' - Keeping pre- or post- scripts in the JSS'
624
601
  else
625
- deets = " - Deleting pre- or post- scripts not used elsewhere"
602
+ deets = ' - Deleting pre- or post- scripts not used elsewhere'
626
603
  end # if @options.keep_scripts
627
604
 
628
605
  else
629
- deets = " - No pre- or post- scripts to delete"
606
+ deets = ' - No pre- or post- scripts to delete'
630
607
  end # if got_scripts
631
608
 
632
609
  if @options.keep_in_jss
@@ -638,22 +615,21 @@ ENDVERS
638
615
  confirm "DELETE #{pkg.edition}, JSS id #{pkg.id}\nDist.Point Filename: #{pkg.filename}", deets
639
616
 
640
617
  if @options.keep_scripts && got_scripts
641
- puts "Scanning for other packages or policies using pre- or post- scripts before deleting..."
618
+ puts 'Scanning for other packages or policies using pre- or post- scripts before deleting...'
642
619
  end
643
620
 
644
621
  script_actions = pkg.delete(
645
- admin: @admin,
646
- keep_scripts: @options.keep_scripts,
647
- keep_in_jss: @options.keep_in_jss,
648
- rwpw: D3::Admin::Auth.rw_credentials(:dist)[:password]
649
- )
622
+ admin: @admin,
623
+ keep_scripts: @options.keep_scripts,
624
+ keep_in_jss: @options.keep_in_jss,
625
+ rwpw: D3::Admin::Auth.rw_credentials(:dist)[:password]
626
+ )
650
627
 
651
628
  unless script_actions.empty?
652
- puts "Here' what happened to the scripts:"
629
+ puts "Here's what happened to the scripts:"
653
630
  puts script_actions.join "\n"
654
631
  end
655
632
  puts "Done! #{pkg.edition} has been deleted"
656
-
657
633
  end # delete package
658
634
 
659
635
  ### Delete a package that's missing from the JSS
@@ -661,15 +637,15 @@ ENDVERS
661
637
  ###
662
638
  def delete_missing_package (pkgid)
663
639
  pkg_data = D3::Package.package_data[pkgid]
664
- script_ids = [pkg_data[:pre_install_script_id], pkg_data[:post_install_script_id], pkg_data[:pre_remove_script_id], pkg_data[:post_remove_script_id] ].compact
640
+ script_ids = [pkg_data[:pre_install_script_id], pkg_data[:post_install_script_id], pkg_data[:pre_remove_script_id], pkg_data[:post_remove_script_id]].compact
665
641
 
666
642
  if script_ids.empty?
667
- deets = " - No pre- or post- scripts to delete"
643
+ deets = ' - No pre- or post- scripts to delete'
668
644
  else
669
645
  if @options.keep_scripts
670
- deets = " - Keeping pre- or post- scripts in the JSS"
646
+ deets = ' - Keeping pre- or post- scripts in the JSS'
671
647
  else
672
- deets = " - Deleting pre- or post- scripts not in use elsewhere"
648
+ deets = ' - Deleting pre- or post- scripts not in use elsewhere'
673
649
  end # if @options.keep_scripts
674
650
  end # if script_ids.empty?
675
651
 
@@ -678,8 +654,8 @@ ENDVERS
678
654
  JSS::DB_CNX.db.query "DELETE FROM #{D3::Database::PACKAGE_TABLE[:table_name]} WHERE package_id = #{pkgid}"
679
655
  puts "Package #{pkg_data[:edition]} deleted."
680
656
 
681
- if (not @options.keep_scripts) && (not script_ids.empty?)
682
- puts "Scanning for other packages or policies using pre- or post- scripts before deleting..."
657
+ if !@options.keep_scripts && !script_ids.empty?
658
+ puts 'Scanning for other packages or policies using pre- or post- scripts before deleting...'
683
659
  policy_scripts = D3.policy_scripts
684
660
  script_ids.each do |victim_script_id|
685
661
  next unless JSS::Script.all_ids.include? victim_script_id
@@ -693,15 +669,14 @@ ENDVERS
693
669
  end
694
670
  end # policy scripts.each
695
671
  d3_users = (D3::Package.packages_for_script(victim_script_id) - [pkgid])
696
- d3_users.each{|pkgid| puts "Script '#{victim_script_name}' in use by d3 edition '#{D3::Package.ids_to_editions[pkgid]}'" }
697
- if pol_users.empty? and d3_users.empty?
672
+ d3_users.each { |pid| puts "Script '#{victim_script_name}' in use by d3 edition '#{D3::Package.ids_to_editions[pid]}'" }
673
+ if pol_users.empty? && d3_users.empty?
698
674
  JSS::Script.new(id: victim_script_id).delete
699
675
  puts "Deleted script '#{victim_script_name}'"
700
676
  end
701
677
  end # do script id
702
678
  end # if @options.keep_scripts && (not script_ids.empty?)
703
-
704
- end # delete_missing_package (pkgid)
679
+ end # delete_missing_package(pkgid)
705
680
 
706
681
  ### Get an existing pkg id from the user via prompt (if walkthru) or the
707
682
  ### first thing listed in @targets. We don't instantiate the pkg here
@@ -710,11 +685,11 @@ ENDVERS
710
685
  ### @return [Ingeter, nil] an existing d3 pkg id if one was chosen
711
686
  ###
712
687
  def get_pkg_from_cli_or_prompt
713
- if @options.walkthru and @targets.first.nil?
688
+ if @options.walkthru && @targets.first.nil?
714
689
  D3::Admin::Interactive.get_value :get_existing_package, nil, :validate_existing_package
715
690
  else
716
691
  pkg_data = D3::Package.find_package(@targets.first, :hash)
717
- return pkg_data ? pkg_data[:id] : nil
692
+ pkg_data ? pkg_data[:id] : nil
718
693
  end
719
694
  end
720
695
 
@@ -729,21 +704,20 @@ ENDVERS
729
704
  ### @param details[String] The details requireing confirmation
730
705
  ###
731
706
  ###
732
- def confirm (action, details = nil)
733
-
707
+ def confirm(action, details = nil)
734
708
  puts
735
- puts "*****************************************"
709
+ puts '*****************************************'
736
710
  puts "Ahoy there! You are about to:\n#{action}"
737
- puts "*****************************************"
711
+ puts '*****************************************'
738
712
  puts details if details
739
713
 
740
714
  if @options.auto_confirm
741
- puts "auto-confirmed! Here we go....."
715
+ puts 'auto-confirmed! Here we go.....'
742
716
  else
743
717
  puts
744
- reply = Readline.readline("Are you SURE? (y/n): ", false)
718
+ reply = Readline.readline('Are you SURE? (y/n): ', false)
745
719
  return true if reply =~ /^y/i
746
- puts "Cancelled - wise choice!"
720
+ puts 'Cancelled - wise choice!'
747
721
  exit 0
748
722
  end # if autoconfirm
749
723
  end # confirm
@@ -753,11 +727,10 @@ ENDVERS
753
727
  ### @return [void]
754
728
  ###
755
729
  def show_package_info
756
-
757
730
  pkg_id = get_pkg_from_cli_or_prompt
758
731
 
759
732
  if pkg_id.nil?
760
- puts "No targets given or no matching package found"
733
+ puts 'No targets given or no matching package found'
761
734
  return
762
735
  end
763
736
 
@@ -772,10 +745,10 @@ ENDDEETS
772
745
  pkg_deets += "Basename: #{pkg.basename}\n"
773
746
  pkg_deets += "Version: #{pkg.version}\n"
774
747
  pkg_deets += "Revision: #{pkg.revision}\n"
775
- pkg_deets += "Added to on: #{pkg.added_date.strftime "%Y-%m-%d"}\n"
748
+ pkg_deets += "Added to on: #{pkg.added_date.strftime '%Y-%m-%d'}\n"
776
749
  pkg_deets += "Added by: #{pkg.added_by}\n"
777
750
  if pkg.release_date
778
- pkg_deets += "Released on: #{pkg.release_date.strftime "%Y-%m-%d"}\n"
751
+ pkg_deets += "Released on: #{pkg.release_date.strftime '%Y-%m-%d'}\n"
779
752
  pkg_deets += "Released by: #{pkg.released_by}\n"
780
753
  end
781
754
 
@@ -784,15 +757,14 @@ ENDDEETS
784
757
  next if done.include? opt
785
758
  label = D3::Admin::OPTIONS[opt][:label]
786
759
  if D3::Admin::OPTIONS[opt][:display_conversion]
787
- val_display = D3::Admin::OPTIONS[opt][:display_conversion].call(pkg.send opt)
760
+ val_display = D3::Admin::OPTIONS[opt][:display_conversion].call(pkg.send(opt))
788
761
  else
789
- val_display = pkg.send opt
762
+ val_display = pkg.send opt
790
763
  end
791
- val_display = val_display.to_s.empty? ? "none" : val_display
764
+ val_display = val_display.to_s.empty? ? 'none' : val_display
792
765
  pkg_deets += "#{label}: #{val_display}\n"
793
766
  end
794
767
 
795
-
796
768
  puts pkg_deets
797
769
  puts
798
770
  end # show_package_info
@@ -806,22 +778,22 @@ ENDDEETS
806
778
 
807
779
  if @options.walkthru
808
780
  # prompt for search type?
809
- search_for = D3::Admin::Interactive.prompt_for_data(
810
- desc: "SEARCH PACKAGES BY?\nAre you searching for packages by basename, or by scoped groups?\nEnter 'b' or 'g'",
811
- prompt: "Basenames or Groups",
812
- default: 'b',
813
- required: false
814
- )
781
+ search_for = D3::Admin::Interactive.prompt_for_data(
782
+ desc: "SEARCH PACKAGES BY?\nAre you searching for packages by basename, or by scoped groups?\nEnter 'b' or 'g'",
783
+ prompt: 'Basenames or Groups',
784
+ default: 'b',
785
+ required: false
786
+ )
815
787
  @options.search_groups = true if search_for =~ /^g/i
816
788
 
817
789
  @targets = [D3::Admin::Interactive.get_search_target] if @targets.empty?
818
790
  @options.status = D3::Admin::Interactive.get_status_for_filter.split(/,\s*/) if @options.status.empty?
819
- end #if @options.walkthru
791
+ end # if @options.walkthru
820
792
 
821
- @options.status = [] if @options.status.include? "all"
793
+ @options.status = [] if @options.status.include? 'all'
822
794
 
823
795
  # show all pkgs or group scope
824
- if @targets.empty? or @targets.include? "all"
796
+ if @targets.empty? || @targets.include?('all')
825
797
  if @options.search_groups
826
798
  D3::Admin::Report.list_all_pkgs_with_scope @options.status
827
799
  else
@@ -832,14 +804,13 @@ ENDDEETS
832
804
 
833
805
  # show specific basenames or group scopes
834
806
  @targets.each do |search_target|
835
-
836
- # groups?
807
+ # Groups?
837
808
  if @options.search_groups
838
- found_groups = JSS::ComputerGroup.all_names.select{|gn| gn =~ /#{search_target}/}
809
+ found_groups = JSS::ComputerGroup.all_names.select { |gn| gn =~ /#{search_target}/ }
839
810
  if found_groups.empty?
840
811
  puts "No computer groups in Casper match '#{search_target}'"
841
812
  else
842
- found_groups.each {|fgn|
813
+ found_groups.each { |fgn|
843
814
  D3::Admin::Report.list_scoped_installs fgn, @options.status, :auto
844
815
  D3::Admin::Report.list_scoped_installs fgn, @options.status, :excluded
845
816
  } # found_groups.each
@@ -847,11 +818,11 @@ ENDDEETS
847
818
 
848
819
  # basenames
849
820
  else
850
- found_basenames = D3::Package.all_basenames.select{|bn| bn =~ /#{search_target}/}
821
+ found_basenames = D3::Package.all_basenames.select { |bn| bn =~ /#{search_target}/ }
851
822
  if found_basenames.empty?
852
823
  puts "No basenames in d3 match '#{search_target}'"
853
824
  else
854
- found_basenames.each {|fbn| D3::Admin::Report.list_packages fbn, @options.status }
825
+ found_basenames.each { |fbn| D3::Admin::Report.list_packages fbn, @options.status }
855
826
  end # if found_basenames.empty?
856
827
  end # if @options.search_groups
857
828
  end # @targets.each do |search_target|
@@ -872,13 +843,13 @@ ENDDEETS
872
843
  if @targets.empty?
873
844
  one_or_all = D3::Admin::Interactive.prompt_for_data(
874
845
  desc: "ALL COMPUTERS?\nAre you reporting for a single computer or all computers?\nEnter 'all' for all computers, '1' for one",
875
- prompt: "All or 1",
846
+ prompt: 'All or 1',
876
847
  default: 'all',
877
848
  required: false
878
849
  )
879
850
 
880
851
  # basename report across computers
881
- if one_or_all == "all"
852
+ if one_or_all == 'all'
882
853
  @targets = [(D3::Admin::Interactive.get_value :get_basename, nil, :validate_basename)]
883
854
 
884
855
  # reporting single computers
@@ -891,34 +862,32 @@ ENDDEETS
891
862
 
892
863
  # prompt for rcpts or puppies
893
864
  rcpts_or_pups = D3::Admin::Interactive.prompt_for_data(
894
- desc: "RECEIPTS OR PUPPIES?\nShould the report list receipts or pending puppytime installs?\nEnter 'r' for receipts, 'p' for puppies",
895
- prompt: "Receipts or puppies",
896
- required: false,
897
- default: 'r'
865
+ desc: "RECEIPTS OR PUPPIES?\nShould the report list receipts or pending puppytime installs?\nEnter 'r' for receipts, 'p' for puppies",
866
+ prompt: 'Receipts or puppies',
867
+ required: false,
868
+ default: 'r'
898
869
  )
899
- @options.report_q = rcpts_or_pups =~ /^p/i ? true : false
870
+ @options.report_q = rcpts_or_pups =~ /^p/i ? true : false
900
871
 
901
872
  # prompt for status or frozen
902
873
  @options.status = D3::Admin::Interactive.get_status_for_filter(:with_frozen).split(/,\s*/) if @options.status.empty?
903
874
 
904
- end #if @options.walkthru
875
+ end # if @options.walkthru
905
876
 
906
- @options.status = [] if @options.status.include? "all"
877
+ @options.status = [] if @options.status.include? 'all'
907
878
 
908
879
  # pass the --frozen option with the --status options, since
909
880
  # its treated like a pseudo-status, and thats where walkthru puts it too
910
- @options.status << "frozen" if @options.report_frozen
881
+ @options.status << 'frozen' if @options.report_frozen
911
882
 
912
883
  reporting = @options.report_q ? :puppies : :receipts
913
884
 
914
-
915
885
  if @targets.empty?
916
- puts "No basename or computer name given for report"
886
+ puts 'No basename or computer name given for report'
917
887
  return
918
888
  end
919
889
 
920
890
  @targets.each do |target|
921
-
922
891
  # report puppies
923
892
  if reporting == :puppies
924
893
  if @options.report_computers
@@ -951,7 +920,6 @@ ENDDEETS
951
920
  ### @return [void]
952
921
  ###
953
922
  def config
954
-
955
923
  if @targets.include? 'display'
956
924
  D3::Admin::Prefs.display_config
957
925
  else
@@ -959,16 +927,12 @@ ENDDEETS
959
927
  end
960
928
  end # config
961
929
 
962
-
963
930
  end # class App
964
931
 
965
-
966
-
967
-
968
932
  ### save terminal state incase user interrupts during readline or less
969
933
  if $stdin.tty?
970
934
  stty_save = `stty -g`.chomp
971
- trap("SIGINT") do
935
+ trap('SIGINT') do
972
936
  puts "\nCancelled! Woot!"
973
937
  system('stty', stty_save)
974
938
  exit 0
@@ -979,8 +943,8 @@ begin
979
943
  app = App.new
980
944
  app.run
981
945
  rescue
982
- puts "An error occurred: #{$!.class}: #{$!}"
983
- puts $@ if D3::Admin.debug
946
+ puts "An error occurred: #{$ERROR_INFO.class}: #{$ERROR_INFO}!"
947
+ puts $ERROR_POSITION if D3::Admin.debug
984
948
  exit 1
985
949
  ensure
986
950
  if D3::Admin::Auth.connected?