vmcu 0.3.17

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.
Files changed (43) hide show
  1. data/LICENSE +24 -0
  2. data/README.md +160 -0
  3. data/Rakefile +101 -0
  4. data/bin/vmcu +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.rb +47 -0
  13. data/lib/cli/commands/admin.rb +80 -0
  14. data/lib/cli/commands/apps.rb +1128 -0
  15. data/lib/cli/commands/base.rb +238 -0
  16. data/lib/cli/commands/manifest.rb +56 -0
  17. data/lib/cli/commands/micro.rb +115 -0
  18. data/lib/cli/commands/misc.rb +277 -0
  19. data/lib/cli/commands/services.rb +180 -0
  20. data/lib/cli/commands/user.rb +96 -0
  21. data/lib/cli/config.rb +192 -0
  22. data/lib/cli/console_helper.rb +157 -0
  23. data/lib/cli/core_ext.rb +122 -0
  24. data/lib/cli/errors.rb +19 -0
  25. data/lib/cli/frameworks.rb +244 -0
  26. data/lib/cli/manifest_helper.rb +302 -0
  27. data/lib/cli/runner.rb +543 -0
  28. data/lib/cli/services_helper.rb +84 -0
  29. data/lib/cli/tunnel_helper.rb +332 -0
  30. data/lib/cli/usage.rb +118 -0
  31. data/lib/cli/version.rb +7 -0
  32. data/lib/cli/zip_util.rb +77 -0
  33. data/lib/vmc.rb +3 -0
  34. data/lib/vmc/client.rb +591 -0
  35. data/lib/vmc/const.rb +22 -0
  36. data/lib/vmc/micro.rb +56 -0
  37. data/lib/vmc/micro/switcher/base.rb +97 -0
  38. data/lib/vmc/micro/switcher/darwin.rb +19 -0
  39. data/lib/vmc/micro/switcher/dummy.rb +15 -0
  40. data/lib/vmc/micro/switcher/linux.rb +16 -0
  41. data/lib/vmc/micro/switcher/windows.rb +31 -0
  42. data/lib/vmc/micro/vmrun.rb +158 -0
  43. metadata +263 -0
@@ -0,0 +1,238 @@
1
+ require 'rubygems'
2
+ require 'interact'
3
+ require 'terminal-table/import'
4
+
5
+ module VMC::Cli
6
+
7
+ module Command
8
+
9
+ class Base
10
+ include Interactive
11
+
12
+ attr_reader :no_prompt, :prompt_ok
13
+
14
+ MANIFEST = "manifest.yml"
15
+
16
+ def initialize(options={})
17
+ @options = options.dup
18
+ @no_prompt = @options[:noprompts]
19
+ @prompt_ok = !no_prompt
20
+
21
+ # Suppress colorize on Windows systems for now.
22
+ if WINDOWS
23
+ VMC::Cli::Config.colorize = false
24
+ end
25
+
26
+ @path = @options[:path] || '.'
27
+
28
+ load_manifest manifest_file if manifest_file
29
+ end
30
+
31
+ def manifest_file
32
+ return @options[:manifest] if @options[:manifest]
33
+ return @manifest_file if @manifest_file
34
+
35
+ where = File.expand_path(@path)
36
+ while true
37
+ if File.exists?(File.join(where, MANIFEST))
38
+ @manifest_file = File.join(where, MANIFEST)
39
+ break
40
+ elsif File.basename(where) == "/"
41
+ @manifest_file = nil
42
+ break
43
+ else
44
+ where = File.expand_path("../", where)
45
+ end
46
+ end
47
+
48
+ @manifest_file
49
+ end
50
+
51
+ def load_manifest_structure(file)
52
+ manifest = YAML.load_file file
53
+
54
+ Array(manifest["inherit"]).each do |p|
55
+ manifest = merge_parent(manifest, p)
56
+ end
57
+
58
+ if apps = manifest["applications"]
59
+ apps.each do |k, v|
60
+ abs = File.expand_path(k, file)
61
+ if Dir.pwd.start_with? abs
62
+ manifest = merge_manifest(manifest, v)
63
+ end
64
+ end
65
+ end
66
+
67
+ manifest
68
+ end
69
+
70
+ def resolve_manifest(manifest)
71
+ if apps = manifest["applications"]
72
+ apps.each_value do |v|
73
+ resolve_lexically(v, [manifest])
74
+ end
75
+ end
76
+
77
+ resolve_lexically(manifest, [manifest])
78
+ end
79
+
80
+ def load_manifest(file)
81
+ @manifest = load_manifest_structure(file)
82
+ resolve_manifest(@manifest)
83
+ end
84
+
85
+ def merge_parent(child, path)
86
+ file = File.expand_path("../" + path, manifest_file)
87
+ merge_manifest(child, load_manifest_structure(file))
88
+ end
89
+
90
+ def merge_manifest(child, parent)
91
+ merge = proc do |_, old, new|
92
+ if new.is_a?(Hash) and old.is_a?(Hash)
93
+ old.merge(new, &merge)
94
+ else
95
+ new
96
+ end
97
+ end
98
+
99
+ parent.merge(child, &merge)
100
+ end
101
+
102
+ def resolve_lexically(val, ctx = [@manifest])
103
+ case val
104
+ when Hash
105
+ val.each_value do |v|
106
+ resolve_lexically(v, [val] + ctx)
107
+ end
108
+ when Array
109
+ val.each do |v|
110
+ resolve_lexically(v, ctx)
111
+ end
112
+ when String
113
+ val.gsub!(/\$\{([[:alnum:]\-]+)\}/) do
114
+ resolve_symbol($1, ctx)
115
+ end
116
+ end
117
+
118
+ nil
119
+ end
120
+
121
+ def resolve_symbol(sym, ctx)
122
+ case sym
123
+ when "target-base"
124
+ target_base(ctx)
125
+
126
+ when "target-url"
127
+ target_url(ctx)
128
+
129
+ when "random-word"
130
+ "%04x" % [rand(0x0100000)]
131
+
132
+ else
133
+ found = find_symbol(sym, ctx)
134
+
135
+ if found
136
+ resolve_lexically(found, ctx)
137
+ found
138
+ else
139
+ err(sym, "Unknown symbol in manifest: ")
140
+ end
141
+ end
142
+ end
143
+
144
+ def find_symbol(sym, ctx)
145
+ ctx.each do |h|
146
+ if val = resolve_in(h, sym)
147
+ return val
148
+ end
149
+ end
150
+
151
+ nil
152
+ end
153
+
154
+ def resolve_in(hash, *where)
155
+ find_in_hash(hash, ["properties"] + where) ||
156
+ find_in_hash(hash, ["applications", @application] + where) ||
157
+ find_in_hash(hash, where)
158
+ end
159
+
160
+ def manifest(*where)
161
+ resolve_in(@manifest, *where)
162
+ end
163
+
164
+ def find_in_hash(hash, where)
165
+ what = hash
166
+ where.each do |x|
167
+ return nil unless what.is_a?(Hash)
168
+ what = what[x]
169
+ end
170
+
171
+ what
172
+ end
173
+
174
+ def target_url(ctx = [])
175
+ find_symbol("target", ctx) ||
176
+ (@client && @client.target) ||
177
+ VMC::Cli::Config.target_url
178
+ end
179
+
180
+ def target_base(ctx = [])
181
+ if VMC::Cli::Config.uhuru_target
182
+ (VMC::Cli::Config.uhuru_target[:cloud_domain] || target_url).sub(/\A[^\/]*\/\//, "").sub(/\/.*\z/, "")
183
+ else
184
+ VMC::Cli::Config.base_of(find_symbol("target", ctx) || target_url)
185
+ end
186
+ end
187
+
188
+ # Inject a client to help in testing.
189
+ def client(cli=nil)
190
+ @client ||= cli
191
+ return @client if @client
192
+ if VMC::Cli::Config.uhuru_target
193
+ uhuru_target = VMC::Cli::Config.uhuru_target
194
+ @client = VMC::Client.new(target_url, uhuru_target[:token])
195
+ @client.via_uhuru_cloud = true
196
+ @client.cloud_team = uhuru_target[:cloud_team]
197
+ @client.proxy_realm = uhuru_target[:realm] if uhuru_target[:realm]
198
+ else
199
+ @client = VMC::Client.new(target_url, auth_token)
200
+ end
201
+ @client.trace = VMC::Cli::Config.trace if VMC::Cli::Config.trace
202
+ @client.proxy_for @options[:proxy] if @options[:proxy]
203
+ @client
204
+ end
205
+
206
+ def client_info
207
+ @client_info ||= client.info
208
+ end
209
+
210
+ def auth_token
211
+ @auth_token = VMC::Cli::Config.auth_token(@options[:token_file])
212
+ end
213
+
214
+ def runtimes_info
215
+ return @runtimes if @runtimes
216
+ info = client_info
217
+ @runtimes = {}
218
+ if info[:frameworks]
219
+ info[:frameworks].each_value do |f|
220
+ next unless f[:runtimes]
221
+ f[:runtimes].each { |r| @runtimes[r[:name]] = r}
222
+ end
223
+ end
224
+ @runtimes
225
+ end
226
+
227
+ def frameworks_info
228
+ return @frameworks if @frameworks
229
+ info = client_info
230
+ @frameworks = []
231
+ if info[:frameworks]
232
+ info[:frameworks].each_value { |f| @frameworks << [f[:name]] }
233
+ end
234
+ @frameworks
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,56 @@
1
+ module VMC::Cli::Command
2
+ class Manifest < Base
3
+ include VMC::Cli::ManifestHelper
4
+
5
+ def initialize(options)
6
+ super
7
+
8
+ # don't resolve any of the manifest template stuff
9
+ if manifest_file
10
+ @manifest = load_manifest_structure manifest_file
11
+ else
12
+ @manifest = {}
13
+ end
14
+ end
15
+
16
+ def edit
17
+ build_manifest
18
+ save_manifest
19
+ end
20
+
21
+ def extend(which)
22
+ parent = load_manifest_structure which
23
+ @manifest = load_manifest_structure which
24
+
25
+ build_manifest
26
+
27
+ simplify(@manifest, parent)
28
+
29
+ @manifest["inherit"] ||= []
30
+ @manifest["inherit"] << which
31
+
32
+ save_manifest(ask("Save where?"))
33
+ end
34
+
35
+ private
36
+
37
+ def simplify(child, parent)
38
+ return unless child.is_a?(Hash) and parent.is_a?(Hash)
39
+
40
+ child.reject! do |k, v|
41
+ if v == parent[k]
42
+ puts "rejecting #{k}"
43
+ true
44
+ else
45
+ simplify(v, parent[k])
46
+ false
47
+ end
48
+ end
49
+ end
50
+
51
+ def build_manifest
52
+ @application = ask("Configure for which application?", :default => ".")
53
+ interact true
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,115 @@
1
+ module VMC::Cli::Command
2
+ class Micro < Base
3
+
4
+ def initialize(args)
5
+ super(args)
6
+ end
7
+
8
+ def offline(mode)
9
+ command('offline')
10
+ end
11
+
12
+ def online(mode)
13
+ command('online')
14
+ end
15
+
16
+ def status(mode)
17
+ command('status')
18
+ end
19
+
20
+ def command(cmd)
21
+ config = build_config
22
+ switcher(config).send(cmd)
23
+ store_config(config)
24
+ end
25
+
26
+ def switcher(config)
27
+ case Micro.platform
28
+ when :darwin
29
+ switcher = VMC::Micro::Switcher::Darwin.new(config)
30
+ when :linux
31
+ switcher = VMC::Micro::Switcher::Linux.new(config)
32
+ when :windows
33
+ switcher = VMC::Micro::Switcher::Windows.new(config)
34
+ when :dummy # for testing only
35
+ switcher = VMC::Micro::Switcher::Dummy.new(config)
36
+ else
37
+ err "unsupported platform: #{Micro.platform}"
38
+ end
39
+ end
40
+
41
+ # Returns the configuration needed to run the micro related subcommands.
42
+ # First loads saved config from file (if there is any), then overrides
43
+ # loaded values with command line arguments, and finally tries to guess
44
+ # in case neither was used:
45
+ # vmx location of micro.vmx file
46
+ # vmrun location of vmrun command
47
+ # password password for vcap user (in the guest vm)
48
+ # platform current platform
49
+ def build_config
50
+ conf = VMC::Cli::Config.micro # returns {} if there isn't a saved config
51
+
52
+ override(conf, 'vmx', true) do
53
+ locate_vmx(Micro.platform)
54
+ end
55
+
56
+ override(conf, 'vmrun', true) do
57
+ VMC::Micro::VMrun.locate(Micro.platform)
58
+ end
59
+
60
+ override(conf, 'password') do
61
+ @password = ask("Please enter your Micro Cloud Foundry VM password (vcap user) password", :echo => "*")
62
+ end
63
+
64
+ conf['platform'] = Micro.platform
65
+
66
+ conf
67
+ end
68
+
69
+ # Save the cleartext password if --save is supplied.
70
+ # Note: it is due to vix we have to use a cleartext password :(
71
+ # Only if --password is used and not --save is the password deleted from the
72
+ # config file before it is stored to disk.
73
+ def store_config(config)
74
+ if @options[:save]
75
+ warn("cleartext password saved in: #{VMC::Cli::Config::MICRO_FILE}")
76
+ elsif @options[:password] || @password
77
+ config.delete('password')
78
+ end
79
+
80
+ VMC::Cli::Config.store_micro(config)
81
+ end
82
+
83
+ # override with command line arguments and yield the block in case the option isn't set
84
+ def override(config, option, escape=false, &blk)
85
+ # override if given on the command line
86
+ if opt = @options[option.to_sym]
87
+ opt = VMC::Micro.escape_path(opt) if escape
88
+ config[option] = opt
89
+ end
90
+ config[option] = yield unless config[option]
91
+ end
92
+
93
+ def locate_vmx(platform)
94
+ paths = YAML.load_file(VMC::Micro.config_file('paths.yml'))
95
+ vmx_paths = paths[platform.to_s]['vmx']
96
+ vmx = VMC::Micro.locate_file('micro.vmx', 'micro', vmx_paths)
97
+ err "Unable to locate micro.vmx, please supply --vmx option" unless vmx
98
+ vmx
99
+ end
100
+
101
+ def self.platform
102
+ case RUBY_PLATFORM
103
+ when /darwin/ # x86_64-darwin11.2.0
104
+ :darwin
105
+ when /linux/ # x86_64-linux
106
+ :linux
107
+ when /mingw|mswin32|cygwin/ # i386-mingw32
108
+ :windows
109
+ else
110
+ RUBY_PLATFORM
111
+ end
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,277 @@
1
+ module VMC::Cli::Command
2
+
3
+ class Misc < Base
4
+ def version
5
+ say "vmcu #{VMC::Cli::VERSION}"
6
+ end
7
+
8
+ def target
9
+ return uhuru_target if VMC::Cli::Config.uhuru_target
10
+ return display JSON.pretty_generate({:target => target_url}) if @options[:json]
11
+ banner "[#{target_url}]"
12
+ end
13
+
14
+ def targets
15
+ targets = VMC::Cli::Config.targets
16
+ return display JSON.pretty_generate(targets) if @options[:json]
17
+ return display 'None specified' if targets.empty?
18
+ targets_table = table do |t|
19
+ t.headings = 'Target', 'Authorization'
20
+ targets.each { |target, token| t << [target, token] }
21
+ end
22
+ display "\n"
23
+ display targets_table
24
+ end
25
+
26
+ alias :tokens :targets
27
+
28
+ def set_target(target_url)
29
+ target_url = "http://#{target_url}" unless /^https?/ =~ target_url
30
+ target_url = target_url.gsub(/\/+$/, '')
31
+
32
+ uhuru_targets = VMC::Cli::Config.all_uhuru_targets || {}
33
+
34
+ client = VMC::Client.new(target_url)
35
+ client.trace = VMC::Cli::Config.trace if VMC::Cli::Config.trace
36
+
37
+ unless client.target_valid?
38
+ unless client.uhuru_target_valid?
39
+ if prompt_ok
40
+ display "Host is not available or is not valid: '#{target_url}'".red
41
+ show_response = ask "Would you like see the response?",
42
+ :default => false
43
+ display "\n<<<\n#{client.raw_info}\n>>>\n" if show_response
44
+ end
45
+ exit(false)
46
+ else
47
+ VMC::Cli::Config.store_target(target_url)
48
+
49
+ new_uhuru_target = uhuru_targets[target_url.to_sym] || {}
50
+ VMC::Cli::Config.store_uhuru_target(
51
+ target_url,
52
+ new_uhuru_target
53
+ )
54
+ say "Successfully targeted to Uhuru App Cloud [#{target_url}]".green
55
+
56
+ end
57
+ else
58
+ VMC::Cli::Config.store_target(target_url)
59
+ say "Successfully targeted to [#{target_url}]".green
60
+ end
61
+ end
62
+
63
+ def set_cloud_team(cloud_team = nil)
64
+ err "Must be targeted to a Uhuru App Cloud to use cloud teams" unless client.via_uhuru_cloud
65
+
66
+ client.proxy_realm = @options[:realm]
67
+
68
+ detailed_cloud_teams = nil
69
+ unless no_prompt || cloud_team
70
+
71
+ err "No cloud team found for your UhuruApp account" if (detailed_cloud_teams ||= client.get_detailed_cloud_teams).length == 0
72
+
73
+ detailed_cloud_teams.each{|cloud_team|
74
+ cloud_team[:CloudEntity] ||= client.get_cloud_entity((cloud_team[:Cloud] || cloud_team[:CloudTeamCloud])[:Id])
75
+ }
76
+
77
+ cloud_team_chosen = ask(
78
+ "\nWhich cloud team would you like to target to?",
79
+ { :indexed => true,
80
+ #:choices => (detailed_cloud_teams ||= client.get_detailed_cloud_teams).collect { |cloud_team| {:Name => cloud_team[:Name], :Id => cloud_team[:Id]}}
81
+ :choices => (detailed_cloud_teams ||= client.get_detailed_cloud_teams).collect { |cloud_team|
82
+ "#{cloud_team[:Name]} \t[Cloud: #{cloud_team[:CloudEntity][:Name]}] \t[Cloud Team Id: #{cloud_team[:Id]}]"
83
+ }
84
+ }
85
+ )
86
+
87
+ cloud_team_desc = detailed_cloud_teams.select{|i| cloud_team_chosen.index i[:Id]}.first
88
+ cloud_team_id = cloud_team = cloud_team_desc[:Id]
89
+ end
90
+ err "Cloud team Id or Name required." unless cloud_team
91
+
92
+ # if it matches a GUID format
93
+ unless cloud_team =~ /\A\{?\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\}?\z/
94
+ found_cloud_team = (detailed_cloud_teams ||= client.get_detailed_cloud_teams).select { |i|
95
+ i[:Name] == cloud_team
96
+ }
97
+
98
+ err "Could not find a cloud team with name \"#{cloud_team}\"" if found_cloud_team.length == 0
99
+ cloud_team_desc = found_cloud_team.first
100
+ cloud_team_id = cloud_team_desc[:Id]
101
+ else
102
+ cloud_team_id = cloud_team
103
+ end
104
+
105
+ client.cloud_team = cloud_team_id
106
+ cloud_team_desc ||= client.get_cloud_team(cloud_team_id)
107
+ cloud_team_desc[:CloudEntity] ||= client.get_cloud_entity((cloud_team_desc[:Cloud] || cloud_team_desc[:CloudTeamCloud])[:Id])
108
+
109
+ new_uhuru_target = VMC::Cli::Config.all_uhuru_targets[target_url.to_sym] || {}
110
+ new_uhuru_target[:cloud_team] = cloud_team_id
111
+ new_uhuru_target[:cloud_domain] = cloud_team_desc[:CloudEntity][:Domain]
112
+ new_uhuru_target[:realm] = @options[:realm]
113
+ VMC::Cli::Config.store_uhuru_target(
114
+ target_url,
115
+ new_uhuru_target
116
+ )
117
+
118
+
119
+ display "\nTargeted to UhuruApp Cloud:\t[#{target_url}]\n Cloud Team:\t\t\t[#{cloud_team_desc[:Name]}]\n Cloud Team Id:\t\t\t[#{new_uhuru_target[:cloud_team]}]\n Cloud Foundry domain:\t\t[#{new_uhuru_target[:cloud_domain]}]"
120
+
121
+ end
122
+
123
+ def import_from_registry
124
+ require 'win32/registry'
125
+ keyname = 'Software\Uhuru\CloudTargets'
126
+ access = Win32::Registry::KEY_READ
127
+ reg_targets = []
128
+
129
+ Win32::Registry::HKEY_CURRENT_USER.open(keyname, access) do |reg|
130
+ reg.each{|k|
131
+ t = reg[k]
132
+ if t[0] == 'isUhuruApi'
133
+ reg_targets << {:uhuruApi => true,
134
+ :target_url => t[2],
135
+ :auth_token => t[3],
136
+ :cloud_team => t[4],
137
+ # todo: get the cloud_domain
138
+ :cloud_domain => t[6],
139
+ :desc => "Uhuru AppCloud [#{t[2]}] / #{t[5]}"
140
+ }
141
+ end
142
+ if t[0] == 'notUhuruApi'
143
+ reg_targets << {:uhuruApi => false,
144
+ :target_url => t[2],
145
+ :auth_token => t[4],
146
+ :desc => "Cloud Foundry [#{t[2]}] / #{t[3]}"
147
+ }
148
+ end
149
+
150
+ }
151
+ end
152
+
153
+ selected_target_desc = ask(
154
+ "Which target to import?",
155
+ {
156
+ :indexed => true,
157
+ :choices => reg_targets.collect{|t| "#{t[:desc]}" }
158
+ }
159
+ )
160
+
161
+ selected_target = reg_targets.select{|t| selected_target_desc.index(t[:desc]) }.first
162
+
163
+ if selected_target[:uhuruApi]
164
+ VMC::Cli::Config.store_uhuru_target(
165
+ selected_target[:target_url],
166
+ {
167
+ :token => selected_target[:auth_token],
168
+ :cloud_team => selected_target[:cloud_team],
169
+ :cloud_domain => selected_target[:cloud_domain]
170
+ }
171
+ )
172
+
173
+ VMC::Cli::Config.store_target(selected_target[:target_url])
174
+ else
175
+ VMC::Cli::Config.store_target(selected_target[:target_url])
176
+ VMC::Cli::Config.store_uhuru_target(
177
+ selected_target[:target_url],
178
+ nil
179
+ )
180
+ VMC::Cli::Config.store_token(selected_target[:auth_token], @options[:token_file])
181
+ end
182
+
183
+ display "Targeted to #{selected_target[:desc]}"
184
+ end
185
+
186
+ def uhuru_target
187
+ return display JSON.pretty_generate(VMC::Cli::Config.uhuru_target) if @options[:json]
188
+ banner "Uhuru AppCloud [#{VMC::Cli::Config.target_url}]"
189
+ end
190
+
191
+ def info
192
+ display "\nUsing Uhuru AppCloud [#{VMC::Cli::Config.target_url}]" if VMC::Cli::Config.uhuru_target
193
+
194
+ info = client_info
195
+ return display JSON.pretty_generate(info) if @options[:json]
196
+
197
+ display "\n#{info[:description]}"
198
+ display "For support visit #{info[:support]}"
199
+ display ""
200
+ display "Target: #{target_url} (v#{info[:version]})"
201
+ display "Client: v#{VMC::Cli::VERSION}"
202
+ if info[:user]
203
+ display ''
204
+ display "User: #{info[:user]}"
205
+ end
206
+ if usage = info[:usage] and limits = info[:limits]
207
+ tmem = pretty_size(limits[:memory]*1024*1024)
208
+ mem = pretty_size(usage[:memory]*1024*1024)
209
+ tser = limits[:services]
210
+ ser = usage[:services]
211
+ tapps = limits[:apps] || 0
212
+ apps = usage[:apps] || 0
213
+ display "Usage: Memory (#{mem} of #{tmem} total)"
214
+ display " Services (#{ser} of #{tser} total)"
215
+ display " Apps (#{apps} of #{tapps} total)" if limits[:apps]
216
+ end
217
+ end
218
+
219
+ def runtimes
220
+ raise VMC::Client::AuthError unless client.logged_in?
221
+ return display JSON.pretty_generate(runtimes_info) if @options[:json]
222
+ return display "No Runtimes" if runtimes_info.empty?
223
+ rtable = table do |t|
224
+ t.headings = 'Name', 'Description', 'Version'
225
+ runtimes_info.each_value { |rt| t << [rt[:name], rt[:description], rt[:version]] }
226
+ end
227
+ display "\n"
228
+ display rtable
229
+ end
230
+
231
+ def frameworks
232
+ raise VMC::Client::AuthError unless client.logged_in?
233
+ return display JSON.pretty_generate(frameworks_info) if @options[:json]
234
+ return display "No Frameworks" if frameworks_info.empty?
235
+ rtable = table do |t|
236
+ t.headings = ['Name']
237
+ frameworks_info.each { |f| t << f }
238
+ end
239
+ display "\n"
240
+ display rtable
241
+ end
242
+
243
+ def aliases
244
+ aliases = VMC::Cli::Config.aliases
245
+ return display JSON.pretty_generate(aliases) if @options[:json]
246
+ return display "No Aliases" if aliases.empty?
247
+ atable = table do |t|
248
+ t.headings = 'Alias', 'Command'
249
+ aliases.each { |k,v| t << [k, v] }
250
+ end
251
+ display "\n"
252
+ display atable
253
+ end
254
+
255
+ def alias(k, v=nil)
256
+ k,v = k.split('=') unless v
257
+ aliases = VMC::Cli::Config.aliases
258
+ aliases[k] = v
259
+ VMC::Cli::Config.store_aliases(aliases)
260
+ display "Successfully aliased '#{k}' to '#{v}'".green
261
+ end
262
+
263
+ def unalias(key)
264
+ aliases = VMC::Cli::Config.aliases
265
+ if aliases.has_key?(key)
266
+ aliases.delete(key)
267
+ VMC::Cli::Config.store_aliases(aliases)
268
+ display "Successfully unaliased '#{key}'".green
269
+ else
270
+ display "Unknown alias '#{key}'".red
271
+ end
272
+ end
273
+
274
+ end
275
+
276
+ end
277
+