rhc 0.68.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2011 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 "uri"
26
+ require "net/http"
27
+ require "net/https"
28
+ require "getoptlong"
29
+ require "json"
30
+ require 'parseconfig'
31
+ require 'fileutils'
32
+ require 'rhc-common'
33
+
34
+ #
35
+ # print help
36
+ #
37
+ def p_usage
38
+ rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "(required)"
39
+ puts <<USAGE
40
+
41
+ Usage: rhc-user-info
42
+ Display information about a user
43
+
44
+ -l|--rhlogin rhlogin RHCloud rhlogin (#{rhlogin})
45
+ -p|--password password RHLogin password (optional, will prompt)
46
+ -a|--apps List applications for rhlogin
47
+ -i|--info Show user info
48
+ -d|--debug Print Debug info
49
+ -h|--help Show Usage info
50
+
51
+ USAGE
52
+ exit 255
53
+ end
54
+
55
+ def validate_email(email)
56
+ if email =~ /([^@]+)@([a-zA-Z0-9\.])+\.([a-zA-Z]{2,3})/
57
+ if $1 =~ /[^a-zA-Z0-9\.]/
58
+ return false
59
+ else
60
+ return true
61
+ end
62
+ else
63
+ return false
64
+ end
65
+ end
66
+
67
+ begin
68
+ opts = GetoptLong.new(
69
+ ["--debug", "-d", GetoptLong::NO_ARGUMENT],
70
+ ["--help", "-h", GetoptLong::NO_ARGUMENT],
71
+ ["--apps", "-a", GetoptLong::NO_ARGUMENT],
72
+ ["--info", "-i", GetoptLong::NO_ARGUMENT],
73
+ ["--rhlogin", "-l", GetoptLong::REQUIRED_ARGUMENT],
74
+ ["--password", "-p", GetoptLong::OPTIONAL_ARGUMENT]
75
+ )
76
+ opt = {}
77
+ opts.each do |o, a|
78
+ opt[o[2..-1]] = a.to_s
79
+ end
80
+ rescue Exception => e
81
+ #puts e.message
82
+ p_usage
83
+ end
84
+
85
+ # Pull in configs from files
86
+ libra_server = get_var('libra_server')
87
+ debug = get_var('debug') == 'false' ? nil : get_var('debug')
88
+ libra_domain = get_var('libra_domain')
89
+
90
+ libra_kfile = "#{ENV['HOME']}/.ssh/libra_id_rsa"
91
+ libra_kpfile = "#{ENV['HOME']}/.ssh/libra_id_rsa.pub"
92
+
93
+ if opt["help"]
94
+ p_usage
95
+ end
96
+
97
+ if opt["debug"]
98
+ debug = true
99
+ end
100
+
101
+ opt["rhlogin"] = get_var('default_rhlogin') unless opt["rhlogin"]
102
+
103
+ if !RHC::check_rhlogin(opt['rhlogin'])
104
+ p_usage
105
+ end
106
+
107
+ password = opt['password']
108
+ if !password
109
+ password = RHC::get_password
110
+ end
111
+
112
+ opt['apps'] = true if not opt['info'] and not opt['apps']
113
+ user_info = RHC::get_user_info(libra_server, opt['rhlogin'], password, @http, debug, true)
114
+
115
+ if user_info['user_info']['uuid'] != get_var(opt["rhlogin"])
116
+ puts "!! WARNING !! WARNING !! WARNING !! WARNING !!"
117
+ puts
118
+ puts "The UUID in your #{@conf_name} file is either missing or incorrect."
119
+ puts "Please ensure the below line exists in #{@local_config_path}"
120
+ puts
121
+ puts "#{opt['rhlogin']}=#{user_info['user_info']['uuid']}"
122
+ puts
123
+ puts "!! WARNING !! WARNING !! WARNING !! WARNING !!"
124
+ end
125
+
126
+ if opt['info']
127
+ puts "User Info"
128
+ puts "========="
129
+ puts "Namespace: #{user_info['user_info']['namespace']}"
130
+ puts " UUID: #{user_info['user_info']['uuid']}"
131
+ puts " RHLogin: #{user_info['user_info']['rhlogin']}"
132
+ puts " ssh_key: #{user_info['user_info']['ssh_key']}"
133
+ end
134
+
135
+ if opt['apps']
136
+ puts "\n\n" if opt['info']
137
+
138
+ puts "Application Info"
139
+ puts "================"
140
+ user_info['app_info'].each do |key, val|
141
+ puts key
142
+ puts " Framework: #{val['framework']}"
143
+ puts " Creation: #{val['creation_time']}"
144
+ puts " Git URL: ssh://#{user_info['user_info']['uuid']}@#{key}-#{user_info['user_info']['namespace']}.#{libra_domain}/~/git/#{key}.git/"
145
+ puts " Public URL: http://#{key}-#{user_info['user_info']['namespace']}.#{libra_domain}/"
146
+ puts ""
147
+ end
148
+
149
+ end
150
+
151
+ exit 0
@@ -0,0 +1,8 @@
1
+ # Default OpenShift domain
2
+ libra_domain='rhcloud.com'
3
+
4
+ # Remote API server
5
+ libra_server = 'openshift.redhat.com'
6
+
7
+ # Logging
8
+ debug = false
@@ -0,0 +1,318 @@
1
+ # Copyright 2010 Red Hat, Inc.
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation files
5
+ # (the "Software"), to deal in the Software without restriction,
6
+ # including without limitation the rights to use, copy, modify, merge,
7
+ # publish, distribute, sublicense, and/or sell copies of the Software,
8
+ # and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18
+ # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19
+ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'rubygems'
24
+ require 'fileutils'
25
+ require 'getoptlong'
26
+ require 'json'
27
+ require 'net/http'
28
+ require 'net/https'
29
+ require 'parseconfig'
30
+ require 'resolv'
31
+ require 'uri'
32
+
33
+
34
+ module RHC
35
+
36
+ Maxdlen = 16
37
+ Maxretries = 10
38
+ Defaultdelay = 2
39
+
40
+ TYPES = {
41
+ 'php-5.3.2' => :php,
42
+ 'rack-1.1.0' => :rack,
43
+ 'wsgi-3.2.1' => :wsgi
44
+ }
45
+
46
+ def self.delay(time, adj=Defaultdelay)
47
+ (time*=adj).to_int
48
+ end
49
+
50
+ def self.get_cartridge_types(sep=', ')
51
+ i = 1
52
+ type_keys = ''
53
+ TYPES.each_key do |key|
54
+ type_keys += key
55
+ if i < TYPES.size
56
+ type_keys += sep
57
+ end
58
+ i += 1
59
+ end
60
+ type_keys
61
+ end
62
+
63
+ # Invalid chars (") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) (\) (*) (=) (~)
64
+ def self.check_rhlogin(rhlogin)
65
+ if rhlogin
66
+ if rhlogin.length < 6
67
+ puts 'RHLogin must be at least 6 characters'
68
+ return false
69
+ elsif rhlogin =~ /["\$\^<>\|%\/;:,\\\*=~]/
70
+ puts 'RHLogin may not contain any of these characters: (\") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) (\) (*) (=) (~)'
71
+ return false
72
+ end
73
+ else
74
+ puts "RHLogin is required"
75
+ return false
76
+ end
77
+ true
78
+ end
79
+
80
+ def self.check_app(app)
81
+ check_field(app, 'application', Maxdlen)
82
+ end
83
+
84
+ def self.check_namespace(namespace)
85
+ check_field(namespace, 'namespace', Maxdlen)
86
+ end
87
+
88
+ def self.check_field(field, type, max=0)
89
+ if field
90
+ if field =~ /[^0-9a-zA-Z]/
91
+ puts "#{type} contains non-alphanumeric characters!"
92
+ return false
93
+ end
94
+ if max != 0 && field.length > Maxdlen
95
+ puts "maximum #{type} size is #{Maxdlen} characters"
96
+ return false
97
+ end
98
+ else
99
+ puts "#{type} is required"
100
+ return false
101
+ end
102
+ true
103
+ end
104
+
105
+ def self.get_cartridge(type)
106
+ if type
107
+ if !(RHC::TYPES.has_key?(type))
108
+ puts 'type must be ' << get_cartridge_types(' or ')
109
+ else
110
+ return RHC::TYPES[type]
111
+ end
112
+ else
113
+ puts "Type is required"
114
+ end
115
+ nil
116
+ end
117
+
118
+ def self.print_post_data(h, debug)
119
+ if (debug)
120
+ puts 'DEBUG: Submitting form:'
121
+ h.each do |k,v|
122
+ if k.to_s != 'password'
123
+ puts "#{k.to_s}: #{v.to_s}"
124
+ else
125
+ print 'password: '
126
+ for i in (1..v.length)
127
+ print 'X'
128
+ end
129
+ puts ''
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ def self.get_user_info(libra_server, rhlogin, password, net_http, debug, print_result)
136
+
137
+ puts "Contacting https://#{libra_server}"
138
+ data = {'rhlogin' => rhlogin}
139
+ if debug
140
+ data['debug'] = "true"
141
+ end
142
+ print_post_data(data, debug)
143
+ json_data = JSON.generate(data)
144
+
145
+ url = URI.parse("https://#{libra_server}/app/broker/userinfo")
146
+ response = http_post(net_http, url, json_data, password)
147
+
148
+ unless response.code == '200'
149
+ if response.code == '404'
150
+ puts "A user with rhlogin '#{rhlogin}' does not have a registered domain. Be sure to run rhc-create-domain before using the other rhc tools."
151
+ exit 99
152
+ elsif response.code == '401'
153
+ puts "Invalid user credentials"
154
+ exit 97
155
+ else
156
+ print_response_err(response, debug)
157
+ end
158
+ exit 254
159
+ end
160
+ if print_result
161
+ print_response_success(response, debug)
162
+ end
163
+ begin
164
+ json_resp = JSON.parse(response.body)
165
+ user_info = JSON.parse(json_resp['result'].to_s)
166
+ rescue JSON::ParserError
167
+ exit 254
168
+ end
169
+ user_info
170
+ end
171
+
172
+ def self.get_password
173
+ password = nil
174
+ begin
175
+ print "Password: "
176
+ system "stty -echo"
177
+ password = gets.chomp
178
+ ensure
179
+ system "stty echo"
180
+ end
181
+ puts "\n"
182
+ password
183
+ end
184
+
185
+ def self.http_post(http, url, json_data, password)
186
+ req = http::Post.new(url.path)
187
+
188
+ req.set_form_data({'json_data' => json_data, 'password' => password})
189
+ http = http.new(url.host, url.port)
190
+ http.open_timeout = 10
191
+ if url.scheme == "https"
192
+ http.use_ssl = true
193
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
194
+ end
195
+ begin
196
+ response = http.start {|http| http.request(req)}
197
+ if response.code == '404' && response.content_type == 'text/html'
198
+ # TODO probably want to remove this at some point
199
+ puts "!!!! WARNING !!!! WARNING !!!! WARNING !!!!"
200
+ puts "RHCloud server not found. You might want to try updating your rhc client tools."
201
+ exit 218
202
+ end
203
+ response
204
+ rescue Exception => e
205
+ puts "There was a problem communicating with the server. Response message: #{e.message}"
206
+ puts "If you were disconnected it is possible the operation finished without being able to report success."
207
+ puts "You can use rhc-user-info and rhc-ctl-app to learn about the status of your user and application(s)."
208
+ exit 219
209
+ end
210
+ end
211
+
212
+ def self.print_response_err(response, debug)
213
+ puts "Problem reported from server. Response code was #{response.code}."
214
+ if (!debug)
215
+ puts "Re-run with -d for more information."
216
+ end
217
+ exit_code = 254
218
+ if response.content_type == 'application/json'
219
+ exit_code = print_json_body(response, debug)
220
+ elsif debug
221
+ puts "HTTP response from server is #{response.body}"
222
+ end
223
+ exit exit_code.nil? ? 666 : exit_code
224
+ end
225
+
226
+ def self.print_response_success(response, debug, always_print_result=false)
227
+ if debug
228
+ puts "Response from server:"
229
+ print_json_body(response, debug)
230
+ elsif always_print_result
231
+ print_json_body(response, debug)
232
+ end
233
+ end
234
+
235
+ def self.print_json_body(response, debug)
236
+ json_resp = JSON.parse(response.body);
237
+ exit_code = json_resp['exit_code']
238
+ if debug
239
+ if json_resp['debug']
240
+ puts ''
241
+ puts 'DEBUG:'
242
+ puts json_resp['debug']
243
+ puts ''
244
+ puts "Exit Code: #{exit_code}"
245
+ if (json_resp.length > 3)
246
+ json_resp.each do |k,v|
247
+ if (k != 'results' && k != 'debug' && k != 'exit_code')
248
+ puts "#{k.to_s}: #{v.to_s}"
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ if json_resp['result']
255
+ puts ''
256
+ puts 'RESULT:'
257
+ puts json_resp['result']
258
+ puts ''
259
+ end
260
+ exit_code
261
+ end
262
+
263
+ #
264
+ # Check if host exists
265
+ #
266
+ def self.hostexist?(host)
267
+ dns = Resolv::DNS.new
268
+ resp = dns.getresources(host, Resolv::DNS::Resource::IN::A)
269
+ return resp.any?
270
+ end
271
+
272
+ end
273
+
274
+ #
275
+ # Config paths... /etc/openshift/express.conf or $GEM/conf/express.conf -> ~/.openshift/express.conf
276
+ #
277
+ # semi-private: Just in case we rename again :)
278
+ @conf_name = 'express.conf'
279
+ _linux_cfg = '/etc/openshift/' + @conf_name
280
+ _gem_cfg = File.join(File.expand_path(File.dirname(__FILE__) + "/../conf"), @conf_name)
281
+ _home_conf = File.expand_path('~/.openshift')
282
+ @local_config_path = File.join(_home_conf, @conf_name)
283
+ @config_path = File.exists?(_linux_cfg) ? _linux_cfg : _gem_cfg
284
+
285
+ FileUtils.mkdir_p _home_conf unless File.directory?(_home_conf)
286
+ if !File.exists?(File.expand_path(@local_config_path)) && File.exists?("#{ENV['HOME']}/.li/libra.conf")
287
+ print "Moving old-style config file..."
288
+ FileUtils.cp "#{ENV['HOME']}/.li/libra.conf", File.expand_path(@local_config_path)
289
+ FileUtils.mv "#{ENV['HOME']}/.li/libra.conf", "#{ENV['HOME']}/.li/libra.conf.deprecated"
290
+ puts " Done."
291
+ end
292
+
293
+ FileUtils.touch File.expand_path(@local_config_path)
294
+
295
+ begin
296
+ @global_config = ParseConfig.new(@config_path)
297
+ @local_config = ParseConfig.new(File.expand_path(@local_config_path))
298
+ rescue Errno::EACCES => e
299
+ puts "Could not open config file: #{e.message}"
300
+ exit 253
301
+ end
302
+
303
+ #
304
+ # Check for proxy environment
305
+ #
306
+ if ENV['http_proxy']
307
+ host, port = ENV['http_proxy'].split(':')
308
+ @http = Net::HTTP::Proxy(host, port)
309
+ else
310
+ @http = Net::HTTP
311
+ end
312
+
313
+ #
314
+ # Check for local var in ~/.li/libra.conf use it, else use $GEM/../conf/libra.conf
315
+ #
316
+ def get_var(var)
317
+ @local_config.get_value(var) ? @local_config.get_value(var) : @global_config.get_value(var)
318
+ end