startapp 0.1.6
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.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +95 -0
- data/Rakefile +6 -0
- data/autocomplete/rhc_bash +1672 -0
- data/bin/app +37 -0
- data/conf/express.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +191 -0
- data/features/deployments_feature.rb +129 -0
- data/features/domains_feature.rb +58 -0
- data/features/keys_feature.rb +37 -0
- data/features/members_feature.rb +166 -0
- data/lib/rhc/auth/basic.rb +64 -0
- data/lib/rhc/auth/token.rb +102 -0
- data/lib/rhc/auth/token_store.rb +53 -0
- data/lib/rhc/auth.rb +5 -0
- data/lib/rhc/autocomplete.rb +66 -0
- data/lib/rhc/autocomplete_templates/bash.erb +39 -0
- data/lib/rhc/cartridge_helpers.rb +118 -0
- data/lib/rhc/cli.rb +40 -0
- data/lib/rhc/command_runner.rb +185 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +726 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +115 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +329 -0
- data/lib/rhc/commands/clone.rb +66 -0
- data/lib/rhc/commands/configure.rb +20 -0
- data/lib/rhc/commands/create.rb +100 -0
- data/lib/rhc/commands/delete.rb +19 -0
- data/lib/rhc/commands/deploy.rb +32 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +172 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/force_stop.rb +17 -0
- data/lib/rhc/commands/git_clone.rb +34 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/logs.rb +21 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/reload.rb +17 -0
- data/lib/rhc/commands/restart.rb +17 -0
- data/lib/rhc/commands/scp.rb +54 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -0
- data/lib/rhc/commands/show.rb +43 -0
- data/lib/rhc/commands/snapshot.rb +137 -0
- data/lib/rhc/commands/ssh.rb +51 -0
- data/lib/rhc/commands/sshkey.rb +97 -0
- data/lib/rhc/commands/start.rb +17 -0
- data/lib/rhc/commands/stop.rb +17 -0
- data/lib/rhc/commands/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands/tidy.rb +17 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +321 -0
- data/lib/rhc/context_helper.rb +121 -0
- data/lib/rhc/core_ext.rb +202 -0
- data/lib/rhc/coverage_helper.rb +33 -0
- data/lib/rhc/deployment_helpers.rb +111 -0
- data/lib/rhc/exceptions.rb +256 -0
- data/lib/rhc/git_helpers.rb +106 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +481 -0
- data/lib/rhc/highline_extensions.rb +479 -0
- data/lib/rhc/json.rb +51 -0
- data/lib/rhc/output_helpers.rb +260 -0
- data/lib/rhc/rest/activation.rb +11 -0
- data/lib/rhc/rest/alias.rb +42 -0
- data/lib/rhc/rest/api.rb +87 -0
- data/lib/rhc/rest/application.rb +348 -0
- data/lib/rhc/rest/attributes.rb +36 -0
- data/lib/rhc/rest/authorization.rb +8 -0
- data/lib/rhc/rest/base.rb +79 -0
- data/lib/rhc/rest/cartridge.rb +162 -0
- data/lib/rhc/rest/client.rb +650 -0
- data/lib/rhc/rest/deployment.rb +18 -0
- data/lib/rhc/rest/domain.rb +98 -0
- data/lib/rhc/rest/environment_variable.rb +15 -0
- data/lib/rhc/rest/gear_group.rb +16 -0
- data/lib/rhc/rest/httpclient.rb +145 -0
- data/lib/rhc/rest/key.rb +44 -0
- data/lib/rhc/rest/membership.rb +105 -0
- data/lib/rhc/rest/mock.rb +1042 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/scp_helpers.rb +27 -0
- data/lib/rhc/ssh_helpers.rb +380 -0
- data/lib/rhc/tar_gz.rb +51 -0
- data/lib/rhc/usage_templates/command_help.erb +51 -0
- data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
- data/lib/rhc/usage_templates/help.erb +61 -0
- data/lib/rhc/usage_templates/missing_help.erb +1 -0
- data/lib/rhc/usage_templates/options_help.erb +12 -0
- data/lib/rhc/vendor/okjson.rb +600 -0
- data/lib/rhc/vendor/parseconfig.rb +178 -0
- data/lib/rhc/vendor/sshkey.rb +253 -0
- data/lib/rhc/vendor/zliby.rb +628 -0
- data/lib/rhc/version.rb +5 -0
- data/lib/rhc/wizard.rb +637 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +82 -0
- data/spec/direct_execution_helper.rb +339 -0
- data/spec/keys/example.pem +23 -0
- data/spec/keys/example_private.pem +27 -0
- data/spec/keys/server.pem +19 -0
- data/spec/rest_spec_helper.rb +31 -0
- data/spec/rhc/assets/cert.crt +22 -0
- data/spec/rhc/assets/cert_key_rsa +27 -0
- data/spec/rhc/assets/empty.txt +0 -0
- data/spec/rhc/assets/env_vars.txt +7 -0
- data/spec/rhc/assets/env_vars_2.txt +1 -0
- data/spec/rhc/assets/foo.txt +1 -0
- data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
- data/spec/rhc/assets/targz_sample.tar.gz +0 -0
- data/spec/rhc/auth_spec.rb +442 -0
- data/spec/rhc/cli_spec.rb +186 -0
- data/spec/rhc/command_spec.rb +435 -0
- data/spec/rhc/commands/account_spec.rb +42 -0
- data/spec/rhc/commands/alias_spec.rb +333 -0
- data/spec/rhc/commands/app_spec.rb +777 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +157 -0
- data/spec/rhc/commands/cartridge_spec.rb +665 -0
- data/spec/rhc/commands/clone_spec.rb +41 -0
- data/spec/rhc/commands/deployment_spec.rb +327 -0
- data/spec/rhc/commands/domain_spec.rb +401 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +102 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +247 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -0
- data/spec/rhc/commands/scp_spec.rb +77 -0
- data/spec/rhc/commands/server_spec.rb +69 -0
- data/spec/rhc/commands/setup_spec.rb +118 -0
- data/spec/rhc/commands/snapshot_spec.rb +179 -0
- data/spec/rhc/commands/ssh_spec.rb +163 -0
- data/spec/rhc/commands/sshkey_spec.rb +188 -0
- data/spec/rhc/commands/tail_spec.rb +81 -0
- data/spec/rhc/commands/threaddump_spec.rb +84 -0
- data/spec/rhc/config_spec.rb +407 -0
- data/spec/rhc/helpers_spec.rb +531 -0
- data/spec/rhc/highline_extensions_spec.rb +314 -0
- data/spec/rhc/json_spec.rb +30 -0
- data/spec/rhc/rest_application_spec.rb +258 -0
- data/spec/rhc/rest_client_spec.rb +752 -0
- data/spec/rhc/rest_spec.rb +740 -0
- data/spec/rhc/targz_spec.rb +55 -0
- data/spec/rhc/wizard_spec.rb +756 -0
- data/spec/spec_helper.rb +575 -0
- data/spec/wizard_spec_helper.rb +330 -0
- metadata +469 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rhc'
|
|
3
|
+
require 'rhc/ssh_helpers'
|
|
4
|
+
require 'rhc/cartridge_helpers'
|
|
5
|
+
require 'rhc/git_helpers'
|
|
6
|
+
require 'rhc/core_ext'
|
|
7
|
+
require 'rhc/config'
|
|
8
|
+
require 'rhc/rest/mock'
|
|
9
|
+
require 'date'
|
|
10
|
+
require 'resolv'
|
|
11
|
+
require 'ostruct'
|
|
12
|
+
|
|
13
|
+
class AllRhcHelpers
|
|
14
|
+
include RHC::Helpers
|
|
15
|
+
include RHC::SSHHelpers
|
|
16
|
+
include RHC::CartridgeHelpers
|
|
17
|
+
|
|
18
|
+
def config
|
|
19
|
+
@config ||= RHC::Config.new
|
|
20
|
+
end
|
|
21
|
+
def options
|
|
22
|
+
@options ||= OpenStruct.new(:server => nil)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe AllRhcHelpers do
|
|
27
|
+
before do
|
|
28
|
+
mock_terminal
|
|
29
|
+
user_config
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
its(:openshift_server) { should == 'broker.startapp.bg' }
|
|
33
|
+
its(:openshift_url) { should == 'https://broker.startapp.bg' }
|
|
34
|
+
|
|
35
|
+
it("should display slashes"){ subject.system_path('foo/bar').should == 'foo/bar' }
|
|
36
|
+
context "on windows" do
|
|
37
|
+
it("should display backslashes"){ with_constants({:ALT_SEPARATOR => '\\'}, File) { subject.system_path('foo/bar').should == 'foo\\bar' } }
|
|
38
|
+
it("should handle drives"){ with_constants({:ALT_SEPARATOR => '\\'}, File) { subject.system_path('C:/foo/bar').should == 'C:\\foo\\bar' } }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it("should pluralize many") { subject.pluralize(3, 'fish').should == '3 fishs' }
|
|
42
|
+
it("should not pluralize one") { subject.pluralize(1, 'fish').should == '1 fish' }
|
|
43
|
+
|
|
44
|
+
it("should decode json"){ subject.decode_json("{\"a\" : 1}").should == {'a' => 1} }
|
|
45
|
+
|
|
46
|
+
shared_examples_for "colorized output" do
|
|
47
|
+
it("should be colorized") do
|
|
48
|
+
message = "this is #{_color} -"
|
|
49
|
+
output = capture{ subject.send(method,message) }
|
|
50
|
+
output.should be_colorized(message,_color)
|
|
51
|
+
end
|
|
52
|
+
it("should return true"){ subject.send(method,'anything').should be_true }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context "success output" do
|
|
56
|
+
let(:_color){ :green }
|
|
57
|
+
let(:method){ :success }
|
|
58
|
+
it_should_behave_like "colorized output"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "warn output" do
|
|
62
|
+
let(:_color){ :yellow }
|
|
63
|
+
let(:method){ :warn }
|
|
64
|
+
it_should_behave_like "colorized output"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "info output" do
|
|
68
|
+
let(:_color){ :cyan }
|
|
69
|
+
let(:method){ :info }
|
|
70
|
+
it_should_behave_like "colorized output"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it("should invoke debug from debug_error"){ expect{ subject.debug_error(double(:class => "Mock", :message => 'msg', :backtrace => [])) }.to call(:debug).on($terminal).with("msg (Mock)\n ") }
|
|
74
|
+
|
|
75
|
+
it("should draw a table") do
|
|
76
|
+
subject.table([[10,2], [3,40]]) do |i|
|
|
77
|
+
i.map(&:to_s)
|
|
78
|
+
end.to_a.should == ['10 2','3 40']
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "error output" do
|
|
82
|
+
let(:_color){ :red }
|
|
83
|
+
let(:method){ :error }
|
|
84
|
+
it_should_behave_like "colorized output"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it("should output a table") do
|
|
88
|
+
subject.send(:format_no_info, 'test').to_a.should == ['This test has no information to show']
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should parse an RFC3339 date" do
|
|
92
|
+
d = subject.datetime_rfc3339('2012-06-24T20:48:20-04:00')
|
|
93
|
+
d.day.should == 24
|
|
94
|
+
d.month.should == 6
|
|
95
|
+
d.year.should == 2012
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe "#human_size" do
|
|
99
|
+
it{ subject.human_size(nil).should == 'unknown' }
|
|
100
|
+
it{ subject.human_size(1).should == '1 B' }
|
|
101
|
+
it{ subject.human_size(500).should == '500 B' }
|
|
102
|
+
it{ subject.human_size(1000).should == '1 KB' }
|
|
103
|
+
it{ subject.human_size(500000).should == '500 KB' }
|
|
104
|
+
it{ subject.human_size(1000*1000).should == '1 MB' }
|
|
105
|
+
it{ subject.human_size(1000*1000*1000).should == '1 GB' }
|
|
106
|
+
it{ subject.human_size(1000*1000*1000*1000).should == '1 TB' }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe "#distance_of_time_in_words" do
|
|
110
|
+
it{ subject.distance_of_time_in_words(0, 1).should == 'less than 1 minute' }
|
|
111
|
+
it{ subject.distance_of_time_in_words(0, 60).should == '1 minute' }
|
|
112
|
+
it{ subject.distance_of_time_in_words(0, 130).should == '2 minutes' }
|
|
113
|
+
it{ subject.distance_of_time_in_words(0, 50*60).should == 'about 1 hour' }
|
|
114
|
+
it{ subject.distance_of_time_in_words(0, 3*60*60).should == 'about 3 hours' }
|
|
115
|
+
it{ subject.distance_of_time_in_words(0, 25*60*60).should == 'about 1 day' }
|
|
116
|
+
it{ subject.distance_of_time_in_words(0, 3*24*60*60).should == '3 days' }
|
|
117
|
+
it{ subject.distance_of_time_in_words(0, 40*24*60*60).should == 'about 1 month' }
|
|
118
|
+
it{ subject.distance_of_time_in_words(0, 10*30*24*60*60).should == 'about 10 months' }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
context 'using the current time' do
|
|
122
|
+
let(:date){ Time.local(2008,1,2,1,1,0) }
|
|
123
|
+
let(:today){ Date.new(2008,1,2) }
|
|
124
|
+
before{ Date.stub(:today).and_return(today) }
|
|
125
|
+
|
|
126
|
+
let(:rfc3339){ '%Y-%m-%dT%H:%M:%S%z' }
|
|
127
|
+
it("should output the time for a date that is today") do
|
|
128
|
+
subject.date(date.strftime(rfc3339)).should =~ /^[0-9]/
|
|
129
|
+
end
|
|
130
|
+
it("should exclude the year for a date that is this year") do
|
|
131
|
+
subject.date(date.strftime(rfc3339)).should_not match(date.year.to_s)
|
|
132
|
+
end
|
|
133
|
+
it("should output the year for a date that is not this year") do
|
|
134
|
+
older = Date.today - 1*365
|
|
135
|
+
subject.date(older.strftime(rfc3339)).should match(older.year.to_s)
|
|
136
|
+
end
|
|
137
|
+
it("should handle invalid input") do
|
|
138
|
+
subject.date('Unknown date').should == 'Unknown date'
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context 'when the year is different' do
|
|
142
|
+
let(:today){ Date.new(2007,1,2) }
|
|
143
|
+
it{ subject.date(date.strftime(rfc3339)).should match(date.year.to_s) }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context 'when the year of the day is different' do
|
|
147
|
+
let(:today){ Date.new(2008,1,1) }
|
|
148
|
+
it{ subject.date(date.strftime(rfc3339)).should_not match(date.year.to_s) }
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context 'with LIBRA_SERVER environment variable' do
|
|
153
|
+
before do
|
|
154
|
+
ENV['LIBRA_SERVER'] = 'test.com'
|
|
155
|
+
user_config
|
|
156
|
+
end
|
|
157
|
+
its(:openshift_server) { should == 'test.com' }
|
|
158
|
+
its(:openshift_url) { should == 'https://test.com' }
|
|
159
|
+
after { ENV['LIBRA_SERVER'] = nil }
|
|
160
|
+
end
|
|
161
|
+
context 'with --server environment variable' do
|
|
162
|
+
before do
|
|
163
|
+
subject.options.server = "test.com"
|
|
164
|
+
end
|
|
165
|
+
its(:openshift_server) { should == 'test.com' }
|
|
166
|
+
its(:openshift_url) { should == 'https://test.com' }
|
|
167
|
+
after { ENV['LIBRA_SERVER'] = nil }
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context "without RHC::Config" do
|
|
171
|
+
subject do
|
|
172
|
+
Class.new(Object){ include RHC::Helpers }.new
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it("should raise on config"){ expect{ subject.config }.to raise_error }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
context "with a bad timeout value" do
|
|
179
|
+
context "on the command line" do
|
|
180
|
+
let(:arguments){ ['help', '--timeout=string'] }
|
|
181
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
182
|
+
it{ run_output.should match("invalid argument: --timeout=string") }
|
|
183
|
+
end
|
|
184
|
+
context "that is a negative integer" do
|
|
185
|
+
let(:arguments){ ['help', '--timeout=0'] }
|
|
186
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
187
|
+
it{ run_output.should match("must be a positive integer") }
|
|
188
|
+
end
|
|
189
|
+
context "via the config" do
|
|
190
|
+
before{ base_config{ |c, d| d.add 'timeout', 'string' } }
|
|
191
|
+
let(:arguments){ ['help'] }
|
|
192
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
193
|
+
it{ run_output.should match(/The configuration file.*invalid setting: invalid value for Integer/) }
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
context "with a valid client cert file" do
|
|
197
|
+
let(:arguments){ ['help', '--ssl-client-cert-file=spec/keys/example.pem'] }
|
|
198
|
+
it{ expect{ run }.to exit_with_code(0) }
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
context "with a missing client cert file" do
|
|
202
|
+
context "on the command line" do
|
|
203
|
+
let(:arguments){ ['help', '--ssl-client-cert-file=not_a_file'] }
|
|
204
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
205
|
+
it{ run_output.should match("The certificate 'not_a_file' cannot be loaded: No such") }
|
|
206
|
+
end
|
|
207
|
+
context "via the config" do
|
|
208
|
+
before{ base_config{ |c, d| d.add 'ssl_client_cert_file', 'not_a_file' } }
|
|
209
|
+
let(:arguments){ ['help'] }
|
|
210
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
211
|
+
it{ run_output.should match("The certificate 'not_a_file' cannot be loaded: No such") }
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context 'with a valid --ssl-version' do
|
|
216
|
+
let(:arguments){ ['help', '--ssl-version=sslv3'] }
|
|
217
|
+
|
|
218
|
+
context 'on an older version of HTTPClient' do
|
|
219
|
+
before{ HTTPClient::SSLConfig.stub(:method_defined?).with(:ssl_version).and_return(false) }
|
|
220
|
+
it('should print an error') { run_output.should =~ /You are using an older version of the httpclient.*--ssl-version/ }
|
|
221
|
+
it('should error out') { expect{ run }.to exit_with_code(1) }
|
|
222
|
+
end
|
|
223
|
+
context 'a newer version of HTTPClient' do
|
|
224
|
+
before{ HTTPClient::SSLConfig.stub(:method_defined?).with(:ssl_version).and_return(true) }
|
|
225
|
+
it('should not print an error') { run_output.should_not =~ /You are using an older version of the httpclient.*--ssl-version/ }
|
|
226
|
+
it('should error out') { expect{ run }.to exit_with_code(0) }
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context "with an invalid SSLVersion" do
|
|
231
|
+
context "on the command line" do
|
|
232
|
+
let(:arguments){ ['help', '--ssl-version=ssl'] }
|
|
233
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
234
|
+
it{ run_output.should match("The provided SSL version 'ssl' is not valid. Supported values: ") }
|
|
235
|
+
end
|
|
236
|
+
context "via the config" do
|
|
237
|
+
before{ base_config{ |c, d| d.add 'ssl_version', 'ssl' } }
|
|
238
|
+
let(:arguments){ ['help'] }
|
|
239
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
240
|
+
it{ run_output.should match("The provided SSL version 'ssl' is not valid. Supported values: ") }
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
context "with an valid ssl CA file" do
|
|
245
|
+
let(:arguments){ ['help', '--ssl-ca-file=spec/keys/example.pem'] }
|
|
246
|
+
it{ expect{ run }.to exit_with_code(0) }
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
context "with an invalid ssl CA file" do
|
|
250
|
+
let(:arguments){ ['help', '--ssl-ca-file=not_a_file'] }
|
|
251
|
+
it{ expect{ run }.to exit_with_code(1) }
|
|
252
|
+
it{ run_output.should match("The certificate 'not_a_file' cannot be loaded: No such file or directory ") }
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
context "#get_properties" do
|
|
256
|
+
it{ subject.send(:get_properties, double(:plan_id => 'free'), :plan_id).should == [[:plan_id, 'Free']] }
|
|
257
|
+
context "when an error is raised" do
|
|
258
|
+
let(:bar){ double.tap{ |s| s.should_receive(:foo).and_raise(::Exception) } }
|
|
259
|
+
it{ subject.send(:get_properties, bar, :foo).should == [[:foo, '<error>']] }
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
describe "#exec" do
|
|
264
|
+
it{ subject.send(:exec, 'echo foo').should == [0, "foo\n"] }
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context "Git Helpers" do
|
|
268
|
+
subject{ Class.new(Object){ include RHC::Helpers; include RHC::GitHelpers; def debug?; false; end }.new }
|
|
269
|
+
before{ subject.stub(:git_version){ raise "Fake Exception" } }
|
|
270
|
+
its(:has_git?) { should be_false }
|
|
271
|
+
|
|
272
|
+
context "without git" do
|
|
273
|
+
before{ subject.stub(:git_cmd){ "nonexistent_git" } }
|
|
274
|
+
its(:has_git?) { should be_false }
|
|
275
|
+
it { subject.git_config_get('key').should == nil }
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
context "git clone repo" do
|
|
280
|
+
let(:stdout){ 'fake git clone' }
|
|
281
|
+
let(:exit_status){ 0 }
|
|
282
|
+
let!(:spawn) do
|
|
283
|
+
out, err = stdout, stderr
|
|
284
|
+
Open4.should_receive(:spawn).and_return(exit_status) do |cmd, opts|
|
|
285
|
+
opts['stdout'] << out if out
|
|
286
|
+
opts['stderr'] << err if err
|
|
287
|
+
exit_status
|
|
288
|
+
end
|
|
289
|
+
true
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
it { capture{ subject.git_clone_repo("url", "repo").should == File.expand_path('repo') } }
|
|
293
|
+
it { capture_all{ subject.git_clone_repo("url", "repo") }.should match("fake git clone") }
|
|
294
|
+
|
|
295
|
+
context "does not succeed" do
|
|
296
|
+
let(:stderr){ 'fatal: error' }
|
|
297
|
+
let(:exit_status){ 1 }
|
|
298
|
+
|
|
299
|
+
it { capture{ expect{ subject.git_clone_repo("url", "repo") }.to raise_error(RHC::GitException) } }
|
|
300
|
+
it { capture_all{ subject.git_clone_repo("url", "repo") rescue nil }.should match("fake git clone") }
|
|
301
|
+
it { capture_all{ subject.git_clone_repo("url", "repo") rescue nil }.should match("fatal: error") }
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
context "directory is missing" do
|
|
305
|
+
let(:stderr){ "fatal: destination path 'foo' already exists and is not an empty directory." }
|
|
306
|
+
let(:exit_status){ 1 }
|
|
307
|
+
|
|
308
|
+
it { capture{ expect{ subject.git_clone_repo("url", "repo") }.to raise_error(RHC::GitDirectoryExists) } }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
context "permission denied" do
|
|
312
|
+
let(:stderr){ "Permission denied (publickey,gssapi-mic)." }
|
|
313
|
+
let(:exit_status){ 1 }
|
|
314
|
+
|
|
315
|
+
it { capture{ expect{ subject.git_clone_repo("url", "repo") }.to raise_error(RHC::GitPermissionDenied) } }
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
context "SSH Key Helpers" do
|
|
321
|
+
it "should generate an ssh key then return nil when it tries to create another" do
|
|
322
|
+
FakeFS do
|
|
323
|
+
FakeFS::FileSystem.clear
|
|
324
|
+
subject.generate_ssh_key_ruby.should match("\.ssh/id_rsa\.pub")
|
|
325
|
+
subject.generate_ssh_key_ruby == nil
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it "should print an error when finger print fails" do
|
|
330
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).with('1').and_raise(Net::SSH::Exception.new("An error"))
|
|
331
|
+
subject.should_receive(:error).with('An error')
|
|
332
|
+
subject.fingerprint_for_local_key('1').should be_nil
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
it "should catch exceptions from fingerprint failures" do
|
|
336
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).with('1').and_raise(StandardError.new("An error"))
|
|
337
|
+
subject.fingerprint_for_local_key('1').should be_nil
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
it "should handle a block in multi_ssh calls" do
|
|
341
|
+
expect_multi_ssh('foo', 'fakegearid0@fakesshurl.com' => 'bar')
|
|
342
|
+
subject.run_on_gears('foo', [RHC::Rest::Mock::MockRestGearGroup.new], :as => :gear){ |gear, data, group| data.should == 'bar'; 'test' }.should == ['test']
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "should handle a block in multi_ssh calls" do
|
|
346
|
+
expect_multi_ssh('foo', 'fakegearid0@fakesshurl.com' => 'bar')
|
|
347
|
+
capture{ subject.table_from_gears('foo', [RHC::Rest::Mock::MockRestGearGroup.new], :header => ['cart','col']) }.should match /cart.*col\n-+.*fakegearid0.*bar/m
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
it "should handle a run_on_gears error for unrecognized type" do
|
|
351
|
+
expect_multi_ssh('foo', {})
|
|
352
|
+
expect{ subject.run_on_gears('foo', RHC::Rest::Mock::MockRestGearGroup.new.gears) }.to raise_error(RuntimeError)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
it "should handle an error for unrecognized type" do
|
|
356
|
+
expect_multi_ssh('foo', {'fakegearid0@fakesshurl.com' => 'bar'}, true)
|
|
357
|
+
subject.run_on_gears('foo', [RHC::Rest::Mock::MockRestGearGroup.new])
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it "should rescue load errors from ssh-multi" do
|
|
361
|
+
RHC::SSHHelpers::MultipleGearTask.any_instance.should_receive(:require).and_raise(LoadError)
|
|
362
|
+
expect{ RHC::SSHHelpers::MultipleGearTask.new(nil,nil,nil).send(:requires_ssh_multi!) }.to raise_error RHC::OperationNotSupportedException, /must install Net::SSH::Multi/
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
describe "#wrap" do
|
|
367
|
+
it{ "abc".wrap(1).should == "a\nb\nc" }
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
describe "#textwrap_ansi" do
|
|
371
|
+
it{ "".textwrap_ansi(80).should == [] }
|
|
372
|
+
it{ "\n".textwrap_ansi(80).should == ["",""] }
|
|
373
|
+
it{ "a".textwrap_ansi(1).should == ['a'] }
|
|
374
|
+
it{ "ab".textwrap_ansi(1).should == ['a','b'] }
|
|
375
|
+
it{ "ab".textwrap_ansi(2).should == ['ab'] }
|
|
376
|
+
it{ "ab cd".textwrap_ansi(4).should == ['ab', 'cd'] }
|
|
377
|
+
it{ " ab".textwrap_ansi(2).should == [' a','b'] }
|
|
378
|
+
it{ "a b".textwrap_ansi(1).should == ['a','b'] }
|
|
379
|
+
it{ "a w b".textwrap_ansi(2).should == ['a','w','b'] }
|
|
380
|
+
it{ "a w b".textwrap_ansi(3).should == ['a w','b'] }
|
|
381
|
+
it{ "a\nb".textwrap_ansi(1).should == ['a','b'] }
|
|
382
|
+
it{ "\e[1m".textwrap_ansi(1).should == ["\e[1m\e[0m"] }
|
|
383
|
+
it{ "\e[31;1m".textwrap_ansi(1).should == ["\e[31;1m\e[0m"] }
|
|
384
|
+
it{ "\e[1ma".textwrap_ansi(1).should == ["\e[1ma\e[0m"] }
|
|
385
|
+
it{ "a\e[12m".textwrap_ansi(1).should == ["a\e[12m\e[0m"] }
|
|
386
|
+
it{ "a\e[12m\e[34mb".textwrap_ansi(1).should == ["a\e[12m\e[34m\e[0m","\e[12m\e[34mb\e[0m"] }
|
|
387
|
+
it{ "\e[12;34ma".textwrap_ansi(1).should == ["\e[12;34ma\e[0m"] }
|
|
388
|
+
it{ "\e[1m\e[1m".textwrap_ansi(1).should == ["\e[1m\e[1m\e[0m"] }
|
|
389
|
+
it{ "\e[1m \e[1m".textwrap_ansi(1).should == ["\e[1m\e[0m", "\e[1m\e[1m\e[0m"] }
|
|
390
|
+
it{ "\e[1ma\nb".textwrap_ansi(80).should == ["\e[1ma","b"] }
|
|
391
|
+
|
|
392
|
+
it{ "ab".textwrap_ansi(1,false).should == ['ab'] }
|
|
393
|
+
it{ " abc".textwrap_ansi(3,false).should == [' abc'] }
|
|
394
|
+
it{ "abcd".textwrap_ansi(3,false).should == ['abcd'] }
|
|
395
|
+
it{ "abcd\e[1m".textwrap_ansi(3,false).should == ["abcd\e[1m\e[0m"] }
|
|
396
|
+
it{ "abcd efg a".textwrap_ansi(3,false).should == ['abcd', 'efg', 'a'] }
|
|
397
|
+
it('next line'){ "abcd e a".textwrap_ansi(5,false).should == ['abcd', 'e a'] }
|
|
398
|
+
it{ "abcd efgh a".textwrap_ansi(3,false).should == ['abcd', 'efgh', 'a'] }
|
|
399
|
+
it{ " abcd efg a".textwrap_ansi(3,false).should == [' abcd', 'efg', 'a'] }
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
describe "#strip_ansi" do
|
|
403
|
+
it{ "\e[1m \e[1m".strip_ansi.should == " " }
|
|
404
|
+
it{ "\eiei0".strip_ansi.should == "\eiei0" }
|
|
405
|
+
it{ "\e[iei0]".strip_ansi.should == "\e[iei0]" }
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
context "Resolv helper" do
|
|
409
|
+
let(:resolver) { Object.new }
|
|
410
|
+
let(:existent_host) { 'real_host' }
|
|
411
|
+
let(:nonexistent_host) { 'fake_host' }
|
|
412
|
+
|
|
413
|
+
before do
|
|
414
|
+
Resolv::Hosts.stub(:new) { resolver }
|
|
415
|
+
resolver.stub(:getaddress).with(existent_host) { existent_host }
|
|
416
|
+
resolver.stub(:getaddress).with(nonexistent_host){ Resolv::ResolvError }
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
context "when hosts file has the desired host" do
|
|
420
|
+
it "does not raise error" do
|
|
421
|
+
expect {
|
|
422
|
+
subject.hosts_file_contains?(existent_host)
|
|
423
|
+
}.to_not raise_error
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
context "when hosts file does not have the desired host" do
|
|
428
|
+
it "does not raise error" do
|
|
429
|
+
expect {
|
|
430
|
+
subject.hosts_file_contains?(nonexistent_host)
|
|
431
|
+
}.to_not raise_error
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
context "cartridge helpers" do
|
|
437
|
+
before{ mock_terminal }
|
|
438
|
+
|
|
439
|
+
describe '#check_cartridges' do
|
|
440
|
+
let(:cartridges){ [] }
|
|
441
|
+
let(:find_cartridges){ [] }
|
|
442
|
+
context "with a generic object" do
|
|
443
|
+
it { expect{ subject.send(:check_cartridges, 'foo', :from => cartridges) }.to raise_error(RHC::CartridgeNotFoundException, 'There are no cartridges that match \'foo\'.') }
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
describe '#match_cart' do
|
|
448
|
+
context 'with a nil cart' do
|
|
449
|
+
let(:cart){ OpenStruct.new(:name => nil, :description => nil, :tags => nil) }
|
|
450
|
+
it{ subject.send(:match_cart, cart, 'foo').should be_false }
|
|
451
|
+
end
|
|
452
|
+
context 'with simple strings' do
|
|
453
|
+
let(:cart){ OpenStruct.new(:name => 'FOO-more_max any', :description => 'bar word', :tags => [:baz]) }
|
|
454
|
+
it{ subject.send(:match_cart, cart, 'foo').should be_true }
|
|
455
|
+
it{ subject.send(:match_cart, cart, 'fo').should be_true }
|
|
456
|
+
it{ subject.send(:match_cart, cart, 'oo').should be_true }
|
|
457
|
+
it{ subject.send(:match_cart, cart, 'bar').should be_true }
|
|
458
|
+
it{ subject.send(:match_cart, cart, 'word').should be_true }
|
|
459
|
+
it{ subject.send(:match_cart, cart, 'bar word').should be_true }
|
|
460
|
+
it{ subject.send(:match_cart, cart, 'wor').should be_false }
|
|
461
|
+
it{ subject.send(:match_cart, cart, 'baz').should be_true }
|
|
462
|
+
it{ subject.send(:match_cart, cart, 'more max').should be_true }
|
|
463
|
+
it{ subject.send(:match_cart, cart, 'foo more max any').should be_true }
|
|
464
|
+
it{ subject.send(:match_cart, cart, 'foo_more max-any').should be_true }
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
describe "#collect_env_vars" do
|
|
470
|
+
it { subject.collect_env_vars('FOO=BAR').first.to_hash.should == { :name => 'FOO', :value => 'BAR' } }
|
|
471
|
+
it { subject.collect_env_vars('FOO2=BAR2').first.to_hash.should == { :name => 'FOO2', :value => 'BAR2' } }
|
|
472
|
+
it { subject.collect_env_vars('FOO_BAR=ZEE').first.to_hash.should == { :name => 'FOO_BAR', :value => 'ZEE' } }
|
|
473
|
+
it { subject.collect_env_vars('_FOO=BAR').first.to_hash.should == { :name => '_FOO', :value => 'BAR' } }
|
|
474
|
+
it { subject.collect_env_vars('FOO=').first.to_hash.should == { :name => 'FOO', :value => '' } }
|
|
475
|
+
it { subject.collect_env_vars('FOO==').first.to_hash.should == { :name => 'FOO', :value => '=' } }
|
|
476
|
+
it { subject.collect_env_vars('FOO=BAR=ZEE').first.to_hash.should == { :name => 'FOO', :value => 'BAR=ZEE' } }
|
|
477
|
+
it { subject.collect_env_vars('foo25_=BAR=\][#%*').first.to_hash.should == { :name => 'foo25_', :value => 'BAR=\][#%*' } }
|
|
478
|
+
it { subject.collect_env_vars('FOO=Test 1 2 3').first.to_hash.should == { :name => 'FOO', :value => 'Test 1 2 3' } }
|
|
479
|
+
it { subject.collect_env_vars('2FOO=BAR').empty?.should be_true }
|
|
480
|
+
it { subject.collect_env_vars('FOO.2=BAR').empty?.should be_true }
|
|
481
|
+
it { subject.collect_env_vars('FOO BAR=ZEE').empty?.should be_true }
|
|
482
|
+
it { subject.collect_env_vars('FOO*BAR=ZEE').empty?.should be_true }
|
|
483
|
+
it { subject.collect_env_vars('FOO&BAR=ZEE').empty?.should be_true }
|
|
484
|
+
it { subject.collect_env_vars('FOO:BAR=ZEE').empty?.should be_true }
|
|
485
|
+
it { subject.collect_env_vars('FOO@BAR=ZEE').empty?.should be_true }
|
|
486
|
+
it { subject.collect_env_vars('FOO!BAR=ZEE').empty?.should be_true }
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
describe RHC::Helpers::StringTee do
|
|
491
|
+
let(:other){ StringIO.new }
|
|
492
|
+
subject{ RHC::Helpers::StringTee.new(other) }
|
|
493
|
+
context "It should copy output" do
|
|
494
|
+
before{ subject << 'foo' }
|
|
495
|
+
its(:string) { should == 'foo' }
|
|
496
|
+
it("should tee to other") { other.string.should == 'foo' }
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
describe Object do
|
|
501
|
+
context 'present?' do
|
|
502
|
+
specify('nil') { nil.present?.should be_false }
|
|
503
|
+
specify('empty array') { [].present?.should be_false }
|
|
504
|
+
specify('array') { [1].present?.should be_true }
|
|
505
|
+
specify('string') { 'a'.present?.should be_true }
|
|
506
|
+
specify('empty string') { ''.present?.should be_false }
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
context 'presence' do
|
|
510
|
+
specify('nil') { nil.presence.should be_nil }
|
|
511
|
+
specify('empty array') { [].presence.should be_nil }
|
|
512
|
+
specify('array') { [1].presence.should == [1] }
|
|
513
|
+
specify('string') { 'a'.presence.should == 'a' }
|
|
514
|
+
specify('empty string') { ''.presence.should be_nil }
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
context 'blank?' do
|
|
518
|
+
specify('nil') { nil.blank?.should be_true }
|
|
519
|
+
specify('empty array') { [].blank?.should be_true }
|
|
520
|
+
specify('array') { [1].blank?.should be_false }
|
|
521
|
+
specify('string') { 'a'.blank?.should be_false }
|
|
522
|
+
specify('empty string') { ''.blank?.should be_true }
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
describe OpenURI do
|
|
527
|
+
context 'redirectable?' do
|
|
528
|
+
specify('http to https') { OpenURI.redirectable?(URI.parse('http://foo.com'), URI.parse('https://foo.com')).should be_true }
|
|
529
|
+
specify('https to http') { OpenURI.redirectable?(URI.parse('https://foo.com'), URI.parse('http://foo.com')).should be_false }
|
|
530
|
+
end
|
|
531
|
+
end
|