rhc 1.3.8 → 1.4.7
Sign up to get free protection for your applications and to get access to all the features.
- data/features/lib/rhc_helper/domain.rb +9 -18
- data/features/scaled_application.feature +1 -1
- data/features/step_definitions/cartridge_steps.rb +1 -1
- data/lib/rhc.rb +3 -0
- data/lib/rhc/cartridge_helpers.rb +85 -27
- data/lib/rhc/command_runner.rb +1 -1
- data/lib/rhc/commands/app.rb +64 -52
- data/lib/rhc/commands/cartridge.rb +19 -32
- data/lib/rhc/commands/port_forward.rb +4 -2
- data/lib/rhc/coverage_helper.rb +2 -4
- data/lib/rhc/exceptions.rb +0 -3
- data/lib/rhc/git_helpers.rb +1 -1
- data/lib/rhc/helpers.rb +25 -11
- data/lib/rhc/output_helpers.rb +1 -7
- data/lib/rhc/rest/cartridge.rb +1 -1
- data/lib/rhc/rest/client.rb +3 -3
- data/lib/rhc/rest/mock.rb +8 -2
- data/lib/rhc/wizard.rb +29 -22
- data/spec/coverage_helper.rb +5 -8
- data/spec/rhc/commands/app_spec.rb +95 -8
- data/spec/rhc/commands/cartridge_spec.rb +2 -4
- data/spec/rhc/commands/port_forward_spec.rb +16 -7
- data/spec/rhc/helpers_spec.rb +52 -16
- data/spec/rhc/wizard_spec.rb +1 -6
- data/spec/spec_helper.rb +0 -1
- metadata +2 -61
- data/bin/rhc-app +0 -549
- data/bin/rhc-chk +0 -595
- data/bin/rhc-create-app +0 -249
- data/bin/rhc-create-domain +0 -190
- data/bin/rhc-ctl-app +0 -180
- data/bin/rhc-ctl-domain +0 -191
- data/bin/rhc-domain +0 -347
- data/bin/rhc-domain-info +0 -156
- data/bin/rhc-port-forward +0 -234
- data/bin/rhc-snapshot +0 -109
- data/bin/rhc-sshkey +0 -177
- data/bin/rhc-tail-files +0 -133
- data/bin/rhc-user-info +0 -12
- data/lib/rhc-common.rb +0 -1205
data/bin/rhc-sshkey
DELETED
@@ -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
|
data/bin/rhc-tail-files
DELETED
@@ -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
|
data/bin/rhc-user-info
DELETED
data/lib/rhc-common.rb
DELETED
@@ -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
|