openshift 0.60.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2010 Red Hat, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person
5
+ # obtaining a copy of this software and associated documentation files
6
+ # (the "Software"), to deal in the Software without restriction,
7
+ # including without limitation the rights to use, copy, modify, merge,
8
+ # publish, distribute, sublicense, and/or sell copies of the Software,
9
+ # and to permit persons to whom the Software is furnished to do so,
10
+ # subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
+ # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
+ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'openshift'
25
+
26
+ def usage
27
+ puts <<USAGE
28
+ == Synopsis
29
+
30
+ os-tail-logs: Tail or download log files from an environment
31
+
32
+ == Usage
33
+
34
+ os tail-logs [options] [NAME]
35
+
36
+ -u|--username
37
+ Redhat Login (RHN or OpenShift login with OpenShift Express access)
38
+
39
+ -p|--password
40
+ Redhat Password
41
+
42
+ -t|--target flex|express
43
+ The cloud platform the environment is running on.
44
+
45
+ -h|--help
46
+ Prints this message
47
+
48
+ NAME: The name or GUID of the environment to get logs from.
49
+ USAGE
50
+ end
51
+
52
+ opts = GetoptLong.new(
53
+ ["--username", "-u", GetoptLong::REQUIRED_ARGUMENT],
54
+ ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
55
+ ["--sso", GetoptLong::REQUIRED_ARGUMENT],
56
+ ["--debug", GetoptLong::NO_ARGUMENT],
57
+ ["--help", GetoptLong::NO_ARGUMENT],
58
+ ["--porcelin", GetoptLong::NO_ARGUMENT]
59
+ )
60
+
61
+ args = {}
62
+ begin
63
+ opts.each{ |k,v| args[k]=v }
64
+ rescue GetoptLong::Error => e
65
+ usage
66
+ exit -100
67
+ end
68
+
69
+ @debug = true if args['--debug']
70
+ args['--target'] = conf('default_target') || 'flex' if args['--target'].nil? or args['--target']==""
71
+ debug "Target platform #{args['--target']}"
72
+
73
+ if args['--help']
74
+ usage
75
+ exit
76
+ end
77
+
78
+ if args['--target'] == 'flex'
79
+ flex_server = conf('flex_server')
80
+ cookie = args['--sso']
81
+ if !cookie
82
+ username = args['--username'] || conf("username") || Openshift::IO.prompt("Redhat username",[],Openshift::Validation.method(:check_login))
83
+ password = args['--password'] || Openshift::IO.prompt("Redhat password",nil,nil,true,false)
84
+ csay("Logging into Openshift Flex as #{username}\n",:message)
85
+ cookie=Openshift.login(@http,username,password)
86
+ end
87
+
88
+ environment_id = ARGV.shift
89
+ debug "Tailing environment: #{environment_id}"
90
+ if not environment_id
91
+ csay("No environment specified.",:error)
92
+ exit
93
+ end
94
+
95
+ csay("Fetching environment list... ")
96
+ environments=nil
97
+ begin
98
+ environments=`os-list-environments --sso "#{cookie}" --porcelin`
99
+ environments = JSON.parse(environments)
100
+ csay("[OK]",:conf)
101
+ rescue Exception => e
102
+ debug environments
103
+ debug e
104
+ csay("[ERROR]",:error)
105
+ csay("Error retrieving environment list.")
106
+ exit -400
107
+ end
108
+ candidates = environments.find_all{ |c| c["name"]==environment_id or c["id"]==environment_id }
109
+
110
+ if candidates.size == 0
111
+ csay("Unable to find environment identified by #{environment_id}",:error)
112
+ exit -200
113
+ end
114
+
115
+ if candidates.size > 1
116
+ csay("Multiple environments are named #{environment_id}. Please provide the environment Id",:error)
117
+ exit -201
118
+ end
119
+
120
+ environment = candidates[0]
121
+ csay("Tailing logs for environment ")
122
+ csay("#{environment["name"]} ",:emphasis)
123
+ csay("...")
124
+ lastEntry = nil
125
+ params = nil
126
+ while(true)
127
+ params = { "start-time" => lastEntry['timestamp'].to_i, "start-index" => lastEntry['index'].to_i} if not lastEntry.nil?
128
+ uri = URI.parse("https://#{environment['dns']}:4242/monitoring/logs")
129
+ response = Openshift::Rest.get(@http, uri, params,
130
+ nil, {'user' => environment['username'], 'password' => environment['password']})
131
+ case response
132
+ when Net::HTTPSuccess
133
+
134
+ else
135
+ debug "HTTP code: #{response.code}"
136
+ debug response.body
137
+ csay("[ERROR]",:error) if not @porcelin
138
+ csay("Unable to retrieve application logs for environment.",:error)
139
+ end
140
+ logs = JSON.parse(response.body)
141
+ logs = logs['logs']
142
+ lastEntry = logs['last-entry']
143
+ entries = logs['entries']
144
+
145
+ if entries.size ==0
146
+ csay("No more logs..sleeping 5 sec..")
147
+ sleep(5)
148
+ end
149
+ entries.each{ |entry|
150
+ csay("[#{Time.at(entry['timestamp']).utc}] ")
151
+ csay("[#{entry['app_id']}] ")
152
+ csay(entry['text'])
153
+ }
154
+ lastEntry['index'] = lastEntry['index'].to_i + 1
155
+ debug lastEntry
156
+ end
157
+ else
158
+ csay("This feature is currently not implemented for Openshift Express applications.\n",:red)
159
+ end
@@ -0,0 +1,5 @@
1
+ debug=false
2
+ login_server=https://www.redhat.com
3
+ flex_server=https://openshift.redhat.com/flex
4
+ libra_server=openshift.redhat.com
5
+ domain=prod.rhcloud.com
@@ -0,0 +1,666 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2010 Red Hat, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person
5
+ # obtaining a copy of this software and associated documentation files
6
+ # (the "Software"), to deal in the Software without restriction,
7
+ # including without limitation the rights to use, copy, modify, merge,
8
+ # publish, distribute, sublicense, and/or sell copies of the Software,
9
+ # and to permit persons to whom the Software is furnished to do so,
10
+ # subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
+ # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
+ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'rubygems'
25
+ require 'fileutils'
26
+ require 'getoptlong'
27
+ require 'json'
28
+ require 'net/http'
29
+ require 'net/https'
30
+ require 'net/http/post/multipart'
31
+ require 'parseconfig'
32
+ require 'resolv'
33
+ require 'uri'
34
+ require 'highline/import'
35
+ require 'cgi'
36
+
37
+ @libra_kfile = "#{ENV['HOME']}/.ssh/libra_id_rsa"
38
+ @libra_kpfile = "#{ENV['HOME']}/.ssh/libra_id_rsa.pub"
39
+ @conf_name = 'openshift.conf'
40
+
41
+ _linux_cfg = '/etc/openshift/' + @conf_name
42
+ _gem_cfg = File.join(File.expand_path(File.dirname(__FILE__) + "/../conf"), @conf_name)
43
+ _home_conf = File.expand_path('~/.openshift')
44
+ @local_config_path = File.join(_home_conf, @conf_name)
45
+ @config_path = File.exists?(_linux_cfg) ? _linux_cfg : _gem_cfg
46
+
47
+ FileUtils.mkdir_p _home_conf unless File.directory?(_home_conf)
48
+ local_config_path = File.expand_path(@local_config_path)
49
+ if !File.exists? local_config_path
50
+ FileUtils.touch local_config_path
51
+ puts ""
52
+ puts "Created local config file: " + local_config_path
53
+ puts "openshift.conf contains user configuration and can be transferred across clients."
54
+ puts ""
55
+ end
56
+
57
+ begin
58
+ $global_config = ParseConfig.new(@config_path)
59
+ $local_config = ParseConfig.new(File.expand_path(@local_config_path))
60
+ rescue Errno::EACCES => e
61
+ puts "Could not open config file: #{e.message}"
62
+ exit 253
63
+ end
64
+
65
+ # Check for proxy environment
66
+ if ENV['http_proxy']
67
+ host, port = ENV['http_proxy'].split(':')
68
+ @http = Net::HTTP::Proxy(host, port)
69
+ else
70
+ @http = Net::HTTP
71
+ end
72
+
73
+ def conf(name)
74
+ val = $local_config.get_value(name) ? $local_config.get_value(name) : $global_config.get_value(name)
75
+ val.gsub!(/\\:/,":") if not val.nil?
76
+ #print "CONF #{name} => #{val}\n\n"
77
+ val
78
+ end
79
+
80
+ def setconf(name,value)
81
+ $local_config.add(name,value)
82
+ $local_config.write(File.open(File.expand_path(@local_config_path),"w"))
83
+ end
84
+
85
+ HighLine.track_eof=false
86
+ HighLine.color_scheme = HighLine::ColorScheme.new do |cs|
87
+ cs[:emphasis] = [ :blue, :bold ]
88
+ cs[:error] = [ :red ]
89
+ cs[:warn] = [ :red ]
90
+ cs[:debug] = [ :red, :on_white, :bold ]
91
+ cs[:conf] = [ :green ]
92
+ cs[:question] = [ :magenta, :bold ]
93
+ cs[:table] = [ :blue ]
94
+ cs[:table_header] = [ :bold ]
95
+ cs[:message] = [ :bold ]
96
+ end
97
+
98
+ @h = HighLine.new
99
+ def csay(str,*options)
100
+ lastChar = str[-1..-1]
101
+ h = HighLine.new
102
+ if lastChar == ' ' or lastChar == '\t'
103
+ str=h.color(str[0..-2],*options)+lastChar
104
+ else
105
+ str=h.color(str,*options)
106
+ end
107
+ h.say(str)
108
+ end
109
+
110
+ def debug(*s)
111
+ @h = HighLine.new if @h.nil?
112
+ if @debug or conf('debug') == "true"
113
+ str = "DEBUG"
114
+ str += " "*(@h.output_cols()-str.length) if str.length < @h.output_cols()
115
+ csay(str,:debug)
116
+ s.each{ |line|
117
+ str = line.to_s
118
+ str += " "*(@h.output_cols()-str.length) + "\n" if str.length < @h.output_cols()
119
+ csay(str,:debug)
120
+ }
121
+ end
122
+ end
123
+
124
+ module Openshift
125
+ module SSH
126
+ def self.gen_ssh_keys(libra_kfile, libra_kpfile)
127
+ if File.readable?(libra_kfile)
128
+ puts "OpenShift ssh key found at #{libra_kfile}. Reusing..."
129
+ else
130
+ puts "Generating OpenShift ssh key to #{libra_kfile}"
131
+ # Use system for interaction
132
+ system("ssh-keygen -t rsa -f '#{libra_kfile}'")
133
+ end
134
+ ssh_key = File.open(libra_kpfile).gets.chomp.split(' ')[1]
135
+ end
136
+
137
+ def self.setup_ssh_config(domain)
138
+ ssh_config = "#{ENV['HOME']}/.ssh/config"
139
+ ssh_config_d = "#{ENV['HOME']}/.ssh/"
140
+ # Check / add new host to ~/.ssh/config
141
+ puts "Checking ~/.ssh/config"
142
+
143
+ found = false
144
+ begin
145
+ File.open(ssh_config, "r") do |sline|
146
+ while(line = sline.gets)
147
+ if line.to_s.start_with? "Host *.#{domain}"
148
+ found = true
149
+ break
150
+ end
151
+ end
152
+ end
153
+ rescue Errno::EACCES
154
+ puts "Could not read from #{ssh_config}"
155
+ puts "Reason: " + $!
156
+ puts
157
+ puts "Please correct this first. Then run rerun."
158
+ puts
159
+ exit 213
160
+ rescue Errno::ENOENT
161
+ puts "Could not find #{ssh_config}. This is ok, continuing"
162
+ end
163
+ if found
164
+ puts "Found #{domain} in ~/.ssh/config... No need to adjust"
165
+ else
166
+ puts " Adding #{domain} to ~/.ssh/config"
167
+ begin
168
+ f = File.open(ssh_config, "a")
169
+ f.puts <<SSH
170
+
171
+ # Added by rhc-create-application on #{`date`}
172
+ Host *.#{domain}
173
+ IdentityFile ~/.ssh/libra_id_rsa
174
+ VerifyHostKeyDNS yes
175
+ StrictHostKeyChecking no
176
+ UserKnownHostsFile ~/.ssh/libra_known_hosts
177
+
178
+ SSH
179
+ f.close
180
+ rescue Errno::EACCES
181
+ puts "Could not write to #{ssh_config}"
182
+ puts "Reason: " + $!
183
+ puts
184
+ puts "Please correct this first. Then run rerun."
185
+ puts
186
+ exit 214
187
+ rescue Errno::ENOENT
188
+ # Make directory and config if they do not exist
189
+ puts "Could not find directory: " + $!
190
+ puts "creating"
191
+ FileUtils.mkdir_p ssh_config_d
192
+ file = File.open(ssh_config, 'w')
193
+ file.close
194
+ retry
195
+ end
196
+ end
197
+ File.chmod(0700, ssh_config_d)
198
+ File.chmod(0600, ssh_config)
199
+ end
200
+ end
201
+
202
+ module Validation
203
+ Maxdlen = 16
204
+
205
+ TYPES = {
206
+ 'php-5.3' => :php,
207
+ 'perl-5.10' => :perl,
208
+ 'rack-1.1' => :rack,
209
+ 'wsgi-3.2' => :wsgi,
210
+ 'jbossas-7.0' => :jbossas
211
+ }
212
+
213
+ EXPRESS_SUPPORTED_TYPES = {
214
+ 'php-5.3' => :php,
215
+ 'rack-1.1' => :rack,
216
+ 'wsgi-3.2' => :wsgi
217
+ }
218
+
219
+ def self.get_supportted_templates(sep=', ', target="express")
220
+ if target == "express"
221
+ return get_cartridge_types(EXPRESS_SUPPORTED_TYPES)
222
+ else
223
+ return get_cartridge_types(FLEX_SUPPORTED_TYPES)
224
+ end
225
+ end
226
+
227
+ def self.check_login(login)
228
+ if login
229
+ if login.length < 6
230
+ csay('Login must be at least 6 characters\n',:error)
231
+ return false
232
+ elsif login =~ /["\$\^<>\|%\/;:,\\\*=~]/
233
+ csay('Login may not contain any of these characters: (\") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) (\) (*) (=) (~)\n',:error)
234
+ return false
235
+ end
236
+ else
237
+ csay("Login is required\n",:error)
238
+ return false
239
+ end
240
+ true
241
+ end
242
+
243
+ def self.check_field(field, type, max=0, space_ok=false)
244
+ if field
245
+ if space_ok
246
+ if field =~ /[^0-9a-zA-Z ]/
247
+ csay("#{type} contains non-alphanumeric characters!\n",:error)
248
+ return false
249
+ end
250
+ else
251
+ if field =~ /[^0-9a-zA-Z]/
252
+ csay("#{type} contains non-alphanumeric characters!\n",:error)
253
+ return false
254
+ end
255
+ end
256
+ if max != 0 && field.length > max
257
+ csay("maximum #{type} size is #{max} characters\n",:error)
258
+ return false
259
+ end
260
+ if field.strip.length == 0
261
+ csay("#{type} is required",:error)
262
+ return false
263
+ end
264
+ else
265
+ csay("#{type} is required",:error)
266
+ return false
267
+ end
268
+ true
269
+ end
270
+ end
271
+
272
+ module IO
273
+ def self.prompt(prompt, options=nil,func=nil,required=false,echo=true,limit=nil)
274
+ input = nil
275
+ while input == nil
276
+ if options.nil? or options.length == 0
277
+ csay("#{prompt}? ",:question)
278
+ input = ask(""){ |q|
279
+ q.echo = "*" if !echo
280
+ q.limit = limit if !limit.nil?
281
+ }
282
+ else
283
+ csay("#{prompt} [#{options.join(',')}]? default: ",:question)
284
+ input = ask(""){ |q|
285
+ q.default = options[0] if !options.nil? and options.length > 0
286
+ }
287
+ if options.index(input).nil?
288
+ csay("Invalid value: #{input}. Please choose from ",:error)
289
+ csay("[#{options.join(',')}]",:emphasis)
290
+ input = nil
291
+ end
292
+ end
293
+
294
+ if func and not func.call(input)
295
+ input = nil
296
+ end
297
+
298
+ if required and (input.nil? or input.strip == "")
299
+ csay("This is required field. Please enter a value.",:error)
300
+ input = nil
301
+ end
302
+ end
303
+ input
304
+ end
305
+ end
306
+
307
+ module Formatter
308
+ def self.table( col_names, col_keys, col_sizes, rows, indent=0)
309
+ self.print_row_delim(col_sizes,indent)
310
+ print (" " * 4 * indent)
311
+ csay("| ",:table)
312
+ (0...col_names.size).each{ |i|
313
+ csay(sprintf("%#{col_sizes[i]}s ",col_names[i]),:table_header)
314
+ csay("| ",:table)
315
+ }
316
+ print "\n"
317
+ self.print_row_delim(col_sizes,indent)
318
+ rows.each{ |r|
319
+ print (" " * 4 * indent)
320
+ csay("| ",:table)
321
+ (0...col_names.size).each{ |i|
322
+ if not r[col_keys[i]].nil?
323
+ printf "%#{col_sizes[i]}s ", r[col_keys[i]]
324
+ else
325
+ printf "%#{col_sizes[i]}s ", " "
326
+ end
327
+ csay("| ", :table)
328
+ }
329
+ print "\n"
330
+ }
331
+ self.print_row_delim(col_sizes,indent)
332
+ end
333
+
334
+ def self.print_row_delim(col_sizes,indent)
335
+ print(" " * 4 * indent)
336
+ str = "+"
337
+ col_sizes.each{ |s|
338
+ str += "-"*(s+2)
339
+ str += "+"
340
+ }
341
+ csay(str,:table)
342
+ end
343
+ end
344
+
345
+ module Rest
346
+ def self.execute(http, req, url, params=nil, cookies=nil, auth=nil)
347
+ cookies ||= ''
348
+
349
+ req['cookie']=""
350
+ cookies.each{ |cookie|
351
+ req['cookie'] += cookie
352
+ }
353
+
354
+ debug "---cookie---"
355
+ debug req['cookie']
356
+ debug "------------"
357
+
358
+ req.set_form_data(params) if params
359
+ req.basic_auth(auth['user'], auth['password']) if auth != nil
360
+
361
+ http = http.new(url.host, url.port)
362
+ #http.set_debug_output $stderr
363
+ if url.scheme == "https"
364
+ http.use_ssl = true
365
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
366
+ http.timeout = 60*10
367
+ end
368
+ http.open_timeout = 10
369
+ http.read_timeout = 60*10
370
+ begin
371
+ response = http.start {|http| http.request(req)}
372
+ response.each{|k,v|
373
+ debug "Header: #{k}:#{v}"
374
+ }
375
+ debug "Response code:#{response.code} body:#{response.body}"
376
+ response
377
+ rescue Exception => e
378
+ puts "There was a problem communicating with the server. Response message: #{e.message}"
379
+ exit 219
380
+ end
381
+
382
+ end
383
+
384
+ def self.doHttp(http, method, url, params=nil, cookies=nil, auth=nil)
385
+ case method
386
+ when "POST"
387
+ post(http, url, params, cookies, auth)
388
+ when "PUT"
389
+ put(http, url, params, cookies, auth)
390
+ when "GET"
391
+ get(http, url, params, cookies, auth)
392
+ when "DELETE"
393
+ delete(http, url, params, cookies, auth)
394
+ else
395
+ get(http, url, params, cookies, auth)
396
+ end
397
+ end
398
+
399
+ def self.put(http, url, params=nil, cookies=nil, auth=nil)
400
+ req = http::Put.new(url.path)
401
+ execute(http, req, url, params, cookies, auth)
402
+ end
403
+
404
+ def self.get(http, url, params=nil, cookies='', auth=nil)
405
+ path = url.path
406
+ path += "?" + params.collect { |k,v| "#{k}=#{CGI::escape(v.to_s)}" }.join('&') if not params.nil?
407
+ req = http::Get.new(path)
408
+ execute(http, req, url, nil, cookies, auth)
409
+ end
410
+
411
+ def self.postFile(http, url, params, fileParam, cookies=nil, auth=nil)
412
+ paramName=fileParam.keys[0]
413
+ fileName=fileParam[paramName]
414
+ response=nil
415
+ File.open(fileName) do |file|
416
+ params[paramName] = UploadIO.new(file, "application/octet-stream", File.basename(fileName))
417
+ req = Net::HTTP::Post::Multipart.new(url.path, params)
418
+ response = execute(http, req, url, nil, cookies, auth)
419
+ end
420
+ response
421
+ end
422
+
423
+ def self.post(http, url, params, cookies=nil, auth=nil)
424
+ req = http::Post.new(url.path)
425
+ execute(http, req, url, params, cookies, auth)
426
+ end
427
+
428
+ def self.delete(http, url, params, cookies=nil, auth=nil)
429
+ req = http::Delete.new(url.path)
430
+ execute(http, req, url, params, cookies, auth)
431
+ end
432
+ end
433
+
434
+ def self.login(http, username, password)
435
+ login_server = conf('login_server')
436
+ login_url = URI.parse("#{login_server}/wapps/streamline/login.html")
437
+ response = Rest.post(http, login_url, {'login' => username, 'password' => password})
438
+ case response
439
+ when Net::HTTPUnauthorized:
440
+ csay("Invalid username or password.\n", :red, :bold)
441
+ exit -1
442
+ end
443
+ debug response
444
+ response['Set-Cookie'].split("\; ")[0] + "\; "
445
+ end
446
+
447
+ def self.add_rhlogin_config(rhlogin, uuid=nil)
448
+ f = open(File.expand_path(@local_config_path), 'a')
449
+
450
+ unless @local_config.get_value('username')
451
+ f.puts("# Default rhlogin to use if none is specified")
452
+ f.puts("username=#{rhlogin}")
453
+ end
454
+ f.puts("#{rhlogin}=#{uuid}") unless @local_config.get_value('uuid') or uuid.nil?
455
+ f.close
456
+ end
457
+
458
+ module Flex
459
+ TEMPLATES = {
460
+ 'php' => ['php-5', 'www-dynamic'],
461
+ 'zend' => ['zend-server-php', 'www-dynamic'],
462
+ 'zend_ce' => ['zend-server-ce', 'www-dynamic'],
463
+ 'tomcat' => ['tomcat', 'jdk6'],
464
+ 'jboss6' => ['jboss-6', 'jdk6'],
465
+ 'jboss7' => ['jboss-7', 'jdk6']
466
+ }
467
+
468
+ def self.templates
469
+ return TEMPLATES
470
+ end
471
+ end
472
+
473
+ module Git
474
+ def self.git_repo?
475
+ `git rev-parse --show-toplevel 2> /dev/null`.strip != ""
476
+ end
477
+
478
+ def self.get_git_base_dir
479
+ `git rev-parse --show-toplevel 2> /dev/null`.strip
480
+ end
481
+
482
+ def self.add_remote(uri,remote_name)
483
+ system("git remote add #{remote_name} #{uri}")
484
+ end
485
+
486
+ def self.clone(uri,dirName,remote_name="origin")
487
+ system("git clone #{uri} #{dirName} --origin #{remote_name} --quiet")
488
+ end
489
+
490
+ def self.pull(remote_name="origin")
491
+ system("git pull #{remote_name} master --quiet")
492
+ end
493
+
494
+ def self.push(uri,remote_name)
495
+ system("git push #{remote_name} master --quiet")
496
+ end
497
+ end
498
+
499
+ module Debug
500
+ def self.print_post_data(h)
501
+ debug 'DEBUG: Submitting form:'
502
+ h.each do |k,v|
503
+ if k.to_s != 'password'
504
+ debug "#{k.to_s}: #{v.to_s}"
505
+ else
506
+ debug 'password: ' + ("X" * v.length)
507
+ end
508
+ end
509
+ end
510
+ end
511
+
512
+ module Express
513
+ Maxdlen = 16
514
+ Maxretries = 10
515
+ Defaultdelay = 2
516
+
517
+ def self.delay(time, adj=Defaultdelay)
518
+ (time*=adj).to_int
519
+ end
520
+
521
+ def self.get_cartridges_list(libra_server, net_http, cart_type="standalone", debug=true, print_result=nil)
522
+ puts "Contacting https://#{libra_server} to obtain list of cartridges..."
523
+ puts " (please excuse the delay)"
524
+ data = {'cart_type' => cart_type}
525
+ if debug
526
+ data['debug'] = "true"
527
+ end
528
+ print_post_data(data, debug)
529
+ json_data = JSON.generate(data)
530
+
531
+ url = URI.parse("https://#{libra_server}/broker/cartlist")
532
+ response = http_post(net_http, url, json_data, "none")
533
+
534
+ unless response.code == '200'
535
+ print_response_err(response, debug)
536
+ return []
537
+ end
538
+ json_resp = JSON.parse(response.body)
539
+ if print_result
540
+ print_response_success(json_resp, debug)
541
+ end
542
+ begin
543
+ carts = (JSON.parse(json_resp['data']))['carts']
544
+ rescue JSON::ParserError
545
+ exit 254
546
+ end
547
+ carts
548
+ end
549
+
550
+ def self.get_cartridge_listing(carts, sep, libra_server, net_http, cart_type="standalone", debug=true, print_result=nil)
551
+ carts = get_cartridges_list(libra_server, net_http, cart_type, debug, print_result) if carts.nil?
552
+ carts.join(sep)
553
+ end
554
+
555
+ def self.get_password
556
+ password = nil
557
+ begin
558
+ print "Password: "
559
+ system "stty -echo"
560
+ password = gets.chomp
561
+ ensure
562
+ system "stty echo"
563
+ end
564
+ puts "\n"
565
+ password
566
+ end
567
+
568
+ def self.http_post(http, url, json_data, password)
569
+ req = http::Post.new(url.path)
570
+
571
+ req.set_form_data({'json_data' => json_data, 'password' => password})
572
+ http = http.new(url.host, url.port)
573
+ http.open_timeout = 10
574
+ if url.scheme == "https"
575
+ http.use_ssl = true
576
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
577
+ end
578
+ begin
579
+ response = http.start {|http| http.request(req)}
580
+ if response.code == '404' && response.content_type == 'text/html'
581
+ # TODO probably want to remove this at some point
582
+ puts "!!!! WARNING !!!! WARNING !!!! WARNING !!!!"
583
+ puts "RHCloud server not found. You might want to try updating your rhc client tools."
584
+ exit 218
585
+ end
586
+ response
587
+ rescue Exception => e
588
+ puts "There was a problem communicating with the server. Response message: #{e.message}"
589
+ puts "If you were disconnected it is possible the operation finished without being able to report success."
590
+ puts "You can use rhc-user-info and rhc-ctl-app to learn about the status of your user and application(s)."
591
+ exit 219
592
+ end
593
+ end
594
+
595
+ def self.print_response_err(response)
596
+ puts "Problem reported from server. Response code was #{response.code}."
597
+ exit_code = 254
598
+ if response.content_type == 'application/json'
599
+ exit_code = print_json_body(response, debug)
600
+ elsif debug
601
+ debug "HTTP response from server is #{response.body}"
602
+ end
603
+ exit exit_code.nil? ? 666 : exit_code
604
+ end
605
+
606
+ def self.print_response_messages(json_resp)
607
+ messages = json_resp['messages']
608
+ if (messages && !messages.empty?)
609
+ puts ''
610
+ puts 'MESSAGES:'
611
+ puts messages
612
+ puts ''
613
+ end
614
+ end
615
+
616
+ def self.print_response_success(response, debug, always_print_result=false)
617
+ if debug
618
+ puts "Response from server:"
619
+ print_json_body(response, debug)
620
+ elsif always_print_result
621
+ print_json_body(response, debug)
622
+ else
623
+ json_resp = JSON.parse(response.body)
624
+ print_response_messages(json_resp)
625
+ end
626
+ end
627
+
628
+ def self.print_json_body(response, debug)
629
+ json_resp = JSON.parse(response.body)
630
+ print_response_messages(json_resp)
631
+ exit_code = json_resp['exit_code']
632
+ if debug
633
+ if json_resp['debug']
634
+ puts ''
635
+ puts 'DEBUG:'
636
+ puts json_resp['debug']
637
+ puts ''
638
+ puts "Exit Code: #{exit_code}"
639
+ if (json_resp.length > 3)
640
+ json_resp.each do |k,v|
641
+ if (k != 'result' && k != 'debug' && k != 'exit_code' && k != 'messages')
642
+ puts "#{k.to_s}: #{v.to_s}"
643
+ end
644
+ end
645
+ end
646
+ end
647
+ end
648
+ if json_resp['result']
649
+ puts ''
650
+ puts 'RESULT:'
651
+ puts json_resp['result']
652
+ puts ''
653
+ end
654
+ exit_code
655
+ end
656
+
657
+ #
658
+ # Check if host exists
659
+ #
660
+ def self.hostexist?(host)
661
+ dns = Resolv::DNS.new
662
+ resp = dns.getresources(host, Resolv::DNS::Resource::IN::A)
663
+ return resp.any?
664
+ end
665
+ end
666
+ end