trucker-cli 0.0.1
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 +15 -0
- data/LICENSE +1277 -0
- data/Rakefile +13 -0
- data/bin/truck +18 -0
- data/lib/admin/README.md +30 -0
- data/lib/admin/curl.rb +59 -0
- data/lib/admin/guid.rb +89 -0
- data/lib/admin/plugin.rb +8 -0
- data/lib/admin/service_auth_token.rb +93 -0
- data/lib/admin/service_broker/add.rb +54 -0
- data/lib/admin/service_broker/remove.rb +33 -0
- data/lib/admin/service_broker/service_brokers.rb +29 -0
- data/lib/admin/service_broker/update.rb +60 -0
- data/lib/admin/set_quota.rb +44 -0
- data/lib/cf.rb +14 -0
- data/lib/cf/cli.rb +495 -0
- data/lib/cf/cli/app/app.rb +43 -0
- data/lib/cf/cli/app/apps.rb +87 -0
- data/lib/cf/cli/app/base.rb +72 -0
- data/lib/cf/cli/app/delete.rb +95 -0
- data/lib/cf/cli/app/deprecated.rb +11 -0
- data/lib/cf/cli/app/env.rb +99 -0
- data/lib/cf/cli/app/events.rb +45 -0
- data/lib/cf/cli/app/files.rb +137 -0
- data/lib/cf/cli/app/health.rb +26 -0
- data/lib/cf/cli/app/instances.rb +53 -0
- data/lib/cf/cli/app/logs.rb +76 -0
- data/lib/cf/cli/app/push.rb +104 -0
- data/lib/cf/cli/app/push/create.rb +108 -0
- data/lib/cf/cli/app/push/interactions.rb +90 -0
- data/lib/cf/cli/app/push/sync.rb +57 -0
- data/lib/cf/cli/app/rename.rb +35 -0
- data/lib/cf/cli/app/restart.rb +31 -0
- data/lib/cf/cli/app/scale.rb +63 -0
- data/lib/cf/cli/app/start.rb +175 -0
- data/lib/cf/cli/app/stats.rb +66 -0
- data/lib/cf/cli/app/stop.rb +27 -0
- data/lib/cf/cli/domain/base.rb +9 -0
- data/lib/cf/cli/domain/domains.rb +40 -0
- data/lib/cf/cli/domain/map.rb +55 -0
- data/lib/cf/cli/domain/unmap.rb +56 -0
- data/lib/cf/cli/help.rb +15 -0
- data/lib/cf/cli/interactive.rb +104 -0
- data/lib/cf/cli/login_requirements.rb +13 -0
- data/lib/cf/cli/organization/base.rb +12 -0
- data/lib/cf/cli/organization/create.rb +36 -0
- data/lib/cf/cli/organization/delete.rb +61 -0
- data/lib/cf/cli/organization/org.rb +45 -0
- data/lib/cf/cli/organization/orgs.rb +30 -0
- data/lib/cf/cli/organization/rename.rb +36 -0
- data/lib/cf/cli/populators/base.rb +16 -0
- data/lib/cf/cli/populators/organization.rb +32 -0
- data/lib/cf/cli/populators/populator_methods.rb +64 -0
- data/lib/cf/cli/populators/space.rb +33 -0
- data/lib/cf/cli/populators/target.rb +14 -0
- data/lib/cf/cli/route/base.rb +9 -0
- data/lib/cf/cli/route/delete.rb +28 -0
- data/lib/cf/cli/route/map.rb +68 -0
- data/lib/cf/cli/route/routes.rb +26 -0
- data/lib/cf/cli/route/unmap.rb +56 -0
- data/lib/cf/cli/service/base.rb +9 -0
- data/lib/cf/cli/service/bind.rb +43 -0
- data/lib/cf/cli/service/create.rb +158 -0
- data/lib/cf/cli/service/delete.rb +82 -0
- data/lib/cf/cli/service/rename.rb +35 -0
- data/lib/cf/cli/service/service.rb +40 -0
- data/lib/cf/cli/service/service_helper.rb +25 -0
- data/lib/cf/cli/service/service_instance_helper.rb +100 -0
- data/lib/cf/cli/service/services.rb +110 -0
- data/lib/cf/cli/service/unbind.rb +36 -0
- data/lib/cf/cli/space/base.rb +27 -0
- data/lib/cf/cli/space/create.rb +66 -0
- data/lib/cf/cli/space/delete.rb +55 -0
- data/lib/cf/cli/space/rename.rb +38 -0
- data/lib/cf/cli/space/space.rb +66 -0
- data/lib/cf/cli/space/spaces.rb +57 -0
- data/lib/cf/cli/space/switch.rb +18 -0
- data/lib/cf/cli/start/base.rb +35 -0
- data/lib/cf/cli/start/colors.rb +13 -0
- data/lib/cf/cli/start/login.rb +104 -0
- data/lib/cf/cli/start/logout.rb +17 -0
- data/lib/cf/cli/start/target.rb +50 -0
- data/lib/cf/cli/start/target_prettifier.rb +35 -0
- data/lib/cf/cli/start/targets.rb +16 -0
- data/lib/cf/cli/user/base.rb +29 -0
- data/lib/cf/cli/user/create.rb +51 -0
- data/lib/cf/cli/user/passwd.rb +36 -0
- data/lib/cf/cli/user/register.rb +42 -0
- data/lib/cf/cli/user/users.rb +32 -0
- data/lib/cf/constants.rb +10 -0
- data/lib/cf/errors.rb +19 -0
- data/lib/cf/plugin.rb +56 -0
- data/lib/cf/spacing.rb +89 -0
- data/lib/cf/spec_helper.rb +1 -0
- data/lib/cf/test_support.rb +6 -0
- data/lib/cf/version.rb +3 -0
- data/lib/console/README.md +16 -0
- data/lib/console/console.rb +187 -0
- data/lib/console/plugin.rb +32 -0
- data/lib/manifests/errors.rb +35 -0
- data/lib/manifests/loader.rb +31 -0
- data/lib/manifests/loader/builder.rb +39 -0
- data/lib/manifests/loader/normalizer.rb +145 -0
- data/lib/manifests/loader/resolver.rb +79 -0
- data/lib/manifests/manifests.rb +343 -0
- data/lib/manifests/plugin.rb +140 -0
- data/lib/micro/README.md +25 -0
- data/lib/micro/errors.rb +4 -0
- data/lib/micro/micro.rb +56 -0
- data/lib/micro/plugin.rb +197 -0
- data/lib/micro/switcher/base.rb +79 -0
- data/lib/micro/switcher/darwin.rb +21 -0
- data/lib/micro/switcher/dummy.rb +15 -0
- data/lib/micro/switcher/linux.rb +16 -0
- data/lib/micro/switcher/windows.rb +31 -0
- data/lib/micro/vmrun.rb +175 -0
- data/lib/tasks/gem_release.rake +56 -0
- data/lib/tasks/windows_build.rake +14 -0
- data/lib/tunnel/README.md +29 -0
- data/lib/tunnel/config/clients.yml +17 -0
- data/lib/tunnel/helper-app/Gemfile +10 -0
- data/lib/tunnel/helper-app/Gemfile.lock +48 -0
- data/lib/tunnel/helper-app/server.rb +43 -0
- data/lib/tunnel/plugin.rb +183 -0
- data/lib/tunnel/tunnel.rb +295 -0
- data/spec/admin/curl_spec.rb +52 -0
- data/spec/admin/guid_spec.rb +85 -0
- data/spec/admin/service_broker/add_spec.rb +64 -0
- data/spec/admin/service_broker/remove_spec.rb +46 -0
- data/spec/admin/service_broker/service_brokers_spec.rb +34 -0
- data/spec/admin/service_broker/update_spec.rb +51 -0
- data/spec/admin/set_quota_spec.rb +89 -0
- data/spec/assets/env/Gemfile +4 -0
- data/spec/assets/env/Gemfile.lock +20 -0
- data/spec/assets/env/env_test.rb +58 -0
- data/spec/assets/hello-sinatra/Gemfile +3 -0
- data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
- data/spec/assets/hello-sinatra/config.ru +3 -0
- data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
- data/spec/assets/hello-sinatra/main.rb +8 -0
- data/spec/assets/rails328_ruby187_app/Gemfile +39 -0
- data/spec/assets/rails328_ruby187_app/README.rdoc +261 -0
- data/spec/assets/rails328_ruby187_app/Rakefile +7 -0
- data/spec/assets/rails328_ruby187_app/app/assets/images/rails.png +0 -0
- data/spec/assets/rails328_ruby187_app/app/assets/javascripts/application.js +15 -0
- data/spec/assets/rails328_ruby187_app/app/assets/stylesheets/application.css +13 -0
- data/spec/assets/rails328_ruby187_app/app/controllers/application_controller.rb +3 -0
- data/spec/assets/rails328_ruby187_app/app/helpers/application_helper.rb +2 -0
- data/spec/assets/rails328_ruby187_app/app/views/layouts/application.html.erb +14 -0
- data/spec/assets/rails328_ruby187_app/config.ru +4 -0
- data/spec/assets/rails328_ruby187_app/config/application.rb +62 -0
- data/spec/assets/rails328_ruby187_app/config/boot.rb +6 -0
- data/spec/assets/rails328_ruby187_app/config/database.yml +25 -0
- data/spec/assets/rails328_ruby187_app/config/environment.rb +5 -0
- data/spec/assets/rails328_ruby187_app/config/environments/development.rb +37 -0
- data/spec/assets/rails328_ruby187_app/config/environments/production.rb +67 -0
- data/spec/assets/rails328_ruby187_app/config/environments/test.rb +37 -0
- data/spec/assets/rails328_ruby187_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/assets/rails328_ruby187_app/config/initializers/inflections.rb +15 -0
- data/spec/assets/rails328_ruby187_app/config/initializers/mime_types.rb +5 -0
- data/spec/assets/rails328_ruby187_app/config/initializers/secret_token.rb +7 -0
- data/spec/assets/rails328_ruby187_app/config/initializers/session_store.rb +8 -0
- data/spec/assets/rails328_ruby187_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/assets/rails328_ruby187_app/config/locales/en.yml +5 -0
- data/spec/assets/rails328_ruby187_app/config/routes.rb +58 -0
- data/spec/assets/rails328_ruby187_app/db/seeds.rb +7 -0
- data/spec/assets/rails328_ruby187_app/doc/README_FOR_APP +2 -0
- data/spec/assets/rails328_ruby187_app/manifest.yml +7 -0
- data/spec/assets/rails328_ruby187_app/public/404.html +26 -0
- data/spec/assets/rails328_ruby187_app/public/422.html +26 -0
- data/spec/assets/rails328_ruby187_app/public/500.html +25 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application-7270767b2a9e9fff880aa5de378ca791.css +0 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application-7270767b2a9e9fff880aa5de378ca791.css.gz +0 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application-ccab98dc1abdf097c0af693e20aed861.js +17 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application-ccab98dc1abdf097c0af693e20aed861.js.gz +0 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application.css +0 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application.css.gz +0 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application.js +17 -0
- data/spec/assets/rails328_ruby187_app/public/assets/application.js.gz +0 -0
- data/spec/assets/rails328_ruby187_app/public/assets/manifest.yml +4 -0
- data/spec/assets/rails328_ruby187_app/public/assets/rails-be8732dac73d845ac5b142c8fb5f9fb0.png +0 -0
- data/spec/assets/rails328_ruby187_app/public/assets/rails.png +0 -0
- data/spec/assets/rails328_ruby187_app/public/favicon.ico +0 -0
- data/spec/assets/rails328_ruby187_app/public/index.html +241 -0
- data/spec/assets/rails328_ruby187_app/public/robots.txt +5 -0
- data/spec/assets/rails328_ruby187_app/script/rails +6 -0
- data/spec/assets/rails328_ruby187_app/test/performance/browsing_test.rb +12 -0
- data/spec/assets/rails328_ruby187_app/test/test_helper.rb +13 -0
- data/spec/cf/cli/app/base_spec.rb +17 -0
- data/spec/cf/cli/app/delete_spec.rb +197 -0
- data/spec/cf/cli/app/env_spec.rb +261 -0
- data/spec/cf/cli/app/events_spec.rb +72 -0
- data/spec/cf/cli/app/help_spec.rb +39 -0
- data/spec/cf/cli/app/instances_spec.rb +69 -0
- data/spec/cf/cli/app/push/create_spec.rb +444 -0
- data/spec/cf/cli/app/push/interactions_spec.rb +32 -0
- data/spec/cf/cli/app/push_spec.rb +332 -0
- data/spec/cf/cli/app/rename_spec.rb +108 -0
- data/spec/cf/cli/app/restart_spec.rb +47 -0
- data/spec/cf/cli/app/scale_spec.rb +63 -0
- data/spec/cf/cli/app/start_spec.rb +255 -0
- data/spec/cf/cli/app/stats_spec.rb +66 -0
- data/spec/cf/cli/domain/help_spec.rb +39 -0
- data/spec/cf/cli/domain/map_spec.rb +140 -0
- data/spec/cf/cli/domain/unmap_spec.rb +77 -0
- data/spec/cf/cli/help_spec.rb +21 -0
- data/spec/cf/cli/organization/create_spec.rb +121 -0
- data/spec/cf/cli/organization/delete_spec.rb +105 -0
- data/spec/cf/cli/organization/help_spec.rb +39 -0
- data/spec/cf/cli/organization/orgs_spec.rb +116 -0
- data/spec/cf/cli/organization/rename_spec.rb +116 -0
- data/spec/cf/cli/populators/organization_spec.rb +179 -0
- data/spec/cf/cli/populators/space_spec.rb +156 -0
- data/spec/cf/cli/populators/target_spec.rb +39 -0
- data/spec/cf/cli/route/delete_spec.rb +92 -0
- data/spec/cf/cli/route/help_spec.rb +32 -0
- data/spec/cf/cli/route/map_spec.rb +148 -0
- data/spec/cf/cli/route/unmap_spec.rb +114 -0
- data/spec/cf/cli/service/bind_spec.rb +25 -0
- data/spec/cf/cli/service/create_spec.rb +147 -0
- data/spec/cf/cli/service/delete_spec.rb +22 -0
- data/spec/cf/cli/service/help_spec.rb +39 -0
- data/spec/cf/cli/service/rename_spec.rb +103 -0
- data/spec/cf/cli/service/service_helper_spec.rb +66 -0
- data/spec/cf/cli/service/service_instance_helper_spec.rb +155 -0
- data/spec/cf/cli/service/service_spec.rb +23 -0
- data/spec/cf/cli/service/services_spec.rb +156 -0
- data/spec/cf/cli/service/unbind_spec.rb +25 -0
- data/spec/cf/cli/space/base_spec.rb +49 -0
- data/spec/cf/cli/space/create_spec.rb +144 -0
- data/spec/cf/cli/space/delete_spec.rb +109 -0
- data/spec/cf/cli/space/help_spec.rb +39 -0
- data/spec/cf/cli/space/rename_spec.rb +110 -0
- data/spec/cf/cli/space/space_spec.rb +80 -0
- data/spec/cf/cli/space/spaces_spec.rb +107 -0
- data/spec/cf/cli/space/switch_space_spec.rb +57 -0
- data/spec/cf/cli/start/help_spec.rb +39 -0
- data/spec/cf/cli/start/login_spec.rb +142 -0
- data/spec/cf/cli/start/logout_spec.rb +49 -0
- data/spec/cf/cli/start/target_prettifier_spec.rb +78 -0
- data/spec/cf/cli/start/target_spec.rb +123 -0
- data/spec/cf/cli/user/create_spec.rb +98 -0
- data/spec/cf/cli/user/help_spec.rb +32 -0
- data/spec/cf/cli/user/passwd_spec.rb +94 -0
- data/spec/cf/cli/user/register_spec.rb +145 -0
- data/spec/cf/cli_spec.rb +474 -0
- data/spec/console/console_spec.rb +189 -0
- data/spec/factories/cfoundry/v2/apps_factory.rb +12 -0
- data/spec/factories/cfoundry/v2/clients_factory.rb +7 -0
- data/spec/factories/cfoundry/v2/domains_factory.rb +8 -0
- data/spec/factories/cfoundry/v2/managed_service_instances_factory.rb +13 -0
- data/spec/factories/cfoundry/v2/organizations_factory.rb +14 -0
- data/spec/factories/cfoundry/v2/quota_definitions.rb +13 -0
- data/spec/factories/cfoundry/v2/routes_factory.rb +8 -0
- data/spec/factories/cfoundry/v2/service_bindings_factory.rb +11 -0
- data/spec/factories/cfoundry/v2/service_brokers_factory.rb +11 -0
- data/spec/factories/cfoundry/v2/service_plans_factory.rb +17 -0
- data/spec/factories/cfoundry/v2/services_factory.rb +14 -0
- data/spec/factories/cfoundry/v2/spaces_factory.rb +13 -0
- data/spec/factories/cfoundry/v2/stacks_factory.rb +11 -0
- data/spec/factories/cfoundry/v2/user_provided_service_instances_factory.rb +12 -0
- data/spec/factories/cfoundry/v2/users_factory.rb +7 -0
- data/spec/features/backspace_spec.rb +46 -0
- data/spec/features/create_user_spec.rb +74 -0
- data/spec/features/delete_orphaned_service_spec.rb +64 -0
- data/spec/features/login_spec.rb +65 -0
- data/spec/features/manifests_spec.rb +86 -0
- data/spec/features/org_spec.rb +50 -0
- data/spec/features/push_flow_spec.rb +169 -0
- data/spec/features/service_brokers_spec.rb +173 -0
- data/spec/features/services_spec.rb +122 -0
- data/spec/features/space_spec.rb +107 -0
- data/spec/features/switching_targets_spec.rb +70 -0
- data/spec/manifests/errors_spec.rb +43 -0
- data/spec/manifests/loader/builder_spec.rb +80 -0
- data/spec/manifests/loader/normalizer_spec.rb +158 -0
- data/spec/manifests/manifests_spec.rb +335 -0
- data/spec/manifests/plugin_spec.rb +410 -0
- data/spec/micro/plugin_spec.rb +64 -0
- data/spec/spec_helper.rb +69 -0
- data/spec/support/cli_helper.rb +87 -0
- data/spec/support/config_helper.rb +15 -0
- data/spec/support/factory_girl.rb +6 -0
- data/spec/support/fake_home_dir.rb +55 -0
- data/spec/support/features_helper.rb +99 -0
- data/spec/support/interact_helper.rb +27 -0
- data/spec/support/matchers.rb +16 -0
- data/spec/support/mock_commands/mock_restart.rb +16 -0
- data/spec/support/mock_commands/mock_start.rb +17 -0
- data/spec/support/shared_examples/errors.rb +40 -0
- data/spec/support/shared_examples/input.rb +14 -0
- data/spec/tunnel/plugin_spec.rb +31 -0
- data/spec/tunnel/tunnel_spec.rb +54 -0
- metadata +814 -0
data/spec/cf/cli_spec.rb
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
module CF
|
|
4
|
+
describe CLI do
|
|
5
|
+
let(:context) { CF::CLI.new }
|
|
6
|
+
let(:command) { nil }
|
|
7
|
+
|
|
8
|
+
let(:fake_home_dir) { nil }
|
|
9
|
+
stub_home_dir_with { fake_home_dir }
|
|
10
|
+
|
|
11
|
+
describe "#wrap_errors" do
|
|
12
|
+
let(:inputs) { {} }
|
|
13
|
+
|
|
14
|
+
subject do
|
|
15
|
+
capture_output do
|
|
16
|
+
context.stub(:input) { inputs }
|
|
17
|
+
context.wrap_errors { action.call }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "with a CFoundry::Timeout" do
|
|
22
|
+
let(:action) { proc { raise CFoundry::Timeout.new(123, "fizzbuzz") } }
|
|
23
|
+
|
|
24
|
+
it_behaves_like "an error that's obvious to the user", :with_message => "fizzbuzz"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "with a UserError" do
|
|
28
|
+
let(:action) { proc { context.fail "foo bar" } }
|
|
29
|
+
|
|
30
|
+
it_behaves_like "an error that's obvious to the user",
|
|
31
|
+
:with_message => "foo bar"
|
|
32
|
+
|
|
33
|
+
it "saves it in the crashlog" do
|
|
34
|
+
context.should_receive(:log_error)
|
|
35
|
+
subject
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "with a UserFriendlyError" do
|
|
40
|
+
let(:action) { proc { raise CF::UserFriendlyError.new("user friendly") } }
|
|
41
|
+
|
|
42
|
+
it_behaves_like "an error that's obvious to the user",
|
|
43
|
+
:with_message => "user friendly"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "with a CFoundry::StagingError" do
|
|
47
|
+
let(:exception) { CFoundry::StagingError.new("whatever", 170001, nil, nil) }
|
|
48
|
+
let(:action) { proc { raise exception } }
|
|
49
|
+
before { exception.should_receive(:backtrace).at_least(1).times.and_return([]) }
|
|
50
|
+
|
|
51
|
+
it "prints the message" do
|
|
52
|
+
subject
|
|
53
|
+
expect(stderr.string).to include "Application failed to stage"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "sets the exit code to 1" do
|
|
57
|
+
context.should_receive(:exit_status).with(1)
|
|
58
|
+
subject
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "logs the error" do
|
|
62
|
+
context.should_receive(:log_error).with(anything)
|
|
63
|
+
subject
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "with a SystemExit" do
|
|
68
|
+
let(:action) { proc { exit 1 } }
|
|
69
|
+
|
|
70
|
+
it_behaves_like "an error that gets passed through",
|
|
71
|
+
:with_exception => SystemExit
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context "with a Mothership::Error" do
|
|
75
|
+
let(:action) { proc { raise Mothership::Error } }
|
|
76
|
+
|
|
77
|
+
it_behaves_like "an error that gets passed through",
|
|
78
|
+
:with_exception => Mothership::Error
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "with an Interrupt" do
|
|
82
|
+
let(:action) { proc { raise Interrupt } }
|
|
83
|
+
|
|
84
|
+
it "sets the exit code to 130" do
|
|
85
|
+
context.should_receive(:exit_status).with(130)
|
|
86
|
+
subject
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "when CC can't decode the auth token" do
|
|
91
|
+
let(:action) { proc { raise CFoundry::InvalidAuthToken.new("foo bar") } }
|
|
92
|
+
let(:asked) { false }
|
|
93
|
+
|
|
94
|
+
before do
|
|
95
|
+
$cf_asked_auth = asked
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "tells the user they are not authenticated" do
|
|
99
|
+
subject
|
|
100
|
+
expect(stdout.string).to include "Invalid authentication token. Try logging in again with 'truck login'. If problems continue, please contact your Cloud Operator."
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "exits without attempting to login again" do
|
|
104
|
+
context.should_not_receive(:invoke)
|
|
105
|
+
subject
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context "with a CFoundry authentication error" do
|
|
110
|
+
let(:action) { proc { raise CFoundry::Forbidden.new("foo bar") } }
|
|
111
|
+
let(:asked) { false }
|
|
112
|
+
|
|
113
|
+
before do
|
|
114
|
+
$cf_asked_auth = asked
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "tells the user they are not authenticated" do
|
|
118
|
+
context.stub(:invoke)
|
|
119
|
+
subject
|
|
120
|
+
expect(stdout.string).to include "Not authenticated! Try logging in:"
|
|
121
|
+
expect($cf_asked_auth).to be_true
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "asks the user to log in" do
|
|
125
|
+
context.should_receive(:invoke).with(:login)
|
|
126
|
+
subject
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context "and after logging in they got another authentication error" do
|
|
130
|
+
let(:asked) { true }
|
|
131
|
+
|
|
132
|
+
it "does not ask them to log in" do
|
|
133
|
+
context.should_not_receive(:invoke)
|
|
134
|
+
subject
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it_behaves_like "an error that's obvious to the user",
|
|
138
|
+
:with_message => "Denied: foo bar"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
context "with a CFoundry API error" do
|
|
143
|
+
let(:error) { CFoundry::APIError.new("CC had a problem", 123) }
|
|
144
|
+
let(:action) { proc { raise error } }
|
|
145
|
+
|
|
146
|
+
it "prints the error message" do
|
|
147
|
+
subject
|
|
148
|
+
expect(stderr.string).to include "APIError: 123: CC had a problem"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "does not include the crash log" do
|
|
152
|
+
subject
|
|
153
|
+
expect(stderr.string).to_not include "spec/cf/cli_spec.rb"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context "with an arbitrary exception" do
|
|
158
|
+
let(:error) { RuntimeError.new("ahhhh it's all broken!!!!") }
|
|
159
|
+
let(:action) { proc { raise error } }
|
|
160
|
+
|
|
161
|
+
it "prints the error message" do
|
|
162
|
+
subject
|
|
163
|
+
expect(stderr.string).to include "RuntimeError: ahhhh it's all broken!!!!"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "prints the crash log" do
|
|
167
|
+
subject
|
|
168
|
+
expect(stderr.string).to include "spec/cf/cli_spec.rb"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "sets the exit code to 1" do
|
|
172
|
+
context.should_receive(:exit_status).with(1)
|
|
173
|
+
subject
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context "when we are debugging" do
|
|
177
|
+
let(:inputs) { {:debug => true} }
|
|
178
|
+
|
|
179
|
+
it_behaves_like "an error that gets passed through",
|
|
180
|
+
:with_exception => RuntimeError
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
describe "#execute" do
|
|
186
|
+
let(:inputs) { {} }
|
|
187
|
+
let(:client) { build(:client) }
|
|
188
|
+
|
|
189
|
+
before do
|
|
190
|
+
stub_client
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
subject do
|
|
194
|
+
capture_output do
|
|
195
|
+
context.stub(:input) { inputs }
|
|
196
|
+
context.execute(command, [])
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
describe "token refreshing" do
|
|
201
|
+
let(:context) { TokenRefreshDummy.new }
|
|
202
|
+
let(:command) { Mothership.commands[:refresh_token] }
|
|
203
|
+
let(:auth_token) { CFoundry::AuthToken.new("old-header") }
|
|
204
|
+
let(:new_auth_token) { CFoundry::AuthToken.new("new-header") }
|
|
205
|
+
|
|
206
|
+
class TokenRefreshDummy < CF::CLI
|
|
207
|
+
class << self
|
|
208
|
+
attr_accessor :new_token
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def precondition;
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def refresh_token
|
|
215
|
+
if client
|
|
216
|
+
client.token = self.class.new_token
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
context "when there is a target" do
|
|
222
|
+
before do
|
|
223
|
+
TokenRefreshDummy.new_token = nil
|
|
224
|
+
client.token = auth_token
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
context "when the token refreshes" do
|
|
228
|
+
it "saves to the target file" do
|
|
229
|
+
TokenRefreshDummy.any_instance.stub(:target_info) { {} }
|
|
230
|
+
TokenRefreshDummy.any_instance.stub(:save_target_info).with(anything) do |info|
|
|
231
|
+
expect(info[:token]).to eq new_auth_token.auth_header
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
subject
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
context "but there is no token initially" do
|
|
239
|
+
let(:auth_token) { nil }
|
|
240
|
+
|
|
241
|
+
it "doesn't save the new token because something else probably did" do
|
|
242
|
+
context.should_not_receive(:save_target_info)
|
|
243
|
+
subject
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
context "and the token becomes nil" do
|
|
248
|
+
let(:new_auth_token) { nil }
|
|
249
|
+
|
|
250
|
+
it "doesn't save the nil token" do
|
|
251
|
+
context.should_not_receive(:save_target_info)
|
|
252
|
+
subject
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
context "when there is no target" do
|
|
258
|
+
let(:client) { nil }
|
|
259
|
+
|
|
260
|
+
it "doesn't try to compare the tokens" do
|
|
261
|
+
expect { subject }.to_not raise_error
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
describe "#log_error" do
|
|
268
|
+
subject do
|
|
269
|
+
context.log_error(exception)
|
|
270
|
+
File.read(File.expand_path(CF::CRASH_FILE))
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
context "when the exception is a normal error" do
|
|
274
|
+
let(:exception) do
|
|
275
|
+
error = StandardError.new("gemfiles are kinda hard")
|
|
276
|
+
error.set_backtrace(["fo/gems/bar", "baz quick"])
|
|
277
|
+
error
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it { should include "Time of crash:" }
|
|
281
|
+
it { should include "gemfiles are kinda hard" }
|
|
282
|
+
it { should include "bar" }
|
|
283
|
+
it { should_not include "fo/gems/bar" }
|
|
284
|
+
it { should include "baz quick" }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
context "when the exception is an APIError" do
|
|
288
|
+
let(:request) { {:method => "GET", :url => "http://api.cloudfoundry.com/foo", :headers => {}, :body => nil} }
|
|
289
|
+
let(:response) { {:status => 404, :body => "bar", :headers => {}} }
|
|
290
|
+
let(:exception) do
|
|
291
|
+
error = CFoundry::APIError.new(nil, nil, request, response)
|
|
292
|
+
error.set_backtrace(["fo/gems/bar", "baz quick"])
|
|
293
|
+
error
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
before do
|
|
297
|
+
response.stub(:body) { "Response Body" }
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it { should include "REQUEST: " }
|
|
301
|
+
it { should include "RESPONSE: " }
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
describe "#client_target" do
|
|
306
|
+
subject { context.client_target }
|
|
307
|
+
|
|
308
|
+
context "when a ~/.truck/target exists" do
|
|
309
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
|
|
310
|
+
|
|
311
|
+
it "returns the target in that file" do
|
|
312
|
+
expect(subject).to eq "https://api.some-domain.com"
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
context "when no target file exists" do
|
|
317
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/no_config" }
|
|
318
|
+
|
|
319
|
+
it "returns nil" do
|
|
320
|
+
expect(subject).to eq nil
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
describe "#targets_info" do
|
|
326
|
+
subject { context.targets_info }
|
|
327
|
+
|
|
328
|
+
context "when a ~/.truck/tokens.yml exists" do
|
|
329
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
|
|
330
|
+
|
|
331
|
+
it "returns the file's contents as a hash" do
|
|
332
|
+
expect(subject).to eq({
|
|
333
|
+
"https://api.some-domain.com" => {
|
|
334
|
+
:token => "bearer some-token",
|
|
335
|
+
:version => 2
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
context "when no token file exists" do
|
|
342
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/no_config" }
|
|
343
|
+
|
|
344
|
+
it "returns an empty hash" do
|
|
345
|
+
expect(subject).to eq({})
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
describe "#target_info" do
|
|
351
|
+
subject { CF::CLI.new.target_info("https://api.some-domain.com") }
|
|
352
|
+
|
|
353
|
+
context "when a ~/.truck/tokens.yml exists" do
|
|
354
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
|
|
355
|
+
|
|
356
|
+
it "returns the info for the given url" do
|
|
357
|
+
expect(subject).to eq({
|
|
358
|
+
:token => "bearer some-token",
|
|
359
|
+
:version => 2
|
|
360
|
+
})
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
context "when no token file exists" do
|
|
365
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/no_config" }
|
|
366
|
+
|
|
367
|
+
it "returns an empty hash" do
|
|
368
|
+
expect(subject).to eq({})
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
describe "methods that update the token info" do
|
|
374
|
+
before do
|
|
375
|
+
context.stub(:targets_info) do
|
|
376
|
+
{
|
|
377
|
+
"https://api.some-domain.com" => {:token => "bearer token1"},
|
|
378
|
+
"https://api.some-other-domain.com" => {:token => "bearer token2"}
|
|
379
|
+
}
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
describe "#save_target_info" do
|
|
384
|
+
it "adds the given target info, and writes the result to ~/.truck/tokens.yml" do
|
|
385
|
+
context.save_target_info({:token => "bearer token3"}, "https://api.some-domain.com")
|
|
386
|
+
YAML.load_file(File.expand_path("~/.truck/tokens.yml")).should == {
|
|
387
|
+
"https://api.some-domain.com" => {:token => "bearer token3"},
|
|
388
|
+
"https://api.some-other-domain.com" => {:token => "bearer token2"}
|
|
389
|
+
}
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
describe "#remove_target_info" do
|
|
394
|
+
it "removes the given target, and writes the result to ~/.truck/tokens.yml" do
|
|
395
|
+
context.remove_target_info("https://api.some-domain.com")
|
|
396
|
+
YAML.load_file(File.expand_path("~/.truck/tokens.yml")).should == {
|
|
397
|
+
"https://api.some-other-domain.com" => {:token => "bearer token2"}
|
|
398
|
+
}
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
describe "#client" do
|
|
404
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dirs/new" }
|
|
405
|
+
|
|
406
|
+
before { context.stub(:input).and_return({}) }
|
|
407
|
+
|
|
408
|
+
describe "the client's token" do
|
|
409
|
+
it "constructs an AuthToken object with the data from the tokens.yml file" do
|
|
410
|
+
expect(context.client.token).to be_a(CFoundry::AuthToken)
|
|
411
|
+
expect(context.client.token.auth_header).to eq("bearer some-token")
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
it "does not assign an AuthToken on the client if there is no token stored" do
|
|
415
|
+
context.should_receive(:target_info).with("some-fake-target") { {:version => 2} }
|
|
416
|
+
expect(context.client("some-fake-target").token).to be_nil
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
describe "the client's version" do
|
|
421
|
+
it "uses the version stored in the yml file" do
|
|
422
|
+
expect(context.client.version).to eq(2)
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
context "with a cloud controller" do
|
|
427
|
+
before do
|
|
428
|
+
context.stub(:target_info) { {:version => 2} }
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
it "connects using the v2 api" do
|
|
432
|
+
expect(context.client).to be_a(CFoundry::V2::Client)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
%w{https_proxy HTTPS_PROXY http_proxy HTTP_PROXY}.each do |variable|
|
|
436
|
+
proxy_name = variable.downcase.to_sym
|
|
437
|
+
|
|
438
|
+
context "when ENV['#{variable}'] is set" do
|
|
439
|
+
before { ENV[variable] = "http://lower.example.com:80" }
|
|
440
|
+
after { ENV.delete(variable) }
|
|
441
|
+
|
|
442
|
+
it "uses the #{proxy_name} proxy URI on the environment variable" do
|
|
443
|
+
expect(context.client.send(proxy_name)).to eq("http://lower.example.com:80")
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
context "when both input and environment variable are provided" do
|
|
449
|
+
before do
|
|
450
|
+
ENV["HTTPS_PROXY"] = "http://should.be.overwritten.example.com:80"
|
|
451
|
+
context.stub(:input) { {:https_proxy => "http://arg.example.com:80"} }
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
after { ENV.delete("HTTPS_PROXY") }
|
|
455
|
+
|
|
456
|
+
it "uses the provided https proxy URI" do
|
|
457
|
+
expect(context.client.https_proxy).to eq("http://arg.example.com:80")
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
describe "#sane_target_url" do
|
|
464
|
+
it "removes any trailing slashes" do
|
|
465
|
+
expect(context.sane_target_url("http://example.com/")).to eq "http://example.com"
|
|
466
|
+
expect(context.sane_target_url("https://example.com/")).to eq "https://example.com"
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it "defaults to https when the given url has no http(s) scheme" do
|
|
470
|
+
expect(context.sane_target_url("example.com")).to eq "https://example.com"
|
|
471
|
+
end
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
end
|