sys 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/sys +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 +48 -0
  13. data/lib/cli/commands/admin.rb +80 -0
  14. data/lib/cli/commands/apps.rb +1208 -0
  15. data/lib/cli/commands/base.rb +233 -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 +140 -0
  19. data/lib/cli/commands/services.rb +217 -0
  20. data/lib/cli/commands/user.rb +65 -0
  21. data/lib/cli/config.rb +170 -0
  22. data/lib/cli/console_helper.rb +163 -0
  23. data/lib/cli/core_ext.rb +122 -0
  24. data/lib/cli/errors.rb +19 -0
  25. data/lib/cli/file_helper.rb +123 -0
  26. data/lib/cli/frameworks.rb +265 -0
  27. data/lib/cli/manifest_helper.rb +316 -0
  28. data/lib/cli/runner.rb +568 -0
  29. data/lib/cli/services_helper.rb +104 -0
  30. data/lib/cli/tunnel_helper.rb +336 -0
  31. data/lib/cli/usage.rb +125 -0
  32. data/lib/cli/version.rb +7 -0
  33. data/lib/cli/zip_util.rb +77 -0
  34. data/lib/vmc.rb +3 -0
  35. data/lib/vmc/client.rb +558 -0
  36. data/lib/vmc/const.rb +27 -0
  37. data/lib/vmc/micro.rb +56 -0
  38. data/lib/vmc/micro/switcher/base.rb +97 -0
  39. data/lib/vmc/micro/switcher/darwin.rb +19 -0
  40. data/lib/vmc/micro/switcher/dummy.rb +15 -0
  41. data/lib/vmc/micro/switcher/linux.rb +16 -0
  42. data/lib/vmc/micro/switcher/windows.rb +31 -0
  43. data/lib/vmc/micro/vmrun.rb +158 -0
  44. metadata +217 -0
@@ -0,0 +1,233 @@
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
+ client.infra = v['infra'] if v['infra']
61
+ abs = File.expand_path(k, file)
62
+ if Dir.pwd.start_with? abs
63
+ manifest = merge_manifest(manifest, v)
64
+ end
65
+ end
66
+ end
67
+
68
+ manifest
69
+ end
70
+
71
+ def resolve_manifest(manifest)
72
+ if apps = manifest["applications"]
73
+ apps.each_value do |v|
74
+ resolve_lexically(v, [manifest])
75
+ end
76
+ end
77
+
78
+ resolve_lexically(manifest, [manifest])
79
+ end
80
+
81
+ def load_manifest(file)
82
+ @manifest = load_manifest_structure(file)
83
+ resolve_manifest(@manifest)
84
+ end
85
+
86
+ def merge_parent(child, path)
87
+ file = File.expand_path("../" + path, manifest_file)
88
+ merge_manifest(child, load_manifest_structure(file))
89
+ end
90
+
91
+ def merge_manifest(child, parent)
92
+ merge = proc do |_, old, new|
93
+ if new.is_a?(Hash) and old.is_a?(Hash)
94
+ old.merge(new, &merge)
95
+ else
96
+ new
97
+ end
98
+ end
99
+
100
+ parent.merge(child, &merge)
101
+ end
102
+
103
+ def resolve_lexically(val, ctx = [@manifest])
104
+ case val
105
+ when Hash
106
+ val.each_value do |v|
107
+ resolve_lexically(v, [val] + ctx)
108
+ end
109
+ when Array
110
+ val.each do |v|
111
+ resolve_lexically(v, ctx)
112
+ end
113
+ when String
114
+ val.gsub!(/\$\{([[:alnum:]\-]+)\}/) do
115
+ resolve_symbol($1, ctx)
116
+ end
117
+ end
118
+
119
+ nil
120
+ end
121
+
122
+ def resolve_symbol(sym, ctx)
123
+ case sym
124
+ when "target-base"
125
+ target_base(ctx)
126
+
127
+ when "target-url"
128
+ target_url(ctx)
129
+
130
+ when "random-word"
131
+ "%04x" % [rand(0x0100000)]
132
+
133
+ else
134
+ found = find_symbol(sym, ctx)
135
+
136
+ if found
137
+ resolve_lexically(found, ctx)
138
+ found
139
+ else
140
+ err(sym, "Unknown symbol in manifest: ")
141
+ end
142
+ end
143
+ end
144
+
145
+ def find_symbol(sym, ctx)
146
+ ctx.each do |h|
147
+ if val = resolve_in(h, sym)
148
+ return val
149
+ end
150
+ end
151
+
152
+ nil
153
+ end
154
+
155
+ def resolve_in(hash, *where)
156
+ find_in_hash(hash, ["properties"] + where) ||
157
+ find_in_hash(hash, ["applications", @application] + where) ||
158
+ find_in_hash(hash, where)
159
+ end
160
+
161
+ def manifest(*where)
162
+ resolve_in(@manifest, *where)
163
+ end
164
+
165
+ def find_in_hash(hash, where)
166
+ what = hash
167
+ where.each do |x|
168
+ return nil unless what.is_a?(Hash)
169
+ what = what[x]
170
+ end
171
+
172
+ what
173
+ end
174
+
175
+ def target_url(ctx = [])
176
+ find_symbol("target", ctx) ||
177
+ (@client && @client.target) ||
178
+ VMC::Cli::Config.target_url
179
+ end
180
+
181
+ def target_base(ctx = [])
182
+ VMC::Cli::Config.base_of(find_symbol("target", ctx) || "api.#{client.suggest_url}")
183
+ end
184
+
185
+ # Inject a client to help in testing.
186
+ def client(cli=nil)
187
+ @client ||= cli
188
+ return @client if @client
189
+ @client = VMC::Client.new(target_url, auth_token)
190
+ @client.trace = VMC::Cli::Config.trace if VMC::Cli::Config.trace
191
+ @client.proxy_for @options[:proxy] if @options[:proxy]
192
+ @client
193
+ end
194
+
195
+ def client_info
196
+ @client_info ||= client.info
197
+ end
198
+
199
+ def auth_token
200
+ @auth_token = VMC::Cli::Config.auth_token(@options[:token_file])
201
+ end
202
+
203
+ def runtimes_info
204
+ return @runtimes if @runtimes
205
+ info = client_info
206
+ @runtimes = {}
207
+ if info[:frameworks]
208
+ info[:frameworks].each_value do |f|
209
+ next unless f[:runtimes]
210
+ f[:runtimes].each { |r| @runtimes[r[:name]] = r}
211
+ end
212
+ end
213
+ @runtimes
214
+ end
215
+
216
+ def frameworks_info
217
+ return @frameworks if @frameworks
218
+ info = client_info
219
+ @frameworks = []
220
+ if info[:frameworks]
221
+ info[:frameworks].each_value { |f| @frameworks << [f[:name]] }
222
+ end
223
+ @frameworks
224
+ end
225
+
226
+ def default_infra
227
+ "aws"
228
+ end
229
+
230
+ end
231
+ end
232
+ end
233
+
@@ -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,140 @@
1
+ module VMC::Cli::Command
2
+
3
+ class Misc < Base
4
+ def version
5
+ say "sys #{VMC::Cli::VERSION}"
6
+ end
7
+
8
+ def target
9
+ return display JSON.pretty_generate({:target => target_url}) if @options[:json]
10
+ banner "[#{target_url}]"
11
+ end
12
+
13
+ def targets
14
+ targets = VMC::Cli::Config.targets
15
+ return display JSON.pretty_generate(targets) if @options[:json]
16
+ return display 'None specified' if targets.empty?
17
+ targets_table = table do |t|
18
+ t.headings = 'Target', 'Authorization'
19
+ targets.each { |target, token| t << [target, token] }
20
+ end
21
+ display "\n"
22
+ display targets_table
23
+ end
24
+
25
+ alias :tokens :targets
26
+
27
+ def set_target(target_url)
28
+ target_url = "https://#{target_url}" unless /^https?/ =~ target_url
29
+ target_url = target_url.gsub(/\/+$/, '')
30
+ client = VMC::Client.new(target_url)
31
+ unless client.target_valid?
32
+ if prompt_ok
33
+ display "Host is not available or is not valid: '#{target_url}'".red
34
+ show_response = ask "Would you like see the response?",
35
+ :default => false
36
+ display "\n<<<\n#{client.raw_info}\n>>>\n" if show_response
37
+ end
38
+ exit(false)
39
+ else
40
+ VMC::Cli::Config.store_target(target_url)
41
+ say "Successfully targeted to [#{target_url}]".green
42
+ end
43
+ end
44
+
45
+ def info
46
+ info = client_info
47
+ return display JSON.pretty_generate(info) if @options[:json]
48
+
49
+ display "\n#{info[:description]}"
50
+ display "For support visit #{info[:support]}"
51
+ display ""
52
+ display "Target: #{target_url} (v#{info[:version]})"
53
+ display "Client: v#{VMC::Cli::VERSION}"
54
+ if info[:user]
55
+ display ''
56
+ display "User: #{info[:user]}"
57
+ end
58
+ if usage = info[:usage] and limits = info[:limits]
59
+ tmem = pretty_size(limits[:memory]*1024*1024)
60
+ mem = pretty_size(usage[:memory]*1024*1024)
61
+ tser = limits[:services]
62
+ ser = usage[:services]
63
+ tapps = limits[:apps] || 0
64
+ apps = usage[:apps] || 0
65
+ display "Usage: Memory (#{mem} of #{tmem} total)"
66
+ display " Services (#{ser} of #{tser} total)"
67
+ display " Apps (#{apps} of #{tapps} total)" if limits[:apps]
68
+ end
69
+ end
70
+
71
+ def runtimes
72
+ raise VMC::Client::AuthError unless client.logged_in?
73
+ return display JSON.pretty_generate(runtimes_info) if @options[:json]
74
+ return display "No Runtimes" if runtimes_info.empty?
75
+ rtable = table do |t|
76
+ t.headings = 'Name', 'Description', 'Version'
77
+ runtimes_info.each_value { |rt| t << [rt[:name], rt[:description], rt[:version]] }
78
+ end
79
+ display "\n"
80
+ display rtable
81
+ end
82
+
83
+ def infras
84
+ infras_info = client.infras
85
+ return display "Multiple infras not supported" if infras_info.empty?
86
+ itable = table do |t|
87
+ t.headings = [ 'Name','Description' ]
88
+ infras_info.each { |i| t << [i[:infra], i[:description]] }
89
+ end
90
+ display "\n"
91
+ display itable
92
+ end
93
+
94
+ def frameworks
95
+ raise VMC::Client::AuthError unless client.logged_in?
96
+ return display JSON.pretty_generate(frameworks_info) if @options[:json]
97
+ return display "No Frameworks" if frameworks_info.empty?
98
+ rtable = table do |t|
99
+ t.headings = ['Name']
100
+ frameworks_info.each { |f| t << f }
101
+ end
102
+ display "\n"
103
+ display rtable
104
+ end
105
+
106
+ def aliases
107
+ aliases = VMC::Cli::Config.aliases
108
+ return display JSON.pretty_generate(aliases) if @options[:json]
109
+ return display "No Aliases" if aliases.empty?
110
+ atable = table do |t|
111
+ t.headings = 'Alias', 'Command'
112
+ aliases.each { |k,v| t << [k, v] }
113
+ end
114
+ display "\n"
115
+ display atable
116
+ end
117
+
118
+ def alias(k, v=nil)
119
+ k,v = k.split('=') unless v
120
+ aliases = VMC::Cli::Config.aliases
121
+ aliases[k] = v
122
+ VMC::Cli::Config.store_aliases(aliases)
123
+ display "Successfully aliased '#{k}' to '#{v}'".green
124
+ end
125
+
126
+ def unalias(key)
127
+ aliases = VMC::Cli::Config.aliases
128
+ if aliases.has_key?(key)
129
+ aliases.delete(key)
130
+ VMC::Cli::Config.store_aliases(aliases)
131
+ display "Successfully unaliased '#{key}'".green
132
+ else
133
+ display "Unknown alias '#{key}'".red
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+