ncfoundry 4.9.2
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/.gitignore +8 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/Checkfile +2 -0
- data/Gemfile +3 -0
- data/LICENSE +987 -0
- data/NOTICE +10 -0
- data/README.md +9 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/cfoundry.gemspec +41 -0
- data/config/locales/en.yml +168 -0
- data/lib/cc_api_stub/app_usage_events.rb +11 -0
- data/lib/cc_api_stub/applications.rb +57 -0
- data/lib/cc_api_stub/domains.rb +32 -0
- data/lib/cc_api_stub/events.rb +11 -0
- data/lib/cc_api_stub/frameworks.rb +22 -0
- data/lib/cc_api_stub/helper.rb +148 -0
- data/lib/cc_api_stub/login.rb +21 -0
- data/lib/cc_api_stub/organization_users.rb +27 -0
- data/lib/cc_api_stub/organizations.rb +82 -0
- data/lib/cc_api_stub/routes.rb +26 -0
- data/lib/cc_api_stub/runtimes.rb +22 -0
- data/lib/cc_api_stub/service_bindings.rb +22 -0
- data/lib/cc_api_stub/service_instances.rb +22 -0
- data/lib/cc_api_stub/services.rb +21 -0
- data/lib/cc_api_stub/space_users.rb +27 -0
- data/lib/cc_api_stub/spaces.rb +58 -0
- data/lib/cc_api_stub/users.rb +85 -0
- data/lib/cc_api_stub.rb +20 -0
- data/lib/cfoundry/auth_token.rb +62 -0
- data/lib/cfoundry/baseclient.rb +220 -0
- data/lib/cfoundry/chatty_hash.rb +46 -0
- data/lib/cfoundry/client.rb +42 -0
- data/lib/cfoundry/concerns/login_helpers.rb +14 -0
- data/lib/cfoundry/concerns/proxy_options.rb +14 -0
- data/lib/cfoundry/errors.rb +163 -0
- data/lib/cfoundry/rest_client.rb +316 -0
- data/lib/cfoundry/test_support.rb +3 -0
- data/lib/cfoundry/trace_helpers.rb +64 -0
- data/lib/cfoundry/uaaclient.rb +151 -0
- data/lib/cfoundry/upload_helpers.rb +222 -0
- data/lib/cfoundry/v2/app.rb +313 -0
- data/lib/cfoundry/v2/app_event.rb +13 -0
- data/lib/cfoundry/v2/app_instance.rb +74 -0
- data/lib/cfoundry/v2/app_usage_event.rb +14 -0
- data/lib/cfoundry/v2/base.rb +112 -0
- data/lib/cfoundry/v2/client.rb +104 -0
- data/lib/cfoundry/v2/domain.rb +20 -0
- data/lib/cfoundry/v2/event.rb +17 -0
- data/lib/cfoundry/v2/helper.rb +11 -0
- data/lib/cfoundry/v2/managed_service_instance.rb +13 -0
- data/lib/cfoundry/v2/model.rb +213 -0
- data/lib/cfoundry/v2/model_magic/attribute.rb +49 -0
- data/lib/cfoundry/v2/model_magic/client_extensions.rb +170 -0
- data/lib/cfoundry/v2/model_magic/has_summary.rb +49 -0
- data/lib/cfoundry/v2/model_magic/query_multi_value_helper.rb +21 -0
- data/lib/cfoundry/v2/model_magic/query_value_helper.rb +33 -0
- data/lib/cfoundry/v2/model_magic/queryable_by.rb +39 -0
- data/lib/cfoundry/v2/model_magic/to_many.rb +145 -0
- data/lib/cfoundry/v2/model_magic/to_one.rb +81 -0
- data/lib/cfoundry/v2/model_magic.rb +134 -0
- data/lib/cfoundry/v2/organization.rb +44 -0
- data/lib/cfoundry/v2/quota_definition.rb +12 -0
- data/lib/cfoundry/v2/route.rb +25 -0
- data/lib/cfoundry/v2/service.rb +22 -0
- data/lib/cfoundry/v2/service_auth_token.rb +9 -0
- data/lib/cfoundry/v2/service_binding.rb +10 -0
- data/lib/cfoundry/v2/service_broker.rb +12 -0
- data/lib/cfoundry/v2/service_instance.rb +14 -0
- data/lib/cfoundry/v2/service_plan.rb +16 -0
- data/lib/cfoundry/v2/space.rb +31 -0
- data/lib/cfoundry/v2/stack.rb +10 -0
- data/lib/cfoundry/v2/user.rb +97 -0
- data/lib/cfoundry/v2/user_provided_service_instance.rb +16 -0
- data/lib/cfoundry/validator.rb +41 -0
- data/lib/cfoundry/version.rb +4 -0
- data/lib/cfoundry/zip.rb +56 -0
- data/lib/cfoundry.rb +6 -0
- data/release_notes/release_1_5_3.md +177 -0
- data/release_notes/release_2.3.1.md +14 -0
- data/release_notes/release_2.3.3.md +38 -0
- data/release_notes/release_2.3.4.md +16 -0
- data/release_notes/release_2.3.5.md +14 -0
- data/release_notes/release_2.3.6.md +14 -0
- data/release_notes/release_2.3.6.rc1.md +29 -0
- data/release_notes/release_2.3.6.rc2.md +19 -0
- data/release_notes/release_2.3.7.rc1.md +14 -0
- data/release_notes/release_2.4.0.md +41 -0
- data/release_notes/release_2.4.1.rc1.md +58 -0
- data/release_notes/release_3.0.0.md +21 -0
- data/release_notes/release_3.0.1.md +16 -0
- data/release_notes/release_3.0.2.rc1.md +19 -0
- data/release_notes/release_4.0.0.md +19 -0
- data/release_notes/release_4.0.1.md +14 -0
- data/release_notes/release_4.0.2.rc1.md +14 -0
- data/release_notes/release_4.0.2.rc2.md +11 -0
- data/release_notes/release_4.0.2.rc3.md +11 -0
- data/release_notes/release_4.0.2.rc4.md +19 -0
- data/release_notes/release_4.0.2.rc5.md +14 -0
- data/release_notes/release_4.0.3.md +19 -0
- data/release_notes/release_4.0.4.rc1.md +14 -0
- data/release_notes/release_4.0.4.rc2.md +14 -0
- data/release_notes/release_4.1.0.md +19 -0
- data/release_notes/release_4.2.0.rc.md +24 -0
- data/release_notes/release_4.3.0.md +22 -0
- data/release_notes/release_4.3.1.md +14 -0
- data/release_notes/release_4.3.10.md +14 -0
- data/release_notes/release_4.3.11.md +14 -0
- data/release_notes/release_4.3.12.md +14 -0
- data/release_notes/release_4.3.2.rc1.md +21 -0
- data/release_notes/release_4.3.3.md +24 -0
- data/release_notes/release_4.3.4.md +11 -0
- data/release_notes/release_4.3.4.rc1.md +24 -0
- data/release_notes/release_4.3.5.md +36 -0
- data/release_notes/release_4.3.5.rc1.md +21 -0
- data/release_notes/release_4.3.6.md +14 -0
- data/release_notes/release_4.3.7.md +50 -0
- data/release_notes/release_4.3.8.md +19 -0
- data/release_notes/release_4.3.9.md +14 -0
- data/release_notes/release_4.4.0.md +16 -0
- data/release_notes/release_4.5.1.md +11 -0
- data/release_notes/release_4.5.2.md +14 -0
- data/release_notes/release_4.5.3.md +29 -0
- data/release_notes/release_4.6.0.md +24 -0
- data/release_notes/release_4.6.1.md +14 -0
- data/release_notes/release_4.6.2.md +16 -0
- data/release_notes/release_4.6.3.rc1.md +14 -0
- data/release_notes/release_4.6.3.rc2.md +14 -0
- data/release_notes/release_4.6.3.rc3.md +17 -0
- data/release_notes/release_4.7.0.md +11 -0
- data/release_notes/release_4.7.1.md +14 -0
- data/release_notes/release_4.7.1.rc.1.md +14 -0
- data/release_notes/release_4.7.1.rc1.md +19 -0
- data/script/gpp +3 -0
- data/spec/cc_api_stub/app_usage_events_spec.rb +12 -0
- data/spec/cc_api_stub/applications_spec.rb +69 -0
- data/spec/cc_api_stub/domains_spec.rb +40 -0
- data/spec/cc_api_stub/events_spec.rb +12 -0
- data/spec/cc_api_stub/frameworks_spec.rb +19 -0
- data/spec/cc_api_stub/login_spec.rb +20 -0
- data/spec/cc_api_stub/organization_users_spec.rb +35 -0
- data/spec/cc_api_stub/organizations_spec.rb +118 -0
- data/spec/cc_api_stub/routes_spec.rb +19 -0
- data/spec/cc_api_stub/runtimes_spec.rb +19 -0
- data/spec/cc_api_stub/service_bindings_spec.rb +13 -0
- data/spec/cc_api_stub/service_instances_spec.rb +19 -0
- data/spec/cc_api_stub/services_spec.rb +11 -0
- data/spec/cc_api_stub/space_users_spec.rb +35 -0
- data/spec/cc_api_stub/spaces_spec.rb +38 -0
- data/spec/cc_api_stub/users_spec.rb +107 -0
- data/spec/cfoundry/auth_token_spec.rb +153 -0
- data/spec/cfoundry/baseclient_spec.rb +284 -0
- data/spec/cfoundry/client_spec.rb +13 -0
- data/spec/cfoundry/errors_spec.rb +117 -0
- data/spec/cfoundry/rest_client_spec.rb +367 -0
- data/spec/cfoundry/trace_helpers_spec.rb +91 -0
- data/spec/cfoundry/uaaclient_spec.rb +421 -0
- data/spec/cfoundry/upload_helpers_spec.rb +182 -0
- data/spec/cfoundry/v2/app_event_spec.rb +97 -0
- data/spec/cfoundry/v2/app_instance_spec.rb +31 -0
- data/spec/cfoundry/v2/app_spec.rb +354 -0
- data/spec/cfoundry/v2/app_usage_event_spec.rb +15 -0
- data/spec/cfoundry/v2/base_spec.rb +375 -0
- data/spec/cfoundry/v2/client_spec.rb +121 -0
- data/spec/cfoundry/v2/domain_spec.rb +63 -0
- data/spec/cfoundry/v2/event_spec.rb +15 -0
- data/spec/cfoundry/v2/managed_service_instance_spec.rb +149 -0
- data/spec/cfoundry/v2/model_magic/attribute_spec.rb +123 -0
- data/spec/cfoundry/v2/model_magic/has_summary_spec.rb +17 -0
- data/spec/cfoundry/v2/model_magic/to_many_spec.rb +53 -0
- data/spec/cfoundry/v2/model_magic/to_one_spec.rb +106 -0
- data/spec/cfoundry/v2/model_magic_spec.rb +43 -0
- data/spec/cfoundry/v2/model_spec.rb +472 -0
- data/spec/cfoundry/v2/organization_spec.rb +282 -0
- data/spec/cfoundry/v2/quota_definition_spec.rb +50 -0
- data/spec/cfoundry/v2/route_spec.rb +42 -0
- data/spec/cfoundry/v2/service_plan_spec.rb +53 -0
- data/spec/cfoundry/v2/service_spec.rb +58 -0
- data/spec/cfoundry/v2/space_spec.rb +160 -0
- data/spec/cfoundry/v2/user_provided_service_instance_spec.rb +57 -0
- data/spec/cfoundry/v2/user_spec.rb +206 -0
- data/spec/cfoundry/validator_spec.rb +94 -0
- data/spec/factories/app_events_factory.rb +7 -0
- data/spec/factories/app_usage_events_factory.rb +32 -0
- data/spec/factories/apps_factory.rb +11 -0
- data/spec/factories/clients_factory.rb +7 -0
- data/spec/factories/domains_factory.rb +10 -0
- data/spec/factories/events_factory.rb +50 -0
- data/spec/factories/organizations_factory.rb +12 -0
- data/spec/factories/quota_definitions_factory.rb +8 -0
- data/spec/factories/routes_factory.rb +10 -0
- data/spec/factories/service_instances_factory.rb +10 -0
- data/spec/factories/service_plans_factory.rb +10 -0
- data/spec/factories/services_factory.rb +10 -0
- data/spec/factories/spaces_factory.rb +10 -0
- data/spec/factories/user_provided_service_instances_factory.rb +10 -0
- data/spec/factories/users_factory.rb +10 -0
- data/spec/fixtures/apps/with_cfignore/.cfignore +4 -0
- data/spec/fixtures/apps/with_cfignore/.hidden_file +1 -0
- data/spec/fixtures/apps/with_cfignore/ambiguous_ignored +0 -0
- data/spec/fixtures/apps/with_cfignore/ignored_dir/file_in_ignored_dir.txt +1 -0
- data/spec/fixtures/apps/with_cfignore/ignored_file.txt +1 -0
- data/spec/fixtures/apps/with_cfignore/non_ignored_dir/file_in_non_ignored_dir.txt +1 -0
- data/spec/fixtures/apps/with_cfignore/non_ignored_dir/ignored_file.txt +1 -0
- data/spec/fixtures/apps/with_cfignore/non_ignored_dir/toplevel_ignored.txt +0 -0
- data/spec/fixtures/apps/with_cfignore/non_ignored_file.txt +1 -0
- data/spec/fixtures/apps/with_cfignore/toplevel_ignored.txt +0 -0
- data/spec/fixtures/apps/with_dotfiles/.dotfile +1 -0
- data/spec/fixtures/apps/with_dotfiles/xyz +1 -0
- data/spec/fixtures/apps/with_external_symlink/foo +1 -0
- data/spec/fixtures/apps/with_ignored_external_symlink/.cfignore +1 -0
- data/spec/fixtures/apps/with_ignored_external_symlink/foo +1 -0
- data/spec/fixtures/apps/with_nested_directories/foo/bar/baz/fizz +0 -0
- data/spec/fixtures/apps/with_nested_directories/xyz +0 -0
- data/spec/fixtures/empty_file +0 -0
- data/spec/fixtures/fake_cc_app_usage_events.json +152 -0
- data/spec/fixtures/fake_cc_application.json +20 -0
- data/spec/fixtures/fake_cc_application_summary.json +56 -0
- data/spec/fixtures/fake_cc_created_application.json +11 -0
- data/spec/fixtures/fake_cc_created_domain.json +15 -0
- data/spec/fixtures/fake_cc_created_organization.json +11 -0
- data/spec/fixtures/fake_cc_created_route.json +13 -0
- data/spec/fixtures/fake_cc_created_service_instance.json +11 -0
- data/spec/fixtures/fake_cc_created_space.json +11 -0
- data/spec/fixtures/fake_cc_created_user.json +11 -0
- data/spec/fixtures/fake_cc_domain.json +55 -0
- data/spec/fixtures/fake_cc_domain_spaces.json +27 -0
- data/spec/fixtures/fake_cc_empty_search.json +7 -0
- data/spec/fixtures/fake_cc_events.json +419 -0
- data/spec/fixtures/fake_cc_frameworks.json +20 -0
- data/spec/fixtures/fake_cc_managed_service_instance.json +83 -0
- data/spec/fixtures/fake_cc_organization.json +161 -0
- data/spec/fixtures/fake_cc_organization_domains.json +59 -0
- data/spec/fixtures/fake_cc_organization_search.json +37 -0
- data/spec/fixtures/fake_cc_organization_spaces.json +99 -0
- data/spec/fixtures/fake_cc_organization_summary.json +20 -0
- data/spec/fixtures/fake_cc_organization_users.json +81 -0
- data/spec/fixtures/fake_cc_route.json +16 -0
- data/spec/fixtures/fake_cc_runtimes.json +20 -0
- data/spec/fixtures/fake_cc_service_binding.json +22 -0
- data/spec/fixtures/fake_cc_service_bindings.json +24 -0
- data/spec/fixtures/fake_cc_service_instance.json +83 -0
- data/spec/fixtures/fake_cc_service_instances.json +72 -0
- data/spec/fixtures/fake_cc_services.json +160 -0
- data/spec/fixtures/fake_cc_space.json +45 -0
- data/spec/fixtures/fake_cc_space_apps.json +49 -0
- data/spec/fixtures/fake_cc_space_summary.json +84 -0
- data/spec/fixtures/fake_cc_spaces.json +92 -0
- data/spec/fixtures/fake_cc_stats.json +29 -0
- data/spec/fixtures/fake_cc_user.json +139 -0
- data/spec/fixtures/fake_cc_user_organizations.json +92 -0
- data/spec/fixtures/fake_cc_user_provided_service_instance.json +51 -0
- data/spec/fixtures/fake_cc_user_with_managers.json +85 -0
- data/spec/integration/client_spec.rb +38 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/factory_girl.rb +6 -0
- data/spec/support/shared_examples/cc_api_stub_request_examples.rb +79 -0
- data/spec/support/shared_examples/client_login_examples.rb +46 -0
- data/spec/support/shared_examples/model_summary_examples.rb +34 -0
- data/spec/support/test_model_builder.rb +10 -0
- data/vendor/errors/v1.yml +189 -0
- data/vendor/errors/v2.yml +845 -0
- metadata +712 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'Errors' do
|
|
4
|
+
describe CFoundry::Timeout do
|
|
5
|
+
let(:parent) { Timeout::Error.new }
|
|
6
|
+
|
|
7
|
+
subject { CFoundry::Timeout.new("POST", '/blah', parent) }
|
|
8
|
+
|
|
9
|
+
describe '#to_s' do
|
|
10
|
+
subject { super().to_s }
|
|
11
|
+
it { should eq "POST /blah timed out" }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '#method' do
|
|
15
|
+
subject { super().method }
|
|
16
|
+
it { should eq "POST" }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe '#uri' do
|
|
20
|
+
subject { super().uri }
|
|
21
|
+
it { should eq '/blah' }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#parent' do
|
|
25
|
+
subject { super().parent }
|
|
26
|
+
it { should eq parent }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe CFoundry::InvalidTarget do
|
|
31
|
+
let(:target) { "http://--foo-bar" }
|
|
32
|
+
subject { CFoundry::InvalidTarget.new(target) }
|
|
33
|
+
|
|
34
|
+
describe '#to_s' do
|
|
35
|
+
subject { super().to_s }
|
|
36
|
+
it { should eq "Invalid target URI: #{target}"}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe '#target' do
|
|
40
|
+
subject { super().target }
|
|
41
|
+
it { should eq target }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe CFoundry::APIError do
|
|
46
|
+
let(:request) { { :method => "GET", :url => "http://api.example.com/foo", :headers => {} } }
|
|
47
|
+
let(:response_body) { "NOT FOUND" }
|
|
48
|
+
let(:response) { { :status => 404, :headers => {}, :body => response_body } }
|
|
49
|
+
|
|
50
|
+
subject { CFoundry::APIError.new(nil, nil, request, response) }
|
|
51
|
+
|
|
52
|
+
describe '#to_s' do
|
|
53
|
+
subject { super().to_s }
|
|
54
|
+
it { should eq "404: NOT FOUND" }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#request' do
|
|
58
|
+
subject { super().request }
|
|
59
|
+
it { should eq request }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe '#response' do
|
|
63
|
+
subject { super().response }
|
|
64
|
+
it { should eq response }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "#initialize" do
|
|
68
|
+
|
|
69
|
+
context "Response body is JSON" do
|
|
70
|
+
|
|
71
|
+
let(:response_body) { "{\"description\":\"Something went wrong\"}"}
|
|
72
|
+
|
|
73
|
+
it "sets description to description field in parsed JSON" do
|
|
74
|
+
expect(CFoundry::APIError.new(nil, nil, request, response).description).to eq("Something went wrong")
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
context "Response body is not JSON" do
|
|
80
|
+
|
|
81
|
+
let(:response_body) { "Some plain text"}
|
|
82
|
+
|
|
83
|
+
it "sets description to body text" do
|
|
84
|
+
expect(CFoundry::APIError.new(nil, nil, request, response).description).to eq("Some plain text")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "allows override of description" do
|
|
89
|
+
expect(CFoundry::APIError.new("My description", nil, request, response).description).to eq("My description")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe "#request_trace" do
|
|
95
|
+
describe '#request_trace' do
|
|
96
|
+
subject { super().request_trace }
|
|
97
|
+
it { should include "REQUEST: " }
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe "#response_trace" do
|
|
102
|
+
describe '#response_trace' do
|
|
103
|
+
subject { super().response_trace }
|
|
104
|
+
it { should include "RESPONSE: " }
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "sets error code to response error code by default" do
|
|
109
|
+
expect(CFoundry::APIError.new(nil, nil, request, response).error_code).to eq(404)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "allows override of error code" do
|
|
113
|
+
expect(CFoundry::APIError.new(nil, 303, request, response).error_code).to eq(303)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe CFoundry::RestClient do
|
|
4
|
+
let(:token) { nil }
|
|
5
|
+
let(:target) { "https://api.example.com" }
|
|
6
|
+
let(:rest_client) { CFoundry::RestClient.new(target, token) }
|
|
7
|
+
|
|
8
|
+
describe '#request' do
|
|
9
|
+
let(:path) { "some-path" }
|
|
10
|
+
let(:url) { "#{target}/#{path}" }
|
|
11
|
+
let(:verb) { "GET" }
|
|
12
|
+
let(:options) { {} }
|
|
13
|
+
|
|
14
|
+
def check_request(verb = :get, &block)
|
|
15
|
+
request_stub = stub_request(verb, url).to_return do |req|
|
|
16
|
+
block.call(req)
|
|
17
|
+
{}
|
|
18
|
+
end
|
|
19
|
+
subject
|
|
20
|
+
expect(request_stub).to have_been_requested
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
subject { rest_client.request(verb, path, options) }
|
|
24
|
+
|
|
25
|
+
describe 'headers' do
|
|
26
|
+
%w[Authorization X-Request-Id Content-Type].each do |header_name|
|
|
27
|
+
it "should not include the #{header_name} by default" do
|
|
28
|
+
check_request do |req|
|
|
29
|
+
expect(req.headers).not_to have_key(header_name)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should not provide specific accept mimetypes by default" do
|
|
35
|
+
check_request do |req|
|
|
36
|
+
expect(req.headers["Accept"]).to eql("*/*")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'should always include a content length' do
|
|
41
|
+
check_request do |req|
|
|
42
|
+
expect(req.headers["Content-Length"]).to eql(0)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "when a payload is passed" do
|
|
47
|
+
context "when the payload is a string" do
|
|
48
|
+
let(:options) { { :payload => "some payload"} }
|
|
49
|
+
|
|
50
|
+
it 'includes a content length matching the payload size' do
|
|
51
|
+
check_request do |req|
|
|
52
|
+
expect(req.headers["Content-Length"]).to eql("some payload".length)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "when the payload is a hash and the content-type is JSON" do
|
|
58
|
+
let(:options) { { :payload => { "key" => "value" }, :content => :json } }
|
|
59
|
+
|
|
60
|
+
it 'includes a content length matching the JSON encoded length' do
|
|
61
|
+
check_request do |req|
|
|
62
|
+
expect(req.headers["Content-Length"]).to eql('{"key":"value"}'.length)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when the payload is a hash (i.e. multipart upload)" do
|
|
68
|
+
let(:verb) { "PUT" }
|
|
69
|
+
let(:options) { {:payload => {"key" => "value"}} }
|
|
70
|
+
|
|
71
|
+
it 'includes a nonzero content length' do
|
|
72
|
+
check_request(:put) do |req|
|
|
73
|
+
expect(req.headers["Content-Length"].to_i).to be > 0
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context "when params are passed" do
|
|
80
|
+
context "when params is an empty hash" do
|
|
81
|
+
let(:options) { {:params => {}} }
|
|
82
|
+
|
|
83
|
+
it "does not add a query string delimiter (the question mark)" do
|
|
84
|
+
request_stub = stub_request(:get, "https://api.example.com/some-path")
|
|
85
|
+
subject
|
|
86
|
+
expect(request_stub).to have_been_requested
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "when params has values" do
|
|
91
|
+
let(:options) { {:params => {"key" => "value"}} }
|
|
92
|
+
|
|
93
|
+
it "appends a query string and delimiter" do
|
|
94
|
+
request_stub = stub_request(:get, "https://api.example.com/some-path?key=value")
|
|
95
|
+
subject
|
|
96
|
+
expect(request_stub).to have_been_requested
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context 'and the token is set' do
|
|
102
|
+
let(:token_header) { "bearer something" }
|
|
103
|
+
let(:token) { CFoundry::AuthToken.new(token_header) }
|
|
104
|
+
|
|
105
|
+
it 'should include Authorization in the header' do
|
|
106
|
+
check_request do |req|
|
|
107
|
+
expect(req.headers["Authorization"]).to eq(token_header)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'and the request_id is set' do
|
|
113
|
+
before { rest_client.request_id = "SomeRequestId" }
|
|
114
|
+
|
|
115
|
+
it 'should include X-Request-Id in the header' do
|
|
116
|
+
check_request do |req|
|
|
117
|
+
expect(req.headers["X-Request-Id"]).to eq "SomeRequestId"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context 'and the content is passed in' do
|
|
123
|
+
let(:options) { {:content => "text/xml"} }
|
|
124
|
+
|
|
125
|
+
it 'should include Content-Type in the header' do
|
|
126
|
+
check_request do |req|
|
|
127
|
+
expect(req.headers["Content-Type"]).to eq "text/xml"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context 'and custom headers are passed in' do
|
|
133
|
+
let(:options) { {:headers => {"X-Foo" => "Bar"}} }
|
|
134
|
+
|
|
135
|
+
it 'should include the custom header in the header' do
|
|
136
|
+
check_request do |req|
|
|
137
|
+
expect(req.headers["X-Foo"]).to eq "Bar"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context 'and it overrides an existing one' do
|
|
142
|
+
let(:options) { {:content => "text/xml", :headers => {"Content-Type" => "text/html"}} }
|
|
143
|
+
|
|
144
|
+
it 'uses the custom header' do
|
|
145
|
+
check_request do |req|
|
|
146
|
+
expect(req.headers["Content-Type"]).to eq "text/html"
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
describe 'errors' do
|
|
154
|
+
context "when the target refuses the connection" do
|
|
155
|
+
let(:target) { "http://localhost:2358974958" }
|
|
156
|
+
|
|
157
|
+
it "raises CFoundry::TargetRefused" do
|
|
158
|
+
stub_request(:get, url).to_raise(Errno::ECONNREFUSED)
|
|
159
|
+
expect { subject }.to raise_error(CFoundry::TargetRefused)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
context "when the target is not a HTTP(S) URI" do
|
|
164
|
+
let(:target) { "ftp://foo-bar.com" }
|
|
165
|
+
|
|
166
|
+
it "raises CFoundry::InvalidTarget" do
|
|
167
|
+
expect { subject }.to raise_error(CFoundry::InvalidTarget)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context "when the target URI is invalid" do
|
|
172
|
+
let(:target) { "@#*#^! rubby" }
|
|
173
|
+
|
|
174
|
+
it "raises CFoundry::InvalidTarget" do
|
|
175
|
+
expect { subject }.to raise_error(CFoundry::InvalidTarget)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
describe "the return value" do
|
|
181
|
+
before do
|
|
182
|
+
stub_request(:get, url).to_return({
|
|
183
|
+
:status => 201,
|
|
184
|
+
:headers => {"Content-Type" => "application/json"},
|
|
185
|
+
:body => '{ "foo": 1 }'
|
|
186
|
+
})
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "returns a request hash and a response hash" do
|
|
190
|
+
expect(subject).to be_an(Array)
|
|
191
|
+
expect(subject.length).to eq(2)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
describe "the returned request hash" do
|
|
195
|
+
it "returns a hash of :headers, :url, :body and :verb" do
|
|
196
|
+
expect(subject[0]).to eq({
|
|
197
|
+
:url => url,
|
|
198
|
+
:method => "GET",
|
|
199
|
+
:headers => {"Content-Length" => 0},
|
|
200
|
+
:body => nil
|
|
201
|
+
})
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
describe "the returned response hash" do
|
|
206
|
+
it "returns a hash of :headers, :status, :body" do
|
|
207
|
+
expect(subject[1]).to eq({
|
|
208
|
+
:status => "201",
|
|
209
|
+
:headers => {"content-type" => "application/json"},
|
|
210
|
+
:body => '{ "foo": 1 }'
|
|
211
|
+
})
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
describe "when the path starts with a slash" do
|
|
217
|
+
let(:path) { "/some-path/some-segment" }
|
|
218
|
+
|
|
219
|
+
it "doesn't add a double slash" do
|
|
220
|
+
stub = stub_request(:get, "https://api.example.com/some-path/some-segment")
|
|
221
|
+
subject
|
|
222
|
+
expect(stub).to have_been_requested
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
describe "when the path does not start with a slash" do
|
|
227
|
+
let(:path) { "some-path/some-segment" }
|
|
228
|
+
|
|
229
|
+
it "doesn't add a double slash" do
|
|
230
|
+
stub = stub_request(:get, "https://api.example.com/some-path/some-segment")
|
|
231
|
+
subject
|
|
232
|
+
expect(stub).to have_been_requested
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
describe "when the path is a full url" do
|
|
237
|
+
let(:path) { "http://example.com" }
|
|
238
|
+
|
|
239
|
+
it "requests the given url" do
|
|
240
|
+
stub = stub_request(:get, "http://example.com")
|
|
241
|
+
subject
|
|
242
|
+
expect(stub).to have_been_requested
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
describe "when the path is malformed" do
|
|
247
|
+
let(:path) { "#%&*$(#%&$%)" }
|
|
248
|
+
|
|
249
|
+
it "blows up" do
|
|
250
|
+
expect { subject }.to raise_error(URI::InvalidURIError)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
describe 'trace' do
|
|
255
|
+
before do
|
|
256
|
+
rest_client.trace = true
|
|
257
|
+
stub_request(:get, url).to_return(:status => 200, :headers => {"content-type" => "application/json"}, :body => '{"some": "json"}')
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it "prints the request and the response" do
|
|
261
|
+
expect(rest_client).to receive(:print_request).with({:headers => {"Content-Length" => 0}, :url => "https://api.example.com/some-path", :method => "GET", :body => nil})
|
|
262
|
+
expect(rest_client).to receive(:print_response).with({:status => "200", :headers => {"content-type" => "application/json"}, :body => '{"some": "json"}'})
|
|
263
|
+
subject
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
describe "following redirects" do
|
|
268
|
+
before do
|
|
269
|
+
stub_request(:post, "https://api.example.com/apps").to_return(
|
|
270
|
+
:status => 301,
|
|
271
|
+
:headers => {"location" => "https://api.example.com/apps/some-guid"}
|
|
272
|
+
)
|
|
273
|
+
stub_request(:get, "https://api.example.com/apps/some-guid").to_return(
|
|
274
|
+
:status => 200,
|
|
275
|
+
:body => '{"some": "json"}'
|
|
276
|
+
)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "follows redirects correctly, returning the response to the 2nd redirect" do
|
|
280
|
+
request, response = rest_client.request("POST", "apps")
|
|
281
|
+
expect(response).to eql(
|
|
282
|
+
:status => "200",
|
|
283
|
+
:headers => {},
|
|
284
|
+
:body => '{"some": "json"}'
|
|
285
|
+
)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
describe CFoundry::RestClient::HTTPFactory do
|
|
291
|
+
describe ".create" do
|
|
292
|
+
let(:proxy_options) { [] }
|
|
293
|
+
let(:target_uri) { "http://api.example.com" }
|
|
294
|
+
|
|
295
|
+
subject { CFoundry::RestClient::HTTPFactory.create(URI.parse(target_uri), proxy_options) }
|
|
296
|
+
|
|
297
|
+
context "when no proxy URI is set" do
|
|
298
|
+
before do
|
|
299
|
+
@original_no_proxy_env = ENV["NO_PROXY"]
|
|
300
|
+
ENV["NO_PROXY"] = "example.com"
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
after do
|
|
304
|
+
ENV["NO_PROXY"] = @original_no_proxy_env
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
it "should return an instance of the plain Net:HTTP class" do
|
|
308
|
+
expect(subject).to be_instance_of(Net::HTTP)
|
|
309
|
+
expect(subject.use_ssl?).to be_falsey
|
|
310
|
+
expect(subject.proxy?).to_not be_truthy
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
context "when the target is an https URI" do
|
|
315
|
+
before do
|
|
316
|
+
@original_no_proxy_env = ENV["NO_PROXY"]
|
|
317
|
+
ENV["NO_PROXY"] = "example.com"
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
after do
|
|
321
|
+
ENV["NO_PROXY"] = @original_no_proxy_env
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
let(:target_uri) { "https://example.com" }
|
|
325
|
+
it "should return an instance of the plain Net:HTTP class with use_ssl" do
|
|
326
|
+
expect(subject).to be_instance_of(Net::HTTP)
|
|
327
|
+
expect(subject.use_ssl?).to be_truthy
|
|
328
|
+
expect(subject.proxy?).to_not be_truthy
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
context "when a http proxy URI without user/password is set " do
|
|
333
|
+
let(:proxy_options) { ["exapmle.com", 8080, nil, nil] }
|
|
334
|
+
|
|
335
|
+
it "should return an instance of the proxy class" do
|
|
336
|
+
expect(subject.proxy?).to be_truthy
|
|
337
|
+
expect(subject.proxy_address).to eql("exapmle.com")
|
|
338
|
+
expect(subject.proxy_port).to eql(8080)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
context "when a http proxy URI with user/password is set " do
|
|
343
|
+
let(:proxy_options) { ["exapmle.com", "8080", "user", "pass"] }
|
|
344
|
+
|
|
345
|
+
it "should return an instance of the proxy class" do
|
|
346
|
+
expect(subject.proxy?).to be_truthy
|
|
347
|
+
expect(subject.proxy_user).to eql("user")
|
|
348
|
+
expect(subject.proxy_pass).to eql("pass")
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
describe "#target=" do
|
|
355
|
+
let(:token) { "some-token" }
|
|
356
|
+
|
|
357
|
+
it "invalidates the token if the target has changed" do
|
|
358
|
+
rest_client.target = "http://some-target.com"
|
|
359
|
+
expect(rest_client.token).to be_nil
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
it "does not invalidate the token if the target has not changed" do
|
|
363
|
+
rest_client.target = target
|
|
364
|
+
expect(rest_client.token).to eq token
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe CFoundry::TraceHelpers do
|
|
4
|
+
let(:tracehelper_test_class) { Class.new { include CFoundry::TraceHelpers } }
|
|
5
|
+
let(:request) do
|
|
6
|
+
{
|
|
7
|
+
:method => "GET",
|
|
8
|
+
:url => "http://api.example.com/foo",
|
|
9
|
+
:headers => { "bb-foo" => "bar", "accept" => "*/*" }
|
|
10
|
+
}
|
|
11
|
+
end
|
|
12
|
+
let(:response) { { :status => 404, :body => "not found", :headers => {} } }
|
|
13
|
+
|
|
14
|
+
shared_examples "request_trace tests" do
|
|
15
|
+
it { should include request_trace }
|
|
16
|
+
it { should include header_trace }
|
|
17
|
+
it { should include body_trace }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
shared_examples "response_trace tests" do
|
|
21
|
+
before { response[:body] = response_body }
|
|
22
|
+
|
|
23
|
+
it "traces the provided response" do
|
|
24
|
+
expect(tracehelper_test_class.new.response_trace(response)).to eq(response_trace)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#request_trace" do
|
|
29
|
+
let(:request_trace) { "REQUEST: GET http://api.example.com/foo" }
|
|
30
|
+
let(:header_trace) { "REQUEST_HEADERS:\n accept : */*\n bb-foo : bar" }
|
|
31
|
+
let(:body_trace) { "" }
|
|
32
|
+
|
|
33
|
+
subject { tracehelper_test_class.new.request_trace(request) }
|
|
34
|
+
|
|
35
|
+
context "without a request body" do
|
|
36
|
+
include_examples "request_trace tests"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "with a request body" do
|
|
40
|
+
let(:body_trace) { "REQUEST_BODY: Some body text" }
|
|
41
|
+
|
|
42
|
+
before { request[:body] = "Some body text" }
|
|
43
|
+
|
|
44
|
+
include_examples "request_trace tests"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "returns nil if request is nil" do
|
|
48
|
+
expect(tracehelper_test_class.new.request_trace(nil)).to eq(nil)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "with protected attributes" do
|
|
52
|
+
let(:header_trace) { "REQUEST_HEADERS:\n Authorization : [PRIVATE DATA HIDDEN]" }
|
|
53
|
+
let(:request) do
|
|
54
|
+
{
|
|
55
|
+
:method => "GET",
|
|
56
|
+
:url => "http://api.example.com/foo",
|
|
57
|
+
:headers => { 'Authorization' => "SECRET STUFF" }
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
include_examples "request_trace tests"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
describe "#response_trace" do
|
|
66
|
+
context "with a non-JSON response body" do
|
|
67
|
+
let(:response_trace) { "RESPONSE: [404]\nRESPONSE_HEADERS:\n\nRESPONSE_BODY:\nSome body" }
|
|
68
|
+
let(:response_body) { "Some body"}
|
|
69
|
+
|
|
70
|
+
include_examples "response_trace tests"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "with a JSON response body" do
|
|
74
|
+
let(:response_body) { "{\"name\": \"vcap\",\"build\": 2222,\"support\": \"http://support.example.com\"}" }
|
|
75
|
+
let(:response_trace) { "RESPONSE: [404]\nRESPONSE_HEADERS:\n\nRESPONSE_BODY:\n#{MultiJson.dump(MultiJson.load(response_body), :pretty => true)}" }
|
|
76
|
+
|
|
77
|
+
include_examples "response_trace tests"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context "with credentials in the response body" do
|
|
81
|
+
let(:response_body) { '{"resources": [{"entity": {"credentials": {"super_secret_stuff": "goes here"}, "other_stuff": "still here"}}]}' }
|
|
82
|
+
let(:response_trace) { "RESPONSE: [404]\nRESPONSE_HEADERS:\n\nRESPONSE_BODY:\n#{MultiJson.dump({"resources" => [{"entity" => {"credentials" => "[PRIVATE DATA HIDDEN]", "other_stuff" => "still here"}}]}, :pretty => true)}" }
|
|
83
|
+
|
|
84
|
+
include_examples "response_trace tests"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "returns nil if response is nil" do
|
|
88
|
+
expect(tracehelper_test_class.new.response_trace(nil)).to eq(nil)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|