pbox 1.17.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +40 -0
- data/Rakefile +6 -0
- data/autocomplete/pbox_bash +1639 -0
- data/bin/pbox +37 -0
- data/conf/protonbox.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +178 -0
- data/features/deployments_feature.rb +127 -0
- data/features/domains_feature.rb +49 -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 +186 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +701 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +96 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +326 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +167 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/git_clone.rb +29 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -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/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +320 -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 +88 -0
- data/lib/rhc/exceptions.rb +232 -0
- data/lib/rhc/git_helpers.rb +91 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +477 -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 +332 -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 +154 -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 +1024 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/ssh_helpers.rb +378 -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 +35 -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 +633 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +89 -0
- data/spec/direct_execution_helper.rb +338 -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 +188 -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 +754 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +145 -0
- data/spec/rhc/commands/cartridge_spec.rb +641 -0
- data/spec/rhc/commands/deployment_spec.rb +286 -0
- data/spec/rhc/commands/domain_spec.rb +383 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +80 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +228 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -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 +524 -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 +248 -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 +435 -0
@@ -0,0 +1,752 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'stringio'
|
4
|
+
require 'rest_spec_helper'
|
5
|
+
require 'rhc/rest'
|
6
|
+
|
7
|
+
module RHC
|
8
|
+
module Rest
|
9
|
+
describe Client do
|
10
|
+
|
11
|
+
after{ ENV['http_proxy'] = nil }
|
12
|
+
after{ ENV['HTTP_PROXY'] = nil }
|
13
|
+
|
14
|
+
it 'should set the proxy protocol if it is missing' do
|
15
|
+
ENV['http_proxy'] = 'foo.bar.com:8081'
|
16
|
+
expect{ RHC::Rest::Client.new.send(:httpclient_for, {}) }.to raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should not alter the proxy protocol if it is present' do
|
20
|
+
ENV['http_proxy'] = 'http://foo.bar.com:8081'
|
21
|
+
RHC::Rest::Client.new.send(:httpclient_for, {}).proxy.to_s.should == URI.parse(ENV['http_proxy']).to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should not affect the proxy protocol if nil' do
|
25
|
+
ENV['http_proxy'] = nil
|
26
|
+
RHC::Rest::Client.new.send(:httpclient_for, {}).proxy.should be_nil
|
27
|
+
ENV['http_proxy'].should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:endpoint){ mock_href }
|
31
|
+
let(:username){ nil }
|
32
|
+
let(:password){ nil }
|
33
|
+
let(:use_debug){ false }
|
34
|
+
let(:client) do
|
35
|
+
respond_to?(:spec_versions) ?
|
36
|
+
RHC::Rest::Client.new(endpoint, username, password, use_debug, spec_versions) :
|
37
|
+
RHC::Rest::Client.new(endpoint, username, password, use_debug)
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:client_links) { mock_response_links(mock_client_links) }
|
41
|
+
let(:domain_0_links) { mock_response_links(mock_domain_links('mock_domain_0')) }
|
42
|
+
let(:domain_1_links) { mock_response_links(mock_domain_links('mock_domain_1')) }
|
43
|
+
let(:app_0_links) { mock_response_links(mock_app_links('mock_domain_0', 'mock_app')) }
|
44
|
+
let(:user_links) { mock_response_links(mock_user_links) }
|
45
|
+
let(:key_links) { mock_response_links(mock_key_links) }
|
46
|
+
let(:api_links) { client_links }
|
47
|
+
|
48
|
+
context "#new" do
|
49
|
+
before do
|
50
|
+
stub_api_request(:get, '').
|
51
|
+
to_return({ :body => { :data => client_links, :supported_api_versions => [1.0, 1.1] }.to_json,
|
52
|
+
:status => 200
|
53
|
+
})
|
54
|
+
stub_api_request(:get, 'api_error').
|
55
|
+
to_raise(HTTPClient::BadResponseError.new('API Error'))
|
56
|
+
stub_api_request(:get, 'other_error').
|
57
|
+
to_raise(StandardError.new('Other Error'))
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns a client object from the required arguments" do
|
61
|
+
credentials = Base64.strict_encode64(mock_user + ":" + mock_pass)
|
62
|
+
client.api.send(:links).should == client_links
|
63
|
+
end
|
64
|
+
context "against an endpoint that won't connect" do
|
65
|
+
let(:endpoint){ mock_href('api_error') }
|
66
|
+
it "raises an error message" do
|
67
|
+
expect{ client.api }.to raise_error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
context "against an endpoint that has a generic error" do
|
71
|
+
let(:endpoint){ mock_href('other_error') }
|
72
|
+
it "raises a generic error for any other error condition" do
|
73
|
+
expect{ client.api }.to raise_error(RHC::Rest::ConnectionException, "An unexpected error occured: Other Error")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#new" do
|
79
|
+
context "when server supports API versions [1.0, 1.1]" do
|
80
|
+
before :each do
|
81
|
+
stub_api_request(:get, '').
|
82
|
+
with(:headers => {'Accept' => 'application/json'}).
|
83
|
+
to_return({ :status => 200, :body => { :data => client_links, :version => '1.0', :supported_api_versions => [1.0, 1.1] }.to_json })
|
84
|
+
stub_api_request(:get, '').
|
85
|
+
with(:headers => {'Accept' => 'application/json;version=1.0'}).
|
86
|
+
to_return({ :status => 200, :body => { :data => client_links, :version => '1.0', :supported_api_versions => [1.0, 1.1] }.to_json })
|
87
|
+
stub_api_request(:get, '').
|
88
|
+
with(:headers => {'Accept' => 'application/json;version=1.1'}).
|
89
|
+
to_return({ :status => 200, :body => { :data => client_links, :version => '1.1', :supported_api_versions => [1.0, 1.1] }.to_json })
|
90
|
+
stub_api_request(:get, '').
|
91
|
+
with(:headers => {'Accept' => /application\/json;version=(1.2|1.3)/}).
|
92
|
+
to_raise(StandardError.new('Bad Version'))
|
93
|
+
stub_api_request(:get, 'api_error').
|
94
|
+
to_raise(HTTPClient::BadResponseError.new('API Error'))
|
95
|
+
stub_api_request(:get, 'other_error').
|
96
|
+
to_raise(StandardError.new('Other Error'))
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when client is instantiated with [1.0, 1.1] as the preferred API versions" do
|
100
|
+
let(:spec_versions){ [1.0, 1.1] }
|
101
|
+
it "settles on 1.1 as the API version" do
|
102
|
+
client.api.api_version_negotiated.should == 1.1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when client is instantiated with [1.1, 1.0] as the preferred API versions" do
|
107
|
+
let(:spec_versions){ [1.1, 1.0] }
|
108
|
+
it "settles on 1.0 as the API version" do
|
109
|
+
client.api.api_version_negotiated.should == 1.0
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when client is instantiated with [1.2, 1.3] as the preferred API versions" do
|
114
|
+
let(:spec_versions){ [1.2, 1.3] }
|
115
|
+
it "fails to negotiate an agreeable API version" do
|
116
|
+
client.api.api_version_negotiated.should be_nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when client is instantiated with [1.1, 1.0, 1.3] as the preferred API versions" do
|
121
|
+
let(:spec_versions){ [1.1, 1.0, 1.3] }
|
122
|
+
it "settles on 1.0 as the API version" do
|
123
|
+
client.api.api_version_negotiated.should == 1.0
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "with an instantiated client " do
|
130
|
+
before do
|
131
|
+
stub_api_request(:get, '').
|
132
|
+
to_return({ :body => {
|
133
|
+
:data => api_links,
|
134
|
+
:supported_api_versions => [1.0, 1.1]
|
135
|
+
}.to_json,
|
136
|
+
:status => 200
|
137
|
+
})
|
138
|
+
end
|
139
|
+
|
140
|
+
context "#add_domain" do
|
141
|
+
before do
|
142
|
+
stub_api_request(:any, api_links['ADD_DOMAIN']['relative']).
|
143
|
+
to_return({ :body => {
|
144
|
+
:type => 'domain',
|
145
|
+
:supported_api_versions => [1.0, 1.1],
|
146
|
+
:data => {
|
147
|
+
:id => 'mock_domain',
|
148
|
+
:links => mock_response_links(mock_domain_links('mock_domain')),
|
149
|
+
}
|
150
|
+
}.to_json,
|
151
|
+
:status => 200
|
152
|
+
})
|
153
|
+
end
|
154
|
+
it "returns a domain object" do
|
155
|
+
domain = client.add_domain('mock_domain')
|
156
|
+
domain.class.should == RHC::Rest::Domain
|
157
|
+
domain.name.should == 'mock_domain'
|
158
|
+
domain.send(:links).should ==
|
159
|
+
mock_response_links(mock_domain_links('mock_domain'))
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "#update_members" do
|
164
|
+
subject{ RHC::Rest::Application.new }
|
165
|
+
it "raises when the update link is disabled" do
|
166
|
+
subject.should_receive(:supports_members?).and_return(true)
|
167
|
+
expect{ subject.update_members([]) }.to raise_error(RHC::ChangeMembersOnResourceNotSupported)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "#domains" do
|
172
|
+
before(:each) do
|
173
|
+
stub_api_request(:any, api_links['LIST_DOMAINS']['relative']).
|
174
|
+
to_return({ :body => {
|
175
|
+
:type => 'domains',
|
176
|
+
:data =>
|
177
|
+
[{ :id => 'mock_domain_0',
|
178
|
+
:links => mock_response_links(mock_domain_links('mock_domain_0')),
|
179
|
+
},
|
180
|
+
{ :id => 'mock_domain_1',
|
181
|
+
:links => mock_response_links(mock_domain_links('mock_domain_1')),
|
182
|
+
}]
|
183
|
+
}.to_json,
|
184
|
+
:status => 200
|
185
|
+
}).
|
186
|
+
to_return({ :body => {
|
187
|
+
:type => 'domains',
|
188
|
+
:data => []
|
189
|
+
}.to_json,
|
190
|
+
:status => 200
|
191
|
+
})
|
192
|
+
end
|
193
|
+
it "returns a list of existing domains" do
|
194
|
+
domains = client.domains
|
195
|
+
domains.length.should equal(2)
|
196
|
+
(0..1).each do |idx|
|
197
|
+
domains[idx].class.should == RHC::Rest::Domain
|
198
|
+
domains[idx].name.should == "mock_domain_#{idx}"
|
199
|
+
domains[idx].send(:links).should ==
|
200
|
+
mock_response_links(mock_domain_links("mock_domain_#{idx}"))
|
201
|
+
end
|
202
|
+
end
|
203
|
+
it "returns an empty list when no domains exist" do
|
204
|
+
# Disregard the first response; this is for the previous expectiation.
|
205
|
+
domains = client.domains
|
206
|
+
client.instance_variable_set(:@domains, nil)
|
207
|
+
domains = client.domains
|
208
|
+
domains.length.should equal(0)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context "#find_domain" do
|
213
|
+
context "when server does not support SHOW_DOMAIN" do
|
214
|
+
before do
|
215
|
+
stub_api_request(:any, api_links['LIST_DOMAINS']['relative']).
|
216
|
+
to_return({ :body => {
|
217
|
+
:type => 'domains',
|
218
|
+
:data =>
|
219
|
+
[{ :id => 'mock_domain_0',
|
220
|
+
:links => mock_response_links(mock_domain_links('mock_domain_0')),
|
221
|
+
},
|
222
|
+
{ :id => 'mock_domain_1',
|
223
|
+
:links => mock_response_links(mock_domain_links('mock_domain_1')),
|
224
|
+
}]
|
225
|
+
}.to_json,
|
226
|
+
:status => 200
|
227
|
+
})
|
228
|
+
end
|
229
|
+
it "returns a domain object for matching domain IDs" do
|
230
|
+
match = nil
|
231
|
+
expect { match = client.find_domain('mock_domain_0') }.to_not raise_error
|
232
|
+
match.name.should == 'mock_domain_0'
|
233
|
+
match.class.should == RHC::Rest::Domain
|
234
|
+
end
|
235
|
+
it "returns a domain object for matching case-insensitive domain IDs" do
|
236
|
+
match = nil
|
237
|
+
expect { match = client.find_domain('MOCK_DOMAIN_0') }.to_not raise_error
|
238
|
+
match.name.should == 'mock_domain_0'
|
239
|
+
match.class.should == RHC::Rest::Domain
|
240
|
+
end
|
241
|
+
it "raise an error when no matching domain IDs can be found" do
|
242
|
+
expect { client.find_domain('mock_domain_2') }.to raise_error(RHC::Rest::DomainNotFoundException)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context "when server supports SHOW_DOMAIN" do
|
247
|
+
let(:api_links){ client_links.merge!(mock_response_links([['SHOW_DOMAIN', 'domains/:name', 'get']])) }
|
248
|
+
before do
|
249
|
+
stub_api_request(:any, api_links['SHOW_DOMAIN']['relative'].gsub(/:name/, 'mock_domain_0')).
|
250
|
+
to_return({ :body => {
|
251
|
+
:type => 'domain',
|
252
|
+
:data =>
|
253
|
+
{ :id => 'mock_domain_0',
|
254
|
+
:links => mock_response_links(mock_domain_links('mock_domain_0')),
|
255
|
+
}
|
256
|
+
}.to_json,
|
257
|
+
:status => 200
|
258
|
+
})
|
259
|
+
stub_api_request(:any, api_links['SHOW_DOMAIN']['relative'].gsub(/:name/, 'mock_domain_%^&')).
|
260
|
+
to_return({ :body => {
|
261
|
+
:type => 'domain',
|
262
|
+
:data =>
|
263
|
+
{ :id => 'mock_domain_%^&',
|
264
|
+
:links => mock_response_links(mock_domain_links('mock_domain_0')),
|
265
|
+
}
|
266
|
+
}.to_json,
|
267
|
+
:status => 200
|
268
|
+
})
|
269
|
+
stub_api_request(:any, api_links['SHOW_DOMAIN']['relative'].gsub(/:name/, 'mock_domain_2')).
|
270
|
+
to_return({ :body => {:messages => [{:exit_code => 127}, {:severity => 'warning', :text => 'A warning'}]}.to_json,
|
271
|
+
:status => 404
|
272
|
+
})
|
273
|
+
end
|
274
|
+
it "returns a domain object for matching domain IDs" do
|
275
|
+
match = nil
|
276
|
+
expect { match = client.find_domain('mock_domain_0') }.to_not raise_error
|
277
|
+
match.name.should == 'mock_domain_0'
|
278
|
+
match.class.should == RHC::Rest::Domain
|
279
|
+
end
|
280
|
+
it "encodes special characters" do
|
281
|
+
match = nil
|
282
|
+
expect { match = client.find_domain('mock_domain_%^&') }.to_not raise_error
|
283
|
+
match.name.should == 'mock_domain_%^&'
|
284
|
+
match.class.should == RHC::Rest::Domain
|
285
|
+
end
|
286
|
+
it "raise an error when no matching domain IDs can be found" do
|
287
|
+
expect{ client.find_domain('mock_domain_2') }.to raise_error(RHC::Rest::DomainNotFoundException)
|
288
|
+
end
|
289
|
+
it "prints a warning when an error is returned" do
|
290
|
+
client.should_receive(:warn).with('A warning')
|
291
|
+
expect{ client.find_domain('mock_domain_2') }.to raise_error(RHC::Rest::DomainNotFoundException)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
context "when server supports LIST_DOMAINS_BY_OWNER" do
|
297
|
+
let(:api_links){ client_links.merge!(mock_response_links([['LIST_DOMAINS_BY_OWNER', 'domains', 'get']])) }
|
298
|
+
before do
|
299
|
+
stub_api_request(:any, "#{api_links['LIST_DOMAINS_BY_OWNER']['relative']}?owner=@self").
|
300
|
+
to_return({ :body => {
|
301
|
+
:type => 'domains',
|
302
|
+
:data => [{
|
303
|
+
:id => 'mock_domain_0',
|
304
|
+
:links => mock_response_links(mock_domain_links('mock_domain_0')),
|
305
|
+
}]
|
306
|
+
}.to_json,
|
307
|
+
:status => 200
|
308
|
+
})
|
309
|
+
end
|
310
|
+
it "returns owned domains when called" do
|
311
|
+
match = nil
|
312
|
+
expect { match = client.owned_domains }.to_not raise_error
|
313
|
+
match.length.should == 1
|
314
|
+
match.first.name.should == 'mock_domain_0'
|
315
|
+
match.first.class.should == RHC::Rest::Domain
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
context "find_application" do
|
320
|
+
let(:mock_domain){ 'mock_domain_0' }
|
321
|
+
let(:mock_app){ 'mock_app' }
|
322
|
+
let(:missing){ 'no_match' }
|
323
|
+
before(:each) do
|
324
|
+
stub_one_application(mock_domain, mock_app)
|
325
|
+
stub_one_application(mock_domain, missing, {
|
326
|
+
:type => nil,
|
327
|
+
:data => nil,
|
328
|
+
:messages => [{
|
329
|
+
:exit_code => 101,
|
330
|
+
:field => nil,
|
331
|
+
:severity => 'error',
|
332
|
+
:text => "Application #{missing} not found"
|
333
|
+
}],
|
334
|
+
:status => 'not_found'
|
335
|
+
}, 404)
|
336
|
+
stub_one_application(missing, mock_app, {
|
337
|
+
:type => nil,
|
338
|
+
:data => nil,
|
339
|
+
:messages => [{
|
340
|
+
:exit_code => 127,
|
341
|
+
:field => nil,
|
342
|
+
:severity => 'error',
|
343
|
+
:text => "Domain #{missing} not found"
|
344
|
+
}],
|
345
|
+
:status => 'not_found'
|
346
|
+
}, 404)
|
347
|
+
end
|
348
|
+
it "returns application object for nested application IDs" do
|
349
|
+
match = client.find_application(mock_domain, mock_app)
|
350
|
+
match.class.should == RHC::Rest::Application
|
351
|
+
match.name.should == mock_app
|
352
|
+
match.domain_id.should == mock_domain
|
353
|
+
match.send(:links).should ==
|
354
|
+
mock_response_links(mock_app_links(mock_domain, mock_app))
|
355
|
+
end
|
356
|
+
it "Raises an exception when no matching applications can be found" do
|
357
|
+
expect { client.find_application(mock_domain, missing) }.to raise_error(RHC::Rest::ApplicationNotFoundException)
|
358
|
+
end
|
359
|
+
it "Raises an exception when no matching domain can be found" do
|
360
|
+
expect { client.find_application(missing, mock_app) }.to raise_error(RHC::Rest::DomainNotFoundException)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
context "#find_application_by_id" do
|
365
|
+
context "when server does not support SHOW_APPLICATION" do
|
366
|
+
let(:server){ mock_uri }
|
367
|
+
let(:endpoint){ "https://#{server}/broker/rest/api"}
|
368
|
+
before do
|
369
|
+
stub_api
|
370
|
+
stub_one_domain('test')
|
371
|
+
stub_one_application('test', 'app1')
|
372
|
+
end
|
373
|
+
it "returns an app object for matching IDs" do
|
374
|
+
match = nil
|
375
|
+
expect { match = client.find_application_by_id(1) }.to_not raise_error
|
376
|
+
match.id.should == 1
|
377
|
+
match.class.should == RHC::Rest::Application
|
378
|
+
end
|
379
|
+
it "raise an error when no matching app IDs can be found" do
|
380
|
+
expect { client.find_application_by_id('2') }.to raise_error(RHC::Rest::ApplicationNotFoundException)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
context "when server supports SHOW_APPLICATION" do
|
385
|
+
let(:api_links){ mock_response_links([['SHOW_APPLICATION', 'application/:id', 'get']]) }
|
386
|
+
before do
|
387
|
+
stub_api_request(:any, api_links['SHOW_APPLICATION']['relative'].gsub(/:id/, 'app_0')).
|
388
|
+
to_return({ :body => {
|
389
|
+
:type => 'application',
|
390
|
+
:data =>
|
391
|
+
{ :id => 'app_0',
|
392
|
+
:links => mock_response_links(mock_app_links('app_0')),
|
393
|
+
}
|
394
|
+
}.to_json,
|
395
|
+
:status => 200
|
396
|
+
})
|
397
|
+
stub_api_request(:any, api_links['SHOW_APPLICATION']['relative'].gsub(/:id/, 'app_1')).
|
398
|
+
to_return({ :body => {:messages => [{:exit_code => 101}]}.to_json,
|
399
|
+
:status => 404
|
400
|
+
})
|
401
|
+
end
|
402
|
+
it "returns an app object for matching IDs" do
|
403
|
+
match = nil
|
404
|
+
expect { match = client.find_application_by_id('app_0') }.to_not raise_error
|
405
|
+
match.id.should == 'app_0'
|
406
|
+
match.class.should == RHC::Rest::Application
|
407
|
+
end
|
408
|
+
it "raise an error when no matching IDs can be found" do
|
409
|
+
expect { client.find_application_by_id('app_1') }.to raise_error(RHC::Rest::ApplicationNotFoundException)
|
410
|
+
end
|
411
|
+
it "should fetch application ids" do
|
412
|
+
client.api
|
413
|
+
client.should_receive(:request).with(:url => "#{api_links['SHOW_APPLICATION']['href'].gsub(/:id/, 'app_2')}", :method => "GET", :payload => {}).and_return(1)
|
414
|
+
client.find_application_by_id('app_2').should == 1
|
415
|
+
end
|
416
|
+
it "should fetch application gear groups" do
|
417
|
+
client.api
|
418
|
+
client.should_receive(:request).with(:url => "#{api_links['SHOW_APPLICATION']['href'].gsub(/:id/, 'app_2')}/gear_groups", :method => "GET", :payload => {}).and_return(1)
|
419
|
+
client.find_application_by_id_gear_groups('app_2').should == 1
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
describe RHC::Rest::Cartridge do
|
425
|
+
subject do
|
426
|
+
RHC::Rest::Cartridge.new({
|
427
|
+
:name => 'foo',
|
428
|
+
:links => mock_response_links([
|
429
|
+
['GET', 'broker/rest/cartridge', 'get']
|
430
|
+
])}, client)
|
431
|
+
end
|
432
|
+
context "when several messages are present" do
|
433
|
+
before do
|
434
|
+
stub_api_request(:get, 'broker/rest/cartridge', true).
|
435
|
+
with(:query => {:include => 'status_messages'}).
|
436
|
+
to_return(:body => {
|
437
|
+
:type => 'cartridge',
|
438
|
+
:data => {
|
439
|
+
:status_messages => [{:message => 'Test'}]
|
440
|
+
}
|
441
|
+
}.to_json)
|
442
|
+
end
|
443
|
+
its(:status){ should == [{'message' => 'Test'}] }
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
context "#cartridges" do
|
448
|
+
before(:each) do
|
449
|
+
stub_api_request(:any, api_links['LIST_CARTRIDGES']['relative']).
|
450
|
+
to_return({ :body => {
|
451
|
+
:type => 'cartridges',
|
452
|
+
:data =>
|
453
|
+
[{ :name => 'mock_cart_0',
|
454
|
+
:type => 'mock_cart_0_type',
|
455
|
+
:links => mock_response_links(mock_cart_links('mock_cart_0')),
|
456
|
+
},
|
457
|
+
{ :name => 'mock_cart_1',
|
458
|
+
:type => 'mock_cart_1_type',
|
459
|
+
:links => mock_response_links(mock_cart_links('mock_cart_1')),
|
460
|
+
}]
|
461
|
+
}.to_json,
|
462
|
+
:status => 200
|
463
|
+
}).
|
464
|
+
to_return({ :body => {
|
465
|
+
:type => 'cartridges',
|
466
|
+
:data => []
|
467
|
+
}.to_json,
|
468
|
+
:status => 200
|
469
|
+
})
|
470
|
+
end
|
471
|
+
it "returns a list of existing cartridges" do
|
472
|
+
carts = client.cartridges
|
473
|
+
carts.length.should equal(2)
|
474
|
+
(0..1).each do |idx|
|
475
|
+
carts[idx].class.should == RHC::Rest::Cartridge
|
476
|
+
carts[idx].name.should == "mock_cart_#{idx}"
|
477
|
+
carts[idx].type.should == "mock_cart_#{idx}_type"
|
478
|
+
carts[idx].send(:links).should ==
|
479
|
+
mock_response_links(mock_cart_links("mock_cart_#{idx}"))
|
480
|
+
end
|
481
|
+
end
|
482
|
+
it "caches cartridges on the client" do
|
483
|
+
# Disregard the first response; this is for the previous expectiation.
|
484
|
+
old = client.cartridges.length
|
485
|
+
client.cartridges.length.should equal(old)
|
486
|
+
client.instance_variable_set(:@cartridges, nil)
|
487
|
+
client.cartridges.length.should equal(0)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
context "#find_cartridges" do
|
492
|
+
before(:each) do
|
493
|
+
stub_api_request(:any, api_links['LIST_CARTRIDGES']['relative']).
|
494
|
+
to_return({ :body => {
|
495
|
+
:type => 'cartridges',
|
496
|
+
:data =>
|
497
|
+
[{ :name => 'mock_cart_0',
|
498
|
+
:type => 'mock_cart_0_type',
|
499
|
+
:links => mock_response_links(mock_cart_links('mock_cart_0')),
|
500
|
+
},
|
501
|
+
{ :name => 'mock_cart_1',
|
502
|
+
:type => 'mock_cart_1_type',
|
503
|
+
:links => mock_response_links(mock_cart_links('mock_cart_1')),
|
504
|
+
},
|
505
|
+
{ :name => 'mock_nomatch_cart_0',
|
506
|
+
:type => 'mock_nomatch_cart_0_type',
|
507
|
+
:links => mock_response_links(mock_cart_links('mock_nomatch_cart_0')),
|
508
|
+
}
|
509
|
+
]
|
510
|
+
}.to_json,
|
511
|
+
:status => 200
|
512
|
+
})
|
513
|
+
end
|
514
|
+
it "returns a list of cartridge objects for matching cartridges" do
|
515
|
+
matches = client.find_cartridges('mock_cart_0')
|
516
|
+
matches.length.should equal(1)
|
517
|
+
matches[0].class.should == RHC::Rest::Cartridge
|
518
|
+
matches[0].name.should == 'mock_cart_0'
|
519
|
+
matches[0].type.should == 'mock_cart_0_type'
|
520
|
+
matches[0].send(:links).should ==
|
521
|
+
mock_response_links(mock_cart_links('mock_cart_0'))
|
522
|
+
end
|
523
|
+
it "returns an empty list when no matching cartridges can be found" do
|
524
|
+
matches = client.find_cartridges('no_match')
|
525
|
+
matches.length.should equal(0)
|
526
|
+
end
|
527
|
+
it "returns multiple cartridge matches" do
|
528
|
+
matches = client.find_cartridges :regex => "mock_cart_[0-9]"
|
529
|
+
matches.length.should equal(2)
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
context "#user" do
|
534
|
+
before(:each) do
|
535
|
+
stub_api_request(:any, api_links['GET_USER']['relative']).
|
536
|
+
to_return({ :body => {
|
537
|
+
:type => 'user',
|
538
|
+
:data =>
|
539
|
+
{ :login => mock_user,
|
540
|
+
:links => mock_response_links(mock_user_links)
|
541
|
+
}
|
542
|
+
}.to_json,
|
543
|
+
:status => 200
|
544
|
+
})
|
545
|
+
end
|
546
|
+
it "returns the user object associated with this client connection" do
|
547
|
+
user = client.user
|
548
|
+
user.class.should == RHC::Rest::User
|
549
|
+
user.login.should == mock_user
|
550
|
+
user.send(:links).should == mock_response_links(mock_user_links)
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
context "#find_key" do
|
555
|
+
before(:each) do
|
556
|
+
stub_api_request(:any, api_links['GET_USER']['relative']).
|
557
|
+
to_return({ :body => {
|
558
|
+
:type => 'user',
|
559
|
+
:data =>
|
560
|
+
{ :login => mock_user,
|
561
|
+
:links => mock_response_links(mock_user_links)
|
562
|
+
}
|
563
|
+
}.to_json,
|
564
|
+
:status => 200
|
565
|
+
})
|
566
|
+
stub_api_request(:any, user_links['LIST_KEYS']['relative']).
|
567
|
+
to_return({ :body => {
|
568
|
+
:type => 'keys',
|
569
|
+
:data =>
|
570
|
+
[{ :name => 'mock_key_0',
|
571
|
+
:type => 'mock_key_0_type',
|
572
|
+
:content => '123456789:0',
|
573
|
+
:links => mock_response_links(mock_key_links('mock_key_0'))
|
574
|
+
},
|
575
|
+
{ :name => 'mock_key_1',
|
576
|
+
:type => 'mock_key_1_type',
|
577
|
+
:content => '123456789:1',
|
578
|
+
:links => mock_response_links(mock_key_links('mock_key_1'))
|
579
|
+
}]
|
580
|
+
}.to_json,
|
581
|
+
:status => 200
|
582
|
+
})
|
583
|
+
end
|
584
|
+
it "returns a list of key objects for matching keys" do
|
585
|
+
key = nil
|
586
|
+
expect { key = client.find_key('mock_key_0') }.to_not raise_error
|
587
|
+
|
588
|
+
key.class.should == RHC::Rest::Key
|
589
|
+
key.name.should == 'mock_key_0'
|
590
|
+
key.type.should == 'mock_key_0_type'
|
591
|
+
key.content.should == '123456789:0'
|
592
|
+
key.send(:links).should ==
|
593
|
+
mock_response_links(mock_key_links('mock_key_0'))
|
594
|
+
end
|
595
|
+
it "raise an error when no matching keys can be found" do
|
596
|
+
expect { client.find_key('no_match') }.to raise_error(RHC::KeyNotFoundException)
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
context "#delete_key" do
|
601
|
+
before(:each) do
|
602
|
+
stub_api_request(:any, api_links['GET_USER']['relative']).
|
603
|
+
to_return({ :body => {
|
604
|
+
:type => 'user',
|
605
|
+
:data =>
|
606
|
+
{ :login => mock_user,
|
607
|
+
:links => mock_response_links(mock_user_links)
|
608
|
+
}
|
609
|
+
}.to_json,
|
610
|
+
:status => 200
|
611
|
+
})
|
612
|
+
stub_api_request(:any, user_links['LIST_KEYS']['relative']).
|
613
|
+
to_return({ :body => {
|
614
|
+
:type => 'keys',
|
615
|
+
:data =>
|
616
|
+
[{ :name => 'mock_key_0',
|
617
|
+
:type => 'mock_key_0_type',
|
618
|
+
:content => '123456789:0',
|
619
|
+
:links => mock_response_links(mock_key_links('mock_key_0'))
|
620
|
+
},
|
621
|
+
{ :name => 'mock_key_1',
|
622
|
+
:type => 'mock_key_1_type',
|
623
|
+
:content => '123456789:1',
|
624
|
+
:links => mock_response_links(mock_key_links('mock_key_1'))
|
625
|
+
}]
|
626
|
+
}.to_json,
|
627
|
+
:status => 200
|
628
|
+
})
|
629
|
+
|
630
|
+
stub_api_request(:post, key_links['DELETE']['relative']).
|
631
|
+
to_return({ :body => {}.to_json,
|
632
|
+
:status => 200
|
633
|
+
})
|
634
|
+
end
|
635
|
+
|
636
|
+
it "should delete keys" do
|
637
|
+
expect { client.delete_key('mock_key_0') }.to be_true
|
638
|
+
end
|
639
|
+
|
640
|
+
it 'raises an error if nonexistent key is requested' do
|
641
|
+
expect { client.find_key('no_match') }.to raise_error(RHC::KeyNotFoundException)
|
642
|
+
end
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
context "when server supports API versions 1.0 and 1.1" do
|
647
|
+
before :each do
|
648
|
+
stub_api_request(:get, '').
|
649
|
+
to_return({ :body => {
|
650
|
+
:data => api_links,
|
651
|
+
:supported_api_versions => [1.0, 1.1]
|
652
|
+
}.to_json,
|
653
|
+
:status => 200
|
654
|
+
})
|
655
|
+
end
|
656
|
+
|
657
|
+
context "when client supports API version 1.1" do
|
658
|
+
let(:spec_versions){ [1.1] }
|
659
|
+
|
660
|
+
describe "#api_version_negotiated" do
|
661
|
+
it "returns 1.1" do
|
662
|
+
client.api.api_version_negotiated.to_s.should == '1.1'
|
663
|
+
end
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
context "when client supports only API version 1.2" do
|
668
|
+
let(:spec_versions){ [1.2] }
|
669
|
+
|
670
|
+
describe "#api_version_negotiated" do
|
671
|
+
it 'returns nil' do
|
672
|
+
client.api.api_version_negotiated.should be_nil
|
673
|
+
end
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|
677
|
+
context "when client supports only API version 0.9" do
|
678
|
+
describe "#new" do
|
679
|
+
let(:spec_versions){ [0.9] }
|
680
|
+
it "warns user that it is outdated" do
|
681
|
+
capture do
|
682
|
+
client.api
|
683
|
+
@output.rewind
|
684
|
+
@output.read.should =~ /client version may be outdated/
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
describe "#supports_sessions?" do
|
692
|
+
before{ subject.should_receive(:api).at_least(2).times.and_return(double) }
|
693
|
+
context "with ADD_AUTHORIZATION link" do
|
694
|
+
before{ subject.api.should_receive(:supports?).with('ADD_AUTHORIZATION').and_return(true) }
|
695
|
+
its(:supports_sessions?){ should be_true }
|
696
|
+
end
|
697
|
+
context "without ADD_AUTHORIZATION link" do
|
698
|
+
before{ subject.api.should_receive(:supports?).with('ADD_AUTHORIZATION').and_return(false) }
|
699
|
+
its(:supports_sessions?){ should be_false }
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
describe "#authorizations" do
|
704
|
+
before do
|
705
|
+
stub_api_request(:get, '').to_return({:body => {
|
706
|
+
:data => mock_response_links(mock_api_with_authorizations),
|
707
|
+
:supported_api_versions => [1.0, 1.1]
|
708
|
+
}.to_json,
|
709
|
+
:status => 200
|
710
|
+
})
|
711
|
+
stub_authorizations
|
712
|
+
end
|
713
|
+
it{ client.authorizations.first.token.should == 'a_token_value' }
|
714
|
+
it{ client.authorizations.first.note.should == 'an_authorization' }
|
715
|
+
it{ client.authorizations.first.expires_in_seconds.should == 60 }
|
716
|
+
end
|
717
|
+
end
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
module RHC
|
722
|
+
module Rest
|
723
|
+
describe HTTPClient do
|
724
|
+
end
|
725
|
+
|
726
|
+
describe WWWAuth::DeferredCredential do
|
727
|
+
subject{ described_class.new(nil, nil) }
|
728
|
+
its(:user){ should be_nil }
|
729
|
+
its(:passwd){ should be_nil }
|
730
|
+
|
731
|
+
context "with a username and password" do
|
732
|
+
subject{ described_class.new(username, password) }
|
733
|
+
let(:username){ 'a_user' }
|
734
|
+
let(:password){ 'a_password' }
|
735
|
+
|
736
|
+
its(:user){ should == username }
|
737
|
+
its(:passwd){ should == password }
|
738
|
+
its(:to_str){ should == ["#{username}:#{password}"].pack('m').tr("\n", '') }
|
739
|
+
end
|
740
|
+
|
741
|
+
context "with a deferred username and password" do
|
742
|
+
subject{ described_class.new(username, password) }
|
743
|
+
let(:username){ lambda{ 'a_user' } }
|
744
|
+
let(:password){ lambda{ 'a_password' } }
|
745
|
+
|
746
|
+
its(:user){ should == username.call }
|
747
|
+
its(:passwd){ should == password.call }
|
748
|
+
its(:to_str){ should == ["#{username.call}:#{password.call}"].pack('m').tr("\n", '') }
|
749
|
+
end
|
750
|
+
end
|
751
|
+
end
|
752
|
+
end
|