vmc 0.3.13.beta.5 → 0.3.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -388,7 +388,6 @@ module VMC::Cli::Command
388
388
 
389
389
  # check if we have hit our app limit
390
390
  check_app_limit
391
-
392
391
  # check memsize here for capacity
393
392
  if memswitch && !no_start
394
393
  check_has_capacity_for(mem_choice_to_quota(memswitch) * instances)
@@ -572,6 +571,17 @@ module VMC::Cli::Command
572
571
  err "Can't deploy applications from staging directory: [#{Dir.tmpdir}]"
573
572
  end
574
573
 
574
+ def check_unreachable_links
575
+ path = Dir.pwd
576
+ files = Dir.glob("#{path}/**/*", File::FNM_DOTMATCH)
577
+ unreachable_paths = files.select { |f|
578
+ File.symlink? f and !File.expand_path(File.readlink(f)).include? path
579
+ } if files
580
+ if unreachable_paths.length > 0
581
+ err "Can't deploy application containing links '#{unreachable_paths}' that reach outside its root '#{path}'"
582
+ end
583
+ end
584
+
575
585
  def upload_app_bits(appname, path)
576
586
  display 'Uploading Application:'
577
587
 
@@ -586,6 +596,7 @@ module VMC::Cli::Command
586
596
  if war_file = Dir.glob('*.war').first
587
597
  VMC::Cli::ZipUtil.unpack(war_file, explode_dir)
588
598
  else
599
+ check_unreachable_links
589
600
  FileUtils.mkdir(explode_dir)
590
601
  files = Dir.glob('{*,.[^\.]*}')
591
602
  # Do not process .git files
@@ -1,5 +1,5 @@
1
-
2
1
  require 'rubygems'
2
+ require 'interact'
3
3
  require 'terminal-table/import'
4
4
 
5
5
  module VMC::Cli
@@ -7,6 +7,9 @@ module VMC::Cli
7
7
  module Command
8
8
 
9
9
  class Base
10
+ include Interactive
11
+ disable_rewind
12
+
10
13
  attr_reader :no_prompt, :prompt_ok
11
14
 
12
15
  def initialize(options={})
@@ -20,7 +23,9 @@ module VMC::Cli
20
23
  end
21
24
  end
22
25
 
23
- def client
26
+ # Inject a client to help in testing.
27
+ def client(cli=nil)
28
+ @client ||= cli
24
29
  return @client if @client
25
30
  @client = VMC::Client.new(target_url, auth_token)
26
31
  @client.trace = VMC::Cli::Config.trace if VMC::Cli::Config.trace
@@ -68,334 +68,6 @@ module VMCExtensions
68
68
  return sprintf("%.#{prec}fM", size/(1024.0*1024.0)) if size < (1024*1024*1024)
69
69
  return sprintf("%.#{prec}fG", size/(1024.0*1024.0*1024.0))
70
70
  end
71
-
72
- # general-purpose interaction
73
- #
74
- # `question' is the prompt (without ": " at the end)
75
- # `options' is a hash containing:
76
- # :input - the input source (defaults to STDIN)
77
- # :default - the default value, also used to attempt type conversion
78
- # of the answer (e.g. numeric/boolean)
79
- # :choices - a list of strings to choose from
80
- # :indexed - whether to allow choosing from `:choices' by their index,
81
- # best for when there are many choices
82
- # :echo - a string to echo when showing the input;
83
- # used for things like censoring password inpt
84
- # :callback - a block used to override certain actions
85
- #
86
- # takes 4 arguments:
87
- # action: the event, e.g. :up or [:key, X] where X is a
88
- # string containing a single character
89
- # answer: the current answer to the question; you'll
90
- # probably mutate this
91
- # position: the current offset from the start of the
92
- # answer string, e.g. when typing in the middle
93
- # of the input, this will be where you insert
94
- # characters
95
- # echo: the :echo option above, may be nil
96
- #
97
- # the block should return the updated `position', or nil if
98
- # it didn't handle the event
99
- def ask(question, options = {})
100
- default = options[:default]
101
- choices = options[:choices]
102
- indexed = options[:indexed]
103
- callback = options[:callback]
104
- input = options[:input] || STDIN
105
- echo = options[:echo]
106
-
107
- if choices
108
- VMCExtensions.ask_choices(input, question, default, choices, indexed, echo, &callback)
109
- else
110
- VMCExtensions.ask_default(input, question, default, echo, &callback)
111
- end
112
- end
113
-
114
- ESCAPES = {
115
- "[A" => :up, "H" => :up,
116
- "[B" => :down, "P" => :down,
117
- "[C" => :right, "M" => :right,
118
- "[D" => :left, "K" => :left,
119
- "[3~" => :delete, "S" => :delete,
120
- "[H" => :home, "G" => :home,
121
- "[F" => :end, "O" => :end
122
- }
123
-
124
- def handle_action(which, ans, pos, echo = nil)
125
- if block_given?
126
- res = yield which, ans, pos, echo
127
- return res unless res.nil?
128
- end
129
-
130
- case which
131
- when :up
132
- # nothing
133
-
134
- when :down
135
- # nothing
136
-
137
- when :tab
138
- # nothing
139
-
140
- when :right
141
- unless pos == ans.size
142
- display censor(ans[pos .. pos], echo), false
143
- return pos + 1
144
- end
145
-
146
- when :left
147
- unless pos == 0
148
- display "\b", false
149
- return pos - 1
150
- end
151
-
152
- when :delete
153
- unless pos == ans.size
154
- ans.slice!(pos, 1)
155
- if WINDOWS
156
- rest = ans[pos .. -1]
157
- display(censor(rest, echo) + " \b" + ("\b" * rest.size), false)
158
- else
159
- display("\e[P", false)
160
- end
161
- end
162
-
163
- when :home
164
- display("\b" * pos, false)
165
- return 0
166
-
167
- when :end
168
- display(censor(ans[pos .. -1], echo), false)
169
- return ans.size
170
-
171
- when :backspace
172
- if pos > 0
173
- ans.slice!(pos - 1, 1)
174
-
175
- if WINDOWS
176
- rest = ans[pos - 1 .. -1]
177
- display("\b" + censor(rest, echo) + " \b" + ("\b" * rest.size), false)
178
- else
179
- display("\b\e[P", false)
180
- end
181
-
182
- return pos - 1
183
- end
184
-
185
- when :interrupt
186
- raise Interrupt.new
187
-
188
- when :eof
189
- return false if ans.empty?
190
-
191
- when :kill_word
192
- if pos > 0
193
- start = /[^\s]*\s*$/ =~ ans[0 .. pos]
194
- length = pos - start
195
- ans.slice!(start, length)
196
- display("\b" * length + " " * length + "\b" * length, false)
197
- return start
198
- end
199
-
200
- when Array
201
- case which[0]
202
- when :key
203
- c = which[1]
204
- rest = ans[pos .. -1]
205
-
206
- ans.insert(pos, c)
207
-
208
- display(censor(c + rest, echo) + ("\b" * rest.size), false)
209
-
210
- return pos + 1
211
- end
212
- end
213
-
214
- pos
215
- end
216
-
217
- def censor(str, with)
218
- return str unless with
219
- with * str.size
220
- end
221
-
222
- # ask a simple question, maybe with a default answer
223
- #
224
- # reads character-by-character, handling backspaces, and sending each
225
- # character to a block if provided
226
- def self.ask_default(input, question, default = nil, echo = nil, &callback)
227
- while true
228
- prompt(question, default)
229
-
230
- ans = ""
231
- pos = 0
232
- escaped = false
233
- escape_seq = ""
234
-
235
- with_char_io(input) do
236
- until pos == false or (c = get_character(input)) =~ /[\r\n]/
237
- if c == "\e" || c == "\xE0"
238
- escaped = true
239
- elsif escaped
240
- escape_seq << c
241
-
242
- if cmd = ESCAPES[escape_seq]
243
- pos = handle_action(cmd, ans, pos, echo, &callback)
244
- escaped, escape_seq = false, ""
245
- elsif ESCAPES.select { |k, v| k.start_with? escape_seq }.empty?
246
- escaped, escape_seq = false, ""
247
- end
248
- elsif c == "\177" or c == "\b" # backspace
249
- pos = handle_action(:backspace, ans, pos, echo, &callback)
250
- elsif c == "\x01"
251
- pos = handle_action(:home, ans, pos, echo, &callback)
252
- elsif c == "\x03"
253
- pos = handle_action(:interrupt, ans, pos, echo, &callback)
254
- elsif c == "\x04"
255
- pos = handle_action(:eof, ans, pos, echo, &callback)
256
- elsif c == "\x05"
257
- pos = handle_action(:end, ans, pos, echo, &callback)
258
- elsif c == "\x17"
259
- pos = handle_action(:kill_word, ans, pos, echo, &callback)
260
- elsif c == "\t"
261
- pos = handle_action(:tab, ans, pos, echo, &callback)
262
- elsif c < " "
263
- # ignore
264
- else
265
- pos = handle_action([:key, c], ans, pos, echo, &callback)
266
- end
267
- end
268
- end
269
-
270
- display "\n", false
271
-
272
- if ans.empty?
273
- return default unless default.nil?
274
- else
275
- return match_type(ans, default)
276
- end
277
- end
278
- end
279
-
280
- def self.ask_choices(input, question, default, choices, indexed = false, echo = nil, &callback)
281
- msg = question.dup
282
-
283
- if indexed
284
- choices.each.with_index do |o, i|
285
- say "#{i + 1}: #{o}"
286
- end
287
- else
288
- msg << " (#{choices.collect(&:inspect).join ", "})"
289
- end
290
-
291
- while true
292
- ans = ask_default(input, msg, default, echo, &callback)
293
-
294
- matches = choices.select { |x| x.start_with? ans }
295
-
296
- if matches.size == 1
297
- return matches.first
298
- elsif indexed and ans =~ /^\d+$/ and res = choices.to_a[ans.to_i - 1]
299
- return res
300
- elsif matches.size > 1
301
- warn "Please disambiguate: #{matches.join " or "}?"
302
- else
303
- warn "Unknown answer, please try again!"
304
- end
305
- end
306
- end
307
-
308
- # display a question and show the default value
309
- def self.prompt(question, default = nil)
310
- msg = question.dup
311
-
312
- case default
313
- when true
314
- msg << " [Yn]"
315
- when false
316
- msg << " [yN]"
317
- else
318
- msg << " [#{default.inspect}]" if default
319
- end
320
-
321
- display "#{msg}: ", false
322
- end
323
-
324
- # try to make `str' be the same class as `x'
325
- def self.match_type(str, x)
326
- case x
327
- when Integer
328
- str.to_i
329
- when true, false
330
- str.upcase.start_with? "Y"
331
- else
332
- str
333
- end
334
- end
335
-
336
- # definitions for reading character-by-character
337
- begin
338
- require "Win32API"
339
-
340
- def self.with_char_io(input)
341
- yield
342
- end
343
-
344
- def self.get_character(input)
345
- if input == STDIN
346
- begin
347
- Win32API.new("msvcrt", "_getch", [], "L").call.chr
348
- rescue
349
- Win32API.new("crtdll", "_getch", [], "L").call.chr
350
- end
351
- else
352
- input.getc.chr
353
- end
354
- end
355
- rescue LoadError
356
- begin
357
- require "termios"
358
-
359
- def self.with_char_io(input)
360
- return yield unless input.tty?
361
-
362
- before = Termios.getattr(input)
363
-
364
- new = before.dup
365
- new.c_lflag &= ~(Termios::ECHO | Termios::ICANON)
366
- new.c_cc[Termios::VMIN] = 1
367
-
368
- begin
369
- Termios.setattr(input, Termios::TCSANOW, new)
370
- yield
371
- ensure
372
- Termios.setattr(input, Termios::TCSANOW, before)
373
- end
374
- end
375
-
376
- def self.get_character(input)
377
- input.getc.chr
378
- end
379
- rescue LoadError
380
- # set tty modes for the duration of a block, restoring them afterward
381
- def self.with_char_io(input)
382
- return yield unless input.tty?
383
-
384
- begin
385
- before = `stty -g`
386
- system("stty raw -echo -icanon isig")
387
- yield
388
- ensure
389
- system("stty #{before}")
390
- end
391
- end
392
-
393
- # this assumes we're wrapped in #with_stty
394
- def self.get_character(input)
395
- input.getc.chr
396
- end
397
- end
398
- end
399
71
  end
400
72
 
401
73
  module VMCStringExtensions
@@ -438,6 +438,10 @@ class VMC::Cli::Runner
438
438
  end
439
439
 
440
440
  rescue OptionParser::InvalidOption => e
441
+ puts(e.message.red)
442
+ puts("\n")
443
+ puts(basic_usage)
444
+ @exit_status = false
441
445
  rescue OptionParser::AmbiguousOption => e
442
446
  puts(e.message.red)
443
447
  puts("\n")
@@ -473,7 +477,7 @@ class VMC::Cli::Runner
473
477
  rescue Interrupt => e
474
478
  say("\nInterrupted".red)
475
479
  @exit_status = false
476
- rescue => e
480
+ rescue Exception => e
477
481
  puts e.message.red
478
482
  puts e.backtrace
479
483
  @exit_status = false
@@ -2,6 +2,6 @@ module VMC
2
2
  module Cli
3
3
  # This version number is used as the RubyGem release version.
4
4
  # The internal VMC version number is VMC::VERSION.
5
- VERSION = '0.3.13.beta.5'
5
+ VERSION = '0.3.13'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vmc
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 7
5
- version: 0.3.13.beta.5
4
+ prerelease:
5
+ version: 0.3.13
6
6
  platform: ruby
7
7
  authors:
8
8
  - VMware
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-10-24 00:00:00 -07:00
13
+ date: 2011-11-02 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -61,38 +61,49 @@ dependencies:
61
61
  type: :runtime
62
62
  version_requirements: *id004
63
63
  - !ruby/object:Gem::Dependency
64
- name: rake
64
+ name: interact
65
65
  prerelease: false
66
66
  requirement: &id005 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ version: 0.2.0
72
+ type: :runtime
73
+ version_requirements: *id005
74
+ - !ruby/object:Gem::Dependency
75
+ name: rake
76
+ prerelease: false
77
+ requirement: &id006 !ruby/object:Gem::Requirement
67
78
  none: false
68
79
  requirements:
69
80
  - - ">="
70
81
  - !ruby/object:Gem::Version
71
82
  version: "0"
72
83
  type: :development
73
- version_requirements: *id005
84
+ version_requirements: *id006
74
85
  - !ruby/object:Gem::Dependency
75
86
  name: rspec
76
87
  prerelease: false
77
- requirement: &id006 !ruby/object:Gem::Requirement
88
+ requirement: &id007 !ruby/object:Gem::Requirement
78
89
  none: false
79
90
  requirements:
80
91
  - - ~>
81
92
  - !ruby/object:Gem::Version
82
93
  version: 1.3.0
83
94
  type: :development
84
- version_requirements: *id006
95
+ version_requirements: *id007
85
96
  - !ruby/object:Gem::Dependency
86
97
  name: webmock
87
98
  prerelease: false
88
- requirement: &id007 !ruby/object:Gem::Requirement
99
+ requirement: &id008 !ruby/object:Gem::Requirement
89
100
  none: false
90
101
  requirements:
91
102
  - - "="
92
103
  - !ruby/object:Gem::Version
93
104
  version: 1.5.0
94
105
  type: :development
95
- version_requirements: *id007
106
+ version_requirements: *id008
96
107
  description: Client library and CLI that provides access to the VMware Cloud Application Platform.
97
108
  email: support@vmware.com
98
109
  executables:
@@ -144,9 +155,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
144
155
  required_rubygems_version: !ruby/object:Gem::Requirement
145
156
  none: false
146
157
  requirements:
147
- - - ">"
158
+ - - ">="
148
159
  - !ruby/object:Gem::Version
149
- version: 1.3.1
160
+ version: "0"
150
161
  requirements: []
151
162
 
152
163
  rubyforge_project: