olympe 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/LICENSE +24 -0
  2. data/README.md +103 -0
  3. data/Rakefile +101 -0
  4. data/bin/olympe +6 -0
  5. data/caldecott_helper/Gemfile +10 -0
  6. data/caldecott_helper/Gemfile.lock +48 -0
  7. data/caldecott_helper/server.rb +43 -0
  8. data/config/clients.yml +17 -0
  9. data/config/micro/offline.conf +2 -0
  10. data/config/micro/paths.yml +22 -0
  11. data/config/micro/refresh_ip.rb +20 -0
  12. data/lib/cli/commands/admin.rb +80 -0
  13. data/lib/cli/commands/apps.rb +1208 -0
  14. data/lib/cli/commands/base.rb +233 -0
  15. data/lib/cli/commands/manifest.rb +56 -0
  16. data/lib/cli/commands/micro.rb +115 -0
  17. data/lib/cli/commands/misc.rb +140 -0
  18. data/lib/cli/commands/services.rb +217 -0
  19. data/lib/cli/commands/user.rb +65 -0
  20. data/lib/cli/config.rb +170 -0
  21. data/lib/cli/console_helper.rb +163 -0
  22. data/lib/cli/core_ext.rb +122 -0
  23. data/lib/cli/errors.rb +19 -0
  24. data/lib/cli/file_helper.rb +123 -0
  25. data/lib/cli/frameworks.rb +265 -0
  26. data/lib/cli/manifest_helper.rb +316 -0
  27. data/lib/cli/runner.rb +568 -0
  28. data/lib/cli/services_helper.rb +104 -0
  29. data/lib/cli/tunnel_helper.rb +336 -0
  30. data/lib/cli/usage.rb +125 -0
  31. data/lib/cli/version.rb +7 -0
  32. data/lib/cli/zip_util.rb +77 -0
  33. data/lib/cli.rb +48 -0
  34. data/lib/vmc/client.rb +558 -0
  35. data/lib/vmc/const.rb +27 -0
  36. data/lib/vmc/micro/switcher/base.rb +97 -0
  37. data/lib/vmc/micro/switcher/darwin.rb +19 -0
  38. data/lib/vmc/micro/switcher/dummy.rb +15 -0
  39. data/lib/vmc/micro/switcher/linux.rb +16 -0
  40. data/lib/vmc/micro/switcher/windows.rb +31 -0
  41. data/lib/vmc/micro/vmrun.rb +158 -0
  42. data/lib/vmc/micro.rb +56 -0
  43. data/lib/vmc.rb +3 -0
  44. metadata +279 -0
data/lib/cli/runner.rb ADDED
@@ -0,0 +1,568 @@
1
+
2
+ require 'optparse'
3
+
4
+ require File.dirname(__FILE__) + '/usage'
5
+
6
+ class VMC::Cli::Runner
7
+
8
+ attr_reader :namespace
9
+ attr_reader :action
10
+ attr_reader :args
11
+ attr_reader :options
12
+
13
+ def self.run(args)
14
+ new(args).run
15
+ end
16
+
17
+ def initialize(args=[])
18
+ @args = args
19
+ @options = { :colorize => true }
20
+ @exit_status = true
21
+ end
22
+
23
+ # Collect all the available options for all commands
24
+ # Some duplicates exists to capture all scenarios
25
+ def parse_options!
26
+ opts_parser = OptionParser.new do |opts|
27
+ opts.banner = "\nAvailable options:\n\n"
28
+
29
+ opts.on('--email EMAIL') { |email| @options[:email] = email }
30
+ opts.on('--user EMAIL') { |email| @options[:email] = email }
31
+ opts.on('--passwd PASS') { |pass| @options[:password] = pass }
32
+ opts.on('--pass PASS') { |pass| @options[:password] = pass }
33
+ opts.on('--password PASS') { |pass| @options[:password] = pass }
34
+ opts.on('--token-file TOKEN_FILE') { |token_file| @options[:token_file] = token_file }
35
+ opts.on('--app NAME') { |name| @options[:name] = name }
36
+ opts.on('--name NAME') { |name| @options[:name] = name }
37
+ opts.on('--bind BIND') { |bind| @options[:bind] = bind }
38
+ opts.on('--instance INST') { |inst| @options[:instance] = inst }
39
+ opts.on('--instances INST') { |inst| @options[:instances] = inst }
40
+ opts.on('--url URL') { |url| @options[:url] = url }
41
+ opts.on('--mem MEM') { |mem| @options[:mem] = mem }
42
+ opts.on('--path PATH') { |path| @options[:path] = path }
43
+ opts.on('--no-start') { @options[:nostart] = true }
44
+ opts.on('--nostart') { @options[:nostart] = true }
45
+ opts.on('--force') { @options[:force] = true }
46
+ opts.on('--all') { @options[:all] = true }
47
+
48
+ # generic tracing and debugging
49
+ opts.on('-t [TKEY]') { |tkey| @options[:trace] = tkey || true }
50
+ opts.on('--trace [TKEY]') { |tkey| @options[:trace] = tkey || true }
51
+
52
+ # start application in debug mode
53
+ opts.on('-d [MODE]') { |mode| @options[:debug] = mode || "run" }
54
+ opts.on('--debug [MODE]') { |mode| @options[:debug] = mode || "run" }
55
+
56
+ # override manifest file
57
+ opts.on('-m FILE') { |file| @options[:manifest] = file }
58
+ opts.on('--manifest FILE') { |file| @options[:manifest] = file }
59
+
60
+ opts.on('-q', '--quiet') { @options[:quiet] = true }
61
+
62
+ # micro cloud options
63
+ opts.on('--vmx FILE') { |file| @options[:vmx] = file }
64
+ opts.on('--vmrun FILE') { |file| @options[:vmrun] = file }
65
+ opts.on('--save') { @options[:save] = true }
66
+
67
+ # Don't use builtin zip
68
+ opts.on('--no-zip') { @options[:nozip] = true }
69
+ opts.on('--nozip') { @options[:nozip] = true }
70
+
71
+ opts.on('--no-resources') { @options[:noresources] = true }
72
+ opts.on('--noresources') { @options[:noresources] = true }
73
+
74
+ opts.on('--no-color') { @options[:colorize] = false }
75
+ opts.on('--verbose') { @options[:verbose] = true }
76
+
77
+ opts.on('-n','--no-prompt') { @options[:noprompts] = true }
78
+ opts.on('--noprompt') { @options[:noprompts] = true }
79
+ opts.on('--non-interactive') { @options[:noprompts] = true }
80
+
81
+ opts.on('--prefix') { @options[:prefixlogs] = true }
82
+ opts.on('--prefix-logs') { @options[:prefixlogs] = true }
83
+ opts.on('--prefixlogs') { @options[:prefixlogs] = true }
84
+
85
+ opts.on('--json') { @options[:json] = true }
86
+
87
+ opts.on('-v', '--version') { set_cmd(:misc, :version) }
88
+ opts.on('-h', '--help') { puts "#{command_usage}\n"; exit }
89
+
90
+ opts.on('--port PORT') { |port| @options[:port] = port }
91
+
92
+ opts.on('--runtime RUNTIME') { |rt| @options[:runtime] = rt }
93
+
94
+ # deprecated
95
+ opts.on('--exec EXEC') { |exec| @options[:exec] = exec }
96
+ opts.on('--noframework') { @options[:noframework] = true }
97
+ opts.on('--canary') { @options[:canary] = true }
98
+
99
+ # Proxying for another user, requires admin privileges
100
+ opts.on('-u PROXY') { |proxy| @options[:proxy] = proxy }
101
+
102
+ # Select infrastructure
103
+ opts.on('--infra INFRA') { |infra| @options[:infra] = infra }
104
+
105
+ opts.on_tail('--options') { puts "#{opts}\n"; exit }
106
+ end
107
+ instances_delta_arg = check_instances_delta!
108
+ @args = opts_parser.parse!(@args)
109
+ @args.concat instances_delta_arg
110
+ convert_options!
111
+ self
112
+ end
113
+
114
+ def check_instances_delta!
115
+ return unless @args
116
+ instance_args = @args.select { |arg| /^[-]\d+$/ =~ arg } || []
117
+ @args.delete_if { |arg| instance_args.include? arg}
118
+ instance_args
119
+ end
120
+
121
+ def display_help
122
+ puts command_usage
123
+ exit
124
+ end
125
+
126
+ def convert_options!
127
+ # make sure certain options are valid and in correct form.
128
+ @options[:instances] = Integer(@options[:instances]) if @options[:instances]
129
+ end
130
+
131
+ def set_cmd(namespace, action, args_range=0)
132
+ return if @help_only
133
+ unless args_range == "*" || args_range.is_a?(Range)
134
+ args_range = (args_range.to_i..args_range.to_i)
135
+ end
136
+
137
+ if args_range == "*" || args_range.include?(@args.size)
138
+ @namespace = namespace
139
+ @action = action
140
+ else
141
+ @exit_status = false
142
+ if @args.size > args_range.last
143
+ usage_error("Too many arguments for [#{action}]: %s" % [ @args[args_range.last..-1].map{|a| "'#{a}'"}.join(', ') ])
144
+ else
145
+ usage_error("Not enough arguments for [#{action}]")
146
+ end
147
+ end
148
+ end
149
+
150
+ def parse_command!
151
+ # just return if already set, happends with -v, -h
152
+ return if @namespace && @action
153
+
154
+ verb = @args.shift
155
+ case verb
156
+
157
+ when 'version'
158
+ usage('olympe version')
159
+ set_cmd(:misc, :version)
160
+
161
+ when 'target'
162
+ usage('olympe target [url] [--url]')
163
+ if @args.size == 1
164
+ set_cmd(:misc, :set_target, 1)
165
+ else
166
+ set_cmd(:misc, :target)
167
+ end
168
+
169
+ when 'targets'
170
+ usage('olympe targets')
171
+ set_cmd(:misc, :targets)
172
+
173
+ when 'tokens'
174
+ usage('olympe tokens')
175
+ set_cmd(:misc, :tokens)
176
+
177
+ when 'info'
178
+ usage('olympe info')
179
+ set_cmd(:misc, :info)
180
+
181
+ when 'runtimes'
182
+ usage('olympe runtimes')
183
+ set_cmd(:misc, :runtimes)
184
+
185
+ when 'frameworks'
186
+ usage('olympe frameworks')
187
+ set_cmd(:misc, :frameworks)
188
+
189
+ when 'infras'
190
+ usage('olympe infras')
191
+ set_cmd(:misc, :infras)
192
+
193
+ when 'user'
194
+ usage('olympe user')
195
+ set_cmd(:user, :info)
196
+
197
+ when 'login'
198
+ usage('olympe login [email] [--email EMAIL] [--passwd PASS]')
199
+ if @args.size == 1
200
+ set_cmd(:user, :login, 1)
201
+ else
202
+ set_cmd(:user, :login)
203
+ end
204
+
205
+ when 'logout'
206
+ usage('olympe logout')
207
+ set_cmd(:user, :logout)
208
+
209
+ when 'passwd'
210
+ usage('olympe passwd')
211
+ if @args.size == 1
212
+ set_cmd(:user, :change_password, 1)
213
+ else
214
+ set_cmd(:user, :change_password)
215
+ end
216
+
217
+ when 'add-user', 'add_user', 'create_user', 'create-user', 'register'
218
+ usage('olympe add-user [user] [--email EMAIL] [--passwd PASS]')
219
+ if @args.size == 1
220
+ set_cmd(:admin, :add_user, 1)
221
+ else
222
+ set_cmd(:admin, :add_user)
223
+ end
224
+
225
+ when 'delete-user', 'delete_user', 'unregister'
226
+ usage('olympe delete-user <user>')
227
+ set_cmd(:admin, :delete_user, 1)
228
+
229
+ when 'users'
230
+ usage('olympe users')
231
+ set_cmd(:admin, :users)
232
+
233
+ when 'apps'
234
+ usage('olympe apps')
235
+ set_cmd(:apps, :apps)
236
+
237
+ when 'list'
238
+ usage('olympe list')
239
+ set_cmd(:apps, :list)
240
+
241
+ when 'start'
242
+ usage('olympe start <appname>')
243
+ set_cmd(:apps, :start, @args.size == 1 ? 1 : 0)
244
+
245
+ when 'stop'
246
+ usage('olympe stop <appname>')
247
+ set_cmd(:apps, :stop, @args.size == 1 ? 1 : 0)
248
+
249
+ when 'restart'
250
+ usage('olympe restart <appname>')
251
+ set_cmd(:apps, :restart, @args.size == 1 ? 1 : 0)
252
+
253
+ when 'mem'
254
+ usage('olympe mem <appname> [memsize]')
255
+ if @args.size == 2
256
+ set_cmd(:apps, :mem, 2)
257
+ else
258
+ set_cmd(:apps, :mem, 1)
259
+ end
260
+
261
+ when 'stats'
262
+ usage('olympe stats <appname>')
263
+ set_cmd(:apps, :stats, @args.size == 1 ? 1 : 0)
264
+
265
+ when 'map'
266
+ usage('olympe map <appname> <url>')
267
+ set_cmd(:apps, :map, 2)
268
+
269
+ when 'unmap'
270
+ usage('olympe unmap <appname> <url>')
271
+ set_cmd(:apps, :unmap, 2)
272
+
273
+ when 'delete'
274
+ usage('olympe delete <appname>')
275
+ if @options[:all] && @args.size == 0
276
+ set_cmd(:apps, :delete)
277
+ else
278
+ set_cmd(:apps, :delete, 1)
279
+ end
280
+
281
+ when 'files'
282
+ usage('olympe files <appname> [path] [--instance N] [--all] [--prefix]')
283
+ if @args.size == 1
284
+ set_cmd(:apps, :files, 1)
285
+ else
286
+ set_cmd(:apps, :files, 2)
287
+ end
288
+
289
+ when 'download'
290
+ usage('olympe download <appname> [path]')
291
+ if @args.size == 1
292
+ set_cmd(:apps, :download, 1)
293
+ else
294
+ set_cmd(:apps, :download, 2)
295
+ end
296
+
297
+ when 'pull'
298
+ usage('olympe pull <appname> [path]')
299
+ if @args.size == 1
300
+ set_cmd(:apps, :pull, 1)
301
+ else
302
+ set_cmd(:apps, :pull, 2)
303
+ end
304
+
305
+ when 'logs'
306
+ usage('olympe logs <appname> [--instance N] [--all] [--prefix]')
307
+ set_cmd(:apps, :logs, 1)
308
+
309
+ when 'instances', 'scale'
310
+ if @args.size > 1
311
+ usage('olympe instances <appname> <num|delta>')
312
+ set_cmd(:apps, :instances, 2)
313
+ else
314
+ usage('olympe instances <appname>')
315
+ set_cmd(:apps, :instances, 1)
316
+ end
317
+
318
+ when 'crashes'
319
+ usage('olympe crashes <appname>')
320
+ set_cmd(:apps, :crashes, 1)
321
+
322
+ when 'crashlogs'
323
+ usage('olympe crashlogs <appname>')
324
+ set_cmd(:apps, :crashlogs, 1)
325
+
326
+ when 'push'
327
+ usage('olympe push [appname] [--path PATH] [--url URL] [--instances N] [--mem] [--runtime RUNTIME] [--no-start] [--infra infraname]')
328
+ if @args.size == 1
329
+ set_cmd(:apps, :push, 1)
330
+ else
331
+ set_cmd(:apps, :push, 0)
332
+ end
333
+
334
+ when 'update'
335
+ usage('olympe update <appname> [--path PATH]')
336
+ set_cmd(:apps, :update, @args.size == 1 ? 1 : 0)
337
+
338
+ when 'services'
339
+ usage('olympe services')
340
+ set_cmd(:services, :services)
341
+
342
+ when 'env'
343
+ usage('olympe env <appname>')
344
+ set_cmd(:apps, :environment, 1)
345
+
346
+ when 'env-add'
347
+ usage('olympe env-add <appname> <variable[=]value>')
348
+ if @args.size == 2
349
+ set_cmd(:apps, :environment_add, 2)
350
+ elsif @args.size == 3
351
+ set_cmd(:apps, :environment_add, 3)
352
+ end
353
+
354
+ when 'env-del'
355
+ usage('olympe env-del <appname> <variable>')
356
+ set_cmd(:apps, :environment_del, 2)
357
+
358
+ when 'create-service', 'create_service'
359
+ usage('olympe create-service [service] [servicename] [appname] [--name servicename] [--bind appname] [--infra infraname]')
360
+ set_cmd(:services, :create_service) if @args.size == 0
361
+ set_cmd(:services, :create_service, 1) if @args.size == 1
362
+ set_cmd(:services, :create_service, 2) if @args.size == 2
363
+ set_cmd(:services, :create_service, 3) if @args.size == 3
364
+
365
+ when 'delete-service', 'delete_service'
366
+ usage('olympe delete-service <service>')
367
+ if @args.size == 1
368
+ set_cmd(:services, :delete_service, 1)
369
+ else
370
+ set_cmd(:services, :delete_service)
371
+ end
372
+
373
+ when 'bind-service', 'bind_service'
374
+ usage('olympe bind-service <servicename> <appname>')
375
+ set_cmd(:services, :bind_service, 2)
376
+
377
+ when 'unbind-service', 'unbind_service'
378
+ usage('olympe unbind-service <servicename> <appname>')
379
+ set_cmd(:services, :unbind_service, 2)
380
+
381
+ when 'clone-services'
382
+ usage('olympe clone-services <src-app> <dest-app>')
383
+ set_cmd(:services, :clone_services, 2)
384
+
385
+ when 'export-service'
386
+ usage('olympe export-service <service-name>')
387
+ set_cmd(:services, :export_service, 1)
388
+
389
+ when 'import-service'
390
+ usage('olympe import-service <service-name> <url>')
391
+ set_cmd(:services, :import_service, 2)
392
+
393
+ when 'clone'
394
+ usage('olympe clone <src-app> <dest-app> [<infra>]')
395
+ set_cmd(:apps, :clone, 2) if @args.size == 2
396
+ set_cmd(:apps, :clone, 3) if @args.size == 3
397
+
398
+ when 'aliases'
399
+ usage('olympe aliases')
400
+ set_cmd(:misc, :aliases)
401
+
402
+ when 'alias'
403
+ usage('olympe alias <alias[=]command>')
404
+ if @args.size == 1
405
+ set_cmd(:misc, :alias, 1)
406
+ elsif @args.size == 2
407
+ set_cmd(:misc, :alias, 2)
408
+ end
409
+
410
+ when 'unalias'
411
+ usage('olympe unalias <alias>')
412
+ set_cmd(:misc, :unalias, 1)
413
+
414
+ when 'tunnel'
415
+ usage('olympe tunnel [servicename] [clientcmd] [--port port]')
416
+ set_cmd(:services, :tunnel, 0) if @args.size == 0
417
+ set_cmd(:services, :tunnel, 1) if @args.size == 1
418
+ set_cmd(:services, :tunnel, 2) if @args.size == 2
419
+
420
+ when 'rails-console'
421
+ usage('olympe rails-console <appname>')
422
+ set_cmd(:apps, :console, 1)
423
+
424
+ when 'micro'
425
+ usage('olympe micro <online|offline|status> [--password password] [--save] [--vmx file] [--vmrun executable]')
426
+ if %w[online offline status].include?(@args[0])
427
+ set_cmd(:micro, @args[0].to_sym, 1)
428
+ end
429
+
430
+ when 'help'
431
+ display_help if @args.size == 0
432
+ @help_only = true
433
+ parse_command!
434
+
435
+ when 'usage'
436
+ display basic_usage
437
+ exit(true)
438
+
439
+ when 'options'
440
+ # Simulate --options
441
+ @args = @args.unshift('--options')
442
+ parse_options!
443
+
444
+ when 'manifest'
445
+ usage('olympe manifest')
446
+ set_cmd(:manifest, :edit)
447
+
448
+ when 'extend-manifest'
449
+ usage('olympe extend-manifest')
450
+ set_cmd(:manifest, :extend, 1)
451
+
452
+ else
453
+ if verb
454
+ display "olympe: Unknown command [#{verb}]"
455
+ display basic_usage
456
+ exit(false)
457
+ end
458
+ end
459
+ end
460
+
461
+ def process_aliases!
462
+ return if @args.empty?
463
+ aliases = VMC::Cli::Config.aliases
464
+ aliases.each_pair do |k,v|
465
+ if @args[0] == k
466
+ display "[#{@args[0]} aliased to #{aliases.invert[key]}]" if @options[:verbose]
467
+ @args[0] = v
468
+ break;
469
+ end
470
+ end
471
+ end
472
+
473
+ def usage(msg = nil)
474
+ @usage = msg if msg
475
+ @usage
476
+ end
477
+
478
+ def usage_error(msg = nil)
479
+ @usage_error = msg if msg
480
+ @usage_error
481
+ end
482
+
483
+ def run
484
+
485
+ trap('TERM') { print "\nTerminated\n"; exit(false)}
486
+
487
+ parse_options!
488
+
489
+ @options[:colorize] = false unless STDOUT.tty?
490
+
491
+ VMC::Cli::Config.colorize = @options.delete(:colorize)
492
+ VMC::Cli::Config.nozip = @options.delete(:nozip)
493
+ VMC::Cli::Config.trace = @options.delete(:trace)
494
+ VMC::Cli::Config.output ||= STDOUT unless @options[:quiet]
495
+ VMC::Cli::Config.infra = @options[:infra]
496
+
497
+ process_aliases!
498
+ parse_command!
499
+
500
+ if @namespace && @action
501
+ cmd = VMC::Cli::Command.const_get(@namespace.to_s.capitalize)
502
+ cmd.new(@options).send(@action, *@args.collect(&:dup))
503
+ elsif @help_only || @usage
504
+ display_usage
505
+ else
506
+ display basic_usage
507
+ exit(false)
508
+ end
509
+
510
+ rescue OptionParser::InvalidOption => e
511
+ puts(e.message.red)
512
+ puts("\n")
513
+ puts(basic_usage)
514
+ @exit_status = false
515
+ rescue OptionParser::AmbiguousOption => e
516
+ puts(e.message.red)
517
+ puts("\n")
518
+ puts(basic_usage)
519
+ @exit_status = false
520
+ rescue VMC::Client::AuthError => e
521
+ if VMC::Cli::Config.auth_token.nil?
522
+ puts "Login Required".red
523
+ else
524
+ puts "Not Authorized".red
525
+ end
526
+ @exit_status = false
527
+ rescue VMC::Client::TargetError, VMC::Client::NotFound, VMC::Client::BadTarget => e
528
+ puts e.message.red
529
+ @exit_status = false
530
+ rescue VMC::Client::HTTPException => e
531
+ puts e.message.red
532
+ @exit_status = false
533
+ rescue VMC::Cli::GracefulExit => e
534
+ # Redirected commands end up generating this exception (kind of goto)
535
+ rescue VMC::Cli::CliExit => e
536
+ puts e.message.red
537
+ @exit_status = false
538
+ rescue VMC::Cli::CliError => e
539
+ say("Error #{e.error_code}: #{e.message}".red)
540
+ @exit_status = false
541
+ rescue SystemExit => e
542
+ @exit_status = e.success?
543
+ rescue SyntaxError => e
544
+ puts e.message.red
545
+ puts e.backtrace
546
+ @exit_status = false
547
+ rescue Interrupt => e
548
+ say("\nInterrupted".red)
549
+ @exit_status = false
550
+ rescue Exception => e
551
+ puts e.message.red
552
+ puts e.backtrace
553
+ @exit_status = false
554
+ ensure
555
+ say("\n")
556
+ @exit_status == true if @exit_status.nil?
557
+ if @options[:verbose]
558
+ if @exit_status
559
+ puts "[#{@namespace}:#{@action}] SUCCEEDED".green
560
+ else
561
+ puts "[#{@namespace}:#{@action}] FAILED".red
562
+ end
563
+ say("\n")
564
+ end
565
+ exit(@exit_status)
566
+ end
567
+
568
+ end
@@ -0,0 +1,104 @@
1
+
2
+ module VMC::Cli
3
+ module ServicesHelper
4
+ def display_system_services(services=nil)
5
+ services ||= client.services_info
6
+
7
+ display "\n============== System Services ==============\n\n"
8
+
9
+ return display "No system services available" if services.empty?
10
+
11
+ displayed_services = []
12
+ services.each do |service_type, value|
13
+ value.each do |vendor, version|
14
+ version.each do |version_str, service|
15
+ displayed_services << [ vendor, version_str, service[:description] ]
16
+ end
17
+ end
18
+ end
19
+ displayed_services.sort! { |a, b| a.first.to_s <=> b.first.to_s}
20
+
21
+ services_table = table do |t|
22
+ t.headings = 'Service', 'Version', 'Description'
23
+ displayed_services.each { |s| t << s }
24
+ end
25
+ display services_table
26
+ end
27
+
28
+ def display_provisioned_services(services=nil)
29
+ services ||= client.services
30
+ display "\n=========== Provisioned Services ============\n\n"
31
+ display_provisioned_services_table(services)
32
+ end
33
+
34
+ def display_provisioned_services_table(services)
35
+ return unless services && !services.empty?
36
+
37
+ infra_supported = !services.detect { |a| a[:infra] }.nil?
38
+ services_table = table do |t|
39
+ t.headings = 'Name', 'Service'
40
+ t.headings << 'In' if infra_supported
41
+ services.each do |service|
42
+ s = [ service[:name], service[:vendor] ]
43
+ if infra_supported
44
+ s << ( service[:infra] ? service[:infra][:provider] : " " )
45
+ end
46
+ t << s
47
+ end
48
+ end
49
+ display services_table
50
+ end
51
+
52
+ def create_service_banner(service, name, display_name=false, infra=nil)
53
+ sn = " [#{name}]" if display_name
54
+ display "Creating Service#{sn}: ", false
55
+ client.create_service(infra,service, name)
56
+ display 'OK'.green
57
+ end
58
+
59
+ def bind_service_banner(service, appname, check_restart=true)
60
+ display "Binding Service [#{service}]: ", false
61
+ client.bind_service(service, appname)
62
+ display 'OK'.green
63
+ check_app_for_restart(appname) if check_restart
64
+ end
65
+
66
+ def unbind_service_banner(service, appname, check_restart=true)
67
+ display "Unbinding Service [#{service}]: ", false
68
+ client.unbind_service(service, appname)
69
+ display 'OK'.green
70
+ check_app_for_restart(appname) if check_restart
71
+ end
72
+
73
+ def delete_service_banner(service)
74
+ display "Deleting service [#{service}]: ", false
75
+ client.delete_service(service)
76
+ display 'OK'.green
77
+ end
78
+
79
+ def random_service_name(service)
80
+ r = "%04x" % [rand(0x0100000)]
81
+ "#{service.to_s}-#{r}"
82
+ end
83
+
84
+ def generate_cloned_service_name(src_appname,dest_appname,src_servicename,dest_infra)
85
+ r = "%04x" % [rand(0x0100000)]
86
+ dest_servicename = src_servicename.sub(src_appname,dest_appname).sub(/-[0-9A-Fa-f]{4,5}/,"-#{r}")
87
+ if src_servicename == dest_servicename
88
+ if dest_infra
89
+ dest_servicename = "#{dest_servicename}-#{dest_infra}"
90
+ else
91
+ dest_servicename = "#{dest_servicename}-#{r}"
92
+ end
93
+ end
94
+ dest_servicename
95
+ end
96
+
97
+ def check_app_for_restart(appname)
98
+ app = client.app_info(appname)
99
+ cmd = VMC::Cli::Command::Apps.new(@options)
100
+ cmd.restart(appname) if app[:state] == 'STARTED'
101
+ end
102
+
103
+ end
104
+ end