rhc 1.3.8 → 1.4.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,177 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rhc/coverage_helper'
4
-
5
- require 'rhc-common'
6
-
7
- RHC::Helpers.deprecated_command('rhc sshkey',true)
8
-
9
- #
10
- # print help
11
- #
12
- def p_usage(exit_code = 255)
13
- rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "required"
14
- puts <<USAGE
15
-
16
- Usage: rhc sshkey (<command> | --help) [<args>]
17
- Manage multiple keys for the registered rhcloud user.
18
-
19
- List of commands
20
- list Display all the SSH keys for the user account
21
- add Add SSH key to the user account
22
- update Update SSH key for the user account
23
- remove Remove SSH key from the user account
24
-
25
- List of arguments
26
- -l|--rhlogin rhlogin OpenShift login (#{rhlogin})
27
- -p|--password password Password (optional, will prompt)
28
- -i|--identifier key-name User-specified identifier for the key
29
- -k|--ssh key-filepath SSH public key filepath
30
- -d|--debug Print Debug info
31
- -h|--help Show Usage info
32
- --config path Path of alternate config file
33
- --timeout # Timeout, in seconds, for the session
34
-
35
- USAGE
36
- exit exit_code
37
- end
38
-
39
-
40
- def validate_args(val_id=true)
41
- # If provided a config path, check it
42
- RHC::Config.check_cpath($opt)
43
-
44
- # Pull in configs from files
45
- $libra_server = get_var('libra_server')
46
- debug = get_var('debug') == 'false' ? nil : get_var('debug')
47
-
48
- $opt['rhlogin'] = get_var('default_rhlogin') unless $opt['rhlogin']
49
- p_usage if !RHC::check_rhlogin($opt['rhlogin'])
50
-
51
- debug = $opt["debug"] ? true : false
52
- RHC::debug(debug)
53
-
54
- p_usage if val_id && !RHC::check_key($opt['identifier'])
55
-
56
- RHC::timeout($opt["timeout"], get_var('timeout'))
57
- RHC::connect_timeout($opt["timeout"], get_var('timeout'))
58
- $password = $opt['password'] ? $opt['password'] : RHC::get_password
59
- end
60
-
61
- def remove_key
62
- validate_args(true)
63
-
64
- data = {}
65
- data[:rhlogin] = $opt['rhlogin']
66
- data[:key_name] = $opt['identifier']
67
- data[:action] = 'remove-key'
68
-
69
- url = URI.parse("https://#{$libra_server}/broker/ssh_keys")
70
- handle_key_mgmt_response(url, data, $password)
71
- end
72
-
73
- def show_key_list
74
- validate_args(false)
75
-
76
- ssh_keys = RHC::get_ssh_keys($libra_server, $opt['rhlogin'], $password, RHC::Config.default_proxy)
77
- additional_ssh_keys = ssh_keys['keys']
78
-
79
- puts ""
80
- puts "SSH keys"
81
- puts "========"
82
-
83
- # first list the primary key
84
- puts " Name: default"
85
- puts " Type: #{ssh_keys['ssh_type']}"
86
- puts "Fingerprint: #{ssh_keys['fingerprint']}"
87
- #puts " Key: #{ssh_keys['ssh_key']}"
88
- puts ""
89
-
90
- # now list the additional keys
91
- if additional_ssh_keys && additional_ssh_keys.kind_of?(Hash)
92
- additional_ssh_keys.each do |name, keyval|
93
- puts " Name: #{name}"
94
- puts " Type: #{keyval['type']}"
95
- puts "Fingerprint: #{keyval['fingerprint']}"
96
- #puts " Key: #{keyval['key']}"
97
- puts ""
98
- end
99
- end
100
- end
101
-
102
- begin
103
- argv_c = ARGV.clone
104
-
105
- if ARGV[0] =~ /^(add|update)$/
106
- ARGV.shift
107
- opts = GetoptLong.new(
108
- ["--debug", "-d", GetoptLong::NO_ARGUMENT],
109
- ["--help", "-h", GetoptLong::NO_ARGUMENT],
110
- ["--rhlogin", "-l", GetoptLong::REQUIRED_ARGUMENT],
111
- ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
112
- ["--identifier", "-i", GetoptLong::REQUIRED_ARGUMENT],
113
- ["--ssh", "-k", GetoptLong::REQUIRED_ARGUMENT],
114
- ["--config", GetoptLong::REQUIRED_ARGUMENT],
115
- ["--timeout", GetoptLong::REQUIRED_ARGUMENT]
116
- )
117
- elsif ARGV[0] =~ /^remove$/
118
- ARGV.shift
119
- opts = GetoptLong.new(
120
- ["--debug", "-d", GetoptLong::NO_ARGUMENT],
121
- ["--help", "-h", GetoptLong::NO_ARGUMENT],
122
- ["--rhlogin", "-l", GetoptLong::REQUIRED_ARGUMENT],
123
- ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
124
- ["--identifier", "-i", GetoptLong::REQUIRED_ARGUMENT],
125
- ["--config", GetoptLong::REQUIRED_ARGUMENT],
126
- ["--timeout", GetoptLong::REQUIRED_ARGUMENT]
127
- )
128
- elsif ARGV[0] =~ /^list$/
129
- ARGV.shift
130
- opts = GetoptLong.new(
131
- ["--debug", "-d", GetoptLong::NO_ARGUMENT],
132
- ["--help", "-h", GetoptLong::NO_ARGUMENT],
133
- ["--rhlogin", "-l", GetoptLong::REQUIRED_ARGUMENT],
134
- ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
135
- ["--config", GetoptLong::REQUIRED_ARGUMENT],
136
- ["--timeout", GetoptLong::REQUIRED_ARGUMENT]
137
- )
138
- else
139
- opts = GetoptLong.new(
140
- ["--help", "-h", GetoptLong::NO_ARGUMENT]
141
- )
142
- unless ARGV[0] =~ /^(help|-h|--help)$/
143
- puts "Missing or invalid command!"
144
- # just exit at this point
145
- # printing the usage description will be handled in the rescue
146
- exit 255
147
- end
148
- end
149
-
150
- $opt = {}
151
- opts.each do |o, a|
152
- $opt[o[2..-1]] = a.to_s
153
- end
154
-
155
- rescue Exception => e
156
- p_usage
157
- end
158
-
159
- p_usage 0 if $opt["help"]
160
-
161
- case argv_c[0]
162
- when "add", "update"
163
- validate_args(true)
164
- add_or_update_key(argv_c[0], $opt['identifier'], $opt['ssh'],
165
- $opt['rhlogin'], $password)
166
- when "remove"
167
- remove_key
168
- when "list", nil
169
- show_key_list
170
- when "-h", "--help", "help", nil
171
- p_usage 0
172
- else
173
- puts "Invalid command!"
174
- p_usage
175
- end
176
-
177
- exit 0
@@ -1,133 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rhc/coverage_helper'
4
-
5
- require 'rhc-common'
6
- require 'base64'
7
-
8
- #
9
- # print help
10
- #
11
- def p_usage(exit_code = 255)
12
- rhlogin = get_var('default_rhlogin') ? "Default: #{get_var('default_rhlogin')}" : "required"
13
- puts <<USAGE
14
-
15
- Usage: #{$0}
16
- Tail the logs of an application
17
-
18
- -l|--rhlogin rhlogin OpenShift login (#{rhlogin})
19
- -a|--app Target application (required)
20
- -f|--files File glob relative to app (default <application_name>/logs/*) (optional)
21
- -o|--opts Options to pass to the server-side (linux based) tail command (-f is implicit. See the linux tail man page full list of options.) (Ex: --opts '-n 100')
22
- -p|--password password Password (optional, will prompt)
23
- -d|--debug Print Debug info
24
- -h|--help Show Usage info
25
- --config path Path of alternate config file
26
- --timeout # Timeout, in seconds, for the session
27
-
28
- USAGE
29
- exit exit_code
30
- end
31
-
32
- begin
33
- opts = GetoptLong.new(
34
- ["--debug", "-d", GetoptLong::NO_ARGUMENT],
35
- ["--help", "-h", GetoptLong::NO_ARGUMENT],
36
- ["--app", "-a", GetoptLong::REQUIRED_ARGUMENT],
37
- ["--opts", "-o", GetoptLong::REQUIRED_ARGUMENT],
38
- ["--files", "-f", GetoptLong::REQUIRED_ARGUMENT],
39
- ["--rhlogin", "-l", GetoptLong::REQUIRED_ARGUMENT],
40
- ["--config", GetoptLong::REQUIRED_ARGUMENT],
41
- ["--password", "-p", GetoptLong::REQUIRED_ARGUMENT],
42
- ["--timeout", GetoptLong::REQUIRED_ARGUMENT]
43
- )
44
- opt = {}
45
- opts.each do |o, a|
46
- opt[o[2..-1]] = a.to_s
47
- end
48
- rescue Exception => e
49
- #puts e.message
50
- p_usage
51
- end
52
-
53
- # If provided a config path, check it
54
- RHC::Config.check_cpath(opt)
55
-
56
- # Pull in configs from files
57
- libra_server = get_var('libra_server')
58
- debug = get_var('debug') == 'false' ? nil : get_var('debug')
59
-
60
- p_usage 0 if opt['help']
61
-
62
- p_usage if !opt['app'] || 0 != ARGV.length
63
-
64
- debug = true if opt['debug']
65
-
66
- RHC::debug(debug)
67
-
68
- RHC::timeout(opt["timeout"], get_var('timeout'))
69
- RHC::connect_timeout(opt["timeout"], get_var('timeout'))
70
-
71
- opt['rhlogin'] = get_var('default_rhlogin') unless opt['rhlogin']
72
-
73
- if !RHC::check_rhlogin(opt['rhlogin'])
74
- p_usage
75
- end
76
-
77
- password = opt['password']
78
- if !password
79
- password = RHC::get_password
80
- end
81
-
82
- user_info = RHC::get_user_info(libra_server, opt['rhlogin'], password, RHC::Config.default_proxy, false)
83
-
84
- app = opt['app']
85
-
86
- unless user_info['app_info'][app]
87
- puts
88
- puts "Could not find app '#{opt['app']}'. Please run rhc-domain-info to get a list"
89
- puts "of your current running applications"
90
- puts
91
- exit 101
92
- end
93
-
94
- opt['files'] = "*/log*/*" unless opt['files']
95
- file_glob = "#{opt['files']}"
96
- app_uuid = user_info['app_info'][app]['uuid']
97
- namespace = user_info['user_info']['domains'][0]['namespace']
98
- rhc_domain = user_info['user_info']['rhc_domain']
99
-
100
- # -t to force PTY and avoid daemons
101
- # Red Hat OpenShift: https://bugzilla.redhat.com/show_bug.cgi?id=726646
102
- # OpenSSH https://bugzilla.mindrot.org/show_bug.cgi?id=396
103
-
104
- remote_cmd = "tail#{opt['opts'] ? ' --opts ' + Base64::encode64(opt['opts']).chomp : ''} #{file_glob}"
105
- ssh_cmd = "ssh -t #{app_uuid}@#{app}-#{namespace}.#{rhc_domain} '#{remote_cmd}'"
106
-
107
- puts "Attempting to tail files: #{file_glob}"
108
- puts "Use ctl + c to stop"
109
- puts ssh_cmd if debug
110
- begin
111
- if opt['files'] == 'system-messages'
112
- RHC::ctl_app(libra_server, RHC::Config.default_proxy, opt['app'], opt['rhlogin'], password,
113
- 'system-messages', false, nil, nil)
114
- else
115
- ssh_ruby("#{app}-#{namespace}.#{rhc_domain}", app_uuid, remote_cmd)
116
- end
117
- rescue Interrupt
118
- puts
119
- puts "Terminating..."
120
- exit 0
121
- rescue SocketError => e
122
- puts
123
- puts "Could not connect: #{e.message}"
124
- puts
125
- puts "DEBUG: #{e.debug}" if debug
126
- puts "You can try to run this manually if you have ssh installed: "
127
- puts
128
- puts ssh_cmd
129
- puts
130
- exit 1
131
- end
132
- # this should never happen
133
- exit 1
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- args = ""
4
- ARGV.each do|a|
5
- if a.to_s.strip.length == 0; a = "'#{a}'" end
6
- args += " #{a}"
7
- end
8
-
9
- system("rhc-domain-info #{args} 2>&1")
10
- retcode = $?.exitstatus
11
-
12
- exit retcode
@@ -1,1205 +0,0 @@
1
- require 'rubygems' # Will eventually be removed when this file is deprecated
2
- require 'fileutils'
3
- require 'getoptlong'
4
- require 'net/http'
5
- require 'net/https'
6
- require 'net/ssh'
7
- require 'rhc/vendor/sshkey'
8
- require 'resolv'
9
- require 'uri'
10
- require 'highline/import'
11
- require 'rhc'
12
- require 'rhc/rest'
13
- require 'rhc/helpers'
14
- require 'rhc/config'
15
- require 'rhc/wizard'
16
- require 'rhc/tar_gz'
17
- require 'rhc/json'
18
-
19
- module RHC
20
-
21
- DEFAULT_MAX_LENGTH = 16
22
- APP_NAME_MAX_LENGTH = 32
23
- MAX_RETRIES = 7
24
- DEFAULT_DELAY = 2.0
25
- API = "1.1.3"
26
- PATTERN_VERSION=/\A\d+\.\d+\.\d+\z/
27
- @read_timeout = 120
28
- @connect_timeout = 20
29
- @mydebug = false
30
- @@api_version = "?.?.?"
31
-
32
- # reset lines
33
- # \r moves the cursor to the beginning of line
34
- # ANSI escape code to clear line from cursor to end of line
35
- # "\e" is an alternative to "\033"
36
- # cf. http://en.wikipedia.org/wiki/ANSI_escape_code
37
- CLEAR_LINE = "\r" + "\e[0K"
38
-
39
- DEBUG_INGORE_KEYS = {
40
- 'result' => nil,
41
- 'debug' => nil,
42
- 'exit_code' => nil,
43
- 'messages' => nil,
44
- 'data' => nil,
45
- 'api' => nil
46
- }
47
-
48
- def self.timeout(*vals)
49
- vals.each do |val|
50
- if val
51
- unless val.to_i > 0
52
- puts 'Timeout must be specified as a number greater than 0'
53
- exit 1
54
- end
55
- @read_timeout = [val.to_i, @read_timeout].max
56
- return @read_timeout
57
- end
58
- end
59
- end
60
-
61
- def self.connect_timeout(*vals)
62
- vals.each do |val|
63
- if val
64
- unless val.to_i > 0
65
- puts 'Timeout must be specified as a number greater than 0'
66
- exit 1
67
- end
68
- @connect_timeout = [val.to_i, @connect_timeout].max
69
- return @connect_timeout
70
- end
71
- end
72
- end
73
-
74
- def self.debug(bool)
75
- @mydebug = bool
76
- end
77
-
78
- def self.update_server_api_v(dict)
79
- if !dict['api'].nil? && (dict['api'] =~ PATTERN_VERSION)
80
- @@api_version = dict['api']
81
- end
82
- end
83
-
84
- def self.check_version
85
- if @@api_version =~ PATTERN_VERSION
86
- if API != @@api_version
87
- puts "\nNOTICE: Client API version (#{API}) does not match the server (#{@@api_version}).\nThough requests may succeed, you should consider updating your client tools.\n\n"
88
- end
89
- end
90
- end
91
-
92
- def self.delay(time, adj=DEFAULT_DELAY)
93
- (time*=adj).to_int
94
- end
95
-
96
- def self.json_encode(data)
97
- RHC::Json.encode(data)
98
- end
99
-
100
- def self.json_decode(json)
101
- RHC::Json.decode(json)
102
- end
103
-
104
- def self.generate_json(data)
105
- data['api'] = API
106
- json = json_encode(data)
107
- json
108
- end
109
-
110
- def self.get_cartridges_list(libra_server, net_http, cart_type="standalone", print_result=nil)
111
- puts "Obtaining list of cartridges (please excuse the delay)..."
112
- data = {'cart_type' => cart_type}
113
- if @mydebug
114
- data[:debug] = true
115
- end
116
- print_post_data(data)
117
- json_data = generate_json(data)
118
-
119
- url = URI.parse("https://#{libra_server}/broker/cartlist")
120
- response = http_post(net_http, url, json_data, "none")
121
-
122
- unless response.code == '200'
123
- print_response_err(response)
124
- return []
125
- end
126
- begin
127
- json_resp = json_decode(response.body)
128
- rescue RHC::JsonError
129
- exit 1
130
- end
131
- update_server_api_v(json_resp)
132
- if print_result
133
- print_response_success(json_resp)
134
- end
135
- begin
136
- carts = (json_decode(json_resp['data']))['carts']
137
- rescue RHC::JsonError
138
- exit 1
139
- end
140
- carts
141
- end
142
-
143
- def self.get_cartridge_listing(carts, sep, libra_server, net_http, cart_type="standalone", print_result=nil)
144
- carts = get_cartridges_list(libra_server, net_http, cart_type, print_result) if carts.nil?
145
- carts.join(sep)
146
- end
147
-
148
-
149
- # Invalid chars (") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) (\) (*) (=) (~)
150
- def self.check_rhlogin(rhlogin)
151
- if rhlogin
152
- if rhlogin =~ /["\$\^<>\|%\/;:,\\\*=~]/
153
- puts 'OpenShift login may not contain any of these characters: (\") ($) (^) (<) (>) (|) (%) (/) (;) (:) (,) (\) (*) (=) (~)'
154
- return false
155
- end
156
- else
157
- puts "OpenShift login is required"
158
- return false
159
- end
160
- true
161
- end
162
-
163
- def self.check_app(app)
164
- check_field(app, 'application', APP_NAME_MAX_LENGTH)
165
- end
166
-
167
- def self.check_namespace(namespace)
168
- check_field(namespace, 'namespace', DEFAULT_MAX_LENGTH)
169
- end
170
-
171
- def self.check_key(keyname)
172
- check_field(keyname, 'key name', DEFAULT_MAX_LENGTH, /[^0-9a-zA-Z]/,
173
- 'contains invalid characters! Only alpha-numeric characters allowed.')
174
- end
175
-
176
- def self.check_field(field, type, max=0, val_regex=/[^0-9a-zA-Z]/,
177
- regex_failed_error='contains non-alphanumeric characters!')
178
- if field
179
- if field =~ val_regex
180
- say "#{type} " + regex_failed_error
181
- return false
182
- end
183
- if max != 0 && field.length > max
184
- say "maximum #{type} size is #{max} characters"
185
- return false
186
- end
187
- else
188
- say "#{type} is required"
189
- return false
190
- end
191
- field
192
- end
193
-
194
- def self.print_post_data(h)
195
- if (@mydebug)
196
- puts 'Submitting form:'
197
- h.each do |k,v|
198
- if k.to_s != 'password'
199
- puts "#{k.to_s}: #{v.to_s}"
200
- else
201
- print 'password: '
202
- for i in (1..v.length)
203
- print 'X'
204
- end
205
- puts ''
206
- end
207
- end
208
- end
209
- end
210
-
211
- def self.get_user_info(libra_server, rhlogin, password, net_http, print_result, not_found_message=nil)
212
- data = {'rhlogin' => rhlogin}
213
- if @mydebug
214
- data[:debug] = true
215
- end
216
- print_post_data(data)
217
- json_data = generate_json(data)
218
-
219
- url = URI.parse("https://#{libra_server}/broker/userinfo")
220
- response = http_post(net_http, url, json_data, password)
221
-
222
- unless response.code == '200'
223
- if response.code == '404'
224
- if not_found_message
225
- puts not_found_message
226
- else
227
- puts "A user with rhlogin '#{rhlogin}' does not have a registered domain. Be sure to run 'rhc domain create' before using the other rhc tools."
228
- end
229
- exit 99
230
- elsif response.code == '401'
231
- puts "Invalid user credentials"
232
- exit 97
233
- else
234
- print_response_err(response)
235
- end
236
- exit 1
237
- end
238
- begin
239
- json_resp = json_decode(response.body)
240
- rescue RHC::JsonError
241
- exit 1
242
- end
243
- update_server_api_v(json_resp)
244
- if print_result
245
- print_response_success(json_resp)
246
- end
247
- begin
248
- user_info = json_decode(json_resp['data'].to_s)
249
- rescue RHC::JsonError
250
- exit 1
251
- end
252
- user_info
253
- end
254
-
255
- # Public: Get a list of ssh keys
256
- #
257
- # type - The String type RSA or DSS.
258
- # libra_server - The String DNS for the broker
259
- # rhlogin - The String login name
260
- # password - The String password for login
261
- # net_http - The NET::HTTP Object to use
262
- #
263
- # Examples
264
- #
265
- # RHC::get_ssh_keys('openshift.redhat.com',
266
- # 'mylogin@example.com',
267
- # 'mypassword',
268
- # RHC::Config.default_proxy)
269
- # # => { "ssh_type" => "ssh-rsa",
270
- # "ssh_key" => "AAAAB3NzaC1yc2EAAAADAQAB....",
271
- # "fingerprint" => "ea:08:e3:c7:e3:c3:8e:6a:66:34:65:e4:56:f4:3e:ff"}
272
- #
273
- # FIXME! Exits on failure! Should return something instead
274
- #
275
- # Returns Hash on success or exits on failure
276
- def self.get_ssh_keys(libra_server, rhlogin, password, net_http)
277
- data = {'rhlogin' => rhlogin, 'action' => 'list-keys'}
278
- if @mydebug
279
- data[:debug] = true
280
- end
281
- print_post_data(data)
282
- json_data = generate_json(data)
283
-
284
- url = URI.parse("https://#{libra_server}/broker/ssh_keys")
285
- response = http_post(net_http, url, json_data, password)
286
-
287
- unless response.code == '200'
288
- if response.code == '401'
289
- puts "Invalid user credentials"
290
- exit 97
291
- else
292
- print_response_err(response)
293
- end
294
- exit 1
295
- end
296
- begin
297
- json_resp = json_decode(response.body)
298
- rescue RHC::JsonError
299
- exit 1
300
- end
301
- update_server_api_v(json_resp)
302
- begin
303
- ssh_keys = (json_decode(json_resp['data'].to_s))
304
- rescue RHC::JsonError
305
- exit 1
306
- end
307
-
308
- # Inject public fingerprint into key.
309
- begin
310
- if ssh_keys['ssh_type'].nil? or ssh_keys['ssh_type'].empty?
311
- ssh_keys['fingerprint'] = nil
312
- else
313
- ssh_keys['fingerprint'] = \
314
- Net::SSH::KeyFactory.load_data_public_key(
315
- "#{ssh_keys['ssh_type']} #{ssh_keys['ssh_key']}").fingerprint
316
- end
317
- rescue NoMethodError
318
- #older net/ssh (mac for example)
319
- tempfile = `mktemp /tmp/openshift.XXXXXXXX`
320
- `echo "#{ssh_keys['ssh_type']} #{ssh_keys['ssh_key']}" > #{tempfile}`
321
- ssh_keys['fingerprint'] = `ssh-keygen -lf #{tempfile}`.split(' ')[1]
322
- rescue Net::SSH::Exception, NotImplementedError, OpenSSL::PKey::PKeyError
323
- # Could be a new unsupported key type or invalid data on the server
324
- ssh_keys['fingerprint'] = 'Key type is not recognized. Please check this key is valid.'
325
- end
326
-
327
- if ssh_keys['keys'] && ssh_keys['keys'].kind_of?(Hash)
328
- ssh_keys['keys'].each do |name, keyval|
329
- type = keyval['type']
330
- key = keyval['key']
331
- begin
332
- ssh_keys['keys'][name]['fingerprint'] = \
333
- Net::SSH::KeyFactory.load_data_public_key(
334
- "#{type} #{key}").fingerprint
335
- rescue NoMethodError
336
- #older net/ssh (mac for example)
337
- tempfile = `mktemp /tmp/openshift.XXXXXXXX`
338
- `echo "#{type} #{key}" > #{tempfile}`
339
- ssh_keys['keys'][name]['fingerprint'] = `ssh-keygen -lf #{tempfile}`.split(' ')[1]
340
- rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
341
- # Could be a new unsupported key type or invalid data on the server
342
- ssh_keys['keys'][name]['fingerprint'] = 'Key type is not recognized. Please check this key is valid.'
343
- end
344
- end
345
- end
346
- ssh_keys
347
- end
348
-
349
- def self.get_password
350
- password = nil
351
- begin
352
- password = ask_password
353
- rescue Interrupt
354
- puts "\n"
355
- exit 1
356
- end
357
- puts "\n"
358
- password
359
- end
360
-
361
- def self.http_post(http, url, json_data, password)
362
- req = http::Post.new(url.path)
363
-
364
- puts "Contacting #{url.scheme}://#{url.host}" if @mydebug
365
- req.set_form_data({'json_data' => json_data, 'password' => password})
366
- req['User-Agent'] = RHC::Helpers.user_agent
367
-
368
- http = http.new(url.host, url.port)
369
- http.open_timeout = @connect_timeout
370
- http.read_timeout = @read_timeout
371
- if url.scheme == "https"
372
- http.use_ssl = true
373
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
374
- end
375
- begin
376
- response = http.start {|http| http.request(req)}
377
- if response.code == '404' && response.content_type == 'text/html'
378
- # TODO probably want to remove this at some point
379
- puts "!!!! WARNING !!!! WARNING !!!! WARNING !!!!"
380
- puts "RHCloud server not found. You might want to try updating your rhc client tools."
381
- exit 218
382
- end
383
- response
384
- rescue Exception => e
385
- puts "There was a problem communicating with the server. Response message: #{e.message}"
386
- puts "If you were disconnected it is possible the operation finished without being able to report success."
387
- puts "You can use 'rhc domain show' and 'rhc app show --state' to learn about the status of your user and application(s)."
388
- exit 219
389
- end
390
- end
391
-
392
- def self.print_response_err(response)
393
- puts "Problem reported from server. Response code was #{response.code}."
394
- if (!@mydebug)
395
- puts "Re-run with -d for more information."
396
- end
397
- exit_code = 1
398
- if response.class.inspect == "Struct::FakeResponse"
399
- print_response_message(response.body)
400
- elsif response.content_type == 'application/json'
401
- begin
402
- json_resp = json_decode(response.body)
403
- exit_code = print_json_body(json_resp)
404
- rescue RHC::JsonError
405
- exit_code = 1
406
- end
407
- elsif @mydebug
408
- puts "HTTP response from server is #{response.body}"
409
- end
410
- exit exit_code.nil? ? 666 : exit_code
411
- end
412
-
413
- def self.print_response_messages(json_resp)
414
- messages = json_resp['messages']
415
- print_response_message(messages)
416
- end
417
-
418
- def self.print_response_message(message)
419
- if (message && !message.empty?)
420
- puts ''
421
- puts 'MESSAGES:'
422
- puts message
423
- puts ''
424
- end
425
- end
426
-
427
- def self.print_response_success(json_resp, print_result=false)
428
- if @mydebug
429
- print "Response from server:"
430
- $stdout.flush
431
- print_json_body(json_resp, print_result)
432
- elsif print_result
433
- print_json_body(json_resp)
434
- else
435
- print_response_messages(json_resp)
436
- end
437
- end
438
-
439
- def self.print_json_body(json_resp, print_result=true)
440
- print_response_messages(json_resp)
441
- exit_code = json_resp['exit_code']
442
- if @mydebug
443
- if json_resp['debug']
444
- puts ''
445
- puts 'DEBUG:'
446
- puts json_resp['debug']
447
- puts ''
448
- puts "Exit Code: #{exit_code}"
449
- if (json_resp.length > 3)
450
- json_resp.each do |k,v|
451
- if !DEBUG_INGORE_KEYS.has_key?(k)
452
- puts "#{k.to_s}: #{v.to_s}"
453
- end
454
- end
455
- end
456
- end
457
- if json_resp['api']
458
- puts "API version: #{json_resp['api']}"
459
- end
460
- end
461
- if print_result && json_resp['result']
462
- puts ''
463
- puts 'RESULT:'
464
- puts json_resp['result']
465
- puts ''
466
- end
467
- exit_code
468
- end
469
-
470
- #
471
- # Check if host exists
472
- #
473
- def self.hostexist?(host)
474
- RHC::Helpers.host_exists?(host)
475
- end
476
-
477
- def self.create_app(libra_server, net_http, user_info, app_name, app_type, rhlogin, password, repo_dir=nil, no_dns=false, no_git=false, is_embedded_jenkins=false, gear_size='small',scale=false)
478
-
479
- # Need to have a fake HTTPResponse object for passing to print_reponse_err
480
- # May already be initialized if called from another piece of code
481
- # FIXME: remove this requirement when refactoring rhc
482
- begin
483
- Struct::FakeResponse
484
- rescue NameError
485
- Struct.new('FakeResponse',:body,:code,:content_type)
486
- end
487
-
488
- domains = user_info['user_info']['domains']
489
- if domains.empty?
490
- emessage = "Please create a domain with 'rhc domain create -n <namespace>' before creating applications."
491
- print_response_err(Struct::FakeResponse.new(emessage,403))
492
- end
493
- namespace = domains[0]['namespace']
494
- puts "Creating application: #{app_name} in #{namespace}"
495
- data = {:cartridge => app_type,
496
- :action => 'configure',
497
- :node_profile => gear_size,
498
- :app_name => app_name,
499
- :rhlogin => rhlogin
500
- }
501
- if @mydebug
502
- data[:debug] = true
503
- end
504
-
505
- # Need to use the new REST API for scaling apps
506
- # We'll need to then get the new application using the existing
507
- # API in order to access the rest of the logic in this function
508
- if scale
509
- end_point = "https://#{libra_server}/broker/rest/api"
510
- client = RHC::Rest::Client.new(end_point, rhlogin, password)
511
-
512
- domain = client.find_domain(user_info['user_info']['domains'][0]['namespace'])
513
-
514
- namespace = domain.id
515
- # Catch errors
516
- begin
517
- application = domain.add_application(app_name,{:cartridge => app_type, :scale => true, :gear_profile => gear_size})
518
-
519
- # Variables that are needed for the rest of the function
520
- app_uuid = application.uuid
521
- result = "Successfully created application: #{app_name}"
522
-
523
- # health check path now returned by the API
524
- health_check_path = application.health_check_path
525
-
526
- puts "DEBUG: '#{app_name}' creation returned success." if @mydebug
527
- rescue RHC::Rest::ConnectionException, RHC::Rest::ResourceAccessException => e
528
- print_response_err(Struct::FakeResponse.new(e.message,e.code))
529
- rescue RHC::Rest::ValidationException => e
530
- validation_error_code = (e.code.nil?) ? 406 : e.code
531
- print_response_err(Struct::FakeResponse.new(e.message, validation_error_code))
532
- rescue RHC::Rest::ServerErrorException => e
533
- error_code = (e.code.nil?) ? 500 : e.code
534
- print_response_err(Struct::FakeResponse.new(e.message, error_code))
535
- end
536
- else
537
- json_data = generate_json(data)
538
-
539
- url = URI.parse("https://#{libra_server}/broker/cartridge")
540
- response = http_post(net_http, url, json_data, password)
541
-
542
- if response.code == '200'
543
- json_resp = json_decode(response.body)
544
- print_response_success(json_resp)
545
- json_data = json_decode(json_resp['data'])
546
- health_check_path = json_data['health_check_path']
547
- app_uuid = json_data['uuid']
548
- result = json_resp['result']
549
- puts "DEBUG: '#{app_name}' creation returned success." if @mydebug
550
- else
551
- print_response_err(response)
552
- end
553
- end
554
-
555
- #
556
- # At this point, we need to register a handler to guarantee app
557
- # cleanup on any exceptions or calls to exit
558
- #
559
- at_exit do
560
- unless $!.nil? || $!.is_a?(SystemExit) && $!.success?
561
- puts "Cleaning up application"
562
- destroy_app(libra_server, net_http, app_name, rhlogin, password)
563
- end
564
- end
565
-
566
- rhc_domain = user_info['user_info']['rhc_domain']
567
-
568
- fqdn = "#{app_name}-#{namespace}.#{rhc_domain}"
569
-
570
- loop = 0
571
- #
572
- # Confirm that the host exists in DNS
573
- #
574
- unless no_dns
575
- puts "Now your new domain name is being propagated worldwide (this might take a minute)..."
576
-
577
- # Allow DNS to propogate
578
- sleep 15
579
-
580
- # Now start checking for DNS
581
- sleep_time = 2
582
- while loop < MAX_RETRIES && !hostexist?(fqdn)
583
- sleep sleep_time
584
- loop+=1
585
- print CLEAR_LINE + " retry # #{loop} - Waiting for DNS: #{fqdn}"
586
- $stdout.flush
587
- sleep_time = delay(sleep_time)
588
- end
589
- end
590
-
591
- # if we have executed print statements, then move to the next line
592
- if loop > 0
593
- puts
594
- end
595
-
596
- # construct the Git URL
597
- git_url = "ssh://#{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain}/~/git/#{app_name}.git/"
598
-
599
- # If the hostname couldn't be resolved, print out the git URL
600
- # and exit cleanly. This will help solve issues where DNS times
601
- # out in APAC, etc on resolution.
602
- if loop >= MAX_RETRIES
603
- puts <<WARNING
604
-
605
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
606
- WARNING: We were unable to lookup your hostname (#{fqdn})
607
- in a reasonable amount of time. This can happen periodically and will just
608
- take an extra minute or two to propagate depending on where you are in the
609
- world. Once you are able to access your application in a browser, you can then
610
- clone your git repository.
611
-
612
- Application URL: http://#{fqdn}
613
-
614
- Git Repository URL: #{git_url}
615
-
616
- Git Clone command:
617
- git clone #{git_url} #{repo_dir}
618
-
619
- If you can't get your application '#{app_name}' running in the browser, you can
620
- also try destroying and recreating the application as well using:
621
-
622
- rhc app destroy -a #{app_name} -l #{rhlogin}
623
-
624
- If this doesn't work for you, let us know in the forums or in IRC and we'll
625
- make sure to get you up and running.
626
-
627
- Forums: https://openshift.redhat.com/community/forums/openshift
628
-
629
- IRC: #openshift (on Freenode)
630
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
631
-
632
- WARNING
633
- exit 0
634
- end
635
-
636
- #
637
- # Pull new repo locally
638
- #
639
-
640
- unless no_git
641
- puts "Pulling new repo down" if @mydebug
642
-
643
- quiet = (@mydebug ? ' ' : '--quiet ')
644
- puts "git clone #{quiet}#{git_url} #{repo_dir}" if @mydebug
645
- git_clone = %x[git clone #{quiet} #{git_url} #{repo_dir} 2>&1]
646
- if $?.exitstatus != 0
647
-
648
- if RHC::Helpers.windows?
649
-
650
- `nslookup #{app_name}-#{namespace}.#{rhc_domain}`
651
- windows_nslookup = $?.exitstatus == 0
652
- `ping #{app_name}-#{namespace}.#{rhc_domain} -n 2`
653
- windows_ping = $?.exitstatus == 0
654
-
655
- if windows_nslookup and !windows_ping # this is related to BZ #826769
656
- puts <<WINSOCKISSUE
657
-
658
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
659
- WARNING: We were unable to lookup your hostname (#{fqdn})
660
- in a reasonable amount of time. This can happen periodically and will just
661
- take up to 10 extra minutes to propagate depending on where you are in the
662
- world. This may also be related to an issue with Winsock on Windows [1][2].
663
- We recommend you wait a few minutes then clone your git repository manually.
664
-
665
- Git Clone command:
666
- git clone #{git_url} #{repo_dir}
667
-
668
- [1] http://support.microsoft.com/kb/299357
669
- [2] http://support.microsoft.com/kb/811259
670
-
671
- If this doesn't work for you, let us know in the forums or in IRC and we'll
672
- make sure to get you up and running.
673
-
674
- Forums: https://openshift.redhat.com/community/forums/openshift
675
-
676
- IRC: #openshift (on Freenode)
677
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
678
-
679
- WINSOCKISSUE
680
- exit 0
681
- end
682
- end
683
- puts "Error in git clone"
684
- puts git_clone
685
- exit 216
686
- end
687
- else
688
- if is_embedded_jenkins
689
- # if this is a jenkins client application to be embedded,
690
- # then print this message only in debug mode
691
- if @mydebug
692
- puts "
693
- Note: There is a git repo for your Jenkins application '#{app_name}'
694
- but it isn't being downloaded as part of this process. In most cases
695
- it isn't needed but you can always clone it later.
696
-
697
- "
698
- end
699
- else
700
- puts <<IMPORTANT
701
-
702
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
703
- IMPORTANT: Since the -n flag was specified, no local repo has been created.
704
- This means you can't make changes to your published application until after
705
- you clone the repo yourself. See the git url below for more information.
706
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
707
-
708
- IMPORTANT
709
- end
710
- end
711
-
712
- #
713
- # At this point, we need to register a handler to guarantee git
714
- # repo cleanup on any exceptions or calls to exit
715
- #
716
- unless no_git
717
- at_exit do
718
- unless $!.nil? || $!.is_a?(SystemExit) && $!.success?
719
- puts "Cleaning up git repo"
720
- FileUtils.rm_rf repo_dir
721
- end
722
- end
723
- end
724
- return {:app_name => app_name,
725
- :fqdn => fqdn,
726
- :health_check_path => health_check_path,
727
- :git_url => git_url,
728
- :repo_dir => repo_dir,
729
- :result => result
730
- }
731
- end
732
-
733
- #
734
- # An application is considered available if the health check URL unambiguously returns a 1 or 0.
735
- # Otherwise, if the root URL for the app successfully returns content it is also considered
736
- # successful. In the future, applications that do not expose a public web interface will need
737
- # a more advanced check mechanism, or the check should not prevent creation.
738
- #
739
- def self.check_app_available(net_http, app_name, fqdn, health_check_path, result, git_url, repo_dir, no_git)
740
-
741
- available = MAX_RETRIES.times.any? do |i|
742
- sleep i * DEFAULT_DELAY
743
-
744
- puts "Checking if the application is available ##{i+1}"
745
- if health_check_path and !health_check_path.empty?
746
- value = open("http://#{fqdn}/#{health_check_path}").read[0,1] rescue nil
747
- # TODO: I should be typed exception ApplicationHealthFailure
748
- raise "ERROR: The application was unable to start. Please report this issue via the forums or IRC or file a bug through our public bug tracker." if value == '0'
749
- next true if value == '1'
750
- end
751
- open("http://#{fqdn}") rescue nil
752
- end
753
-
754
- if available
755
- puts "Application #{app_name} is available at: http://#{fqdn}/"
756
- puts " Git URL: #{git_url}"
757
-
758
- if @mydebug
759
- unless no_git
760
- puts "To make changes to '#{app_name}', commit to #{repo_dir}/."
761
- else
762
- puts <<LOOKSGOOD
763
- To make changes to '#{app_name}', you must first clone it with:
764
- git clone #{git_url}
765
-
766
- LOOKSGOOD
767
- puts "Then run 'git push' to update your OpenShift space."
768
- end
769
- end
770
- if result && !result.empty?
771
- puts "#{result}"
772
- end
773
- true
774
- else
775
- puts "Application is not available"
776
- false
777
- end
778
- rescue StandardError => e
779
- puts e
780
- false
781
- end
782
-
783
- def self.destroy_app(libra_server, net_http, app_name, rhlogin, password)
784
- json_data = generate_json(
785
- {:action => 'deconfigure',
786
- :app_name => app_name,
787
- :rhlogin => rhlogin
788
- })
789
- url = URI.parse("https://#{libra_server}/broker/cartridge")
790
- http_post(net_http, url, json_data, password)
791
- end
792
-
793
- def self.ctl_app(libra_server, net_http, app_name, rhlogin, password, action, embedded=false, framework=nil, server_alias=nil, print_result=true)
794
- data = {:action => action,
795
- :app_name => app_name,
796
- :rhlogin => rhlogin
797
- }
798
-
799
- data[:server_alias] = server_alias if server_alias
800
- if framework
801
- data[:cartridge] = framework
802
- end
803
-
804
- if @mydebug
805
- data[:debug] = true
806
- end
807
-
808
- json_data = generate_json(data)
809
-
810
- url = nil
811
- if embedded
812
- url = URI.parse("https://#{libra_server}/broker/embed_cartridge")
813
- else
814
- url = URI.parse("https://#{libra_server}/broker/cartridge")
815
- end
816
- response = http_post(net_http, url, json_data, password)
817
-
818
- if response.code == '200'
819
- json_resp = json_decode(response.body)
820
- print_response_success(json_resp, print_result || @mydebug)
821
- else
822
- print_response_err(response)
823
- end
824
- json_decode(response.body)
825
- end
826
-
827
- def self.snapshot_create(rhc_domain, namespace, app_name, app_uuid, filename, debug=false)
828
-
829
- ssh_cmd = "ssh #{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain} 'snapshot' > #{filename}"
830
- puts "Pulling down a snapshot to #{filename}..."
831
- puts ssh_cmd if debug
832
- puts
833
-
834
- begin
835
-
836
- if ! RHC::Helpers.windows?
837
- output = `#{ssh_cmd}`
838
- if $?.exitstatus != 0
839
- puts output
840
- puts "Error in trying to save snapshot. You can try to save manually by running:"
841
- puts
842
- puts ssh_cmd
843
- puts
844
- return 1
845
- end
846
- else
847
- Net::SSH.start("#{app_name}-#{namespace}.#{rhc_domain}", app_uuid) do |ssh|
848
- File.open(filename, 'wb') do |file|
849
- ssh.exec! "snapshot" do |channel, stream, data|
850
- if stream == :stdout
851
- file.write(data)
852
- else
853
- puts data if debug
854
- end
855
- end
856
- end
857
- end
858
- end
859
- rescue Exception => e
860
- puts e.backtrace if debug
861
- puts "Error in trying to save snapshot. You can try to save manually by running:"
862
- puts
863
- puts ssh_cmd
864
- puts
865
- return 1
866
- end
867
- true
868
- end
869
-
870
- def self.snapshot_restore(rhc_domain, namespace, app_name, app_uuid, filename, debug=false)
871
- if File.exists? filename
872
-
873
- include_git = RHC::Helpers.windows? ? false : RHC::TarGz.contains(filename, './*/git')
874
-
875
- ssh_cmd = "cat #{filename} | ssh #{app_uuid}@#{app_name}-#{namespace}.#{rhc_domain} 'restore#{include_git ? ' INCLUDE_GIT' : ''}'"
876
- puts "Restoring from snapshot #{filename}..."
877
- puts ssh_cmd if debug
878
- puts
879
-
880
- begin
881
- if ! RHC::Helpers.windows?
882
- output = `#{ssh_cmd}`
883
- if $?.exitstatus != 0
884
- puts output
885
- puts "Error in trying to restore snapshot. You can try to restore manually by running:"
886
- puts
887
- puts ssh_cmd
888
- puts
889
- return 1
890
- end
891
- else
892
- ssh = Net::SSH.start("#{app_name}-#{namespace}.#{rhc_domain}", app_uuid)
893
- ssh.open_channel do |channel|
894
- channel.exec("restore#{include_git ? ' INCLUDE_GIT' : ''}") do |ch, success|
895
- channel.on_data do |ch, data|
896
- puts data
897
- end
898
- channel.on_extended_data do |ch, type, data|
899
- puts data
900
- end
901
- channel.on_close do |ch|
902
- puts "Terminating..."
903
- end
904
- File.open(filename, 'rb') do |file|
905
- file.chunk(1024) do |chunk|
906
- channel.send_data chunk
907
- end
908
- end
909
- channel.eof!
910
- end
911
- end
912
- ssh.loop
913
- end
914
- rescue Exception => e
915
- puts e.backtrace
916
- puts "Error in trying to restore snapshot. You can try to restore manually by running:"
917
- puts
918
- puts ssh_cmd
919
- puts
920
- return 1
921
- end
922
-
923
- else
924
- puts "Archive not found: #{filename}"
925
- return 255
926
- end
927
- true
928
- end
929
-
930
- end
931
-
932
- # provide a hook for performing actions before rhc-* commands exit
933
- at_exit {
934
- # ensure client tools are up to date
935
- RHC::check_version
936
- }
937
-
938
- #
939
- # Config paths... /etc/openshift/express.conf or $GEM/conf/express.conf -> ~/.openshift/express.conf
940
- #
941
- # semi-private: Just in case we rename again :)
942
- @opts_config_path = nil
943
- @conf_name = 'express.conf'
944
- _linux_cfg = '/etc/openshift/' + @conf_name
945
- _gem_cfg = File.join(File.expand_path(File.dirname(__FILE__) + "/../conf"), @conf_name)
946
- @home_conf = File.expand_path('~/.openshift')
947
- @local_config_path = File.join(@home_conf, @conf_name)
948
- @config_path = File.exists?(_linux_cfg) ? _linux_cfg : _gem_cfg
949
- @home_dir=File.expand_path("~")
950
-
951
- local_config_path = File.expand_path(@local_config_path)
952
-
953
- #
954
- # Check for proxy environment
955
- #
956
-
957
- @http = RHC::Config.default_proxy
958
-
959
- def config_path
960
- return @opts_config_path ? @opts_config_path : @local_config_path
961
- end
962
-
963
- def config
964
- return @opts_config ? @opts_config : @local_config
965
- end
966
-
967
- def ask_password
968
- return ask("Password: ") { |q|
969
- q.echo = '*'
970
- q.whitespace = :chomp
971
- }
972
- end
973
-
974
- def kfile_not_found
975
- puts <<KFILE_NOT_FOUND
976
- Your SSH keys are created either by running ssh-keygen (password optional)
977
- or by having the 'rhc domain create' command do it for you. If you created
978
- them on your own (or want to use an existing keypair), be sure to paste
979
- your public key into the express console at http://www.openshift.com.
980
- The client tools use the value of 'ssh_key_file' in express.conf to find
981
- your key followed by the defaults of id_rsa[.pub] and then
982
- id_rsa[.pub].
983
- KFILE_NOT_FOUND
984
-
985
- #exit 212
986
- end
987
-
988
- def get_kfile(check_exists=true)
989
- ssh_key_file = get_var('ssh_key_file')
990
- if ssh_key_file
991
- if (File.basename(ssh_key_file) == ssh_key_file)
992
- kfile = "#{ENV['HOME']}/.ssh/#{ssh_key_file}"
993
- else
994
- kfile = File.expand_path(ssh_key_file)
995
- end
996
- else
997
- kfile = "#{ENV['HOME']}/.ssh/id_rsa"
998
- end
999
- if check_exists && !File.exists?(kfile)
1000
- if ssh_key_file
1001
- puts "WARNING: Unable to find '#{kfile}' referenced in express.conf."
1002
- kfile_not_found
1003
- else
1004
- kfile = "#{ENV['HOME']}/.ssh/id_rsa"
1005
- if !File.exists?(kfile)
1006
- puts "WARNING: Unable to find ssh key file."
1007
- kfile_not_found
1008
- end
1009
- end
1010
- end
1011
- return kfile
1012
- end
1013
-
1014
- def get_kpfile(kfile, check_exists=true)
1015
- kpfile = kfile + '.pub'
1016
- if check_exists && !File.exists?(kpfile)
1017
- puts "WARNING: Unable to find '#{kpfile}'"
1018
- kfile_not_found
1019
- end
1020
- return kpfile
1021
- end
1022
-
1023
- # Add a new namespace to configs
1024
- def self.add_rhlogin_config(rhlogin, uuid)
1025
- config_path = RHC::Config.local_config_path
1026
- f = open(File.expand_path(config_path), 'a')
1027
- unless RHC::Config['default_rhlogin']
1028
- f.puts("# Default rhlogin to use if none is specified")
1029
- f.puts("default_rhlogin=#{rhlogin}")
1030
- f.puts("")
1031
- end
1032
- f.close
1033
- end
1034
-
1035
- # Public: Handle response message when updating keys
1036
- #
1037
- # url - The Object URI::HTTPS
1038
- # data - The Hash representation of the data response
1039
- # password - The String password for the user
1040
- #
1041
- # Examples
1042
- #
1043
- # handle_key_mgmt_response(
1044
- # URI.parse('https://openshift.redhat.com/broker/ssh_keys'),
1045
- # {
1046
- # :rhlogin=>"rhnlogin@example.com",
1047
- # :key_name=>"default",
1048
- # :action=>"update-key",
1049
- # :ssh=>"AAAAB3NzaC1yc2EAAAADAQABAAAAgQCrXG5c.....",
1050
- # :key_type=>"ssh-rsa"},
1051
- # 'mypass')
1052
- # # => nil
1053
- #
1054
- # Returns nil on Success and RHC::http object on failure
1055
- def handle_key_mgmt_response(url, data, password)
1056
- RHC::print_post_data(data)
1057
- json_data = RHC::generate_json(data)
1058
-
1059
- response = RHC::http_post(RHC::Config.default_proxy, url, json_data, password)
1060
-
1061
- if response.code == '200'
1062
- begin
1063
- json_resp = RHC::json_decode(response.body)
1064
- RHC::update_server_api_v(json_resp)
1065
- RHC::print_response_success(json_resp)
1066
- puts "Success"
1067
- return
1068
- rescue RHC::JsonError
1069
- RHC::print_response_err(response)
1070
- end
1071
- else
1072
- RHC::print_response_err(response)
1073
- end
1074
- puts "Failure"
1075
- return response
1076
- end
1077
-
1078
- # Public: Add or upload an ssh key
1079
- #
1080
- # type - The String type RSA or DSS.
1081
- # command - The String value 'add' or 'update'
1082
- # identifier - The String value to identify the key
1083
- # pub_key_file_path - The String file path of the public key
1084
- # rhlogin - The String login to the broker
1085
- # password- The String password for the user
1086
- #
1087
- # Examples
1088
- #
1089
- # generate_ssh_key_ruby('add', 'newkeyname', '~/.ssh/id_rsa',
1090
- # 'mylogin', 'mypass')
1091
- # # => /home/user/.ssh/id_rsa.pub
1092
- #
1093
- # Returns nil on success or HTTP object on failure
1094
- def add_or_update_key(command, identifier, pub_key_file_path, rhlogin, password)
1095
-
1096
- # Read user public ssh key
1097
- if pub_key_file_path
1098
- if File.readable?(pub_key_file_path)
1099
- begin
1100
- ssh_keyfile_contents = File.open(pub_key_file_path).gets.chomp.split(' ')
1101
- ssh_key = ssh_keyfile_contents[1]
1102
- ssh_key_type = ssh_keyfile_contents[0]
1103
- rescue Exception => e
1104
- puts "Invalid public keyfile format! Please specify a valid user public keyfile."
1105
- exit 1
1106
- end
1107
- else
1108
- puts "Unable to read user public keyfile #{pub_key_file_path}"
1109
- exit 1
1110
- end
1111
- else # create key
1112
- key_name = identifier
1113
- puts "Generating ssh key pair for user '#{key_name}' in the dir '#{Dir.pwd}/'"
1114
- # REMOVED in favor of generate_ssh_key_ruby: system("ssh-keygen -t rsa -f '#{key_name}'")
1115
- ssh_pub_key_file = generate_ssh_key_ruby()
1116
- ssh_keyfile_contents = File.open(ssh_pub_key_file).gets.chomp.split(' ')
1117
- ssh_key = ssh_keyfile_contents[1]
1118
- ssh_key_type = ssh_keyfile_contents[0]
1119
- end
1120
-
1121
- data = {}
1122
- data[:rhlogin] = rhlogin
1123
- data[:key_name] = identifier
1124
- data[:ssh] = ssh_key
1125
- data[:action] = 'add-key'
1126
- data[:key_type] = ssh_key_type
1127
-
1128
- if command == 'add'
1129
- data[:action] = 'add-key'
1130
- elsif command == 'update'
1131
- data[:action] = 'update-key'
1132
- end
1133
-
1134
- url = URI.parse("https://#{RHC::Config['libra_server']}/broker/ssh_keys")
1135
- handle_key_mgmt_response(url, data, password)
1136
- end
1137
-
1138
-
1139
- # Public: Generate an SSH key and store it in ~/.ssh/id_rsa
1140
- #
1141
- # type - The String type RSA or DSS.
1142
- # bits - The Integer value for number of bits.
1143
- # comment - The String comment for the key
1144
- #
1145
- # Examples
1146
- #
1147
- # generate_ssh_key_ruby()
1148
- # # => /home/user/.ssh/id_rsa.pub
1149
- #
1150
- # Returns nil on failure or public key location as a String on success
1151
- def generate_ssh_key_ruby(type="RSA", bits = 1024, comment = "OpenShift-Key")
1152
- key = RHC::Vendor::SSHKey.generate(:type => type,
1153
- :bits => bits,
1154
- :comment => comment)
1155
- ssh_dir = "#{RHC::Config.home_dir}/.ssh"
1156
- if File.exists?("#{ssh_dir}/id_rsa")
1157
- puts "SSH key already exists: #{ssh_dir}/id_rsa. Reusing..."
1158
- return nil
1159
- else
1160
- unless File.exists?(ssh_dir)
1161
- FileUtils.mkdir_p(ssh_dir)
1162
- File.chmod(0700, ssh_dir)
1163
- end
1164
- File.open("#{ssh_dir}/id_rsa", 'w') {|f| f.write(key.private_key)}
1165
- File.chmod(0600, "#{ssh_dir}/id_rsa")
1166
- File.open("#{ssh_dir}/id_rsa.pub", 'w') {|f| f.write(key.ssh_public_key)}
1167
- end
1168
- "#{ssh_dir}/id_rsa.pub"
1169
- end
1170
-
1171
- # Public: Run ssh command on remote host
1172
- #
1173
- # host - The String of the remote hostname to ssh to.
1174
- # username - The String username of the remote user to ssh as.
1175
- # command - The String command to run on the remote host.
1176
- #
1177
- # Examples
1178
- #
1179
- # ssh_ruby('myapp-t.rhcloud.com',
1180
- # '109745632b514e9590aa802ec015b074',
1181
- # 'rhcsh tail -f $OPENSHIFT_LOG_DIR/*"')
1182
- # # => true
1183
- #
1184
- # Returns true on success
1185
- def ssh_ruby(host, username, command)
1186
- Net::SSH.start(host, username) do |session|
1187
- session.open_channel do |channel|
1188
- channel.request_pty do |ch, success|
1189
- puts "pty could not be obtained" unless success
1190
- end
1191
-
1192
- channel.on_data do |ch, data|
1193
- #puts "[#{file}] -> #{data}"
1194
- puts data
1195
- end
1196
- channel.exec command
1197
- end
1198
- session.loop
1199
- end
1200
- end
1201
-
1202
- # Public: legacy convinience function for getting config keys
1203
- def get_var(key)
1204
- RHC::Config[key]
1205
- end