rhc 1.15.6 → 1.16.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/autocomplete/rhc_bash +168 -24
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +6 -0
- data/features/deployments_feature.rb +127 -0
- data/features/keys_feature.rb +37 -0
- data/features/members_feature.rb +36 -1
- data/lib/rhc/commands/app.rb +79 -2
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/snapshot.rb +6 -1
- data/lib/rhc/commands/sshkey.rb +29 -14
- data/lib/rhc/commands/tail.rb +1 -1
- data/lib/rhc/deployment_helpers.rb +88 -0
- data/lib/rhc/exceptions.rb +24 -0
- data/lib/rhc/git_helpers.rb +1 -1
- data/lib/rhc/helpers.rb +17 -14
- data/lib/rhc/highline_extensions.rb +15 -15
- data/lib/rhc/output_helpers.rb +51 -9
- data/lib/rhc/rest.rb +1 -0
- data/lib/rhc/rest/activation.rb +11 -0
- data/lib/rhc/rest/application.rb +53 -1
- data/lib/rhc/rest/client.rb +16 -12
- data/lib/rhc/rest/deployment.rb +18 -0
- data/lib/rhc/rest/key.rb +14 -2
- data/lib/rhc/rest/mock.rb +90 -5
- data/lib/rhc/ssh_helpers.rb +82 -21
- data/lib/rhc/wizard.rb +2 -2
- data/spec/direct_execution_helper.rb +93 -26
- data/spec/rhc/commands/deployment_spec.rb +286 -0
- data/spec/rhc/commands/snapshot_spec.rb +12 -0
- data/spec/rhc/commands/sshkey_spec.rb +37 -0
- data/spec/rhc/commands/tail_spec.rb +2 -2
- data/spec/rhc/rest_client_spec.rb +6 -2
- data/spec/spec_helper.rb +1 -1
- metadata +17 -5
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rhc/rest/activation'
|
2
|
+
|
3
|
+
module RHC
|
4
|
+
module Rest
|
5
|
+
class Deployment < Base
|
6
|
+
define_attr :id, :ref, :sha1, :artifact_url, :hot_deploy, :created_at, :force_clean_build, :activations
|
7
|
+
|
8
|
+
def activations
|
9
|
+
@activations ||=
|
10
|
+
attributes['activations'].map{|activation| Activation.new({:created_at => RHC::Helpers.datetime_rfc3339(activation)}, client)}.sort
|
11
|
+
end
|
12
|
+
|
13
|
+
def <=>(other)
|
14
|
+
other.created_at <=> created_at
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/rhc/rest/key.rb
CHANGED
@@ -3,6 +3,14 @@ module RHC
|
|
3
3
|
class Key < Base
|
4
4
|
define_attr :name, :type, :content
|
5
5
|
|
6
|
+
def is_ssh?
|
7
|
+
type != 'krb5-principal'
|
8
|
+
end
|
9
|
+
|
10
|
+
def is_kerberos?
|
11
|
+
type == 'krb5-principal'
|
12
|
+
end
|
13
|
+
|
6
14
|
def update(type, content)
|
7
15
|
debug "Updating key #{self.name}"
|
8
16
|
rest_method "UPDATE", :type => type, :content => content
|
@@ -14,17 +22,21 @@ module RHC
|
|
14
22
|
end
|
15
23
|
alias :delete :destroy
|
16
24
|
|
25
|
+
def principal
|
26
|
+
content if is_kerberos?
|
27
|
+
end
|
28
|
+
|
17
29
|
def fingerprint
|
18
30
|
@fingerprint ||= begin
|
19
31
|
public_key = Net::SSH::KeyFactory.load_data_public_key("#{type} #{content}")
|
20
32
|
public_key.fingerprint
|
21
33
|
rescue NotImplementedError, OpenSSL::PKey::PKeyError => e
|
22
34
|
'Invalid key'
|
23
|
-
end
|
35
|
+
end if is_ssh?
|
24
36
|
end
|
25
37
|
|
26
38
|
def visible_to_ssh?
|
27
|
-
Net::SSH::Authentication::Agent.connect.identities.
|
39
|
+
is_ssh? and Net::SSH::Authentication::Agent.connect.identities.
|
28
40
|
find{ |i| fingerprint == i.fingerprint }.present? rescue false
|
29
41
|
end
|
30
42
|
end
|
data/lib/rhc/rest/mock.rb
CHANGED
@@ -2,12 +2,31 @@ module RHC::Rest::Mock
|
|
2
2
|
|
3
3
|
def self.start
|
4
4
|
RHC::Helpers.warn "Running in mock mode"
|
5
|
+
require 'webmock'
|
6
|
+
WebMock.disable_net_connect!
|
7
|
+
MockRestClient.class_eval do
|
8
|
+
include WebMock::API
|
9
|
+
include Helpers
|
10
|
+
def user_agent_header
|
11
|
+
end
|
12
|
+
def user_auth
|
13
|
+
{:user => nil, :password => nil}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
MockRestUser.class_eval do
|
17
|
+
def add_key(*args)
|
18
|
+
attributes['links'] ||= {}
|
19
|
+
links['ADD_KEY'] = {'href' => 'https://test.domain.com/broker/rest/user/keys', 'method' => 'POST'}
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
5
23
|
MockRestClient.new.tap do |c|
|
6
24
|
d = c.add_domain("test1")
|
7
25
|
app = d.add_application('app1', 'carttype1')
|
8
26
|
app.cartridges[0].display_name = "A display name"
|
9
27
|
app.add_cartridge('mockcart2')
|
10
28
|
app2 = d.add_application('app2', 'carttype2', true)
|
29
|
+
c.stub_add_key_error('test', 'this failed')
|
11
30
|
end
|
12
31
|
end
|
13
32
|
|
@@ -98,8 +117,12 @@ module RHC::Rest::Mock
|
|
98
117
|
end
|
99
118
|
def stub_add_key_error(name, message, code=422)
|
100
119
|
stub_api_request(:post, "broker/rest/user/keys", mock_user_auth).
|
101
|
-
with(:body => hash_including({:type => 'ssh-rsa'})).
|
102
|
-
to_return({:status => code, :body => {:messages => [
|
120
|
+
with(:body => hash_including({:name => name, :type => 'ssh-rsa'})).
|
121
|
+
to_return({:status => code, :body => {:messages => [
|
122
|
+
{:text => message, :field => 'name', :severity => 'error'},
|
123
|
+
{:text => "A warning from the server", :field => nil, :severity => 'warning'},
|
124
|
+
]
|
125
|
+
}.to_json})
|
103
126
|
end
|
104
127
|
def stub_create_domain(name)
|
105
128
|
stub_api_request(:post, 'broker/rest/domains', mock_user_auth).
|
@@ -380,6 +403,11 @@ module RHC::Rest::Mock
|
|
380
403
|
['SET_UNSET_ENVIRONMENT_VARIABLES', "domains/#{domain_id}/apps/#{app_id}/event", 'post'],
|
381
404
|
['DELETE', "broker/rest/domains/#{domain_id}/applications/#{app_id}", 'delete'],
|
382
405
|
(['LIST_MEMBERS', "domains/#{domain_id}/apps/#{app_id}/members", 'get'] if example_allows_members?),
|
406
|
+
['UPDATE', "broker/rest/domain/#{domain_id}/application/#{app_id}", 'put'],
|
407
|
+
['LIST_DEPLOYMENTS', "broker/rest/domain/#{domain_id}/application/#{app_id}/deployments", 'get' ],
|
408
|
+
['UPDATE_DEPLOYMENTS', "broker/rest/domain/#{domain_id}/application/#{app_id}/deployments", 'post' ],
|
409
|
+
['ACTIVATE', "broker/rest/domain/#{domain_id}/application/#{app_id}/events", 'post'],
|
410
|
+
['DEPLOY', "broker/rest/domain/#{domain_id}/application/#{app_id}/deployments", 'post']
|
383
411
|
].compact
|
384
412
|
end
|
385
413
|
|
@@ -503,8 +531,8 @@ module RHC::Rest::Mock
|
|
503
531
|
end
|
504
532
|
end
|
505
533
|
@domains = []
|
506
|
-
@user = MockRestUser.new(
|
507
|
-
@api = MockRestApi.new(
|
534
|
+
@user = MockRestUser.new(self, config.username)
|
535
|
+
@api = MockRestApi.new(self, config)
|
508
536
|
@version = version
|
509
537
|
end
|
510
538
|
|
@@ -611,7 +639,8 @@ module RHC::Rest::Mock
|
|
611
639
|
@login = login
|
612
640
|
@keys = [
|
613
641
|
MockRestKey.new(client, 'mockkey1', 'ssh-rsa', 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDNK8xT3O+kSltmCMsSqBfAgheB3YFJ9Y0ESJnFjFASVxH70AcCQAgdQSD/r31+atYShJdP7f0AMWiQUTw2tK434XSylnZWEyIR0V+j+cyOPdVQlns6D5gPOnOtweFF0o18YulwCOK8Q1H28GK8qyWhLe0FcMmxtKbbQgaVRvQdXZz4ThzutCJOyJm9xVb93+fatvwZW76oLLvfFJcJSOK2sgW7tJM2A83bm4mwixFDF7wO/+C9WA+PgPKJUIjvy1gZjBhRB+3b58vLOnYhPOgMNruJwzB+wJ3pg8tLJEjxSbHyyoi6OqMBs4BVV7LdzvwTDxEjcgtHVvaVNXgO5iRX'),
|
614
|
-
MockRestKey.new(client, 'mockkey2', 'ssh-dsa', 'AAAAB3NzaC1kc3MAAACBAPaaFj6Xjrjd8Dc4AAkJe0HigqaXMxj/87xHoV+nPgerHIceJWhPUWdW40lSASrgpAV9Eq4zzD+L19kgYdbMw0vSX5Cj3XtNOsow9MmMxFsYjTxCv4eSs/rLdGPaYZ5GVRPDu8tN42Bm8lj5o+ky3HzwW+mkQMZwcADQIgqtn6QhAAAAFQCirDfIMf/JoMOFf8CTnsTKWw/0zwAAAIAIQp6t2sLIp1d2TBfd/qLjOJA10rPADcnhBzWB/cd/oFJ8a/2nmxeSPR5Ov18T6itWqbKwvZw2UC0MrXoYbgcfVNP/ym1bCd9rB5hu1sg8WO4JIxA/47PZooT6PwTKVxHuENEzQyJL2o6ZJq+wuV0taLvm6IaM5TAZuEJ2p4TC/gAAAIBpLcVXZREa7XLY55nyidt/+UC+PxpjhPHOHbzL1OvWEaumN4wcJk/JZPppgXX9+WDkTm1SD891U0cXnGMTP0OZOHkOUHF2ZcfUe7p9kX4WjHs0OccoxV0Lny6MC4DjalJyaaEbijJHSUX3QlLcBOlPHJWpEpvWQ9P8AN4PokiGzA==')
|
642
|
+
MockRestKey.new(client, 'mockkey2', 'ssh-dsa', 'AAAAB3NzaC1kc3MAAACBAPaaFj6Xjrjd8Dc4AAkJe0HigqaXMxj/87xHoV+nPgerHIceJWhPUWdW40lSASrgpAV9Eq4zzD+L19kgYdbMw0vSX5Cj3XtNOsow9MmMxFsYjTxCv4eSs/rLdGPaYZ5GVRPDu8tN42Bm8lj5o+ky3HzwW+mkQMZwcADQIgqtn6QhAAAAFQCirDfIMf/JoMOFf8CTnsTKWw/0zwAAAIAIQp6t2sLIp1d2TBfd/qLjOJA10rPADcnhBzWB/cd/oFJ8a/2nmxeSPR5Ov18T6itWqbKwvZw2UC0MrXoYbgcfVNP/ym1bCd9rB5hu1sg8WO4JIxA/47PZooT6PwTKVxHuENEzQyJL2o6ZJq+wuV0taLvm6IaM5TAZuEJ2p4TC/gAAAIBpLcVXZREa7XLY55nyidt/+UC+PxpjhPHOHbzL1OvWEaumN4wcJk/JZPppgXX9+WDkTm1SD891U0cXnGMTP0OZOHkOUHF2ZcfUe7p9kX4WjHs0OccoxV0Lny6MC4DjalJyaaEbijJHSUX3QlLcBOlPHJWpEpvWQ9P8AN4PokiGzA=='),
|
643
|
+
MockRestKey.new(client, 'mockkey3', 'krb5-principal', 'mockuser@mockdomain')
|
615
644
|
]
|
616
645
|
end
|
617
646
|
|
@@ -738,6 +767,8 @@ module RHC::Rest::Mock
|
|
738
767
|
@aliases = []
|
739
768
|
@environment_variables = environment_variables || []
|
740
769
|
@gear_profile = gear_profile
|
770
|
+
@auto_deploy = true
|
771
|
+
@keep_deployments = 1
|
741
772
|
if scale
|
742
773
|
@scalable = true
|
743
774
|
end
|
@@ -863,6 +894,34 @@ module RHC::Rest::Mock
|
|
863
894
|
(@members ||= []) << member
|
864
895
|
self
|
865
896
|
end
|
897
|
+
|
898
|
+
def configure(options={})
|
899
|
+
options.each {|key,value| self.instance_variable_set("@#{key.to_s}", value)}
|
900
|
+
end
|
901
|
+
|
902
|
+
def auto_deploy
|
903
|
+
@auto_deploy || false
|
904
|
+
end
|
905
|
+
|
906
|
+
def keep_deployments
|
907
|
+
@keep_deployments
|
908
|
+
end
|
909
|
+
|
910
|
+
def deployments
|
911
|
+
base_time1 = Time.local(2000,1,1,1,0,0).strftime('%Y-%m-%dT%H:%M:%S%z')
|
912
|
+
base_time2 = Time.local(2000,1,1,2,0,0).strftime('%Y-%m-%dT%H:%M:%S%z')
|
913
|
+
base_time3 = Time.local(2000,1,1,3,0,0).strftime('%Y-%m-%dT%H:%M:%S%z')
|
914
|
+
base_time4 = Time.local(2000,1,1,4,0,0).strftime('%Y-%m-%dT%H:%M:%S%z')
|
915
|
+
base_time5 = Time.local(2000,1,1,5,0,0).strftime('%Y-%m-%dT%H:%M:%S%z')
|
916
|
+
base_time6 = Time.local(2000,1,1,6,0,0).strftime('%Y-%m-%dT%H:%M:%S%z')
|
917
|
+
[
|
918
|
+
MockRestDeployment.new(self, '0000001', 'master', '0000001', nil, false, base_time1, false, [base_time1]),
|
919
|
+
MockRestDeployment.new(self, '0000002', 'master', '0000002', nil, false, base_time2, false, [base_time2, base_time6]),
|
920
|
+
MockRestDeployment.new(self, '0000003', 'master', '0000003', nil, false, base_time3, false, [base_time3, base_time5]),
|
921
|
+
MockRestDeployment.new(self, '0000004', 'master', '0000004', nil, false, base_time4, false, [base_time4]),
|
922
|
+
MockRestDeployment.new(self, '0000005', 'master', '0000005', nil, false, base_time5, false, [base_time5]),
|
923
|
+
]
|
924
|
+
end
|
866
925
|
end
|
867
926
|
|
868
927
|
class MockRestCartridge < RHC::Rest::Cartridge
|
@@ -935,5 +994,31 @@ module RHC::Rest::Mock
|
|
935
994
|
@content = content
|
936
995
|
end
|
937
996
|
end
|
997
|
+
|
998
|
+
class MockRestDeployment < RHC::Rest::Deployment
|
999
|
+
def initialize(client, id, ref, sha1, artifact_url, hot_deploy, created_at, force_clean_build, activations)
|
1000
|
+
super({}, client)
|
1001
|
+
@id = id
|
1002
|
+
@ref = ref
|
1003
|
+
@sha1 = sha1
|
1004
|
+
@artifact_url = artifact_url
|
1005
|
+
@hot_deploy = hot_deploy
|
1006
|
+
@created_at = created_at
|
1007
|
+
@force_clean_build = force_clean_build
|
1008
|
+
@activations = activations
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
def activations
|
1012
|
+
@activations.map{|activation| MockRestActivation.new(client, RHC::Helpers.datetime_rfc3339(activation))}.sort
|
1013
|
+
end
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
|
1017
|
+
class MockRestActivation < RHC::Rest::Activation
|
1018
|
+
def initialize(client, created_at)
|
1019
|
+
super({}, client)
|
1020
|
+
@created_at = created_at
|
1021
|
+
end
|
1022
|
+
end
|
938
1023
|
end
|
939
1024
|
|
data/lib/rhc/ssh_helpers.rb
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
|
18
18
|
require 'net/ssh'
|
19
19
|
require 'rhc/vendor/sshkey'
|
20
|
+
require 'httpclient'
|
20
21
|
|
21
22
|
module RHC
|
22
23
|
module SSHHelpers
|
@@ -34,11 +35,11 @@ module RHC
|
|
34
35
|
out = nil
|
35
36
|
|
36
37
|
Net::SSH::Multi.start(
|
37
|
-
:concurrent_connections => @opts[:limit],
|
38
|
-
:on_error => lambda{ |server| $stderr.puts "Unable to connect to gear #{server}" }
|
38
|
+
:concurrent_connections => @opts[:limit],
|
39
|
+
:on_error => lambda{ |server| $stderr.puts RHC::Helpers.color("Unable to connect to gear #{server}", :red) }
|
39
40
|
) do |session|
|
40
|
-
|
41
|
-
@over.each do |item|
|
41
|
+
|
42
|
+
@over.each do |item|
|
42
43
|
case item
|
43
44
|
when RHC::Rest::GearGroup
|
44
45
|
item.gears.each do |gear|
|
@@ -47,7 +48,7 @@ module RHC
|
|
47
48
|
#when RHC::Rest::Gear
|
48
49
|
# session.use ssh_host_for(item), :properties => {:gear => item}
|
49
50
|
#end
|
50
|
-
else
|
51
|
+
else
|
51
52
|
raise "Cannot establish an SSH session to this type"
|
52
53
|
end
|
53
54
|
end
|
@@ -59,7 +60,7 @@ module RHC
|
|
59
60
|
}
|
60
61
|
when @opts[:as] == :table
|
61
62
|
out = []
|
62
|
-
lambda { |ch, dest, data|
|
63
|
+
lambda { |ch, dest, data|
|
63
64
|
label = label_for(ch)
|
64
65
|
data.chomp.each_line do |line|
|
65
66
|
row = out.find{ |row| row[0] == label } || (out << [label, []])[-1]
|
@@ -67,7 +68,7 @@ module RHC
|
|
67
68
|
end
|
68
69
|
}
|
69
70
|
when @opts[:as] == :gear
|
70
|
-
lambda { |ch, dest, data| (ch.connection.properties[:gear]['data'] ||= "") << data }
|
71
|
+
lambda { |ch, dest, data| (ch.connection.properties[:gear]['data'] ||= "") << data }
|
71
72
|
else
|
72
73
|
width = 0
|
73
74
|
lambda { |ch, dest, data|
|
@@ -111,7 +112,7 @@ module RHC
|
|
111
112
|
end
|
112
113
|
|
113
114
|
def label_for(channel)
|
114
|
-
channel.properties[:label] ||=
|
115
|
+
channel.properties[:label] ||=
|
115
116
|
begin
|
116
117
|
group = channel.connection.properties[:group]
|
117
118
|
"#{key_for(channel)} #{group.cartridges.map{ |c| c['name'] }.join('+')}"
|
@@ -123,12 +124,12 @@ module RHC
|
|
123
124
|
end
|
124
125
|
|
125
126
|
def requires_ssh_multi!
|
126
|
-
begin
|
127
|
-
require 'net/ssh/multi'
|
127
|
+
begin
|
128
|
+
require 'net/ssh/multi'
|
128
129
|
rescue LoadError
|
129
130
|
raise RHC::OperationNotSupportedException, "You must install Net::SSH::Multi to use the --gears option. Most systems: 'gem install net-ssh-multi'"
|
130
131
|
end
|
131
|
-
end
|
132
|
+
end
|
132
133
|
end
|
133
134
|
|
134
135
|
def run_on_gears(command, gears, opts={}, &block)
|
@@ -153,6 +154,9 @@ module RHC
|
|
153
154
|
# host - The String of the remote hostname to ssh to.
|
154
155
|
# username - The String username of the remote user to ssh as.
|
155
156
|
# command - The String command to run on the remote host.
|
157
|
+
# compression - Use compression in ssh, set to false if sending files.
|
158
|
+
# request_pty - Request for pty, set to false when pipe a file.
|
159
|
+
# block - Will yield this block and send the channel if provided.
|
156
160
|
#
|
157
161
|
# Examples
|
158
162
|
#
|
@@ -162,29 +166,86 @@ module RHC
|
|
162
166
|
# # => true
|
163
167
|
#
|
164
168
|
# Returns true on success
|
165
|
-
def ssh_ruby(host, username, command)
|
169
|
+
def ssh_ruby(host, username, command, compression=false, request_pty=false, &block)
|
166
170
|
debug "Opening Net::SSH connection to #{host}, #{username}, #{command}"
|
167
|
-
|
171
|
+
exit_status = 0
|
172
|
+
Net::SSH.start(host, username, :compression => compression) do |session|
|
168
173
|
#:nocov:
|
169
|
-
session.open_channel do |channel|
|
170
|
-
|
171
|
-
|
174
|
+
channel = session.open_channel do |channel|
|
175
|
+
if request_pty
|
176
|
+
channel.request_pty do |ch, success|
|
177
|
+
say "pty could not be obtained" unless success
|
178
|
+
end
|
172
179
|
end
|
173
|
-
|
174
|
-
|
175
|
-
|
180
|
+
channel.exec(command) do |ch, success|
|
181
|
+
channel.on_data do |ch, data|
|
182
|
+
print data
|
183
|
+
end
|
184
|
+
channel.on_extended_data do |ch, type, data|
|
185
|
+
print data
|
186
|
+
end
|
187
|
+
channel.on_close do |ch|
|
188
|
+
debug "Terminating ... "
|
189
|
+
end
|
190
|
+
channel.on_request("exit-status") do |ch, data|
|
191
|
+
exit_status = data.read_long
|
192
|
+
end
|
193
|
+
yield channel if block_given?
|
194
|
+
channel.eof!
|
176
195
|
end
|
177
|
-
channel.exec command
|
178
196
|
end
|
179
197
|
session.loop
|
180
198
|
#:nocov:
|
181
199
|
end
|
200
|
+
raise RHC::SSHCommandFailed.new(exit_status) if exit_status != 0
|
182
201
|
rescue Errno::ECONNREFUSED => e
|
202
|
+
debug_error e
|
183
203
|
raise RHC::SSHConnectionRefused.new(host, username)
|
204
|
+
rescue Net::SSH::AuthenticationFailed => e
|
205
|
+
debug_error e
|
206
|
+
raise RHC::SSHAuthenticationFailed.new(host, username)
|
184
207
|
rescue SocketError => e
|
208
|
+
debug_error e
|
185
209
|
raise RHC::ConnectionFailed, "The connection to #{host} failed: #{e.message}"
|
186
210
|
end
|
187
211
|
|
212
|
+
|
213
|
+
# Public: Run ssh command on remote host and pipe the specified
|
214
|
+
# file contents to the command input
|
215
|
+
#
|
216
|
+
# host - The String of the remote hostname to ssh to.
|
217
|
+
# username - The String username of the remote user to ssh as.
|
218
|
+
# command - The String command to run on the remote host.
|
219
|
+
# filename - The String path to file to send.
|
220
|
+
#
|
221
|
+
def ssh_send_file_ruby(host, username, command, filename)
|
222
|
+
filename = File.expand_path(filename)
|
223
|
+
ssh_ruby(host, username, command) do |channel|
|
224
|
+
File.open(filename, 'rb') do |file|
|
225
|
+
file.chunk(1024) do |chunk|
|
226
|
+
channel.send_data chunk
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# Public: Run ssh command on remote host and pipe the specified
|
233
|
+
# url contents to the command input
|
234
|
+
#
|
235
|
+
# host - The String of the remote hostname to ssh to.
|
236
|
+
# username - The String username of the remote user to ssh as.
|
237
|
+
# command - The String command to run on the remote host.
|
238
|
+
# content_url - The url with the content to pipe to command.
|
239
|
+
#
|
240
|
+
def ssh_send_url_ruby(host, username, command, content_url)
|
241
|
+
content_url = URI.parse(URI.encode(content_url.to_s))
|
242
|
+
ssh_ruby(host, username, command) do |channel|
|
243
|
+
HTTPClient.new.get_content(content_url) do |chunk|
|
244
|
+
channel.send_data chunk
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
188
249
|
# Public: Generate an SSH key and store it in ~/.ssh/id_rsa
|
189
250
|
#
|
190
251
|
# type - The String type RSA or DSS.
|
@@ -269,7 +330,7 @@ module RHC
|
|
269
330
|
raise ::RHC::KeyFileAccessDeniedException.new("Access denied to '#{key}'.")
|
270
331
|
end
|
271
332
|
end
|
272
|
-
|
333
|
+
|
273
334
|
def ssh_key_triple_for_default_key
|
274
335
|
ssh_key_triple_for(RHC::Config.ssh_pub_key_file_path)
|
275
336
|
end
|
data/lib/rhc/wizard.rb
CHANGED
@@ -29,7 +29,11 @@ module RhcExecutionHelper
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def a_web_cartridge
|
32
|
-
'
|
32
|
+
if ENV['RHC_TARGET'] == 'rhel' || !File.exist?("/etc/fedora-release")
|
33
|
+
'php-5.3'
|
34
|
+
else
|
35
|
+
'php-5.5'
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
35
39
|
def rhc(*args)
|
@@ -38,25 +42,32 @@ module RhcExecutionHelper
|
|
38
42
|
if user = opts[:as]
|
39
43
|
args << '--rhlogin'
|
40
44
|
args << user.login
|
41
|
-
if user.
|
45
|
+
if user.attributes.has_key? :token
|
42
46
|
args << '--token'
|
43
|
-
args << user.token
|
44
|
-
elsif user.
|
47
|
+
args << user.attributes[:token]
|
48
|
+
elsif user.attributes.has_key? :password
|
45
49
|
args << '--password'
|
46
|
-
args << user.password
|
50
|
+
args << user.attributes[:password]
|
47
51
|
end
|
48
52
|
elsif !server_supports_sessions?
|
49
53
|
args << '--password'
|
50
54
|
args << ENV['TEST_PASSWORD']
|
51
55
|
end
|
56
|
+
oldenv = if opts[:env]
|
57
|
+
old = ENV.to_hash
|
58
|
+
ENV.update(opts[:env])
|
59
|
+
old
|
60
|
+
end
|
52
61
|
execute_command(args.unshift(rhc_executable), opts[:with])
|
62
|
+
ensure
|
63
|
+
ENV.replace(oldenv) if oldenv
|
53
64
|
end
|
54
65
|
|
55
66
|
def execute_command(args, stdin="", tty=true)
|
56
67
|
stdin = stdin.join("\n") if stdin.is_a? Array
|
57
68
|
stdout, stderr =
|
58
69
|
if debug?
|
59
|
-
[debug, debug].map{ |t| RHC::Helpers::StringTee.new(t) }
|
70
|
+
[debug, debug].map{ |t| RHC::Helpers::StringTee.new(t) }
|
60
71
|
else
|
61
72
|
[StringIO.new, StringIO.new]
|
62
73
|
end
|
@@ -111,6 +122,7 @@ module RhcExecutionHelper
|
|
111
122
|
def other_users
|
112
123
|
$other_users ||= begin
|
113
124
|
(ENV['TEST_OTHER_USERS'] || "other1:a,other2:b,other3:c,other4:d").split(',').map{ |s| s.split(':') }.inject({}) do |h, (u, p)|
|
125
|
+
register_user(u,p) unless ENV['REGISTER_USER'].nil?
|
114
126
|
h[u] = base_client(u, p).user
|
115
127
|
h[u].attributes[:password] = p
|
116
128
|
h
|
@@ -123,36 +135,51 @@ module RhcExecutionHelper
|
|
123
135
|
object.members.length.should == 1
|
124
136
|
end
|
125
137
|
|
126
|
-
def has_an_application
|
138
|
+
def has_an_application(for_user=nil)
|
139
|
+
c = for_user ? for_user.client : client
|
127
140
|
debug.puts "Creating or reusing an app" if debug?
|
128
|
-
apps =
|
141
|
+
apps = c.applications
|
129
142
|
apps.first or begin
|
130
|
-
domain = has_a_domain
|
143
|
+
domain = has_a_domain(for_user)
|
131
144
|
debug.puts " creating a new application" if debug?
|
132
|
-
|
145
|
+
c.domains.first.add_application("test#{random}", :cartridges => [a_web_cartridge])
|
133
146
|
end
|
134
147
|
end
|
135
148
|
|
136
|
-
def has_a_domain
|
149
|
+
def has_a_domain(for_user=nil)
|
150
|
+
c = for_user ? for_user.client : client
|
137
151
|
debug.puts "Creating or reusing a domain" if debug?
|
138
|
-
domain =
|
152
|
+
domain = c.domains.first or begin
|
139
153
|
debug.puts " creating a new domain" if debug?
|
140
|
-
|
154
|
+
c.add_domain("test#{random}")
|
141
155
|
end
|
142
156
|
end
|
143
157
|
|
144
158
|
def setup_args(opts={})
|
159
|
+
c = opts[:client] || client
|
145
160
|
args = []
|
146
161
|
args << 'yes' if (ENV['TEST_INSECURE'] == '1' || false)
|
147
|
-
args << ENV['TEST_USERNAME']
|
148
|
-
args << ENV['TEST_PASSWORD']
|
149
|
-
args << 'yes' if server_supports_sessions?
|
162
|
+
args << (opts[:login] || ENV['TEST_USERNAME'])
|
163
|
+
args << (opts[:password] || ENV['TEST_PASSWORD'])
|
164
|
+
args << 'yes' if server_supports_sessions?(c)
|
150
165
|
args << 'yes' # generate a key, temp dir will never have one
|
151
|
-
args << ENV['TEST_USERNAME'] if (
|
152
|
-
args << "d#{random}" if (
|
166
|
+
args << (opts[:login] || ENV['TEST_USERNAME']) if (c.find_key('default').present? rescue false) # same key name as username
|
167
|
+
args << (opts[:domain_name] || "d#{random}") if (c.domains.empty? rescue true)
|
153
168
|
args
|
154
169
|
end
|
155
170
|
|
171
|
+
def has_local_ssh_key(user)
|
172
|
+
with_environment(user) do
|
173
|
+
r = rhc :setup, :with => setup_args(:login => user.login, :password => user.attributes[:password], :domain_name => "\n")
|
174
|
+
r.status.should == 0
|
175
|
+
user
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def ssh_exec_for_env
|
180
|
+
@environment[:ssh_exec]
|
181
|
+
end
|
182
|
+
|
156
183
|
def use_clean_config
|
157
184
|
environment
|
158
185
|
FileUtils.rm_rf(File.join(@environment[:dir], ".openshift"))
|
@@ -189,8 +216,22 @@ module RhcExecutionHelper
|
|
189
216
|
@environment[:id]
|
190
217
|
end
|
191
218
|
|
192
|
-
def server_supports_sessions?
|
193
|
-
@environment &&
|
219
|
+
def server_supports_sessions?(c=client)
|
220
|
+
@environment && c.supports_sessions?
|
221
|
+
end
|
222
|
+
|
223
|
+
def with_environment(user, &block)
|
224
|
+
previous = @environment
|
225
|
+
@environment, @client = nil
|
226
|
+
env = ENV.to_hash
|
227
|
+
ENV['TEST_RANDOM_USER'] = nil
|
228
|
+
ENV['TEST_USERNAME'] = user.login
|
229
|
+
ENV['TEST_PASSWORD'] = user.attributes[:password]
|
230
|
+
environment("custom_#{user.login}")
|
231
|
+
yield
|
232
|
+
ensure
|
233
|
+
@environment = previous
|
234
|
+
ENV.replace(env)
|
194
235
|
end
|
195
236
|
|
196
237
|
private
|
@@ -209,7 +250,7 @@ module RhcExecutionHelper
|
|
209
250
|
update_env(e)
|
210
251
|
|
211
252
|
dir = Dir.mktmpdir('rhc_features_test')
|
212
|
-
at_exit{ FileUtils.rm_rf(dir) }
|
253
|
+
at_exit{ FileUtils.rm_rf(dir) } unless ENV['RHC_DEBUG_DIRS']
|
213
254
|
Dir.chdir(dir)
|
214
255
|
|
215
256
|
@client = e[:client]
|
@@ -231,26 +272,52 @@ module RhcExecutionHelper
|
|
231
272
|
ENV['TEST_USERNAME'] or raise "No TEST_USERNAME set"
|
232
273
|
ENV['TEST_PASSWORD'] or raise "No TEST_PASSWORD set"
|
233
274
|
end
|
275
|
+
|
276
|
+
register_user(ENV['TEST_USERNAME'],ENV['TEST_PASSWORD']) unless ENV['REGISTER_USER'].nil?
|
234
277
|
ENV['GIT_SSH'] = config[:ssh_exec]
|
235
278
|
end
|
279
|
+
|
280
|
+
def register_user(user,password)
|
281
|
+
if File.exists?("/etc/openshift/plugins.d/openshift-origin-auth-mongo.conf")
|
282
|
+
command = "bash -c 'unset GEM_HOME; unset GEM_PATH; oo-register-user -l admin -p admin --username #{user} --userpass #{password}'"
|
283
|
+
if Object.const_defined?('Bundler')
|
284
|
+
Bundler::with_clean_env do
|
285
|
+
system command
|
286
|
+
end
|
287
|
+
else
|
288
|
+
system command
|
289
|
+
end
|
290
|
+
elsif File.exists?("/etc/openshift/plugins.d/openshift-origin-auth-remote-user.conf")
|
291
|
+
system "/usr/bin/htpasswd -b /etc/openshift/htpasswd #{user} #{password}"
|
292
|
+
else
|
293
|
+
#ignore
|
294
|
+
print "Unknown auth plugin. Not registering user #{user}/#{password}."
|
295
|
+
print "Modify #{__FILE__}:239 if user registration is required."
|
296
|
+
cmd = nil
|
297
|
+
end
|
298
|
+
end
|
236
299
|
end
|
237
300
|
|
238
301
|
module Environments
|
239
302
|
def self.get(id, &block)
|
240
303
|
(@environments ||= {})[id] ||= begin
|
241
304
|
dir = Dir.mktmpdir('rhc_features')
|
242
|
-
at_exit{ FileUtils.rm_rf(dir) }
|
305
|
+
at_exit{ FileUtils.rm_rf(dir) } unless ENV['RHC_DEBUG_DIRS']
|
243
306
|
id = Random.rand(1000000)
|
244
|
-
ssh_exec =
|
245
|
-
IO.write(ssh_exec, "#!/bin/sh\nssh -o StrictHostKeyChecking=no -i #{dir}/.ssh/id_rsa \"$@\"")
|
246
|
-
FileUtils.chmod("u+x", ssh_exec)
|
307
|
+
ssh_exec = create_ssh_exec(dir)
|
247
308
|
yield if block_given?
|
248
309
|
{:dir => dir, :id => id, :ssh_exec => ssh_exec}
|
249
310
|
end
|
250
311
|
end
|
312
|
+
def self.create_ssh_exec(dir, for_user=nil)
|
313
|
+
ssh_exec = File.join(dir, "ssh_exec#{for_user ? "_#{for_user}" : ""}")
|
314
|
+
IO.write(ssh_exec, "#!/bin/sh\nssh -o StrictHostKeyChecking=no -i #{dir}/.ssh/id_rsa \"$@\"")
|
315
|
+
FileUtils.chmod("u+x", ssh_exec)
|
316
|
+
ssh_exec
|
317
|
+
end
|
251
318
|
end
|
252
319
|
|
253
320
|
RSpec.configure do |config|
|
254
321
|
config.include(RhcExecutionHelper)
|
255
322
|
config.extend(RhcExecutionHelper)
|
256
|
-
end
|
323
|
+
end
|