rhc 0.68.5

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.
@@ -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